文章目录
- 组件
- ServletWebRequest
- WebDataBinderFactory
- ModelFactory
- InvocableHandlerMethod
- ServletInvocableHandlerMethod
- ModelAndViewContainer
- RequestMappingHandlerAdapter
- SessionAttributesHandler
- Handler处理流程
组件
ServletWebRequest
包装servlet的request和response
public class ServletWebRequest extends ServletRequestAttributes implements NativeWebRequest {
private final HttpServletRequest request;
@Nullable
private HttpServletResponse response;
@Nullable
private volatile HttpSession session;
}
WebDataBinderFactory
生成DataBinder实例的工厂,DataBinder将request请求的参数绑定到java Bean对象
public interface WebDataBinderFactory {
WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName)
throws Exception;
}
ModelFactory
在真实处理器调用前初始化Model(数据模型Map),在调用结束后更新Model值。
public final class ModelFactory {
private final List<ModelMethod> modelMethods = new ArrayList<>();
// 请求数据绑定工厂
private final WebDataBinderFactory dataBinderFactory;
// session属性处理
private final SessionAttributesHandler sessionAttributesHandler;
}
// 内部类
private static class ModelMethod {
//
private final InvocableHandlerMethod handlerMethod;
private final Set<String> dependencies = new HashSet<>();
}
InvocableHandlerMethod
继承HandlerMethod,提供参数解析器和参数名寻找
public class InvocableHandlerMethod extends HandlerMethod {
// 请求数据绑定工厂
private WebDataBinderFactory dataBinderFactory;
// 方法参数解析
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
// 参数名寻找,生成NamedValueInfo时使用
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
}
ServletInvocableHandlerMethod
继承InvocableHandlerMethod,在其基础上增加返回值处理器, 在方法级别支持@ResponseStatus注解。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
}
ModelAndViewContainer
记录模型和视图的信息,持有一个默认的模型,当发生重定向时使用redirectModel代替默认模型记录数据。
public class ModelAndViewContainer {
private boolean ignoreDefaultModelOnRedirect = false;
@Nullable
private Object view;
private final ModelMap defaultModel = new BindingAwareModelMap();
@Nullable
private ModelMap redirectModel;
// 为true返回重定向模型
private boolean redirectModelScenario = false;
@Nullable
private HttpStatus status;
// 请求是否处理完成
private boolean requestHandled = false;
}
RequestMappingHandlerAdapter
@RequestMapping注解使用的适配器
// 将属性存入Session中
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
// @SessionAttributes注解的处理,类+@SessionAttributes处理器
private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64);
// 实际处理类缓存的@ModelAttribute
private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);
// 消息转换器 @RequestBody @ResponseBody 使用
private List<HttpMessageConverter<?>> messageConverters;
SessionAttributesHandler
@SessionAttributes注解的处理器,@SessionAttributes将指定的Model中的键值对添加至session中
public class SessionAttributesHandler {
private final Set<String> attributeNames = new HashSet<>();
private final Set<Class<?>> attributeTypes = new HashSet<>();
private final Set<String> knownAttributeNames = Collections.newSetFromMap(new ConcurrentHashMap<>(4));
private final SessionAttributeStore sessionAttributeStore;
}
Handler处理流程
- DispatcherServlet中调用ha.handle(processedRequest, response, mappedHandler.getHandler());调用适配器处理请求,这里分析常用的RequestMappingHandlerAdapter。首先进入AbstractHandlerMethodAdapter的handle方法
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
- 调用RequestMappingHandlerAdapter的handleInternal方法,首先检查是否支持给定请求,判断是否要求session同步,调用invokeHandlerMethod方法
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
// 检查是否支持给定的请求
checkRequest(request);
// 如果要求在Session上同步
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 {
// 通过反射调用真实处理器
mav = invokeHandlerMethod(request, response, handlerMethod);
}
// 如果不包含Cache-Control
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
- RequestMappingHandlerAdapter的invokeHandlerMethod方法调用,生成ServletInvocableHandlerMethod来调用处理器的方法,首先将request和response包装为ServletWebRequest,然后初始化两个工厂分别处理@InitBinder和@ModelAttribute注解。通过handlerMethod创建一个ServletInvocableHandlerMethod,为其设置参数和返回值解析器,创建MAV容器,反射调用方法,获得返回值。
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
// 用ServletWebRequest来包装request和response
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
// 用于从web请求参数到JavaBean对象的数据绑定,处理@InitBinder
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
// 协助在控制器方法调用之前初始化model,处理完成后更新model,处理@ModelAttribute
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 通过handlerMethod创建一个ServletInvocableHandlerMethod来反射执行
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
// 设置参数解析器
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
// 设置返回值解析器
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
// 用于解析方法和构造器的参数名
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
// MAV容器,关联视图和数据模型
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
// 为默认model设置数据
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
// 异步处理
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
// 反射调用处理器方法
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 获得处理器返回
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
- 调用ServletInvocableHandlerMethod的invokeAndHandle,对返回值进行判断,如果返回值为null或者实际处理器设置了响应码直接返回,否则调用返回值处理器来处理返回值。
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// 设置响应状态
setResponseStatus(webRequest);
// 处理器已经完全处理了请求无MAV返回,或者响应码被设置了
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
disableContentCachingIfNecessary(webRequest);
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
// 处理器处理完成后有返回且状态码未被修改
mavContainer.setRequestHandled(false);
try {
// 调用返回值解析器处理返回值
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
···异常处理
}
- 调用InvocableHandlerMethod的invokeForRequest解析方法的传入参数
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 参数解析
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
return doInvoke(args);
}
- 调用InvocableHandlerMethod的doInvoke方法,就是调用bridgedMethod的invoke反射方法来执行
protected Object doInvoke(Object... args) throws Exception {
// 设置方法绕过检查
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 反射调用处理器方法
return getBridgedMethod().invoke(getBean(), args);
}
····抛出异常
}