spring mvc相关源码剖析

来源:互联网 发布:软件开发部 编辑:程序博客网 时间:2024/06/05 08:24
 
 spring 启动分两个方式,
 1. 通过监听的方式来启动(ContextLoaderListener)
 2. 通过DispatcherServlet来启动
 
 监听启动优先于servlet启动。
 
  在spring 容器启动的时候,会触发ContextRefreshListener这个监听,这个监听负责初始化一些spring mvc相关的数据
  
  如果系统应用是没有通过监听的方式启动,仅单纯的使用servlet启动,那么在servlet  init()方法里面也同样会做这个事情
  通过这个参数来控制 refreshEventReceived 。以避免和监听的方式冲突
  
 
  private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {

public void onApplicationEvent(ContextRefreshedEvent event) {
FrameworkServlet.this.onApplicationEvent(event);
}
}
public void onApplicationEvent(ContextRefreshedEvent event) {
this.refreshEventReceived = true;
onRefresh(event.getApplicationContext());
}
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}

/**
 * Initialize the strategy objects that this servlet uses.
 * <p>May be overridden in subclasses in order to initialize further strategy objects.
 */
protected void initStrategies(ApplicationContext context) {  
            initMultipartResolver(context);//文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析  
            initLocaleResolver(context);//本地化解析  
            initThemeResolver(context);//主题解析  
            initHandlerMappings(context);//通过HandlerMapping,将请求映射到处理器  
            initHandlerAdapters(context);//通过HandlerAdapter支持多种类型的处理器  
            initHandlerExceptionResolvers(context);//如果执行过程中遇到异常,将交给HandlerExceptionResolver来解析  
            initRequestToViewNameTranslator(context);//直接解析请求到视图名  
            initViewResolvers(context);//通过viewResolver解析逻辑视图到具体视图实现  
            initFlashMapManager(context);//flash映射管理器  
    }
这里主要讲一下initHandlerMappings , 此处是为了初始化映射解析器
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
//这个值可以在web.xml里面做控制,默认值为true 
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
//从spring容器里面获取HandlerMapping实例的对象,默认我们spring mvc中使用的是RequestMapping 
//所以这里的HandlerMapping一定会有这个RequestMappingHandlerMapping这个实例
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
OrderComparator.sort(this.handlerMappings);
}
}
else {
try {
//此处为指定固定的Bean来做这个映射解析器,bean name = handlerMapping
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}

// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
//加入通过以上的手段都无法获取到映射解析器的话,那么系统会加载默认的解析器,
//该方法内部会加载和dispatchServlet同目录下的DispatchServlet.proprerties
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}
//initHandlerAdapters 这个方法里面初始化的代码逻辑都差不多。
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;

if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
OrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
}

// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
}
}
}
// 上面说到RequestMapperingHandlerMappering, 该解析器替代了之前的基于注解的解析器
继承关系如下:
RequestMapperingHandlerMappering》RequestMappingInfoHandlerMapping》
AbstractHandlerMethodMapping》AbstractHandlerMapping》WebApplicationObjectSupport
在AbstractHandlerMethodMapping 类中有一个方法
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
//获取spring 容器中所有的beanName
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));

for (String beanName : beanNames) {
//首先看一下isHandler这个方法的实现,看下方源码
if (isHandler(getApplicationContext().getType(beanName))){
//如果注解都有,那么没问题,走到下一个方法里面去,看看具体实现
detectHandlerMethods(beanName);
}
}
//这是一个空方法,不用管它
handlerMethodsInitialized(getHandlerMethods());
}
protected boolean isHandler(Class<?> beanType) {
//通过传入的class,判断这个类是否有Controller注解获取有RequerMapping注解
return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
}
protected void detectHandlerMethods(final Object handler) {
//根据handler这个字符串,从spring容器里面获取class
Class<?> handlerType =
(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());

// Avoid repeated calls to getMappingForMethod which would rebuild RequestMatchingInfo instances
//定义一个method的集合
final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
final Class<?> userType = ClassUtils.getUserClass(handlerType);
//这行代码的意思,就是通过类,然后反射,拿到这个类下面所有的方法 ,通过一个MethodFilter 这个方法来
//过滤方法,主要是获取拥有requestMapping的方法
Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
public boolean matches(Method method) {
//这个方法的核心就是在这里,看具体实现 ,该方法在下方
T mapping = getMappingForMethod(method, userType);
if (mapping != null) {
mappings.put(method, mapping);
return true;
}
else {
return false;
}
}
});
//循环带有requestMapping的方法
for (Method method : methods) {
//注册方法
registerHandlerMethod(handler, method, mappings.get(method));
}
}
//获取方法上的requestMappingInfo
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = null;
//判断该方法上面是否存在RequestMapping 这个注解
RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
if (methodAnnotation != null) { //存在注解,则进入该if , 否则return null 
RequestCondition<?> methodCondition = getCustomMethodCondition(method);
//该方法主要是获取requestMapping注解上的一些属性数据,封装到requestMappingInfo里面去
info = createRequestMappingInfo(methodAnnotation, methodCondition);
//判断类上是否存在requestMapping注解
RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
if (typeAnnotation != null) {
//如果存在,那么需要将类上的注解和方法上的注解进行合并
RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
}
}
return info;
}
//创建requestMapping
protected RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition) {
String[] patterns = resolveEmbeddedValuesInPatterns(annotation.value());
return new RequestMappingInfo(
new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),
this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions),
new RequestMethodsRequestCondition(annotation.method()),
new ParamsRequestCondition(annotation.params()),
new HeadersRequestCondition(annotation.headers()),
new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),
new ProducesRequestCondition(annotation.produces(), annotation.headers(), getContentNegotiationManager()),
customCondition);
}
//注册方法
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
//封装HandlerMethod  , 里面有method, BeanFactory , applicationContext等信息
HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);
HandlerMethod oldHandlerMethod = this.handlerMethods.get(mapping);
if (oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod)) {
throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean() +
"' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '" +
oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped.");
}
//将requestMappingInfo 为键, handlerMethod为value, 封装HandlerMethods
this.handlerMethods.put(mapping, newHandlerMethod);
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod);
}
//获取映射上的路径
Set<String> patterns = getMappingPathPatterns(mapping);
for (String pattern : patterns) {
if (!getPathMatcher().isPattern(pattern)) {
//将请求路径和requMappinginfo放入map中,这个Map是一个多值Map, 
一个key可以对应多个值得,防止同一个路径,但是有GET方法和POST方法的区分。
this.urlMap.add(pattern, mapping);
}
}
}
//以上的代码,是spring容器针对spring mvc初始化的一些代码,现在开始讲http请求过程,spring mvc是如何处理的
首先一个请求过来,首先进的是doService 方法,之后是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 {
//验证请求是否是上传文件的
processedRequest = checkMultipart(request);
multipartRequestParsed = processedRequest != request;

// Determine handler for the current request.
//获取方法执行的handler , 此处主要是通过handleMappings ,然后gethandle
通过请求地址,从requestMappingHandlerMapping这个对象的urlMap中,获取requestMappingInfo ,
通过requestMappingInfo从handlerMethods中获取handlerMethod , 之后获取拦截器,获取拦截器的执行列表。
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
// 表示 no mapped found 
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 = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//执行拦截器列表里面的preHandle方法,如果有一个执行失败,那么则return ,这也是为什么prHandle方法可以阻止请求的执行
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

try {
// Actually invoke the handler.
//执行方法 , 返回modleAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
}
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
原创粉丝点击