我的Java之旅 第八课 Servlet 进阶API、过滤器与监听器

1、Servlet、ServletConfig与GenericServlet
    首次请求的顺序 
    => 生成HttpServletRequest与HttpServletResponse
     =>调用service()方法,以前边两个对象作为参数
      =>Web容器启动,
       =>读取Servlet设置信息,实例化Servlet类
         =>为每个Servlet设置信息产生一个ServletConfig对象。
           =>调用Servlet接口的init()方法,以产生的ServletConfig对象作为参数。
       完成初始化。
      说明:容器会为每个Servlet设置信息产生一个Servlet及ServletConfig实例,GenericServlet同时实现了Servlet及Servlet-Config。
          GenericServlet主要的目的,就是将初始Servlet调用init()方法传入的ServletConfig封装起来。
          GenericServlet在实现Servlet的init()方法时,也调用了另一个无参数的init()方法,在编写Servlet()时,如果有一些初始时所要运行的动作,可以重新定义这个无参数的init()方法,而不是直接重新定义有ServletConfig参数的init()方法。
         GenericServlet也包括了Servlet和ServletConfig所定义方法的简单实现,实现内容主要是通过ServletConfig来取得一些相关信息。所以在继承HttpServlet实现Servlet时,就可以通过这些方法来取得所要的相关信息,而不是直接意识到ServletConfig的存在。
2、使用ServletConfig
     可以从ServletConfig中取得Servlet设置信息。
     getinitparameter()、getInitParameterNames() 可以取得Servlet时的初始参数。
     若要设置个别Servlet的初始参数,可以在@WebServlet中使用@WebInitParam设置initParams属性。在web.xml中设置参数使用<init-param>等标签进行设置。web.xml中设置会覆盖标注的设置 。
3、使用ServletContext
    ServletContext接口定义了运行Servlet的应用程序环境的一些行为与观点,可以使用ServletContext实现对象取得所请求资源的URL、设置与储存属性、应用程序初始参数,甚至动态设置Servlet实例。
   通过ServletConfig的getServletContext()方法取得ServletContext对象。
   1)getRequestDispatcher()
       取得RequestDispatcher实例,使用时路径的指定必须以“/”开头,这个斜杠代表应用程序环境根目录(Context Root)。
   2)getResourcePaths()
    取得Web应用程序的某个目录中有哪些文件,使用时路径的指定必须以“/”开头。
   3)getResourceAsStream()
       取得Web应用程序的某个目录中文件的内容,运行结果返回InputStream实例,使用时路径的指定必须以“/”开头。
  每个Web应用程序都会有一个相对应的ServletContext,针对“应用程序”初始化时用到的参数,可以在Web.xml设置,通常这会结合ServletContextListener来做。
4、监听器
    ServletContext监听器
   1)ServletContextListener
     生命周期监听器。在Web应用程序初始化后或即将结束销毁前分别调用contextInitialized()和contextDestroyed()方法。
   2)ServletContextAttributeListener
    监听属性改变的监听器。如果想要对象被设置、移除或替换ServletContext属性时,可以收到通知以进行一些操作,则可以实现ServletContextAttributeListener。对应方法有attributeAdded()、attributeRemoved()与attributeReplaced()。通过传入的参数可以调用一些方法,如getName(),getValue()等得到属性名称和值等。
   HttpSession监听器
  3)HttpSessionListener
     生命周期监听器。在HttpSession对象创建或结束时,调用sessionCreated()与sessionDestroyed()。
    可以使用传入的参数HttpSessionEvent实例的getSession()方法取得HttpSession实例,以针对Session对象作出创建或者结束等操作。
  4)HttpSessionAttributeListener
   属性改变监听器。具体同2)     
  5 )HttpSessionBindingListener
  对象绑定监听器。当实现此接口的类对象被加入HttpSession或者从中移除时,调用对应的valueBound()和valueUnbound()方法,以HttpSessionBindingEvent 对象作为参数。
  6)HttpSessionActivationListener
 对象迁移监听器。一般情况不会用到该监听器,在分布式环境时,应用程序对象可能分散在多个JVM中。当HttpSession从一个JVM迁移至别一个JVM时,涉及到序列化操作,这时就会调用sessionWillPassivate()和sessionDidActivate()。
  HttpServletReques监听器
  7)ServletRequestListener 
 生命周期监听器。在HttpServletRequest对象创建或结束时,调用requestInitialized()与requestDestroyed()。以ServletRequestEvent对象为参数,通过参数可取得ServletRequest,以针对请求对象做出相应初始化和结束操作。
  8)ServletRequestAttributeListener
  属性改变监听器。具体同2)     
5、过滤器
   过滤器介于Servlet的service()之前,可拦截过滤浏览器对Servlet的请求,过滤器介于Servlet的service()之后,可以改变Servlet对浏览器的响应。
   在Servlet/JSP中要实现过滤器,必须实现Filter接口,并使用@WebFilter标注或web.xml中定义过滤器,让容器知道该加载哪些过滤器。web.xml中的设置会覆盖标的设置。
   Filter接口有三个要实现的方法:init(FilterConifg filterConfig)、doFilter(ServletRequest request)、destroy()。
   FilterConifg类似于Servlet接口init()方法参数上的ServletConfig
   doFilter方法则类似于Servlet接口的service()方法。可以在doFilter方法中进行service()方法的前置处理。然后决定是否调用FilterChain的doFilter()方法。调用 了FilterChain的doFilter()方法后,运行下一个过滤器,如果没有了,就调用Servlet的service()方法。
  如果因为某种情况没有调用FilterChain的doFilter(),则请求就不会继续交给接下来的过滤器或目标Servlet,这时就是所谓的拦截了请求。
  默认是浏览器发出请求触发过滤器,如果是通过RequestDispatcher的forward()或include()的请求,可设置@WebFilter的dispatcherTypes。
6、封装器  
 HttpServletRequestWrapper   请求封装器
 应用场景,如:实现留言板字符替换的功能;实现编码统一设置的功能
 HttpServletResponseWrapper 响应封装器
 应用场景,如:对响应的内容进行压缩再发送;
7、异步处理
   Web容器会为每一个请求分配一个线程,并且默认情况下,响应完成前,该线程占用的资源不会被释放。
   在Servlet3.0中,在ServletRequest上提供了startAsync()方法。分无参和有参两个重载,这两个方法都会返回AsyncContext接口的实现对象;无参的会直接利用原有的请求与响应对象来创建AsyncContext,有参的可以传入自行创建的请求、响应封装对象。
   在调用了startAsync()方法取得AsyncContext对象之后,此次请求的响应会被延后,并释放容器分配的线程。
   可以通过AsyncContext的getRequest()、getResponse()方法取得请求、响应对象,此次对客户端的响应将暂缓至调用AsyncContext的complete()或dispatch()方法为止。
   对于延后响应的请求,创建一个实现Runnable接口的AsyncRequest对象,并将其调度一个线程池(Thread pool),线程池的线程数是固定的,让这些必须长时间处理的请求,在这些有限数量的线程中完成,而不是每次请求都占用容器分配的线程。
   若要能调用ServletRequest的startAsync()以取得AsyncContext,必须告知容器此Servlet支持异步处理,可以通过@WebServlet标注或web.xml设置。
   如果Servlet要进行异步处理,而前端有过滤器,则过滤器也需要标识为支持异步处理。同样可通过@WebServlet标注或web.xml设置。
posted @ 2017-03-07 18:10  net515  阅读(409)  评论(0编辑  收藏  举报