流程图
核心:
1.DispatcherServlet 前端控制器
2.HandlerMapping 处理器映射器
3.HandlerAdapter 处理器适配器
4.ViewResolver 视图解析器
5.View 视图对象
SpringMVC执行流程源码分析
前提要求
在controller中写好一个接口
@RestController
@RequestMapping("/wdl")
public class TestController {
@Autowired
private TestApplicationContextAware app;
@GetMapping("/test")
public void test(){
CareerService bean =(CareerService) app.getBean("programmerService");
bean.entry();
}
}
在项目启动的时候扫描controller中带有@GetMapping、PostMapping、DeleteMapping、PutMapping、RequestMapping的注解,并将这些注解所在的接口名称,接口地址、接口所在类封装到AbstractHandlerMethodMapping抽象类的register方法,在这个方法中会 封装好项目中所有的接口
源代码
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
...
private final AbstractHandlerMethodMapping<T>.MappingRegistry mappingRegistry = new AbstractHandlerMethodMapping.MappingRegistry();
//在这个方法会存项目中所有的接口,并保存到mappingRegistry 中,方便接口请求时从这里面获取对应的执行方法
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = AbstractHandlerMethodMapping.this.createHandlerMethod(handler, method);
this.validateMethodMapping(handlerMethod, mapping);
Set<String> directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping);
Iterator var6 = directPaths.iterator();
while(var6.hasNext()) {
String path = (String)var6.next();
this.pathLookup.add(path, 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) {
corsConfig.validateAllowCredentials();
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new AbstractHandlerMethodMapping.MappingRegistration(mapping, handlerMethod, directPaths, name, corsConfig != null));
} finally {
this.readWriteLock.writeLock().unlock();
}
}
}
在同一个类中,在接口请求之后,查询项目中这个接口的方法名、地址、所在类名
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList();
//这里就是从上面register注册的所有接口中获取本次请求的接口信息
List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
.....
}
``
`
接口请求源码分析
1、DispatcherServlet接收到请求之后由doDispatch方法进行接收请求
```java
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);//获取本次请求的接口执行者
if (mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
//get方法增加判断,Spring MVC中,我们发出请求,就会返回view,而实际上这样就引出了一个问题:我的请求如果没有任何改变的话,也就是说上次请求获得的静态资源是没有变化的。此时按照Spring MVC的机制,我们仍然返回了一套静态资源。显然这样增加了服务器的负载,以及网络带宽的使用。所以如果时间戳相同的情况下,从缓存中获取视图
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//开始执行具体的接口方法,底层用来反射
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);
}
}
}
//获取执行者
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
Iterator var2 = this.handlerMappings.iterator();
while(var2.hasNext()) {
HandlerMapping mapping = (HandlerMapping)var2.next();
//获取接口的执行者,调用的接口HandlerMapping接口的getHandler方法,这个接口默认的实现类是AbstractHandlerMapping,由这个类的getHandler方法去前的AbstractHandlerMethodMapping抽象类中获取已经在项目启动的时候已经封装好的所有接口信息
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}