1. 背景
今天我们的某个大型商城做UAT, 客户在后台创建了个 商品code 是 0900-PK.3.58-4-A004
的商品, 然后界面可以搜索到, 但是点击进入明细页面报错了
分析logback 日志, 发现了异常, 以及一个怪怪的 商品code
0900-PK.3.58-4-A004
到了controller 层,变成了 0900-PK.3
检查 Controller 中的 rrequestMapping , 感觉没毛病
2. 排查
事务反常必有妖, 老司机遇到了新问题, 我们做过了那么多的官方商城, 商品code 通常都是规整的, 比如 ABC1234, 第一次遇到 0900-PK.3.58-4-A004
的商品Code
OK, let go, 捉妖去~~
源码面前,了无秘密, 开启debug 大法
对于@PathVariable 的参数, 值其实是解析之后,转成map 存放在 request 作用域中, name是 常量 org.springframework.web.servlet.HandlerMapping#URI_TEMPLATE_VARIABLES_ATTRIBUTE
当我去看这个属性值的时候, 发现 uriTemplateVars map 中值 已经被解析成
storeId=2, itemCode=0900-PK.3
那顺藤摸瓜,往上走
发现原来的 路径格式是 /item/{storeId}/{itemCode}
,变成了 /item/{storeId}/{itemCode}.*
好神奇
再往上走 到了 org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getMatchingPattern(String, String)
private String getMatchingPattern(String pattern, String lookupPath) {
if (pattern.equals(lookupPath)) {
return pattern;
}
if (this.useSuffixPatternMatch) {
if (!this.fileExtensions.isEmpty() && lookupPath.indexOf('.') != -1) {
for (String extension : this.fileExtensions) {
if (this.pathMatcher.match(pattern + extension, lookupPath)) {
return pattern + extension;
}
}
}
else {
boolean hasSuffix = pattern.indexOf('.') != -1;
if (!hasSuffix && this.pathMatcher.match(pattern + ".*", lookupPath)) {
return pattern + ".*";
}
}
}
if (this.pathMatcher.match(pattern, lookupPath)) {
return pattern;
}
if (this.useTrailingSlashMatch) {
if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath)) {
return pattern +"/";
}
}
return null;
}
表示, 如果 开启了 useSuffixPatternMatch (默认值是 true) ,且路径中有 .号, 将会把. 后面的部分解析为 扩展名
因此就变成了 最后面一个 . 之前的是 商品code ,这就导致了 0900-PK.3.58-4-A004
到了controller 层,变成了 0900-PK.3
如何解决呢?
3. 解决方案
方案A: 全局统一处理
直接在 mvc:annotation-driven 加入 <mvc:path-matching suffix-pattern="false" />
<mvc:annotation-driven>
<!--
add by feilong ,do with http://127.0.0.1:8091/item/2/0900-PK.3.58-4-A004
see http://jira.baozun.cn/browse/BBFED-3045
-->
<mvc:path-matching suffix-pattern="false" />
...
如果该特性, since spring 3.1
方案B
可以在 pdp controller 中把路径改成 /item/{storeId}/{itemCode:.+}
方案C
新建个单独的类 MvcConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
@Configuration
public class MvcConfig extends WebMvcConfigurationSupport{
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
handlerMapping.setUseSuffixPatternMatch(false);
handlerMapping.setUseTrailingSlashMatch(false);
return handlerMapping;
}
}
4. 参考
https://stackoverflow.com/questions/16332092/spring-mvc-pathvariable-with-dot-is-getting-truncated
相关推荐
当我们在控制器方法的参数前添加`@PathVariable`时,Spring MVC会自动将URL中对应的部分映射到该参数上。例如,对于URL `/users/{userId}`,我们可以定义如下控制器方法: ```java @GetMapping("/users/{userId}") ...
RESTful服务鼓励使用HATEOAS,它提倡在响应中包含链接,使客户端可以根据链接发现资源,而不是硬编码URL。 **实例步骤:** 1. 创建Spring MVC项目,引入相关依赖(Spring Web、Spring Web MVC、Jackson等)。 2. ...
### 使用Java Spring框架的核心概念与实践 #### 一、Spring框架概述 Spring框架是一个轻量级的开源Java平台,主要用于企业级应用开发。它通过提供一系列的开发工具和框架来帮助开发者快速构建稳定且可扩展的应用...
在Spring注解驱动的开发中,我们通常会遇到如Bean的生命周期、AOP的实现原理、以及Spring MVC的DispatcherServlet工作模式等主题。对于这些内容,深入阅读源码可以帮助我们理解Spring如何高效地管理bean,如何实现切...
4.2.x版本对Spring MVC进行了优化,增强了模型视图解析器(ModelAndViewResolver)的性能,提供了更好的RESTful支持,如@PathVariable、@MatrixVariable等。此外,还引入了ModelAttribute注解,简化了模型数据的绑定...
在Spring MVC中,接收请求参数有多种方式,包括@RequestParam、@PathVariable、@RequestBody以及@ModelAttribute。这些注解各自适用于不同的场景,并且与HTTP请求的方法(GET、POST等)和Content-Type紧密相关。以下...
**Spring MVC 概述** Spring MVC 是 Spring 框架的一部分,它是一个用于构建 Web 应用程序的轻量级、模型-视图-控制器(MVC)框架。Spring MVC 提供了处理 HTTP 请求和响应的机制,以及解耦业务逻辑和用户界面的...
9. **RESTful服务**:Spring Web模块可以帮助创建RESTful风格的服务,通过@RestController和@RequestMapping等注解实现。 10. **静态资源处理**:Spring MVC可以通过配置轻松地处理静态资源,如CSS、JavaScript和...
Spring MVC 是一个基于Java的轻量级Web应用框架,它是Spring框架的重要组成部分,主要用于构建Web应用程序的后端控制器。在本教程中,我们将深入探讨Spring MVC的核心概念、配置、使用方法以及它如何与Spring框架...
首先,依赖注入是Spring的核心特性,允许对象之间的关系在运行时被外部容器管理,而不是硬编码在类内部。Spring 3.1.0引入了更强大的注解配置支持,使得开发者可以通过注解轻松地声明依赖关系,减少了XML配置的复杂...
《Spring注解详解:从1.x到5.x的演变与应用》 在Java开发领域,Spring框架无疑是最具影响力和广泛使用的轻量级框架之一。随着版本的不断迭代,Spring框架逐渐引入并强化了注解的使用,极大地简化了代码,提高了开发...
11. **RESTful支持**:Spring MVC支持创建RESTful风格的Web服务,通过@PathVariable、@RequestParam等注解处理URL路径变量和请求参数。 12. **MVC注解**:例如@RequestMapping、@GetMapping、@PostMapping等,用于...
在Java开发中,元数据编程是一种强大的工具,它允许开发者通过元数据来描述代码的行为,而不是硬编码在程序中。这种技术在很多框架中得到广泛应用,例如Spring框架。本篇文章将探讨如何在Java环境中,利用元数据编程...
### 构建RESTful Web服务与Spring框架 #### 一、基础知识 在构建RESTful Web服务时,了解REST的基本原则是至关重要的。REST(Representational State Transfer)是一种用于设计网络应用程序的架构风格,其核心原则...
Spring MVC 提供了灵活的处理机制,包括处理器映射、视图解析、数据绑定、本地化和主题支持,以及对 RESTful 风格的 URL 支持,使得开发人员可以轻松地创建功能丰富的、高性能的 Web 应用。 ### 1. MVC 架构模式 ...
### Spring Boot 前后端传值知识点详解 #### 一、@RequestParam 注解 - **定义**:`@RequestParam` 注解主要用于处理 Content-Type 为 `application/x-www-form-urlencoded` 编码的内容,适用于 GET 或 POST 请求...
12. **RESTful 风格的支持**:通过 @PathVariable 注解,Spring MVC 支持创建符合 RESTful 风格的 URL,方便构建 Web 服务。 13. **本地化与主题支持**:Spring MVC 提供了本地化和主题支持,可以依据用户偏好显示...
Spring MVC的组件包括`@Controller`注解的控制器类、`@RequestMapping`处理请求、`@RequestParam`、`@PathVariable`等获取请求参数的方式,以及`ModelAndView`对象用于返回视图和模型数据。 7. **RESTful支持** ...
- JSON 格式广泛用于 RESTful API 中的数据传输,Spring MVC 提供了 Jackson 或 Gson 等库进行 JSON 编码和解码。 12. **安全控制(Security)**: - Spring Security 可以与 Spring MVC 结合,提供认证、授权等...