46

注意:这个问题也可以是:

如何在 Java 中支持无 hashbang 客户端 mvc 框架的书签。

我正在将使用的 Angular 应用程序转换hashtagshtml5mode. 我已经成功设置

$locationProvider.html5Mode(true);

登陆页面 (index.html) 中的所有链接都可以正常工作。

问题是,如果直接引用部分 url,我自然会得到 404,因为服务器端点定义不耦合到客户端定义的路由。

因此,如果没有 HTML5,我们将获得非 SEO 友好的 hashbang,但有了它,我们无法为着陆页(引导 angular 的页面)以外的任何内容添加书签。

如果首先请求默认登录页面(index.html),即 htpp://mydomain.com/ ,为什么它会起作用:

  1. 浏览器从服务器请求 index.html
  2. 服务器返回index.html,浏览器加载angular框架
  3. URL 更改被发送到客户端路由器并加载正确的部分/s。

如果直接从浏览器请求(即) http://mydomain.com/foo ,为什么它不起作用:

  1. 浏览器从服务器请求 mydomain/foo。
  2. 资源不存在
  3. 服务器返回 404

这个故事缺少了一些东西,我只是不知道是什么。这是我能看到的唯一两个答案......

  • 这是设计使然。 这是它应该如何工作的吗?用户必须始终登陆客户端 MVC 框架的引导页面(通常是 index.html),然后从那里导航。这并不理想,因为无法保存状态并且无法添加书签……更不用说爬行了。
  • 服务器解决方案。 这是否与服务器端技巧有关?例如,在所有请求上,返回 index.html 并立即使用附加上下文调用路由器。如果是这样,这违背了 AngularJS 完全是客户端的目标,并且看起来像是一个 hack。
4

3 回答 3

40

AngularJS 文档实际上确实提到了这一点

服务器端 使用此模式需要在服务器端重写 URL,基本上你必须重写所有指向应用程序入口点的链接(例如 index.html)

在这种情况下,一种基于 Java 的解决方案是告诉服务器“将所有 url 映射到 index.html”。这可以在任何 HTTP 服务器或容器中完成。我使用 Java/Servet 实现了这一点,因为我希望我的应用程序与 HTTP 服务器无关(即 Apache 与 NginX,或仅 Tomcat/JBoss)。

在 web.xml 中:

  <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <servlet>
      <servlet-name>StaticServlet</servlet-name>
      <jsp-file>/index.jsp</jsp-file>
  </servlet>

  <servlet-mapping>
      <servlet-name>StaticServlet</servlet-name>
      <url-pattern>/app</url-pattern>
  </servlet-mapping>

index.jsp 看起来就像:

<%@ include file="index.html" %>

并将以下内容添加到 index.html 中的标记中:

<base href="/app" />
于 2013-07-15T23:30:13.320 回答
3

我花了一些时间为我的 PHP 网站考虑这个问题。我将所有服务器端代码挂在/api路由上,以使其与 Angular 分开。这是我通过更新我的 apache 配置提出的解决方案:

RewriteEngine on
#let the php framework do its thing
RewriteRule ^(api/.*)$ index.php?url=$1 [QSA,L,NC]
#let angular do its thing
RewriteCond %{REQUEST_FILENAME} !-f      
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.html [NC,L]

我在http://www.awnage.com/2013/10/10/taking-flight-with-angularjs/上写了我是如何使用 Flight PHP 框架解决这个问题的

于 2013-10-10T15:41:25.807 回答
-3

您链接到并放置在用户地址栏中的 URL 应该引用服务器上的有效内容,并且如果可能的话,它们应该引用正确的内容。当然,您可以为每个 URL 提供相同的页面,然后让客户端代码运行并加载真实内容,并且事情的运行方式与它们在 hash-URL 世界中的运行方式非常相似。事实上,这是代码最少的方法。但它也被称为“破坏互联网”,这就是为什么 HTML5 和 History API 为您提供了一种链接到语义正确的URL 的方法。

举个小例子,如果你去https://github.com/kriskowal/q并点击“examples”,客户端代码会在不离开页面的情况下将“examples”目录加载到文件浏览器中,并且URL 栏将显示https://github.com/kriskowal/q/tree/master/examples。如果您直接访问https://github.com/kriskowal/q/tree/master/examples,您会得到“examples”目录的内容直接发送到您的浏览器,无需客户端代码中介。是的,这更难做到,在“单页应用程序”中可能是不可能的,但只要有可能,这是正确的做法。

于 2013-07-15T23:55:27.887 回答