在上两篇中,我们简单的介绍了web模式下bean的注入以及ioc容器的创建时间。那么,在容器创建之后,servletContext会持有ioc容器,以便在后面去处理业务逻辑
这一篇我们就仔细分析一下springmvc是怎么处理请求,又是如何去使用ioc容器中的bean的
我们都知道,springmvc也是基于servlet去处理请求。那么他就应该符合servlet的执行流程与规范
在使用servlet的时候,我们需要在web.xml文件中去配置servlet的名字与类路径以及他需要处理的请求。同样,我们也为DispatcherServlet做了相关配置
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
//简单说明一下
<url-pattern>/</url-pattern> 会匹配到/login这样的路径型url,不会匹配到模式为*.jsp这样的后缀型url
<url-pattern>/*</url-pattern> 会匹配所有url:路径型的和后缀型的url(包括/login,*.jsp,*.js和*.html等)
所以我们的DispatcherServlet会处理我们的所有的请求。 servlet处理请求都是在service()里面
dispatcherServlet的请求处理
FrameworkServlet 431 line
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求方式
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
//进行请求判断 对于 get post put delete options trace 等进行处理 略过
if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
super.service(request, response);
} else {
this.processRequest(request, response);
}
}
最终都会走到这个方法
FrameworkServlet 487 line
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//构建了一系列参数
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = this.buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
//将本次请求的信息保存在threadLocal中
this.initContextHolders(request, localeContext, requestAttributes);
try {
//业务处理 往下看
this.doService(request, response);
} catch (IOException | ServletException var16) {
failureCause = var16;
throw var16;
} catch (Throwable var17) {
failureCause = var17;
throw new NestedServletException("Request processing failed", var17);
} finally {
this.resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
this.logResult(request, response, (Throwable)failureCause, asyncManager);
this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
}
}
业务处理
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
......
//设置一些请求信息
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
if (this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
try {
//请求分发
this.doDispatch(request, response);
}
......
}
请求分发
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 {
//如果请求带有文件 则进行request的一个简单包装
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//获取handler 也就是我们的控制器?? 直接就获取了?
//那么handler什么时候注册的呢?稍后介绍
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
//不存在对应handler 返回404
this.noHandlerFound(processedRequest, response);
return;
}
//handler是从HandlerMapping中拿到的 根据handler获取HandlerAdapter
//HandlerAdapter也是具体执行handle的执行类 也就是业务方法的执行类
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
//请求方式 请求类型
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;
}
}
//调用拦截器,判断这个请求是否需要被拦截!!!这里涉及到了拦截器哦
//DispatcherServlet持有拦截器的引用
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//调用handle方法,这里会生成modelAndView 后续分析
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
//业务执行之后,再次调用拦截器的post方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
......异常处理哦
//这里会进行结果处理 也就是视图渲染...... 后续分析
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
获取handlerMapping 从中获取handler
DispatcherServlet 628 line
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
//从handlerMappings中取 handlerMappings是一个arrayList
Iterator var2 = this.handlerMappings.iterator();
while(var2.hasNext()) {
HandlerMapping mapping = (HandlerMapping)var2.next();
//获取hander 往下看
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
AbstarctHandlerMapping 224 line
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//获取handler 等会研究 继续往里面看
Object handler = this.getHandlerInternal(request);
if (handler == null) {
handler = this.getDefaultHandler();
}
if (handler == null) {
return null;
} else {
if (handler instanceof String) {
String handlerName = (String)handler;
handler = this.obtainApplicationContext().getBean(handlerName);
}
//包装成HandlerExecutionChain 这里面会将HandlerMapping中的一些拦截器拿到HandlerExecutionChain中
HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);
//看样子是跨域相关配置的处理
if (this.hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null;
CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
config = config != null ? config.combine(handlerConfig) : handlerConfig;
executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
}
//返回
return executionChain;
}
}
获取handler
AbstractHandlerMethodMapping 201 line
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//获取请求uri
String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
//获取一个独占锁
this.mappingRegistry.acquireReadLock();
HandlerMethod var4;
try {
//获取handler 往下看
HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);
var4 = handlerMethod != null ? handlerMethod.createWithResolvedBean() : null;
} finally {
this.mappingRegistry.releaseReadLock();
}
return var4;
}
还是这个文件 218 line
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList();
//这一块其实也就是在本bean中,以一个map来保存接口以及接口处理的类与方法
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
//将匹配的handler保存在上面创建的matches集合中
this.addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
AbstractHandlerMethodMapping<T>.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
//如果一个接口有多个方法与其对应 直接报错
if (matches.size() > 1) {
Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request));
matches.sort(comparator);
bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
(CorsUtils.isPreFlightRequest(request)) {
//如果请求方式是Origin 则返回一个默认的hander 因为这个请求来判断是否可以跨域
return PREFLIGHT_AMBIGUOUS_MATCH;
}
AbstractHandlerMethodMapping<T>.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)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.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
//将一些信息放置在请求域中
this.handleMatch(bestMatch.mapping, lookupPath, request);
//返回匹配到的hander
return bestMatch.handlerMethod;
} else {
//没有匹配到,直接返回null
return this.handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
稍微总结一下:
到目前位置,已经拿到对应的hander
下一篇分析 springmvc是什么时候将接口与对应的业务处理bean来结合放置在HandlerMapping中的map里面
以及springmvc如何使用hander来获取ModelAndView。以及渲染时怎么进行的