Servlet 分析

来源:互联网 发布:qq飞车飞碟数据被改 编辑:程序博客网 时间:2024/05/20 10:52

上面的servlet只是接口,相当于描述了servlet的标准,也就是说与协议无关。而HttpServlet的实现是根据Http协议来完成的。

打开源码看后发现大多数接口和抽象类,那么真正的实现都在哪呢?在servlet容器源代码里,即类似Tomcat这样的servlet容器。

  所以我觉得可以这样理解Servlet的作用:它提供了操控的按钮,这些按钮一旦被安装到Servlet容器里面,我们就可以通过这些按钮操控servlet容器,从而管理我们自己的Servlet实例。

  这一点很重要。所以阅读Servlet源码其实就是了解他的基本结构和API,我们真正要读的是Tomcat的源码!

 

Servlet的运行结构和API:

首先看下一次Http请求-响应的过程:
  A
,首先客户端通过浏览器向服务器发送Http请求;
  B,Tomcat监听服务器的8080端口,当有Http请求发过来之后,解析出项目名称,然后到webapps目录下搜索到该项目文件夹。
  C,Tomcat作为servlet的容器,实例化第一次请求调用的的servlet实例(以后再有相同的servlet的请求,使用第一次的实例)。
  D,调用init()方法,初始化工作。

  E,调用HttpServlet的service方法,中间会更加请求,调用doGet或doPost方法,执行核心逻辑代码。
  F,执行完servlet后,返回响应,客户端浏览器根据响应呈现效果。


从图上可以看出,不同的用户请求并发使用同一个Servlet实例,这是一个比较重要的基础机制。

Container解析Http请求后,实例化Servlet,因为是Http请求,会执行HttpServlet的代码:

首先会执行HttpServlet中的service(ServletRequest req, ServletResponse res)方法:

  1. public void service(ServletRequest req, ServletResponse res)  
  2.     throws ServletException, IOException {  
  3.  
  4.     HttpServletRequest  request;  
  5.     HttpServletResponse response;  
  6.       
  7.     try {  
  8.         request = (HttpServletRequest) req;//请求转换成Http请求  
  9.         response = (HttpServletResponse) res;//响应转换成Http响应  
  10.     } catch (ClassCastException e) {  
  11.         throw new ServletException("non-HTTP request or response");  
  12.     }  
  13.     service(request, response);//调用处理Http的service方法  
  14. }  

然后会调用service(HttpServletRequest req, HttpServletResponse resp)方法:

  1. protected void service(HttpServletRequest req, HttpServletResponse resp)  
  2.         throws ServletException, IOException {  
  3.  
  4.         String method = req.getMethod();//取得req中的方法类型  
  5.  
  6.         if (method.equals(METHOD_GET)) {//根据方法类型来决定执行后续的方法,我们只关注doGet和doPost  
  7.             long lastModified = getLastModified(req);  
  8.             if (lastModified == -1) {  
  9.                 doGet(req, resp);  
  10.             } else {  
  11.                 long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);  
  12.                 if (ifModifiedSince < (lastModified / 1000 * 1000)) {  
  13.                     maybeSetLastModified(resp, lastModified);  
  14.                     doGet(req, resp);//如此我们就能执行到自己写的doGet方法,从而执行自己的业务逻辑。  
  15.                 } else {  
  16.                     resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);  
  17.                 }  
  18.             }  
  19.  
  20.         } else if (method.equals(METHOD_HEAD)) {  
  21.             long lastModified = getLastModified(req);  
  22.             maybeSetLastModified(resp, lastModified);  
  23.             doHead(req, resp);  
  24.  
  25.         } else if (method.equals(METHOD_POST)) {  
  26.             doPost(req, resp);  
  27.               
  28.         } else if (method.equals(METHOD_PUT)) {  
  29.             doPut(req, resp);          
  30.               
  31.         } else if (method.equals(METHOD_DELETE)) {  
  32.             doDelete(req, resp);  
  33.               
  34.         } else if (method.equals(METHOD_OPTIONS)) {  
  35.             doOptions(req,resp);  
  36.               
  37.         } else if (method.equals(METHOD_TRACE)) {  
  38.             doTrace(req,resp);  
  39.               
  40.         } else {//不属于http的方法类型,返回501错误  
  41.             String errMsg = lStrings.getString("http.method_not_implemented");  
  42.             Object[] errArgs = new Object[1];  
  43.             errArgs[0] = method;  
  44.             errMsg = MessageFormat.format(errMsg, errArgs);  
  45.               
  46.             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);  
  47.         }  
  48.     }  

我们自己实现的Servlet,我们只要继承HttpServlet,实现doGet就ok了:

  1. public class HelloWorld extends HttpServlet{  
  2.  
  3.     private static final long serialVersionUID = 1L;  
  4.     @Override 
  5.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  6.             throws ServletException, IOException {  
  7.         System.out.println("test");  
  8.         getServletContext().getRequestDispatcher("/jsp/test.html").forward(req, resp);    
  9.     }  
  10. }  


来关注下Servlet运行时需要注意的:
A,Servlet生命周期:
  servlet类加载--->实例化--->服务--->销毁

B,其中牵涉到3个方法代表了Servlet的生命周期:
    1、init方法:负责初始化Servlet对象。
    2、service方法:负责响应客户的请求。
    3、destroy方法:当Servlet对象退出生命周期时,负责释放占用的资源。

C,执行自己Servlet时需要用到的几个重要参数:

1,HttpSession:一次连结到客户端关闭,从客户端连接的层面来管理。
2,ServletConfig:从一个servlet被实例化后,对任何客户端在任何时候访问有效,但仅对本servlet 有效,一个servlet的ServletConfig对象不能被另一个servlet访问。 从单个servlet的层面来管理。
3,ServletContext:对任何servlet,任何人在任何时间都有效,这才是真正全局的对象。从全部的servlet的层面来管理

4,HttpServletRequest,HttpServletResponse:从单个servlet的单次响应侧面来管理


0 0