Filter

1、功能

  • Java Servlet 2.3 中新增加的功能,主要作用是对Servlet 容器的请求和响应进行检查和修改
  • Filter 本身并不生成请求和响应对象,它只提供过滤作用

    在Servlet 被调用之前,检查Request 对象
      »可以对其Request Header 和Request 内容进行审查和修改
    在Servlet 调用结束之后,检查Response 对象
      »可以对其Response Header 和Response 内容进行审查和修改

  • Filter 可以过滤的Web 组件包括Servlet,JSP,HTML等
  • Filter主要负责拦截请求,和放行。
  • Filter 过滤过程

2、接口Filter

  • init( FilterConfig config )

    Filter 的初始化方法
    容器创建Filter 之后将调用这个方法
    使用这个方法可以读取web.xml 文件中定义的初始化参数

  • doFilter(ServletRequest req,ServletResponse resp ,FilterChain chain)

    该方法完成实际的过滤操作
    当客户请求访问与Filter 相关联的URL 时,将调用该方法
    chain 用于访问后续的Filter 或Servlet

  • destroy()

    容器在销毁Filter 实例前调用该方法
    该方法中可以释放该Filter 所占用的资源

  • Filter的生命周期

    Filter的创建和销毁由web服务器控制。

      »服务器启动的时候,web服务器创建Filter的实例对象,并调用其init方法,完成对象的初始化功能。filter对象只会创建一次,init方法也只会执行一次。

      »拦截到请求时,执行doFilter方法。可以执行多次。

      »服务器关闭时,web服务器销毁Filter的实例对象。

3、接口FilterChain

  • 过滤器链
  • 一组过滤器对某些web资源进行拦截,那么这组过滤器就称为过滤器链。过滤器的执行顺序和<filter-mapping>有关

  • 该接口中定义的方法

    doFilter(ServletRequest req,ServletResponse resp )
      »负责把所有的过滤器给串联起来
      »使得一个过滤器执行完后,下一个可以继续执行
      »被串联的多个过滤器按照配置文件中的映射顺序依次执行

4、创建Filter

  • 实现Filter
  1. package ecut.filter.filter;
  2.  
  3. import java.io.IOException;
  4.  
  5. import javax.servlet.Filter;
  6. import javax.servlet.FilterChain;
  7. import javax.servlet.FilterConfig;
  8. import javax.servlet.ServletException;
  9. import javax.servlet.ServletRequest;
  10. import javax.servlet.ServletResponse;
  11.  
  12. public class HelloFilter implements Filter {
  13.  
  14. public void init(FilterConfig config) throws ServletException {
  15. }
  16.  
  17. public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
  18. // place your code here
  19. System.out.println( "hello" );
  20.  
  21. // pass the request along the filter chain
  22. chain.doFilter( req, resp );
  23.  
  24. System.out.println( "world" );
  25. }
  26.  
  27. public void destroy() {
  28. }
  29.  
  30. }
  • 注册Filter
  1. <filter>
  2. <filter-name>HelloFilter</filter-name>
  3. <filter-class>ecut.filter.filter.HelloFilter</filter-class>
  4. </filter>
  • 发布Filter

    同Servlet 一样,url-pattern 可以写多个

    url-mapping匹配规则有三种:

      »精确匹配 —— 如/index.html,只会匹配index.html这个URL

      »路径匹配 —— 如/*,会匹配所有的URL

      »后缀匹配 —— 如*.html,会匹配所有以.html为后缀的URL

  1. <filter-mapping>
  2. <filter-name>HelloFilter</filter-name>
  3. <url-pattern>/*</url-pattern>
  4. </filter-mapping>
  • 测试案例
  1. package ecut.filter.servlet;
  2.  
  3. import java.io.IOException;
  4. import java.io.PrintWriter;
  5.  
  6. import javax.servlet.ServletException;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10.  
  11. public class HelloServlet extends HttpServlet {
  12.  
  13. private static final long serialVersionUID = -8731391727918781480L;
  14.  
  15. @Override
  16. protected void service( HttpServletRequest request, HttpServletResponse response )
  17. throws ServletException, IOException {
  18.  
  19. System.out.println( "service" );
  20.  
  21. response.setContentType( "text/html" );
  22.  
  23. PrintWriter w = response.getWriter();
  24.  
  25. w.println( "<h2 style='text-align:center;'>你好 , Servlet .</h2>" );
  26.  
  27. }
  28.  
  29. }
  1. <servlet>
  2. <servlet-name>HelloServlet</servlet-name>
  3. <servlet-class>ecut.filter.servlet.HelloServlet</servlet-class>
  4. </servlet>
  5.  
  6. <servlet-mapping>
  7. <servlet-name>HelloServlet</servlet-name>
  8. <url-pattern>/filter/hello</url-pattern>
  9. </servlet-mapping>

在浏览器中访问HelloServle

运行结果如下:

  1. hello
  2. service
  3. world

5、在config中指定初始化参数

  • 用 户在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其 init方法时,会把封装了filter初始化参数的filterConfig对象传递进来
  • 在web.xml 中可以指定初始化参数
  1. <filter>
  2. <filter-name>CharacterEncodingFilter</filter-name>
  3. <filter-class>ecut.filter.filter.CharacterEncodingFilter</filter-class>
  4. <init-param>
  5. <param-name>encoding</param-name>
  6. <param-value>UTF-8</param-value>
  7. </init-param>
  8. </filter>
  • 访问初始化参数

    在init 方法中通过FilterConfig 对象访问

字符集过滤器测试案例:

  1. package ecut.filter.filter;
  2.  
  3. import java.io.IOException;
  4. import java.nio.charset.Charset;
  5.  
  6. import javax.servlet.DispatcherType;
  7. import javax.servlet.Filter;
  8. import javax.servlet.FilterChain;
  9. import javax.servlet.FilterConfig;
  10. import javax.servlet.ServletException;
  11. import javax.servlet.ServletRequest;
  12. import javax.servlet.ServletResponse;
  13. import javax.servlet.http.HttpServletRequest;
  14.  
  15. public class CharacterEncodingFilter implements Filter{
  16.  
  17. private static final String ENCODING_PARAM = "encoding" ;
  18.  
  19. private static final String DEFAULT_ENCODING = "UTF-8" ;
  20.  
  21. private String encoding ;
  22.  
  23. @Override
  24. public void init( FilterConfig filterConfig ) throws ServletException {
  25. System.out.println( "CharacterEncodingFilter 初始化" );
  26. // 获取 Filter 的初始化参数
  27. encoding = filterConfig.getInitParameter( ENCODING_PARAM );
  28. // 如果 未指定初始化参数 或 初始化参数值是 空串 则采用默认编码
  29. encoding = ( encoding == null || encoding.trim().isEmpty() ) ? DEFAULT_ENCODING : encoding ;
  30. // 如果指定的编码名称不被JVM所支持,则采用默认编码
  31. // encoding = Charset.isSupported( encoding ) ? encoding : DEFAULT_ENCODING ;
  32. /*
  33. if( ! Charset.isSupported( encoding ) ) { // 如果指定的字符集名称是不支持的
  34. encoding = DEFAULT_ENCODING ;
  35. }
  36. */
  37. }
  38.  
  39. @Override
  40. public void doFilter( ServletRequest req , ServletResponse resp , FilterChain chain )
  41. throws IOException, ServletException {
  42. HttpServletRequest request = (HttpServletRequest) req ;
  43. String uri = request.getRequestURI();
  44. DispatcherType type = request.getDispatcherType();
  45. System.out.println( "CharacterEncodingFilter ::: DispatcherType : " + type + " , URI : " + uri );
  46. // place your code here
  47. req.setCharacterEncoding( encoding );
  48. resp.setCharacterEncoding( encoding );
  49. // pass the request along the filter chain
  50. chain.doFilter( req , resp );
  51. }
  52.  
  53. @Override
  54. public void destroy() {
  55. System.out.println( "CharacterEncodingFilter 销毁" );
  56. }
  57.  
  58. }

运行结果:

解决中文乱码问题,使用过滤器后还需要 response.setContentType( "text/html" );否则仍然会乱码, 或者在响应中文中直接指定字符集response.setContentType( "text/html;charset=UTF-8" );
6、实现对指定的调度进行过滤

  • 在web.xml 中可以指定过滤的请求REQUEST:直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是REQUEST;
  • FORWARD:转发访问执行过滤器。包括RequestDispatcher#forward()方法、< jsp:forward>标签都是转发访问;
  • INCLUDE:包含访问执行过滤器。包括RequestDispatcher#include()方法、< jsp:include>标签都是包含访问;
  • ERROR:当目标资源在web.xml中配置为< error-page>中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。
  1. <filter-mapping>
  2. <filter-name>CharacterEncodingFilter</filter-name>
  3. <url-pattern>/*</url-pattern>
  4. <dispatcher>REQUEST</dispatcher>
  5. <dispatcher>FORWARD</dispatcher>
  6. <dispatcher>INCLUDE</dispatcher>
  7. </filter-mapping>
  • 使得filter将会作用于直接从客户端过来的request,通过forward过来的request,通过include过来的request和通过<error-page>过来的request。如果没有指定任何< dispatcher >元素,默认值是REQUEST。

测试案例:

  1. package ecut.filter.servlet;
  2.  
  3. import java.io.IOException;
  4.  
  5. import javax.servlet.RequestDispatcher;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.annotation.WebServlet;
  8. import javax.servlet.http.HttpServlet;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11.  
  12. @WebServlet( "/filter/action/login" )
  13. public class LoginActionServlet extends HttpServlet {
  14.  
  15. private static final long serialVersionUID = -7857947923197325636L;
  16.  
  17. @Override
  18. protected void service( HttpServletRequest request, HttpServletResponse response )
  19. throws ServletException, IOException {
  20.  
  21. String username = request.getParameter( "username" );
  22. String password = request.getParameter( "password" );
  23.  
  24. System.out.println( "username : " + username + " , password : " + password );
  25.  
  26. request.setAttribute( "username" , username );
  27.  
  28. RequestDispatcher dispatcher = request.getRequestDispatcher( "/filter/success/login" );
  29.  
  30. dispatcher.forward( request, response );
  31.  
  32. }
  33.  
  34. }
  1. package ecut.filter.servlet;
  2.  
  3. import java.io.IOException;
  4.  
  5. import javax.servlet.ServletException;
  6. import javax.servlet.annotation.WebServlet;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10.  
  11. @WebServlet( "/filter/success/login" )
  12. public class LoginSuccessServlet extends HttpServlet {
  13.  
  14. private static final long serialVersionUID = 2707448998600792264L;
  15.  
  16. @Override
  17. protected void service( HttpServletRequest request, HttpServletResponse response )
  18. throws ServletException, IOException {
  19.  
  20. //String username = (String)request.getAttribute( "username" );
  21.  
  22. String username = request.getParameter( "username" );
  23. System.out.println( "success : " + username );
  24.  
  25. response.setContentType( "text/html" );
  26.  
  27. response.getWriter().println( "<h1>" + username + " </h1>" );
  28.  
  29. }
  30.  
  31. }
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Filter</title>
  6. </head>
  7. <body>
  8.  
  9. <h5>登录</h5>
  10. <form action="/s/action/login" method="post" >
  11. <input type="text" name="username" placeholder="用户名">
  12. <input type="password" name="password" placeholder="输入密码">
  13. <input type="submit" value="登录">
  14. </form>
  15.  
  16. </body>
  17. </html>

运行结果:

  1. hello
  2. CharacterEncodingFilter ::: DispatcherType : REQUEST , URI : /s/filter/action/login
  3. IdentifyBrowserFilter ::: User Agent : mozilla/5.0 (windows nt 6.1; win64; x64; rv:59.0) gecko/20100101 firefox/59.0
  4. username : , password : 123
  5. CharacterEncodingFilter ::: DispatcherType : FORWARD , URI : /s/filter/success/login
  6. success :
  7. world

8、使用注解

  • Servlet 3.0 允许使用注解来标注Filter
  • @WebFilter用以标注一个实现过Filter 接口的类
  • 使用@WebFilter 标注不如web.xml 文件中可以通过映射顺序来控制过滤器的执行顺序
  • @WebFilter 的常用属性

    String filterName 指定当前Filter 的名称,相当于xml 中的filter-name
    String[] value 指定当前Filter 对应的url (与url-pattern 对应)
    String[] urlPatterns 与value 作用相同
    DispatcherType[] dispatcherTypes 指定当前Filter 关联的dispatcher 类型
      »默认值是DispatcherType.REQUEST
      »javax.servlet.DispatcherType 是Servlet 3.0 新定义的枚举
    boolean asyncSupported 指定是否支持异步操作
    WebInitParam[] initParams 用于设置Filter 初始化参数

9、使用过滤器过滤浏览器

测试案例:

  1. package ecut.filter.filter;
  2.  
  3. import java.io.IOException;
  4.  
  5. import javax.servlet.Filter;
  6. import javax.servlet.FilterChain;
  7. import javax.servlet.FilterConfig;
  8. import javax.servlet.ServletException;
  9. import javax.servlet.ServletRequest;
  10. import javax.servlet.ServletResponse;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13.  
  14. public class IdentifyBrowserFilter implements Filter {
  15.  
  16. @Override
  17. public void init( FilterConfig config ) throws ServletException {
  18. }
  19.  
  20. @Override
  21. public void doFilter( ServletRequest req , ServletResponse resp , FilterChain chain )
  22. throws IOException, ServletException {
  23.  
  24. HttpServletRequest request = (HttpServletRequest) req ;
  25. HttpServletResponse response = (HttpServletResponse) resp ;
  26.  
  27. String userAgent = request.getHeader( "user-agent" );
  28.  
  29. userAgent = userAgent.toLowerCase();
  30.  
  31. System.out.println( "IdentifyBrowserFilter ::: User Agent : " + userAgent );
  32.  
  33. // 如果在 userAgent 中找到了 trident 则说明目前正在使用 IE 访问
  34. if( userAgent.indexOf( "trident" ) != - 1 ) {
  35. String uri = request.getRequestURI();
  36. System.out.println( "uri : " + uri );
  37. int index = uri.lastIndexOf( "/" );
  38. uri = uri.substring( 0 , index ) ;
  39. System.out.println( "uri : " + uri );
  40.  
  41. index = uri.lastIndexOf( "/" );
  42. uri = uri.substring( index ) ;
  43. System.out.println( "uri : " + uri );
  44. //解析字符串,如果访问的是IE目录下的就继续
  45. if( "/ie".equals( uri ) ) {
  46. chain.doFilter( req , resp );
  47. } else {//如果访问的不是IE目录下的就重定向到ie.html
  48. response.sendRedirect( request.getContextPath() + "/pages/filter/ie/ie.html" );
  49. }
  50.  
  51. } else {
  52. // 如果是 非 IE 浏览器,则可以通过 FilterChain 向后传递 请求 和 响应
  53. chain.doFilter( req , resp );
  54. }
  55.  
  56. }
  57.  
  58. @Override
  59. public void destroy() {
  60. }
  61.  
  62. }
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>珍爱生命,远离IE</title>
  6. <link rel="stylesheet" href="/s/pages/filter/ie/ie.css" >
  7. </head>
  8. <body>
  9.  
  10. <h2>珍爱生命,远离IE</h2>
  11.  
  12. <h2>请使用现代浏览器: Chrome 、FireFox </h2>
  13.  
  14. </body>
  15. </html>
  1. @CHARSET "UTF-8";
  2.  
  3. h2 {
  4. text-align: center;
  5. }
  6.  
  7. h2:first-child {
  8. color: red ;
  9. font-weight: bold ;
  10. }
  11.  
  12. h2:last-child {
  13. color: blue ;
  14. }

运行结果:

转载请于明显处标明出处

http://www.cnblogs.com/AmyZheng/p/9024091.html

Servlet 学习(八)的更多相关文章

  1. Servlet学习(八)——Session

    1.Session技术 Session技术是将数据存储在服务器端的技术,会为每个客户端都创建一块内存空间存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间.所以说Ses ...

  2. JSP&Servlet学习手册

    JSP&Servlet学习手册 沙琪玛 书 目录 JSP 指令... 3 书写方式... 3 指令列表... 3 JSP 内置对象... 3 内置对象特点... 3 常用内置对象... 3 o ...

  3. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

  4. Servlet 学习笔记

    Servlet 运行在服务器上的 java 类: Servlet 容器为 javaWeb 应用提供运行时环境,负责管理 servlet 和 jsp 生命周期,以及管理他们的共享数据. 现在我们知道了 ...

  5. Servlet学习:(三)Servlet3.0 上传文件

    转: Servlet学习:(三)Servlet3.0 上传文件 2018年08月03日 11:57:58 iDark_CSDN 阅读数:362   一.注意事项 客户端(浏览器) 表单的提交方法必须是 ...

  6. SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  7. Servlet学习(九)——request

    request运行流程在Servlet学习(四)——response已介绍,不再赘述 1.通过抓包工具获取Http请求 因为request代表请求,所以我们可以通过该对象分别获得Http请求的请求行, ...

  8. # jsp及servlet学习笔记

    目录 jsp及servlet学习笔记 JSP(Java Server Page Java服务端网页) 指令和动作: servlet(小服务程序) jsp及servlet学习笔记 JSP(Java Se ...

  9. Servlet学习笔记(四)

    目录 Servlet学习笔记(四) 一.会话技术Cookie.session 1. 什么是会话技术? 2. 会话技术有什么用? 3. Cookie 3.1 什么是Cookie? 3.2 使用Cooki ...

  10. Servlet学习笔记(三)

    目录 Servlet学习笔记(三) 一.HTTP协议 1.请求:客户端发送欸服务器端的数据 2.响应:服务器端发送给客户端的数据 3.响应状态码 二.Response对象 1.Response设置响应 ...

随机推荐

  1. CSS学习(7)继承、属性值的计算过程

    子元素会继承父元素的某些css属性 通常跟字体相关的属性都能被继承,具体的可以在mdn里查询是否是可继承属性 属性值的计算过程(渲染过程) 按照页面文档的树形目录结构进行依次渲染 前提条件:渲染的元素 ...

  2. 最漂亮的Spring事务管理详解

    SnailClimb 2018年05月21日阅读 7245 可能是最漂亮的Spring事务管理详解 Java面试通关手册(Java学习指南):github.com/Snailclimb/- 微信阅读地 ...

  3. 图片的onerror 事件解析

    1. 该事件触发条件 文档和图像在加载失败的时候(用户体验会下降.)会触发该事件 2. 解决碎图的办法 利用img的onerror事件和javascript 例: 现有的图片是 successed.p ...

  4. mysql区分大小写问题

  5. ScheduledThreadPoolExecutor与Timer

    首先来看一下Timer类 例子如下: package cn.concurrent.executor; import java.util.Timer; import java.util.TimerTas ...

  6. 吴裕雄 PYTHON 人工智能——基于MASK_RCNN目标检测(4)

    import os import sys import random import math import re import time import numpy as np import tenso ...

  7. TensorFlow:使用inception-v3实现各种图像识别

    程序来自博客: # https://www.cnblogs.com/felixwang2/p/9190740.html上面这个博客是一些列的,所以可以从前往后逐一练习. # https://www.c ...

  8. Python socket day1

    客户端和服务端通过ip地址确认互相身份.(ip:用来在网络中标记一台电脑) 如果A,B两个人IP地址相同,接受到的信息有时候A收到,有时候B收到 当你用QQ时,双击选中头像其实就是选中了对方的IP地址 ...

  9. MySQL死锁1

    MySQL行级排他锁的使用及死锁解除技巧 这篇笔记存粹是做学习记录之用,方便将来查阅,老鸟请跳过.关于MySQL排他锁的具体使用. 使用排他锁 假设有一张user表如下: id name age 1 ...

  10. 【原】Mysql最大连接数

    MySQL最大连接数的默认值是100, 这个数值对于并发连接很多的数据库的应用是远不够用的,当连接请求大于默认连接数后,就会出现无法连接数据库的错误,因此我们需要把它适当调大一些. 在使用MySQL数 ...