许煜 每日总结
Web增强day2
动态代理增强
前提 被增强的类实现接口即可 动态代理比起装饰者模式的优势在于动态代理更加直接以及灵活,装饰者模式增强类需要被增强类实现同一个接口,在增强类中获得被增强类的引用.以及若是没有提供准备好的模板类(包装类),装饰者模式需要实现接口全部方法,而动态代理可以利用反射直接加强需要增强的方法.
动态代理实现细节
类加载器 class.getclassloader( ).
所有接口 class.getinterfs(),
代理类 InvocationHandler( )用于实现增强内容
Proxy.newProxyInstance(classloader, interfaces,new InvocationHandler( ){ });
InvocationHandler是一个接口 可通过创建匿名内部类 和创建InvocationHandler实现类来充当代理类
重写InvocationHandler 的invoke的方法来增强方法 通过方法名匹配调用指定代码块 若是不需要增强的方法 则直接返回原方法调用
动态代理处理编码乱码
// 动态代理处理乱码
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 这里为什么要求用final?//匿名内部类调用的参数必须为final修饰 ? 规定
final HttpServletRequest req = (HttpServletRequest) request;
// 类加载器
ClassLoader cl =req.getClass().getClassLoader();
// 接口集合
Class<?>[] interfaces = req.getClass().getInterfaces();
// 增强req
HttpServletRequest myReq = (HttpServletRequest) Proxy.newProxyInstance(cl, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if ("getParameter".equals(method.getName())) {
String type = req.getMethod();
if ("get".equalsIgnoreCase(type)) {
String value = (String) method
.invoke(req, args);
value = new String(
value.getBytes("ISO-8859-1"), "UTF-8");
return value;
} else if ("post".equalsIgnoreCase(type)) {
req.setCharacterEncoding("UTF-8");
}
}
return method.invoke(req, args);
}
});
chain.doFilter(myReq, response);
}
BaseServlet存在的意义 避免一个请求就创建一个Servlet,提供公共Servlet以提高代码的复用性.
原理:需要传递的参数为调用的方法名 利用反射通过方法名调用方法,baseServlet继承httpServlet后,其余sevlet只需继承baseServle即可
难以理解的点:this.getclass(),this永远表示的是当前类的对象,继承类继承baseServlet后代码执行到this.getclass()获得到的class对象就是自己的class(),这个时候super.class代表的才是其父类的class对象
继承baseServlet()的类不用再重写service方法且将方法返回对象设为path更方便请求后进行页面的跳转等操作
代码如下
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 通过连接将方法名传过来
String methodName = request.getParameter("method");
// 反射 通过方法名调用
Class clazz = this.getClass();// 继承类调用时获得的是自己本身的class对象
try {
Method method = clazz.getMethod(methodName,HttpServletRequest.class, HttpServletResponse.class);
// 调用方法
String path = (String) method.invoke(this, request, response);
// 将register login等方法返回值设为string路径更方便坐页面跳转等后续处理
if (path != null) {
request.getRequestDispatcher(path).forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
|