web proxy and class loader
概述
- 使用“动态代理”来解决网站的字符集编码问题
- 对比使用装饰者模式来处理网站的字符集编码问题
Proxy
-
Proxy.newProxyInstance
- 参数1:loader,类加载器,动态代理类 任何类都需要类加载器加载到内存
- 使用方式1:当前类.class.getClassLoader()
- 参数2:class[] interfaces 代理类需要实现的所有接口
- 使用方式1:目标类实例.getClass().getInterfaces() 此种方式只能获取自己的接口,无法获取父元素接口
- 使用方式2:new Class[] {UserService.class}
- 参数3:InvocationHandler 处理类,接口,必须进行实现,一般采用匿名内部实现
- 提供 invoke 方法,代理类的每个方法执行的时候,都将调用一次 invoke
- 参数1:Object proxy:代理对象
- 参数2:Method method:代理对象当前执行的方法的描述对象(反射)
- 执行方法名:method.getName()
- 执行方法:method.invoke(对象,实际参数)
- 参数3:Object[] args:方法实际参数
- 提供 invoke 方法,代理类的每个方法执行的时候,都将调用一次 invoke
- 参数1:loader,类加载器,动态代理类 任何类都需要类加载器加载到内存
-
通用字符集编码过滤器
@WebFilter("/*")
public class GenericEncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) request;
// 增强req
HttpServletRequest myReq = (HttpServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 判断是否是在执行getParameter()方法
if ("getParameter".equals(method.getName())) {
// 判断是get还是post请求
String _method = req.getMethod();
if ("get".equalsIgnoreCase(_method)) {
String value = (String) method.invoke(req, args);
return new String(value.getBytes("iso-8859-1"),"utf-8");
} else if ("post".equalsIgnoreCase(_method)) {
req.setCharacterEncoding("utf-8");
}
}
return method.invoke(req, args);
}
});
// 设置响应头
response.setContentType("text/html;charset=utf-8");
// 放行
chain.doFilter(myReq, response);
}
@Override
public void destroy() {}
}
Class Loader
- https://blog.csdn.net/u013412772/article/details/80837735
- 类加载器:负责加载类的对象。将class文件从硬盘加载到内存中生成Class对象。
- 所有的类加载器都是 java.lang.ClassLoader 的子类
- 使用 类.class.getClassLoader() 获得加载自己的类加载器
- 类加载器的加载机制:全盘负责委托机制
- 全盘负责:A类使用B类(不存在),那A类的加载器必须负责加载B类
- 委托机制:A类使用B类(不存在),那A类先问其父类是否加载,如果加载将直接使用;如果没有加载,再进行加载。
- 全盘负责委托机制会保证一个class文件只会被加载一次,形成一个Class对象。
- 如果一个class文件,被两个类加载器加载,将是两个对象