如何用Spring @RequestMapping精准匹配单级路径及根路径,排除末尾斜杠路径?
Let's break down your problem and fix it step by step—this is a common gotcha with Spring's path matching rules, so you're not alone here!
First, Let's Clear Up the Regular Expression Confusion
You mentioned that @RequestMapping(value = "/[^/]+") didn't match /whatever—that's because Spring's @RequestMapping paths use Ant-style patterns by default, not raw regex. When you write /[^/]+ directly, Spring treats it as a literal path (meaning it would only match a request to https://localhost:8443/[^/]+, not any path like /whatever). To use regex in Spring path mappings, you need the {variableName:regex} syntax.
Core Issue with Your Current Setup
Your original /* pattern matches any single-level path, but Spring's default useTrailingSlashMatch property treats /api and /api/ as equivalent paths. This is why your controller was intercepting Spring Data REST's /api/ endpoint even though you intended to leave it alone.
Solution 1: Strict Path Matching + Targeted Mappings
This is the cleanest approach—we'll disable trailing slash matching and create precise mappings for exactly the paths you want to forward.
First, add a configuration class to disable trailing slash matching (so Spring treats /api and /api/ as distinct paths):
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { // Disable automatic trailing slash matching configurer.setUseTrailingSlashMatch(false); } }
Then update your ForwardController to handle only the paths you need:
@Controller public class ForwardController { // Handle the root path (https://localhost:8443/) @RequestMapping(value = "/", method = RequestMethod.GET) public String redirectRoot() { return "forward:/a/web/index.html"; } // Handle single-level paths without a trailing slash (e.g., /test, /api) // The regex [^/]+ ensures we only match paths with no slashes in the segment @RequestMapping(value = "/{path:[^/]+}", method = RequestMethod.GET) public String redirectSingleLevel() { return "forward:/a/web/index.html"; } }
Solution 2: Manual Path Check (No Configuration Change)
If you don't want to disable trailing slash matching, you can add a manual check in your controller to skip paths ending with a slash:
@Controller public class ForwardController { @RequestMapping(value = {"/*", "/"}, method = RequestMethod.GET) public String redirect(HttpServletRequest request) { String requestURI = request.getRequestURI(); // Skip paths that end with a slash (leave them for Spring Data REST) if (requestURI.endsWith("/")) { return null; // Let Spring find the correct controller for this path } return "forward:/a/web/index.html"; } }
Verify the Fix
Test these scenarios to confirm everything works:
https://localhost:8443/→ Forwards to your index page ✅https://localhost:8443/test→ Forwards to your index page ✅https://localhost:8443/api→ Forwards to your index page ✅https://localhost:8443/api/→ Handled by Spring Data REST ✅https://localhost:8443/api/users→ Handled by Spring Data REST ✅
内容的提问来源于stack exchange,提问作者Stefan Falk

