Spring-MVC 对DispatcherServlet 完成初始化之后,下面看下一个http 请求是如何被分发到不同请求处理handlerMapping 。
在spring-mvc 中对于每种情形的http 访问,对由一个handlerMapping 进行处理,接下来先看下spring-mvc对于handlerMapping 是如何选择的?
请求进来: HttpServlet -->service 方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
可以看到根据请求的方式,进行不同的方法调用;doGet/doPost/doHead -->调用到FrameworkServlet 的doGet/doPost/doHead -->DispatcherServlet 的doService 方法:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 日志记录,进来 header 和 reqeust param 参数
this.logRequest(request);
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap();
Enumeration<?> attrNames = request.getAttributeNames();
label116:
while(true) {
String attrName;
do {
if (!attrNames.hasMoreElements()) {
break label116;
}
attrName = (String)attrNames.nextElement();
} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
// 存储相关属性对象
// 存储容器对象
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);
}
RequestPath previousRequestPath = null;
if (this.parseRequestPath) {
previousRequestPath = (RequestPath)request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
ServletRequestPathUtils.parseAndCache(request);
}
try {
// 分发
this.doDispatch(request, response);
} finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot);
}
if (this.parseRequestPath) {
ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
}
}
}
接下来进入 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;
Exception dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// 根据请求路径 获取 HandlerExecutionChain ,如果没有找到则报404
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
// 没有根据request 找到对应的handlerMapping 报404
this.noHandlerFound(processedRequest, response);
return;
}
// mappedHandler.getHandler() 有可能是bean 对象 也有可能是一个方法 所有使用object 接收
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
// 调用HandlerInterceptor的applyPreHandle方法,如果返回false,那么调用流程结束
// 遍历所有的拦截器 调用 applyPreHandle 方法,返回true 则拦截器链路依次向后执行
// 如果某一个拦截器applyPreHandle 返回false 则调用方法执行后的 afterCompletion
// 拦截器所有的 applyPreHandle 都通过 通过 返回true 则继续向下执行
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 调用adaper 中handle 的方法 得到ModelAndView 对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 设置默认视图名称
this.applyDefaultViewName(processedRequest, mv);
// 调用拦截器的 applyPostHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
// 先渲染视图,渲染完毕调用拦截器的afterCompletion 方法
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
这里面需要注意的就是 this.getHandler(processedRequest); 对于handlerMapping 的选择,以及 this.getHandlerAdapter(mappedHandler.getHandler()); 根据handlerMapping 选择对应的 HandlerAdapter ;以及 ha.handle(processedRequest, response, mappedHandler.getHandler()); 使用HandlerAdapter 去调用方法并封装返回值结果;
如果是json 字符串则 得到的返回结果是null ,如果是页面则返回页面的视图;
对于HandlerAdapter 的获取,以及返回值的包装分别放到 二、 HandlerAdapter 的获取:进行介绍,下面看下对于 handlerMapping 的获取;
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
Iterator var2 = this.handlerMappings.iterator();
// 依次遍历 handlerMappings 默认 会有 BeanNameUrlHandlerMapping 根据请求路径找bean,
// RequestMappingHandlerMapping 根据请求路径找方法,
// RouterFunctionMapping 根据请求路径找方法 3个 handlerMapping
while(var2.hasNext()) {
HandlerMapping mapping = (HandlerMapping)var2.next();
// 从中根据请求的request 获取到对应的类和方法
// 将handler 进行HandlerExecutionChain 封装(如果有对方法的拦截则加入拦截器 )
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
// 如果不为空则匹配到了
return handler;
}
}
}
return null;
}
如果我们没有自定义 HandlerMapping 则会取到系统默认的BeanNameUrlHandlerMapping ,RequestMappingHandlerMapping ,RouterFunctionMapping 然后遍历通过其方法内部的 getHandler 方法 然后找到能够处理请求的HandlerMapping ,将其包装成HandlerExecutionChain 对象并返回,如果没有找到则返回null;
在这里需要注意的是默认的三个HandlerMapping bean 是分别对于不同情形http 的处理:
HandlerAdapter 的作用比较重要,它即负责了对方法调用前请求参数的封装,又负责了对于返回值的封装;
this.getHandlerAdapter(mappedHandler.getHandler()) 根据 HandlerMapping 取回 对应的 HandlerAdapter :
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
// 获取handlerAdapters 进行遍历
Iterator var2 = this.handlerAdapters.iterator();
while(var2.hasNext()) {
HandlerAdapter adapter = (HandlerAdapter)var2.next();
if (adapter.supports(handler)) {
// 进行判断 调用不同的adaper 的 supports 方法 进行类型的判断
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
如果我们没有自定义 HandlerAdapter 那么就遍历默认的HandlerAdapter 根各个类中的 supports 方法 找到最匹配的HandlerAdapter,下面看下默认的4个HandlerAdapter 的作用:
如果是实现了Controller/HttpRequestHandler 接口则进入到对应的adaper 后最后调用handle 中的handleRequest 进行方法的调用;如果是HandlerFunction 则根据route 绑定的路由进行方法的调用;这两种都不需要对传入的参数进行解析和封装,所有下面具体看下我们项目中经常用到的,RequestMappingHandlerAdapter 对请求的参数进行解析,然后包装为方法所需要的数据类型;
下面看下RequestMappingHandlerAdapter 下的 handleInternal 方法:是如何对参数进行解析的
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
// request 检查 可以自己定义RequestMappingHandlerAdapter 的bean 对请求的方式和session 做检验
this.checkRequest(request);
ModelAndView mav;
if (this.synchronizeOnSession) {
// session 同步锁,两个请求是同一个session 则发送过来的请求进行串行处理
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized(mutex) {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
// 方法调用
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader("Cache-Control")) {
if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
} else {
this.prepareResponse(response);
}
}
return mav;
}
this.invokeHandlerMethod(request, response, handlerMethod); 中进行了参数的解析,方法的调用,返回值的封装;
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
Object result;
try {
// 找出当前类和全局设置的 @InitBinder 并记录到集合中 对其请求参数进行转换 如 张三 转为 user 对象
WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod);
// 根据当前对象生成 ModelFactory 取当前类的@SessionAttributes("name")
// 定义的key 如name 生成Model 对象 并设置这些值 为Model 放入一些session key--value 的值
ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod);
// 设置参数解析器(解析参数),设置返回值解析器(返回的数据进行转换,如转换json 返回页面)
// 默认会提供一些参数的解析 会在adapter 完成一些默认的参数解析 ;对方方法的参数进行注解解析
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
// 返回的类型解析器
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
// 设置binderFactory 执行方法时 需要使用它完成 参数类型的转换
invocableMethod.setDataBinderFactory(binderFactory);
// spring 用来解析方法参数的名称 使用ASM ,解析方法参数的名称
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
// 每次执行方法都会 新建一个 ModelAndViewContainer 对象
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
// 添加属性
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
// mavContainer中已经有model对象了,现在进行初始化
// 比如执行@ModeLAttribute的方法,把attribute添加到model中
// 比如从session获取某些attribute添加到model中 (@SessionAttributes)
// 注意:并没有把request parameter、request attribute添加到model中
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()) {
result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
LogFormatUtils.traceDebug(this.logger, (traceOn) -> {
String formatted = LogFormatUtils.formatValue(result, !traceOn);
return "Resume with async result [" + formatted + "]";
});
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
// 初始化model完成之后,对方法进行调用,方法返回的结果 也会放在 mavContainer中
invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
if (!asyncManager.isConcurrentHandlingStarted()) {
// 对封装的ModeLAndView进行处理,主要是判断当前请求是否进行了重定向,如果进行了重定向
// 还会判断是否需要将FLashAttributes封装到新的请求中
ModelAndView var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
return var15;
}
result = null;
} finally {
webRequest.requestCompleted();
}
return (ModelAndView)result;
}
invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]); 进入 ServletInvocableHandlerMethod 下的 invokeAndHandle 方法:对于方法的调用:
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 执行方法,并得到方法返回值,就是我们方法中的返回值,没有额外的处理,所以后面是要处理的
// 但是这个方法中就涉及到参数绑定,比如要判断方法需要哪些参数,分别该传什么值,也是比较复杂的
Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
this.setResponseStatus(webRequest);
if (returnValue == null) {
if (this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) {
this.disableContentCachingIfNecessary(webRequest);
mavContainer.setRequestHandled(true);
return;
}
} else if (StringUtils.hasText(this.getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
// 如果返回类型的是Map,那就用MapMethodProcessor处理
// 如果返回类型的是ModelAndView,那就用ModeLAndViewMethodReturnValueHandler处理
// 如果返回类型上有@ResponseBody,那就用RequestResponseBodyMethodProcessor处理,重点
// 如果返回类型是String,那就用ViewNameMethodReturnValueHandler处理,重点
// 等等,有很多种
this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
} catch (Exception var6) {
if (logger.isTraceEnabled()) {
logger.trace(this.formatErrorForReturnValue(returnValue), var6);
}
throw var6;
}
}
方法的执行:
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 获取方法的参数
Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
// 执行方法
return this.doInvoke(args);
}
方法参数获取及参数封装:
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
//获取改方法的所有参数
MethodParameter[] parameters = this.getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
} else {
Object[] args = new Object[parameters.length];
for(int i = 0; i < parameters.length; ++i) {
// 遍历方法参数
MethodParameter parameter = parameters[i];
// 方法的参数名称 解析
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
// 获取方法参数的名字 providedArgs 是null
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] == null) {
// 看是否有HandlerMethodArgumentResolver能不能解析当前参数
// 只要有一个HandlerMethodArgumentResolver能解析,能就用它来解析
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
// 解析参数 获取到要传个参数的值
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
} catch (Exception var10) {
if (logger.isDebugEnabled()) {
String exMsg = var10.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
throw var10;
}
}
}
// 方法参数的值数组 返回
return args;
}
}
this.resolvers.resolveArgument 方法解析参数:
@Nullable
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
// 参数解析器
HandlerMethodArgumentResolver resolver = this.getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
} else {
// 解析参数并返回值 Mode类型对应的就是ModeTMethodProcessor
// 参数前面有@RequestParam,对应的就是RequestParamMethodArgumentResolver
// 参数前面有RequestAttribute,对应的就是RequestAttributeMethodArgumentResolverI
// 如果参数没什么特殊的,默认对应的也是RequestParamMethodArgumentResolver
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
}
解析器 对参数的值进行解析进入到 AbstractNamedValueMethodArgumentResolver 的 resolveArgument:
@Nullable
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
// 获取参数的名字 如果使用@RequestParam (“name”) string test
// 定义了 则使用定义的,如果没有定义则使用 方法参数的名字
NamedValueInfo namedValueInfo = this.getNamedValueInfo(parameter);
MethodParameter nestedParameter = parameter.nestedIfOptional();
// 占位符填充
Object resolvedName = this.resolveEmbeddedValuesAndExpressions(namedValueInfo.name);
if (resolvedName == null) {
throw new IllegalArgumentException("Specified name must not resolve to null: [" + namedValueInfo.name + "]");
} else {
// 根据参数 得到对应的值
Object arg = this.resolveName(resolvedName.toString(), nestedParameter, webRequest);
if (arg == null) {
// 如果根据参数没有获取到value
if (namedValueInfo.defaultValue != null) {
// 如果 指定了默认值 进行解析
arg = this.resolveEmbeddedValuesAndExpressions(namedValueInfo.defaultValue);
} else if (namedValueInfo.required && !nestedParameter.isOptional()) {
// 如果没有默认值,则判断 required 为true 并且非Optional 类型则报错
this.handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
}
// 对null 进行处理: 如果是boolean 类型则返回false 否则 抛异常
arg = this.handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
} else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
// 如果参数是 空字符串 ,但是有默认值,使用默认值
arg = this.resolveEmbeddedValuesAndExpressions(namedValueInfo.defaultValue);
}
// 进行类型转换
if (binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, (Object)null, namedValueInfo.name);
try {
// 类型转换 如将字符串 转换为 java 对象
arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
} catch (ConversionNotSupportedException var11) {
throw new MethodArgumentConversionNotSupportedException(arg, var11.getRequiredType(), namedValueInfo.name, para meter, var11.getCause());
} catch (TypeMismatchException var12) {
throw new MethodArgumentTypeMismatchException(arg, var12.getRequiredType(), namedValueInfo.name, parameter, var12.getCause());
}
if (arg == null && namedValueInfo.defaultValue == null && namedValueInfo.required && !nestedParameter.isOptional()) {
// 如果最后没有找到值,并且required 是true 则抛异常
this.handleMissingValueAfterConversion(namedValueInfo.name, nestedParameter, webRequest);
}
}
this.handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
return arg;// 返回参数
}
}
至此我们已经看到了mvc 是如何完成对参数的解析,这里进行下小结:
this.returnValueHandlers.handleReturnValue 通过返回值 以及返回值的类型 来筛选 返回值处理器的方法,然后进行调用;
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 根据返回值和返回值类型 筛选出合适的 方法返回值处理器器
HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
} else {
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
}
``
this.selectHandler(returnValue, returnType) 筛选方法返回值解析器:
```java
@Nullable
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
boolean isAsyncValue = this.isAsyncReturnValue(value, returnType);
Iterator var4 = this.returnValueHandlers.iterator();
HandlerMethodReturnValueHandler handler;
do {
do {
if (!var4.hasNext()) {
return null;
}
handler = (HandlerMethodReturnValueHandler)var4.next();
} while(isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler));
} while(!handler.supportsReturnType(returnType));
return handler;
}
这里会先判断 是否又被@ResponseBody 注解标注,有则说明返回json 是字符串,需要用json字符串的处理器处理;没有则说明是一个页面,需要用到其它的处理器处理;所以接下来分为两类进行分析;
1) 返回的是json字符串:
此种情况 会使用 RequestResponseBodyMethodProcessor 中的 handleReturnValue 进行处理:
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
// 先进行下标记,改请求已经完成,不需要额外的去找页面,和渲染;
mavContainer.setRequestHandled(true);
// 获取请求的 输出对象:
ServletServerHttpRequest inputMessage = this.createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = this.createOutputMessage(webRequest);
// 将结果写出到body中
this.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
2) 返回的是页面:
在获取到请求的处理结果之后,会进入到DispatcherServlet 下的processDispatchResult 对于页面进行处理,此时 ModelAndView 非空;
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
this.logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException)exception).getModelAndView();
} else {
Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
mv = this.processHandlerException(request, response, handler, exception);
errorView = mv != null;
}
}
if (mv != null && !mv.wasCleared()) {
// 对视图解析
this.render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("No view rendering, null ModelAndView returned.");
}
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
}
}
}
通过render 方法,对视图进行解析,会拿到视图文件的路径 然后返回给到浏览器;
1)路径的解析:
@GetMapping("/{id}/{name}")
@ResponseBody
public String testGet(HttpServletRequest request, @PathVariable("name") String name, @PathVariable("id") String id) {
System.out.println("name = " + name);
System.out.println("id = " + id);
return "success";
}
解析请求 后设置map key 为{“xxx”} 中对应的xxx ,value 对应的值;在解析请求参数时 通过PathVariable定义的名称 从map 中进行获取;
2) Request 参数解析:
@GetMapping("/test")
@ResponseBody
public String testGet1(@RequestParam("test") String test) {
System.out.println("test = " + test);
return "success";
}
@GetMapping("/test/map")
@ResponseBody
public Map testGet2(@RequestParam Map map) {
System.out.println("map = " + map);
Map<String, Object> oneMap = new HashMap<>();
oneMap.put("name", "lisi");
return oneMap;
}
参数类型是map 则,解析参数后都放入到map 中;
参数类型是基本的数类型 ,按照RequestParam 定义的名称去获取参数值,如果RequestParam没有设置则根据 参数名称去获取;
3)RequestAttribute 参数:
@GetMapping("/test/attribute")
@ResponseBody
public String testGet3(@RequestAttribute String name) {
System.out.println("name = " + name);
return "success";
}
获取所有的请求attribute 遍历根据名称获取;
4)RequestHeader 参数:
@GetMapping("/test/header")
@ResponseBody
public String testGet4(@RequestHeader("token") String header) {
System.out.println("header = " + header);
return "success";
}
获取所有的请求头 ,然后遍历 根据 名称去获取;
5) ResponseBody 参数:
@PostMapping("post")
@ResponseBody
public String testPost1(@RequestBody Map map) {
System.out.println("map = " + map);
return "success";
}
ResponseBody 获取request 的body 流,然后获取转换器,然后通过转换器对body 内容进行转换;
本文主要对DispatcherServlet 的请求分发,请求参数,请求结果的包装返回 在原码层面进行了流程上的分析;