(Filter处理中文乱码)Filter 过滤器的基本知识点

Filter 过滤器的使用

导读{
}

【1】什么是Filter(过滤器)?

Filter 被称为过滤器,用于在Servlet 之外就对 request 或者 response 进行修改。 基本功能就是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理前后实现一些特殊功能。
Filter 提出了滤镜链(FilterChain),一个FilterChain 中包含了许多的Filter 。完成的工作就是 客户端发送的请求(request)会在进入Servlet 之前先经过FilterChain 中的Filter,服务器响应(response)会在到达客户端之前先进入 FilterChain中的Filter 中,进行处理。

当浏览器访问服务器中的目标资源时,会被 Filter 拦截,在 Filter 中进行预处理操作,然后再将请求转发给目标资源。当服务器接收到这个请求后会对其进行响应,在服务器处理响应的过程中,也需要先将响应结果发送给拦截器,在拦截器中对响应结果进行处理后,才会发送给客户端。  

[2]怎么使用Filter ?


(1)实现Filter 的接口(javax.servlet.Filter;重写其中的 doFilter() 方法。

注意:(doFilter() 中必须实现 chain.doFilter() 这个方法,chain.doFilter()将request 提交给下一个Filter ,当所有的Filter执行完后,就交给Servlet 进行处理。如果不执行这个方法 request 不会交给后面的Filter 或者 Servlet 进行处理

(2)在web.xml配置Filter 的参数。

主要配置 <filter>  和 <filter-mapping>  (跟servlet 的配置差不多)
   
   
  1. <!-- 配置过滤器 -->
  2. <filter>
  3. <filter-name>MyFilter</filter-name>
  4. <filter-class>filter.MyFilter</filter-class>
  5. </filter>
  6. <filter-mapping>
  7. <filter-name>MyFilter</filter-name>
  8. <url-pattern>/*</url-pattern>
  9. </filter-mapping>
参数注意: name 一致,class 是 包名.类名 
url-pattern  可以配置多个,可以是通配符(*)   /*     使用通配符“*”来实现让过滤器拦截所有的请求访问
                                            /jsp/*   适用于以 /jsp/  的Servlet 路径

<filter-mapping> 元素中有一个特殊的子元素 <dispatcher> ,该元素用于指定过滤器所拦截的资源被 Servlet 容器调用的方式
<dispatcher>(调度者) 配置到达Servlet 的四种方式:
 
REQUEST : 表示仅当直接请求Servlet 的时候才有效。
FORWOED: 表示仅当某Servlet 通过FORWARD 到该Servlet 时才有效。
INCLUDE:      JSP中可以通过<jsp;include /> 请求某 Servlet 。 仅这种情况下有效。
ERROR:      JSP中可以通过<%@ page errorPage="error.jsp"> 指定错误处理页面, 仅这种情况下有效。

而且拦截的request 必须同时满足  url-pattern   和 <dispatcher> 的条件,才拦截
如果不写 <dispatcher> ,默认是 REQUEST

【3】Filter 的生命周期

   
   
  1. package filter;
  2. import java.io.IOException;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletRequest;
  8. import javax.servlet.ServletResponse;
  9. public class MyFilter implements Filter {
  10. //创建过滤器对象后,立即执行本方法(当web 程序加载的时候调用,只执行一次)
  11. public void init(FilterConfig arg0) throws ServletException {
  12. System.out.println("init()....");
  13. }
  14. //拦截用户的请求,如果请求资源路径和当前过滤器的拦截路径匹配时,就执行本方法
  15. public void doFilter(ServletRequest req, ServletResponse res,
  16. FilterChain chain) throws IOException, ServletException {
  17. System.out.println("request 被处理之前...");
  18. //放行(将请求交给下一个过滤器或者交给目标资源)
  19. chain.doFilter(req, res);
  20. System.out.println("request 被处理之后,response 抵达客户端浏览器之前...");
  21. }
  22. //过滤器对象销毁前执行, (当web 程序卸载的时候调用,只执行一次)
  23. public void destroy() {
  24. System.out.println("destory....");
  25. }
  26. }
运行结果:

加载web程序
 可以看见  (当web 程序加载的时候调用,只执行一次)
访问我们的MyServlet 

 可以看出,先进入doFilter 方法中,当调用  chain . doFilter ( req , res );
后进入 Myservlet.java 中 ,在处理完 request 后,返回到 doFilter () 方法中。
(doFilter() 中必须实现 chain.doFilter() 这个方法,chain.doFilter()将request 提交给下一个Filter ,当所有的Filter执行完后,就交给Servlet 进行处理。如果不执行这个方法 request 不会交给后面的Filter 或者 Servlet 进行处理
Myservlet.java
     
     
  1. public void doPost(HttpServletRequest request, HttpServletResponse response)
  2. throws ServletException, IOException {
  3. System.out.println("myServlet....");
  4. }
当我们关掉服务器,执行 destroy() 方法

演示 <dispatcher>   为 FORWORD  时。
Servlet  : 我们将转发到 index.jsp 页面
     
     
  1. public void doPost(HttpServletRequest request, HttpServletResponse response)
  2. throws ServletException, IOException {
  3. //通过请求转发得到目标资源
  4. request.getRequestDispatcher("/index.jsp").forward(request, response);
  5. }
Filter 执行输出语句到页面
      
      
  1. public void doFilter(ServletRequest req, ServletResponse res,
  2. FilterChain chain) throws IOException, ServletException {
  3. res.getWriter().print("myFilter...");
  4. }
web.xml   配置信息 
     
     
  1. <filter>
  2. <filter-name>MyFilter</filter-name>
  3. <filter-class>filter.MyFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>MyFilter</filter-name>
  7. <url-pattern>/index.jsp</url-pattern>
  8. <dispatcher>FORWARD</dispatcher>
  9. </filter-mapping>
结果:

 注意:转发的页面必须是在 url-pattern 中满足的

【4】处理多个Filter ,执行的先后次序

我们在配置文件配置出来  两个 Filter , 创建两个 Filter 类出来
    
    
  1. <!-- 配置MyFilter01 -->
  2. <filter>
  3. <filter-name>MyFilter01</filter-name>
  4. <filter-class>filter.MyFilter01</filter-class>
  5. </filter>
  6. <filter-mapping>
  7. <filter-name>MyFilter01</filter-name>
  8. <url-pattern>/MyServlet</url-pattern>
  9. </filter-mapping>
  10. <!-- 配置MyFilter02 -->
  11. <filter>
  12. <filter-name>MyFilter02</filter-name>
  13. <filter-class>filter.MyFilter02</filter-class>
  14. </filter>
  15. <filter-mapping>
  16. <filter-name>MyFilter02</filter-name>
  17. <url-pattern>/MyServlet</url-pattern>
  18. </filter-mapping>
执行其中的 doFilter 方法
MyFilter01.java
     
     
  1. public void doFilter(ServletRequest req, ServletResponse res,
  2. FilterChain chain) throws IOException, ServletException {
  3. PrintWriter out = res.getWriter();
  4. out.print("myFilter01...");
  5. //放行
  6. chain.doFilter(req, res);
  7. out.print("myFilter01 back...");
  8. }
MyFilter02.java
      
      
  1. public void doFilter(ServletRequest req, ServletResponse res,
  2. FilterChain chain) throws IOException, ServletException {
  3. PrintWriter out = res.getWriter();
  4. out.print("myFilter02...");
  5. //放行
  6. chain.doFilter(req, res);
  7. out.print("myFilter02 back...");
  8. }
运行结果:

 可以看出,在配置文件中配置Filter 目录  哪一个在前面,就先经过那一个Filter。
我们在配置文件中 先配置的是  MyFilter01 ,则先走这个过滤器。然后再走 MyFilter02 过滤器,
然后将request(请求)进入到servlet 中处理,然后再返回到过滤器中

【5】拿取Filter 中配置文件的初始化参数信息

为了拿到在web.xml 中的配置信息,我们需要用到 FilterConfig 接口的内容

FilterConfig接口

  为了获取Filter程序在web.xml文件中的配置信息,Servlet API提供了一个FilterConfig接口,该接口封装了Filter程序在web.xml中的所有注册信息,并且提供了一系列获取这些配置信息的方法

方法声明

功能描述

String getFilterName ()

getFilterName()方法用于返回在web.xml文件中为Filter所设置的名称,也就是返回<filter-name>元素的设置值。

ServletContext getServletContext()

getServletContext()方法用于返回FilterConfig对象中所包装的ServletContext对象的引用。

String getInitParameter(String name)

getInitParameter(String name)方法用于返回在web.xml文件中为Filter所设置的某个名称的初始化参数值,如果指定名称的初始化参数不存在,则返回null

Enumeration getInitParameterNames()

getInitParameterNames()方法用于返回一个Enumeration集合对象,该集合对象中包含在web.xml文件中为当前Filter设置的所有初始化参数的名称。

下面我们在配置文件配置两个Filter
    
    
  1. <filter>
  2. <filter-name>MyFilter</filter-name>
  3. <filter-class>filter.MyFilter</filter-class>
  4. <!-- 初始化参数配置 -->
  5. <init-param>
  6. <param-name>school</param-name>
  7. <param-value>rjxy</param-value>
  8. </init-param>
  9. </filter>
  10. <filter-mapping>
  11. <filter-name>MyFilter</filter-name>
  12. <url-pattern>/MyServlet</url-pattern>
  13. </filter-mapping>
  14. <filter>
  15. <filter-name>myFilter01</filter-name>
  16. <filter-class>filter.Filter01</filter-class>
  17. <init-param>
  18. <param-name>name</param-name>
  19. <param-value>耿帅佳</param-value>
  20. </init-param>
  21. </filter>
在我们的Filter 类中获取
     
     
  1. package filter;
  2. import java.io.IOException;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletContext;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10. public class MyFilter implements Filter {
  11. public void destroy() {
  12. // TODO Auto-generated method stub
  13. }
  14. public void doFilter(ServletRequest arg0, ServletResponse arg1,
  15. FilterChain arg2) throws IOException, ServletException {
  16. // TODO Auto-generated method stub
  17. }
  18. public void init(FilterConfig config) throws ServletException {
  19. // 获取过滤器名字
  20. String name = config.getFilterName();
  21. System.out.println(name);
  22. //获取SerletContext对象
  23. ServletContext sc = config.getServletContext();
  24. System.out.println(sc);
  25. //获取初始化参数根据参数名
  26. String value = config.getInitParameter("school");
  27. System.out.println(value);
  28. }
  29. }
在init() 方法中,有我们的 FilterConfig 接口
结果:

 这就是 我们拿到的 两个初始化信息

【6】常见的Filter - 字符编码

Web开发中,经常会遇到中文乱码问题,现在,我们可以在Filter中对获取到的请求和响应消息进行编码,从而统一全站的编码方式。

那么我们处理的就是 get 或者 post 请求发生的中文乱码情况。

那我们的思路应该是:

(1)用户请求 (get 或者 post 方式) 

(2)先走Filter 中,判断是 get 还是 post 请求方式,获取用户的请求的数据,并根据不同的请求方式来处理中文乱码。

(3)然后走 Servlet 方法就完成了。

************************************************

 Filter过滤器可以获取到代表用户请求和响应的requestresponse对象。可是如果想对requestresponse对象中的任何信息进行修改,则需要通过包装类来实现。

   Servlet API中,提供了HttpServletRequestWrapperHttpServletResponseWrapper两个类,它们分别是requestresponse对象的包装类。

***************************************************

    代码实现:
    
    
  1. package filter;
  2. import java.io.IOException;
  3. import java.io.UnsupportedEncodingException;
  4. import javax.servlet.Filter;
  5. import javax.servlet.FilterChain;
  6. import javax.servlet.FilterConfig;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletRequestWrapper;
  12. import javax.servlet.http.HttpServletResponse;
  13. /**
  14. * 字符过滤器处理中文乱码
  15. * @author Administrator
  16. *
  17. */
  18. public class CharacterFilter implements Filter {
  19. public void destroy() {
  20. // TODO Auto-generated method stub
  21. }
  22. public void doFilter(ServletRequest req, ServletResponse res,
  23. FilterChain chain) throws IOException, ServletException {
  24. HttpServletRequest request = (HttpServletRequest)req;
  25. HttpServletResponse response = (HttpServletResponse)res;
  26. //拦截请求处理乱码
  27. //post请求
  28. request.setCharacterEncoding("UTF-8");
  29. response.setContentType("text/html;charset=UTF-8");
  30. /*
  31. * 对request进行包装
  32. * characterRequest功能增强了,获取中文参数直接处理乱码
  33. */
  34. CharacterRequest characterRequest = new CharacterRequest(request);
  35. //放行
  36. chain.doFilter(characterRequest, response);
  37. }
  38. public void init(FilterConfig arg0) throws ServletException {
  39. // TODO Auto-generated method stub
  40. }
  41. }
  42. //对request对象重新包装(增强的功能:处理get请求的中文乱码)
  43. class CharacterRequest extends HttpServletRequestWrapper{
  44. public CharacterRequest(HttpServletRequest request) {
  45. super(request);
  46. // TODO Auto-generated constructor stub
  47. }
  48. /*
  49. * 重写getParameter(),增强的功能:处理get请求的中文乱码
  50. */
  51. public String getParameter(String name){
  52. //调用被包装对象已有的方法,获取请求参数
  53. String value = super.getParameter(name);
  54. if(value == null){
  55. return null;
  56. }
  57. //判断请求方式
  58. String method = super.getMethod();
  59. //如果是get请求
  60. if("get".equalsIgnoreCase(method)){
  61. try {
  62. value = new String(value.getBytes("ISO-8859-1"),"UTF-8");
  63. } catch (UnsupportedEncodingException e) {
  64. // TODO Auto-generated catch block
  65. e.printStackTrace();
  66. }
  67. }
  68. return value;
  69. }
  70. }
配置文件
     
     
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  5. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  6. <!-- 配置字符过滤器 -->
  7. <filter>
  8. <filter-name>CharacterFilter</filter-name>
  9. <filter-class>filter.CharacterFilter</filter-class>
  10. </filter>
  11. <filter-mapping>
  12. <filter-name>CharacterFilter</filter-name>
  13. <url-pattern>/*</url-pattern>
  14. </filter-mapping>
  15. <servlet>
  16. <servlet-name>CharacterServlet</servlet-name>
  17. <servlet-class>servlet.CharacterServlet</servlet-class>
  18. </servlet>
  19. <servlet-mapping>
  20. <servlet-name>CharacterServlet</servlet-name>
  21. <url-pattern>/CharacterServlet</url-pattern>
  22. </servlet-mapping>
  23. <welcome-file-list>
  24. <welcome-file>index.jsp</welcome-file>
  25. </welcome-file-list>
  26. </web-app>
演示结果:

 点击 “get方式”  得到结果

 输入“耿帅佳”  post  提交

结果:
 

 特别注意:

【1】页面编码方式与 Filter 的编码方式必须一致 。

 【2】如果表单是GET 方式提交的,还需要修改Tomcat 的conf/server.xml 配置文件,指定 URIEncoding(默认为ISO-8859-1);
否则,依然会乱码。
          
          
  1. <Connector port="8080" protocol="HTTP/1.1"
  2. connectionTimeout="20000"
  3. redirectPort="8443" URIEncoding="ISO-8859-1" />

处理中文乱码-Filter 源码: day30_06 

















评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值