用伪代码梳理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();
        }
    }
}
待续。。。

 

posted @ 2018-09-05 11:02  一棵小草77  阅读(583)  评论(0编辑  收藏  举报