spring mvc 一次请求过程跟踪
项目背景
Spring Boot
- 主方法
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UploadApplication {
public static void main(String[] args) {
SpringApplication.run(UploadApplication.class, args);
}
}
- Controller
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by wdmyong on 2017/9/2.
*/
@RequestMapping("/test")
@RestController
public class TestController {
@RequestMapping("/index")
public String testIndex() {
return "testIndex";
}
}
- 项目启动
spring boot 启动方式很简单,以Application运行(或者debug)即可,eclipse的话应该还有以spring boot application方式。
跟踪方式
就是debug方式启动之后打断点
- 1. 根据查询资料在启动时在RequestMappingHandlerMapping中打断点
public void afterPropertiesSet() {
this.config = new BuilderConfiguration();
this.config.setUrlPathHelper(this.getUrlPathHelper());
this.config.setPathMatcher(this.getPathMatcher());
this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
this.config.setContentNegotiationManager(this.getContentNegotiationManager());
super.afterPropertiesSet(); // 这里打断点点进去,到2
}
- 2. RequestMappingHandlerMapping父类RequestMappingInfoHandlerMapping的父类AbstractHandlerMethodMapping
public void afterPropertiesSet() {
this.initHandlerMethods();
}
// initHandlerMethods方法中调用的以下部分
if(beanType != null && this.isHandler(beanType)) {
this.detectHandlerMethods(beanName);
}
// 然后detectHandlerMethods继续
protected void detectHandlerMethods(Object handler) {
// 前后代码我省略了
this.registerHandlerMethod(handler, invocableMethod, mapping);
}
// registerHandlerMethod继续
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
// 调用到mappingRegistry.register, mappingRegistry定义
private final AbstractHandlerMethodMapping<T>.MappingRegistry mappingRegistry = new AbstractHandlerMethodMapping.MappingRegistry();
// AbstractHandlerMethodMapping中register方法
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = AbstractHandlerMethodMapping.this.createHandlerMethod(handler, method);
this.assertUniqueMethodMapping(handlerMethod, mapping);
if(AbstractHandlerMethodMapping.this.logger.isInfoEnabled()) {
AbstractHandlerMethodMapping.this.logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
this.mappingLookup.put(mapping, handlerMethod); // 这将mapping和handlerMethod的关系保存了
List<String> directUrls = this.getDirectUrls(mapping);
Iterator var6 = directUrls.iterator();
while(var6.hasNext()) {
String url = (String)var6.next();
this.urlLookup.add(url, mapping);
}
String name = null;
if(AbstractHandlerMethodMapping.this.getNamingStrategy() != null) {
name = AbstractHandlerMethodMapping.this.getNamingStrategy().getName(handlerMethod, mapping);
this.addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = AbstractHandlerMethodMapping.this.initCorsConfiguration(handler, method, mapping);
if(corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new AbstractHandlerMethodMapping.MappingRegistration(mapping, handlerMethod, directUrls, name));
} finally {
this.readWriteLock.writeLock().unlock();
}
}
- 3. 通过以上两步基本应该知道是通过mappingLookup来找到我们请求url里面path对应的处理方法的
请求跟踪
- 1. 在DispatcherServlet中打断点,因为不管是spring boot里面,还是自己配置的spring mvc项目中入口都在这
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 {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest); // 通过mapping找到处理的handlerMethod,见1-1
if(mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); // 通过handler再来找到对应的适配器,见1-2
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if(isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if(this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if(!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 见1-3
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if(asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
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);
}
}
}
- 1-1. mappedHandler = this.getHandler(processedRequest);
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
/*
* private List<HandlerMapping> handlerMappings;
* 保存了一个HandlerMapping的列表
* 每一项都是处理你mapping到handler的一个HandlerMapping
* 本文调试中使用的是RequestMappingHandlerMapping@5034
* 然后通过下面注释位置获取handler
*/
Iterator var2 = this.handlerMappings.iterator();
HandlerExecutionChain handler;
do {
if(!var2.hasNext()) {
return null;
}
HandlerMapping hm = (HandlerMapping)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
// 通过getHandler拿到handler
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
-1-2. HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
/*
* private List<HandlerAdapter> handlerAdapters;
* 保存了一个HandlerAdapter的列表
* 找到一个能够支持传入handler的适配器,见注释
* 本文调试过程为RequestMappingHandlerAdapter@4325
*/
Iterator var2 = this.handlerAdapters.iterator();
HandlerAdapter ha;
do {
if(!var2.hasNext()) {
throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
ha = (HandlerAdapter)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler adapter [" + ha + "]");
}
} while(!ha.supports(handler)); // 直至找到能够支持的ha
return ha;
}
-1-3. AbstractHandlerMethodAdapter
// 父类模板方法
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return this.handleInternal(request, response, (HandlerMethod)handler);
}
protected abstract ModelAndView handleInternal(HttpServletRequest var1, HttpServletResponse var2, HandlerMethod var3) throws Exception; // 实现跟在后面
// class: RequestMappingHandlerAdapter
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
this.checkRequest(request);
ModelAndView mav;
if(this.synchronizeOnSession) {
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 {
// 这一行就是得到结果的行,见1-3-1
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;
}
-1-3-1. RequestMappingHandlerAdapter
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
Object result;
try {
WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
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()) {
result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if(this.logger.isDebugEnabled()) {
this.logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
// 见1-3-2
invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
if(!asyncManager.isConcurrentHandlingStarted()) {
ModelAndView var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
return var15;
}
result = null;
} finally {
webRequest.requestCompleted();
}
return (ModelAndView)result;
}
-1-3-2. ServletInvocableHandlerMethod
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 见1-3-3
Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
this.setResponseStatus(webRequest);
if(returnValue == null) {
if(this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
} else if(StringUtils.hasText(this.getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
try {
this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
} catch (Exception var6) {
if(this.logger.isTraceEnabled()) {
this.logger.trace(this.getReturnValueHandlingErrorMessage("Error handling return value", returnValue), var6);
}
throw var6;
}
}
-1-3-3. InvocableHandlerMethod
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
if(this.logger.isTraceEnabled()) {
this.logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(this.getMethod(), this.getBeanType()) + "' with arguments " + Arrays.toString(args));
}
// 见1--3-4
Object returnValue = this.doInvoke(args);
if(this.logger.isTraceEnabled()) {
this.logger.trace("Method [" + ClassUtils.getQualifiedMethodName(this.getMethod(), this.getBeanType()) + "] returned [" + returnValue + "]");
}
return returnValue;
}
-1-3-4 InvocableHandlerMethod
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(this.getBridgedMethod());
try {
// 这一行去调用的controller
return this.getBridgedMethod().invoke(this.getBean(), args);
} catch (IllegalArgumentException var5) {
this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args);
String text = var5.getMessage() != null?var5.getMessage():"Illegal argument";
throw new IllegalStateException(this.getInvocationErrorMessage(text, args), var5);
} catch (InvocationTargetException var6) {
Throwable targetException = var6.getTargetException();
if(targetException instanceof RuntimeException) {
throw (RuntimeException)targetException;
} else if(targetException instanceof Error) {
throw (Error)targetException;
} else if(targetException instanceof Exception) {
throw (Exception)targetException;
} else {
String text = this.getInvocationErrorMessage("Failed to invoke handler method", args);
throw new IllegalStateException(text, targetException);
}
}
}
- 2. 现在开始返回了哈
原路返回的这里就不多说了
- 3. 说点返回过程中跟踪到的个人觉得有用的信息
见上文中的1-3-2中,this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);进行返回值的处理
// HandlerMethodReturnValueHandlerComposite
public void handleReturnValue(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);
}
}
// RequestResponseBodyMethodProcessor
public void handleReturnValue(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);
this.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
//AbstractMessageConverterMethodProcessor
protected <T> void writeWithMessageConverters(T value, MethodParameter returnType, ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
Object outputValue;
Class valueType;
Object declaredType;
if(value instanceof CharSequence) {
outputValue = value.toString();
valueType = String.class;
declaredType = String.class;
} else {
outputValue = value;
valueType = this.getReturnValueType(value, returnType);
declaredType = this.getGenericType(returnType);
}
HttpServletRequest request = inputMessage.getServletRequest();
List<MediaType> requestedMediaTypes = this.getAcceptableMediaTypes(request);
List<MediaType> producibleMediaTypes = this.getProducibleMediaTypes(request, valueType, (Type)declaredType);
if(outputValue != null && producibleMediaTypes.isEmpty()) {
throw new IllegalArgumentException("No converter found for return value of type: " + valueType);
} else {
Set<MediaType> compatibleMediaTypes = new LinkedHashSet();
Iterator var12 = requestedMediaTypes.iterator();
MediaType selectedMediaType;
Iterator var14;
MediaType mediaType;
while(var12.hasNext()) {
selectedMediaType = (MediaType)var12.next();
var14 = producibleMediaTypes.iterator();
while(var14.hasNext()) {
mediaType = (MediaType)var14.next();
if(selectedMediaType.isCompatibleWith(mediaType)) {
compatibleMediaTypes.add(this.getMostSpecificMediaType(selectedMediaType, mediaType));
}
}
}
if(compatibleMediaTypes.isEmpty()) {
if(outputValue != null) {
throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes);
}
} else {
List<MediaType> mediaTypes = new ArrayList(compatibleMediaTypes);
MediaType.sortBySpecificityAndQuality(mediaTypes);
selectedMediaType = null;
var14 = mediaTypes.iterator();
while(var14.hasNext()) {
mediaType = (MediaType)var14.next();
if(mediaType.isConcrete()) {
selectedMediaType = mediaType;
break;
}
if(mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) {
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
break;
}
}
if(selectedMediaType != null) {
selectedMediaType = selectedMediaType.removeQualityValue();
var14 = this.messageConverters.iterator();
while(var14.hasNext()) {
HttpMessageConverter<?> messageConverter = (HttpMessageConverter)var14.next();
if(messageConverter instanceof GenericHttpMessageConverter) {
if(((GenericHttpMessageConverter)messageConverter).canWrite((Type)declaredType, valueType, selectedMediaType)) {
outputValue = this.getAdvice().beforeBodyWrite(outputValue, returnType, selectedMediaType, messageConverter.getClass(), inputMessage, outputMessage);
if(outputValue != null) {
this.addContentDispositionHeader(inputMessage, outputMessage);
((GenericHttpMessageConverter)messageConverter).write(outputValue, (Type)declaredType, selectedMediaType, outputMessage);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Written [" + outputValue + "] as \"" + selectedMediaType + "\" using [" + messageConverter + "]");
}
}
return;
}
} else if(messageConverter.canWrite(valueType, selectedMediaType)) {
outputValue = this.getAdvice().beforeBodyWrite(outputValue, returnType, selectedMediaType, messageConverter.getClass(), inputMessage, outputMessage);
if(outputValue != null) {
this.addContentDispositionHeader(inputMessage, outputMessage);
messageConverter.write(outputValue, selectedMediaType, outputMessage);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Written [" + outputValue + "] as \"" + selectedMediaType + "\" using [" + messageConverter + "]");
}
}
return;
}
}
}
if(outputValue != null) {
throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
}
}
}
}
// 见上文1中this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, 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.isDebugEnabled()) {
this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling");
}
if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
if(mappedHandler != null) {
// 调用了拦截哭的interceptor.afterCompletion(request, response, this.handler, ex);
mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
}
}
}
最后,过了FilterChain。调用了StandardContextValve中的
public final void invoke(Request request, Response response) throws IOException, ServletException {
MessageBytes requestPathMB = request.getRequestPathMB();
if(!requestPathMB.startsWithIgnoreCase("/META-INF/", 0) && !requestPathMB.equalsIgnoreCase("/META-INF") && !requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0) && !requestPathMB.equalsIgnoreCase("/WEB-INF")) {
Wrapper wrapper = request.getWrapper();
if(wrapper != null && !wrapper.isUnavailable()) {
try {
response.sendAcknowledgement();
} catch (IOException var6) {
this.container.getLogger().error(sm.getString("standardContextValve.acknowledgeException"), var6);
request.setAttribute("javax.servlet.error.exception", var6);
response.sendError(500);
return;
}
if(request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
wrapper.getPipeline().getFirst().invoke(request, response);
} else {
response.sendError(404);
}
} else {
response.sendError(404);
}
}
后续还应该有挺多内容,在(二)中更吧,一写的比较粗糙。