web_day40_Filter_生命周期&全站中文乱码

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35537301/article/details/84501581

一、生命周期

1、创建

  • 启动服务器的时候,创建过滤器对象
  • 然后调用init(FilterConfig config)方法完成初始化操作
  • 该方法在整个过滤器的生命周期中只会被执行一次!

2、执行

  • 当对指定的资源进行过滤的时候,会调用doFilter(ServletRequest req,ServletResponse resp,FilterChain chain)方法
  • doFilter方法子在整个过滤器的生命周期中会被执行多次
  • 处理HTTP的请求时,需要强转

3、销毁

  • 正常关闭服务器的时候,过滤器被销毁,会调用destroy()方法,该方法在整个过滤器的生命周期中只会执行一次!
  • 关闭服务器之前执行!

二、filter对象

1、FilterConfig对象

FilterConfig获得当前过滤器的初始化的配置信息

方法 说明
getFilterName() 获得Filter的名称
getInitParameter("username") 获得初始化的参数值(需要在web.xml文件中配置)

getServletContext()

获得ServletContext对象

getInitParameterNames()

获得所有配置的参数的名称

 

package com.itheima.web.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 BFilter implements Filter {

	public void destroy() {

	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 放行
		chain.doFilter(request, response);
	}

	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("过滤器名字:"+fConfig.getFilterName());
		System.out.println("初始化参数:"+fConfig.getInitParameter("username"));
		System.out.println("项目路径:"+fConfig.getServletContext().getContextPath());
	}

}

 

2、FilterChain对象

  • 过滤器链对象,由多个过滤器组成
  • 在过滤器链中的多个过滤器执行顺序与web.xml文件中配置filter-mapping的顺序有关,谁在前面就先执行!

package com.itheima.web.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 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 CFilter1 implements Filter {

	public void destroy() {

	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 放行
		System.out.println("第一座大山,女大王");
		chain.doFilter(request, response);
	}

	public void init(FilterConfig fConfig) throws ServletException {

	}

}
package com.itheima.web.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 CFilter2 implements Filter {

	public void destroy() {

	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 放行
		System.out.println("第二座大山,二大王");
		chain.doFilter(request, response);
	}

	public void init(FilterConfig fConfig) throws ServletException {

	}

}
package com.itheima.web.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 CServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 处理post请求中文乱码问题
		request.setCharacterEncoding("utf-8");
		// 处理响应的中文乱码问题
		response.setContentType("text/html;charset=utf-8");
		System.out.println("已抵达,姥姥家");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

三、相关配置

1、url-pattern的配置

  • 完全匹配:/a.jsp   只过滤a.jsp文件
  • 目录配置过滤a目录下面b目录里面的所有资源
  • 匹配所有::/a/b/*  /*     过滤所有
  • 扩展名匹配:*.jsp  过滤所有以.jsp结尾的文件

2、dispatcher的配置

  • REQUEST    只对请求进行过滤  【开发常用】
  • FORWARD    只对请求转发进行过滤
  • INCLUDE     只对请求包含进行过滤
  • ERROR      对跳转错误页面或全局错误页面的时候进行过滤

四、全站中文乱码

方式1:装饰者设计模式

  • 编写一个类实现共同的父接口
  • 在自己编写的实现类中的构造方法里面要有默认处理类的引用
  • 定义一个成员变量来存储默认的处理类的引用
  • 对需要增强的方法进行实现
  • 对其它方法(后续需要使用的方法) 进行实现

需要

package com.itheima.utils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

//1.被增强的对象和增强对象必须实现相同的接口或者继承包装类
public class MyHttpServletRequest extends HttpServletRequestWrapper {

    // 3.在增强对象中要有私有的属性(存储被增强对象,其目的是为了调用被增强对象的方法)
    private HttpServletRequest request;

    // 2.在增强对象类中的构造方法必须有被增强对象的引用(使用其父接口:多态<参数是形式参数,主要创建对象MyHttpServletRequest,构造方法使用具体实现对象即可>)
    public MyHttpServletRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    // 4.编写需要增强的方法(解决get请求中文乱码)
    @Override
    public String getParameter(String name) {
        // 获得用户的请求参数
        String parameter = request.getParameter(name);
        try {
            // 处理乱码
            parameter = new String(parameter.getBytes("iso8859-1"), "utf-8");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return parameter;
    }

    // 5.实现其它需要的方法(目前不需要)

}

 EncodingFilter过滤器

package com.itheima.web.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 javax.servlet.http.HttpServletResponse;

import com.itheima.utils.MyHttpServletRequest;

public class EncodingFilter implements Filter {

    public void destroy() {

    }
    
    /**
     * 处理请求全站乱码
     */
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        //1.强转
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        System.out.println(request);
        
        //解决响应的中文乱码
        response.setContentType("text/html;charset=utf-8");
        
        //2.获得请求方式
        String method = request.getMethod();
        //3.判断
        if(method.equalsIgnoreCase("post")){
            //解决post请求乱码
            request.setCharacterEncoding("utf-8");
            //放行
            chain.doFilter(request, response);
            //不让后面代码执行
            return ;
        }else if(method.equalsIgnoreCase("get")){
            //解决get请求乱码
            //request.getParameter("username"); //不这么干,这样其它的就不能用了,写死了,我们可以考虑对request的getParameter方法进行增强(具备处理get请求乱码问题的能力)
            //创建MyHttpServletRequest对象
            MyHttpServletRequest myrequest = new MyHttpServletRequest(request);
            //放行
            chain.doFilter(myrequest, response);
            //不让后面代码执行
            return ;
        }
        //放行
        chain.doFilter(request, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {

    }

}
package com.itheima.web.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 EncodingServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //如果是get请求,那么调用此方法,已经处理了中文乱码
        String username = request.getParameter("username");
        System.out.println(username);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

 方式二:动态代理

package cn.itcast.web.filter;
import java.io.IOException;
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;

public class EncodingFilter implements Filter {

    public void destroy() {

    }

    //使用动态代理处理全站中文乱码问题
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //1.创建一个被代理对象(直接强转)
        final HttpServletRequest req = (HttpServletRequest) request;
        
        //2.创建一个代理对象
        /**
         * 第一个参数:通过被代理对象获得的类加载器
         * 第二个参数:通过被代理对象获得的父接口
         * 第三个参数:代理对象处理类(接口)
         */
        HttpServletRequest myreq = (HttpServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            
            //代理对象处理接口的方法
            /**
             * 第一个参数:代理对象(此处没卵用)
             * 第二个参数:被代理对象的方法对象
             * 第三个参数:被代理对象的方法对象的参数
             */
            //乱码处理的代码都写在这个方法中(每调用一次目标方法都会执行一次invoke方法)
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //对指定的方法进行增强(getParameter)
                //3.通过被代理对象的方法对象获得方法名称
                String methodName = method.getName();
                //4.对指定的方法进行增强
                if("getParameter".equals(methodName)){
                    //5.获得请求方式
                    String method2 = req.getMethod();
                    //6.判断
                    if("GET".equalsIgnoreCase(method2)){
                        //7.执行被代理对象里面的方法获得请求参数(是乱码的)【代理对象的功能依靠被代理对象的方法】
                        String parameter = (String) method.invoke(req, args);
                        //8.处理GET请求的乱码问题
                        parameter = new String(parameter.getBytes("iso8859-1"),"utf-8");
                        //9.将处理好乱码的参数返回
                        return parameter;
                    }else if("POST".equalsIgnoreCase(method2)){
                        //10.设置编码
                        req.setCharacterEncoding("utf-8");
                        //11.在代理对象中依旧得依赖被代理对象的方法
                        return method.invoke(req, args);
                    }
                    //12.处理其它请求方式(比如DELETE/PUT)
                    return method.invoke(req, args);
                }
                //13.对其它方法进行调用(在代理对象中依旧得依赖被代理对象的方法)
                return method.invoke(req, args);
            }
        });
        
        //放行(一定是代理对象!)
        chain.doFilter(myreq, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {

    }

}

猜你喜欢

转载自blog.csdn.net/qq_35537301/article/details/84501581