You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot含特殊字符编码PathVariable时触发CORS错误求助

问题描述

在Spring Boot 2.7.1中实现了一个获取Entity详情的接口,通过@PathVariable从URI中获取ID,普通格式ID(如12345869)请求正常,但当使用RDF数据库的URI格式ID(如<http://www.semanticweb.org/blah/ontologies/2022/6/blah#12345869>,包含<、>、#等特殊字符)时,经JavaScriptencodeURIComponent编码后发起请求,Spring Boot返回CORS错误。

相关代码如下:

控制器代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.semdetect.server.entities.models.Entity;
import com.semdetect.server.entities.services.EntityService;

@RestController
@RequestMapping("api/entity")
public class EntityController {
    private final EntityService entityService;

    @Autowired
    public EntityController(EntityService entityService) {
        this.entityService = entityService;
    }

    @GetMapping("/{iri}")
    public Entity getEntityByIri(@PathVariable String iri) {
        System.out.println("In controller: " + iri);
        return this.entityService.getEntityByIri(iri);
    }
}

CORS配置代码

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootApplication
public class ServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerApplication.class, args);
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").allowedOrigins("http://localhost:4200");
            }
        };
    }
}

POM配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.sem-detect</groupId>
    <artifactId>server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>server</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>18</java.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.eclipse.rdf4j</groupId>
                <artifactId>rdf4j-bom</artifactId>
                <version>3.0.4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.eclipse.rdf4j</groupId>
            <artifactId>rdf4j-client</artifactId>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.eclipse.rdf4j</groupId>
            <artifactId>rdf4j-repository-sparql</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
解决方案

1. 调整路径匹配与Tomcat字符限制

Spring Boot 2.6+默认使用path_pattern_matcher,对路径中的特殊字符拦截较严格,同时Tomcat默认不允许部分特殊字符出现在路径中,需通过配置放开:

在application.properties中添加:

# 切换为宽松的Ant路径匹配器
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
# 允许路径中包含特殊字符
server.tomcat.relaxed-path-chars=<>#[]^`{}
# 允许查询参数中包含特殊字符(按需添加)
server.tomcat.relaxed-query-chars=<>#[]^`{}

2. 完善CORS配置,覆盖预检请求

编码后的特殊字符路径会触发浏览器的OPTIONS预检请求,原CORS配置未明确允许该方法,需补充:

修改CORS配置代码:

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("http://localhost:4200")
                    .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                    .allowedHeaders("*")
                    .allowCredentials(true);
        }
    };
}

3. 优化PathVariable的路径匹配规则

默认@PathVariable不会匹配路径中的斜杠,需通过正则表达式确保完整捕获URI格式的ID:

修改控制器的GetMapping注解:

@GetMapping("/{iri:.+}")
public Entity getEntityByIri(@PathVariable(value = "iri", required = true) String iri) {
    System.out.println("In controller: " + iri);
    return this.entityService.getEntityByIri(iri);
}

其中.+正则表示匹配任意字符(包括斜杠),确保完整获取编码后的URI内容。

4. 前端请求注意事项

确保前端使用encodeURIComponent对完整的URI进行编码,例如:

const iri = "<http://www.semanticweb.org/blah/ontologies/2022/6/blah#12345869>";
const encodedIri = encodeURIComponent(iri);
fetch(`http://localhost:8080/api/entity/${encodedIri}`)
  .then(response => response.json())
  .then(data => console.log(data));

内容的提问来源于stack exchange,提问作者whitefang1993

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:55:03