鲁春利的工作笔记,好记性不如烂笔头
Servlet的框架是由两个Java包组成:javax.servlet和javax.servlet.http。
在javax.servlet包中定义了所有的Servlet类都必须实现或扩展的的通用接口和类。
在javax.servlet.http包中定义了采用HTTP通信协议的HttpServlet类。
Servlet的框架的核心是javax.servlet.Servlet接口,所有的Servlet类都直接或间接实现这一接口。
每一个Servlet就是一个运行于Web server中的小Java程序。Servert接收并响应Web client的请求,通常为HTTP协议的请求。
为了实现Servlet,可以实现该接口,或者是继承javax.servlet.GenericServlet或javax.servlet.http.HttpServlet。
Servlet接口中定义了5个方法,其中有3个方法代表了Servlet的生命周期:
init方法:初始化servlet对象
service方法:处理客户端请求
destory方法:当Servlet对象退出生命周期时,负责释放占有的资源
除此之外,Servlet接口还定义了getServletConfig和getServletInfo方法:
getServletConfig方法:用来获取servlet启动信息
getServletInfo方法:用户来气servlet本身的基本信息,如作者、版本号或版权信息等
GenericServlet定义了一个通用的、与实现协议无关的Servlet。
public abstract class GenericServlet extends java.lang.Object implements Servlet, ServletConfig, java.io.Serializable
GenericServlet简化了Servlet程序的开发,因为它已经对于Servlet生命周期的init和destory提供了简单实现(空方法),并且实现了ServletConfig接口的所有方法。另外,GenericServlet也实现了ServletContext 接口中声明的log方法。
HttpServlet类扩展了GenericServlet并且提供了servlet接口中基于HTTP的实现,一般情况下都是通过该类来扩展Servlet。
public abstract class HttpServlet extends GenericServlet implements java.io.Serializable # 方法 doGet, if the servlet supports HTTP GET requests doPost, for HTTP POST requests doPut, for HTTP PUT requests doDelete, for HTTP DELETE requests init and destroy, to manage resources that are held for the life of the servlet getServletInfo, which the servlet uses to provide information about itself
HttpServlet定义了两种形式的service方法:
/** * Overrides: service(...) in GenericServlet * Dispatches client requests to the protected service method. * There's no need to override this method. * */ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; if (!(req instanceof HttpServletRequest && res instanceof HttpServletResponse)) { throw new ServletException("non-HTTP request or response"); } request = (HttpServletRequest) req; response = (HttpServletResponse) res; service(request, response); } /** * Receives standard HTTP requests from the public service method * and dispatches them to the doXXX methods defined in this class. * There's no need to override this method. * */ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
实现自定义Servlet的方式
实现Servlet接口,实现其所有方法;
继承GenericServlet抽象类,实现其service方法;
继承HttpServlet抽象类,实现其doGet或doPost方法。
HttpServet的响应过程
当Web容器接收到某个Servlet请求时,Servlet把请求封装成一个HttpServletRequest对象,然后把对象传给Servlet的对应的服务方法。
HttpServlet容器响应Web客户请求流程如下:
1)Web客户向Servlet容器发出Http请求;
2)Servlet容器解析Web客户的Http请求;
3)Servlet容器创建一个HttpRequest对象,在这个对象中封装Http请求信息;
4)Servlet容器创建一个HttpResponse对象;
5)Servlet容器调用HttpServlet的service方法,把HttpRequest和HttpResponse对象作为service方法的参数传给HttpServlet对象;
6)HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息;
7)HttpServlet调用HttpResponse的有关方法,生成响应数据;
8)Servlet容器把HttpServlet的响应结果传给Web客户。
自定义Servlet示例
package com.mywork.web.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; /** * * <p> Date : 2015年11月13日-下午1:39:55 </p> * * <p> Description : MyWorkServlet, just as sample file </p> * * @author luchunli * * @version 1.0 * */ public class MyWorkServlet extends HttpServlet { /** * serialVersionUID */ private static final long serialVersionUID = 1L; private static Logger logger = Logger.getLogger(MyWorkServlet.class); /** * for http get request */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } /** * for http post request */ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { logger.info("Invoke customize servlet."); /** * 简单响应 */ resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); /* 第一次测试 */ // out.print("<script type='text/javascript'>alert('This is my test.');</script>"); /* 第二次测试 */ // out.print("<font color='red'>This is my test.</font>"); out.flush(); out.close(); /* 第三次测试:服务器端跳转 */ RequestDispatcher dispatch = req.getRequestDispatcher("/mywork.jsp"); dispatch.forward(req, resp); /* 第四次测试:客户端跳转 */ resp.sendRedirect("/mywork.jsp"); } }