web19_proxy_classloader

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:方法实际参数
  • 通用字符集编码过滤器

@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文件,被两个类加载器加载,将是两个对象
发布了48 篇原创文章 · 获赞 1 · 访问量 1060

猜你喜欢

转载自blog.csdn.net/laonxs/article/details/104563016