SpringMVC原理剖析

SpringMVC原理

SpringMVC原理图

# 执行流程
1、用户发送http请求
2、dispatchServlet解析请求头中的uri
3、通过处理器映射器(HandlerMapping)拿到对应的hanlder
4、处理器适配器(HandlerAdapter)通过拿到的hanlder处理业务逻辑,返回视图ModelAndView
5、dispatchServlet通过视图解析器(ViewResolver)将物理视图解析成逻辑视图View
6、视图渲染。
  • DispatcherServlet:

    • 调用HandlerMapping拿到Handler
    • 调用HandlerAdapter拿到ModelAndView
    • 调用ViewResolver拿到View
    // 视图渲染
    protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    		// Determine locale for request and apply it to the response.
    		Locale locale =
    				(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
    		response.setLocale(locale);
    
    		View view;
    		String viewName = mv.getViewName();
    		if (viewName != null) {
    			// We need to resolve the view name.
    			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
    			if (view == null) {
    				throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
    						"' in servlet with name '" + getServletName() + "'");
    			}
    		}
    		else {
    			// No need to lookup: the ModelAndView object contains the actual View object.
    			view = mv.getView();
    			if (view == null) {
    				throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
    						"View object in servlet with name '" + getServletName() + "'");
    			}
    		}
    
    		// Delegate to the View object for rendering.
    		if (logger.isTraceEnabled()) {
    			logger.trace("Rendering view [" + view + "] ");
    		}
    		try {
    			if (mv.getStatus() != null) {
    				response.setStatus(mv.getStatus().value());
    			}
    			view.render(mv.getModelInternal(), request, response);
    		}
    		catch (Exception ex) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Error rendering view [" + view + "]", ex);
    			}
    			throw ex;
    		}
    	} 
    
  • HandlerMapping:根据请求的url找到对应的handler

    • urlLookup
      urlLookup案例伪造

    • mappingLookup
      请添加图片描述

    public interface HandlerMapping {
        @Nullable
        HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
    }
    
    public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
    		implements HandlerMapping, Ordered, BeanNameAware {
        // 实现类逻辑
        @Override
        @Nullable
        public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            // 获取handler对象
            Object handler = getHandlerInternal(request);
            ...
            // Handler执行前后要执行的拦截器
            HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
            ...
            return executionChain;
        }
        
        @Nullable
    	protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;
    }
    
    // 映射信息封装handler
    public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {
        String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath";
    	@Override
    	@Nullable
    	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
    		// 从请求头中获取请求路径
            String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
            // org.springframework.web.servlet.HandlerMapping.lookupPath -> /test
    		request.setAttribute(LOOKUP_PATH, lookupPath);
    		Object handler = lookupHandler(lookupPath, request);
            ...
            return handler;
        }
        
        // 路径封装handler
        @Nullable
    	protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
    		// Direct match?
    		Object handler = this.handlerMap.get(urlPath);
        	if (handler != null) {
    			// Bean name or resolved handler?
    			if (handler instanceof String) {
    				String handlerName = (String) handler;
    				handler = obtainApplicationContext().getBean(handlerName);
    			}
    			validateHandler(handler, request);
    			return buildPathExposingHandler(handler, urlPath, urlPath, null);
    		}
        }
        
        // 方法执行前后拦截器创建
        protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
    			String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) {
    		HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
    		chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
    		if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
    			chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
    		}
    		return chain;
    	}
        
        // 相关拦截器添加
        protected HandlerExecutionChain getHandlerExecutionChain(Object handler,HttpServletRequest request) {
    		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
    				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
    		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
    			if (interceptor instanceof MappedInterceptor) {
    				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
    				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
    					chain.addInterceptor(mappedInterceptor.getInterceptor());
    				}
    			}
    			else {
    				chain.addInterceptor(interceptor);
    			}
    		}
    		return chain;
    	}
    }
    
  • HandlerAdapter:根据找到的handler执行对应的方法

    public interface HandlerAdapter {
    
        // 该适配器是否能支持指定处理器
        boolean supports(Object handler);
    
        // 执行处理逻辑,返回 ModelAndView
        @Nullable
        ModelAndView handle(
            HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    
        // 请求的目标资源最近一次的修改时间
        long getLastModified(HttpServletRequest request, Object handler);
    
    }
    
    public abstract class AbstractHandlerMethodAdapter 
        extends WebContentGenerator implements HandlerAdapter, Ordered {
            
        ...
        @Override
    	@Nullable
    	public final ModelAndView handle(
            HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    		return handleInternal(request, response, (HandlerMethod) handler);
    	}
        
        @Nullable
    	protected abstract ModelAndView handleInternal(
            HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) 
            throws Exception;
    	...
    }
    
    // 通过反射业务方法执行
    public class RequestMappingHandlerAdapter 
        extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
    	
        @Override
    	protected ModelAndView handleInternal(
            HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) 
            throws Exception {
    		ModelAndView mav;
    		// Execute invokeHandlerMethod in synchronized block if required.
    		if (this.synchronizeOnSession) {
    			HttpSession session = request.getSession(false);
    			if (session != null) {
    				Object mutex = WebUtils.getSessionMutex(session);
    				synchronized (mutex) {
    					mav = invokeHandlerMethod(request, response, handlerMethod);
    				}
    			}
    			else {
    				// No HttpSession available -> no mutex necessary
    				mav = invokeHandlerMethod(request, response, handlerMethod);
    			}
    		}
    		else {
    			// No synchronization on session demanded at all...
    			mav = invokeHandlerMethod(request, response, handlerMethod);
    		}
    
    		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
    			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
    				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
    			}
    			else {
    				prepareResponse(response);
    			}
    		}
    		return mav;
    	}
    }
    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值