经过上一篇(https://www.jianshu.com/p/117c12f5f334
)的分析,DispatcherServlet已经初始化完毕,本篇文章将分析获取处理器执行链的过程。
入口代码AccountController类:
@Controller
@RequestMapping("/account")
public class AccountController {
@Autowired
AccountService accountService;
@RequestMapping("/findAll")
public @ResponseBody List<AccountSSM> findAll(){
List<AccountSSM> list = accountService.findAll();
return list;
}
@RequestMapping("/findOne")
public @ResponseBody AccountSSM findAccount(String name,int id){
AccountSSM accountSSM = new AccountSSM();
accountSSM.setId(id);
accountSSM.setName(name);
return accountSSM;
}
}
配置一个拦截器
public class MyIntercepter implements HandlerInterceptor {
/**
*预处理方法
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @return true 放行;false 不放行
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("MyIntercepter执行了preHandle()方法");
return true;
}
/**
* 后处理方法,Controller方法执行之后,success.jsp执行之前
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("MyIntercepter执行了postHandle()方法");
}
/**
* success.jsp执行之后执行,最后执行的方法
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("MyIntercepter执行了afterCompletion()方法");
}
}
springmvc.xml配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<!--要拦截的方法-->
<mvc:mapping path="/account/findOne"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="com.ljessie.ssm_demo.intercepter.MyIntercepter"></bean>
</mvc:interceptor>
</mvc:interceptors>
DispatherServlet处理请求的过程如图所示:
请求处理流程.png
断点打到FrameworkServlet#doGet中
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
FrameworkServlet#processRequest
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
//省略其他代码
try {
doService(request, response);
}
//省略其他代码
}
DispatcherServlet#doService
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//省略其他代码
try {
doDispatch(request, response);
}
//省略其他代码
}
DispatcherServlet#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);
// 获取HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 获取适配器
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;
}
}
//应用前置拦截器
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 处理Handler方法
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);
}
}
}
}
1、检查是否上传文件
checkMultipart()不是这里分析的重点,大致看一下就行。
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
"this typically results from an additional MultipartFilter in web.xml");
}
else if (hasMultipartException(request) ) {
logger.debug("Multipart resolution failed for current request before - " +
"skipping re-resolution for undisturbed error rendering");
}
else {
try {
return this.multipartResolver.resolveMultipart(request);
}
catch (MultipartException ex) {
if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) {
logger.debug("Multipart resolution failed for error dispatch", ex);
// Keep processing error dispatch with regular request handle below
}
else {
throw ex;
}
}
}
}
// If not returned before: return original request.
return request;
}
2、获取HandlerExecutionChain
获取处理器的执行链过程如下图所示:
获取处理器执行链.jpg
getHandler()
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
//调用HandlerMapping 的getHandler方法,获取执行链
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
AbstractHandlerMapping#getHandler:获取Handler执行链
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//1、获取HandlerMethod
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);
}
//2、获取HandlerMethod的执行链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
2.1、获取HandlerMethod
AbstractHandlerMethodMapping#getHandlerInternal:获取HandlerMethod
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//1、获取lookupPath
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
this.mappingRegistry.acquireReadLock();
try {
//2、根据lookupPath获取HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
//3、将HandlerMethod里面的bean,从String类型实例化为它的实际类型
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
2.1.1、获取lookupPath
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
2.1.2、获取HandlerMethod
AbstractHandlerMethodMapping#lookupHandlerMethod
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
//1、根据lookupPath查找RequestMappingInfo对象
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
//2、根据拿到的RequestMappingInfo对象,封装Match集合
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
Collections.sort(matches, comparator);
if (logger.isTraceEnabled()) {
logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
lookupPath + "] : " + matches);
}
//3、找到最合适的Match对象
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
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();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
}
}
handleMatch(bestMatch.mapping, lookupPath, request);
//4、返回Match的HandlerMethod对象
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
第一步中,根据lookupPath查找RequestMappingInfo对象,实际上就是去urlLookup属性中找。
public List<T> getMappingsByUrl(String urlPath) {
return this.urlLookup.get(urlPath);
}
上面的Match对象其实只有两个属性,一个是泛型T(RequestMappingInfo类型),另外一个是HandlerMethod对象
private class Match {
private final T mapping;
private final HandlerMethod handlerMethod;
public Match(T mapping, HandlerMethod handlerMethod) {
this.mapping = mapping;
this.handlerMethod = handlerMethod;
}
@Override
public String toString() {
return this.mapping.toString();
}
}
addMatchingMappings方法:根据RequestMappingInfo来封装Match集合
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
T match = getMatchingMapping(mapping, request);
if (match != null) {
matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
}
}
}
其中this.mappingRegistry.getMappings()返回的是Map<T, HandlerMethod>集合。
public Map<T, HandlerMethod> getMappings() {
return this.mappingLookup;
}
2.1.3、实例化HandlerMethod的bean属性
HandlerMethod#createWithResolvedBean:先拿到beanFactory,然后调用beanFactory.getBean(beanName)方法。
public HandlerMethod createWithResolvedBean() {
Object handler = this.bean;
if (this.bean instanceof String) {
Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
String beanName = (String)this.bean;
handler = this.beanFactory.getBean(beanName);
}
return new HandlerMethod(this, handler);
}
2.2、获取HandlerMethod的执行链
AbstractHandlerMapping#getHandlerExecutionChain:根据路径lookupPath找到这个请求的拦截器,并添加到执行链中。
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
//1、获取请求的路径
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
//自定义的MyInterceptor拦截器和另外两个Spring的拦截器都在adaptedInterceptors属性中
//2、遍历this.adaptedInterceptors集合
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
//3、如果拦截器和路径匹配
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
//4、将拦截器添加到执行链中
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
网友评论