zoukankan      html  css  js  c++  java
  • 用伪代码梳理javaweb从零开始

    架构步骤:
    一、确定目标
     @Controller
     class CustomerController {
      @Inject
      CustomerService customerService;
      
      @Action("get:customer")
      View index(Param param){
       List<customer> customerList = customerService.getCustomerList();
       return new View("customerList.jsp").addModel("customerList",customerList);
      }
      
      @Action("post:customer_create")
      public Data createSubmit(Param param){
       Map<String,Object> fieldMap = param.getMap();
       boolean result = customerService.createCustomer();
       return new Data(result);
      }
      
      ...
     }

    二、搭建轻量级Web框架

    1、创建框架项目:
    A、new maven prj -> 
        goupId:org.smart4j
        artifactId:smart-framework
        version:1.0.0
    B、Maven pom.xml:
        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artfactId>java.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        <dependency>
        <!-- JSP -->
        <!-- JSTL -->
        <!-- SLF4J -->
        <!-- MYSQL -->
        <!-- Jackson -->
        <!-- Apache Commons Lang -->
        <!-- Apache Commons DbUtils -->
        <!-- Apache DBCP -->
    2、定义框架配置项:
        2.1、smart.properties 配置文件
        |--src
            |--main
                |--resources 
                    |--smart.properties
                        smart.framework.jdbc.xx = com.mysql.jdbc.Driver
                        ...
        2.2、加载配置项:
            |-- ConfigConstant  相关配置项常量(匹配配置文件内容)
            |-- ConfigHelper     属性文件助手类
                    |-- PropsUtil.loadProps(ConfigConstant.CONFIG_FILE);
                    |-- getJdbcXX() -> 获取对应的属性
    3、开发一个类加载器:
        描述:用来加载该基础包名下的所有类,比如使用了某注解的类,或者实现了某接口的类,再或者继承了某父类的所有子类等。
        |-- ClassUtil 
            |-- ClassLoader getClassLoader();  // 获取类加载器
            |-- Class<?> loadClass(String className, boolean isInitialized); // 加载类
            |-- Set<Class<?>> getClassSet(String packageName);// 获取指定包名下的所有类
    4、定义注解类:
    // 控制器注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @Interface Controller {
    }
    // Action 方法注解
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @Interface Action {
        String value(); // 请求路径
    }
    // 服务类注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @Interface Service {
    }
    // 依赖注入注解
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @Interface Inject {
    }
    
    4.1 需要提供一个ClassHelper助手类(获取所加载的类)
    |-- ClassHelper
        |-- Set<Class<?>> CLASS_SET; // 定义类集合(用于存放所加载的类)
        |--    static{
                backPage = ConfigHelper.getAppBasePackage();
                CLASS_SET = ClassUtil.getClassSet(backPage);
            }
        |-- Set<Class<?>> getClassSet() -> return CLASS_SET;    // 获取应用包名下的所有类
        |-- Set<Class<?>> getServiceSet() -> return CLASS_SET.filter(cls -> cls.isAnnotationPresent(Service.class)); // 获取应用包名下的所有Service类
        |-- Set<Class<?>> getControllerSet() -> return CLASS_SET.filter(cls -> cls.isAnnotationPresent(Controller.class)); // 获取应用包名下的所有Contoller类
        |-- Set<Class<?>> getBeanClassSet() -> return (getServiceSet()+getControllerSet()); // 获取应用包名下所有Bean类(包括Service、Controller)
        
    4.2 实现Bean容器(因为ClassHelper助手类无法通过类来实例化)
    |-- ReflectionUtil 
        |-- Object newInstance(Class<?> cls) -> return cls.newInstance(); // 创建实例 
        |-- Object invokeMethod(Object obj, Method method, Object... args) { // 调用方法
                try {
                    method.setAccessible(true);
                    result = method.invoke(obj, args);
                } catch(e){}
            }
        |-- void setField(Object obj, Field field, Object value)    { // 设置成员变更
                try {
                    field.setAccessible(true);
                    field.setField(obj, value);
                } catch(e){}
            }
        
    4.3 提供一个Bean助手类
    结合上面2点,可以调用ClassHelper.getBeanClassSet(),循环实例化类ReflectionUtil.newInstance(cls),存在在静态Map<Class<?>,Object>
    |-- BeanHelper 
        |-- Map<Class<?>,Object> BEAN_MAP; // 定义bean映射(用于存在bean类与实例的映射关系)
        |-- static {
                // 
                Set<Class<?>> beanClassSet = ClassHelper.getBeanClassSet();
                for (classSet cls : beanClassSet){
                    Object obj = ReflectionUtil.newInstance(cls);
                    BEAN_MAP.put(cls, obj);
                }
            }
        |-- Map<Class<?>,Object> getBeanMap(); -> return BEAN_MAP; // 获取Bean映射
        |-- <T> T getBean(Class<T> cls); -> return BEAN_MAP.get(cls); // 获取Bean实例(引入泛型)
    
    5、实现依赖注入
    |-- IocHelper
        |-- static {
            //Set<?> beanClassSet = ClassHelper.getBeanClassSet();
            //for(beanClassSet beanClass : )
            // 获取所有bean类映射关系对象
            Map<Class<?>, Object> beanMap = ClassHelper.getBeanMap();
            // 遍历beanMap
            for(Map.Entry<Class<?>, Object> beanEntry: beanMap.entrySet()){
                // 取出bean 类与对象
                Class<?> cls = beanEntry.getKey();
                Object beanInstance = beanEntry.getValue();
                
                // 获取所有成员变量
                Field[] beanFields = cls.getDeclareFields();
                for(Field beanField : beanFields){
                
                    // 判断当前属性是否有注释@Inject
                    if (beanField.isAnnotationPresent(Inject.class)){
                        
                        // 在BeanMap 获取对象实例
                        Class<?> beanFieldClass = beanField.getType();
                        Object beanFieldInstance = beanMap.get(beanFieldClass);
                        // 通过反射设置属性值
                        ReflectionUtil.setField(beanInstance, beanField, beanFieldInstance);
                    }
                }
            }
        }
    
    6、加载Controller,定义一个ControllerHelper助手类,用来绑定请求与处理器之间映射关系
        |-- ControllerHelper
            |-- Map<Request, Handler> ACTION_MAP; // 用于存放请求与处理器之间映射关系(简称Action Map)
            |-- static {
                
                    // 获取所有的Controller类
                    Set<Class<?>> controllerClassSet = ClassHelper.getControllerCassSet();
                    if (CollectionUtils.isNotEmpty(controllerClassSet)){
                        // 遍历Controller类
                        for (Class<?> controllerClass : controllerClassSet){
                            // 获取Controller类定义的方法
                            Method[] methods = controllerClass.getDeclareMethods();
                            if (CollectionUtils.isNotEmpty(methods)){
                                // 遍历方法
                                for (Method method : methods){
                                    if (method.isAnnotationPresent(Action.class)){
                                        // 从Action获取URL映射规则
                                        Action action = method.getAnnotation(Action.calss);
                                        String mapping = action.value();
                                        // 验证映射规则
                                        if (mapping.matches("\w+:/\*")){
                                            String[] array = mapping.split(":");
                                            if (ArrayUtil.isNotEmpty(array) && array.lentgh()==2){
                                                // 获取请求方法和路径
                                                String requestMethod = array[0];
                                                String requestPath = array[1];
                                                Request request = new Request(requestMethod, requestPath); // 封装请求信息
                                                Handler handler = Handler(controllerClass, method); // 封装Action信息
                                                // 初始化Action Map
                                                ACTION_MAP.put(request, handler);
                                            }
                                            
                                            
                                        }
                                        
                                    }
                                }
                            }
                        }
                    }
                }
            |-- Handler getHandler(requestMethod, requestPath); -> return ACTION_MAP(new Request(requestMethod, requestPath)); // 获取Handler
    
    7、初始化框架:
        |-- HelperLoader
            |-- void init(){
                Class<?> classList = {ClassHelper.class, BeanHelper.class, IocHelper.class, ControllerHelper.class};
                for (Class<?> cls : classList){
                    ClassUtil.loadClass(cls.getName());
                }
            }
    
    8、请求转发器
    |-- Param // 参数
    |-- Map<String, Object> paramMap;
    |-- getLong(String name)
    |-- ...
    |-- View // 视图
    |-- String path;  // 视图路径 
    |-- Map<String, Object> model;  // 模型数据
    |-- addModel(String key, Object value); // 添加属性
    |-- getPath() -> return path;
    |-- getModel() -> return model;
    |-- Data // 返回数据对象
    |-- Object model; // 模型数据
    |-- DispatcherServlet extends HttpServlet     // 核心控制器
    |-- void init(ServletConfig servletConfig){
        // 初始化相关Helper类
        HelperLoader.init();
        // 获取ServletContext对象
        ServletContext servletContext = servletConfig.getServletContext();
        // 注册处理jsp的Servlet
        ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");
        jspServlet.addMapping(ConfigHelper.getAppJspPath());
        // 注册处理静态资源的默认Servlet
        ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
        jspServlet.addMapping(defaultServlet);
    }
    |-- void sevice(request, response){
        // 获取请求方法与请求路径
        String requestMethod = request.getRequestMethod();
        String requestPath = request.getPathInfo();
        // 获取Action 处理器
        Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
        if (handler != null){
            // 获取Controller类及Bean实例
            Class<?> controllerClass = handler.getControllerCass();
            Object controllerBean = BeanHelper.getBean(controllerClass);
            // 创建请求参数
            Map<String, Object> paramMap = new Hasm<String, Object>();
            Enumeration<String> paramNames = request.getParametersNames();
            while (paramNames.hasMoreElements()){
                String paramName = paramNames.nextElement();
                String paramValue = request.getParameter(paramName);
                parammap.put(paramName, paramValue);
            }
            String body = CodecUtil.decodeURL(StreamUtil.getString(request.getInputStream())); // CodecUtil-编码与解码工具类,StreamUtil-流操作工具类,
            if (StringUtil.isNotEmpty(body)){
                String[] params = StringUtil.splitString(body, "&");
                if (ArrayUtil.isNotEmpty(params)){
                    for (String param : params){
                        String[] array = StringUtil.splitString(param, "=");
                        if (ArrayUtil.isNotEmpty(array) && array.length() == 2){
                            String paramName = array[0];
                            String paramValue = array[1];
                            paramMap.put(paramName, paramValue);
                        }
                    }
                }
            }
            Param param = new Param(paramMap);
            // 调用 Action方法
            Method actionMethod = handler.getActionMethod();
            Object result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
            // 处理 Action 返回值
            if (result instanceof View){
                // 返回jsp页面
                View view = (View) result;
                String path = view.getPath();
                if (StringUtil.isNotEmpty(path)){
                    if (path.startsWith("/")){
                        response.sendRedirect(request.getContextPath() + path);
                    } else {
                        Map<String, Object> model = view.getModel();
                        for (Map.Entry<String, Object> entry : model.entrySet()){
                            request.setAttribute(entry.getKey(), entry.getValue());
                        }
                        request.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(request, response);
                    }
                }
            } else if (resut instanceof Data){
                // 返回json数据
                Data data = (Data) result;
                Object model = data.getModel();
                if (model != null){
                    response.setContentType("application/json");
                    response.setCharacterEncoding("UTF-8");
                    PrintWriter writer = response.getWriter();
                    String json = JsontUtil.toJson(model);
                    writer.write(json);
                    writer.flush();
                    writer.close();
                }
            }
        }
    }

    三、强化框架功能

    1、代理技术(静态代理、JDK动态代理、CGLib代理)
    静态代理:
    |-- Hello 
    |-- void say(String name);
    |-- HelloImpl implements Hello {
    voiv say(String name){
        sysout("Hello!"+name);
    }
    }
    |-- HelloProxy implents Hello {
        Hello hello; 
        HelloProxy(){
            hello = new HelloImpl();
        }
        voiv say(String name){
            before();
            sysout("Hello!"+name);
            end();
        }
        void before(){
            sysout("Before");
        }
        void after(){
            sysout("After");
        }
        
        main(String[] args){
            Hello hello = new HelloProxy();
            hello.say("Jack");
        }
    }
    JDK动态代理:
    |-- DynamicProxy implements InvocationHandler {
        Object target; 
        DynamicProxy (Object target){
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args){
            before();
            object result = method.invoke(target, args);
            after();
            return result;
        }
        ...
        
        main(String[] args){
            // 尝试1
            Hello hello = new HelloImpl();
            DynamicProxy dynamicProxy = new DynamicProxy(hello);
            Hello hello = (Hello)Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass.getInterfaces(), dynamicProxy);
            hello.say("Jack");
            
            // 尝试2
            DynamicProxy dynamicProxy = new DynamicProxy(new HelloImpl());
            Hello hello = dynamicProxy.getProxy();
            hello.say("Jack");
        }
        
        public <T> T getProxy(){
            return (T)Proxy.newProxyInstance(
                target.getClass().getClassLoader(), 
                target.getClass.getInterfaces(), 
                this
            );
        }
    }
    
    CGLib动态代理:
    |-- CGLibProxy implements MethodInterceptor {
        private static CGLibProxy instance = new CGLibProxy();
        
        private CGLibProxy() {}
        
        public CGLibProxy getInstance(){
            return instance;
        }
    
        public <T> T getProxy(Class<T> cls){
            return (T) Enhancer.create(cls, this);
        }
        public Object inercept(Object obj, Method method, Object[] args, MethodProxy proxy){
            before();
            Object result = proxy.invokeSuper(obj, args);
            after();
            return result;
        }
        ...    
        
        main(String[] args){
            // 尝试1
            CGLibProxy cgLibProxy = new CGLibProxy();
            Hello helloProxy = cgLibProxy.getProxy(HelloImpl.class);
            helloProxy.say("Jack");
            // 尝试2
            Hello helloProxy =CGLibProxy.getInstance().getProxy(HelloImpl.class);
            helloProxy.say("Jack");
        }
    }
    
    2、AOP技术
    |-- interface Greeting 
    |-- void sayHello(String name);
    |-- GreetingImpl implements Greeting
    |-- sayHello(String name){
        before();
        sysout("Hello!"+name);
        after();
    }
    |-- GreetingProxy implements Greeting
    |-- GreetingImpl greetingImpl;
    |-- GreetingProxy(GreetingImpl greetingImpl) -> this.greetingImpl = greetingImpl;
    |-- sayHello(String name){
        before();
        greetingImpl.sayHello();
        after();
    }
    |-- before() -> sysout("Before");
    |-- after() -> sysout("After");
    |-- main(String[] args){
        Greeting greetingProxy = new GreetingProxy(new GreetingImpl());
        greetingProxy.sayHello("Jack");
    }
    |-- JDKDynamicProxy implements InvocationHandler {
        Object target; 
        JDKDynamicProxy (Object target){
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args){
            before();
            object result = method.invoke(target, args);
            after();
            return result;
        }
        public <T> T getProxy(){
            return (T)Proxy.newProxyInstance(
                target.getClass().getClassLoader(), 
                target.getClass.getInterfaces(), 
                this
            );
        }
        private void before(){
            sysout("Before");
        }
        private void after(){
            sysout("After");
        }
        
        main(String[] args){
            Greeting greeting = new JDKDynamicProxy(new GreetingImpl()).getProxy();
            greeting.sayHello("Jack");
        }
    }
    |-- CGLibProxy implements MethodInterceptor{
        private static CGLibProxy instance = new CGLibProxy();
            
        private CGLibProxy() {}
        
        public CGLibProxy getInstance(){
            return instance;
        }
    
        public <T> T getProxy(Class<T> cls){
            return (T) Enhancer.create(cls, this);
        }
        public Object inercept(Object obj, Method method, Object[] args, MethodProxy proxy){
            before();
            Object result = proxy.invokeSuper(obj, args);
            after();
            return result;
        }
        main(String[] args){
            Greeting greeting = CGLibProxy.getInstance().getProxy(GreetingImpl.class);
            greeting.sayHello("Jack");
        }
    }
    
    3、spring AOP技术
    |-- GreetingBeforeAdvice implements MethodBeforeAdvice
        |-- before(Method method, Object[] args, Object target) throws Throwable -> sysout("Before");
    |-- AfterReturningAdvice 
        |-- afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable -> sysout("after");
    |-- GreetingBeforeAndAfterAdvice implements MethodBeforeAdvice, AfterReturningAdvice
        |-- before(Method method, Object[] args, Object target) throws Throwable -> sysout("Before");
        |-- afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable -> sysout("after");
    |-- GreetingAroundAdvice implements MethodInterceptor // 环绕增强(org.aopalliance.intercept.MethodInterceptor,AOP联盟)
        |-- Object invoke(MethodInvocation invocation){
            before();
            Object result = invocation.proceed();
            after();
        }
        |-- before() -> sysout("Before")
        |-- after() -> sysout("After")
    |-- main (String[] args){
            ProxyFactory proxyFactory = new ProxyFactory(); // 创建代理工厂
            proxyFactory.setTarget(new GreetingImpl()); // 射入目标类对象
            // proxyFactory.addAdvice(new GreetingBeforeAdvice()); // 添加前置增强
            // proxyFactory.addAdvice(new AfterReturningAdvice()); // 添加后置增强
            // proxyFactory.addAdvice(new GreetingBeforeAndAfterAdvice()); // 添加前后置增强
            proxyFactory.addAdvice(new GreetingAroundAdvice()); // 添加环绕增强
            
            Greeting greeting = (Greeting)proxyFactory.getProxy(); // 从代理工厂获取代理对象
            greeting.sayHello("Jack"); // 调用代理方法
        }
    |-- 配置文件-spring.xml
        <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
        <context:componet-scan base-package="aop.demo"/> 
        <!-- 配置一个代理 --> 
        <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="interfaces" value="aop.Greeting"></property><!-- 需要代理的接口 -->
            <property name="target" value="greetingImpl"></property><!-- 接口实现类 -->
            <!-- <property name="target" value="greetingAroundAdvice"></property> -->
            <property name="interceptorNames">
                <list>
                    <value>greetingAroundAdvice</value>
                </list>
            </property>
        </bean>
        
        spring2.5+特性,@Component
        @Component
        public calss GreetingImpl implements Greeting {
            ...
        }
        --> 
        <bean id="xxx" class="xxx">
    |-- 客户端调用
        |-- main(String[] args){
                ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml");
                Greeting greeting = (Greeting)context.getBean("greetingProxy");
                greeting.sayHello("Jack");
            }
    |-- 抛出增强-ThrowsAdvice
        |-- GreetingThrowAdvice implements ThrowsAdvice {
                public void afterThrowing(Method method, Object[] args, Object target, Exception e){
                    sysout("--------- Throw Exception ---------");
                    sysout("Target Class: " + target.getClass().getName());
                    sysout("Method Name: " + method.getName());
                    sysout("Exception Message: " + e.getMessage());
                    sysout("-----------------------------------");
                }
            }
    |-- 引入增强
        |-- interface Apology 
            |-- void saySorry(String name);
        |-- @Component
            GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology {
                @Override 
                public Object invoke(MethodInvocation invocation) throws Throwable{
                    return super.invoke(invocation);
                }
                
                @Overrice
                public void saySorry(String name){
                    sysout("Sorry! + name);
                }
            }
        |-- 配置文件-spring.xml
            <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
            <context:componet-scan base-package="aop.demo"/> 
            <!-- 配置一个代理 --> 
            <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                <property name="interfaces" value="aop.demo.Apology"></property><!-- 需要动态实现的接口 -->
                <property name="target" value="greetingImpl"></property><!-- 目标类 -->
                <property name="interceptorNames" value="greetingIntroAdvice"></property> <!-- 引入增强 -->
                <property name="proxyTargetClass" value="true"/> <!-- 代理目标类(默认为false,代理接口)-->
            </bean>
        |-- 调用
            |-- main(String[] args){
                ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml");
                GeetingImpl greetingImpl = (GeetingImpl)context.getBean("greetingProxy"); // 转型为目标类,而非它的接口
                greetingImpl.sayHello("Jack");
                
                Apology apology = (Apology) greetingImpl; // 将目标类型强制向上转型为Apology接口(这就是引入增强给我们带来的特性,也就是“接口动态实现”功能)
                apology.saySorry("Jack");
            }
    |-- AOP 切面
        |-- @Component
            public class GreetingImpl implements Greeting {
                @Override
                public void sayHello(){
                    sysout("Hello!" + name);
                }
                
                public void goodMorning(String name){
                    sysout("Good Morning!" + name);
                }
                public void goodNight(String name){
                    sysout("Good Night!" + name);
                }
            }
        |-- 配置文件-spring.xml
            <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
            <context:componet-scan base-package="aop.demo"/> 
            <!-- 配置一个切面 -->
            <bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
                <property name="advice" value="greetingAroundAdvice"></property> <!-- 增强 -->
                <property name="pattern" value="aop.demo.GreetingImpl.good.*"></property> <!-- 切点(正则表达式) -->
            </bean>
            
            <!-- 配置一个代理 --> 
            <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                <property name="target" value="greetingImpl"></property><!-- 目标类 -->
                <property name="interceptorNames" value="greetingAdvisor"></property><!-- 切面 -->
                <property name="proxyTargetClass" value="true"/> <!-- 代理目标类(默认为false,代理接口)-->
            </bean>
    |-- AOP自动代理(每一个类都需要配置切面太麻烦,因此需要自动生成代理)
        |-- 配置文件-spring.xml
        <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="target" value="*Impl"></property><!-- 目标类 -->
            <property name="interceptorNames" value="greetingAroundAdvice"></property><!-- 增强 -->
            <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
        </bean>
        *Impl -> 不清楚Bean实现了多少接口,不能代理接口,只能代理类。
        |-- 匹配到目标类的指定方法
            |-- 配置文件-spring.xml
                <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
                    <!-- <property name="target" value="*Impl">--></property><!-- 目标类 -->
                    <!-- <property name="interceptorNames" value="greetingAroundAdvice"></property>--><!-- 增强 -->
                    <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
                </bean>
                --> 
                <bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
                    <property name="advice" ref="greetingAroundAdvice"></property> <!-- 增强 -->
                    <property name="pattern" value="aop.demo.GreetingImpl.good.*"></property> <!-- 切点(正则表达式) -->
                </bean>
                <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
                    <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
                </bean>
    
    总结:
        CGLib代理:创建代理速度慢,创建代理后运行速度快(系统初始化创建代理备用最佳)
        JDK动态代理:创建代理速度快,运行速度慢
        
    |-- spring + AspectJ(Advisor)
    |-- 普通demo
        |-- @Aspect
            @Component
            public class GreetingAspect {
                @Arount("execution(* aop.demo.GreetingImpl.*(..))")
                public Object around(ProceedingJoinPoint pjp) throws Throwable {
                    before();
                    Object result = pjp.proceed();
                    after();
                    return result;
                }
                public void before(){
                    sysout("Before");
                }
                public void after(){
                    sysout("after");
                }
            }
        |-- 配置文件-spring.xml
            <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
            <context:componet-scan base-package="aop.demo"/> 
            <aop:aspect-autoproxy proxy-target-class="true" />    
    |-- 基于注解
        |-- @Target(ElementType.METHOD)
            @Retention(RetentionPolicy.RUNTIME)
            public @Interface Tag {
            }
        |-- @Aspect
            @Component
            public class GreetingAspect {
                @Arount("@Annotation(aop.demo.Tag)")
                public Object around(ProceedingJoinPoint pjp) throws Throwable {
                    ...
                }
                ...
            }
        |-- @Component
            public class GreetingImpl implements Greeting {
                @Tag
                @Override 
                public void sayHello(String name){
                    sysout("Hello!" + name);
                }
                ...
            }
        |-- 实现引入增强
            |-- @Aspect
                @Component
                public class GreetingAspect {
                    
                    @DelareParents(value="aop.demo.GreetingImpl",defaultImpl="ApologyImpl.class")
                    private Apology apology;
                }
            |-- ApologyImpl implements Apology {
                    
                    @Override
                    public void saySorry(String name){
                        sysout("Sorry!" + name);
                    }
                    main(String[] args){
                        ApplicationContext context = new ClassPathXmlApplicationContext("aop/demp/spring.xml");
                        Greeting greeting = context.getBean("greetingImpl");
                        greeting.sayHello("Jack");
                        Apology apology = (Apology) greeting;
                        apology.saySorry("Jack");
                    }
                }
            
    |-- 基于配置
        |-- 配置文件-spring.xml
            <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
            <context:componet-scan base-package="aop.demo"/>
            <beans ...>
                
                <bean id="greetingImpl" class="aop.demo.GreetingImpl" />
                <bean id="greetingAspect" class="aop.demo.GreetingAspect" />
                <aop:config>
                    <aop:aspect ref="greetingAspect">
                        <aop:around method="around" pointcut="execution (* aop.demo.GreetingImpl.*(..))"/>
                    </aop:aspect>
                </aop:config>
            </beans>
    4、开发aop框架
    |-- 定义注解类:
    |-- @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @Interface Aspect {
        Class<? extends Annotion> value();
    }
    |-- 搭建代理框架
    |-- interface Proxy { 代理接口
        // 执行链式代理:可将多个代理通过一条链子串起来,一个个地去执行,执行顺序取决于添加到链上的先后顺序
        Object doProxy(ProxyChain proxyChain) throws Throwable;
    }
    |-- class ProxyChain // 代理链
    |-- Class<?> targetClass;
    |-- Object targetObject;
    }-- Method targetMethod;
    |-- MethodProxy methodProxy;
    }-- Object[] methodParams;
    |-- List<Proxy> proxyList = new ArrayList<>();
    |-- int proxyIndex=0;
    |-- ProxChain(Class<?> targetClass,Object targetObject,Method targetMethod,MethodProxy methodProxy,Object[] methodParams,List<Proxy> proxyList){
            this.targetClass = targetClass;
            ...
        }
    |-- getMethodParams() -> return methodParams;
    |-- getTargetClass() -> return targetClass;
    |-- getTargetMethod() -> return targetMethod;
    |-- Object doProxyChain() throws throwable{
            Object methodResult;
            if (proxyIndex < proxyList.size()){
                methodResult = proxyList.get(proxyIndex++).doProxy();
            } else {
                methodResult = methodProxy.invokeSuper(targetObject, methodParams);
            }
            return methodResult;
        }
    |-- 添加pom.xml依赖
    <!-- cglib 依赖-->
    <grouId>cglib<groupId>...
    |-- class ProxyManger // 代理管理类
    |-- <T> T createProxy(final Class<?> targetClass, final List<Proxy> proxyList){
            return (T) Enhancer.create(targetClass, new MethodInterceptor(){
                @Overrice
                public Object intercept(Object targetObject, Method targetMethod, 
                    Object[] methodParams, MethodProxy methodProxy){
                    return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList);
                }
            });
        }
    |-- public abstract calss AspectProxy implements Proxy { // 切面代理
        @Override
        public final Object doProxy(ProxyChain proxyChain) throws throwable {
            Object result = null;
            Class<?> cls = proxyChain.getTargetClass();
            Method method = proxyChain.getTargetMethod();
            Object[] params = proxyChain.getMethodParams();
            begin();
            try {
                if (intercept(cls, method, params)){
                    before(cls, method, params);
                    result = proxyChain.doProxyChain();
                    after(cls, method, params);
                } else {
                    return proxyChain.doProxyChain();
                }
            } catch(Exception e){
                logger.error("proxy failure", e);
                error(cls, method, params, e);
                throw e;
            } finally {
                end();
            }
        }
        public void begin(){
        }
        public void end(){
        }
        public boolean intercept(Class<?> cls, Method method, Object[] params) throws Throwable {
            return true;
        }
        public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
        }
        public void after(Class<?> cls, Method method, Object[] params) throws Throwable {
        }
        public void error(Class<?> cls, Method method, Object[] params, Throwable e){
        }
    }
    |-- @Aspect(Controller.class)
    ControllerAspect extends AspectProxy{ // 拦截Controller    所有方法
        private long begin;
        @Override
        public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
            begin = System.currentTimeMillis();
        }
        @Override
        public void after(Class<?> cls, Method method, Object[] params) throws Throwable {
            sysout(System.currentTimeMillis()-begin);
        }
    }
    |-- BeanHelper {
        ...
        // 设置bean实例 
        public static void setBean(Class<?> cls, Object obj){
            BEAN_MAP.put(cls, obj);
        }
    }    
    |-- ClassHelper {
        ...
        // 获取某父类(或接口)的所有子类(或实现类)
        public static Set<Class<?>> getClassSetBySuper(Class<?> superClass){
            Set<Class<?>> classSet = new HashSet<Classs<?>();
            for(Class<?> cls : CLASS_SET){
                if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)){
                    classSet.add(cls);
                }
            }
        } 
        // 获取应用包名下带有注解的所有类
        public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotionClass){
            Set<Class<?>> classSet = new HashSet<Classs<?>();
            for(Class<?> cls : CLASS_SET){
                if (superClass.isAnnotationPresent(annotionClass)){
                    classSet.add(cls);
                }
            }
        }
        ...
    }
    |-- AopHelper {
        ...
        private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception {
            Set<Class<?>> targetClassSet = new HashSet<Class<?>>();
            Class<? extends annotation> annotation = aspect.value();
            if (annotation != null && !annotation.equals(Aspect.class)){
                targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));
            }
            return targetClassSet;
        }
        private static Map<Class<?>>,Set<Class<?>>> createProxyMap() throws Exception {
            Map<Class<?>>,Set<Class<?>>> proxyMap = new HashMap<Class<?>>,Set<Class<?>>>();
            Set<Class<?>> proxyClassSet = ClassHelper.getClassSetByAnnotation(AspectProxy.class);
            for(Class<?> proxyClass : proxyClassSet){
                if (proxyClass.isAnnotationPresent(Aspect.class)){
                    Aspect aspect = proxyClass.getAnnotation(Aspect.class);
                    Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
                    proxyMap.put(proxyClass, targetClassSet);
                }
            }
            return proxyMap;
        }    
        private static Map<Class<?>,List<Proxy>> createTargetMap(Map<Class<?>>,Set<Class<?>>> proxyMap) throws Exception {
            Map<Class<?>,List<Proxy>> targetMap = new HashMap<Class<?>,List<Proxy>>();
            for(Map.Entry<Class<?>>,Set<Class<?>>> proxyEntry : proxyMap.entrySet()){
                Class<?> proxyClass = proxyEntry.getKey();
                Set<Class<?> targetClassSet = proxyEntry.getValue();
                for(Class<?> targetClass : targetClassSet){
                    Proxy proxy = (Proxy) targetClass.newInstance();
                    if (targetMap.contains(targetClass)){
                        targetMap.get(targetClass).add(proxy);
                    } else {
                        List<Proxy> proxyList = new ArrayList<Proxy>();
                        proxyList.add(proxy);
                        targetMap.put(targetClass, proxyList);
                    }
                }
            }
        }
        
        static {
            try {
                Map<Class<?>>,Set<Class<?>>> proxyMap = createProxyMap();
                Map<Class<?>,List<Proxy>> targetMap = createTargetMap(proxyMap);
                for(Map.Entry<Class<?>,List<Proxy>> targetEntry : targetMap.etrySet()){
                    Class<?> targetClass =targetEntry.getKey();
                    List<Proxy> proxyList = targetEntry.getValue();
                    Object proxy = ProxyManager.createProxy(targetClass, proxyList);
                    BeanHelper.setBean(targetClass, proxy);
                }
            } catch(Exception e){
                Logger.error("aop failure", e);
            }
        }
    }
    |-- HelperLoader {
        public static void init(){
        
            Class<?>[] classList = {
                ClassHelper.class, 
                BeanHelper.class,
                AopHelper.class,
                IocHelper.class,
                ControllerHelper.class
            };
            for(Class<?> cls : classList){
                ClassUtil.loadClass(cls.getName(), true);
            }
        }
    }
    
    5、事务管理        
    事务的ACID:
    Atomlcity --原子性
    Consitency -- 一致性
    Isolation -- 隔离性
    Duration -- 持久性
    |-- 实现事务控制
    |-- @METHOD -> @Interface Transaction{} // 定义事务注解
    |-- @Service 
    |-- CustomerService
    |-- @Transaction
    |-- boolean createCustomer(Map<String, Object> fieldMap);
    |-- ...
    |-- DatabaseHelper {
        ThreadLocal CONNECTION_HOLDER = new ThreadLocal<Connection>();
        // 开启事务
        public static void beginTransaction(){
            Connection conn = getConnection();
            if (conn != null){
                try {
                    conn.setAutoCommit(false);
                } catch(SQLException e){
                    logger.error("begin transaction failure",e);
                    throw new RunTimeException(e);
                } finally {
                    CONNECTION_HOLDER.set(conn);
                }
            }
        }
        // 提交事务
        public static void commitTransaction{
            Connection conn = getConnection();
            if (conn != null){
                try {
                    conn.commit();
                    conn.close();
                } catch(SQLException e){
                    logger.error("begin transaction failure",e);
                    throw new RunTimeException(e);
                } finally {
                    CONNECTION_HOLDER.remove();
                }
            }
        }
        // 回滚事务
        public static void rollbackTransaction(){
            Connection conn = getConnection();
            if (conn != null){
                try {
                    conn.rollback();
                    conn.close();
                } catch(SQLException e){
                    logger.error("begin transaction failure",e);
                    throw new RunTimeException(e);
                } finally {
                    CONNECTION_HOLDER.remove();
                }
            }
        }
    }
    |-- 事务代理切面类
    |-- public class TransactionProxy implements Proxy{
        private static finall ThreadLocal<Boolean> FLAG_HOLDER = new ThreadLocal<Boolean>(){
            @Override
            protected Boolean initialValue(){
                return false;
            }
        };
        @Override
        public Object Proxy(ProxyChain proxyChain) throws Throwable {
            Object result;
            boolean flag = FLAG_HOLDER.get();
            Method method = proxyChain.getTargetMethod();
            if (!flag && method.isAnnotationPresent(Transaction.class)){
                FLAG_HOLDER.set(true);
                try {
                    DatabaseHelper.beginTransaction();
                    logger.debug("begin transaction");
                    result = proxyChain.doProxyChain();
                    DatabaseHelper.commitTransaction();
                    logger.debug("commit transaction");
                } catch(Exception e){
                    DatabaseHelper.rollbackTransaction();
                    logger.debug("rollback transaction");
                    throw e;
                } finally {
                    FLAG_HOLDER.remover();
                }
            }
        }
    }
    |-- 在构架中添加代理机制
    |-- AopHelper {
        private static Map<Class<?>, Set<Class<?>>> createProxyMap() throws Exception {
            Map<Class<?>, Set<Class<?>, Set<Class<?>>> proxyMap = new HashMap<Class<?>, Set<Class<?>, Set<Class<?>>>;
            addAspectProxy(proxyMap);
            addTransaction(proxyMap);
            return proxyMap;
        }
        private static void addAspectProx(Map<Class<?>, Set<Class<?>, Set<Class<?>>> proxyMap) throws Exception {
            Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
            for (Class<?> proxyClass : proxyClassSet){
                if (proxyClass.isAnnotationPresent(Aspect.class)){
                    Aspect aspect = proxyClass.getAnnotation(Aspect.class);
                    Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
                    proxyMap.put(proxyClass, targetClassSet);
                }
            }
        }
        private static void addTransaction(Map<Class<?>, Set<Class<?>, Set<Class<?>>> proxyMap) throws Exception {
            Set<Class<?>> serviceClassSet = ClassHelper.getClassSetByAnnotation(Service.class);
            proxyMap.put(TransactionProxy.class, serviceClassSet);
        }
    }
    
    6、框架优化与功能扩展
    |-- 1、省略Action param
    |-- @WebServlet(urlPatterns = "/*", loadOnStarup = 0)
    DispatcherServlet {
        ...
        public void services(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ...
            Param param = new Param(paramMap);
            Method actionMethod = handler.getActionMethod();
            Object result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
            ->
            Object result;
            if (param.isEmpty(){
                result = ReflectionUtil.invokeMethod(controllerBean, actionMethod);
            } else {
                result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
            }
            ...
        }
    }
    |-- Param {
        ...
        publie boolean isEmpty(){
            return CollectionUtils.isEmpty(paramMap);
        }
    }
    |-- 2、提供文件上传属性
    |-- CustomerControler
    |-- Data createSubmit(Param param) {
            Map<String,Object> fieldMap = param.getFieldMap();
            FileParam fileParam = param.getFile("photo");
            boolean result = customerService.createCustomer(fieldMap, fileParam);
            return new Data(result);
        }
    |-- CustomerService 
    |-- createCustomer(Map<String, Object> fieldMap, FileParam fileParam){
            boolean result = DatabaseHelper.insertEntity(Customer.class, fieldMap);
            if (result){
                UploadHelper.uploadFile("/tmp/upload/", fileParam);
            }
            return result;
        }
    |-- FileParam {
        String fieldName; // 表单字段名称 
        String fileName; // 文件名称 
        long fileSize; // 文件大小
        String contentType; // 文件类型
        InputStream inputStream; // 上传文件字节输入流
        FileParam(String fieldName,...){
            this.fieldName = fieldName;
            ...
        }
        // settter、getter方法
    }
    |-- FormParam {
        String fieldName;
        Object fieldValue;
        FormParam(String fieldName,...){
            this.fieldName = fieldName; 
            ...
        }
        // setter、getter 方法
    }
    |-- Param {
        List<FileParam> fileParamList;
        List<FormParam> formParamList;
        Param(List<FormParam> formParamList){
            this.formParamList = formParamList;
        }
        Param(List<FormParam> formParamList, List<FileParam> fileParamList){
            this.formParamList = formParamList;
            this.fileParamList = fileParamList;
        }
        public Map<String,Object> getFieldMap(){
            Map<String, Object> fieldMap = new HashMap<String, Object>();
            if (CollectionUtils.isNotEmpty(formParamList)){
                for(FormParam formParam : formParamList){
                    String fieldName = formParam.getFiledName();
                    Object fieldValue = formParam.getFieldValue();
                    if (fieldMap.contains(fieldName)){
                        fieldValue = fieldMap.get(fieldName) + StringUtil.SEPARATOR + fieldValue;
                    }
                    fieldMap.put(fieldName, fieldValue);
                }
            }
            return fieldMap;
        }
        public Map<String, List<FileParam>> getFileMap(){
            Map<String, List<FileParam>> fileMap = new HashMap<String, List<FileParam>>();
            if (CollectionUtils.isNotEmpty(fileParamList)){
                for(FileParam fileParam : fileParamList){
                    String fieldName = formParam.getFiledName();
                    List<FileParam> fileParamList;
                    if (fileMap.contains(fieldName)){
                        fileParamList = fileMap.get(fieldName);
                    } else {
                        fileParamList = new ArrayList<FileParam>();
                    }
                    fileParamList.add(fileParam);
                    fileMap.put(fieldName, fileParamList);
                }
            }
            return fileMap;
        }
        // 获取所有上传文件
        public List<FileParam> getFileList(String fieldName){
            return getFileMap().get(fieldName);
        }
        // 获取唯一上传文件
        public FileParam getFile(String fieldName) {
            List<FileParam> fileParamList = getFileList(fieldName);
            if (CollectionUtils.isNotEmpty(fileParamList) && fileParamList.size() == 1){
                return fileParamList.get(0);
            }
            return null;
        }
        // 验证参数是否为空
        public boolean isEmpty() {
            return CollectionUtils.isEmpty(formParamList) && CollectionUtils.isEmpty(fileParamList);
        }
        // 根据参数名获取double类型值
        public double getDouble(String name){
            return CastUtil.caseDouble(getFieldMap().get(name));
        }
        ...
    }
    |-- 文件上传助手类
    |-- UploadHelper {
        ServletFileUpload servletFileUpload; // Apache Commons FileUpload 提供的Servlet文件上传对象
        public static void init(ServletContext servletcContext){
            File respository = (File) servletcContext.getAttribute("javax.servlet.context.tmpdir");
            servletFileUpload = new ServletFileUpload(new DiskFileItemFactory
                (DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, respository));
            int uploadLimit = ConfigHelper.getAppUploadLimit(0;
            if (uploadLimit != 0){
                servletFileUpload.setFileSizeMax(uploadLimit * 1024 * 1024);
            }
        }
        // 判断是否为multipart类型
        public static boolean isMultipart(HttpServletRequest request){
            return servletFileUpload.isMultipartContent(request);
        }
        // 创建请求对象
        public static Param createParam(HttpServletRequest request){
            List<FileParam> fileParamList = new ArrayList<>();
            List<FormParam> formParamList = new ArrayList<>();
            try {
                Map<String, List<FileItem>> fileItemListMap = servletFileUpload.parseParameterMap(request);
                if (CollectionUtils.isNotEmpty(fileItemListMap)){
                    for (Map.Entry<String, List<FileItem>> fileItemListEntry : fileItemListMap.entrySet()){
                        String fieldName = fileItemListEntry.getKey();
                        List<FileItem> fileItemList = fileItemListEntry.getValue();
                        if (CollectionUtils.isNotEmpty(fileItemList)){
                            for (FileItem fileItem : fileItemList){
                                if (fileItem.isFormField()){
                                    String fieldValue = fileItem.getString("UTF-8");
                                    formParamList.add(new FormParam(fieldName, fieldValue));
                                } else {
                                    String fileName = FileUtil.getRealFileName(new String(fileItem.getName().getBytes(), "UTF-8"));
                                    if (StringUtil.isNotEmpty(fileName)){
                                        long fileSize = fileItem.getSize();
                                        String contentType = fileItem.getContentType();
                                        InputStrem inputStrem  = fileItem.getInputStream();
                                        fileParamList.add(new FileParam(fieldName, fileName, fileSize, contentType, inputStrem));
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (Exception e){
                logger.error("create param failure", e);
                throw new RuntimeException();
            }
            return new Param(formParamList, fileParamList);
        }
        // 上传文件
        public static void uploadFile(String basePath, FileParam fileParam){
            try {
                if (fileParam != null){
                    String filePath = basePath + fileParam.getFileName();
                    FileUtil.createFile(filePath);
                    InputStream inputStream = new BufferedInputStream(fileParam.getInputStream());
                    OutputStrem outputStrem = new BufferedOutputStream(new FileOutputStrem(filePath));
                    StreamUtil.copyStream(inputStream, outputStrem);
                }
            } catch(Exception e){
                logger.error("upload file failure", e);
                throw new RuntimeException();
            }
        }
        // 批量上传
        uploadFile(String bathPath, List<FileParam> fileParamList) -> foreach:uploadFile(bathPath, fileParamList)
    }
    |-- FileUtil
    |-- String getRealFileName(String fileName); -> FilenameUtils.getName(fileName);
    |-- File createFile(String filePath) {
            file = new File(filePath);
            File parentDir = file.getParentFile();
            if (!parentDir.exists()){
                FileUtils.forceMkdir(parentDir);
            }
            return file;
        }
    |-- RequestHelper // 请求助手类
    |-- Param createParam(HttpServletRequest request) // 创建请求对象
        |-- new Param()
            .addAll(parseParameterNames(request))
            .addAll(parseInputStrem(request));
    |-- List<FormParam> parseParameterNames(HttpServletRequest request) return List<FormParam>;
    |-- List<FormParam> parseInputStrem(HttpServletRequest request) return List<FormParam>;
    |-- DispactcherServlet {
        @Override
        void init(servletConfig){
            ...
            ServletContext servletContext = servletConfig.getServletContext();
            UploadHelper.init(servletContext);
        }
        @Override
        public void service(request,response){
            String requestMethod = request.getMethod().toLowerCase();
            String requestPath = request.getPathInfo();
            // 过滤ico
            // 业务处理
            Handler handler = ControllerHelper.getHanlder(requestMethod, requestPath);
            Class<?> controllerClass = handler.getControllerClass();
            Object controllerBean = BeanHelper.getBean(controllerClass);
            Param param;
            if (UploadHelper.isMultipart(request)){
                param = UploadHelper.createParam(request);
            } else {
                param = RequestHelper.createParam(request);
            }
            // 
            Object result;
            Method actionMethod = handler.getActionMethod();
            if (param.isEmpty()){
                result = ReflectionUtil.invokeMethod(controllerBean, actionMethod);
            } else {
                result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
            }
            if (result instanceof View){
                handleViewResult((View) result, request, response);
            } else if (result instanceof Data){
                handleDataResult((Data) result, response);
            }
        }
        void handleViewResult(view, request, response){
            String path = view.getPath();
            if (path.startsWith("/")){
                response.sendRedirect(request.getContextPath() + path);
            } else {
                Map<String, Object> model = view.getModel();
                for(Map.Entry<String, Object> entry : model.entrySet()){
                    model.put(entry.getKey(), entry.getValue());
                }
                request.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(request, response);
            }
        }
        void handleDataResult(data, response){
            Object model = data.getModel();
            if (model != null){
                response.setContentType("application/json");
                response.setCharacterEncoding("UTF-8");
                PrintWriter writer = response.getWriter();
                String json = JsonUtil.toJson(model);
                writer.writer(json);
                writer.flush();
                writer.close();
            }
        }
    }
    |-- ServletHelper {
        static final ThreadLocal<ServletHelper> SERVLET_HELPER_HOLDER = new ThreadLocal<ServletHelper>();
        HttpServletRequest request;
        HttpServletResponse response;
        ServletHelper(request, response){
            this.request = request;
            ...
        }
        public static init(request, response){
            SERVLET_HELPER_HOLDER.set(new ServletHelper(request, response));
        }
        public static destroy(){
            SERVLET_HELPER_HOLDER.remove();
        }
        HttpServletRequest getRequest(){
            return SERVLET_HELPER_HOLDER.get().request;
        }
        HttpServletResponse getResponse(){
            return SERVLET_HELPER_HOLDER.get().response;
        }
        HttpSession getSession(){
            return getRequest().getSession();
        }
        ServletContext getServletContext(){
            return getRequest().getServletContext();
        }
        void setRequestAttribute(key, value){
            getRequest().setAttribute(key, value);
        }
        <T> T getRequestAttribute(key){
            (T) getRequest().getAttribute(key);
        }
        void remoteRequestAttribute(key){
            getRequest().removeAttribute(key);
        }
        // 重定向
        void sendRedirect(String location){
            try {
                getResponse().sendRedirect(getRequest().getContextPath() + location);
            } catch(e){
                ...
            }
        }
        // 使session失效
        void invalidateSession(){
            getRequest().getSession().invalidate();
        }
    }
    |-- DispactcherServlet {
        @Override
        public void service(request,response){
            ServletHelper.init(request, response);
            try {
                ...
            } finally {
                ServletHelper.destroy();
            }
        }
    }
    待续。。。
  • 相关阅读:
    MkDocs: 构建你自己的知识库
    Vue入门
    Vue UI库
    【入门】PyTorch
    【转载】工业相机的原理与选型
    如果你是狮子,就得学会逼狼去吃草
    【转载】剖析Git的实现机制
    管理学-员工管理
    量化投资
    【汇总】图像格式
  • 原文地址:https://www.cnblogs.com/ice-line/p/9590896.html
Copyright © 2011-2022 走看看