一、概述
  本章讲解了一个mvc框架的核心部分,大致分为9个部分
  1.开发环境:pom.xml文件
  2.配置文件:smart.properties(不属于框架,在实际的web应用中定义)
  3.加载配置项:  (interface) ConfigConstant
                            (final class) ConfigHelper
  4.类加载器: (final class) ClassUtil
                       (@Interface) ControllerServiceActionInject
                       (final class) ClassHelper
  5.Bean容器:(final class) ReflectionUtil
                        (final class) BeanHelper
  6.依赖注入:    (final class) IocHelper
  7.加载Controller:(class) Request、Handler
            (final class) ControllerHelper
  8.初始化框架:(final class) HelperLoader
  9.请求转发器:(class) Request、Handler、Param
                          (class) DispatcherServlet extend HttpServlet
                          (final class) StreamUtil、CodeUtil、JsonUtil
 
二、框架核心的具体实现
  2.1  想要框架达成的使用效果:

 1 package cn.m4.chapter3.controller;
 2
 3
 4
 5 import cn.ease4j.annotation.Action;
 6 import cn.ease4j.annotation.Controller;
 7 import cn.ease4j.annotation.Inject;
 8 import cn.ease4j.bean.Data;
 9 import cn.ease4j.bean.Param;
10 import cn.ease4j.bean.View;
11 import cn.m4.chapter3.entity.Customer;
12 import cn.m4.chapter3.service.MyService;
13
14 import java.util.List;
15
16 @Controller
17 public class MyController {
18
19     @Inject
20     private MyService myService;
21
22     @Action("get:/customer_create")
23     public Data getCustomerList(Param param){
24         List<Customer> customerList = myService.getCustomerById();
25         return new Data(customerList);
26     }
27 }

View Code

  2.2  框架核心的具体搭建

2.2.1  第一步、添加一个Java web框架的基本依赖。
具体步骤是:在IDEA中新建一个Maven工程,在pom文件中添加如下10个基本依赖:Servlet、JSP、JSTL、JUNIT、SLF4J、MySQL、JSON、Apache CommonsLand、Apache Commons Collections、Apache Commons DBUtils、dbcp

<dependencies><!--01 Servlet依赖--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--02 JSP依赖--><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope></dependency><!--03 JSTL依赖--><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version><scope>runtime</scope></dependency><!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><!--04 SLF4J--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.7</version></dependency><!--05 mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.35</version><scope>runtime</scope></dependency><!--06 Json--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.4.4</version></dependency><!--添加两个Apache Commons依赖,用于提供常用工具类--><!--07 Apach Commons Lang--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.3.2</version></dependency><!--08 Apache Commons Collections--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.0</version></dependency><!--09 Apache Commons DBUtils--><dependency><groupId>commons-dbutils</groupId><artifactId>commons-dbutils</artifactId><version>1.6</version></dependency><!--10 数据库连接池--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-dbcp2</artifactId><version>2.0.1</version></dependency><!-- cglib --><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.2.2</version></dependency>

View Code

    2.2.2  第二步、提供获取并处理框架配置的工具类:ConfigConstant、ConfigHelper。

ConfigConstant是一个存放.properties配置文件中常量名称的接口;
ConfigHelper则是调用第二章中的PropUtil工具类去读取配置。

package cn.ease4j.constant;/*** 存放配置常量名称* @author Zephyr*/
public interface ConfigConstant {//配置文件名常量String CONFIG_FILE = "ease.properties";//数据库连接常量String JDBC_DRIVER = "ease.framework.jdbc.driver";String JDBC_URL = "ease.framework.jdbc.url";String JDBC_USERNAME = "ease.framework.jdbc.username";String JDBC_PASSWORD = "ease.framework.jdbc.password";//各文件资源路径String APP_BASE_PACKAGE = "ease.framework.app.base_package";String APP_JSP_PATH = "ease.framework.app.jsp_path";String APP_ASSET_PATH = "ease.framework.app.asset_path";
}

View Code

/*** 提取配置的助手类* @author Zephyr*/
public final class ConfigHelper {private static final Properties CONFIG_PROPS =PropUtil.loadProps(ConfigConstant.CONFIG_FILE);/*** 获取jdbc驱动* @return*/public static String getJdbcDriver(){return PropUtil.getString(CONFIG_PROPS,ConfigConstant.JDBC_DRIVER);}/*** 获取jdbc URL* @return*/public static String getJdbcUrl(){return PropUtil.getString(CONFIG_PROPS,ConfigConstant.JDBC_URL);}/*** 获取jdbc用户名* @return*/public static String getJdbcUsername(){return PropUtil.getString(CONFIG_PROPS,ConfigConstant.JDBC_USERNAME);}/*** 获取jdbc密码* @return*/public static String getJdbcPassword(){return PropUtil.getString(CONFIG_PROPS,ConfigConstant.JDBC_PASSWORD);}/*** 获取应用的基本包路径* @return*/public static String getAppBasePackage(){return PropUtil.getString(CONFIG_PROPS,ConfigConstant.APP_BASE_PACKAGE);}/*** 获取应用jsp路径(含默认值)* @return*/public static String getAppJspPath(){return PropUtil.getString(CONFIG_PROPS,ConfigConstant.APP_JSP_PATH,"/WEB-INF/view/");}/*** 获取静态资源的路径(含默认值)* @return*/public static String getAppAssetPath(){return PropUtil.getString(CONFIG_PROPS,ConfigConstant.APP_ASSET_PATH,"/asset/");}}

View Code

/*** 属性文件工具类* @author Zephyr*/
public class PropUtil {//获取日志对象public static final Logger LOGGER= LoggerFactory.getLogger(PropUtil.class);/*** 加载配置文件* @param fileName* @return*/public static Properties loadProps(String fileName){Properties props=null;InputStream is=null;try {is=Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);if(null==is){throw new FileNotFoundException(fileName+" is not found");}props=new Properties();props.load(is);}catch (IOException e){LOGGER.error("load properties file failure",e);}finally {if(is!=null){try {is.close();} catch (IOException e) {LOGGER.error("close inputstream failure",e);}}}return props;}/*** 获取字符型属性,指定默认值* @param prop* @param key* @param defaultValue* @return*/public static String getString(Properties prop, String key,String defaultValue){String value=defaultValue;if(prop.containsKey(key)){value=prop.getProperty(key);}return value;}/*** 获取字符型属性,默认值为空* @param prop* @param key* @return*/public static String getString(Properties prop, String key){return getString(prop,key,"");}/*** 获取整型属性,指定默认值* @param prop* @param key* @param defaultValue* @return*/public static Integer getInt(Properties prop,String key,Integer defaultValue){Integer value = defaultValue;if(prop.containsKey(key)){value=CastUtil.castInt(prop.getProperty(key));}return value;}/*** 获取整型属性,默认值0* @param prop* @param key* @return*/public static Integer getInt(Properties prop,String key){return getInt(prop,key,0);}/*** 获取布尔型属性,指定默认值* @param prop* @param key* @param defaultValue* @return*/public static Boolean getBoolean(Properties prop,String key,Boolean defaultValue){Boolean value=defaultValue;if(prop.containsKey(key)){value=CastUtil.castBoolean(prop.getProperty(key));}return value;}/*** 获取布尔型属性,默认值false* @param prop* @param key* @return*/public static Boolean getBoolean(Properties prop,String key){return getBoolean(prop,key,false);}}

View Code

    2.2.3  第三步、提供让框架具备类加载功能的工具类以及相关注解:ClassUtil、ClassHelper、@Controller、@Service、@Action、@Inject

    1、ClassUtil中包含三个方法:getClassLoader、loadClass、getClassSet

      getClassLoader是获取当前的类加载器,其实就一行代码:Thread.currentThread().getContextClassLoader();

      loadClass用于加载类,核心代码也只有一行,用的是Class.forName,但用的是另一种不常见的形式,public static Class<?> forName(String name,boolean initialize,ClassLoader loader);三个参数的含义分别是class名、是否初始化类(后面的使用中填false)、类加载器(直接用方法类中的getClassLoader());  

      getClassSet方法体比较长。输入参数是String packageName(类似于xx.xx.xx的形式),返回参数是Set<Class<?>>,实现的功能就是根据包名,递归获取本包以及子包中的class文件的名称以及jar包中的class文件的名称,使用工具类中的loadClass方法加载并放入Set集合并返回。并且用到了2个私有方法:addClass、doAddClass。addClass用于递归获取当前包或子包中的class文件,并调用doAddClass方法;而doAddClass方法则用于加载类(调用loadClass方法)并将生成的类放入Set。

/*** 类操作的工具类* @author Zephyr Lai*/
public class ClassUtil {private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);/*** 获取类加载器* @return*/public static ClassLoader getClassLoader(){return Thread.currentThread().getContextClassLoader();}/*** 加载类(返回class对象)* @param className* @param ifInitialize 通常赋值为false* @return*/public static Class<?> loadClass(String className,boolean ifInitialize){Class<?> clz = null;try {clz = Class.forName(className,ifInitialize,getClassLoader());} catch (ClassNotFoundException e) {LOGGER.error("load class failure",e);throw new RuntimeException(e);}return clz;}/*** 获取指定包下的所有类* @param packageName* @return*/public static Set<Class<?>> getClassSet(String packageName){//用于存储类名的集合Set<Class<?>> classSet = new HashSet<Class<?>>();try {String path=packageName.replace(".", "/");ClassLoader classLoader = getClassLoader();Enumeration<URL> urls = getClassLoader().getResources(path);if(!urls.hasMoreElements()){System.out.println("no element !");}while(urls.hasMoreElements()){URL url = urls.nextElement();//非空校验if(null != url){String protocol = url.getProtocol();if(protocol.equals("file")){String packagePath = url.getPath().replace("%20", " ");addClass(classSet,packagePath,packageName);}else if(protocol.equals("jar")){JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection();if(null !=jarURLConnection){JarFile jarFile = jarURLConnection.getJarFile();if(null != jarFile){Enumeration<JarEntry> jarEntries = jarFile.entries();while(jarEntries.hasMoreElements()){JarEntry jarEntry = jarEntries.nextElement();String name = jarEntry.getName();if(name.endsWith(".class")){//去掉.class后缀并且将所有的"/"替换为"."String className = name.substring(0,name.lastIndexOf(".")).replaceAll("/",".");doAddClass(classSet,className);}}}}}}}} catch (IOException e) {e.printStackTrace();LOGGER.error("get class set failure",e);}return classSet;}/*** 递归获取包以及子包下的所有class文件,获取class名并加载* @param classSet* @param packagePath* @param packageName*/private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) {File[] files = new File(packagePath).listFiles(new FileFilter() {public boolean accept(File file) {return (file.isFile() && file.getName().endsWith(".class") || file.isDirectory());}});for (File file : files) {String fileName = file.getName();if(file.isFile()){String className = fileName.substring(0, fileName.lastIndexOf("."));if(StringUtil.isNotEmpty(packageName)){className=packageName+"."+className;}doAddClass(classSet,className);}else{//子目录String subPackagePath = fileName;if(StringUtil.isNotEmpty(packagePath)){subPackagePath = packagePath + "/" + subPackagePath;}//子包String subPackageName = fileName;if(StringUtil.isNotEmpty(packageName)){subPackageName=packageName+"."+subPackageName;}//递归,在子目录、子包中查找class文件
                addClass(classSet,subPackagePath,subPackageName);}}}/*** 仅生成class对象,不初始化实例* @param classSet* @param className*/private static void doAddClass(Set<Class<?>> classSet, String className) {System.out.println(Arrays.toString(classSet.toArray()));Class<?> clz = loadClass(className, false);classSet.add(clz);}}

View Code

    2、4个框架中需要提供的注解:@Controller、@Service、@Action、@Inject,目录结构如图

    

/*** 控制器注解* @author Zephyr Lai*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {}

View Code

/*** 服务类注解* @author Zephyr Lai*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
}

View Code

/*** 依赖注入注解* @author Zephyr Lai*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
}

View Code

/*** Action方法注解* 类似于Spring中的@RequestMapping* @author Zephyr Lai*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Action {/*** 请求类型与路径* 类似于Spring中的@RequestMapping(value=" ")* @return*/String value();
}

View Code

    3、ClassHelper包括1个静态代码块以及3个公有的静态方法。

      静态代码块用于获取应用中所有的class(Set<Class<?>>形式)

      getClassSet:直接返回静态代码块中的Set

      getServiceClassSet:提取代码块中被@Service注解的class,放入新的Set并返回

      getControllerClassSet:提取代码块中被@Controller注解的class,放入新的Set并返回

      getBeanClassSet:提取代码块中被@Controller或者@Service注解的class,放入新的Set并返回(官话:获取被框架管理的Class(即:获取Bean类))

    2.2.4  第四步、提供Bean容器的相关工具类(核心功能是:实例化对象):ReflectionUtil、BeanHelper

    1、ReflectionUtil包含三个方法:方别用于类、方法、域。

      newInstance:核心代码就一行 class.newInstance();

      invokeMethod:核心代码两行 method.setAccessible(true);//设置为方法可以被反射机制调用

                  methos.invoke(obj,args);//反射执行方法

      setField:跟工具类中的invokeMethod方法很类似,核心代码两行 field.setAccessible(true); //设置为域可以被反射机制调用

                                   field.set(obj,value); //向obj这个对象中的field设置新的value

    2、BeanHelper包含1个private static final 的 Map<Class<?>,Object>、1个静态代码块、2个公有的静态方法。

      静态代码块的作用是调用ClassHelper中的getBeanClassSet();获取又框架管理的bean类,然后遍历调用ReflectionUtil中的newInstance方法初始化实例并放入map

      getBeanMap:获取完整的map

      getBean:根据键在map中获取对应的bean实例

package cn.ease4j.util;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*** 反射工具类* @author Zephyr Lai*/
public class ReflectionUtil {private static final Logger LOGGER = LoggerFactory.getLogger(ReflectionUtil.class);/*** 创建实例* @param clz* @return*/public static <T> T getInstance(Class<T> clz){T instance= null;try {instance= clz.newInstance();} catch (Exception e) {LOGGER.error("get instance error",e);throw new RuntimeException(e);}return instance;}/*** 调用方法* @param obj* @param method* @param params* @return*/public static Object invokeMethod(Object obj, Method method,Object... params){Object result ;try {//方法设置为可以被反射机制调用method.setAccessible(true);result=method.invoke(obj,params);} catch (Exception e) {LOGGER.error("method invoke failure",e);throw new RuntimeException(e);}return result;}/*** 设置成员变量的值* (将在IOCHelper中使用)* @param obj* @param field* @param value*/public static void setField(Object obj, Field field,Object value){//todotry {//方法设置为可以被反射机制调用field.setAccessible(true);//为obj这个对象中的field的值设置为value
            field.set(obj,value);} catch (Exception e) {LOGGER.error("set field failure",e);throw new RuntimeException(e);}}}

ReflectionUtil

 1 package cn.ease4j.helper;
 2
 3 import cn.ease4j.util.ClassUtil;
 4 import cn.ease4j.util.ReflectionUtil;
 5 import com.fasterxml.jackson.databind.util.BeanUtil;
 6 import com.sun.corba.se.impl.ior.OldJIDLObjectKeyTemplate;
 7 import org.slf4j.Logger;
 8 import org.slf4j.LoggerFactory;
 9
10 import java.util.HashMap;
11 import java.util.Map;
12 import java.util.Set;
13
14 /**
15  * 定义Bean映射,用于存放Bean类与Bean实例的映射关系
16  * @author Zephyr Lai
17  */
18 public class BeanHelper {
19     public static final Logger LOGGER = LoggerFactory.getLogger(BeanHelper.class);
20     /**
21      * 用于存放class--bean的键值对
22      */
23     public static final Map<Class<?>,Object> BEAN_MAP= new HashMap<Class<?>,Object>();
24
25     /**
26      * 静态代码块用于初始化BEAN_MAP
27      * clz1 -- obj1
28      * clz2 -- obj2
29      */
30     static{
31         //获取由框架管理的bean
32         Set<Class<?>> beanSet = ClassHelper.getBeanClassSet();
33         for (Class<?> beanClass : beanSet) {
34             Object obj = ReflectionUtil.getInstance(beanClass);
35             BEAN_MAP.put(beanClass,obj);
36         }
37     }
38
39     /**
40      * 获取整个Bean映射
41      * @return
42      */
43     public static Map<Class<?>,Object> getBeanMap(){
44         return BEAN_MAP;
45     }
46
47     /**
48      * 根据class名称从映射中获取Bean实例
49      * @param clz
50      * @param <T>
51      * @return
52      */
53     public static <T> T getBean(Class<T> clz){
54         if(!BEAN_MAP.containsKey(clz)){
55             throw new RuntimeException("cannot get bean by class:"+clz.getName());
56         }
57         for (Map.Entry<Class<?>, Object> entry : BEAN_MAP.entrySet()) {
58             Class<?> key = entry.getKey();
59             Object value = entry.getValue();
60             System.out.println(1);
61         }
62         return (T) BEAN_MAP.get(clz);
63     }
64 }

BeanHelper

  2.2.5  第五步、实现框架的依赖注入(DI)功能(人话:实例化Bean中带@Inject注解的域,并设置到Bean实例中),相关工具类:IocHelper

    1、IocHelper的实现逻辑:通过BeanHelper获取所有的bean Map(存放的是class<-->obj),通过反射获取bean实例中所有的成员变量,然后遍历这些成员变量,查看是否带有@Inject注解,如果带有@Inject注解,则将成员变量实例化,并设置到Bean Map的Bean实例中

package cn.ease4j.helper;import cn.ease4j.annotation.Inject;
import cn.ease4j.util.ArrayUtil;
import cn.ease4j.util.CollectionUtil;
import cn.ease4j.util.ReflectionUtil;import java.lang.reflect.Field;
import java.util.Map;/*** 依赖注入助手类* @author Zephyr Lai*/
public final class IocHelper {static {//获取整个Bean映射Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();if(CollectionUtil.isNotEmpty(beanMap)){//Map遍历for (Map.Entry<Class<?>, Object> beanEntity : beanMap.entrySet()) {Class<?> beanClass = beanEntity.getKey();Object beanInstance = beanEntity.getValue();//获取class对象的所有域(属性)Field[] declaredFields = beanClass.getDeclaredFields();if(ArrayUtil.isNotEmpty(declaredFields)){for (Field field : declaredFields) {//匹配@Inject注解if(field.isAnnotationPresent(Inject.class)){//获取域的class对象Class<?> type = field.getType();//生成域的实例Object fieldInstance = ReflectionUtil.getInstance(type);if(null != fieldInstance){//将域实例设置进bean实例
                                ReflectionUtil.setField(beanInstance,field,fieldInstance);}}}}}}}
}

IocHelper

package cn.ease4j.util;import org.apache.commons.lang3.ArrayUtils;/*** 数组工具类* @author Zephyr Lai*/
public class ArrayUtil {public static Boolean isNotEmpty(Object[] array){return ArrayUtils.isNotEmpty(array);}public static Boolean isEmpty(Object[] array){return ArrayUtils.isEmpty(array);}
}

ArrayUtil

  2.2.6  第六步、提供用于加载Controller的工具y以及相关类:Request、Handler、ControllerHelper

    1、Request是请求类,封装了请求方法(String)、请求路径(String)

    2、Handler是处理类,用于封装Action信息,包括controllerClass(Class<?>)、actionMethod(Method)

      一张图理清Request与Handler的关系:

  

    3、ControllerHelper包含一个private static final Map<Request,Hander>、1个静态代码块、1个公有的静态方法getHander

     map中存放请求与处理器之间的映射关系

     静态代码块则负责从现有的Controller Bean中封装Request与Handler的映射关系,封装到Map中并返回

        getHandler 则根据请求方法和请求路径从map中提取对应的处理器(Handler)

 1 package cn.ease4j.helper;
 2
 3 import cn.ease4j.annotation.Action;
 4 import cn.ease4j.annotation.Inject;
 5 import cn.ease4j.bean.Handler;
 6 import cn.ease4j.bean.Request;
 7 import cn.ease4j.util.ArrayUtil;
 8 import cn.ease4j.util.CollectionUtil;
 9 import cn.ease4j.util.ReflectionUtil;
10
11 import java.lang.reflect.Field;
12 import java.lang.reflect.Method;
13 import java.util.HashMap;
14 import java.util.Map;
15 import java.util.Set;
16
17 /**
18  * 控制器助手类
19  * @author Zephyr Lai
20  */
21 public final class ControllerHelper {
22     //请求--处理器 映射
23     public static final Map<Request,Handler> ACTION_MAP = new HashMap<Request, Handler>();
24
25     static{
26         //获取整个Bean映射
27         Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
28         if(CollectionUtil.isNotEmpty(beanMap)){
29             //Map遍历
30             for (Map.Entry<Class<?>, Object> beanEntity : beanMap.entrySet()) {
31                 Class<?> beanClass = beanEntity.getKey();
32                 Object beanInstance = beanEntity.getValue();
33                 //获取class对象的所有域(属性)
34                 Field[] declaredFields = beanClass.getDeclaredFields();
35                 if(ArrayUtil.isNotEmpty(declaredFields)){
36                     for (Field field : declaredFields) {
37                         //匹配@Inject注解
38                         if(field.isAnnotationPresent(Inject.class)){
39                             //获取域的class对象
40                             Class<?> type = field.getType();
41                             //生成域的实例
42                             Object fieldInstance = ReflectionUtil.getInstance(type);
43                             if(null != fieldInstance){
44                                 //将域实例设置进bean实例
45                                 ReflectionUtil.setField(beanInstance,field,fieldInstance);
46                             }
47                         }
48                     }
49                 }
50             }
51         }
52
53
54         //获取所有的Controller Bean
55         Set<Class<?>> controllerSet = ClassHelper.getControllerClassSet();
56         if(null != controllerSet && controllerSet.size()>0){
57             for (Class<?> c : controllerSet) {
58                 //获取class对象中的所有方法
59                 Method[] methods = c.getDeclaredMethods();
60                 if(null != methods && methods.length>0){
61                     for (Method m : methods) {
62                         //匹配@Action注解
63                         if(m.isAnnotationPresent(Action.class)){
64                             Action action = m.getAnnotation(Action.class);
65                             String mapping = action.value();
66                             //正则匹配
67                             if(mapping.matches("\\w+:/\\w*")){
68                                 String[] arrays = mapping.split(":");
69                                 String requestMethod = arrays[0];
70                                 String requestPath = arrays[1];
71                                 Request request = new Request(requestMethod, requestPath);
72                                 Handler handler = new Handler(c, m);
73                                 //封装到 请求--处理器的映射
74                                 ACTION_MAP.put(request,handler);
75                             }
76                         }
77                     }
78                 }
79             }
80         }
81     }
82
83     /**
84      * 根据请求方法(GET、POST),请求路径(../../..),
85      * 获取某个Hander(包括controller class以及对应的method)
86      * @param requestMethod
87      * @param requestPath
88      * @return
89      */
90     public static Handler getHandler(String requestMethod,String requestPath){
91         for (Map.Entry<Request, Handler> entity : ACTION_MAP.entrySet()) {
92             Handler value = entity.getValue();
93             Request request = entity.getKey();
94             System.out.println(value.getActionMethod()+"------------"+value.getControllerClass());
95         }
96         return ACTION_MAP.get(new Request(requestMethod,requestPath));
97     }
98 }

ControllerHelper

  2.2.7  第七步、提供初始化框架的工具类:LoaderHelper(加载ClassHelper、BeanHelper、IocHelper、ControllerHelper)

    没啥好说的,就遍历一下,调用4次ClassUtil#loadClass

 1 package cn.ease4j;
 2
 3 import cn.ease4j.annotation.Controller;
 4 import cn.ease4j.helper.BeanHelper;
 5 import cn.ease4j.helper.ClassHelper;
 6 import cn.ease4j.helper.ControllerHelper;
 7 import cn.ease4j.helper.IocHelper;
 8 import cn.ease4j.util.ClassUtil;
 9
10 /**
11  * 助手加载器
12  * @author Zephyr Lai
13  */
14 public class HelperLoader {
15     /**
16      * 依次加载各个助手(Helper)
17      */
18     public static void init(){
19         Class[] classList={
20                 ClassHelper.class,
21                 BeanHelper.class,
22                 IocHelper.class,
23                 ControllerHelper.class
24         };
25         for (Class clz : classList) {
26             ClassUtil.loadClass(clz.getName(),false);
27         }
28     }
29 }

HelperLoader

  2.2.8  第八步、提供框架中请求转发器DispatcherServlet(人话:就是写个框架中的Servlet)

(未完。。。)

  

转载于:https://www.cnblogs.com/laizonghao/p/8158913.html

《架构探险》第三章 项目核心实现相关推荐

  1. 走向.NET架构设计—第三章—分层设计,初涉架构(后篇)

    走向.NET架构设计-第三章-分层设计,初涉架构(后篇) 前言:本篇主要是接着前两篇文章继续讲述! 本篇的议题如下: 4. 数据访问层设计 5. 显示层设计 6. UI层设计   4.  数据访问层设 ...

  2. 【再读第六版PMBOK】第三章 项目经理的角色

    [再读第六版PMBOK]第三章 项目经理的角色 1)概述 2)项目经理的定义 3)项目经理的影响力范围 4)项目经理的能力 4.1)技术项目管理技能 4.2)战略和商务管理技能 4.3)领导力技能 4 ...

  3. PMBOK(第六版) PMP笔记——《三》第三章 项目经理的角色

    PMBOK(第六版) PMP笔记--<三>第三章 项目经理的角色 1 .项目经理是由执行组织委派,领导团队实现项目目标的个人. 就像是交响乐队的指挥,他不需要掌握每种乐器,但应具备音乐知识 ...

  4. IT项目管理总结:第三章 项目管理过程组

    第三章 项目管理过程组 项目管理过程组(Project Management Process Groups) –启动(initiating)过程:包括定义和批准项目或者项目阶段.它在项目的每个阶段都发 ...

  5. PMP学习系列5:PMBOK(5th)第三章-项目管理过程

    PMP学习系列5:PMBOK(5th)第三章-项目管理过程 一.引言 1.概述 过程的定义:A process is a set of interrelated actions and activit ...

  6. PMP 考点 第三章 项目经理的角色

    第三章 项目经理的角色 章节 序号 知识点 考点级别 备注 第三章 项目经理的角色 3.1 项目经理的角色 1 3.2 项目经理影响力范围 2 3.3 项目经理的能力 2 3.4 项目经理的领导和领导 ...

  7. 2020年PMP笔记归纳第三章项目经理的角色

    第三章 项目经理的角色 掌握第三章项目经理的角色知识 学习内容: 内容章节 3.1 概述 3.2 项目经理的定义 3.3 项目经理的影响力范围 3.4 项目经理的能力 3.5 执行整合 3.1 概述 ...

  8. 计算机一级设置项目符号,重推计算机等级考试题库:一级MS Office第三章“项目符号和段落编号”...

    小编所收集到的相关计算机等级考试题库:一级MS Office第三章"项目符号和段落编号"的资料 大家要认真阅读哦! 编排文档时,在某些段落前加上编号或某种特定的符号(称项目符号), ...

  9. 《大型网站技术架构》——第三章 大型网站核心架构要素

    系统的各个重要组成部分及其关系构成了系统的架构. 系统功能 性能 响应 很多时候网站性能问题是网站架构升级优化的触发器. 浏览器端:浏览器缓存.页面压缩.合理布局页面.减少Cookie传输 CDN:将 ...

最新文章

  1. Python数据分析学习文章归纳
  2. [APUE]文件和目录(中)
  3. 【记录】一些非常方便的命令集合
  4. win7编程接口的一些变化
  5. 用C语言打开文件的几种方式及区别
  6. tomcat安装问题解决
  7. vs dll lib 使用记录
  8. 单独安装想要的office_安装OFFICE不再求人,最省心的方法
  9. python xlwings api_2021-01-13python,xlwings,api运用,及一些问题
  10. C语言课后习题(41)
  11. Oracle案例08——xx.xx.xx.xx,表空间 SYSAUX 使用率95%%
  12. ctf题目:看不见的flag_记一次江西省信息安全线下CTF比赛
  13. 7、51单片机——74HC595、74HC573、字模和点阵屏详解
  14. 人生不过一场旅行,你路过我,我路过你
  15. java达内小发猫课程,详细说明
  16. 【经验】一劳永逸解决中文显示是大方块,不是乱码(最详细解释,有图有真相)
  17. MXNet:基础和入门
  18. 关于万门大学的《理论物理一个月特训》课程
  19. Ubuntu 16.10 禁用 Guest 访客模式
  20. 电脑中毒后常见的问题以及防毒的总结

热门文章

  1. 用java来实现列出指定目录下的文件,子目录下的文件也要输出
  2. java求职面试_Java面试求职
  3. 删除计算机共享信息命令,win10系统使用命令将网络共享删除的操作办法
  4. 如何格式化电脑_计算机格式化的方法教程
  5. 【Flink】Flink flink-runtime.version.properties generated correctly. You MUST run mvn generate-source
  6. 【Elasticsearch】Elasticsearch 缓存策略 QueryCacheingPolicy
  7. 【kibana】状态异常 Status: Red Status changed from red to yellow - No existing Kibana index found
  8. 【hortonworks/registries】Parameter Schema name is null
  9. 11-提升R语言程序性能gc()
  10. 12-linux安装kibana