在 Spring Boot 3 中,它们已发生更改,默认情况下不再忽略尾部斜杠。例如,如果我有一个 GET 资源
/users
,并且导航到 /users/
,那么 Spring Boot webflux 现在将响应 404。
您可以通过实现
WebFluxConfigurer
并覆盖 configurePathMatching
方法来更改此设置:
@Override
public void configurePathMatching(PathMatchConfigurer configurer) {
configurer.setUseTrailingSlashMatch();
}
但是,
setUseTrailingSlashMatch
已被弃用,文档说使用PathPatternParser.setMatchOptionalTrailingSeparator(boolean)
代替。但是,我不明白您实际如何/在哪里配置它。
那么问题来了,如何设置
PathPatternParser.setMatchOptionalTrailingSeparator(boolean)
?
正如 @joe-clay 在他的评论中提到的,
PathPatternParser.setMatchOptionalTrailingSeparator(boolean)
也已被弃用,转而支持显式重定向。所以你有 3 个选择:
在控制器处理程序中显式声明两条路由
@GetMapping({"/users", "/users/"})
。缺点是您需要为每个控制器执行此操作,但可以用作权宜之计。
实现
org.springframework.web.server.WebFilter
接口以显式重定向到所需的 url。沿着这些思路:
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
URI originalUri = exchange.getRequest().getURI();
if (/* check condition for trailing slash using originalUri getPath(), getQuery() etc. */) {
String originalPath = originalUri.getPath();
String newPath = originalPath.substring(0, originalPath.length() - 1); // ignore trailing slash
try {
URI newUri = new URI(originalUri.getScheme(),
originalUri.getUserInfo(),
originalUri.getHost(),
originalUri.getPort(),
newPath,
originalUri.getQuery(),
originalUri.getFragment());
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.MOVED_PERMANENTLY); // optional
response.getHeaders().setLocation(mutatedUri);
return Mono.empty();
} catch (URISyntaxException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
return chain.filter(exchange);
}
rewrite
规则)以匹配预期的 url。在选项 2 和 3 中,您也可以选择返回
HTTP 301
响应。
可以通过添加以下过滤器来解决此问题:
@Component
public class ServletRequestWrapperFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper((HttpServletRequest) request) {
@Override
public String getRequestURI() {
String requestURI = super.getRequestURI();
if (StringUtils.endsWith(requestURI, "/")) {
return StringUtils.removeEnd(requestURI, "/");
}
return requestURI;
}
};
chain.doFilter(requestWrapper, response);
}
}