映射所有请求而不是Spring Boot中的特定模式

koj*_*jot 7 regex spring spring-security spring-boot

我在Spring Boot应用程序内部有VueJS单页应用程序,我想让vue-router处理所有请求,而不是这些以url开头的请求/rest/**

因此,我编写了正则表达式^(?!/rest/).*以匹配不以开头的所有内容,/rest/然后尝试使请求映射如下:

@Controller
public class MainController {

@RequestMapping(value = "/{path:^(?!/rest/).*}")
    public String forwardRequests() {
        return "forward:/";
    }
}
Run Code Online (Sandbox Code Playgroud)

但这不起作用。我做错了什么?

编辑

我有休息控制器文件:

@RestController
@RequestMapping(path = "/rest/project")
public class ProjectController {

    @Autowired
    private ProjectService projectService;

    @GetMapping(value = "/{id}")
    public Project getProjectById(@PathVariable Long id) {
        return projectService.getProjectById(id);
    }
}
Run Code Online (Sandbox Code Playgroud)

它返回带有项目详细信息的JSON。我有一些类似的页面/login/projekty因此我需要转发它们index.html以处理vue路由。我知道我可以做这样的事情:

@Controller
public class MainController {

    @RequestMapping(value = {"/login", "/projekty"}, method = RequestMethod.GET)
    public String forwardRequests() {
        return "forward:/";
    }
}
Run Code Online (Sandbox Code Playgroud)

而且效果很好,但是我不想明确指定每个网址,这就是为什么我尝试使用正则表达式的原因。而且我认为我使用了错误的path变量,但我不知道如何。

https://spring.io/guides/tutorials/spring-security-and-angular-js/部分Using "Natural" Routes

koj*_*jot 6

好吧,正如@JDB所说,AntPathMatcher比较将比较路径并找到最佳匹配。因此,您不必担心具有指定路径的端点,例如我的/restapi。

您可以添加以下内容:

@RequestMapping(value = "/{path:[^\\.]*}")
public String redirect() {
  return "forward:/";
}
Run Code Online (Sandbox Code Playgroud)

和您所有的请求,例如 /login,将正确转发到index.html,JavaScript可在其中进行处理。

问题出在URL之类的/project/edit/33。它们与该正则表达式不匹配,因此您将看到Whitelabel Error Page 404 Not Found。您可以这样写:

@RequestMapping(value = "/**/{path:[^\\.]*}")
public String redirect() {
  return "forward:/";
}
Run Code Online (Sandbox Code Playgroud)

并且工作正常,但是如果启用了安全性,/ouath/token则将返回:

{  
   "timestamp":"2018-02-05T09:13:28.104+0000",
   "status":405,
   "error":"Method Not Allowed",
   "exception":"org.springframework.web.HttpRequestMethodNotSupportedException",
   "message":"Request method 'POST' not supported",
   "path":"/oauth/token"
}
Run Code Online (Sandbox Code Playgroud)

因此您必须排除oauth网址:

@RequestMapping(value = {"/{path:[^\\.]*}", "/**/{path:^(?!oauth).*}/{path:[^\\.]*}"}, method = RequestMethod.GET)
public String forward() {
    return "forward:/";
}
Run Code Online (Sandbox Code Playgroud)

而且效果很好。

如果您对框架提供的其他端点有疑问,/health可以将正则表达式更改为/**/{path:^(?!oauth|health).*}/{path:[^\\.]*}

看起来糟透了,但是可以用。我相信有人会在这里发布更好更好的解决方案。