我的项目迁徙时,抉择了阿里云 Elasticsearch 服务, 版本是 7.10.0 且不能降级版本

[TOC]

Spring Boot 从 2.2.6.RELEASE 降级到 2.5.1 遇到问题如下

1、跨域

1.1、基于 Spring Security 跨域设置
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@EnableWebSecuritypublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {        @Override    protected void configure(HttpSecurity http) throws Exception {        http.cors()                .and()                .csrf().disable()                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);    }        /**     * Spring Security 15.8 CORS     * The easiest way to ensure that CORS is handled first is to use the CorsFilter. Users can integrate the CorsFilter with Spring Security by providing a CorsConfigurationSource using the following:     *     * @return     * @see <a href="https://docs.spring.io/spring-security/site/docs/5.4.10/reference/html5/#cors">     * The easiest way to ensure that CORS is handled first is to use the CorsFilter.     * Users can integrate the CorsFilter with Spring Security by providing a CorsConfigurationSource using the following:</a>     */    @Bean    CorsConfigurationSource corsConfigurationSource() {        CorsConfiguration configuration = new CorsConfiguration();        // 如果设置 true, setAllowedOrigins 须要指定具体域名        // 如果色湖 false, setAllowedOrigins 须要指定具体域名能够用通配符("*")        // spring boot 2.4.0 新增 validateAllowCredentials 函数        // org.springframework:spring-web:jar:5.3.8:compile        // @since 5.3        // configuration.setAllowCredentials(true);        configuration.setAllowedOrigins(Collections.singletonList("*"));        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));        configuration.applyPermitDefaultValues();        configuration.addAllowedHeader("*");        configuration.addAllowedMethod("*");        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();        source.registerCorsConfiguration("/**", configuration);        return source;    }}
1.2、非 Spring Security 形式
package com.example.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.cors.CorsConfiguration;import org.springframework.web.cors.UrlBasedCorsConfigurationSource;import org.springframework.web.filter.CorsFilter;import org.springframework.web.servlet.config.annotation.CorsRegistry;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;import java.util.ArrayList;import java.util.List;/** * 大抵通用,能够查看官网文档适状况解决 * */@Configurationpublic class CorsConfig extends WebMvcConfigurationSupport {    private CorsConfiguration corsConfig() {        CorsConfiguration corsConfiguration = new CorsConfiguration();        corsConfiguration.addAllowedOrigin("*");        corsConfiguration.addAllowedHeader("*");        corsConfiguration.addAllowedMethod("*");        corsConfiguration.setAllowCredentials(true);        corsConfiguration.setMaxAge(3600L);        return corsConfiguration;    }    @Override    public void addCorsMappings(CorsRegistry registry) {        registry.addMapping("/**")                .allowedOriginPatterns("*")                .allowCredentials(true)                .allowedMethods("GET", "POST", "DELETE", "PUT")                .maxAge(3600);    }    @Bean    public CorsFilter corsFilter() {        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();        source.registerCorsConfiguration("/**", corsConfig());        CorsConfiguration config = new CorsConfiguration();        // 是否容许申请带有验证信息        config.setAllowCredentials(true);        // 容许拜访的客户端域名        // (springboot2.4以上的退出这一段可解决 allowedOrigins cannot contain the special value "*"问题)        List<String> allowedOriginPatterns = new ArrayList<>();        allowedOriginPatterns.add("*");        config.setAllowedOriginPatterns(allowedOriginPatterns);        // 设置拜访源地址 config.addAllowedOrigin("*"); 设置拜访源申请头        config.addAllowedHeader("*");        // 设置拜访源申请办法        config.addAllowedMethod("*");        // 对接口配置跨域设置        source.registerCorsConfiguration("/**", config);        return new CorsFilter(source);    }    /**     * 发现如果继承了WebMvcConfigurationSupport,则在yml中配置的相干内容会生效。 须要从新指定动态资源     *     * @param registry     */    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        registry.addResourceHandler("/**").addResourceLocations(                "classpath:/static/");        registry.addResourceHandler("swagger-ui.html")                .addResourceLocations(                        "classpath:/META-INF/resources/");        registry.addResourceHandler("doc.html")                .addResourceLocations(                        "classpath:/META-INF/resources/");        registry.addResourceHandler("/webjars/**").addResourceLocations(                "classpath:/META-INF/resources/webjars/");        super.addResourceHandlers(registry);    }}

2、Elasticsearch @Document 的 type 属性被废除

原来示例

package com.example.data.es.model;import com.fasterxml.jackson.databind.annotation.JsonSerialize;import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;import lombok.Data;import java.io.Serializable;import org.springframework.data.annotation.Id;import org.springframework.data.elasticsearch.annotations.Document;import org.springframework.data.elasticsearch.annotations.Field;import org.springframework.data.elasticsearch.annotations.FieldType;/** * 学生表 */@Data@Document(indexName = "students", type="student")public class ContentEs implements Serializable{    private static final long serialVersionUID = -1L;    @Id    @JsonSerialize(using= ToStringSerializer.class)    private Long id;    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer="ik_smart")    private String name;}

3、必须独自利用 validation 包

<dependencies>    <!-- Bean Validation with Hibernate validator    https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#validation-starter-no-longer-included-in-web-starters-->    <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-validation</artifactId>    </dependency> </dependencies>
# 依赖包[INFO] +- org.springframework.boot:spring-boot-starter-validation:jar:2.5.1:compile[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.5.1:compile[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.5.1:compile[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.5.1:compile[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.3:compile[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.14.1:compile[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.14.1:compile[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.30:compile[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile[INFO] |  |  \- org.yaml:snakeyaml:jar:1.28:compile[INFO] |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.46:compile[INFO] |  \- org.hibernate.validator:hibernate-validator:jar:6.2.0.Final:compile[INFO] |     +- jakarta.validation:jakarta.validation-api:jar:2.0.2:compile[INFO] |     +- org.jboss.logging:jboss-logging:jar:3.4.2.Final:compile[INFO] |     \- com.fasterxml:classmate:jar:1.5.1:compile

形式

package com.example.data.es.model;import com.fasterxml.jackson.databind.annotation.JsonSerialize;import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;import lombok.Data;import java.io.Serializable;import org.springframework.data.annotation.Id;import org.springframework.data.elasticsearch.annotations.Document;import org.springframework.data.elasticsearch.annotations.Field;import org.springframework.data.elasticsearch.annotations.FieldType;/** * 学生表 */@Data@Document(indexName = "students")public class ContentEs implements Serializable{    private static final long serialVersionUID = -1L;    @Id    @JsonSerialize(using= ToStringSerializer.class)    private Long id;    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer="ik_smart")    private String name;}

跨域日志

java.lang.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.    at org.springframework.web.cors.CorsConfiguration.validateAllowCredentials(CorsConfiguration.java:473) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.cors.CorsConfiguration.checkOrigin(CorsConfiguration.java:577) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.cors.DefaultCorsProcessor.checkOrigin(DefaultCorsProcessor.java:174) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.cors.DefaultCorsProcessor.handleInternal(DefaultCorsProcessor.java:116) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.cors.DefaultCorsProcessor.processRequest(DefaultCorsProcessor.java:95) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:87) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.5.0.jar!/:5.5.0]    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar!/:5.3.8]    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:764) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) [tomcat-embed-core-9.0.46.jar!/:na]    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.46.jar!/:na]    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_212]    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_212]    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.46.jar!/:na]    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_212]

材料参考

Spring Boot 2.5.1 CORS SUpport

Cross-Origin Resource Sharing (CORS)

Spring Framework 1.7.CORS Global Configuration

Spring Security 15.8 CORS

Not possible to use allowedOrigins "*" in StompEndpointRegistry after upgrade to Spring Boot 2.4.0 #26111

Support allowedOriginPatterns in SockJS config #26108

Support for pattern based origin cors configuration #25016

Class CorsFilter Document API

Spring Cloud Gateway

Class CorsConfiguration

Updates to CORS patterns contribution

When allowCredentials is true, allowedOrigins cannot contain the special value "*"

Spring Boot 2.X(十八):集成 Spring Security-登录认证和权限管制

v5.3.0-M2

深究摸索: 依据日志、查看源码、查看官网文档

Spring Boot

// org.springframework:spring-web:5.2.6.RELEASEpackage org.springframework.web.cors;...public class CorsConfiguration {    public static final String ALL = "*";    private static final List<HttpMethod> DEFAULT_METHODS;    private static final List<String> DEFAULT_PERMIT_METHODS;    private static final List<String> DEFAULT_PERMIT_ALL;    // 没有 validateAllowCredentials 函数}

Spring Boot Version: 2.5.1

查看依赖

# mvn dependency:tree[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.5.1:compile[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.5.1:compile[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.12.3:compile[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.12.3:compile[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.12.3:compile[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.5.1:compile[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.46:compile[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.46:compile[INFO] |  +- org.springframework:spring-web:jar:5.3.8:compile[INFO] |  \- org.springframework:spring-webmvc:jar:5.3.8:compile[INFO] |     \- org.springframework:spring-expression:jar:5.3.8:compile

查看 spring-web: 5.3.8 源码

// org.springframework:spring-web:5.3.8package org.springframework.web.cors;...    public class CorsConfiguration {    /** Wildcard representing <em>all</em> origins, methods, or headers. */    public static final String ALL = "*";    private static final List<String> ALL_LIST = Collections.unmodifiableList(                    Collections.singletonList(ALL));    private static final OriginPattern ALL_PATTERN = new OriginPattern("*");    private static final List<OriginPattern> ALL_PATTERN_LIST = Collections.unmodifiableList(                    Collections.singletonList(ALL_PATTERN));    private static final List<String> DEFAULT_PERMIT_ALL = Collections.unmodifiableList(                    Collections.singletonList(ALL));    private static final List<HttpMethod> DEFAULT_METHODS = Collections.unmodifiableList(                    Arrays.asList(HttpMethod.GET, HttpMethod.HEAD));    private static final List<String> DEFAULT_PERMIT_METHODS = Collections.unmodifiableList(                    Arrays.asList(HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()));    @Nullable    private List<String> allowedOrigins;    @Nullable    private List<OriginPattern> allowedOriginPatterns;    @Nullable    private List<String> allowedMethods;    @Nullable    private List<HttpMethod> resolvedMethods = DEFAULT_METHODS;    @Nullable    private List<String> allowedHeaders;    @Nullable    private List<String> exposedHeaders;    @Nullable    private Boolean allowCredentials;    @Nullable    private Long maxAge;    /**     * Construct a new {@code CorsConfiguration} instance with no cross-origin     * requests allowed for any origin by default.     * @see #applyPermitDefaultValues()     */    public CorsConfiguration() {    }    /**     * Construct a new {@code CorsConfiguration} instance by copying all     * values from the supplied {@code CorsConfiguration}.     */    public CorsConfiguration(CorsConfiguration other) {        this.allowedOrigins = other.allowedOrigins;        this.allowedOriginPatterns = other.allowedOriginPatterns;        this.allowedMethods = other.allowedMethods;        this.resolvedMethods = other.resolvedMethods;        this.allowedHeaders = other.allowedHeaders;        this.exposedHeaders = other.exposedHeaders;        this.allowCredentials = other.allowCredentials;        this.maxAge = other.maxAge;    }    /**     * A list of origins for which cross-origin requests are allowed. Values may     * be a specific domain, e.g. {@code "https://domain1.com"}, or the CORS     * defined special value {@code "*"} for all origins.     * <p>For matched pre-flight and actual requests the     * {@code Access-Control-Allow-Origin} response header is set either to the     * matched domain value or to {@code "*"}. Keep in mind however that the     * CORS spec does not allow {@code "*"} when {@link #setAllowCredentials     * allowCredentials} is set to {@code true} and as of 5.3 that combination     * is rejected in favor of using {@link #setAllowedOriginPatterns     * allowedOriginPatterns} instead.     * <p>By default this is not set which means that no origins are allowed.     * However an instance of this class is often initialized further, e.g. for     * {@code @CrossOrigin}, via {@link #applyPermitDefaultValues()}.     */    public void setAllowedOrigins(@Nullable List<String> allowedOrigins) {        this.allowedOrigins = (allowedOrigins != null ? new ArrayList<>(allowedOrigins) : null);    }        ...    /**     * A list of origins for which cross-origin requests are allowed. Values may     * be a specific domain, e.g. {@code "https://domain1.com"}, or the CORS     * defined special value {@code "*"} for all origins.     * <p>For matched pre-flight and actual requests the     * {@code Access-Control-Allow-Origin} response header is set either to the     * matched domain value or to {@code "*"}. Keep in mind however that the     * CORS spec does not allow {@code "*"} when {@link #setAllowCredentials     * allowCredentials} is set to {@code true} and as of 5.3 that combination     * is rejected in favor of using {@link #setAllowedOriginPatterns     * allowedOriginPatterns} instead.     * <p>By default this is not set which means that no origins are allowed.     * However an instance of this class is often initialized further, e.g. for     * {@code @CrossOrigin}, via {@link #applyPermitDefaultValues()}.     */    public void setAllowedOrigins(@Nullable List<String> allowedOrigins) {        this.allowedOrigins = (allowedOrigins != null ? new ArrayList<>(allowedOrigins) : null);    }    /**     * Whether user credentials are supported.     * 是否反对用户凭证     *     * <p>By default this is not set (i.e. user credentials are not supported).     */    public void setAllowCredentials(@Nullable Boolean allowCredentials) {        this.allowCredentials = allowCredentials;    }    // 新版跨域减少 validateAllowCredentials 函数    /**     * Validate that when {@link #setAllowCredentials allowCredentials} is 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.");        }    }}