最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java?spring?mvc處理器映射器介紹

 更新時(shí)間:2022年03月29日 15:42:47   投稿:hqx  
這篇文章主要介紹了java?spring?mvc處理器映射器,文章圍繞equestMapping解析映射介紹展開源碼內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

前言:

  • 本文源碼基于spring-framework-5.3.10。
  • mvcspring源碼中的一個(gè)子模塊!

一、RequestMappingHandlerMapping解析映射簡(jiǎn)單介紹

  • @RequestMapping通過RequestMappingHandlerMapping進(jìn)行解析!
  • HandlerMapping是一個(gè)根據(jù)URL映射到Handler的方法。
  • RequestMappingHandlerMapping是HandlerMapping的一個(gè)子類!
  • RequestMappingHandlerMapping他的父類有InitializingBean,所有在spring啟動(dòng)實(shí)例化的時(shí)候會(huì)調(diào)用afterPropertiesSet()方法。解析邏輯就在這里。
  • RequestMappingHandlerMapping有倆個(gè)過程:解析、映射

二、@RequestMapping解析源碼流程

  • 容器加載,調(diào)用RequestMappingHandlerMappingafterPropertiesSet()。
  • 調(diào)用父類的afterPropertiesSet()方法。
  • 調(diào)用initHandlerMethods()方法。
  • 循環(huán)每一個(gè)Bean,看方法上有@RequestMapping或者@Controller的Bean。
  • 解析HandlerMethods,進(jìn)行封裝RequestMappingInfo。
  • 將封裝好的RequestMappingInfo存起來:key為路徑,值為mapping(RequestMappingInfo)

三、@RequestMapping映射源碼流程

  • 請(qǐng)求進(jìn)來,調(diào)用getHandler方法。
  • 獲取當(dāng)前請(qǐng)求對(duì)應(yīng)的HandlerMethod
  • 通過UrlPathHelper對(duì)象,用于來解析從們的request中解析出請(qǐng)求映射路徑。
  • 更具路徑去pathLookup中找。
  • 上面沒找到,從所有的里面找有通配符的。
  • 找到多個(gè)進(jìn)行排序,優(yōu)先級(jí):? > * > {} >** 。
  • 不為空拿到第一個(gè)返回。
  • 如果為空獲取默認(rèn)的。默認(rèn)還是空的,直接返回null。
  • 封裝攔截器,返回。

四、@RequestMapping解析源碼

/**
 * 解析的開始位置。
 * 由于實(shí)現(xiàn)了InitializingBean,初始化Bean的時(shí)候調(diào)用這個(gè)方法。
 * 源碼位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet()
 */
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());
	}
	
	// 調(diào)用父類的afterPropertiesSet方法
	super.afterPropertiesSet();
}

/**
 * 父類的afterPropertiesSet方法。
 * 源碼位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet()
 */
public void afterPropertiesSet() {
	initHandlerMethods();
}

/**
 * 解析@RequestMapping方法
 * 源碼位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods()
 */
protected void initHandlerMethods() {
	// 獲得所有候選beanName—— 當(dāng)前容器所有的beanName
	for (String beanName : getCandidateBeanNames()) {
		// BeanName不是scopedTarget.開頭的
		if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
			// *處理候選bean——即解析@RequestMapping和映射路徑
			processCandidateBean(beanName);
		}
	}
	// 解析完所有@RequestMapping的時(shí)候調(diào)用
	handlerMethodsInitialized(getHandlerMethods());
}

/**
 * 處理候選bean——即解析@RequestMapping和映射路徑
 * 源碼位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.processCandidateBean(String)
 */
protected void processCandidateBean(String beanName) {
	Class<?> beanType = null;
	try {
		// 得到當(dāng)前BeanName得到這個(gè)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);
		}
	}
	// 這一步判斷是關(guān)鍵:是否有Controller 或 RequestMapping注解
	if (beanType != null && isHandler(beanType)) {
		// 解析HandlerMethods
		detectHandlerMethods(beanName);
	}
}

/**
 * 解析HandlerMethods
 * 源碼位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(Object)
 */
protected void detectHandlerMethods(Object handler) {
	Class<?> handlerType = (handler instanceof String ?
			obtainApplicationContext().getType((String) handler) : handler.getClass());

	if (handlerType != null) {
		Class<?> userType = ClassUtils.getUserClass(handlerType);
		// 循環(huán)所有方法
		Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
				(MethodIntrospector.MetadataLookup<T>) method -> {
					try {
						// 根據(jù)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));
		}
		// 遍歷每一個(gè)方法,這里是所有Bean的所有方法
		methods.forEach((method, mapping) -> {
			Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
			// pathLookup放入:key為路徑,值為mapping(RequestMappingInfo)
			registerHandlerMethod(handler, invocableMethod, mapping);
		});
	}
}

/**
 * 根據(jù)Method得到Mapping映射
 * 源碼位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.getMappingForMethod(Method, Class<?>)
 */
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
	// 如果方法上面有@RequestMapping:解析出RequestMappingInfo
	// RequestMappingInfo 是用來在請(qǐng)求的時(shí)候做匹對(duì)的
	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新增  默認(rèn)null
		// 可通過 WebMvcConfigurer#configurePathMatch 進(jìn)行定制
		String prefix = getPathPrefix(handlerType);
		if (prefix != null) {
			info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
		}
	}
	return info;
}

/**
 * 創(chuàng)建請(qǐng)求映射信息的外部邏輯
 * 源碼位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.createRequestMappingInfo(AnnotatedElement)
 */
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
	// 獲取RequestMapping注解信息
	RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
	// 獲取請(qǐng)求調(diào)解:[可擴(kuò)展], 如果有:該條件會(huì)在請(qǐng)求時(shí)匹對(duì)
	RequestCondition<?> condition = (element instanceof Class ?
			getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
	// 如果有RequestMapping注解,封裝成RequestMappingInfo
	return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}

/**
 * 創(chuàng)建請(qǐng)求映射信息的內(nèi)部邏輯
 * 源碼位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.createRequestMappingInfo(RequestMapping, RequestCondition<?>)
 */
protected RequestMappingInfo createRequestMappingInfo(
		RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
	// 將@RequestMapping注解屬性的值構(gòu)建成一個(gè) RequestMappingInfo
	RequestMappingInfo.Builder builder = RequestMappingInfo
			//構(gòu)建路徑
			.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
			//構(gòu)建方法(get還是post等)
			.methods(requestMapping.method())
			//參數(shù) 對(duì)應(yīng)http request parameter
			.params(requestMapping.params())
			//頭部
			.headers(requestMapping.headers())
			//request的提交內(nèi)容類型content type,如application/json, text/html
			.consumes(requestMapping.consumes())
			//指定返回的內(nèi)容類型的content type,僅當(dāng)request請(qǐng)求頭中的(Accept)類型中包含該指定類型才返回
			.produces(requestMapping.produces())
			.mappingName(requestMapping.name());
	if (customCondition != null) {
		builder.customCondition(customCondition);
	}
	// 構(gòu)造RequestMappingInfo:將上面的屬性構(gòu)建成一個(gè)個(gè)的RequestCondition對(duì)象方便在請(qǐng)求的時(shí)候組合匹對(duì)
	return builder.options(this.config).build();
}

/**
 * 得到所有的方法
 * 源碼位置:org.springframework.core.MethodIntrospector.selectMethods(Class<?>, MetadataLookup<T>)
 */
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對(duì)象
	if (!Proxy.isProxyClass(targetType)) {
		specificHandlerType = ClassUtils.getUserClass(targetType);
		handlerTypes.add(specificHandlerType);
	}
	//獲取class的接口
	handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType));
	//循環(huán)我們的class集合
	for (Class<?> currentHandlerType : handlerTypes) {
		final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);

		ReflectionUtils.doWithMethods(currentHandlerType, method -> {
			//獲取具體的方法對(duì)象
			Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
			 /**回調(diào) 即解析@RequestMapping 返回RequestMappingInfo
			  * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#getMappingForMethod(java.lang.reflect.Method, java.lang.Class)*/
			T result = metadataLookup.inspect(specificMethod);
			if (result != null) {
				// 看看有沒有橋接方法:泛型實(shí)現(xiàn)類jvm會(huì)自動(dòng)生成橋接類
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
				if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
					//把方法對(duì)象作為key,RequestMappingInfo對(duì)象作為value保存到map中
					methodMap.put(specificMethod, result);
				}
			}
		}, ReflectionUtils.USER_DECLARED_METHODS);
	}

	return methodMap;
}

五、@RequestMapping映射源碼

/**
 * 獲取@RequestMapping映射
 * 源碼位置:org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(HttpServletRequest)
 */
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	// 獲取當(dāng)前請(qǐng)求對(duì)應(yīng)的HandlerMethod
	Object handler = getHandlerInternal(request);
	
	// 獲取默認(rèn)的handler
	if (handler == null) {
		handler = getDefaultHandler();
	}
	
	// 還是沒有handler的時(shí)候返回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);
	}

	// 獲取攔截器相關(guān)的調(diào)用鏈
	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;
}

/**
 * 獲取當(dāng)前請(qǐng)求對(duì)應(yīng)的HandlerMethod
 * 源碼位置:org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(HttpServletRequest)
 */
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
	try {
		// 直接調(diào)用父類的getHandlerInternal方法
		return super.getHandlerInternal(request);
	}
	finally {
		ProducesRequestCondition.clearMediaTypesAttribute(request);
	}
}
/**
 * 獲取當(dāng)前請(qǐng)求對(duì)應(yīng)的HandlerMethod---父類的
 * 源碼位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(HttpServletRequest)
 */
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	// 通過UrlPathHelper對(duì)象,用于來解析從們的request中解析出請(qǐng)求映射路徑
	String lookupPath = initLookupPath(request);
	this.mappingRegistry.acquireReadLock();
	try {
		// 通過lookupPath解析最終的handler——HandlerMethod對(duì)象
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
	}
	finally {
		this.mappingRegistry.releaseReadLock();
	}
}

/**
 * 通過lookupPath解析最終的handler
 * 源碼位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(String, HttpServletRequest)
 */
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
	List<Match> matches = new ArrayList<>();
	// 根據(jù)uri從mappingRegistry.pathLookup獲取 RequestMappingInfo
	// pathLookup<path,RequestMappingInfo>會(huì)在初始化階段解析好
	List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
	if (directPathMatches != null) {
		// 如果根據(jù)path能直接匹配的RequestMappingInfo 則用該mapping進(jìn)行匹配其他條件(method、header等)
		addMatchingMappings(directPathMatches, matches, request);
	}
	if (matches.isEmpty()) {
		// 如果無path匹配,用所有的RequestMappingInfo  通過AntPathMatcher匹配
		addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
	}
	if (!matches.isEmpty()) {
		// 選擇第一個(gè)為最匹配的
		Match bestMatch = matches.get(0);
		/**
		 * 如果匹配到多個(gè)
		 @RequestMapping(value="/mappin?")
		 @RequestMapping(value="/mappin*")
		 @RequestMapping(value="/{xxxx}")
		 @RequestMapping(value="/**")
		 */
		if (matches.size() > 1) {
			//創(chuàng)建MatchComparator的匹配器對(duì)象
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));

			/** 根據(jù)精準(zhǔn)度排序  大概是這樣的: ? > * > {} >**   具體可以去看:
			 * @see org.springframework.util.AntPathMatcher.AntPatternComparator#compare(java.lang.String, java.lang.String)*/
			matches.sort(comparator);

			// 排完序后拿到優(yōu)先級(jí)最高的
			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);
				//若第一個(gè)和第二個(gè)是一樣的 拋出異常
				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 + "}");
				}
			}
		}
		//把最匹配的設(shè)置到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);
	}
}

到此這篇關(guān)于java spring mvc處理器映射器介紹的文章就介紹到這了,更多相關(guān)spring mvc處理器映射器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java發(fā)起http請(qǐng)求的完整步驟記錄

    Java發(fā)起http請(qǐng)求的完整步驟記錄

    這篇文章主要給大家介紹了關(guān)于Java發(fā)起http請(qǐng)求的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Spring Boot 整合 ShedLock 處理定時(shí)任務(wù)重復(fù)執(zhí)行的問題小結(jié)

    Spring Boot 整合 ShedLock 處理定時(shí)任務(wù)重復(fù)執(zhí)行的問題小結(jié)

    ShedLock是解決分布式系統(tǒng)中定時(shí)任務(wù)重復(fù)執(zhí)行問題的Java庫,通過在數(shù)據(jù)庫中加鎖,確保只有一個(gè)節(jié)點(diǎn)在指定時(shí)間執(zhí)行任務(wù),它與SpringScheduler、Quartz等框架結(jié)合使用,本文介紹Spring Boot 整合 ShedLock 處理定時(shí)任務(wù)重復(fù)執(zhí)行的問題,感興趣的朋友一起看看吧
    2025-02-02
  • idea插件篇之java內(nèi)存分析工具(JProfiler)的使用

    idea插件篇之java內(nèi)存分析工具(JProfiler)的使用

    這篇文章主要介紹了idea插件篇之java內(nèi)存分析工具(JProfiler),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • nacos配置實(shí)例權(quán)重不生效問題

    nacos配置實(shí)例權(quán)重不生效問題

    這篇文章主要介紹了nacos配置實(shí)例權(quán)重不生效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • SpringBoot 項(xiàng)目中的圖片處理策略之本地存儲(chǔ)與路徑映射

    SpringBoot 項(xiàng)目中的圖片處理策略之本地存儲(chǔ)與路徑映射

    在SpringBoot項(xiàng)目中,靜態(tài)資源存放在static目錄下,使得前端可以通過URL來訪問這些資源,我們就需要將文件系統(tǒng)的文件路徑與URL建立一個(gè)映射關(guān)系,把文件系統(tǒng)中的文件當(dāng)成我們的靜態(tài)資源即可,本文給大家介紹SpringBoot本地存儲(chǔ)與路徑映射的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2023-12-12
  • java實(shí)現(xiàn)俄羅斯方塊游戲

    java實(shí)現(xiàn)俄羅斯方塊游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)俄羅斯方塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • SpringCloud feign服務(wù)熔斷下的異常處理操作

    SpringCloud feign服務(wù)熔斷下的異常處理操作

    這篇文章主要介紹了SpringCloud feign服務(wù)熔斷下的異常處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot?Schedule調(diào)度任務(wù)的動(dòng)態(tài)管理

    SpringBoot?Schedule調(diào)度任務(wù)的動(dòng)態(tài)管理

    Scheduled定時(shí)任務(wù)是Spring?boot自身提供的功能,所以不需要引入Maven依賴包,下面這篇文章主要給大家介紹了關(guān)于SpringBoot通過@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)以及問題解決的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Spring事務(wù)傳播屬性和隔離級(jí)別詳細(xì)介紹

    Spring事務(wù)傳播屬性和隔離級(jí)別詳細(xì)介紹

    這篇文章主要介紹了Spring事務(wù)傳播屬性和隔離級(jí)別詳細(xì)介紹,同時(shí)涉及傳播行為介紹,超時(shí)設(shè)置等相關(guān)內(nèi)容,需要的朋友可以參考下。
    2017-09-09
  • spring的data派生查詢機(jī)制的實(shí)現(xiàn)

    spring的data派生查詢機(jī)制的實(shí)現(xiàn)

    SpringData的派生查詢是一種通過方法名約定自動(dòng)生成數(shù)據(jù)庫查詢的機(jī)制,無需手動(dòng)編寫SQL或JPQL,下面就來介紹一下spring data派生查詢的實(shí)現(xiàn),感興趣的可以了解一下
    2025-03-03

最新評(píng)論

宜阳县| 文登市| 汉中市| 九龙坡区| 文昌市| 石泉县| 安福县| 安图县| 伊宁县| 新田县| 延寿县| 炉霍县| 修文县| 威远县| 南开区| 江孜县| 克东县| 光泽县| 广元市| 肇州县| 疏勒县| 石台县| 鞍山市| 徐汇区| 鹤岗市| 太仆寺旗| 资源县| 阿城市| 娱乐| 黄龙县| 如皋市| 德钦县| 连云港市| 大荔县| 肥乡县| 南雄市| 开鲁县| 常德市| 石河子市| 壤塘县| 嘉义县|