原理
通过请求路径,从内存map(Map<T, MappingRegistration>)中,取出controller,执行对应方法。
tomcat处理http请求原理
首先我们自定义servlet类,继承HttpServer,重写doGet、doPost等方法,tomcat通过判断请求方式get、post等,将请求分发到自定义的servlet中,执行我们编写的代码,返回到页面或者返回数据。springmvc帮我们封装了自定义的servlet类DispatcherServlet,首先将所有请求映射到DispatcherServlet,通过一系列的逻辑后,最终找到执行的controller,执行实际请求方法,最终返回页面或者数据。
DispatcherServlet的diagram图

执行顺序
DispatcherServlet继承FrameworkServlet,FrameworkServlet中重写doGet、doPost方法,直接上代码
@Override
protected final void doGet/doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
initContextHolders(request, localeContext, requestAttributes);
try {
//执行doService方法 FrameworkServlet是抽象类,只有一个子类DispatcherServlet
//doService是抽象方法,实际执行是DispatcherServlet的doService方法
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...省略代码
try {
//执行doDispatch方法
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 {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 确定当前请求的处理程序
//实际转发到那个controller
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
//如果找不到请求处理的controller 就会报错
//No mapping for *** 方法找不到请求路径
noHandlerFound(processedRequest, response);
return;
}
// 确定当前请求的处理程序适配器。通过反射调用
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;
}
// 实际调用处理程序 调用实际执行的controller程序
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
//..省略代码
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
//...省略代码
}
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
//this.handlerMappings是List<HandlerMapping> ,springboot内置5个映射器处理器分别是:
//RequestMappintHandlerMapping、BeanNameUrlHandlerMapping、RouterFunctionMapping、SimpleUrlHandlerMapping、WelcomePageHandlerMapping
//可以说RequestMappintHandlerMapping就是springboot提供的默认处理器
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
接着看RequestMappintHandlerMapping的getHandler方法,实际执行其父类AbstractHandlerMethodMapping的getHandler方法
@Override
@Nullable
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//请求路径 比如:/test /test/id/111(实际对应方法/test/id/{id})
String lookupPath = initLookupPath(request);
//上锁 通过ReentrantReadWriteLock.ReadLock加读锁 资源共享 但是不允许修改共享资源
this.mappingRegistry.acquireReadLock();
try {
//获取实际请求的controller以及方法
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
//...省略代码
if (matches.isEmpty()) {
//匹配请求路径
//this.mappingRegistry.getRegistrations()返回的就是Map<T, MappingRegistration<T>>,springboot启动过程中扫描到的所有控制器路径以及springboot默认匹配的路径 比如 /error
//this.mappingRegistry.getRegistrations().keySet() 获取所有的请求路径集合 返回RequestMappingInfo 前文提到的
addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
bestMatch = matches.get(0);
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(request)) {
for (Match match : matches) {
if (match.hasCorsConfig()) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
}
}
else {
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.getHandlerMethod().getMethod();
Method m2 = secondBestMatch.getHandlerMethod().getMethod();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
}
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.getHandlerMethod();
}
else {
return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
}
}
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
//mappings内存中所有的接口地址 见下图
for (T mapping : mappings) {
//匹配实际执行的controller 最终 因为这里的mapping是RequestMappingInfo
//getMatchingMapping(RequestMappingInfo info, HttpServletRequest request)实际执行info.getMatchingCondition(request);
T match = getMatchingMapping(mapping, request);
if (match != null) {
matches.add(new Match(match, this.mappingRegistry.getRegistrations().get(mapping)));
}
}
}

@Override
@Nullable
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
//请求方式 get/post ..
RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
if (methods == null) {
return null;
}
//请求参数
ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
if (params == null) {
return null;
}
//请求头
HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
if (headers == null) {
return null;
}
ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
if (consumes == null) {
return null;
}
ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);
if (produces == null) {
return null;
}
//匹配请求路径
//执行this.pathPatternsCondition.getMatchingCondition方法
//这里简单描述一下匹配路径的逻辑
//把每一个接口路径地址封装成PathPattern,其中有一个属性是PathElement head
//看到head就想到列表(实际使用双向列表方式) "/"<->"rest"<->"id"<->"{id}" 这种形式
//每一个PathElement 对应不同的类型, /->SeparatorPathElement("分隔符") rest->LiteralPPathElement 文字类型
//{id}->CaptureVariablePathElement 可变路径类型
//然后从head开始,通过链表遍历方式 分别调用个不同类型中的match方法,匹配路径
//匹配成功加入到 List<Match>中
/** LiteralPPathElement match方法匹配是一个个字符对比的方式
for (int i = 0; i < this.len; i++) {
if (value.charAt(i) != this.text[i]) {
return false;
}
}
*/
PathPatternsRequestCondition pathPatterns = null;
if (this.pathPatternsCondition != null) {
pathPatterns = this.pathPatternsCondition.getMatchingCondition(request);
if (pathPatterns == null) {
return null;
}
}
PatternsRequestCondition patterns = null;
if (this.patternsCondition != null) {
patterns = this.patternsCondition.getMatchingCondition(request);
if (patterns == null) {
return null;
}
}
RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
if (custom == null) {
return null;
}
return new RequestMappingInfo(this.name, pathPatterns, patterns,
methods, params, headers, consumes, produces, custom, this.options);
}
请求路径是如何映射到后端接口&spm=1001.2101.3001.5002&articleId=141976550&d=1&t=3&u=0b8bc3a8b412411392f34358b998a45f)
2624

被折叠的 条评论
为什么被折叠?



