Springboot/Angular2 - Как обрабатывать URL-адреса HTML5?
Я считаю, что это простой вопрос, но я не мог найти ответ или хотя бы использовать правильные термины в поиске.
Я настраиваю Angular2
и Springboot
вместе. По умолчанию Angular
будет использовать пути, такие как localhost:8080\dashboard
и localhost:8080\dashboard\detail
.
Я хотел бы избежать использования пути как хэш, если это возможно. Как Angular документация заявляет:
Функция router обеспечиватьRouter устанавливает свойство LocationStrategy в PathLocationStrategy, что делает его стратегией по умолчанию. Мы можем переключиться на HashLocationStrategy с переопределением во время процесса начальной загрузки, если мы предпочитаем его.
И затем...
Почти все Angular 2 проекта должны использовать стиль HTML по умолчанию. Он создает URL-адреса, которые пользователям легче понять. И он сохраняет возможность выполнения рендеринга на стороне сервера позже.
Проблема в том, что когда я пытаюсь получить доступ к localhost:8080\dashboard
, Spring будет искать некоторое сопоставление контроллера этому пути, которого у него не будет.
Whitelabel Error Page
There was an unexpected error (type=Not Found, status=404).
No message available
Сначала я думал, что все мои службы будут находиться под localhost:8080\api
и все мои статические под localhost:8080\app
. Но как я могу сказать Spring игнорировать запросы к этому пути app
?
Есть ли лучшее решение с Angular2 или Boot?
Ответы
Ответ 1
У меня есть решение для вас, вы можете добавить ViewController
для пересылки запросов на Angular из Spring загрузки.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ViewController {
@RequestMapping({ "/bikes", "/milages", "/gallery", "/tracks", "/tracks/{id:\\w+}", "/location", "/about", "/tests","/tests/new","/tests/**","/questions","/answers" })
public String index() {
return "forward:/index.html";
}
}
здесь я перенаправил все мои angular2 ( "/bikes", "/milages", "/gallery", "/tracks", "/tracks/{id:\w +}", "/location", "" /about "," /tests "," /tests/new "," /tests/ ** "," /questions "," /answers ") в мой SPA
Вы можете сделать то же самое для своего предлога, и вы также можете перенаправить страницу ошибки 404 на индексную страницу в качестве следующего шага.
Наслаждайтесь!
Ответ 2
Вы можете перенаправить все не найденные ресурсы на свою основную страницу, предоставив пользовательский ErrorViewResolver. Все, что вам нужно сделать, это добавить это в свой класс @Configuration:
@Bean
ErrorViewResolver supportPathBasedLocationStrategyWithoutHashes() {
return new ErrorViewResolver() {
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
return status == HttpStatus.NOT_FOUND
? new ModelAndView("index.html", Collections.<String, Object>emptyMap(), HttpStatus.OK)
: null;
}
};
}
Ответ 3
В моих приложениях загрузки Spring (версии 1 и 2) мои статические ресурсы находятся в одном месте:
src/main/resources/static
static
является папкой, распознанной Spring Boot для загрузки статических ресурсов.
Тогда идея состоит в настройке конфигурации Spring MVC.
Более простой способ - использовать конфигурацию Java Spring.
Я реализую WebMvcConfigurer
для переопределения addResourceHandlers()
.
Я добавляю одиночный ResourceHandler
к текущему ResourceHandlerRegistry
.
Обработчик сопоставляется по каждому запросу, и я указываю classpath:/static/
как значение местоположения ресурса (вы можете, конечно, добавить другие, если требуется).
Я добавляю пользовательский анонимный класс PathResourceResolver
для переопределения getResource(String resourcePath, Resource location)
.
Правило для возврата ресурса следующее: если ресурс существует и доступен для чтения (так что это файл), я возвращаю его. В противном случае по умолчанию я возвращаю страницу index.html
. Каково ожидаемое поведение для обработки URL-адресов HTML 5.
Spring Загрузка 1.X-приложения:
Расширение org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
- это способ.
Класс является адаптером интерфейса WebMvcConfigurer
с пустыми методами, позволяющими подклассам переопределять только те методы, которые им интересны.
Вот полный код:
import java.io.IOException;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.resource.PathResourceResolver;
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**/*")
.addResourceLocations("classpath:/static/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath,
Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/static/index.html");
}
});
}
}
Spring Загрузка 2.X-приложения:
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
устарел.
Внедрение непосредственно WebMvcConfigurer
- это теперь путь, так как он по-прежнему является интерфейсом, но теперь он имеет методы по умолчанию (что стало возможным благодаря базовой линии Java 8) и может быть реализовано непосредственно без использования адаптера.
Вот полный код:
import java.io.IOException;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**/*")
.addResourceLocations("classpath:/static/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath,
Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/static/index.html");
}
});
}
}
Ответ 4
Чтобы сделать его более простым, вы можете просто реализовать ErrorPageRegistrar напрямую.
@Component
public class ErrorPageConfig implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/"));
}
}
Это отправит запросы index.html.
@Controller
@RequestMapping("/")
public class MainPageController {
@ResponseStatus(HttpStatus.OK)
@RequestMapping({ "/" })
public String forward() {
return "forward:/";
}
}
Ответ 5
Вот три шага, которые вам нужно выполнить:
-
Внесите свой собственный TomcatEmbeddedServletContainerFactory bean и настройте RewriteValve
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
...
import org.apache.catalina.valves.rewrite.RewriteValve;
...
@Bean TomcatEmbeddedServletContainerFactory servletContainerFactory() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setPort(8080);
factory.addContextValves(new RewriteValve());
return factory;
}
-
Добавьте файл rewrite.conf в каталог WEB-INF вашего приложения и укажите правила перезаписи. Ниже приведен пример содержимого rewrite.conf, которое я использую в приложении angular, чтобы использовать angular PathLocationStrategy (в основном я просто перенаправляю все на index.html, поскольку мы просто используем spring boot для обслуживания статический веб-контент, иначе вам нужно отфильтровать ваши контроллеры в правиле RewriteCond):
RewriteCond %{REQUEST_URI} !^.*\.(bmp|css|gif|htc|html?|ico|jpe?g|js|pdf|png|swf|txt|xml|svg|eot|woff|woff2|ttf|map)$
RewriteRule ^(.*)$ /index.html [L]
-
Измените использование useHash (или установите его в false) из объявлений маршрутизации:
RouterModule.forRoot(routes)
или
RouterModule.forRoot(routes, {useHash: false})
Ответ 6
Вы можете перенаправить все, не привязанные к Angular, используя что-то вроде этого:
@Controller
public class ForwardController {
@RequestMapping(value = "/**/{[path:[^\\.]*}")
public String redirect() {
// Forward to home page so that route is preserved.
return "forward:/";
}
}
Источник: fooobar.com/questions/381700/...
My Spring Загрузочный сервер для Angular также является сервером шлюза с вызовами API на /api
, чтобы не иметь страницу входа перед страницами Angular, вы можете использовать что-то вроде.
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
/**
* This sets up basic authentication for the microservice, it is here to prevent
* massive screwups, many applications will require more secuity, some will require less
*/
@EnableOAuth2Sso
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
@Override
public void configure(HttpSecurity http) throws Exception {
http
.logout().logoutSuccessUrl("/").and()
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll().and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
Ответ 7
перенаправить все Angular маршрутизацию с помощью index.html. В том числе базовый href.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ViewController {
@RequestMapping({ "jsa/customer","jsa/customer/{id}",})
public String index() {
return "forward:/index.html";
}
}
В моем случае jsa является базовым href.