Spring @RequestMapping 用于除 /api/ 或 /rest/ 之外的所有内容(否定正则表达式中的特定单词)
Spring @RequestMapping for everything except /api/ or /rest/ (negate specific word in regex)
我需要一个 Spring @RequestMapping
,我将使用它来匹配所有非 /api/...
路径,例如 /products
,以便将它们转发到我的 /
(通过 return "forward:/";
) 视图控制器,它实际上提供 index.html
内容并导致前端 (React) 应用程序被提供,以便前端应用程序可以处理此路径以呈现页面。
请注意,隐含的 @RequestMapping
无法匹配 /
,因为它会以无限递归和 WhosebugError
结束。也可能值得排除 index.html
。
换句话说,我希望我的 /api/products
由 Spring 引导应用程序处理 "locally",其中 /products/
应该被转发以呈现 React 应用程序。没有 Apache 或 Nginx 代理 - 由于静态资源映射,React 应用程序由 Spring 提供服务。
我在这方面研究了很多类似的 Whosebug 问题,其中 none 个有效。
重要说明:我在 Whosebug 上看到了问题应该得到解决的案例,只是因为最初它看起来像工作(/products/
转发和 /api/products
由 API 控制器处理),但实际上并非如此,因为提议的正则表达式匹配 所有内容 和 /api/products
仅由 Spring 处理映射优先级(更具体 "wins"),但如果不存在其他控制器,则相同的路径实际上会匹配该模式。
这会导致不适当的 404(或未找到映射)错误处理 - 调用任何甚至不存在的 /api/something
端点最终都会转发到 index.html 我找到的所有答案中,这我想避免。 访问不存在的 /api/something
端点应该以没有找到处理程序 Spring 错误结束,而不是在转发中。 这种解决方案的一个例子是最受欢迎的,喜欢:@RequestMapping(value = "{_:^(?!api).*$}")
问题是,无论我尝试什么模式,它最终都会转发我所有的测试用例(比如 /api
/api/
/api/x
/page/
/page/2
或 none.
只是我尝试过的一些模式示例:
@RequestMapping(value = "{_:^(?!index\.html|api).*$}")
@RequestMapping(value = "{x:^(?!api).*$}")
@RequestMapping(value = "/{path:^(?!api/).*$}")
@RequestMapping(value = "/{dataType:^.*(?!api).*$}")
@RequestMapping(value = "/{arg:(?!sitemap.xml|api|index.html).*$}")
@RequestMapping(value = "{arg:^(?!api|!index.html).*$}/**")
@RequestMapping(value = "{_:^(?!index\.html|api).*$}")
问题仍然有效,但对于需要解决方案的人,我可以建议在过滤器级别转发:
@Bean
public FilterRegistrationBean nonApiRequestToRootPathForwarderFilterRegistrationbean() {
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new Filter() {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
if (!request1.getRequestURI().startsWith("/api/") && !request1.getRequestURI().equals("/")) {
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/");
requestDispatcher.forward(request, response);
return;
}
chain.doFilter(request, response);
}
});
return filterFilterRegistrationBean;
}
看起来原来的正则表达式确实有效(例如 "{_:^(?!index\.html|api).*$}"
)。
问题是,Jetty 显示 404 是在内部转发到 /error
页面,该页面也是该控制器映射的主题!有效地从 public 资源转发到前端应用,而不是呈现错误页面
我需要一个 Spring @RequestMapping
,我将使用它来匹配所有非 /api/...
路径,例如 /products
,以便将它们转发到我的 /
(通过 return "forward:/";
) 视图控制器,它实际上提供 index.html
内容并导致前端 (React) 应用程序被提供,以便前端应用程序可以处理此路径以呈现页面。
请注意,隐含的 @RequestMapping
无法匹配 /
,因为它会以无限递归和 WhosebugError
结束。也可能值得排除 index.html
。
换句话说,我希望我的 /api/products
由 Spring 引导应用程序处理 "locally",其中 /products/
应该被转发以呈现 React 应用程序。没有 Apache 或 Nginx 代理 - 由于静态资源映射,React 应用程序由 Spring 提供服务。
我在这方面研究了很多类似的 Whosebug 问题,其中 none 个有效。
重要说明:我在 Whosebug 上看到了问题应该得到解决的案例,只是因为最初它看起来像工作(/products/
转发和 /api/products
由 API 控制器处理),但实际上并非如此,因为提议的正则表达式匹配 所有内容 和 /api/products
仅由 Spring 处理映射优先级(更具体 "wins"),但如果不存在其他控制器,则相同的路径实际上会匹配该模式。
这会导致不适当的 404(或未找到映射)错误处理 - 调用任何甚至不存在的 /api/something
端点最终都会转发到 index.html 我找到的所有答案中,这我想避免。 访问不存在的 /api/something
端点应该以没有找到处理程序 Spring 错误结束,而不是在转发中。 这种解决方案的一个例子是最受欢迎的,喜欢:@RequestMapping(value = "{_:^(?!api).*$}")
问题是,无论我尝试什么模式,它最终都会转发我所有的测试用例(比如 /api
/api/
/api/x
/page/
/page/2
或 none.
只是我尝试过的一些模式示例:
@RequestMapping(value = "{_:^(?!index\.html|api).*$}")
@RequestMapping(value = "{x:^(?!api).*$}")
@RequestMapping(value = "/{path:^(?!api/).*$}")
@RequestMapping(value = "/{dataType:^.*(?!api).*$}")
@RequestMapping(value = "/{arg:(?!sitemap.xml|api|index.html).*$}")
@RequestMapping(value = "{arg:^(?!api|!index.html).*$}/**")
@RequestMapping(value = "{_:^(?!index\.html|api).*$}")
问题仍然有效,但对于需要解决方案的人,我可以建议在过滤器级别转发:
@Bean
public FilterRegistrationBean nonApiRequestToRootPathForwarderFilterRegistrationbean() {
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new Filter() {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
if (!request1.getRequestURI().startsWith("/api/") && !request1.getRequestURI().equals("/")) {
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/");
requestDispatcher.forward(request, response);
return;
}
chain.doFilter(request, response);
}
});
return filterFilterRegistrationBean;
}
看起来原来的正则表达式确实有效(例如 "{_:^(?!index\.html|api).*$}"
)。
问题是,Jetty 显示 404 是在内部转发到 /error
页面,该页面也是该控制器映射的主题!有效地从 public 资源转发到前端应用,而不是呈现错误页面