前言
描述: springmvc相关文章如下:
【1】SpringMVC 入口及父子容器源码解析
【2】SpringMVC 请求调用流程源码解析
1 工程概述
1.1 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<groupId>org.example</groupId>
<artifactId>rosh-spring</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.2.8.RELEASE</spring.version>
</properties>
<dependencies>
<!--上下文-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${
spring.version}</version>
</dependency>
<!--切面-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${
spring.version}</version>
</dependency>
<!--事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${
spring.version}</version>
</dependency>
<!--spring-mvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${
spring.version}</version>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- 日志相关依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.10</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.2</version>
</dependency>
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>
</project>
1.2 配置文件
public class RoshWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* 父容器配置文件
*/
@Override
protected Class<?>[] getRootConfigClasses() {
System.out.println("RoshWebInitializer invoke getRootConfigClasses");
return new Class<?>[]{
SpringRootConfig.class};
}
/**
* 子容器配置
*/
@Override
protected Class<?>[] getServletConfigClasses() {
System.out.println("RoshWebInitializer invoke getServletConfigClasses");
return new Class<?>[]{
SpringServletConfig.class};
}
/**
*拦截请求(静态资源、js、css.......)
*/
@Override
protected String[] getServletMappings() {
return new String[]{
"/"};
}
}
/**
* 父容器配置文件,只扫描service
*/
@Configuration
@ComponentScan(value = "com.rosh.service")
public class SpringRootConfig {
}
/**
* 子容器配置文件,仅仅扫描@Controller、@RestController
*/
@Configuration
@ComponentScan(value="com.rosh",includeFilters={
@ComponentScan.Filter(type= FilterType.ANNOTATION,classes={
Controller.class, RestController.class})
},useDefaultFilters=false)
@EnableWebMvc
public class SpringServletConfig {
}
1.3 service
@RestController
@RequestMapping("/hello")
public class HelloController {
@Autowired
private HelloService helloService;
@GetMapping("")
public String printHello() {
return helloService.printHello();
}
}
1.4 Controller
@RestController
@RequestMapping("/hello")
public class HelloController {
@Autowired
private HelloService helloService;
@GetMapping("")
public String printHello() {
return helloService.printHello();
}
}
1.5 启动tomcat
2 DispatcherServlet
概述: springmvc 核心类,在创建子容器时,创建DispatcherServlet,处理url请求、响应等。当web发起请求时,调用doDispatch方法。
(1) 根据request获取相应的HandlerExecutionChain(包含handlerMethod、拦截器等)
(2) 根据handlerMethod获取相应的handlerAdapter(handler方法是具体调用)
(3) 前置过滤
(4) handlerAdapter.handler()具体调用
(5) 中置过滤
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 {
/**
* 文件上传
*/
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
/**
* 【重点】 根据request 获取相应的HandlerExecutionChain
*/
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
/**
* 根据handler获取adapter
*/
// Determine handler adapter for the current request.
/**
* 根据handlerMethod 获取相应的 handlerAdapter
*/
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
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.
/**
* 具体调用Controller 方法
*/
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
/**
* 中置过滤
*/
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
3 mappedHandler 源码解析
概念:handlerMethod 具体处理方法
requestMappingInfo @RequestMapping相关配置
3.1 过程解析
3.1.1 handlerMapping解析
描述: handlerMapping解析,获取相应的HandlerExecutionChain
3.1.2 获取handlerMethod
描述: 根据request获取handlerMethod
描述: 根据uri获取相应的hadnlerMethod,核心方法。
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
/**
* 根据url获取mapping匹配关系
*/
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
//如果mapping不为空
if (directPathMatches != null) {
/**
* 根据mapping、request匹配相应的handlerMethod
*/
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
/**
* 如果matches不为空
*/
if (!matches.isEmpty()) {
//获取第一个方法
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
bestMatch = matches.get(0);
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
/**
* 如果匹配多个方法,获取第二个,并且第二个和第一个一样,那么报异常
*/
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
/**
* request设置值
*/
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
3.2 初始化映射关系的建立
描述: 在匹配过程中,AbstractHandlerMethodMapping.lookupHandlerMethod方法,根据uri获取requestMappingInfo、在根据requestMappingInfo获取handlerMethod,那么映射关系是如何建立的呢?
描述: 遍历所有的beanNames
描述: 如果当前类有Controller、RequestMapping注解,那么遍历所有方法,并且用getMappingForMethod进行方法匹配,如果匹配成功,创建RequestMappingInfo对象。
描述: 点进去,遍历方法,调用匿名函数进行方法匹配。
描述: 匿名匹配源码解析,带有@RequestMapping注解的方法创建RequestMappingInfo对象,并且判断该类是否带有@RequestMapping,如果带有,那么进行合并,返回RequestMappingInfo对象。
@Override
@Nullable
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
/**
* 带有@RequestMapping注解方法,然后注解里面的内容封装成对象
*/
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
/**
* 类上面的@RequestMapping注解也封装成对象
*/
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
/**
* 把方法上面的注解属性结合到类上面的RequestMappingInfo对象中
*/
info = typeInfo.combine(info);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
}
}
return info;
}
描述: 创建映射关系。
public void register(T mapping, Object handler, Method method) {
// Assert that the handler method is not a suspending one.
if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
Class<?>[] parameterTypes = method.getParameterTypes();
if ((parameterTypes.length > 0) && "kotlin.coroutines.Continuation".equals(parameterTypes[parameterTypes.length - 1].getName())) {
throw new IllegalStateException("Unsupported suspending handler method detected: " + method);
}
}
this.readWriteLock.writeLock().lock();
try {
/**
* 【1】 创建handlerMethod
*/
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
/**
* 【2】 验证唯一
*/
validateMethodMapping(handlerMethod, mapping);
/**
* 【3】创建映射,uri-> handlerMethod
*/
this.mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
/**
* 【4】 建立的是url 和 requestMappingInfo的映射
*/
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
/**
* 【5】 跨域
*/
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
3.3 总结
(1) AbstractHandlerMethodMapping 在依赖注入完成后调用afterPropertiesSet方法,会建立url->requestMappingInfo->handlerMethod的映射关系。
(2) 当请求过来时,DispatcherServlet调用doDispatch方法处理,第一步根据handMapping获取相应的HandlerExecutionChain,其核心逻辑就是根据request获取requestMappingInfo,在根据requestMappingInfo获取handlerMethod最后封装成HandlerExecutionChain对象。
4 具体调用
描述: 调用赋值
@Nullable
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);
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()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
LogFormatUtils.traceDebug(logger, traceOn -> {
String formatted = LogFormatUtils.formatValue(result, !traceOn);
return "Resume with async result [" + formatted + "]";
});
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
/**
* 【重点】方法调用
*/
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
描述: 核心调用方法
转载:https://blog.csdn.net/qq_34125999/article/details/115290357