美文网首页撸一个mvc框架
动手撸一个 mvc 框架3

动手撸一个 mvc 框架3

作者: 想54256 | 来源:发表于2020-04-29 13:33 被阅读0次

    title: 动手撸一个 mvc 框架3
    date: 2020/04/24 15:44


    本节内容

    继续上节,将找到 RequestMapping 对象并执行整个流程进行实现

    请求来了

    1、FrameworkServlet 对请求进行的处理

    重写了父类的 doGet 和 doPost 方法,将其共同引向一个方法

    // ------> 请求来了
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
    
    protected final void processRequest(HttpServletRequest request, HttpServletResponse response) {
    
        // 准备一些环境(本地化、异步、还有一个什么参数不知道干啥用的)
    
    
        // 调用处理方法
        this.doService(request, response);
    
        // 触发一个事件
    }
    
    
    protected abstract void doService(HttpServletRequest request, HttpServletResponse response);
    

    2、DispatcherServlet 实现 doService 方法

    public class DispatcherServlet extends FrameworkServlet {
    
        // 处理器映射器集合
        private List<HandlerMapping> handlerMappings;
    
        /**
         * This implementation calls {@link #initStrategies}.
         */
        @Override
        protected void onRefresh(ApplicationContext context) {
            initStrategies(context);
        }
    
        /**
         * 初始化此servlet使用的策略对象。
         */
        protected void initStrategies(ApplicationContext context) {
    //        initMultipartResolver(context);
    //        initLocaleResolver(context);
    //        initThemeResolver(context);
    
            // 初始化处理器映射器,通过处理器映射器找到对应的方法进行执行
            this.initHandlerMappings(context);
    //        initHandlerAdapters(context);
    //        initHandlerExceptionResolvers(context);
    //        initRequestToViewNameTranslator(context);
    //        initViewResolvers(context);
    //        initFlashMapManager(context);
        }
    
        private void initHandlerMappings(ApplicationContext context) {
            String[] bdNames = context.getBeanDefinitionNames(HandlerMapping.class);
            this.handlerMappings = Arrays.stream(bdNames)
                    .map(beanName -> context.getBean(beanName, HandlerMapping.class))
                    .collect(Collectors.toList());
        }
    
        @Override
        protected void doService(HttpServletRequest request, HttpServletResponse response) {
    
        }
    
        protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
            HandlerExecutionChain mappedHandler = this.getHandler(request);
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
                return;
            }
        }
    
        /**
         * 根据请求获取【处理链】
         */
        private HandlerExecutionChain getHandler(HttpServletRequest request) {
            for (HandlerMapping handlerMapping : handlerMappings) {
                HandlerExecutionChain handler = handlerMapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
    
            return null;
        }
    
    }
    

    HandlerExecutionChain

    public class HandlerExecutionChain {
    
        private final Object handler;
    
        public HandlerExecutionChain(Object handler) {
            this.handler = handler;
        }
    
        public Object getHandler() {
            return handler;
        }
    }
    

    3、RequestMappingHandlerMapping#getHandler()

    public abstract class AbstractHandlerMapping implements HandlerMapping {
        /**
         * 返回此请求的处理程序和所有拦截器。可以根据请求URL,会话状态或实现类选择的任何因素进行选择。
         */
        @Override
        public final HandlerExecutionChain getHandler(HttpServletRequest request) {
    
            // 根据请求获取处理程序
            Object handler = this.getHandlerInternal(request);
            if (handler == null) {
                return null;
            }
    
            // 如果是实现了 Controller 接口的情况,则从 bf 中取出
            // if (handler instanceof String) {
            //     String handlerName = (String) handler;
            //     handler = getApplicationContext().getBean(handlerName);
            // }
    
            // 这个地方和拦截器有关
    //        return this.getHandlerExecutionChain(handler, request);
            return null;
        }
    
        /**
         * 查找给定请求的处理程序,如果未找到特定请求,则返回 null。
         */
        protected abstract Object getHandlerInternal(HttpServletRequest request);
    }
    
    RequestMappingHandlerMapping 的实现
    
    /**
     * 查找给定请求的处理程序,如果未找到特定请求,则返回 null。
     */
    @Override
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) {
        List<Match> matches = new ArrayList<>();
    
        String lookupPath = request.getRequestURI();
        List<RequestMappingInfo> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        // 如果找到匹配的了,就进行校验,看看是否符合当前请求
        if (directPathMatches != null) {
            this.addMatchingMappings(directPathMatches, matches, request);
        }
        // 如果没有找到合适的,说明可能是 @PathVariable 的情况,则把所有的 RequestMappingInfo 交给它进行寻找匹配的。
        if (matches.isEmpty()) {
            this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }
    
        // 如果匹配的不为空,则取出第一个将它的 handlerMethod 进行返回
        if (CollUtil.isNotEmpty(matches)) {
            Match bestMatch = matches.get(0);
            return bestMatch.handlerMethod;
        }
    
        throw new RuntimeException("没有为当前请求找到处理器!");
    }
    
    /**
        * 对请求方法、请求路径(包括 @PathVariable)【@RequestMapping 相关的内容】进行校验
        */
    private void addMatchingMappings(Collection<RequestMappingInfo> mappingInfos, List<Match> matches, HttpServletRequest request) {
        for (RequestMappingInfo mappingInfo : mappingInfos) {
            RequestMappingInfo info = mappingInfo.getMatchingCondition(request);
            if (ObjectUtil.isNotNull(info)) {
                matches.add(new Match(info, this.mappingRegistry.getMappings().get(mappingInfo)));
            }
        }
    }
    
    private static class Match {
    
        private final RequestMappingInfo mapping;
    
        private final HandlerMethod handlerMethod;
    
        public Match(RequestMappingInfo mapping, HandlerMethod handlerMethod) {
            this.mapping = mapping;
            this.handlerMethod = handlerMethod;
        }
    
        @Override
        public String toString() {
            return this.mapping.toString();
        }
    }
    

    相关文章

      网友评论

        本文标题:动手撸一个 mvc 框架3

        本文链接:https://www.haomeiwen.com/subject/wlvgwhtx.html