|
@@ -0,0 +1,153 @@
|
|
|
|
+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<HandlerMapping> handlerMappings = new ArrayList<HandlerMapping>();
|
|
|
|
+ private Map<HandlerMapping,HandlerAdapter> handlerAdapterMap=new HashMap<HandlerMapping, HandlerAdapter>();
|
|
|
|
+ private List<ViewResolver> viewResolvers=new ArrayList<ViewResolver>();
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @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);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|