A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

许煜 每日总结
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();
                }
        }
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马