DispatcherServlet.java 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package cn.nosum.framework.mvc.v1.servlet;
  2. import cn.nosum.framework.annotation.Autowired;
  3. import cn.nosum.framework.annotation.Controller;
  4. import cn.nosum.framework.annotation.RequestMapping;
  5. import cn.nosum.framework.annotation.Service;
  6. import javax.servlet.ServletConfig;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.http.HttpServlet;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11. import java.io.File;
  12. import java.io.IOException;
  13. import java.io.InputStream;
  14. import java.lang.reflect.Field;
  15. import java.lang.reflect.Method;
  16. import java.net.URL;
  17. import java.util.*;
  18. public class DispatcherServlet extends HttpServlet {
  19. private Map<String, Object> mapping = new HashMap<String, Object>();
  20. @Override
  21. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  22. this.doPost(req, resp);
  23. }
  24. @Override
  25. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  26. try {
  27. doDispatch(req, resp);
  28. } catch (Exception e) {
  29. resp.getWriter().write("500 Exception " + Arrays.toString(e.getStackTrace()));
  30. }
  31. }
  32. /**
  33. * 进行URL的映射
  34. */
  35. private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
  36. String url = req.getRequestURI();
  37. String contextPath = req.getContextPath();
  38. // 去除 URL 中的前缀并且将多个 / 替换为一个
  39. url = url.replace(contextPath, "").replaceAll("/+", "/");
  40. // 找不到页面
  41. if (!this.mapping.containsKey(url)) {
  42. resp.getWriter().write("404 Not Found!!");
  43. return;
  44. }
  45. // 根据 URL 取得对应的方法映射
  46. Method method = (Method) this.mapping.get(url);
  47. // 取得所有的参数
  48. Map<String, String[]> params = req.getParameterMap();
  49. // 调用方法
  50. method.invoke(this.mapping.get(method.getDeclaringClass().getName()), new Object[]{req, resp, params.get("name")[0]});
  51. }
  52. /**
  53. * 初始化所有的相关的类,IOC容器、servletBean
  54. */
  55. @Override
  56. public void init(ServletConfig config) throws ServletException {
  57. InputStream is = null;
  58. try {
  59. Properties configContext = new Properties();
  60. // 取得 application.properties
  61. is = this.getClass().getClassLoader().getResourceAsStream(config.getInitParameter("contextConfigLocation"));
  62. configContext.load(is);
  63. // 获取定义的扫描包路径
  64. String scanPackage = configContext.getProperty("scanPackage");
  65. // 将指定路径中的类名进行缓存
  66. doScanner(scanPackage);
  67. // 初始化 IOC 容器
  68. for (String className : mapping.keySet()) {
  69. if (!className.contains(".")) {
  70. continue;
  71. }
  72. Class<?> clazz = Class.forName(className);
  73. if (clazz.isAnnotationPresent(Controller.class)) {
  74. // 保存 Controller 实例
  75. mapping.put(className, clazz.getDeclaredConstructor().newInstance());
  76. String baseUrl = "";
  77. if (clazz.isAnnotationPresent(RequestMapping.class)) {
  78. RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class);
  79. baseUrl = requestMapping.value();
  80. }
  81. Method[] methods = clazz.getMethods();
  82. for (Method method : methods) {
  83. if (!method.isAnnotationPresent(RequestMapping.class)) {
  84. continue;
  85. }
  86. RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
  87. String url = (baseUrl + "/" + requestMapping.value()).replaceAll("/+", "/");
  88. // 保存 URL 对应的方法引用
  89. mapping.put(url, method);
  90. System.out.println("Mapped " + url + "," + method);
  91. }
  92. } else if (clazz.isAnnotationPresent(Service.class)) {
  93. Service service = clazz.getAnnotation(Service.class);
  94. String beanName = service.value();
  95. if ("".equals(beanName)) {
  96. beanName = clazz.getName();
  97. }
  98. Object instance = clazz.getDeclaredConstructor().newInstance();
  99. mapping.put(beanName, instance);
  100. // 如果当前实例具备有父接口,保存父接口包名
  101. for (Class<?> i : clazz.getInterfaces()) {
  102. mapping.put(i.getName(), instance);
  103. }
  104. } else {
  105. continue;
  106. }
  107. }
  108. // 依赖注入
  109. for (Object object : mapping.values()) {
  110. if (object == null) {
  111. continue;
  112. }
  113. Class clazz = object.getClass();
  114. if (clazz.isAnnotationPresent(Controller.class)) {
  115. // 取得所有的成员变量
  116. Field[] fields = clazz.getDeclaredFields();
  117. for (Field field : fields) {
  118. if (!field.isAnnotationPresent(Autowired.class)) { continue; }
  119. Autowired autowired = field.getAnnotation(Autowired.class);
  120. String beanName = autowired.value();
  121. if ("".equals(beanName)) {
  122. beanName = field.getType().getName();
  123. }
  124. field.setAccessible(true);
  125. try {
  126. // 从容器中,注入实例
  127. field.set(mapping.get(clazz.getName()), mapping.get(beanName));
  128. } catch (IllegalAccessException e) {
  129. e.printStackTrace();
  130. }
  131. }
  132. }
  133. }
  134. } catch (Exception ignored) {
  135. } finally {
  136. if (is != null) {
  137. try {
  138. is.close();
  139. } catch (IOException e) {
  140. e.printStackTrace();
  141. }
  142. }
  143. }
  144. System.out.print("MVC Framework is init");
  145. }
  146. /**
  147. * 将指定路径中的 class 名称保存
  148. */
  149. private void doScanner(String scanPackage) {
  150. // 将 . 替换为 /
  151. URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
  152. File classDir = new File(url.getFile());
  153. // 扫描包所有的 class 文件
  154. for (File file : classDir.listFiles()) {
  155. if (file.isDirectory()) {
  156. // 如果是文件夹,递归调用
  157. doScanner(scanPackage + "." + file.getName());
  158. } else {
  159. if (!file.getName().endsWith(".class")) {
  160. continue;
  161. }
  162. String clazzName = (scanPackage + "." + file.getName().replace(".class", ""));
  163. mapping.put(clazzName, null);
  164. }
  165. }
  166. }
  167. }