package cn.nosum.framework.mvc.v4.servlet; import cn.nosum.framework.annotation.Controller; import cn.nosum.framework.annotation.RequestMapping; import cn.nosum.framework.context.ApplicationContext; import cn.nosum.util.StringUtils; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class DispatcherServlet extends HttpServlet { private ApplicationContext applicationContext; private List handlerMappings = new ArrayList(); private Map handlerAdapterMap=new HashMap(); private List viewResolvers=new ArrayList(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //6、调用,运行阶段 try { doDispatch(req, resp); } catch (Exception e) { try{ processDispatchResult(req,resp,new ModelAndView("500")); }catch (Exception e1){ e.printStackTrace(); } } } private void processDispatchResult(HttpServletRequest req, HttpServletResponse resp, ModelAndView modelAndView) throws Exception { if(null == modelAndView){return;} if(this.viewResolvers.isEmpty()){return;} for (ViewResolver viewResolver : this.viewResolvers) { View view = viewResolver.resolveViewName(modelAndView.getViewName()); // 直接往浏览器输出 view.render(modelAndView.getModel(),req,resp); return; } } private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception { // 通过 request 取得 URL,匹配 handlerMapping HandlerMapping handlerMapping=getHandler(req); if(handlerMapping == null){ processDispatchResult(req,resp,new ModelAndView("404")); return; } HandlerAdapter handlerAdapter = getHandlerAdapter(handlerMapping); ModelAndView mv = handlerAdapter.handler(req,resp,handlerMapping); processDispatchResult(req,resp,mv); } private HandlerAdapter getHandlerAdapter(HandlerMapping handlerMapping) { if(this.handlerAdapterMap.isEmpty()){return null;} return this.handlerAdapterMap.get(handlerMapping); } private HandlerMapping getHandler(HttpServletRequest req) { if(this.handlerMappings.isEmpty()){return null;} String url = req.getRequestURI(); String contextPath = req.getContextPath(); url = url.replaceAll(contextPath,"").replaceAll("/+","/"); for (HandlerMapping mapping : handlerMappings) { Matcher matcher = mapping.getPattern().matcher(url); if(!matcher.matches()){continue;} return mapping; } return null; } @Override public void init(ServletConfig config) throws ServletException { //初始化Spring核心IoC容器 applicationContext = new ApplicationContext(config.getInitParameter("contextConfigLocation")); //完成了IoC、DI和MVC部分对接 //初始化九大组件 initStrategies(applicationContext); System.out.println("Spring framework is init."); } private void initStrategies(ApplicationContext context) { //handlerMapping initHandlerMappings(context); //初始化参数适配器 initHandlerAdapters(context); //初始化视图转换器 initViewResolvers(context); } private void initViewResolvers(ApplicationContext context) { String templateRoot = context.getConfig().getProperty("templateRoot"); String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile(); File templateRootDir = new File(templateRootPath); for (File file : templateRootDir.listFiles()) { this.viewResolvers.add(new ViewResolver(templateRoot)); } } private void initHandlerAdapters(ApplicationContext context) { for (HandlerMapping handlerMapping : handlerMappings) { this.handlerAdapterMap.put(handlerMapping,new HandlerAdapter()); } } private void initHandlerMappings(ApplicationContext context) { if (context.getBeanDefinitionCount()==0){return;} for (String beanName : this.applicationContext.getBeanDefinitionNames()) { Object instance = applicationContext.getBean(beanName); Class clazz = instance.getClass(); if(!clazz.isAnnotationPresent(Controller.class)){ continue; } // 提取 class 上配置的url String baseUrl = ""; if(clazz.isAnnotationPresent(RequestMapping.class)){ RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class); baseUrl = requestMapping.value(); } //只获取public的方法 for (Method method : clazz.getMethods()) { if(!method.isAnnotationPresent(RequestMapping.class)){continue;} //提取每个方法上面配置的url RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); String regex = ("/" + baseUrl + "/" + requestMapping.value() .replaceAll("\\*",".*")) // 将 * 替换成 .* .replaceAll("/+","/"); // 将多个 / 替换为一个 Pattern pattern = Pattern.compile(regex); handlerMappings.add(new HandlerMapping(pattern,instance,method)); System.out.println("Mapped : " + regex + "," + method); } } } }