Servlet简介

  Servlet是Java Web的技术核心之一,而且也是另一技术核心Java Server Pages(JPS)的支撑基础。文章的主要部分将介绍Servlet的使用以及原理,还有Servlet的载体,这里选用Tomcat。

  一个Servlet是一个Java 类,经由Servlet容器创建、调用、销毁,也就是说Servlet容器管理着Servlet的生命周期。它在服务器工作期间将驻留在内存中,响应客户端发来的对应请求。下面是一个Servlet应用的基础架构,其中屏蔽了很多细节,我们将渐渐深入解析。

JavaWeb系列:Servlet_java

  ①浏览器接受到用户输入指令,转而生成Http响应指令发送至Servlet容器;

  ②Servlet容器是一种特殊的Http服务器,将分析Http请求是否是静态数据,如果是则直接发送静态数据;

  ③如果对应的是某一Servlet的第一次调用,则交给Servlet容器创建Servlet,并将Request和Response交由Servlet处理;

  ④处理完结果Response返回至Servlet容器,Servlet容器包装Response之后返回Http响应;

  ⑤浏览器接收Http响应并根据结果请求更多内容和渲染画面,一次交互结束。

 Tomcat容器

  Tomcat容器是一种大家比较熟悉的Servlet容器,解析Servlet容器的工作方式有利于大家理解Servlet。

JavaWeb系列:Servlet_java_02

  Tomcat容器采用众多容器来管理,而底层是Servlet容器,Servlet容器又管理着Context容器,Context容器管理着的是Wrapper类。

  Wrapper类是Servlet的包装类,也就是说真正管理Servlet的是Context容器,一个Context容器表示一个application,一个Context容器管理着很多Wrapper类(Servlet)。为了验证这一点,我们看以下Tomcat的一个启动类org.apache.catalina.startup.Tomcat源码:

JavaWeb系列:Servlet_java_03

public Context addWebapp(Host host, String url, String path) { 
        silence(url); 
  
        Context ctx = new StandardContext(); 
        ctx.setPath( url ); 
        ctx.setDocBase(path); 
        if (defaultRealm == null) { 
            initSimpleAuth(); 
        } 
        ctx.setRealm(defaultRealm); 
  
        ctx.addLifecycleListener(new DefaultWebXmlListener()); 
          
        ContextConfig ctxCfg = new ContextConfig(); 
        ctx.addLifecycleListener(ctxCfg); 
          
        // prevent it from looking ( if it finds one - it'll have dup error ) 
        ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML"); 
          
        if (host == null) { 
            getHost().addChild(ctx); 
        } else { 
            host.addChild(ctx); 
        } 
  
        return ctx; 
    }

JavaWeb系列:Servlet_java_03

每当新增一个application,Tomcat容器会调用一次addWebapp()函数,也就是每次都会创建一个新的StandardContext;

JavaWeb系列:Servlet_java_03

 public static Wrapper addServlet(Context ctx,  
                                      String servletName,  
                                      String servletClass) { 
        // will do class for name and set init params 
        Wrapper sw = ctx.createWrapper(); 
        sw.setServletClass(servletClass); 
        sw.setName(servletName); 
        ctx.addChild(sw); 
          
        return sw; 
    }

JavaWeb系列:Servlet_java_03

Context可以添加Wrapper类,而Wrapper类接受的参数就可以明白它是一个Servlet的包装类。

Servlet层次结构

java.servlet

JavaWeb系列:Servlet_java_07

javax.servlet.http

JavaWeb系列:Servlet_java_08

掌握上述接口和类就可以熟练地进行servlet编程,下面我们重点描述其中几个,其余就进行功能描述:

  ①Servlet

  所有Servlet都必须实现这一接口,主要用于容器配置Servlet,实现初始化,调用,销毁等功能,也就是servlet的生命周期管理函数;

  void init(ServletConfig config) throws ServletException  //初始化  ServletConfig getServletConfig()  //获取servletConfig对象  void service(ServletRequest req,ServletResponse res)throws ServletException,IOException  //当每次有一个对应的servlet请求时,容器会调用service方法  void destroy()  //销毁servlet

  ②servletconfig和servletcontext

  这两个类是用于配置servlet环境。

  servletconfig是用于配置单独当前servlet环境,主要的功能是获取ServletContext;

  String getInitParameter(String name)  //获取初始化参数,使用者可制定servlet如何初始化  ServletContext getServletContext()  //获取servletcontext,后面将介绍

  servletcontext是用于配置context环境,还记得刚说过context管理着servlet的包装类?

  void setAttribute(String name,Object object)  //在context上下文中设置保存一个对象  Object getAttribute(String name)  //获取保存的对象  Enumeration getInitParameterNames()  //获取初始化参数  String getRealPath(String path)  //获取对应path的物理路径  URL getResource(String path)throws MalformedURLException  //获取对应path的相对路径  void log(String message,Throwable throwable)  //当异常发生时记录日志

   ③HttpServlet

  protected void doGet(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException 
  protected void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException

  ④RequestDispatcher

  RequestDispatcher是一个Web资源的包装器,可以用来把当前request传递到该资源,或者把新的资源包括到当前响应中。

  void forward(ServletRequest request,ServletResponse response)throws ServletException,IOException    //把request转发至服务器中的另一资源  void include(ServletRequest request,ServletResponse response)throws ServletException,IOException    //把资源包含到响应中

  ⑤Cookie和HttpSession

  Http是无状态协议,所以需要有一个“地方”用来保存某些状态信息,Cookie是保存在客户端的“地方”,而Session是服务端的“地方”。

  Cookie和HttpSession是javaBean,被用来进行传输保存的对象,没什么好说的。

  ⑥HttpServletRequest和HttpServletResponse

  HttpServletRequest

JavaWeb系列:Servlet_java_03

  Cookie[] getCookies()    //获取浏览器的cookies  Enumeration getHeaders(String name)    //获取requset包含的请求头信息  HttpSession getSession(boolean create)      //create参数为true并没有session创建一个session,有session则获取之前创建的session  
  void setAttribute(String name,Object o)  //设置attribute对象  Object getAttribute(String name)  //获取request中设定的attribute对象  void setCharacterEncoding(String env)throws UnsupportedEncodingException  //设置编码集  String getCharacterEncoding()  //获取编码集  ServletInputStream getInputStream()  //获取request输入字节流  BufferedReader getReader()throws IOException  //获取request输入字符流  RequestDispatcher getRequestDispatcher(String path)  //获取RequestDispatcher  String getParameter(String name)  //获取浏览器设置的参数

JavaWeb系列:Servlet_java_03

  HttpServletResponse

JavaWeb系列:Servlet_java_03

  void addCookie(Cookie cookie)    //添加cookie  void addHeader(String name,String value)    //添加头信息  void setHeader(String name,String value)    //设置头信息  String encodeURL(String url)    //编码一个url使之追加sessionID,用于一些浏览器禁止cookie时使用,可和getSession(boolean create)配合使用  String getCharacterEncoding()    
  void setCharacterEncoding(String charset)
  ServletOutputStream getOutputStream()throws IOException    //获取输出字节流  PrintWriter getWriter()throws IOException    //获取输出字符流

JavaWeb系列:Servlet_java_03

  ⑦Filter和FilterChain

  Filter过滤器可以用来过滤http请求和响应,使之调用特定servlet的service之前或之后执行特定的任务,如:

  1) Authentication Filters 
  2) Logging and Auditing Filters 
  3) Image conversion Filters 
  4) Data compression Filters 
  5) Encryption Filters 
  6) Tokenizing Filters 
  7) Filters that trigger resource access events 
  8) XSL/T filters 
  9) Mime-type chain Filter 

JavaWeb系列:Servlet_java_03

<web-app><filter><filter-name>Basic Filter</filter-name><filter-class>BasicFilter</filter-class></filter>/*********************************/<filter-mapping><filter-name>Basic Filter</filter-name><servlet-name>FilteredServlet</servlet-name></filter-mapping>/*********************************/<servlet><servlet-name>FilteredServlet</servlet-name></servlet></web-app>

JavaWeb系列:Servlet_java_03

 init(FilterConfig filterConfig) ServletException     doFilter(ServletRequest request,ServletResponse response, FilterChain chain)  IOException,ServletException   
 destroy()

  ⑧其他

  其他接口或者对象是Listener、event、exception等,在整个生命周期里可以设计监听对象,用专门的事件来进行通知,按接口来就可以了,没什么好讲。