• 过滤器/拦截器/AOP----Java Web 三大组件之一过滤器 Filter


    录:

    1、过滤器 Filter 的使用
    2、多个过滤器的执行顺序
    3、四种拦截方式
    4、过滤器的应用场景
    5、案例:过滤器实现分 IP 统计网站的访问次数
    6、案例:过滤器处理全站编码问题
        6.1、准备工作
        6.2、测试未处理编码前是否出现乱码问题
        6.3、如何处理 GET 和 POST 请求的编码问题
        6.4、编写全站编码过滤器解决乱码问题

    7、springboot 注册过滤器

    JavaEE 规范里面的三大组件(都需要在web.xml中进行配置)是:

      1) Servlet(单例的)
      2) Listener(两个感知监听器不需要配置)
      3) Filter(单例的)

    1、过滤器 Filter 的使用    <--返回目录

      过滤器作用:它会在一组资源(jsp、servlet、.css、.html等)的前面执行,它可以让请求得到目标资源,也可以不让请求达到。过滤器有拦截请求的能力。
      过滤器如何编写
        1) 写一个类实现Filter接口
        2) 在web.xml中配置

      创建一个类,实现Filter接口

    public class MyFilter implements Filter {
        //Filter会在服务器启动时就创建    
        //过滤器创建之后马上执行,用来做初始化
        pullic void init(FilterConfig filterconfig)throws ServletException{}
        
        //每次过滤时都会执行
        public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException,ServletException{}
        
        //过滤器销毁之前执行,用来做对非内存资源进行释放
        //Filter会在服务器关闭时销毁
        public void destroy(){}
    }

      web.xml配置

    <filter>
        <filter-name>MyFilter</filter-name>
        <filter-class>com.oy.filter.MyFilter</filter-class>
    </filter>    
    <filter-mapping>
        <filter-name>MyFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

      相关的 API:
      FilterConfig => 与 ServletConfig类似
        - 获取初始化参数:getInitParameter()
        - 获取过滤器名称:getFilterName()
        - 获取application:getServletContext()

      FilterChain    
        - doFilter(ServletRequest,ServletResponse):放行,就相当于调用Servlet的service()方法

        - 如果在 MyFilter#doFilter()方法里面不调用 chain.doFilter() 方法,则请求被拦截,无法到达目标资源

    2、多个过滤器的执行顺序    <--返回目录

      Eclipse 新建一个 Dynamic Web Project, 创建了一个 Servlet 和 两个 Filter 用于测试

       MyServlet

    package com.oy.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
            System.out.println("MyServlet#service()...");
        }
    }
    View Code

      MyFilter1

    package com.oy.filter;
    
    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class MyFilter1 implements Filter {
        public void init(FilterConfig fConfig) throws ServletException {}
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            
            System.out.println("MyFilter1#doFilter start...");
            chain.doFilter(request, response);
            System.out.println("MyFilter1#doFilter end...");
            
        }
    
        public void destroy() {}
    }
    View Code

      MyFilter2

    package com.oy.filter;
    
    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class MyFilter2 implements Filter {
        public void init(FilterConfig fConfig) throws ServletException {}
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            
            System.out.println("MyFilter2#doFilter start...");
            chain.doFilter(request, response);
            System.out.println("MyFilter2#doFilter end...");
            
        }
    
        public void destroy() {}
    }
    View Code

      web.xml 配置 Servlet 和 Filter(注意:Filter 执行顺序按照 web.xml 中的filter-mapping 配置顺序执行

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="WebApp_ID" version="2.5">
        <display-name>FilterDemo</display-name>
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
        </welcome-file-list>
        
        <servlet>
            <servlet-name>MyServlet</servlet-name>
            <servlet-class>com.oy.servlet.MyServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>MyServlet</servlet-name>
            <url-pattern>/MyServlet</url-pattern>
        </servlet-mapping>
        
        <filter>
            <filter-name>MyFilter1</filter-name>
            <filter-class>com.oy.filter.MyFilter1</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>MyFilter1</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
        <filter>
            <filter-name>MyFilter2</filter-name>
            <filter-class>com.oy.filter.MyFilter2</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>MyFilter2</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    </web-app>
    View Code

      配置 tomcat 服务器,启动项目:

        访问 http://localhost:8080/FilterDemo/MyServlet,控制台打印结果:

    MyFilter1#doFilter start...
    MyFilter2#doFilter start...
    MyServlet#service()...
    MyFilter2#doFilter end...
    MyFilter1#doFilter end...

      如果注释掉 MyFilter#doFilter() 的放行方法,如下代码所示

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        System.out.println("MyFilter2#doFilter start...");
        // chain.doFilter(request, response);
        System.out.println("MyFilter2#doFilter end...");
        
    }

      控制台打印结果:请求被拦截,无法到达目标资源,即 MyServlet#service() 方法不会执行;但还是会回到 MyFilter1 放行方法处,继续执行后面的代码。

    MyFilter1#doFilter start...
    MyFilter2#doFilter start...
    MyFilter2#doFilter end...
    MyFilter1#doFilter end...

    3、四种拦截方式    <--返回目录

    过滤器有四种拦截方式,分别是:REQUEST、FORWARD、INCLUDE、ERROR。
      1)REQUEST:直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是REQUEST;
      2)FORWARD:转发访问执行过滤器。包括RequestDispatcher#forward()方法、<jsp:forward>标签都是转发访问;
      3)INCLUDE:包含访问执行过滤器。包括RequestDispatcher#include()方法、<jsp:include>标签都是包含访问;
      4)ERROR:当目标资源在web.xml中配置为<error-page>中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。

    <filter>
        <filter-name>MyFilter1</filter-name>
        <filter-class>com.oy.filter.MyFilter1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFilter1</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>  默认是拦截REQUEST,一旦指定就没有默认值了
        <!-- 
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
        <dispatcher>ERROR</dispatcher> 
        -->
    </filter-mapping>

      过滤器配置 ERROR 的例子

       web.xml 配置

    <filter>
        <filter-name>ErrorFilter</filter-name>
        <filter-class>com.oy.filter.ErrorFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ErrorFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>
    
    <error-page>
        <error-code>500</error-code>
        <location>/WEB-INF/jsps/500.jsp</location>
    </error-page>

      在 MyServlet#service() 写个运行时错误,比如 int a = 1/0;

      浏览器访问 这个 MyServlet 时发生运行时异常,返回 500 错误码。根据上面配置的 ErrorFilter 拦截到500错误,给前端返回 /WEB-INF/jsps/500.jsp。

      另外,<error-page>除了可以配置错误状态码外,还可以配置异常类型

    <error-page>
        <exception-type>java.lang.RuntimeException</exception-type>
        <location>/WEB-INF/jsps/500.jsp</location>
    </error-page>

    4、过滤器的应用场景     <--返回目录 

      1)执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作;
      2)通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用;
      3)在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理;

    5、案例:过滤器实现分 IP 统计网站的访问次数    <--返回目录

      分析:

      因为一个网站可能有多个页面,无论哪个页面被访问,都要统计访问次数,所以使用过滤器最为方便。

      因为需要分IP统计,所以可以在过滤器中创建一个Map,使用IP为key,访问次数为value。当有用户访问时,获取请求的IP,如果IP在Map中存在,说明以前访问过,那么在访问次数上加1,即可;IP在Map中不存在,那么设置次数为1。

      把这个Map存放到ServletContext中!使用 ServletContextListener 监听 ServletContext 的创建完成后,在 ServletContext 域中添加一个 Map,用于存储 ip 统计信息。

      MyServlet:用于测试,浏览器访问 http://localhost:8080/FilterDemo/MyServlet 时,将请求转发 到 /WEB-INF/jsps/showIp.jsp 显示 IP 统计信息

    package com.oy.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
            // 请求 MyServlet, 转发到 showIp.jsp 页面
            req.getRequestDispatcher("/WEB-INF/jsps/showIp.jsp").forward(req, res);
        }
    }
    View Code

      MyServletContextListener:监听 ServletContext 的创建完成后,在 ServletContext 域中添加一个 Map,用于存储 ip 统计信息

    package com.oy.listener;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    public class MyServletContextListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            ServletContext app = sce.getServletContext();
            Map<String, Integer> ipMap = new HashMap<>();
            app.setAttribute("ipMap", ipMap);
        }
        
    }
    View Code

      IPFilter:过滤器,拦截所有请求,判断当前请求的 ip 是否已经在ipMap 中存在?如果存在,则将 value 值加1;不存在,将 ip 作为 key,value 为 1,添加到 ipMap 中。

    package com.oy.filter;
    
    import java.io.IOException;
    import java.util.Map;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class IPFilter implements Filter {
        private ServletContext app;
        public void init(FilterConfig fConfig) throws ServletException {
            this.app = fConfig.getServletContext();
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            System.out.println("IPFilterFilter#doFilter start...");
            
            Map<String, Integer> ipMap = (Map<String, Integer>) app.getAttribute("ipMap");
            if (ipMap == null) return;
            
            String ip = request.getRemoteAddr();
            if (ipMap.containsKey(ip)) {
                int count = ipMap.get(ip);
                ipMap.put(ip, count + 1);
            } else {
                ipMap.put(ip, 1);
            }
            
            chain.doFilter(request, response); // 放行
            
            System.out.println("IPFilterFilter#doFilter end...");
        }
    
        public void destroy() {
        }
    }
    View Code

      web.xml: 配置前面的 Servlet、Listener 和 Filter

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>FilterDemo</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
      </welcome-file-list>
      
      <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.oy.servlet.MyServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
      </servlet-mapping>
      
      <!-- 过滤器 -->
      <filter>
        <filter-name>IPFilter</filter-name>
        <filter-class>com.oy.filter.IPFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>IPFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      
      <!-- 监听器 -->
      <listener>
        <listener-class>com.oy.listener.MyServletContextListener</listener-class>
      </listener>
    </web-app>
    View Code

      showIp.jsp: 取出ServletContext 域对象(也称为 application 域对象)中的 ipMap, 循环遍历

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
    <h1>分IP统计访问次数</h1>
    <table align="center" width="50%" border="1">
        <tr>
            <th>IP地址</th>
            <th>次数</th>
        </tr>
    <c:forEach items="${applicationScope.ipMap }" var="entry">
        <tr>
            <td>${entry.key }</td>
            <td>${entry.value }</td>
        </tr>
    </c:forEach>
    </table>
    
    </body>
    </html>
    View Code

    6、案例:过滤器处理全站编码问题    <--返回目录

    6.1、准备工作    <--返回目录

      创建一个 Dynamic Web Project, 包含主页 index.jsp用于浏览器访问测试,一个 MyServlet 来接受 index.jsp 发来的请求。

       index.jsp: 用于浏览器访问测试;一个 a 标签发生 GET 请求,form 表单发生 POST 请求

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>主页</title>
    </head>
    <body>
        <h2>index 页面</h2>
        <a href="${pageContext.request.contextPath}/MyServlet?name=测试GET请求乱码" >测试GET请求乱码</a>
        <br/><br/>
        
        <form action="${pageContext.request.contextPath}/MyServlet" method="post">
            name: <input type="text" name="name" value="测试POST请求乱码" /><br/>
            <input type="submit" value="提交" />
        </form>
    </body>
    </html>
    View Code

      MyServlet:接受 index.jsp 发来的请求,并获取请求中的参数,并将参数添加到response, 响应给浏览器

    package com.oy.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String name = req.getParameter("name");
            resp.getWriter().print(name);
        }
    
        @Override
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String name = req.getParameter("name");
            resp.getWriter().print(name);
        }
    }
    View Code

      web.xml: 配置 servlet

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>FilterDemo</display-name>
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
      </welcome-file-list>
      
      <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.oy.servlet.MyServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
      </servlet-mapping>
      
    </web-app>
    View Code

      

    6.2、测试未处理编码前是否出现乱码问题    <--返回目录

      测试访问:http://localhost:8080/FilterDemo/  (也可以访问http://localhost:8080/FilterDemo/index.jsp, 由于web.xml中配置了欢迎页<welcome-file>index.jsp</welcome-file>,所以/index.jsp可以省略)

       点击 a 标签,,发现响应乱码

      点击 "提交",发现响应乱码

     

    6.3、如何处理 GET 和 POST 请求的编码问题    <--返回目录

      获取请求参数中的乱码问题:

    • POST请求:request.setCharacterEncoding(“utf-8”);
    • GET请求:new String(request.getParameter(“xxx”).getBytes(“iso-8859-1”), “utf-8”);

      响应的乱码问题:response.setContextType(“text/html;charset=utf-8”)。

    具体解决编码问题的代码如下:

    package com.oy.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            /* 解决 GET 请求乱码问题 */
            // 将get请求参数先iso-8859-1解码,在utf-8编码(tomcat7的方式)
    //        String name = req.getParameter("name"); // 如果时tomcat9, 直接获取就行
            String name = new String(req.getParameter("name").getBytes("iso-8859-1"), "utf-8");
            System.out.println("GET 请求,获取参数, name=" + name);
            // 告诉浏览器,响应结果使用utf-8
            resp.setContentType("text/html;charset=utf-8"); // 告诉浏览器,响应结果使用utf-8
            
            resp.getWriter().print(name);
        }
    
        @Override
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 解决 POST 请求乱码问题
            req.setCharacterEncoding("UTF-8"); // 告诉服务器,从req.getParameter()获取参数时使用utf-8
            resp.setContentType("text/html;charset=utf-8"); // 告诉浏览器,响应结果使用utf-8
            
            String name = req.getParameter("name");
            resp.getWriter().print(name);
        }
    }

      注意:在Http请求到达Servlet解析之前,GET过来的URL已经被Tomcat先做了一次URLDecode。Tomcat 7 对GET方式默认的URL解码结果是iso-8859-1而不是UTF-8!经过测试 Tomcat 9 默认URL解码时utf-8。

    6.4、编写全站编码过滤器解决乱码问题    <--返回目录

      其实全站乱码问题的难点就是处理GET请求参数的问题。
      如果只是处理POST请求的编码问题,以及响应编码问题,那么这个过滤器就太简单的。
      如果是POST请求,当执行目标Servlet时,Servlet中调用request.getParameter()方法时,就会根据request.setCharacterEncoding()设置的编码来转码!这说明在过滤器中调 request.setCharacterEncoding()方法会影响在目标Servlet中的request.getParameter()方法的行为!
      但是如果是GET请求,我们又如何能影响request.getParameter()方法的行为呢?这是不好做到的!我们不可能先调用request.getParameter()方法获取参数,然后手动转码后,再施加在到request中!因为request只有getParameter(),而没有setParameter()方法。
      处理GET请求参数编码问题,需要在Filter中放行时,把request对象给“调包”了,也就是让目标Servlet使用我们“调包”之后的request对象。这说明我们需要保证“调包”之后的request对象中所有方法都要与“调包”之前一样可以使用,并且getParameter()方法还要有能力返回转码之后的参数。

       对request对象进行增强的条件,刚好符合装饰者模式的特点!因为我们不知道request对象的具体类型,但我们知道request是HttpServletRequest接口的实现类。这说明我们写一个类EncodingRequest,去实现HttpServletRequest接口,然后再把原来的request传递给EncodingRequest类!在EncodingRequest中对HttpServletRequest接口中的所有方法的实现都是通过代理原来的request对象来完成的,只有对getParameter()方法添加了增强代码!


      JavaEE已经给我们提供了一个HttpServletRequestWrapper类,它就是HttpServletRequest的包装类,但它做任何的增强!你可能会说,写一个装饰类,但不做增强,其目的是什么呢?使用这个装饰类的对象,和使用原有的request有什么分别呢?


      HttpServletRequestWrapper类虽然是HttpServletRequest的装饰类,但它不是用来直接使用的,而是用来让我们去继承的!当我们想写一个装饰类时,还要对所有不需要增强的方法做一次实现是很心烦的事情,但如果你去继承HttpServletRequestWrapper类,那么就只需要重写需要增强的方法即可了。

       EncodingRequest: 对 HttpServletRequest 进行装饰,增强了 getParameter() 方法

    package com.oy.servlet;
    
    import java.io.UnsupportedEncodingException;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    
    public class EncodingRequest extends HttpServletRequestWrapper {
        
        private HttpServletRequest request;
        
        public EncodingRequest(HttpServletRequest request) {
            // 将 request 传给 父类 HttpServletRequestWrapper,未增强的方法有父类实现
            super(request);
            this.request = request;
        }
        
        // 增强
        public String getParameter(String name) {
            String value = request.getParameter(name);
            try {
                value = new String(value.getBytes("ISO-8859-1"), "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return value;
            
    //        String method = request.getMethod();
    //        if("post".equalsIgnoreCase(method)) {
    //            try {
    //                request.setCharacterEncoding("utf-8");
    //            } catch (UnsupportedEncodingException e) {
    //                e.printStackTrace();
    //            }
    //        } else if("get".equalsIgnoreCase(method)) {
    //            String value = request.getParameter(name);
    //            try {
    //                value = new String(value.getBytes("ISO-8859-1"), "utf-8");
    //            } catch (UnsupportedEncodingException e) {
    //                e.printStackTrace();
    //            }
    //            return value;
    //        }
    //        return request.getParameter(name);
        }
    }
    View Code

      自定义 编码过滤器 CharacterEncodingFilter,如果是 GET 请求,将 tomcat 传递过来的 request 进行调包,使用自定义的 EncodingRequest

    package com.oy.filter;
    
    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    
    import com.oy.servlet.EncodingRequest;
    
    public class CharacterEncodingFilter implements Filter {
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
            // 告诉浏览器,响应结果使用utf-8
            resp.setContentType("text/html;charset=utf-8");
            // 先将 ServletRequest 强转为 HttpServletRequest
            HttpServletRequest request = (HttpServletRequest) req;
                    
            /* 处理 POST 请求编码问题 */
            String method = request.getMethod();
            if ("post".equalsIgnoreCase(method)) {
                req.setCharacterEncoding("UTF-8"); // 告诉服务器,从req.getParameter()获取参数时使用utf-8
                chain.doFilter(req, resp);
                return;
            }
            
            /* 处理 GET 请求编码问题 */
            if ("get".equalsIgnoreCase(method)) {
                // 使用装饰者模式,将 HttpServletRequest 进行修饰增强(增强了getParameter()方法)
                chain.doFilter(new EncodingRequest(request), resp);
            } else {
                chain.doFilter(req, resp);
            }
        }
    
        public void init(FilterConfig fConfig) throws ServletException {}
        public void destroy() {}
    }
    View Code

      web.xml:注册CharacterEncodingFilter

    <!-- 过滤器 -->
    <filter>
      <filter-name>CharacterEncodingFilter</filter-name>
      <filter-class>com.oy.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>CharacterEncodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
    View Code

      所以,MyServlet 中无需编写处理编码的代码了

    public class MyServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String name = req.getParameter("name");
            resp.getWriter().print(name);
        }
    
        @Override
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String name = req.getParameter("name");
            resp.getWriter().print(name);
        }
    }
    View Code

    后注:spring 项目中通常修改Tomcat的conf目录下的server.xml中配置Connector的URIEconding=“UTF-8"属性来处理 GET 请求编码,通过配置spirng 提供的 org.springframework.web.filter.CharacterEncodingFilter 来处理 POST 编码。

    <!-- POST编码过滤器 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- <async-supported>true</async-supported> -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    View Code

    7、springboot 注册过滤器    <--返回目录

      https://www.cnblogs.com/tiancai/p/11196667.html

     参考:

      1)关于HTTP GET请求的url中文参数编码

  • 相关阅读:
    (三十七)Unittest单元测试框架之认识unittest-重要的概念
    (三十六)Unittest单元测试框架之认识unittest-认识单元测试
    (三十五)什么是自动化测试模型之数据驱动测试实例
    Django_前介
    Django_JavaScript
    Django_HTML
    LAMP环境搭建,防火墙开启,数据库挂载在逻辑卷
    shell脚本案例
    Linux轻量级自动化运维工具— Ansible
    Docker实战总结
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/12682155.html
Copyright © 2020-2023  润新知