Spring源码学习29

DispatcherServlet.doDispatch的mv = ha.handle(processedRequest, response, mappedHandler.getHandler());这个方法调用帮我们调用处理方法或者处理对象进行处理请求。

1.HanderAdapter.java

public interface HandlerAdapter {  
    //判断是否支持传入的Handler
    boolean supports(Object handler);  
    //用来使用Handler处理请求
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;  
    //用来获取资料的Last-Modified值
    long getLastModified(HttpServletRequest request, Object handler);  
}

2.常用的实现类如下图

除RequestMappingHandlerAdapter之外,HttpRequestHandlerAdapter、SimpleServletHandlerAdapter、SimpleControllerHandlerAdapter的实现非常简单;比如SimpleControllerHandlerAdapter

public class SimpleControllerHandlerAdapter implements HandlerAdapter {

	@Override
	public boolean supports(Object handler) {
		return (handler instanceof Controller);
	}

	@Override
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return ((Controller) handler).handleRequest(request, response);
	}

	@Override
	public long getLastModified(HttpServletRequest request, Object handler) {
		if (handler instanceof LastModified) {
			return ((LastModified) handler).getLastModified(request);
		}
		return -1L;
	}

}

直接强转为Controller类型并调用其handleRequest(request,response)方法处理request请求

3.RequestMappingHandlerAdapter该类实现了InitializingBean,该方法会在bean调用BeanPostProcessor的postProcessBeforeInitialize方法之后调用init-method方法之前被调用afterPropertiesSet进行初始化操作

@Override
	public void afterPropertiesSet() {
		// Do this first, it may add ResponseBody advice beans
		//首先执行此操作,它可能会添加ResponseBody 增强bean
		initControllerAdviceCache();

		if (this.argumentResolvers == null) {
			//获取默认的参数解析器
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		if (this.initBinderArgumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		if (this.returnValueHandlers == null) {
			//获取默认的returnValue处理器
			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
		}
	}

4.initControllerAdviceCache();该方法获取上下文中所有的使用了@ControllerAdvice注解的bean;@ControllerAdvice从字面意思理解就是对Controller(控制器)的增强,然后以key-beanType,value-Set<Method>的方式缓存这些对控制器增强bean的有@InitBinder和@ModelAttribute注解的方法,同时也缓存那些@ControllerAdvice并且实现了RequestBodyAdvice和ResponseBodyAdvice接口的bean

private void initControllerAdviceCache() {
		//获取应用上下文
		if (getApplicationContext() == null) {
			return;
		}
		if (logger.isInfoEnabled()) {
			logger.info("Looking for @ControllerAdvice: " + getApplicationContext());
		}
		//查找带有@ControllerAdvice的bean
		List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
		//给这些bean排序
		AnnotationAwareOrderComparator.sort(beans);
		List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>();

		for (ControllerAdviceBean bean : beans) {
			Class<?> beanType = bean.getBeanType();
			//找到bean带有@ModelAttribute注解但是没有@RequestMapping的方法 放到map里面
			Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
			if (!attrMethods.isEmpty()) {
				//放入缓存里
				this.modelAttributeAdviceCache.put(bean, attrMethods);
				if (logger.isInfoEnabled()) {
					logger.info("Detected @ModelAttribute methods in " + bean);
				}
			}
			//找到bean带有@InitBinder注解的方法
			Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
			if (!binderMethods.isEmpty()) {
				this.initBinderAdviceCache.put(bean, binderMethods);
				if (logger.isInfoEnabled()) {
					logger.info("Detected @InitBinder methods in " + bean);
				}
			}
			//如果bean实现了RequestBodyAdvice或者ResponseBodyAdvice接口
			boolean isRequestBodyAdvice = RequestBodyAdvice.class.isAssignableFrom(beanType);
			boolean isResponseBodyAdvice = ResponseBodyAdvice.class.isAssignableFrom(beanType);
			if (isRequestBodyAdvice || isResponseBodyAdvice) {
				requestResponseBodyAdviceBeans.add(bean);
				if (logger.isInfoEnabled()) {
					if (isRequestBodyAdvice) {
						logger.info("Detected RequestBodyAdvice bean in " + bean);
					}
					else {
						logger.info("Detected ResponseBodyAdvice bean in " + bean);
					}
				}
			}
		}

		if (!requestResponseBodyAdviceBeans.isEmpty()) {
			this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
		}
	}

getDefaultArgumentResolvers();初始化RequestMappingHandlerAdapter的默认的HandlerMethodArgumentResolver

/**
 *
 * 用于在给定请求的上下文中将方法参数解析为参数值的策略接口。
 */
public interface HandlerMethodArgumentResolver {

	/**
	 * 此解析程序是否支持给定的{@linkplain MethodParameter方法参数}。
	 */
	boolean supportsParameter(MethodParameter parameter);

	/**
	 * 将给定请求的方法参数解析为 参数值
	 */
	Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;

}
/**
	 * 返回要使用的参数解析器列表,包括内置解析器
	 *   和自定义解析器通过{@link #setCustomArgumentResolvers}提供。
	 */
	private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

		// Annotation-based argument resolution
		// 基于注解的参数解析器
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		resolvers.add(new PathVariableMethodArgumentResolver());
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		resolvers.add(new ServletModelAttributeMethodProcessor(false));
		resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new RequestHeaderMapMethodArgumentResolver());
		resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		resolvers.add(new RequestAttributeMethodArgumentResolver());

		// Type-based argument resolution
		// 基于类型的参数解析器
		resolvers.add(new ServletRequestMethodArgumentResolver());
		resolvers.add(new ServletResponseMethodArgumentResolver());
		resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RedirectAttributesMethodArgumentResolver());
		resolvers.add(new ModelMethodProcessor());
		resolvers.add(new MapMethodProcessor());
		resolvers.add(new ErrorsMethodArgumentResolver());
		resolvers.add(new SessionStatusMethodArgumentResolver());
		resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

		// Custom arguments
		//自定义解析器
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

		// Catch-all
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
		resolvers.add(new ServletModelAttributeMethodProcessor(true));

		return resolvers;
	}

getDefaultReturnValueHandlers();初始化RequestMappingHandlerAdapter的默认的HandlerMethodReturnValueHandler

/**
 *
 * 处理由处理程序的调用返回值的策略接口
 */
public interface HandlerMethodReturnValueHandler {

	/**
	 * 给定的{@linkplain MethodParameter return tpye方法}是否被当前处理器支持
	 */
	boolean supportsReturnType(MethodParameter returnType);

	/**
	 * 通过添加model的属性和设置视图处理返回值或者设置{@link 
     * ModelAndViewContainer#setRequestHandled}标识为true去表示相应已被直接处理
	 * 
	 */
	void handleReturnValue(Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;

}
/**
	 * 返回要使用的返回值处理程序列表,包括内置和
	 * 通过{@link #setReturnValueHandlers}提供的自定义处理程序。
	 */
	private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
		List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();

		// Single-purpose return value types
		handlers.add(new ModelAndViewMethodReturnValueHandler());
		handlers.add(new ModelMethodProcessor());
		handlers.add(new ViewMethodReturnValueHandler());
		handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters()));
		handlers.add(new StreamingResponseBodyReturnValueHandler());
		handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
				this.contentNegotiationManager, this.requestResponseBodyAdvice));
		handlers.add(new HttpHeadersReturnValueHandler());
		handlers.add(new CallableMethodReturnValueHandler());
		handlers.add(new DeferredResultMethodReturnValueHandler());
		handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));

		// Annotation-based return value types
		handlers.add(new ModelAttributeMethodProcessor(false));
		handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
				this.contentNegotiationManager, this.requestResponseBodyAdvice));

		// Multi-purpose return value types
		handlers.add(new ViewNameMethodReturnValueHandler());
		handlers.add(new MapMethodProcessor());

		// Custom return value types
		if (getCustomReturnValueHandlers() != null) {
			handlers.addAll(getCustomReturnValueHandlers());
		}

		// Catch-all
		if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
			handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
		}
		else {
			handlers.add(new ModelAttributeMethodProcessor(true));
		}

		return handlers;
	}

5.RequestMappingHandlerAdapter对请求的处理方法handleInternal(HttpServletRequest request,HttpServletResponse response,HandlerMethod handlerMethod)

@Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		//检测当前请求,验证请求合法性和session合法性
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		// 当前是否需要在同一个session中只能同步处理请求
		if (this.synchronizeOnSession) {
			//获取当前请求的session对象
			HttpSession session = request.getSession(false);
			if (session != null) {
				//获取当前session的同步锁
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				// 如果当前不存在session,则直接对HandlerMethod进行适配
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No synchronization on session demanded at all...
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		// 响应体不包含“Cache-Control”属性
		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			// 如果当前SessionAttribute中存在配置的attributes,则为其设置过期时间。
			// 这里SessionAttribute主要是通过@SessionAttribute注解生成的
			// 如果咱们有sessionAttributes 根据配置的cacheSecondsForSessionAttributeHandlers时长设置
			// Cache-Control属性
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				// 如果当前不存在SessionAttributes,则判断当前是否存在Cache-Control设置,
				// 如果存在,则按照该设置进行response处理,如果不存在,则设置response中的
				// Cache的过期时间为-1,即立即失效
				prepareResponse(response);
			}
		}

		return mav;
	}

该方法通过反射调用@Controller注解的bean的@RequestMapping的方法处理请求

  • a.检查请求合法性
  • /**
    	 * 检查给定的请求以获取支持的方法和必需的会话(如果有)。
    	 * @param request current HTTP request
    	 * @throws ServletException if the request cannot be handled because a check failed
    	 * @since 4.2
    	 */
    	protected final void checkRequest(HttpServletRequest request) throws ServletException {
    		// Check whether we should support the request method.
    		//我们不支持的请求类型抛出异常好了
    		String method = request.getMethod();
    		if (this.supportedMethods != null && !this.supportedMethods.contains(method)) {
    			throw new HttpRequestMethodNotSupportedException(method, this.supportedMethods);
    		}
    
    		// Check whether a session is required.
    		//如果需要session但是request没有session 抛出异常
    		if (this.requireSession && request.getSession(false) == null) {
    			throw new HttpSessionRequiredException("Pre-existing session required but none found");
    		}
    	}
  • b.是否需要在一个session中同步处理请求的判断,需要的话在一个session中只能按顺序处理相同的request请求
  • c.调用方法处理请求invokeHandlerMethod(request,response,handlerMethod);
  • c.response的"Cache-Control"属性处理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值