Spring中如何处理可变长度路径段并提取对象和属性信息
Spring 处理无上限嵌套可变路径段的最优方案
Spring 本身没有直接提供自动拆分交替可变路径段的注解,结合你的业务场景(对象、属性交替出现,无深度上限),最优的实现方案分两种,根据你使用的Spring版本选择即可:
Spring 5.3+ (对应Spring Boot 2.4+)版本
直接使用PathPattern原生支持的剩余路径捕获变量语法{*变量名},可以一次性匹配所有后续路径段,无需手动从请求属性中提取路径:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.nio.charset.StandardCharsets; import java.net.URLDecoder; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @RestController public class ObjectAttributeController { @GetMapping("/application-root/{*segments}") public Object getNestedAttribute(@PathVariable String segments) { // 处理URL编码,拆分路径段 String decodeSegments = URLDecoder.decode(segments, StandardCharsets.UTF_8); List<String> pathSegments = Arrays.stream(decodeSegments.split("/")) .filter(seg -> !seg.isBlank()) .toList(); // 校验路径符合「对象-属性」交替的偶数段规则 if (pathSegments.size() % 2 != 0) { throw new IllegalArgumentException("请求路径不符合规范,必须为对象、属性交替的格式"); } // 按顺序提取成对的对象和属性 Map<String, String> objectAttrPairs = new LinkedHashMap<>(); for (int i = 0; i < pathSegments.size(); i += 2) { objectAttrPairs.put(pathSegments.get(i), pathSegments.get(i + 1)); } // 你的业务逻辑:按顺序读取嵌套对象的属性即可 // ...... return null; } }
低于Spring 5.3版本
如果你的项目Spring版本较低,不支持上述剩余路径捕获语法,可以使用**通配符匹配任意深度路径,手动从请求上下文中提取路径:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.HandlerMapping; import javax.servlet.http.HttpServletRequest; import java.nio.charset.StandardCharsets; import java.net.URLDecoder; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @RestController public class ObjectAttributeController { @GetMapping("/application-root/**") public Object getNestedAttribute(HttpServletRequest request) { // 提取匹配到的所有后续路径 String fullPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); String suffixPath = fullPath.replaceFirst("^/application-root/?", ""); String decodePath = URLDecoder.decode(suffixPath, StandardCharsets.UTF_8); List<String> pathSegments = Arrays.stream(decodePath.split("/")) .filter(seg -> !seg.isBlank()) .toList(); // 后续校验、解析逻辑和上面的方案完全一致 // ...... return null; } }
注意事项
- 两种方案都没有嵌套深度限制,可以适配任意层的对象-属性嵌套需求
- 如果路径段中包含
/以外的特殊字符,建议先做URL解码再拆分处理 - 可以根据业务需要增加路径段的非法字符校验,避免注入风险
内容的提问来源于stack exchange,提问作者FrustratedWithFormsDesigner
相关产品推荐
相关产品推荐

