2

我正在开发一个在 Websphere Application Server Liberty 配置文件版本 17.0.0.3 下运行的应用程序和服务器。我已经在 Angular 4 中开发了 Web 应用程序。只要我不尝试刷新/重新加载网页,一切都运行良好。当我尝试重新加载网页时,收到 404 Not Found 错误。我怀疑问题是完整的 url 在刷新时被传递给服务器。(请参阅 Ben Cole 对这篇文章的回复: #/ 在 url 中的含义是什么?

我的问题是我不确定将主题标签注入应用程序代码中的 url 的最佳方法是什么。我尝试简单地将其添加到 html 中的 routerLink 值,但 url 被编码,将主题标签转换为 %23,然后我的路由器无法识别 url。

我的 Angular 4 应用程序使用来自 @angular/router 的 Routes 和 RouterModule。例如,我的路线定义如下:

const routes: Routes = [
{
    path: '', component: LayoutComponent,
    children: [
        { path: 'dashboard', loadChildren: './dashboard/dashboard.module#DashboardModule' },
        { path: 'versions', loadChildren: './versions/versions.module#VersionsModule' }
  ]
}

在我的 html 中,我以这种方式导航到它们:

<a [routerLink]="['/versions']" 
   [routerLinkActive]="['router-link-active']" class="list-group-item">
                        <i class="fa fa-fw"></i>Versions</a>

我的服务器网址是:http://localhost:9080/zss。当我导航到我的仪表板时,网址是:http://localhost:9080/zss/dashboard 但如果我尝试刷新此网页,我会收到 404 Not Found 错误。我想我需要让 Angular 应用程序导航到以下网址: http://localhost:9080/zss/#dashboard但我不确定在哪里调整代码来执行此操作或如何克服发生的 uri 编码。

4

2 回答 2

4

我现在正在开发一个使用 Liberty 和 Angular 的项目,我们遇到了完全相同的问题。出现问题的原因是 Angular 将所有内容都视为单页应用程序,并自行处理所有 URL 路由和导航。

当您刷新浏览器时,HTTP get 请求将被发送到 Liberty 服务器,类似于http://localhost:9080/zss/dashboard,Liberty 不知道如何处理,因为/zss/路径之外的所有内容都由 Angular 处理。

为了解决这个问题,我们包含了一个 web.xml(位于您的 webapp 的 WEB-INF/ 文件夹中),其中包含以下内容:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <error-page>
        <error-code>404</error-code>
        <location>/</location>
    </error-page>
</web-app>

这解决了问题,因为它将所有 404 错误重新路由到应用程序的根目录,从而允许 Angular 处理路由。

于 2018-02-08T04:17:59.803 回答
2

为了扩展已接受的答案,Angular 利用HTML5来编辑浏览器的历史记录和位置,以模拟页面之间的移动,即使它看起来只是浏览器/服务器的一个真实“页面”。

正如该答案所说,当您刷新页面并且浏览器发出对它认为正在查看的资源的请求时,就会出现困难,而该资源实际上并不存在。设置 web.xml 以将所有 404 重定向到应用程序根目录允许您继续使用 HTML5 URL,但如果您由于某种原因无法支持该历史 API,您可以切换路由器以HashLocationStrategy使用app-routing.module.ts

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(routes, { useHash: true })
  ], 

它将 URL 更改为在真实路径之后包含 # 并在其后放置角度路由(例如contextroot/detail/id变为contextroot/#/detail/id.)。这更兼容,但删除了用服务器渲染页面替换应用程序中某些角度路由的能力。请参阅相关的 Angular 文档

于 2018-02-08T15:07:37.543 回答