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

SpringBoot升級(jí)到2.7.18后不兼容的地方及解決

 更新時(shí)間:2024年08月15日 16:26:06   作者:李昂的數(shù)字之旅  
這篇文章主要介紹了SpringBoot升級(jí)到2.7.18后不兼容的地方及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

背景

最近為了給kafka加性能指標(biāo)采集功能,調(diào)研后發(fā)現(xiàn)spring-kafka在2.3版本之后就自帶了Micrometer指標(biāo)采集功能。

但是當(dāng)前項(xiàng)目的spring-boot版本是2.0.2.RELEASE,對(duì)應(yīng)的spring-kafka版本是2.1.6.RELEASE,所以準(zhǔn)備將spring-boot版本升級(jí)到2.7.18,這是2.x系列的最高版本,對(duì)應(yīng)的spring-kafka版本是2.8.11。

版本升級(jí)

module升級(jí)前version升級(jí)后version
spring-boot2.0.2.RELEASE2.7.18
spring-webmvc5.0.6.RELEASE5.3.31
spring-kafka2.1.6.RELEASE2.8.11

不兼容的地方

Spring boot

2.6版本開(kāi)始默認(rèn)禁用Bean的循環(huán)依賴

項(xiàng)目啟動(dòng)會(huì)檢測(cè)是否存在循環(huán)依賴,存在就報(bào)如下錯(cuò)誤。

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

   collectionController (field private com.biz.manager.CollectionManager com.web.controller.CollectionController.collectionManager)
┌─────┐
|  collectionManagerImpl (field private com.biz.manager.FunnyManager com.biz.manager.impl.CollectionManagerImpl.funnyManager)
↑     ↓
|  funnyManagerImpl (field private com.biz.manager.CollectionManager com.biz.manager.impl.FunnyManagerImpl.collectionManager)
└─────┘

Action:

Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

2.6版本在org.springframework.boot.SpringApplication類里增加了allowCircularReferences屬性來(lái)控制循環(huán)依賴是否允許,默認(rèn)值是false。

private boolean allowCircularReferences;

/**
 * Sets whether to allow circular references between beans and automatically try to
 * resolve them. Defaults to {@code false}.
 * @param allowCircularReferences if circular references are allowed
 * @since 2.6.0
 * @see AbstractAutowireCapableBeanFactory#setAllowCircularReferences(boolean)
 */
public void setAllowCircularReferences(boolean allowCircularReferences) {
	this.allowCircularReferences = allowCircularReferences;
}

所以,要保持和2.6版本之前行為一樣的話,就把a(bǔ)llowCircularReferences屬性設(shè)置為true。

設(shè)置可以添加配置spring.main.allow-circular-references=true,或通過(guò)SpringApplicationSpringApplicationBuilder 對(duì)象直接設(shè)置屬性。

2.1版本禁用Bean覆蓋

當(dāng)出現(xiàn)同名bean時(shí),會(huì)判斷是否允許覆蓋beanDefinition,不允許則拋出BeanDefinitionOverrideException異常。

實(shí)現(xiàn)邏輯如下:

BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
	if (!isAllowBeanDefinitionOverriding()) {
		throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
	}
	
  // ...
	this.beanDefinitionMap.put(beanName, beanDefinition);
}

2.1版本在org.springframework.boot.SpringApplication類里增加了allowBeanDefinitionOverriding屬性來(lái)控制是否允許bean覆蓋,默認(rèn)值是false。

private boolean allowBeanDefinitionOverriding;

/**
 * Sets if bean definition overriding, by registering a definition with the same name
 * as an existing definition, should be allowed. Defaults to {@code false}.
 * @param allowBeanDefinitionOverriding if overriding is allowed
 * @since 2.1.0
 * @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding(boolean)
 */
public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
	this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
}

所以,要和老版本兼容的話,就把a(bǔ)llowBeanDefinitionOverriding屬性設(shè)置為true。

設(shè)置可以添加配置spring.main.allow-bean-definition-overriding=true,或通過(guò)SpringApplication 對(duì)象直接設(shè)置屬性。

默認(rèn)的路徑匹配策略改成了PATH_PATTERN_PARSER

2.6版本之前默認(rèn)策略是ANT_PATH_MATCHER,改成PATH_PATTERN_PARSER會(huì)遇到IllegalArgumentException錯(cuò)誤。

java.lang.IllegalArgumentException: Expected lookupPath in request attribute "org.springframework.web.util.UrlPathHelper.PATH".

解決方案是將策略回滾到ANT_PATH_MATCHER:

**spring.mvc.pathmatch.matching-strategy=***ANT_PATH_MATCHER*

Spring webmvc

Cors不允許將allowedOrigins設(shè)置為*

原來(lái)為了方便,會(huì)將跨域的請(qǐng)求來(lái)源設(shè)置為代表允許來(lái)自所有host的請(qǐng)求。

5.3開(kāi)始增加了allowedOrigins值的校驗(yàn),不允許為,否則拋出IllegalArgumentException異常。

/**
	 * Validate that when {@link #setAllowCredentials allowCredentials} is {@code true},
	 * {@link #setAllowedOrigins allowedOrigins} does not contain the special
	 * value {@code "*"} since in that case the "Access-Control-Allow-Origin"
	 * cannot be set to {@code "*"}.
	 * @throws IllegalArgumentException if the validation fails
	 * @since 5.3
	 */
	public void validateAllowCredentials() {
		if (this.allowCredentials == Boolean.TRUE &&
				this.allowedOrigins != null && this.allowedOrigins.contains(ALL)) {

			throw new IllegalArgumentException(
					"When allowCredentials is true, allowedOrigins cannot contain the special value \\"*\\" " +
							"since that cannot be set on the \\"Access-Control-Allow-Origin\\" response header. " +
							"To allow credentials to a set of origins, list them explicitly " +
							"or consider using \\"allowedOriginPatterns\\" instead.");
		}
	}

另外,5.3增加了allowedOriginPatterns屬性來(lái)代替allowedOrigins的功能。所以,要允許所有host的跨域請(qǐng)求的話,把a(bǔ)llowedOriginPatterns設(shè)置為*。

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")    // 允許跨域訪問(wèn)的路徑
                .allowedOriginPatterns("*")    // 允許跨域訪問(wèn)的源
    }
}

/**
 * Alternative to {@link #setAllowedOrigins} that supports more flexible
 * origins patterns with "*" anywhere in the host name in addition to port
 * lists. Examples:
 * <ul>
 * <li>{@literal https://*.domain1.com} -- domains ending with domain1.com
 * <li>{@literal https://*.domain1.com:[8080,8081]} -- domains ending with
 * domain1.com on port 8080 or port 8081
 * <li>{@literal https://*.domain1.com:[*]} -- domains ending with
 * domain1.com on any port, including the default port
 * </ul>
 * <p>In contrast to {@link #setAllowedOrigins(List) allowedOrigins} which
 * only supports "*" and cannot be used with {@code allowCredentials}, when
 * an allowedOriginPattern is matched, the {@code Access-Control-Allow-Origin}
 * response header is set to the matched origin and not to {@code "*"} nor
 * to the pattern. Therefore allowedOriginPatterns can be used in combination
 * with {@link #setAllowCredentials} set to {@code true}.
 * <p>By default this is not set.
 * @since 5.3
 */
public CorsConfiguration setAllowedOriginPatterns(@Nullable List<String> allowedOriginPatterns) {
	if (allowedOriginPatterns == null) {
		this.allowedOriginPatterns = null;
	}
	else {
		this.allowedOriginPatterns = new ArrayList<>(allowedOriginPatterns.size());
		for (String patternValue : allowedOriginPatterns) {
			addAllowedOriginPattern(patternValue);
		}
	}
	return this;
}

靜態(tài)文件是否存在的判斷方式變了

5.3版本開(kāi)始,ClassPathResource類型的資源文件,判斷是否可讀的isReadable()方法的邏輯改成了文件存在且內(nèi)容不為空。當(dāng)我們?cè)L問(wèn)一個(gè)內(nèi)容為空的資源文件時(shí),spring返回404。

例如,訪問(wèn)http://localhost:8080/hello.html,spring會(huì)在/META-INF/resource、resources、static、public這幾個(gè)目錄下查找hello.html。如果文件放在static文件夾下,實(shí)際查找的是/static/hello.html文件。如果是jar包里,則完整的路徑是這樣jar:file:/opt/apps/demo.jar!/BOOT-INF/classes!/static/hello.html。

然后我們看看5.3前后版本代碼,對(duì)這個(gè)文件是否可讀判斷的差異。

5.3版本之前,jar開(kāi)頭的文件直接返回true。

// 5.3之前
@Override
public boolean isReadable() {
	try {
		URL url = getURL();
    // file/vfsfile/vfs開(kāi)頭的url
		if (ResourceUtils.isFileURL(url)) {
			// Proceed with file system resolution
			File file = getFile();
			return (file.canRead() && !file.isDirectory());
		}
		else {
			return true;
		}
	}
	catch (IOException ex) {
		return false;
	}
}

5.3版本開(kāi)始,jar開(kāi)頭的文件會(huì)通過(guò)con.getContentLengthLong()獲取文件長(zhǎng)度,如果是0的話就返回false。

@Override
public boolean isReadable() {
	URL url = resolveURL();
	return (url != null && checkReadable(url));
}

boolean checkReadable(URL url) {
	try {
    // file/vfsfile/vfs開(kāi)頭的url
		if (ResourceUtils.isFileURL(url)) {
			// Proceed with file system resolution
			File file = getFile();
			return (file.canRead() && !file.isDirectory());
		}
		else {
			// Try InputStream resolution for jar resources
			URLConnection con = url.openConnection();
			customizeConnection(con);
			if (con instanceof HttpURLConnection) {
				HttpURLConnection httpCon = (HttpURLConnection) con;
				httpCon.setRequestMethod("HEAD");
				int code = httpCon.getResponseCode();
				if (code != HttpURLConnection.HTTP_OK) {
					httpCon.disconnect();
					return false;
				}
			}
			long contentLength = con.getContentLengthLong();
			if (contentLength > 0) {
				return true;
			}
			else if (contentLength == 0) {
				// Empty file or directory -> not considered readable...
				return false;
			}
			else {
				// Fall back to stream existence: can we open the stream?
				getInputStream().close();
				return true;
			}
		}
	}
	catch (IOException ex) {
		return false;
	}
}

所以,5.3開(kāi)始,靜態(tài)文件不能是空文件,否則會(huì)返回404。

RequestMappingInfo#getPatternsCondition()返回null

5.3開(kāi)始新增了pathPatternsCondition屬性,它和patternsCondition是互斥的,所以getPatternsCondition()可能會(huì)返回null了。

可以通過(guò)getActivePatternsCondition()方法獲取RequestCondition對(duì)象:

/**
 * Returns either {@link #getPathPatternsCondition()} or
 * {@link #getPatternsCondition()} depending on which is not null.
 * @since 5.3
 */
@SuppressWarnings("unchecked")
public <T> RequestCondition<T> getActivePatternsCondition() {
	if (this.pathPatternsCondition != null) {
		return (RequestCondition<T>) this.pathPatternsCondition;
	}
	else if (this.patternsCondition != null) {
		return (RequestCondition<T>) this.patternsCondition;
	}
	else {
		// Already checked in the constructor...
		throw new IllegalStateException();
	}
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

凯里市| 南郑县| 澳门| 宁陕县| 子长县| 河西区| 瑞金市| 稻城县| 宜川县| 平昌县| 周宁县| 绥化市| 梁河县| 正宁县| 芜湖市| 仙游县| 怀安县| 行唐县| 延寿县| 康保县| 乃东县| 翁源县| 涟水县| 崇文区| 华阴市| 泸溪县| 遵化市| 黎平县| 虹口区| 大邑县| 莆田市| 裕民县| 诸城市| 井陉县| 青田县| 潞西市| 嘉善县| 清镇市| 保亭| 郑州市| 青海省|