iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >java spring mvc处理器映射器介绍
  • 601
分享到

java spring mvc处理器映射器介绍

2024-04-02 19:04:59 601人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录一、RequestMappingHandlerMapping解析映射简单介绍二、@RequestMapping解析源码流程三、@RequestMapping映射源码流程四、@Re

前言:

  • 本文源码基于spring-framework-5.3.10
  • mvcspring源码中的一个子模块!

一、RequestMappingHandlerMapping解析映射简单介绍

  • @RequestMapping通过RequestMappingHandlerMapping进行解析!
  • HandlerMapping是一个根据URL映射到Handler的方法。
  • RequestMappingHandlerMapping是HandlerMapping的一个子类!
  • RequestMappingHandlerMapping他的父类有InitializingBean,所有在spring启动实例化的时候会调用afterPropertiesSet()方法。解析逻辑就在这里。
  • RequestMappingHandlerMapping有俩个过程:解析、映射

二、@RequestMapping解析源码流程

  • 容器加载,调用RequestMappingHandlerMappingafterPropertiesSet()。
  • 调用父类的afterPropertiesSet()方法。
  • 调用initHandlerMethods()方法。
  • 循环每一个Bean,看方法上有@RequestMapping或者@Controller的Bean。
  • 解析HandlerMethods,进行封装RequestMappingInfo。
  • 将封装好的RequestMappingInfo存起来:key为路径,值为mapping(RequestMappingInfo)

三、@RequestMapping映射源码流程

  • 请求进来,调用getHandler方法。
  • 获取当前请求对应的HandlerMethod
  • 通过UrlPathHelper对象,用于来解析从们的request中解析出请求映射路径。
  • 更具路径去pathLookup中找。
  • 上面没找到,从所有的里面找有通配符的。
  • 找到多个进行排序,优先级:? > * > {} >** 。
  • 不为空拿到第一个返回。
  • 如果为空获取默认的。默认还是空的,直接返回null。
  • 封装拦截器,返回。

四、@RequestMapping解析源码


public void afterPropertiesSet() {

	this.config = new RequestMappingInfo.BuilderConfiguration();
	this.config.setTrailingSlashMatch(useTrailingSlashMatch()); // 尾部斜杠
	this.config.setContentNeGotiationManager(getContentNegotiationManager());

	if (getPatternParser() != null) {
		this.config.setPatternParser(getPatternParser());
		Assert.isTrue(!this.useSuffixPatternMatch && !this.useReGISteredSuffixPatternMatch,
				"Suffix pattern matching not supported with PathPatternParser.");
	}
	else {
		this.config.setSuffixPatternMatch(useSuffixPatternMatch());
		this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
		this.config.setPathMatcher(getPathMatcher());
	}
	
	// 调用父类的afterPropertiesSet方法
	super.afterPropertiesSet();
}


public void afterPropertiesSet() {
	initHandlerMethods();
}


protected void initHandlerMethods() {
	// 获得所有候选beanName—— 当前容器所有的beanName
	for (String beanName : getCandidateBeanNames()) {
		// BeanName不是scopedTarget.开头的
		if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
			// *处理候选bean——即解析@RequestMapping和映射路径
			processCandidateBean(beanName);
		}
	}
	// 解析完所有@RequestMapping的时候调用
	handlerMethodsInitialized(getHandlerMethods());
}


protected void processCandidateBean(String beanName) {
	Class<?> beanType = null;
	try {
		// 得到当前BeanName得到这个Bean的类型
		beanType = obtainApplicationContext().getType(beanName);
	}
	catch (Throwable ex) {
		// An unresolvable bean type, probably from a lazy bean - let's ignore it.
		if (logger.isTraceEnabled()) {
			logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
		}
	}
	// 这一步判断是关键:是否有Controller 或 RequestMapping注解
	if (beanType != null && isHandler(beanType)) {
		// 解析HandlerMethods
		detectHandlerMethods(beanName);
	}
}


protected void detectHandlerMethods(Object handler) {
	Class<?> handlerType = (handler instanceof String ?
			obtainApplicationContext().getType((String) handler) : handler.getClass());

	if (handlerType != null) {
		Class<?> userType = ClassUtils.getUserClass(handlerType);
		// 循环所有方法
		Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
				(MethodIntrospector.MetadataLookup<T>) method -> {
					try {
						// 根据Method得到Mapping映射
						return getMappingFORMethod(method, userType);
					}
					catch (Throwable ex) {
						throw new IllegalStateException("Invalid mapping on handler class [" +
								userType.getName() + "]: " + method, ex);
					}
		});
		if (logger.isTraceEnabled()) {
			logger.trace(formatMappings(userType, methods));
		}
		else if (mappingsLogger.isDebugEnabled()) {
			mappingsLogger.debug(formatMappings(userType, methods));
		}
		// 遍历每一个方法,这里是所有Bean的所有方法
		methods.forEach((method, mapping) -> {
			Method invocableMethod = aopUtils.selectInvocableMethod(method, userType);
			// pathLookup放入:key为路径,值为mapping(RequestMappingInfo)
			registerHandlerMethod(handler, invocableMethod, mapping);
		});
	}
}


protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
	// 如果方法上面有@RequestMapping:解析出RequestMappingInfo
	// RequestMappingInfo 是用来在请求的时候做匹对的
	RequestMappingInfo info = createRequestMappingInfo(method);
	if (info != null) {
		// 如果方法上面有@RequestMapping,看看类上面是不是有@RequestMapping
		RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
		// 类上面也有@RequestMapping  那就合并
		// 比如 类:/user  方法:/info 合并为 /user/info
		if (typeInfo != null) {
			info = typeInfo.combine(info);
		}

		// 合并前缀   5.1新增  默认null
		// 可通过 WEBMvcConfigurer#configurePathMatch 进行定制
		String prefix = getPathPrefix(handlerType);
		if (prefix != null) {
			info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
		}
	}
	return info;
}


private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
	// 获取RequestMapping注解信息
	RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
	// 获取请求调解:[可扩展], 如果有:该条件会在请求时匹对
	RequestCondition<?> condition = (element instanceof Class ?
			getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
	// 如果有RequestMapping注解,封装成RequestMappingInfo
	return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}


protected RequestMappingInfo createRequestMappingInfo(
		RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
	// 将@RequestMapping注解属性的值构建成一个 RequestMappingInfo
	RequestMappingInfo.Builder builder = RequestMappingInfo
			//构建路径
			.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
			//构建方法(get还是post等)
			.methods(requestMapping.method())
			//参数 对应Http request parameter
			.params(requestMapping.params())
			//头部
			.headers(requestMapping.headers())
			//request的提交内容类型content type,如application/JSON, text/html
			.consumes(requestMapping.consumes())
			//指定返回的内容类型的content type,仅当request请求头中的(Accept)类型中包含该指定类型才返回
			.produces(requestMapping.produces())
			.mappingName(requestMapping.name());
	if (customCondition != null) {
		builder.customCondition(customCondition);
	}
	// 构造RequestMappingInfo:将上面的属性构建成一个个的RequestCondition对象方便在请求的时候组合匹对
	return builder.options(this.config).build();
}


public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {
	final Map<Method, T> methodMap = new LinkedHashMap<>();
	Set<Class<?>> handlerTypes = new LinkedHashSet<>();
	Class<?> specificHandlerType = null;
	//获取原始的class对象
	if (!Proxy.isProxyClass(targetType)) {
		specificHandlerType = ClassUtils.getUserClass(targetType);
		handlerTypes.add(specificHandlerType);
	}
	//获取class的接口
	handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType));
	//循环我们的class集合
	for (Class<?> currentHandlerType : handlerTypes) {
		final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);

		ReflectionUtils.doWithMethods(currentHandlerType, method -> {
			//获取具体的方法对象
			Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
			 
			T result = metadataLookup.inspect(specificMethod);
			if (result != null) {
				// 看看有没有桥接方法:泛型实现类JVM会自动生成桥接类
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
				if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
					//把方法对象作为key,RequestMappingInfo对象作为value保存到map中
					methodMap.put(specificMethod, result);
				}
			}
		}, ReflectionUtils.USER_DECLARED_METHODS);
	}

	return methodMap;
}

五、@RequestMapping映射源码


public final HandlerExecutionChain getHandler(httpservletRequest request) throws Exception {
	// 获取当前请求对应的HandlerMethod
	Object handler = getHandlerInternal(request);
	
	// 获取默认的handler
	if (handler == null) {
		handler = getDefaultHandler();
	}
	
	// 还是没有handler的时候返回null,404了
	if (handler == null) {
		return null;
	}
	// Bean name or resolved handler?
	// String类型?获取Bean
	if (handler instanceof String) {
		String handlerName = (String) handler;
		handler = obtainApplicationContext().getBean(handlerName);
	}

	// Ensure presence of cached lookupPath for interceptors and others
	if (!ServletRequestPathUtils.hasCachedPath(request)) {
		initLookupPath(request);
	}

	// 获取拦截器相关的调用链
	HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

	if (logger.isTraceEnabled()) {
		logger.trace("Mapped to " + handler);
	}
	else if (logger.isDebugEnabled() && !DispatcherType.ASYNC.equals(request.getDispatcherType())) {
		logger.debug("Mapped to " + executionChain.getHandler());
	}

	if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
		CorsConfiguration config = getCorsConfiguration(handler, request);
		if (getCorsConfigurationSource() != null) {
			CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
			config = (globalConfig != null ? globalConfig.combine(config) : config);
		}
		if (config != null) {
			config.validateAllowCredentials();
		}
		executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
	}

	return executionChain;
}


protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
	try {
		// 直接调用父类的getHandlerInternal方法
		return super.getHandlerInternal(request);
	}
	finally {
		ProducesRequestCondition.clearMediaTypesAttribute(request);
	}
}

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	// 通过UrlPathHelper对象,用于来解析从们的request中解析出请求映射路径
	String lookupPath = initLookupPath(request);
	this.mappingRegistry.acquireReadLock();
	try {
		// 通过lookupPath解析最终的handler——HandlerMethod对象
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
	}
	finally {
		this.mappingRegistry.releaseReadLock();
	}
}


protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
	List<Match> matches = new ArrayList<>();
	// 根据uri从mappingRegistry.pathLookup获取 RequestMappingInfo
	// pathLookup<path,RequestMappingInfo>会在初始化阶段解析好
	List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
	if (directPathMatches != null) {
		// 如果根据path能直接匹配的RequestMappingInfo 则用该mapping进行匹配其他条件(method、header等)
		addMatchingMappings(directPathMatches, matches, request);
	}
	if (matches.isEmpty()) {
		// 如果无path匹配,用所有的RequestMappingInfo  通过AntPathMatcher匹配
		addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
	}
	if (!matches.isEmpty()) {
		// 选择第一个为最匹配的
		Match bestMatch = matches.get(0);
		
		if (matches.size() > 1) {
			//创建MatchComparator的匹配器对象
			Comparator<Match> comparator = new MatchComparator(getMappinGComparator(request));

			
			matches.sort(comparator);

			// 排完序后拿到优先级最高的
			bestMatch = matches.get(0);
			if (logger.isTraceEnabled()) {
				logger.trace(matches.size() + " matching mappings: " + matches);
			}
			// 是否配置CORS并且匹配
			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中
		request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
		handleMatch(bestMatch.mapping, lookupPath, request);
		//返回最匹配的
		return bestMatch.getHandlerMethod();
	}
	else { // return null
		return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
	}
}

到此这篇关于java spring mvc处理器映射器介绍的文章就介绍到这了,更多相关spring mvc处理器映射器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: java spring mvc处理器映射器介绍

本文链接: https://www.lsjlt.com/news/144322.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • java spring mvc处理器映射器介绍
    目录一、RequestMappingHandlerMapping解析映射简单介绍二、@RequestMapping解析源码流程三、@RequestMapping映射源码流程四、@Re...
    99+
    2024-04-02
  • spring-mvc中如何实现映射处理器
    这篇文章主要介绍spring-mvc中如何实现映射处理器,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1.简析映射处理器在spring mvc中,使用映射处理器可以把web请求映射到正确的处理器上,spring内置了...
    99+
    2023-06-17
  • Java spring mvc请求详情介绍
    目录一、源码执行流程二、源码执行流程图三、spring mvc中的一核心组件四、源码分析五、获取组件相关逻辑:六、获取参数,执行方法源码分析七、渲染视图逻辑前言: 本文源码基于spr...
    99+
    2024-04-02
  • Spring后处理器详细介绍
    目录一、概述二、案例演示三、Bean的后处理器BeanPostProcessor四、Spring ioc整体流程总结一、概述 Spring的后处理器是Spring对外开发的重要扩展点...
    99+
    2023-02-07
    Spring后处理器 Spring后置处理器
  • Spring Bean后处理器详细介绍
    常见Bean后处理器的作用: public static void main(String[] args) { // ⬇️GenericApplicationC...
    99+
    2023-01-28
    Spring Bean后处理器 Spring后处理器
  • Java反射机制的原理介绍
    这篇文章主要介绍“Java反射机制的原理介绍”,在日常操作中,相信很多人在Java反射机制的原理介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java反射机制的原理介绍”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-17
  • 龙芯1B芯片处理器介绍
    龙芯1B使用0.13um工艺,是一款轻量级的32位SoC芯片。片内集成了GS232处理器核、16/32位DDR2、高清显示、NAND、SPI、62路GPIO、USB、CAN、UART等接口,能够满足超低价位云终端、数据采集、网络设备等领域需...
    99+
    2023-06-05
  • Java中如何用内存映射处理大文件
    本篇内容介绍了“Java中如何用内存映射处理大文件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!package test;&nbs...
    99+
    2023-06-17
  • Spring MVC 前端控制器 (DispatcherServlet)处理流程解析
    目录Spring MVC 请求处理流程DispatcherServlet源码分析Spring MVC 中的一些核心类Spring MVC 请求处理流程 用户发起请求,到 Dispa...
    99+
    2024-04-02
  • Java并发容器介绍
    目录1、原子类2、锁3、并发容器4、List接口下5、Map接口下6、Set接口下7、Queue接口下Java并发包(concurrent)是Java用来处理并发问题的利器,该并发包...
    99+
    2024-04-02
  • Spring MVC拦截器_动力节点Java学院整理
    Spring为我们提供了:org.springframework.web.servlet.HandlerInterceptor接口,org.springframework.web.servlet.handler.HandlerInterce...
    99+
    2023-05-31
    spring mvc 拦截器
  • Java 超详细讲解Spring MVC异常处理机制
    目录异常处理机制流程图异常处理的两种方式简单异常处理器SimpleMappingExceptionResolver自定义异常处理步骤本章小结异常处理机制流程图 系统中异常包括两类: ...
    99+
    2024-04-02
  • Java异常类型介绍及处理方法
    前言: Java异常,大家都很熟悉。但是对于具体怎么分类的,JVM对其怎么处理的,代码中怎么处理的,应该怎么使用,底层怎么实现的等等,可能就会有些不是那么清晰。本文基于此详细捋一下异...
    99+
    2024-04-02
  • ASP和Spring开发技术:如何在路径映射中处理异常?
    在ASP和Spring开发中,路径映射是非常重要的一个概念。路径映射可以将请求的URL地址映射到具体的处理方法上,从而实现不同的业务逻辑。但是,在路径映射中,有时候会出现异常情况,例如请求的URL地址不存在或者请求的参数不正确等等。那么,...
    99+
    2023-09-08
    spring path 开发技术
  • Spring MVC的拦截器与异常处理机制是什么
    这篇文章主要介绍了Spring MVC的拦截器与异常处理机制是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring MVC的拦截器与异常处理机制是什么文章都会有所收获,下面我们一起...
    99+
    2023-06-29
  • Java 中的异常处理机制详情介绍
    目录介绍 Java 中的异常介绍 Error介绍 ExceptionJava 异常类的结构如何处理函数抛出的异常吞掉 or 抛出受检异常 or 非受检异常处理异常的原则尽量不要捕获通...
    99+
    2024-04-02
  • ARM v8处理器概述、架构及技术介绍
    ARM v8处理器是一种基于ARM架构的64位处理器。它包含了一系列技术和功能,以提供更高的性能和能效。ARM v8架构采用了先进的...
    99+
    2023-09-22
    ARM
  • 介绍下Java Spring的核心接口,容器中Bean的实例化
    目录Spring的核心接口ApplicationContext接口 BeanFactory接口Spring容器中Bean的实例化构造方法无参构造方法有参构造方法工厂静态工厂...
    99+
    2024-04-02
  • MT7682芯片手册资料, MT7682处理器参数介绍
    MT7682是一种高度集成的芯片组,包括一个应用处理器、一个低功耗的1x11n单波段Wi-Fi子系统和一个电源管理单元(Ppu)。MT7682基于arm Cortex-M4,带有浮点微控制器单元(MCU),包括1MB闪存。支持UART、I2...
    99+
    2023-06-05
  • Spring MVC异常解析器的原理是什么
    本篇内容主要讲解“Spring MVC异常解析器的原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring MVC异常解析器的原理是什么”吧!使用介...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作