DispatcherServlet.java 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package cn.nosum.framework.mvc.v4.servlet;
  2. import cn.nosum.framework.annotation.Controller;
  3. import cn.nosum.framework.annotation.RequestMapping;
  4. import cn.nosum.framework.context.ApplicationContext;
  5. import cn.nosum.util.StringUtils;
  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.lang.reflect.Method;
  14. import java.util.*;
  15. import java.util.regex.Matcher;
  16. import java.util.regex.Pattern;
  17. public class DispatcherServlet extends HttpServlet {
  18. private ApplicationContext applicationContext;
  19. private List<HandlerMapping> handlerMappings = new ArrayList<HandlerMapping>();
  20. private Map<HandlerMapping,HandlerAdapter> handlerAdapterMap=new HashMap<HandlerMapping, HandlerAdapter>();
  21. private List<ViewResolver> viewResolvers=new ArrayList<ViewResolver>();
  22. @Override
  23. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  24. this.doPost(req, resp);
  25. }
  26. @Override
  27. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  28. //6、调用,运行阶段
  29. try {
  30. doDispatch(req, resp);
  31. } catch (Exception e) {
  32. try{
  33. processDispatchResult(req,resp,new ModelAndView("500"));
  34. }catch (Exception e1){
  35. e.printStackTrace();
  36. }
  37. }
  38. }
  39. private void processDispatchResult(HttpServletRequest req, HttpServletResponse resp, ModelAndView modelAndView) throws Exception {
  40. if(null == modelAndView){return;}
  41. if(this.viewResolvers.isEmpty()){return;}
  42. for (ViewResolver viewResolver : this.viewResolvers) {
  43. View view = viewResolver.resolveViewName(modelAndView.getViewName());
  44. // 直接往浏览器输出
  45. view.render(modelAndView.getModel(),req,resp);
  46. return;
  47. }
  48. }
  49. private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
  50. // 通过 request 取得 URL,匹配 handlerMapping
  51. HandlerMapping handlerMapping=getHandler(req);
  52. if(handlerMapping == null){
  53. processDispatchResult(req,resp,new ModelAndView("404"));
  54. return;
  55. }
  56. HandlerAdapter handlerAdapter = getHandlerAdapter(handlerMapping);
  57. ModelAndView mv = handlerAdapter.handler(req,resp,handlerMapping);
  58. processDispatchResult(req,resp,mv);
  59. }
  60. private HandlerAdapter getHandlerAdapter(HandlerMapping handlerMapping) {
  61. if(this.handlerAdapterMap.isEmpty()){return null;}
  62. return this.handlerAdapterMap.get(handlerMapping);
  63. }
  64. private HandlerMapping getHandler(HttpServletRequest req) {
  65. if(this.handlerMappings.isEmpty()){return null;}
  66. String url = req.getRequestURI();
  67. String contextPath = req.getContextPath();
  68. url = url.replaceAll(contextPath,"").replaceAll("/+","/");
  69. for (HandlerMapping mapping : handlerMappings) {
  70. Matcher matcher = mapping.getPattern().matcher(url);
  71. if(!matcher.matches()){continue;}
  72. return mapping;
  73. }
  74. return null;
  75. }
  76. @Override
  77. public void init(ServletConfig config) throws ServletException {
  78. //初始化Spring核心IoC容器
  79. applicationContext = new ApplicationContext(config.getInitParameter("contextConfigLocation"));
  80. //完成了IoC、DI和MVC部分对接
  81. //初始化九大组件
  82. initStrategies(applicationContext);
  83. System.out.println("Spring framework is init.");
  84. }
  85. private void initStrategies(ApplicationContext context) {
  86. //handlerMapping
  87. initHandlerMappings(context);
  88. //初始化参数适配器
  89. initHandlerAdapters(context);
  90. //初始化视图转换器
  91. initViewResolvers(context);
  92. }
  93. private void initViewResolvers(ApplicationContext context) {
  94. String templateRoot = context.getConfig().getProperty("templateRoot");
  95. String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();
  96. File templateRootDir = new File(templateRootPath);
  97. for (File file : templateRootDir.listFiles()) {
  98. this.viewResolvers.add(new ViewResolver(templateRoot));
  99. }
  100. }
  101. private void initHandlerAdapters(ApplicationContext context) {
  102. for (HandlerMapping handlerMapping : handlerMappings) {
  103. this.handlerAdapterMap.put(handlerMapping,new HandlerAdapter());
  104. }
  105. }
  106. private void initHandlerMappings(ApplicationContext context) {
  107. if (context.getBeanDefinitionCount()==0){return;}
  108. for (String beanName : this.applicationContext.getBeanDefinitionNames()) {
  109. Object instance = applicationContext.getBean(beanName);
  110. Class<?> clazz = instance.getClass();
  111. if(!clazz.isAnnotationPresent(Controller.class)){ continue; }
  112. // 提取 class 上配置的url
  113. String baseUrl = "";
  114. if(clazz.isAnnotationPresent(RequestMapping.class)){
  115. RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class);
  116. baseUrl = requestMapping.value();
  117. }
  118. //只获取public的方法
  119. for (Method method : clazz.getMethods()) {
  120. if(!method.isAnnotationPresent(RequestMapping.class)){continue;}
  121. //提取每个方法上面配置的url
  122. RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
  123. String regex = ("/" + baseUrl + "/" + requestMapping.value()
  124. .replaceAll("\\*",".*")) // 将 * 替换成 .*
  125. .replaceAll("/+","/"); // 将多个 / 替换为一个
  126. Pattern pattern = Pattern.compile(regex);
  127. handlerMappings.add(new HandlerMapping(pattern,instance,method));
  128. System.out.println("Mapped : " + regex + "," + method);
  129. }
  130. }
  131. }
  132. }