1 packagecom.tjt.springmvc;2
3
4 importjavax.servlet.ServletConfig;5 importjavax.servlet.ServletException;6 importjavax.servlet.http.HttpServlet;7 importjavax.servlet.http.HttpServletRequest;8 importjavax.servlet.http.HttpServletResponse;9 importjava.io.IOException;10 importjava.lang.reflect.InvocationTargetException;11 importjava.lang.reflect.Method;12 importjava.util.List;13 importjava.util.Map;14 importjava.util.Objects;15 importjava.util.concurrent.ConcurrentHashMap;16
17
18
19 /**
20 * DispatcherServlet 处理SpringMVC 框架流程21 * 主要流程:22 * 1、包扫描获取包下面所有的类23 * 2、初始化包下面所有的类24 * 3、初始化HandlerMapping 方法,将url 和方法对应上25 * 4、实现HttpServlet 重写doPost 方法26 *27 */
28 public class DispatcherServlet extendsHttpServlet {29
30 /**
31 * 部分静态常量32 */
33 private static String PACKAGE_CLASS_NULL_EX = "包扫描后的classes为null";34 private static String HTTP_NOT_EXIST = "sorry http is not exit 404";35 private static String METHOD_NOT_EXIST = "sorry method is not exit 404";36 private static String POINT_JSP = ".jsp";37 private static String LEFT_LINE = "/";38
39 /**
40 * 用于存放SpringMVC bean 的容器41 */
42 private ConcurrentHashMap mvcBeans = new ConcurrentHashMap<>();43 private ConcurrentHashMap mvcBeanUrl = new ConcurrentHashMap<>();44 private ConcurrentHashMap mvcMethodUrl = new ConcurrentHashMap<>();45 private static String PROJECT_PACKAGE_PATH = "com.tjt.springmvc";46
47
48 /**
49 * 按顺序初始化组件50 *@paramconfig51 */
52 @Override53 public voidinit(ServletConfig config) {54 String packagePath =PROJECT_PACKAGE_PATH;55 try{56 //1.进行报扫描获取当前包下面所有的类
57 List> classes =comscanPackage(packagePath);58 //2.初始化springmvcbean
59 initSpringMvcBean(classes);60 } catch(Exception e) {61 e.printStackTrace();62 }63 //3.将请求地址和方法进行映射
64 initHandMapping(mvcBeans);65 }66
67
68 /**
69 * 调用ClassUtils 工具类获取工程中所有的class70 *@parampackagePath71 *@return
72 *@throwsException73 */
74 public List> comscanPackage(String packagePath) throwsException {75 List> classes =ClassUtils.getClasses(packagePath);76 returnclasses;77 }78
79 /**
80 * 初始化SpringMVC bean81 *82 *@paramclasses83 *@throwsException84 */
85 public void initSpringMvcBean(List> classes) throwsException {86 /**
87 * 若包扫描出的classes 为空则直接抛异常88 */
89 if(classes.isEmpty()) {90 throw newException(PACKAGE_CLASS_NULL_EX);91 }92
93 /**
94 * 遍历所有classes 获取@MyController 注解95 */
96 for (Class>aClass : classes) {97 //获取被自定义注解的controller 将其初始化到自定义springmvc 容器中
98 MyController declaredAnnotation = aClass.getDeclaredAnnotation(MyController.class);99 if (declaredAnnotation != null) {100 //获取类的名字
101 String beanid =lowerFirstCapse(aClass.getSimpleName());102 //获取对象
103 Object beanObj =aClass.newInstance();104 //放入spring 容器
105 mvcBeans.put(beanid, beanObj);106 }107 }108
109 }110
111 /**
112 * 初始化HandlerMapping 方法113 *114 *@parammvcBeans115 */
116 public void initHandMapping(ConcurrentHashMapmvcBeans) {117 /**
118 * 遍历springmvc 获取注入的对象值119 */
120 for (Map.Entryentry : mvcBeans.entrySet()) {121 Object objValue =entry.getValue();122 Class> aClass =objValue.getClass();123 //获取当前类 判断其是否有自定义的requestMapping 注解
124 String mappingUrl = null;125 MyRequestMapping anRequestMapping = aClass.getDeclaredAnnotation(MyRequestMapping.class);126 if (anRequestMapping != null) {127 mappingUrl =anRequestMapping.value();128 }129 //获取当前类所有方法,判断方法上是否有注解
130 Method[] declaredMethods =aClass.getDeclaredMethods();131 /**
132 * 遍历注解133 */
134 for(Method method : declaredMethods) {135 MyRequestMapping methodDeclaredAnnotation = method.getDeclaredAnnotation(MyRequestMapping.class);136 if (methodDeclaredAnnotation != null) {137 String methodUrl =methodDeclaredAnnotation.value();138 mvcBeanUrl.put(mappingUrl +methodUrl, objValue);139 mvcMethodUrl.put(mappingUrl +methodUrl, method.getName());140 }141 }142
143 }144
145 }146
147 /**
148 *@paramstr149 *@return类名首字母小写150 */
151 public staticString lowerFirstCapse(String str) {152 char[] chars =str.toCharArray();153 chars[0] += 32;154 returnString.valueOf(chars);155
156 }157
158 /**
159 * doPost 请求160 *@paramreq161 *@paramresp162 *@throwsServletException163 *@throwsIOException164 */
165 @Override166 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException {167 try{168 /**
169 * 处理请求170 */
171 doServelt(req, resp);172 } catch(NoSuchMethodException e) {173 e.printStackTrace();174 } catch(InvocationTargetException e) {175 e.printStackTrace();176 } catch(IllegalAccessException e) {177 e.printStackTrace();178 }179 }180
181 /**
182 * doServelt 处理请求183 *@paramreq184 *@paramresp185 *@throwsIOException186 *@throwsNoSuchMethodException187 *@throwsInvocationTargetException188 *@throwsIllegalAccessException189 *@throwsServletException190 */
191 private void doServelt(HttpServletRequest req, HttpServletResponse resp) throwsIOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, ServletException {192 //获取请求地址
193 String requestUrl =req.getRequestURI();194 //查找地址所对应bean
195 Object object =mvcBeanUrl.get(requestUrl);196 if(Objects.isNull(object)) {197 resp.getWriter().println(HTTP_NOT_EXIST);198 return;199 }200 //获取请求的方法
201 String methodName =mvcMethodUrl.get(requestUrl);202 if (methodName == null) {203 resp.getWriter().println(METHOD_NOT_EXIST);204 return;205 }206
207
208 //通过构反射执行方法
209 Class> aClass =object.getClass();210 Method method =aClass.getMethod(methodName);211
212 String invoke =(String) method.invoke(object);213 //获取后缀信息
214 String suffix =POINT_JSP;215 //页面目录地址
216 String prefix =LEFT_LINE;217 req.getRequestDispatcher(prefix + invoke +suffix).forward(req, resp);218
219
220
221
222 }223
224 /**
225 * doGet 请求226 *@paramreq227 *@paramresp228 *@throwsServletException229 *@throwsIOException230 */
231 @Override232 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException {233 this.doPost(req, resp);234 }235
236
237 }