Angular 4部署WebSphere Liberty后深层路由刷新异常问题
首先咱们先把URL拼接的根源说清楚:你之前在web.xml里配置的<location>/</location>是相对路径,当你在/game/heroes页面刷新时,WebSphere Liberty返回的这个/会被浏览器解析为当前路径下的相对地址(也就是/game/heroes/),再加上Angular路由默认重定向到dashboard,最终就出现了/game/heroes/dashboard这种拼接后的URL——这和Angular路由本身的配置无关,是服务器端的重定向逻辑出了问题。
下面给你两种解决方案,优先推荐第一种(更符合现代单页应用的URL风格):
方案一:配置WebSphere Liberty的请求转发(推荐)
Angular是单页应用,所有路由逻辑都在前端处理,服务器只需要把非静态资源的请求统一转发到index.html就行。你可以通过WebSphere Liberty的rewrite-1.0特性实现:
- 先在
server.xml中启用rewrite特性:
<featureManager> <feature>rewrite-1.0</feature> </featureManager>
- 添加针对
game上下文路径的转发规则:
<rewrite id="angularFallback"> <!-- 匹配/game/下所有非静态资源请求,转发到index.html --> <rule match="^/game/(?!.*\.(css|js|html|png|jpg|jpeg|gif|ico|svg)$).*$" url="/game/index.html" /> </rewrite>
这个规则的作用是:只要请求的不是样式、脚本、图片这类静态资源,就把请求转发到index.html,让Angular的前端路由接管处理。
- 修正
base href设置:
因为你的WAR上下文路径是game,所以应该把base href设为/game/,而不是空字符串。你可以在编译Angular项目时指定:
ng build --base-href /game/
或者直接修改index.html里的base标签:
<base href="/game/">
- 移除
web.xml里之前的错误页配置,rewrite规则已经完全覆盖了404的处理逻辑。
这样配置后,不管你在哪个页面刷新,服务器都会把请求转发到index.html,Angular会读取当前URL的路径,正确加载对应组件,URL也会和刷新前保持一致。
方案二:使用Angular的哈希路由(快速临时方案)
如果你暂时不想修改服务器配置,可以启用Angular的HashLocationStrategy,路由会通过URL的哈希部分(#后面的内容)处理,服务器只会解析哈希前面的/game/路径,不会出现404问题:
修改app-routes.module.ts:
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; // 导入你的组件... const routes: Routes = [ { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, { path: 'dashboard', component: DashboardComponent }, { path: 'detail/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroesComponent } ]; @NgModule({ // 添加useHash: true启用哈希路由 imports: [RouterModule.forRoot(routes, { useHash: true })], exports: [RouterModule] }) export class AppRoutesModule { }
这种方案的缺点是URL会带上#(比如/game/#/dashboard),美观性稍差,但优点是不用修改服务器配置,能快速生效。
总结
你之前的错误页配置因为相对路径的问题导致了URL拼接,通过服务器转发或者哈希路由都能解决刷新页面的路由问题,优先推荐服务器转发的方案,既保持URL整洁,又符合单页应用的标准处理方式。
内容的提问来源于stack exchange,提问作者lwestby

