版权声明:本文为博主原创文章,未经博主允许不得转载。 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 {
}
}