javaWeb 使用 filter 处理全站乱码问题

springboot 实例 https://blog.csdn.net/m0_38075425/article/details/81164930

https://www.cnblogs.com/Westfalen/p/6170312.html

1. web.xml文件中的配置

复制代码
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>de.bvb.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>characterEncoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping> 
复制代码

2.CharacterEncodingFilter.java代码

复制代码
package de.bvb.web.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

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 javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

/**
 * 
 * <p><b>Function:     处理全站乱码问题
 * </b></p>Class Name: CharacterEncodingFilter<br/>
 * Date:2016-12-13下午3:31:40<br/>author:Administrator<br/>since: JDK 1.6<br/>
 */
public class CharacterEncodingFilter implements Filter {
    private String charset = "UTF-8"; //默认编码设置为 UTF-8

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String charset = filterConfig.getInitParameter("characterEncoding");
        if (charset != null && !charset.equals("")) {
            this.charset = charset;
        }
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        request.setCharacterEncoding(charset); //只能处理post方式的请求乱码
        response.setCharacterEncoding(charset);
        response.setContentType("text/html;charset=" + charset);

        chain.doFilter(new CharacterEncodingHttpServletRequest(request), response);
    }

    /**
     * 
     * <p><b>Function:     使用包装设计模式处理get方式的请求乱码
     * </b></p>Class Name: CharacterEncodingHttpServletRequest<br/>
     * Date:2016-12-13下午3:45:29<br/>author:Administrator<br/>since: JDK 1.6<br/>
     */
    class CharacterEncodingHttpServletRequest extends HttpServletRequestWrapper {
        private HttpServletRequest request;

        public CharacterEncodingHttpServletRequest(HttpServletRequest request) {
            super(request);
            this.request = request;
        }

        @Override
        public String getParameter(String name) {
            String value = request.getParameter(name);
            if (!"get".equalsIgnoreCase(request.getMethod())) { //如果是非get方法,直接返回
                return value;
            }
            if (value == null) {
                return null;
            }
            try {
                return value = new String(value.getBytes("iso8859-1"), request.getCharacterEncoding());
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }

    }

    @Override
    public void destroy() {
    }

}
复制代码

 2.2 也可以通过动态代理技术处理 (-----------------------------有问题)

复制代码
package de.bvb.web.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

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 javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

/**
 * 
 * <p><b>Function:     通过动态代理技术处理全站乱码问题
 * </b></p>Class Name: CharacterEncodingFilter<br/>
 * Date:2016-12-13下午3:31:40<br/>author:Administrator<br/>since: JDK 1.6<br/>
 */
public class CharacterEncodingFilter implements Filter {
    private String charset = "UTF-8"; //默认编码设置为 UTF-8

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String charset = filterConfig.getInitParameter("characterEncoding");
        if (charset != null && !charset.equals("")) {
            this.charset = charset;
        }
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        request.setCharacterEncoding(charset); //只能处理post方式的请求乱码
        response.setCharacterEncoding(charset);
        response.setContentType("text/html;charset=" + charset);
        chain.doFilter((ServletRequest) Proxy.newProxyInstance(CharacterEncodingFilter.class.getClassLoader(), HttpServletRequest.class.getInterfaces(),
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //改写 getParameter() 方法在get请求时候的功能
                        if ("get".equalsIgnoreCase(request.getMethod()) && "getParameter".equals(method.getName())) {
                            String value = (String) method.invoke(request, args);
                            if (value == null) {
                                return null;
                            }
                            return new String(value.getBytes("iso8859-1"), request.getCharacterEncoding());
                        }
                        return method.invoke(request, args);
                    }
                }), response);
    }

    @Override
    public void destroy() {
    }

}
复制代码
  _________________________________________________________________
 
filter过滤器简单实例
https://blog.csdn.net/tikaber/article/details/78778884

package com.test.filter; import java.io.IOException; 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; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class FirstFilter implements Filter{ //FilterConfig可用于访问Filter的配置信息 private FilterConfig config; @Override public void destroy() { this.config = null; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //获取ServletContext对象,用于记录日志 ServletContext context = this.config.getServletContext(); long before = System.currentTimeMillis(); HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; HttpSession session = req.getSession();; String url = req.getRequestURI(); String queryString = req.getQueryString(); String fullPath = url + queryString; if (fullPath.equals(session.getAttribute("fullPath"))) { long middleTime = System.currentTimeMillis(); if (middleTime - (Long.parseLong(session.getAttribute("before").toString()))<5000) { System.out.println("重复提交"); } } session.setAttribute("before", before); session.setAttribute("fullPath", fullPath); // System.out.println("before invoke firstFilter's chain.doFilter() .."); chain.doFilter(req, resp); // System.out.println("after invoke firstFilter's chain.doFilter() .."); long after = System.currentTimeMillis(); long sumLoad = after - before; System.out.println("1.请求被定位到" + fullPath + "所花的时间为: " + sumLoad); } @Override public void init(FilterConfig config) throws ServletException { this.config = config; System.out.println("firstFilter init()..."); } private HttpServletRequest request; public boolean getParameter() { //如果是以post方式提交数据的,就直接返回获取到的值 if(this.request.getMethod().equalsIgnoreCase("post")) { return true; }else { return false; } } }
 
 
__________________________________________________________________

 https://www.cnblogs.com/qinning/p/9858633.html

一、过滤器Filter

1.filter的简介

filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行,并且可以对目    标资源访问前后进行逻辑处理

2.快速入门

步骤:

1)编写一个过滤器的类实现Filter接口

2)实现接口中尚未实现的方法(着重实现doFilter方法)

3)在web.xml中进行配置(主要是配置要对哪些资源进行过滤)

public class QuickFilter1  implements Filter{

    @Override
    //Filter对象销毁的时候执行destory方法  项目关闭时 (服务器关闭)
    public void destroy() {
        System.out.println("destroy...");        
    }

    @Override
    //doFilter是Filter的核心过滤的方法
        /*
         * request: 内部封装是客户端http请求的内容
         * response: 代表是响应
         * FilterChain: 过滤器链对象
         * 
         */
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
            throws IOException, ServletException {
        // 对客户端的请求 和 响应 做出  过滤 和 拦截 处理操做
        System.out.println("filter1 running....");
        //放行请求    处理完  将请求 和响应 放到 dofilter里 然后 继续下一层操做
        arg2.doFilter(arg0, arg1);
    }

    @Override
    //Filter对象创建的时候执行init方法     ---init方法 只在filter 创建的时候   执行一次
    public void init(FilterConfig arg0) throws ServletException {
        // T1、获得web.xml中filter 的名称<filter-name>QuickFilter1</filter-name>
         System.out.println("filter的名称:"+arg0.getFilterName());
        //2、获得当前filter的初始化参数    ps: 初始化参数是在 filter里面 设置的  获取的是这里面的value 
         System.out.println(arg0.getInitParameter("aaa"));
         //3   获得所有的初始化参数的名称    和 请求响应的 类似  不常用
         // Enumeration<String> parameterNames = arg0.getInitParameterNames();
        
         //4、获得servletContext   所有 servletContext 先创建  后创建的 是 filter
        arg0.getServletContext();
        System.out.println("init.......");
    }

}

  <filter>
    <filter-name>filter1</filter-name>
    <filter-class>com.imooc.web.filter.QuickFilter1</filter-class>
    <init-param>
      <param-name>aaa</param-name>
      <param-value>woaini</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>filter1</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>

3.Filter的API详解

(1)filter生命周期及其与生命周期相关的方法

Filter接口有三个方法,并且这个三个都是与Filter的生命相关的方法

init(Filterconfig):代表filter对象初始化方法 filter对象创建时执行  init方法 只在filter 创建的时候   执行一次

doFilter(ServletRequest,ServletResponse,FilterCha):代表filter执行过滤的核心方法,如果某资源在已经被配置到这个filter进行过滤的话,那么每次访问这个资源都会执行doFilter方法  --可以多次访问  多次执行

* FilterChain: 过滤器链对象   :接受客户端 的 请求和响应  然后向下一个 filter对象  传递值 直到                                  传递到 dopost/doGet 方法中  然后再返回

 *   问题1: 那么多filter对象  先执行的是哪一个?  domain怎么传递filter对象?

 *     Tomcat 会根据<filter-mapping>映射 在 web.xml中配置的先后顺序 来依次执行filter对象 

 *     注意是<filter-mapping>的 先后顺序 不是 <filter>的先后顺序

destory():代表是filter销毁方法 当filter对象销毁时执行该方法

  

Filter对象的生命周期:

1 Filter何时创建:服务器启动时就创建该filter对象   (因为 filter的作用是过滤请求和响应  所以会在服务器启动时 就开始创建)

2  Filter何时销毁:服务器关闭时filter销毁  

3  每次访问(请求)的目标路径  只要配置的该目标资源经过filter过滤,dofilter就执行一次

   Filter的AP详解

1)init(FilterConfig)

其中参数config代表 该Filter对象的配置信息的对象,内部封装是该filter的配置信息。

 @Override
    //Filter对象创建的时候执行init方法     ---init方法 只在filter 创建的时候   执行一次
    public void init(FilterConfig arg0) throws ServletException {
        // T1、获得web.xml中filter 的名称<filter-name>QuickFilter1</filter-name>
         System.out.println("filter的名称:"+arg0.getFilterName());
        //2、获得当前filter的初始化参数    ps: 初始化参数是在 filter里面 设置的  获取的是这里面的value 
         System.out.println(arg0.getInitParameter("aaa"));
         //3   获得所有的初始化参数的名称    和 请求响应的 类似  不常用
         // Enumeration<String> parameterNames = arg0.getInitParameterNames();
        
         //4、获得servletContext   所有 servletContext 先创建  后创建的 是 filter
        arg0.getServletContext();
        System.out.println("init.......");
    }

2)destory()方法

filter对象销毁时执行

3)doFilter方法

doFilter(ServletRequest,ServletResponse,FilterChain)

其中的参数:

ServletRequest/ServletResponse:每次在执行doFilter方法时 web容器负责创建一个request和一个response对象作为doFilter的参数传递进来。该request个该response就是在访问目标资源的service方法时的request和response。

FilterChain:过滤器链对象,通过该对象的doFilter方法可以放行该请求

4.Filter的配置

 

url-pattern配置时

1)完全匹配  /sertvle1

2)目录匹配  /aaa/bbb/* ----最多的

/user/*:访问前台的资源进入此过滤器

/admin/*:访问后台的资源时执行此过滤器

3)扩展名匹配  *.abc  *.jsp   所有以 .abc  .jsp  结尾的

 

注意:url-pattern可以使用servlet-name替代,也可以混用  但是servlet-name               一次只能配一个    太麻烦  不提倡

 

 

dispatcher:访问的方式(了解)

REQUEST:默认值,代表直接访问某个资源时执行filter

FORWARD:转发时才执行filter

INCLUDE: 包含资源时执行filter

ERROR:发生错误时 进行跳转是执行filter

 

     俩个 servlet 对象    访问方式默认的情况下

          转发    filter对象 访问一次  (转发是请求一次)

          重定向  filter对象 访问俩次  (重定向是请求两次)

          转发时   

              A—转发---B   访问一次  先访问B资源 在访问A资源  

          下面的都差不多  不再次细说  可以自己敲一下     

 

   

总结Filter的作用?

1)公共代码的提取

2)可以对request和response中的方法进行增强(装饰者模式/动态代理)

3)进行权限控制

              通过filter 对请求  进行分析  可以决定对访问者 是否放行  是否允许其访问服务端的响应资源 (比如 ceo  和 普通员工访问的资源是不一样的 权限大小 CEO能访问的东西 员工不一定 能访问)

4)乱码处理

 

 

 

 

 

 联想

Struts2 框架 就是通过filter 过滤器  连接web工程的   它是使用的filter的接口

而 spring 框架  则是通过 listener 监听器 连接的项目工程

       应用 处理乱码 


public class EncondingFilter implements Filter {

   
    public void destroy() {
        // TODO Auto-generated method stub
    }

    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
        //通过filter 统一完成 乱码问题
        request.setCharacterEncoding("UTF-8");
        //在传递request之前对request的getParameter方法进行增强
        //增强方法的三种模式     动态代理  继承   装饰者模式
    
        /*
         * 装饰者模式(包装)
         * 
         * 1、增强类与被增强的类要实现统一接口
         * 2、在增强类中传入被增强的类
         * 3、需要增强的方法重写 不需要增强的方法调用被增强对象的
         * 
         */
        
    //被增强的对象     --- get方法 的 乱码解决
    HttpServletRequest req = (HttpServletRequest) request;
    //增强对象
    EnhanceRequest enhanceRequest = new EnhanceRequest(req);
        chain.doFilter(request, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }
//HttpServletRequestWrapper  方法  本质 还是 request 方法   

    /**
     * Servlet  filter可以在调用一个servlet的服务方法后,拦载或加工HTTP请求。尽管这非常诱人,
     * 但其实际使用却有所限制,因为你不能改变HttpServletRequest对象。
     * 这时候装饰模式派上了用场。创建HttpServletRequest的装饰类,需要继承HttpServletRequestWrapper
     * 并且覆盖(增强)你希望改变的方法。 
     * @author lqf
     *
     */
class EnhanceRequest extends HttpServletRequestWrapper{
    
    private HttpServletRequest request;

    public EnhanceRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }
    //对getParaameter增强
    @Override
    public String getParameter(String name) {
        String parameter = request.getParameter(name);//乱码
        try {
            parameter = new String(parameter.getBytes("iso8859-1"),"UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return parameter;
    }

    
}

__________________________________________________________________________________
 

filter过滤器简单实例

  1.  
    package com.test.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.ServletContext;
  9.  
    import javax.servlet.ServletException;
  10.  
    import javax.servlet.ServletRequest;
  11.  
    import javax.servlet.ServletResponse;
  12.  
    import javax.servlet.http.HttpServletRequest;
  13.  
    import javax.servlet.http.HttpServletResponse;
  14.  
    import javax.servlet.http.HttpSession;
  15.  
     
  16.  
    public class FirstFilter implements Filter{
  17.  
     
  18.  
    //FilterConfig可用于访问Filter的配置信息
  19.  
    private FilterConfig config;
  20.  
    @Override
  21.  
    public void destroy() {
  22.  
    this.config = null;
  23.  
    }
  24.  
     
  25.  
    @Override
  26.  
    public void doFilter(ServletRequest request, ServletResponse response,
  27.  
    FilterChain chain) throws IOException, ServletException {
  28.  
     
  29.  
    //获取ServletContext对象,用于记录日志
  30.  
    ServletContext context = this.config.getServletContext();
  31.  
    long before = System.currentTimeMillis();
  32.  
    HttpServletRequest req = (HttpServletRequest) request;
  33.  
    HttpServletResponse resp = (HttpServletResponse) response;
  34.  
    HttpSession session = req.getSession();;
  35.  
    String url = req.getRequestURI();
  36.  
    String queryString = req.getQueryString();
  37.  
    String fullPath = url + queryString;
  38.  
    if (fullPath.equals(session.getAttribute("fullPath"))) {
  39.  
    long middleTime = System.currentTimeMillis();
  40.  
    if (middleTime - (Long.parseLong(session.getAttribute("before").toString()))<5000) {
  41.  
    System.out.println("重复提交");
  42.  
    }
  43.  
    }
  44.  
    session.setAttribute("before", before);
  45.  
    session.setAttribute("fullPath", fullPath);
  46.  
    // System.out.println("before invoke firstFilter's chain.doFilter() ..");
  47.  
    chain.doFilter(req, resp);
  48.  
    // System.out.println("after invoke firstFilter's chain.doFilter() ..");
  49.  
    long after = System.currentTimeMillis();
  50.  
    long sumLoad = after - before;
  51.  
    System.out.println("1.请求被定位到" + fullPath + "所花的时间为: " + sumLoad);
  52.  
     
  53.  
    }
  54.  
     
  55.  
    @Override
  56.  
    public void init(FilterConfig config) throws ServletException {
  57.  
    this.config = config;
  58.  
    System.out.println("firstFilter init()...");
  59.  
    }
  60.  
     
  61.  
    private HttpServletRequest request;
  62.  
    public boolean getParameter() {
  63.  
    //如果是以post方式提交数据的,就直接返回获取到的值
  64.  
    if(this.request.getMethod().equalsIgnoreCase("post")) {
  65.  
    return true;
  66.  
    }else {
  67.  
    return false;
  68.  
    }
  69.  
    }
  70.  
     
  71.  
    }
原文地址:https://www.cnblogs.com/kelelipeng/p/11381661.html