【发布时间】:2015-07-26 16:34:33
【问题描述】:
我对这个主题做了很多研究,但没有找到正确或具体的答案,所以在打开 Spring MVC 项目的 jira 票之前,我在这里问它。
我的应用程序是使用 Spring MVC(带有 spring boot)作为后端和 AngularJS 1.x 在前端构建的。我还激活了 html5mode(所以,没有使用 #,只是像 http://podcast.dk.lan/podcasts/123/items/456/player 这样的普通 url)。
我在后端有一个 @Controller 路由,将“/”请求重定向到我的 index.html。 所有其他路由都由 @RestController 处理并使用 JSON(在“/api”或“/system”上)。
我已经寻找了将所有 AngularJS 路由映射到我的应用程序的 index.html 的正确方法,而不会破坏后端解析器的其他部分(例如资源)。
我尝试了以下元素:
@Controller
public class HomeController {
@RequestMapping(value = "/{.*}")
private String home() {
return "forward:/";
}
}
它不起作用,因为如果我尝试直接访问前端的嵌套 url(如 /podcasts/1/items/1 ),则请求映射正则表达式不会捕获该 url。
@Controller
public class HomeController {
@RequestMapping(value = "/**/{.*}")
private String home() {
return "forward:/";
}
}
此配置导致 StackOverFlow 错误,因为 url 将重定向到自身...
最近,在一篇关于 Spring-Security 和 AngularJS 的非常好的教程中,他们使用了以下模式:
@Controller
public class HomeController {
@RequestMapping(value = "/{[path:[^\\.]*}")
private String home() {
return "forward:/";
}
}
此模式通过排除任何带有 . (点)在网址中。不幸的是,它不适用于嵌套路由...返回 404 错误。
所以,我的应用后端现在链接到我的路由前端,因为我必须将前端使用的 AngularJS 路由硬编码为请求映射值:
@Controller
public class HomeController {
@RequestMapping(value = {"", "items", "podcasts", "podcasts/**", "player", "podcast-creation", "download", "stats"})
private String home() {
return "forward:/";
}
}
我认为(并且我希望)有一个更好的解决方案可以将所有“尚未映射的 url 后端映射”重定向到这样的特定方法。
我项目的所有代码都托管在 github 上(如果您想查看更多代码)davinkevin/Podcast-Server
感谢您的帮助
【问题讨论】:
-
Angular 路由应该只映射到客户端。在后端,您应该只映射入口点页面。作为单页应用程序,其余的路由在客户端进行管理。
-
放下你的控制器。添加 2 个视图控制器,第一个用于
/到index.html,/**用于转发。视图控制器将在所有其他控制器之后处理(最低优先级)。 -
@tarini :我谈论的问题与 Angular 中激活的 HTML5Mode 相关联,创建没有任何 hashbang 的 url。如果什么都不做,这个引导特定路由(除了简单的“/”)将由后端系统解释。
-
@M.Deinum:你能给我举个例子吗?您谈论在扩展 WebMvcConfigurerAdapter 的类中定义的视图控制器?
-
覆盖
addViewControllers方法并创建2 个视图控制器,而不是尝试添加自己的。在/**之前映射/应该可以工作,或者只是创建一个/**将所有内容重定向到index.html 文件。
标签: angularjs spring spring-mvc