springboot请求映射原理(二)请求路径是如何映射到后端接口

原理

通过请求路径,从内存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);
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值