- 前言
- 一、DispatcherServlet
- 1、doServcie
- 2、doDispatch
- 3、getHandler
- 3、getHandlerAdapter
- 二、AbstractHandlerMapping
- 1、getHandler
- 三、RequestMappingHandlerMapping
- 1、afterPropertiesSet
- 2、initHandlerMethods
- 3、detectHandlerMethods
- 3、getHandlerInternal
- 4、lookupHandlerMethod
- 四、HttpRequestHandlerAdapter
- 1、supports
- 总结
办公设备租赁,深圳惠源.
前言
SpringMVC提供了统一的入口DispatcherServlet,有该Servlet分发到各处理器并返回视图,所以从DispatcherServlet开始分析即可。
一、DispatcherServlet
包含了SpringMVC 的整个执行流程,从DispatcherServlet的继承结构和方法调用栈可以看到最终会到DispatcherServlet的doServcie方法开始执行,所以从doServcie方法开始分析。
// 设置常用实例到request属性域
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
try {
// 分发处理请求
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
2、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 {
// 判断并处理文件请求-MultipartHttpServletRequest contentType.toLowerCase().startsWith("multipart/");
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 获取Handler
mappedHandler = getHandler(processedRequest);
// 获取处理器适配器,由于处理器不一样,有Controller类型,方法类型,所以需要由适配器来进行适配执行
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;
}
}
// 执行MVC拦截器得前置方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 执行handler业务方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 执行MVC拦截器得后置方法
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);
}
// 处理返回结果 ModelView
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 执行MVC 拦截器得afterCompletion
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、getHandler
遍历循环当前所有HandlerMapping获取处理器
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
3、getHandlerAdapter
获取处理器适配器,由于Handler,可能是Controller,也可能是Method,所以需要适配器进行适配。
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");
}
二、AbstractHandlerMapping
抽象AbstractHandlerMapping,由具体子类去实现getHandlerInternal,并封装返回执行器链
1、getHandlerpublic final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 获取具体得Handler,由子类实现,以下分析下通用得RequestMappingHandlerMapping
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved 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());
}
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;
}
三、RequestMappingHandlerMapping
1、afterPropertiesSet
由于RequestMappingHandlerMapping实现了InitializingBean,该方法在RequestMappingHandlerMapping实例化后会被Spring调用。设置urlHelper,pathMatche,建立url和method的映射
public void afterPropertiesSet() {
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setUrlPathHelper(getUrlPathHelper());
this.config.setPathMatcher(getPathMatcher());
this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
this.config.setContentNegotiationManager(getContentNegotiationManager()); // 执行父类方法
super.afterPropertiesSet();
}
public void afterPropertiesSet() {
initHandlerMethods();
}
2、initHandlerMethods
初始化HandlerMethod,建立url和method的映射
protected void initHandlerMethods() {
// 获取当前spring所有Bean名称,处理所有候选Bean
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
}
// 处理候选Bean
protected void processCandidateBean(String beanName) {
Class> beanType = null;
try {
// 获取Handler类型
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
// 判断是否Handler
if (beanType != null && isHandler(beanType)) {
// 处理并映射HandlerMethods
detectHandlerMethods(beanName);
}
}
// 判断是否Handler
protected boolean isHandler(Class> beanType) {
//判断是否有RequestMapping注解或者是否实现了Controller
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
3、detectHandlerMethods
protected void detectHandlerMethods(Object handler) {
// 获取Handler类型
Class> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
// 获取Handler真正的类型,存在被代理
Class> userType = ClassUtils.getUserClass(handlerType);
// 获取Handler中所有被@RequestMpping注解的方法
Map methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.metadataLookup) method -> {
try {
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
// 奖所有methods以HandlerMethod的方式注册到mappingRegistry中,
// HandlerMethod = Handler + Method
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
3、getHandlerInternal
获取HandlerMethod
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 获取截取host+contextPath后的url
// 比如请求url: http://localhost/backend/login,context-path为/backend,则lookupPath=/login
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
// 放入request域
request.setAttribute(LOOKUP_PATH, lookupPath);
// 加读锁
this.mappingRegistry.acquireReadLock();
try {
// 查找HandlerMethod,业务执行方法
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
// 释放读锁
this.mappingRegistry.releaseReadLock();
}
}
4、lookupHandlerMethod
查找HandlerMethod
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 获取截取host+contextPath后的url
// 比如请求url: http://localhost/backend/login,context-path为/backend,则lookupPath=/login
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
// 放入request域
request.setAttribute(LOOKUP_PATH, lookupPath);
// 加读锁
this.mappingRegistry.acquireReadLock();
try {
// 查找HandlerMethod,业务执行方法
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
// 释放读锁
this.mappingRegistry.releaseReadLock();
}
}
四、HttpRequestHandlerAdapter
执行器适配器
1、supports判断是否该适配器适配
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
总结
如果需要自己实现一个Starter
那只需要meta-INF/spring-autoconfigure-metadata.properties的资源,并org.springframework.boot.autoconfigure.EnableAutoConfiguration的值为自己写的Configuration即可,一般框架会区分start包和真正实现的jar,然后由start包依赖真正实现的jar包
办公设备租赁,深圳惠源.



