Springmvc的请求处理

在上两篇中,我们简单的介绍了web模式下bean的注入以及ioc容器的创建时间。那么,在容器创建之后,servletContext会持有ioc容器,以便在后面去处理业务逻辑

这一篇我们就仔细分析一下springmvc是怎么处理请求,又是如何去使用ioc容器中的bean的

我们都知道,springmvc也是基于servlet去处理请求。那么他就应该符合servlet的执行流程与规范

在使用servlet的时候,我们需要在web.xml文件中去配置servlet的名字与类路径以及他需要处理的请求。同样,我们也为DispatcherServlet做了相关配置

<servlet>
	<servlet-name>dispatcherServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>dispatcherServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

//简单说明一下
<url-pattern>/</url-pattern>  会匹配到/login这样的路径型url,不会匹配到模式为*.jsp这样的后缀型url

<url-pattern>/*</url-pattern> 会匹配所有url:路径型的和后缀型的url(包括/login,*.jsp,*.js和*.html等)

所以我们的DispatcherServlet会处理我们的所有的请求。 servlet处理请求都是在service()里面

dispatcherServlet的请求处理

FrameworkServlet   431 line

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获取请求方式 
        HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
        //进行请求判断  对于 get post  put  delete  options  trace 等进行处理  略过
        if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
            super.service(request, response);
        } else {
            this.processRequest(request, response);
        }

    }

最终都会走到这个方法

FrameworkServlet  487   line

protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //构建了一系列参数
        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
        LocaleContext localeContext = this.buildLocaleContext(request);
        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
        //将本次请求的信息保存在threadLocal中
        this.initContextHolders(request, localeContext, requestAttributes);

        try {
        	//业务处理  往下看
            this.doService(request, response);
        } catch (IOException | ServletException var16) {
            failureCause = var16;
            throw var16;
        } catch (Throwable var17) {
            failureCause = var17;
            throw new NestedServletException("Request processing failed", var17);
        } finally {
            this.resetContextHolders(request, previousLocaleContext, previousAttributes);
            if (requestAttributes != null) {
                requestAttributes.requestCompleted();
            }

            this.logResult(request, response, (Throwable)failureCause, asyncManager);
            this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
        }

    }

业务处理

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ......
		//设置一些请求信息
        request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
        request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
        request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
        if (this.flashMapManager != null) {
            FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
            if (inputFlashMap != null) {
                request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
            }

            request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
            request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
        }

        try {
        	//请求分发
            this.doDispatch(request, response);
        } 
        ......

    }

请求分发

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            try {
                ModelAndView mv = null;
                Object dispatchException = null;

                try {
                	//如果请求带有文件  则进行request的一个简单包装
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    //获取handler  也就是我们的控制器?? 直接就获取了?
                    //那么handler什么时候注册的呢?稍后介绍
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null) {
                    	//不存在对应handler  返回404
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
					//handler是从HandlerMapping中拿到的 根据handler获取HandlerAdapter
					//HandlerAdapter也是具体执行handle的执行类  也就是业务方法的执行类
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    //请求方式  请求类型
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    //判断是否已经被处理 处理过的话,直接返回
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
					
					//调用拦截器,判断这个请求是否需要被拦截!!!这里涉及到了拦截器哦
					//DispatcherServlet持有拦截器的引用
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }

					//调用handle方法,这里会生成modelAndView  后续分析
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    //业务执行之后,再次调用拦截器的post方法
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } 
                
                ......异常处理哦
                //这里会进行结果处理  也就是视图渲染...... 后续分析
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }

获取handlerMapping 从中获取handler

DispatcherServlet    628  line

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
        	//从handlerMappings中取   handlerMappings是一个arrayList
            Iterator var2 = this.handlerMappings.iterator();
            while(var2.hasNext()) {
                HandlerMapping mapping = (HandlerMapping)var2.next();
                //获取hander   往下看
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }

        return null;
    }

AbstarctHandlerMapping   224 line

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        //获取handler  等会研究  继续往里面看
        Object handler = this.getHandlerInternal(request);
        if (handler == null) {
            handler = this.getDefaultHandler();
        }

        if (handler == null) {
            return null;
        } else {
            if (handler instanceof String) {
                String handlerName = (String)handler;
                handler = this.obtainApplicationContext().getBean(handlerName);
            }
			//包装成HandlerExecutionChain  这里面会将HandlerMapping中的一些拦截器拿到HandlerExecutionChain中
            HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);
            //看样子是跨域相关配置的处理
            if (this.hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
                CorsConfiguration config = this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null;
                CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
                config = config != null ? config.combine(handlerConfig) : handlerConfig;
                executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
            }
			//返回
            return executionChain;
        }
    }

获取handler

AbstractHandlerMethodMapping  201 line

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		//获取请求uri
        String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
        request.setAttribute(LOOKUP_PATH, lookupPath);
        //获取一个独占锁
        this.mappingRegistry.acquireReadLock();
        HandlerMethod var4;
        try {
        	//获取handler  往下看
            HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);
            var4 = handlerMethod != null ? handlerMethod.createWithResolvedBean() : null;
        } finally {
            this.mappingRegistry.releaseReadLock();
        }

        return var4;
    }

还是这个文件    218  line
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList();
        //这一块其实也就是在本bean中,以一个map来保存接口以及接口处理的类与方法
        List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        if (directPathMatches != null) {
        	//将匹配的handler保存在上面创建的matches集合中
            this.addMatchingMappings(directPathMatches, matches, request);
        }

        if (matches.isEmpty()) {
            this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }

        if (!matches.isEmpty()) {
            AbstractHandlerMethodMapping<T>.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
            //如果一个接口有多个方法与其对应 直接报错 
            if (matches.size() > 1) {
                Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request));
                matches.sort(comparator);
                bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
                (CorsUtils.isPreFlightRequest(request)) {
                	//如果请求方式是Origin  则返回一个默认的hander  因为这个请求来判断是否可以跨域
                    return PREFLIGHT_AMBIGUOUS_MATCH;
                }

                AbstractHandlerMethodMapping<T>.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get(1);
                if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                    Method m1 = bestMatch.handlerMethod.getMethod();
                    Method m2 = secondBestMatch.handlerMethod.getMethod();
                    String uri = request.getRequestURI();
                    //抛出异常信息
                    throw new IllegalStateException("Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
                }
            }

            request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
            //将一些信息放置在请求域中
            this.handleMatch(bestMatch.mapping, lookupPath, request);
            //返回匹配到的hander
            return bestMatch.handlerMethod;
        } else {
        	//没有匹配到,直接返回null
            return this.handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
        }
    }
    

稍微总结一下:

在这里插入图片描述

到目前位置,已经拿到对应的hander

下一篇分析 springmvc是什么时候将接口与对应的业务处理bean来结合放置在HandlerMapping中的map里面

以及springmvc如何使用hander来获取ModelAndView。以及渲染时怎么进行的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值