一、过滤器
1.1 介绍
Filter 即为过滤,用于在 Servlet 之外对 Request 或者 Response 进行修改。它主要用于对用户请 求进行预处理,也可以对 HttpServletResponse 进行后处理。使用 Filter 的完整流程:Filter 对用户请 求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,后 Filter 再对服务器响应进行后处 理。在一个 web 应用中,可以开发编写多个 Filter,这些 Filter 组合起来称之为一个 Filter 链。
单个过滤器
多个过滤器
若是一个过滤器链:先配置先执行(请求时的执行顺序);响应时:以相反的顺序执行。
在 HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest 。根据需要检查 HttpServletRequest,也可以修改 HttpServletRequest 头和数据。 在HttpServletResponse 到达客户端之前,拦截 HttpServletResponse。根据需要检查 HttpServletResponse,也可以修改 HttpServletResponse 头和数据。 1.2 实现
我们可以通过实现一个叫做 javax.servlet.Fileter 的接口来实现一个过滤器,其中定义了三个方 法,init(), doFilter(), destroy() 分别在相应的时机执行。后期观察生命周期。Filter 的实现只需要两 步:
Step1: 编写 java 类实现 Filter 接口,并实现其 doFilter 方法。 Step2: 在 web.xml 文件中对编写的 filter 类进行注册,并设置它所能拦截的资源。
public class Filter01 implements Filter {
/**
Filter 接口中有一个 doFilter 方法,当开发人员编写好 Filter,并配置对哪个 web 资源进行拦截 后,Web 服务器每次在调用 web 资源的 service 方法之前,都会先调用一下 filter 的 doFilter 方法。 因此可以达到如下效果:
调用目标资源之前,让一段代码执行。
是否调用目标资源(即是否让用户访问 web 资源)。 web 服务器在调用 doFilter 方法时,会传递一个 filterChain 对象进来,filterChain 对象是 filter 接口中重要的一个对象,它提供了一个 doFilter 方法,开发人员可以根据需求决定是否调用此方 法,调用该方法,则 web 服务器就会调用 web 资源的 service 方法,即 web 资源就会被访问,否则 web 资源不会被访问。(本质是放行,调用 doFilter 方法后,即请求可以到达资源)
web.xml 配置各节点说明:
* 初始化,只执行一次
@<filter>指定一个过滤器。 <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。 <filter-class>元素用于指定过滤器的完整的限定类名。
url-pattern 的配置: ①配置具体路径 /index.html /TestServlet.do
②带有通配符的配置 .do / /user/* *.html *.jsp 2.3 过滤器执行的顺序
通过观察 web.xml 中的配置和各个 filter 的执行顺序,找出 filter 执行先后的依据。根据之前观察 Servlet 生命周期的方式,观察一下过滤器的生命周期。
2.4 过滤器处理字符乱码
注意:Tomcat7 及以下的版本:上述解决 GET 乱码的方式不好,不能解决所有的问题,可以借助 HttpServletRequestWrapper 类和过滤器来完成转换乱码的问题:
元素用于为过滤器指定初始化参数,它的子元素 指定参数的名字, 指定参数的值。 在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。 元素用于设置一个Filter所负责拦截的资源。一个Filter拦截的资源可通过两种方式 来指定:Servlet 名称和资源访问的请求路径 子元素用于设置filter的注册名称。该值必须是在元素中声明过的过滤器 的名字 设置filter所拦截的请求路径(过滤器关联的URL样式) 指定过滤器所拦截的Servlet名称。 指定过滤器所拦截的资源被Servlet容器调用的方式,可以是 REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个子元素用来 指定Filter对资源的多种调用方式进行拦截。 子元素可以设置的值及其意义 REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过 RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。 INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器 将被调用。除此之外,该过滤器不会被调用。 FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器 将被调用,除此之外,该过滤器不会被调用。 ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过 滤器不会被调用。
GET: 请求: Tomcat8及以上,不需要处理 Tomcat7及以下,需要处理乱码 new String(request.getParameter(name).getBytes(“ISO-8859-1”),“UTF-8”); 响应: response.setContentType(“text/html;charset=UTF-8”); POST: 请求: Tomcat8及以上,需要处理乱码,request.setCharacterEncoding(“UTF-8”); Tomcat7及以下,需要处理乱码,request.setCharacterEncoding(“UTF-8”); 响应: response.setContentType(“text/html;charset=UTF-8”);
①在过滤器中判断哪些需要解决 ②定义 HttpServletRequestWrapper 的子类,并且重写 getParameter(String name) 方法,在该 方法中实现乱码的处理
③chain.doFilter(自定义类(HttpServletRequestWrapper 的子类),response)
三、监听器 3.1 介绍
web 监听器是一种 Servlet 中的特殊的类,它们能帮助开发者监听 web 中的特定事件,比如 ServletContext,HttpSession,ServletRequest 的创建和销毁;变量的创建、销毁和修改等。可以在某些 动作前后增加处理,实现监控。例如可以用来统计在线人数等。
3.2 实现
监听器有三类8种: ⑴监听生命周期(三个域对象的创建和销毁):实现接口 ServletRequestListener、 HttpSessionListener 、ServletContextListener
⑵监听值的变化(属性添加,移除,替换):实现接口 ServletRequestAttributeListener、 HttpSessionAttributeListener、ServletContextAttributeListener ⑶针对 session 中的对象:监听 session 中的 java 对象(javaBean),javaBean 直接实现监听器的 接口 HttpSessionBindingListener、HttpSessionActivationListener。这里我们只做一个简单的演示。 假设我们想做一个对在线人数的监控。
Step1:创建一个监听器,需要实现某种接口,根据需求选取 HttpSessionListener
Step2:在 web.xml 中配置该监听器 创建一个类,并实现 HttpSessionListener 接口,用来检测 Session 的创建和销毁。在类中定义一 个成员变量用来存储当前的 session 个数。
在 web.xml 中配置该监听器,让监听器生效
做一个测试的 Servlet 用来访问,和显示当前在线人数
访问并测试结果
四、Servlet3.0 注解
在 Servlet3.0 之前一直使用的都是配置文件的方式来实现各种组件,Servlet3.0 之后提供了注解, 可以达到零配置。但现实中一般是注解+配置结合使用。我们看几个常用的注解。 4.1 @WebServlet
在Servlet3.0中,可以使用 @WebServlet 注解将一个继承于 javax.servlet.http.HttpServlet 的类标 注为可以处理用户请求的 Servlet,无需配置 web.xml。
用注解配置 Servlet
也可以配置多个 urlPatterns 来指定多个访问路径
4.2 @WebFilter
@WebFilter 用来配置过滤器
使用注解时:过滤器链按照类名的字母排序(大部分情况) 4.3 @WebListener
Servlet3.0 提供 @WebListener 注解将一个实现了特定监听器接口的类定义为监听器。比如将实现 了 ServletSessionListener 接口的类标注为监听器。
4.4 @MultipartConfig
使用注解 @MultipartConfig 将一个 Servlet 标识为支持文件上传。Servlet3.0 将 multipart/formdata 的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作。