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