而动态代理则能实现用哪个增强哪个,相对于使用装饰者模式,代码量简单,而且代码格式固定。
我们经常说增强的方式常用的有:
1.继承
2.实现
3.动态代理
4.装饰者设计模式
什么是动态代理呢?
动态代理:在程序运行时 动态创建类 此类代表代理类。
要解决中文乱码问题,同样需要过滤器,在过滤器中使用动态代理。
具体代码如下:
final HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
request.setCharacterEncoding("utf-8");
HttpServletRequest proxyRequest = (HttpServletRequest) Proxy.newProxyInstance(
EncodeFilter.class.getClassLoader(),
request.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强方法名为getParameter的方法
if("getParameter".equals(method.getName())){
//获取请求方式
String method2 = request.getMethod();
//判断是否为get请求
if("GET".equalsIgnoreCase(method2)){
//转码
String val = request.getParameter(args[0].toString());
//将转码后的结果返回
return new String(val.getBytes("iso-8859-1"),"utf-8");
}
}
//执行该方法
return method.invoke(request, args);
}
});
//放行
chain.doFilter(proxyRequest, response);
结合上述代码分析各个参数的意义:
Proxy.newProxyInstance(参数1,参数2,参数3)
参数1:当前类.getClass.getClassLoader
以前没有 proxyRequest 这个类 动态创建这个类出来 加载到内存 需要用到类加载器。
参数2:目标类.getClass.getInterfaces() 获得接口中的方法
动态创建的类 没有方法 方法要和目标类一样 所以获得目标的类接口的方法。
参数3:执行处理类
代理类的方法跟目标类的方法一样 但没有实现,所以要有一个InvocatioHandler
invoke(Object proxy, Method method, Object[] args)中的三个参数:
参数1:Object proxy 代理对象
参数2:Method method 代理对象当前执行的方法的描述对象
参数3:当前执行的方法的实际参数
需要记住的是:目标类每调用一次执行方法 就执行一次代理类的invoke
具体执行流程为:
当请求过来时,先经过过滤器,之后过滤器放行,过滤器放行时传入的request对象时动态代理后的request对象。当进入servlet中时,servlet中调用request.getParameter方法获取请求的值时,由于这里的request对象已经换成我们使用动态代理生成的proxyRequest 对象,所以它会进入过滤器中执行new InvocationHandler()中的invoke方法 ,invoke方法中对原有的方法进行增强,从而解决乱码问题。