过滤器+动态代理过滤请求数据
过滤器
用来过滤请求数据和响应数据的技术
创建方式
首先实现Filter接口:
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//设置字符编码格式,设置过滤请求数据和响应数据的字符编码集
servletRequest.setCharacterEncoding("UTF8");
servletResponse.setContentType("text/html;charset=UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
//过滤完成,放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
注册方式(即项目如何使用)
选择其中一种即可,执行顺序是:
1、先执行配置方式在执行注解的方式
2、配置方式里面,按照在web.xml里面的顺序执行
3、注解方式里面按照类名的字母顺序执行a>b>…>z
配置文件的方式(web.xml)
注意:必须在servlet之前
<!-- 注册过滤器-->
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.cqust.filter.EncodingFilter</filter-class>
</filter>
<!-- 给过滤器添加映射-->
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 注册servlet-->
<servlet>
<servlet-name>userServlet</servlet-name>
<servlet-class>com.cqust.controller.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
注解的方式
在需要的类上添加
@webServlet("/*")//注解方式配置servlet
@webFilter("/*")//注解方式配置过滤器
*:表示匹配任意个任意字符,只能在最前或者最后
如:/*:匹配任意url
/*.do:匹配所有的xxx.do
代理模式
代理模式就是,通过第三方的类代理目标类,就是在执行目标类的方法之前或者之后执行我们需要添加的方法
注意:代理类和目标需要实现同一个接口类
静态代理
由程序员自己写一个代理类对目标类进行扩展
首先需要定义一个接口和目标类:
/**
* 接口类
*/
public interface Car {
/**
* 卖某种车辆
* @param carName 车辆名称
*/
void saleCar(String carName);
}
/**
* 目标类,汽车制造厂
* @author wwq
* @date 2021/5/11-15:44
*/
public class CarFactory implements Car {
@Override
public void saleCar(String carName) {
System.out.println("创造汽车:"+carName);
}
}
程序员自己编写代理类
/**
* 代理类 在执行买车服务之前、之后添加了一下方法
* @author wwq
* @date 2021/5/11-15:46
*/
public class Car4s implements Car {
private Car proxyimp;
public Car4s(Car carFactory) {
this.proxyimp = carFactory;
}
@Override
public void saleCar(String carName) {
System.out.println("预约客户");
proxyimp.saleCar(carName);
System.out.println("车类进行保养");
}
}
调用代理的对象实现测试:
//静态代理
Car carFactory = new CarFactory();
Car carS = new Car4s(carFactory);
carS.saleCar("劳斯莱斯·幻影");
动态代理
首先接口类和目标类都是上面的方法
/*
参数1:目标类的加载器,推测用来加载该类
参数2,目标类的实现的接口数组,推测用来实现父接口
参数3,执行处理,需要程序员实现InvocationHandler,实现方法invoke
*/
Car o = (Car) Proxy.newProxyInstance(CarFactory.class.getClassLoader(), CarFactory.class.getInterfaces(), new MyInvokHandler(CarFactory.class));
自定义执行处理器,添加扩展方法
/**
* 自定义执行处理器
* @author wwq
* @date 2021/5/11-16:41
*/
public class MyInvokHandler implements InvocationHandler {
private Class aClass;
public MyInvokHandler(Class aClass) {
this.aClass = aClass;
}
/**
*
* @param proxy 代理对象(程序自动创建的)
* @param method 需要执行的每一个方法
* @param args 参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法前的扩展");
//目标对象
Object o = aClass.newInstance();
method.invoke(o,args);
System.out.println("方法后的扩展");
return null;
}
}
过滤器+动态代理
自定义过滤器,过滤所有请求
/**
* 过滤器,过滤请求数据中含有sb的参数,将其替换成***
* @author wwq
* @date 2021/5/11-17:48
*/
@WebFilter("/*")
public class ProxyRegister implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//动态代理处理注册的用户名,过滤掉sb
ServletRequest req = (ServletRequest) Proxy.newProxyInstance(servletRequest.getClass().getClassLoader(), servletRequest.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//执行方法的名称
String name = method.getName();
if ("getParameterMap".equals(name)){
//获取所有的参数
Map<String,String[]> map = (Map) method.invoke(servletRequest, args);
//原生的map无法进行修改,需要复制一个新map
HashMap<String,String[]> new_map = new HashMap<>(map);
//获取所有参数的Key,通过key修改对应的value,如果直接values 无法修改map里面的值
Set<String> key = new_map.keySet();
for (String k : key) {
//获取参数对应的值,(如:checkbox对应多个值)
String[] values = new_map.get(k);
//遍历每一个值进行判断是否包含sb,有就进行替换
for (int i = 0; i < values.length; i++) {
if (values[i].contains("sb")){
values[i] = values[i].replace("sb","***");
}
}
}
return new_map;
}
return method.invoke(servletRequest,args);
}
});
System.out.println("register");
filterChain.doFilter(req,servletResponse);
}
@Override
public void destroy() {
}
}