问题描述
使用spring-boot-migrator工具把项目从jdk8升级到jdk17后,controller中暴漏的rest接口从javaee切换为了springmvc,请求路径以/结尾的接口无法正常访问 比如一个Controller中有如下两个接口,在使用javaee时,/user/可以正常匹配到/user接口,但是切换到springmvc后,/user/调用方式只能匹配到/user/{id}接口
@RequestMapping(value = "/user/{id}", produces = JSON_UTF8, method = RequestMethod.GET)
public User find(@PathVariable("id") String id) {
return super.find(id);
}
@Override
@RequestMapping(value = "/user",produces = JSON_UTF8, method = RequestMethod.GET)
public List<User> findAll() {
return super.findAll();
}
解决方案
增加Filter,识别出以/结尾的请求url,修改url为截取/之前的内容
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
public class PathModifyingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化代码(如果有的话)
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
if (requestURI.endsWith("/")) {
// 创建一个包装器来修改请求URI
HttpServletRequestWrapper modifiedRequest = new HttpServletRequestWrapper(httpRequest) {
@Override
public String getRequestURI() {
return requestURI.substring(0, requestURI.length() - 1);
}
@Override
public StringBuffer getRequestURL() {
StringBuffer url = new StringBuffer(httpRequest.getScheme());
url.append("://");
url.append(httpRequest.getServerName());
if (httpRequest.getServerPort() != 80 && httpRequest.getServerPort() != 443) {
url.append(":").append(httpRequest.getServerPort());
}
url.append(getRequestURI());
return url;
}
};
// 使用修改后的请求继续过滤链
chain.doFilter(modifiedRequest, response);
} else {
// 如果路径不以/结尾,则直接继续过滤链
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
// 销毁代码(如果有的话)
}
}
把Filter注册到spring中
import jakarta.annotation.Resource;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SpringWebConfig {
@Bean
public FilterRegistrationBean<PathModifyingFilter> registrationPathModifyingFilter() {
return new FilterRegistrationBean<>(new PathModifyingFilter());
}
}
这样,当请求/user/后实际会匹配到/user;/user/id会匹配到/user/{id}接口,保持和升级前行为一致。 实际上调用方请求/user接口时最后不应该带/,后续新接口需要规范调用