栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring源码学习篇6 - DispatcherServlet 基本工作流程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring源码学习篇6 - DispatcherServlet 基本工作流程

配置DispatcherServlet

Servlet3.0之后, Servlet可以被动态监测到,web.xml不再是必须的,一般的servlet可以使用@WebServlet,除了添加注解,也可编程配置。WebApplicationInitializer的实现类在应用部署的时候会被执行,可以再WebApplicationInitializer.onStartup中配置Spring的DispatcherServlet:

public class MyWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
        webApplicationContext.register(AppConfig.class);

        DispatcherServlet dispatcherServlet = new DispatcherServlet(webApplicationContext);
        ServletRegistration.Dynamic registration = servletContext.addServlet("springApp", dispatcherServlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app
protected void initHandlerMethods() {
	for (String beanName : getCandidateBeanNames()) {
		if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
			processCandidateBean(beanName);
		}
	}
	handlerMethodsInitialized(getHandlerMethods());
}

protected void processCandidateBean(String beanName) {
	Class beanType = null;
	try {
		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);
		}
	}
	if (beanType != null && isHandler(beanType)) {
		detectHandlerMethods(beanName);
	}
}

@Override
protected boolean isHandler(Class beanType) {
	return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
			AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

可以看会对所有的Bean进行处理,如果Bean含有Controller或者RequestMapping注解,那么对所有的 RequestMapping注解的方法进行处理:

  1. 根据@RequestMapping注解,构造RequestMappingInfo
    protected RequestMappingInfo createRequestMappingInfo(
    	RequestMapping requestMapping, @Nullable RequestCondition customCondition) {
    
    RequestMappingInfo.Builder builder = RequestMappingInfo
    		.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
    		.methods(requestMapping.method())
    		.params(requestMapping.params())
    		.headers(requestMapping.headers())
    		.consumes(requestMapping.consumes())
    		.produces(requestMapping.produces())
    		.mappingName(requestMapping.name());
    if (customCondition != null) {
    	builder.customCondition(customCondition);
    }
    return builder.options(this.config).build();
    }
    
  2. 构造HandlerMethod,它主要包含两个重要属性:bean 以及对应的含有@RequestMapping的Method
  3. 获取DirectPath, 并记录DirectPath与RequestMappingInfo的关联
  4. 记录方法名,与HandlerMethod对象的关联
  5. 记录 handlerMethod 与 CorsConfiguration配置对象的关联
  6. 记录RequestMappingInfo 与 MappingRegistratio对象的关联
    //MappingRegistration
    public MappingRegistration(T mapping, HandlerMethod handlerMethod,
    	@Nullable Set directPaths, @Nullable String mappingName, boolean corsConfig) {
    
    Assert.notNull(mapping, "Mapping must not be null");
    Assert.notNull(handlerMethod, "HandlerMethod must not be null");
    this.mapping = mapping;
    this.handlerMethod = handlerMethod;
    this.directPaths = (directPaths != null ? directPaths : Collections.emptySet());
    this.mappingName = mappingName;
    this.corsConfig = corsConfig;
    }
    
处理请求

当客户端发起请求的时候,如果满足DispatcherServlet的处理路径,那么经过doService,交由doDispatch进行处理请求,主要处理逻辑如下:

processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
	noHandlerFound(processedRequest, response);
	return;
}

// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
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;
}

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

if (asyncManager.isConcurrentHandlingStarted()) {
	return;
}

applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
大致的处理流程如下

第一步是根据请求,获取对应的HandlerMethod

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	String lookupPath = initLookupPath(request);
	this.mappingRegistry.acquireReadLock();
	try {
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
	}
	finally {
		this.mappingRegistry.releaseReadLock();
	}
}

基本流程是获取到请求的path, 然后得到RequestMappingInfo,最后取得HandlerMethod

第二步,是构造HandlerExecutionChain,主要是添加合适的拦截器

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
	HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
			(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

	for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
		if (interceptor instanceof MappedInterceptor) {
			MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
			if (mappedInterceptor.matches(request)) {
				chain.addInterceptor(mappedInterceptor.getInterceptor());
			}
		}
		else {
			chain.addInterceptor(interceptor);
		}
	}
	return chain;
}

第三步,处理CorsConfiguration

protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
		HandlerExecutionChain chain, @Nullable CorsConfiguration config) {

	if (CorsUtils.isPreFlightRequest(request)) {
		HandlerInterceptor[] interceptors = chain.getInterceptors();
		return new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
	}
	else {
		chain.addInterceptor(0, new CorsInterceptor(config));
		return chain;
	}
}

第四步,确定HandlerAdapter,各个adapter是否可以处理当前handler的判断也比较简单,比如AbstractHandlerMethodAdapter 基本只要handler是HandlerMethod实例可以。

// AbstractHandlerMethodAdapter.java
@Override
public final boolean supports(Object handler) {
	return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

第五步,优先调用各拦截器的preHandle方法,如果有个拦截器返回false,那么结束处理

第六步,通过HandlerAdapter的实例调用具体的bean,像RequestMappingHandlerAdapter.handleInternal,并得到ModelAndView

第七步,调用各拦截器的postHandle方法

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/292436.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号