第二章:Servlet和JSP结构
在这章我们讨论两个问题JSP和servlets技术,它们是Struts框架的基础。我们描述的servlet结构包括它的生命周期,上下文环境(ServletContext)及WEB应用之间的关系。一旦你对Servlet有了比较透彻的了解,我们将集中讨论Struts框架中的视图即JSP页面。本章的目的是让你对JSP和Servlet技术有个大致的了解。在本章结束的时候你会清楚的知道为何Servlet和JSP技术适合于WEB开发。
Java Servlet 结构
Java servlet是平台独立的WEB应用组件,Servlets和客户端协作是通过request/response来进行处理的。图2.1为处理图
servlet结构有两个包组成:javax.servlet 和 javax.servlet.http。
javax.servlet包含了被用来实现和扩展的通用接口和类。
javax. servlet.http是被用于特定的HTTP协议的。
Servlet接口被定义了五个方法。其中比较重要的有三个:
1.init()方法,用于初始化一个Servlet;
2.service方法,用于接受和响应客户端的请求。
3.destroy()方法,执行清除占用资源的工作。
这些是servlet生命周期方法。我们会在后面的章节解说这些方法。所有的servlet都必须实现javax.servlet.Servlet接口,不管是直接或者是间接的。图2.2是对象图,给出了servlet的层次框架图
GenericServlet和HttpServlet类
HttpServlet从GenericServlet扩展而来,GenericServlet实现了Servlet接口。当开发你的servlets时,你通常需要扩展GenericServlet的子类。你必须实现service()方法。GenericServlet.service()方法已经被定义为抽象方法,定义的原型如下:
public abstract void service(ServletRequest request,
ServletResponse response) throws ServletException, IOException;
ServletRequest,ServletResponse这两个参数通过service()方法来传递。ServletRequest对象用来把得到的信息传送到servlet,ServletResponse对象用来把servlet产生的数据传送回到客户端。
对比GenericServlet和HttpServlet,HttpServlet不需要实现service()方法,HttpServlet类已经为你实现了service()方法。方法原型如下:
protected void service(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException;
当HttpServlet.service()方法被执行,它读取存储在request中的方法类型的值来决定哪个方法被执行。这里是你想重载的方法:如果方法类型为GET,就调用doGet()方法。如果为POST就调用doPost()方法。主要使用的就是这两个方法。另外的五个方法不是经常使用。因此我们比较关注的也就是这两个方法。
Servlet生命周期
Servlet生命周期有一个合理的逻辑顺序。javax.servlet.Servlet接口声明了周期方法。
这些方法就是init(), service(),destroy()。执行顺序分为三个处理步骤:
1. init()方法用来把servlet导入和初始化。这个方法在servlet被预加载或在第一次请求时执行。
2. Servlet处理0个或多个请求。Servlet对每个请求都用service()方法来处理。
3. 当WEB应用声明Servlet被关闭,Servlet被销毁,垃圾收集器对资源进行收集。用destory方法来关闭Servlet。
init() 方法
init()方法是servlet生命周期的开始。这个方法在servlet被实例化后立即执行,它只被调用一次,用来创建和初始化请求中用到的资源。
init() 方法的显示如下:
public void init(ServletConfig config) throws ServletException;
ServletConfig参数对象是成员变量,它在后面会被用到。一个比较通用的做法是调用超类的init()方法super.init()。如果因为一些原因servlet不能初始化请求所要求的资源就会抛出ServletException
service() 方法
service()方法 处理来自客户端的所有请求。
service()方法表示如下:
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
service()方法有两个参数:
ServletRequest:封装来自客户端的请求信息
ServletResponse:返回客户端的信息
通常情况下你不会实现这个方法,除非你扩展GenericServlet抽象类。
经常实现service()这个方法的是HttpServlet类。HttpServlet通过扩展GenericServlet来实现Servlet接口。HttpServlet支持HTTP/1.1。
destroy()方法
这个方法用于结束servlet生命周期。当一个WEB应用被关闭,destroy()方法被执行,
这时在init()方法中被创建的资源被释放。下面是destroy()方法的代码片段:
public void destroy();
创建一个Servlet
现在我们已经基本了解servlet是如何工作了,我们将创建一个非常简单的servlet应用。
它的主要功能是为了处理客户端请求,并在客户端输出客户地址。
在完成代码后我们将编译代码并部署它。下面为SimpleServlet.java类的源代码:
package chapter2;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class SimpleServlet extends HttpServlet {
public void init(ServletConfig config)
throws ServletException {
// Always pass the ServletConfig object to the super class
super.init(config);
}
//Process the HTTP Get request
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
//Process the HTTP Post request
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Simple Servlet</title></head>");
out.println("<body>");
// Outputs the address of the calling client
out.println("Your address is " + request.getRemoteAddr()
+ "\n");
out.println("</body></html>");
out.close();
}
}
现在我们可以查看SimpleServlet代码的细节部分了。我们来看它的三个覆盖方法:
init() ·
doGet() ·
doPost() ·
每个方法的细节:
init()方法
SimpleServlet类首先定义了init()方法,它以ServletConfig对象为参数调用父类的init()方法:super.init(config)
注意:由SimpleServlet的父类GenericServlet来实际处理ServletConfig 对象,你可能也注意到了init()方法并没有创建任何资源,这也是为什么SimpleServlet中不执行destroy()方法的原因了。
doGet() 和 doPost() 方法
所有的业务逻辑都在这两个方法中执行。在这个例子中doGet()方法只是简单的调用doPost()方法。doGet()方法只在GET请求时被执行,doPost()方法也一样,只在Post请求时被执行。两个方法的传入参数是HttpServletRequest和HttpServletResponse对象。HttpServletRequest对象包含的是来自客户端的信息,HttpServletResponse包含的是返回客户端的信息。在doPost()方法中第一步是设置返回的内容类型:代码片段如下:
response.setContentType("text/html");
在输出流中它必须被最先设置,在例子中我们设置为text/html.
下一步获取PrintWriter对象,这是通过ServletResponse对象的getWriter()方法得到的。PrintWriter对象可以让我们写入输出流后发送到客户端显示,这个步骤代码片段如下:
PrintWriter out = response.getWriter();
一旦你获取了PrintWriter对象后,我们将往客户端输出信息,信息包含HTML标记,这是输出到客户端的格式,下面的几行代码显示了如何处理输出:
out.println("<html>");
out.println("<head><title>Simple Servlet</title></head>");
out.println("<body>");
// Outputs the address of the calling client
out.println("Your address is " + request.getRemoteAddr()
+ "\n");
前面部分代码说明你的输出格式为HTML,下面这段代码你可能会有些疑问:
// Outputs the address of the calling client
out.println("Your address is " + request.getRemoteAddr() + "\n");
这段代码调用了HttpServletRequest对象的getRemoteAddr()方法来获取客户端的IP地址,并将它发送到客户端。HttpServletRequest对象可以获取许多HTTP协议下的客户端的信息。如果你想更深入的了解HttpServletRequest和HttpServletResponse对象,可以访问SUN公司的网站:http://java.sun.com/products/servlet/
创建和部署Servlet
我们需要创建一个WEB应用来存放Servlet,并且编译和部署Servlet到WEB应用中去。步骤描述如下:
1.创建名称为wileyapp的WEB应用,如我们在第一章中所说的那样。.
2.编译SimpleServlet.java文件,拷贝SimpleServlet.class文件到<CATALINA_HOME>/webapps/wileyapp/WEB-INF/classes/chapter2/目录
4.你可以启动你的WEB Server,执行SimpleServlet并查看结果。在浏览器中输入如下地址http://localhost:8080/wileyapp/servlet/chapter2.SimpleServlet
你可以看到输出:Your address is 127。0。0。1
注意:在地址中包含了“/servlet”是为了告诉webServer你要执行的是一个servlet
作者:James Goodwill 翻译:周海方
欢迎转载,前提是注明出处和译者