我在Spring Boot应用程序中有VueJS单页面应用程序,我想让vue-router处理所有请求,而不是那些url以/rest/**
开头的请求。
所以我写了正则表达式^(?!/rest/).*
以匹配所有不以/rest/
开头的内容,我尝试将请求映射为:
@Controller
public class MainController {
@RequestMapping(value = "/{path:^(?!/rest/).*}")
public String forwardRequests() {
return "forward:/";
}
}
但它不起作用。我做错了什么?
修改
我有休息控制器文件:
@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);
}
}
返回带有项目详细信息的JSON。我有一些像/login
和/projekty
这样的网页,所以我需要将它们转发到index.html
来处理使用vue的路由。我知道我可以这样做:
@Controller
public class MainController {
@RequestMapping(value = {"/login", "/projekty"}, method = RequestMethod.GET)
public String forwardRequests() {
return "forward:/";
}
}
并且效果很好,但我不想明确指定每个网址,这就是我尝试使用正则表达式的原因。而且我认为我使用错误的path
变量,但我不知道如何。
https://spring.io/guides/tutorials/spring-security-and-angular-js/部分Using "Natural" Routes
答案 0 :(得分:4)
好吧,正如@JDB所说,AntPathMatcher
比较路径并找到最佳匹配。因此,您不必担心具有指定路径的端点,例如我的/rest
api。
您可以添加:
@RequestMapping(value = "/{path:[^\\.]*}")
public String redirect() {
return "forward:/";
}
以及您的所有要求,例如。 /login
,会正确转发到index.html
,javascript可以处理它。
问题在于/project/edit/33
等网址。它们与此正则表达式不匹配,因此您将看到Whitelabel Error Page 404 Not Found
。你可以这样写:
@RequestMapping(value = "/**/{path:[^\\.]*}")
public String redirect() {
return "forward:/";
}
并且工作正常,但如果您启用了安全性,则/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"
}
所以你必须排除oauth网址:
@RequestMapping(value = {"/{path:[^\\.]*}", "/**/{path:^(?!oauth).*}/{path:[^\\.]*}"}, method = RequestMethod.GET)
public String forward() {
return "forward:/";
}
它工作正常。
如果您遇到框架提供的其他终结问题,例如/health
,您可以将正则表达式更改为/**/{path:^(?!oauth|health).*}/{path:[^\\.]*}
它看起来很糟糕,但它确实有效。我相信有人会在这里发布一个更好,更清洁的解决方案。
答案 1 :(得分:1)
我并不专门了解春天,所以我只是根据其他框架的经验做出最好的猜测。
首先,该模式不应该排除正斜杠,因为您已经将它包含在路径中了吗?
/{path:^(?!rest/).*}
如果这不起作用,那么我只能想到AntPathMatcher不支持前瞻。
此设计的典型模式是实现/rest/*
和/*
路由。在某些框架中,这只是正确地排序它们。根据{{3}},您可能需要使用规则来制定/rest/*
路线"更具体的"。
以下是规则:
当多个模式与URL匹配时,必须对它们进行比较以找到最佳匹配。这是通过AntPathMatcher.getPatternComparator(String path)完成的,它查找更具体的模式。
如果模式的URI变量数较少,单个通配符计为1,双通配符计为2,则模式不太具体。给定相等的分数,选择较长的模式。给定相同的分数和长度,选择具有比通配符更多的URI变量的模式。
默认的映射模式/ **从评分中排除,并始终排在最后。另外,诸如/ public / **之类的前缀模式被认为不如没有双通配符的其他模式具体。
有关完整详细信息,请参阅AntPathMatcher中的AntPatternComparator,并记住可以自定义使用的PathMatcher实现。请参阅配置部分中的路径匹配。
因此,基于我对这些规则和代码的解释,我认为这些方面的内容可行:
// Your more specific patterns will take precedence
@RequestMapping(value = "/rest/**")
public String handleRestRequests() {
// forward this to your rest services
}
}
// Your less specific patterns will only apply if the more specific ones don't match
@RequestMapping(value = "/**")
public String forwardRequests() {
// Everything else
return "forward:/";
}
}
答案 2 :(得分:0)
再看一下......你的字符串是/{path:^(?!/rest/).*}
。
有第一个/
,然后正则表达式也声明第一个/
。此正则表达式将匹配/rest/*
,因为它会验证/(?!/rest/).*
而非(?!/rest/).*
。
旧答案和错误,请参阅@JDB评论
/
字符是正则表达式中的特殊字符,需要进行转义。
@Controller
public class MainController {
@RequestMapping(value = "/{path:^(?!\\/rest\\/).*}")
public String forwardRequests() {
return "forward:/";
}
}
由于\
也是Java中字符串的转义字符,因此需要其中2个。
答案 3 :(得分:0)
您可以添加默认的处理程序方法
@RequestMapping()
String default(){
return "This is a default method";
}