用户发送请求,经过前端控制器Dispacherservlet(Controller的核心)将url交给处理器映射器HandlerMapping处理
处理器映射器HandlerMapping处理url,返回HandlerExecutionChain(可能包含拦截器,一定包含自定义的Controller(handler))
前端控制器将Controller交给处理器适配器HandlerAdapter处理,处理完成后,返回MV对象(ModelAndView)
前端控制器将MV交给视图解析器处理ViewResolver,处理的过程:将MV拆分成Model和view两个对象,并且将model渲染到view视图上,并且将view返回给前端控制器。
最后,前端控制器将视图响应给用户
用户发送请求到DispatchServlet,请求查询Handle到处理器映射器(HandleMapping),此时返回一个处理器拦截器链到dispatchServlet之后再请求执行Handler到处理器适配器去选择相应处理器(就是Controller),处理器返回一个ModelAndView之后再转达到dispatchServlet,dispatchServlet在向视图解析器(ViewResolver)请求解析视图,之后视图解析器返回一个View对象给dispatchServlet,前端控制器在渲染视图,之后在响应给用户。
首先我们大家都知道SpringMvc是通过DispatcherServlet
这个类和web.xml配置中的拦截来接管Tomcat中的请求的。所有想看所有关于控制器(打了Controller注解)的细节基本都是在DispatcherServlet这个类中,下面我们就来看看DispatcherServlet
中的dodispatch
方法:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//可以看出springMVC最先初始化的是文件上传组件
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//为request请求找到对应的处理器
(源码在下一个三级标题)
mappedHandler = getHandler(processedRequest);
//非空判断
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//
很明显这是为了拿到处理器适配器了
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//
获取Method,并且在下面代码就开始和Method比较了
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
真正执行处理器适配的方法,返回ModelAndView对象了
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//是否需要解析view name ,渲染时需要。
applyDefaultViewName(processedRequest, mv);
//执行处理器的postHandler方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
//下一步的方法就是拿着ModelAndView去render(渲染)了,至此程序跑完,页面也出来了(这一步也有视图解析器工作流程)
//将map和model参数保存在request中是在internResourceView的exposeModelRequestAttribute
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//此时会拿到所有的处理器映射器进行匹配
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
//通过处理器映射器去找到对应的处理器(三级标题为getHandler)
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//通过这个方法来找到处理器,也就是Controller
Object handler = getHandlerInternal(request);
//很神奇spring做了两次null处理
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// 如果是一个beanName那我就把你变成handler
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//这里就是上面过程略写中的处理器适配器返回处理器执行链,
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
//打印日志处理
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
//条件说明:如果以上方法走下来,拿到的handler不是我们要的,那么SpringMVC会在以下语句中重新搞一下这个handler,把它变成我们想要的对象
if (hasCorsConfigurationSource(handler)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
/*
* getLookupPathForRequest:
* 首先通过getUrlPathHelper得到一个UrlPathHelper
* 返回给定请求的映射查找路径,如果适用,则在当前Servlet映射中,否则返回Web应用程序中的映射查找路径。
* 如果在RequestDispatcher包含中调用,则检测包含请求URL。也就是解析你写的映射路径
* (UrlPathHelper就是专门解析路径的)
*
*
*/
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
//此时你可以看到lookupPath变成了"/list",并且在request的attribute属性中保存起来
request.setAttribute(LOOKUP_PATH, lookupPath);
//这一步就是映射器注册器尝试获取读锁,线程安全考虑
this.mappingRegistry.acquireReadLock();
try {
//这一步就是查找当前请求(list)的最佳匹配处理程序方法。如果找到多个匹配项,则选择最佳匹配项。
//(也就是如果找到多个匹配项那就也只要一个list.get(0)),此时拿到了HandlerMathod对象
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
//释放锁操作
this.mappingRegistry.releaseReadLock();
}
}
通过断点可以看出,我们写的控制器以及@Requestmapping方法的所有信息,参数信息、路径信息、返回值信息都在这个类中保存
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
//通过UrlpathHelp解析路劲
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;
}
protected boolean hasCorsConfigurationSource(Object handler) {
return super.hasCorsConfigurationSource(handler) ||
(handler instanceof HandlerMethod && this.mappingRegistry.getCorsConfiguration((HandlerMethod) handler) != null) ||
handler.equals(PREFLIGHT_AMBIGUOUS_MATCH);
}
==========super.hasCorsConfigurationSource(handler)============
protected boolean hasCorsConfigurationSource(Object handler) {
if (handler instanceof HandlerExecutionChain) {
handler = ((HandlerExecutionChain) handler).getHandler();
}
return (handler instanceof CorsConfigurationSource || this.corsConfigurationSource != null);
}
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
public interface HandlerAdapter {
//是否支持这个处理器
boolean supports(Object handler);
//进行处理,并返回对应的ModelAndView
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
//拿到最后修改的Head
long getLastModified(HttpServletRequest request, Object handler);
}
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// 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 {
// 我的方法在这里执行的,这里就会用到argumentResolver参数解析器以及returnValueHandler返回值处理器
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
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);
......
//通过这个方法就可以到封装好的ModelAndView了,之后返回出去
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
你在Controller方法参数可以写多少种类型就取决于该类型是否有对应argumentResolver去解析
同理,你控制器方法返回值就是通过这个解析的
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//这一步走完,就会跳到你写的Controller的方法中了,这里面是通过动态代理来执行的,此时方法返回的ModelAndView也在这了
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
//设置响应状态
setResponseStatus(webRequest);
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);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
//请求处理结束之后,其他都是处理ModelAndView这个对象携带的数据
modelFactory.updateModel(webRequest, mavContainer);
if (mavContainer.isRequestHandled()) {
return null;
}
ModelMap model = mavContainer.getModel();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
if (request != null) {
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
}
return mav;
}
public class ModelAndViewContainer {
private boolean ignoreDefaultModelOnRedirect = false;
@Nullable
private Object view;
private final ModelMap defaultModel = new BindingAwareModelMap();
@Nullable
private ModelMap redirectModel;
private boolean redirectModelScenario = false;
@Nullable
private HttpStatus status;
private final Set<String> noBinding = new HashSet<>(4);
private final Set<String> bindingDisabled = new HashSet<>(4);
private final SessionStatus sessionStatus = new SimpleSessionStatus();
private boolean requestHandled = false;
public ModelMap getModel() {
if (useDefaultModel()) {
return this.defaultModel;
}
else {
if (this.redirectModel == null) {
this.redirectModel = new ModelMap();
}
return this.redirectModel;
}
}
/**
* 将所有属性复制到model
*/
public ModelAndViewContainer addAllAttributes(@Nullable Map<String, ?> attributes) {
getModel().addAllAttributes(attributes);
return this;
}
/**
* copy属性,name相同优先复制
*/
public ModelAndViewContainer mergeAttributes(@Nullable Map<String, ?> attributes) {
getModel().mergeAttributes(attributes);
return this;
}
/**
* 从Model中删除属性
*/
public ModelAndViewContainer removeAttributes(@Nullable Map<String, ?> attributes) {
if (attributes != null) {
for (String key : attributes.keySet()) {
getModel().remove(key);
}
}
return this;
}
/**
* Model是否包含给定的属性名
*/
public boolean containsAttribute(String name) {
return getModel().containsAttribute(name);
}
}