Cant szczegółowo wyjaśnić, dlaczego tak się dzieje, ale mogę opisać wam drogę I rozwiązać ten problem. Więc użyłem UrlRewriterFilter dla mojego zaplecza SpringMvc. Konfiguracja ogólnego modułu kątowego:
var app = angular.module('ilonaChatGeneralModule',
[
'ui.router'
]);
app.config(function($locationProvider){
$locationProvider.html5Mode(true);
});
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
var home = ['/', {
url: '/',
templateUrl: 'views/userlist.html'
}];
var login = ['login', {
url: '/login',
templateUrl: 'views/login.html'
}];
var privateRoom = ['privateroom', {
url: '/privateroom',
templateUrl: 'views/privateroom.html'
}];
$stateProvider
.state(home)
.state(login)
.state(privateRoom)
;
});
Moja strona główna, indeks.html:
<html ng-app="ilonaChatGeneralModule" ng-controller="ilonaChatGeneralCtrl">
<head>
<base href="/">
...
</head>
<body>
<div>
<div ui-view=""></div>
</div>
</body>
</html>
To jest frontend. Dla backend użyłem UrlRewriteFilter, można go pobrać z następującej zależności maven:
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.3</version>
</dependency>
Dodałem go do mojego SpringMVC WebAppInitializer w następny sposób:
package com.sbk.config;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter;
import javax.servlet.*;
import java.nio.charset.StandardCharsets;
import java.util.EnumSet;
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private static final String URL_REWRITE_FILTER_NAME = "urlRewrite";
private static final String URL_REWRITE_FILTER_MAPPING = "/*";
...
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
FilterRegistration.Dynamic urlReWrite = servletContext.addFilter(URL_REWRITE_FILTER_NAME, new UrlRewriteFilter());
EnumSet<DispatcherType> urlReWriteDispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
urlReWrite.addMappingForUrlPatterns(urlReWriteDispatcherTypes, true, URL_REWRITE_FILTER_MAPPING);
}
}
Ten filtr wymaga urlrewrite.xml plik w ur Katalog WEB-INF (wygląda jak w konfigurowalnym, ale domyślnym miejscu - tutaj). Zawartość tego pliku:
<!DOCTYPE urlrewrite
PUBLIC "-//tuckey.org//DTD UrlRewrite 2.6//EN"
"http://www.tuckey.org/res/dtds/urlrewrite2.6.dtd">
<urlrewrite>
<rule>
<from>/login$</from>
<to>index.html</to>
</rule>
<rule>
<from>/privateroom$</from>
<to>index.html</to>
</rule>
</urlrewrite>
nie uważnie przeczytać instrukcje, ale podejrzewam, że pomysł jest po odświeżeniu ur przeglądarka z http://yourhost:xxxx/privateroom ur aplikacja spróbować znaleźć physicaly istniejącego widoku http://yourhost:xxxx/privateroom. Ale jest nieobecny. A kiedy przekierujesz go do strony głównej, narożnik zbudowałby poprawne łącze do pliku fizycznego, używając definicji stanów. Mogę się pomylić w teorii, ale działa w praktyce.
To w zasadzie rozwiązanie. Jedna rzecz, którą chciałbym dodać: jeśli serwer zaplecza obsługuje także dane dynamiczne, np. API, chcesz wyizolować interfejs API z tego przekierowania, więc musisz dodać tę regułę tylko wtedy, gdy plik pasujący do żądania nie istnieje i nie jest dopasowywana żadna inna trasa API. –
Dobra uwaga. Zaktualizowałem moją odpowiedź. Jeśli chodzi o interfejsy API, wolę je uruchamiać z oddzielnego adresu URL/domeny. –
Istnieje dobry przykład NodeJS obsługujących SPA tutaj: http://stackoverflow.com/questions/20396900/angularjs-routing-in-expressjs – mbokil