리다이렉트 기능이 있는 스프링 부트 (1페이지 angular 2)
Spring Boot을 탑재한 Angular 앱이 1페이지 있습니다.다음과 같이 표시됩니다.
src
main
java
controller
HomeController
CustomerController
OtherController
webapp
js/angular-files.js
index.html
스프링 부트는 webapp 폴더로 올바르게 기본 설정되며 index.html 파일을 제공합니다.
제가 원하는 것은 다음과 같습니다.
모든 로컬 REST 요청은 다음 문자로 시작하지 않습니다.
/api
를 덮어쓰고 기본 webapp/index.blash로 수정합니다.나는 어떤 것이든 대접할 계획이다./api
스프링 컨트롤러에 접속합니다.모든 컨트롤러에 API를 부가하여 매번 API를 작성하지 않아도 되는 방법이 있습니까?
@RequestMapping("/api/home")은 코드 @RequestMapping("/home")에 속기를 쓸 수 있습니다.
또는
@RequestMapping("/api/other-controller/:id") can write shorthand @RequestMapping("/other-controller/:id")
예를 들어 1) http://localhost:8080/api/home keep API와 같은 모든 API 요청을 찾고 컨트롤러를 수정한 후 JSON을 반환하지만, 누군가가 http:///localhost/some-other/123/url과 같은 URL을 입력하면 인덱스 html과 페이지를 유지합니다.
다른 방법: #ErrorViewResolver: Springboot/Angular2 - HTML5 URL을 처리하는 방법
수많은 모순되는 솔루션에 따라 이 문제를 해결하는 데 지쳤다면 여기를 보세요!!
수십 개의 스택 오버플로우 및 블로그 투고에서 산재된 모든 조언을 따르기 위해 몇 시간 동안 노력한 끝에, 저는 마침내 루트 이외의 페이지에서 새로고침 후 항상 index.html로 리다이렉트할 수 있는 최소 PURE Spring Boot + Angular 6 응용 프로그램을 찾았습니다.REST API
엔드 포인트 패스아니요.@EnableWebMvc
,아니요.@ControllerAdvice
, 에 대한 변경 없음application.properties
, 커스텀 없음ResourceHandlerRegistry
단순성:
매우 중요한 전제 조건
다음 결과를 *포함*해야 합니다.ng build
봄으로 접어들어resources/static
폴더입니다.이를 수행하려면maven-resources-plugin
자세한 내용은 이쪽:다중 자원 디렉토리를 maven을 사용하여 독립된 타깃 디렉토리에 복사
코드
@Controller
@SpringBootApplication
public class MyApp implements ErrorController {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
private static final String PATH = "/error";
@RequestMapping(value = PATH)
public String error() {
return "forward:/index.html";
}
@Override
public String getErrorPath() {
return PATH;
}
}
추리
- ng-build 출력 포함
resources/static
빌드 시 스프링 뷰 리다이렉트 가능("forward:/index.html"
)을 클릭합니다.스프링은 리소스 폴더 이외의 다른 항목으로 리디렉션할 수 없기 때문에 사이트의 루트에 있는 페이지에 액세스하려고 하면 작동하지 않습니다. - 디폴트 기능 탑재(즉, 추가 없음)
@EnableWebMvc
또는 변경 사항application.properties
) 네비게이트/
dex를 처리합니다(인덱스에 되어 있는 ).resources/static
폴더)에서 변경할 필요가 없습니다. - 디폴트 에서는 스프링 한 에러는 에러로 .
/error
구현ErrorController
한 대로) - to - - - - to to to 로 라우팅합니다.index.html
에, 「」가 가능하게 됩니다.Angular
루팅을 인계합니다.
언급
HashLocationStrategy
Angular에서 권장하지 않는 문제이므로 이 문제를 해결하려면 https://angular.io/guide/router#which-strategy-is-best를 방문하십시오.
/api로 시작하지 않는 모든 로컬 REST 요청에 대해 덮어쓰고 기본 webapp/index.html로 리디렉션합니다.스프링 컨트롤러에 /api를 제공할 예정입니다.
업데이트 15/05/2017
다른 독자들을 위해 질문을 다시 쓰겠습니다. (오해되시면 정정해주세요.)
★★★
spring 부트로부터의
★★
★★★★★404
api 이외의 요구는 다음 주소로 리다이렉트해야 합니다.index.html
.
NON API - URL이 다음 문자로 시작되지 않는 요청을 의미합니다./api
.
API - 404가 던질 것404
평소처럼.
예
/api/something
요 - 던질게요404
/index.html
index. server index.dll
/something
됩니다. - 리다이렉트 .index.html
마이솔루션
지정된 리소스에 사용할 수 없는 핸들러가 있는 경우 Spring MVC에서 예외를 발생시킵니다.
「 」에 합니다.application.properties
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
ControllerAdvice
과 같이
@ControllerAdvice
public class RedirectOnResourceNotFoundException {
@ExceptionHandler(value = NoHandlerFoundException.class)
public Object handleStaticResourceNotFound(final NoHandlerFoundException ex, HttpServletRequest req, RedirectAttributes redirectAttributes) {
if (req.getRequestURI().startsWith("/api"))
return this.getApiResourceNotFoundBody(ex, req);
else {
redirectAttributes.addFlashAttribute("errorMessage", "My Custom error message");
return "redirect:/index.html";
}
}
private ResponseEntity<String> getApiResourceNotFoundBody(NoHandlerFoundException ex, HttpServletRequest req) {
return new ResponseEntity<>("Not Found !!", HttpStatus.NOT_FOUND);
}
}
원하는 대로 오류 메시지를 사용자 정의할 수 있습니다.
매번 api를 쓸 필요가 없도록 모든 컨트롤러에 api를 붙이는 방법이 있나요?
해서 ''를 만들 수 있어요.BaseController
를 RequestMapping으로 합니다./api
예
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api")
public abstract class BaseController {}
이 를 붙여주세요.BaseController
아이클래스에 주석을 붙이지 않도록 주의해 주세요.@RequestMapping
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FirstTestController extends BaseController {
@RequestMapping(path = "/something")
public String sayHello() {
return "Hello World !!";
}
}
이전 답변
만들 수 요.Filter
'다 하다'로 됩니다./index.html
does if 、 With 、/api
.
// CODE REMOVED. Check Edit History If you want.
대신 이것을 사용해 보세요.
@SpringBootApplication
@Controller
class YourSpringBootApp {
// Match everything without a suffix (so not a static resource)
@RequestMapping(value = "/**/{path:[^.]*}")
public String redirect() {
// Forward to home page so that route is preserved.(i.e forward:/intex.html)
return "forward:/";
}
}
@Controller
public class RedirectController {
/*
* Redirects all routes to FrontEnd except: '/', '/index.html', '/api', '/api/**'
*/
@RequestMapping(value = "{_:^(?!index\\.html|api).*$}")
public String redirectApi() {
return "forward:/";
}
}
이 실타래는 너무 늦었지만 누군가 도움이 될 것 같아서
많은 해결책을 시도했지만, 이것은 매우 솔직하고 훌륭해 보였습니다.
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;
import java.io.IOException;
@Configuration
public class MvcConfiguration 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");
}
});
}
}
크레딧 : https://keepgrowing.in/java/springboot/make-spring-boot-surrender-routing-control-to-angular/
Spring Boot의 BasicErrorController를 덮어쓰는 것이 효과적입니다.
@Component
public class CustomErrorController extends BasicErrorController {
public CustomErrorController(ErrorAttributes errorAttributes) {
super(errorAttributes, new ErrorProperties());
}
@RequestMapping(produces = "text/html")
@Override
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
if (status == HttpStatus.NOT_FOUND) {
return new ModelAndView("forward:/");
} else {
return super.errorHtml(request, response);
}
}
}
메서드 errorHtml은 찾을 수 없는 요청만 대행 수신하고 API로부터의 응답 404(찾을 수 없음)에 대해 투과적입니다.
Spring Boot 2+용 가장 합리적인 솔루션 imho (코드는 Kotlin에 있습니다) :
@Component
class ForwardErrorsToIndex : ErrorViewResolver {
override fun resolveErrorView(request: HttpServletRequest?,
status: HttpStatus?,
model: MutableMap<String, Any>?): ModelAndView {
return ModelAndView("forward:/index.html")
}
}
응용 프로그램 전체에 대해 application.properties에 컨텍스트 경로를 추가할 수 있습니다.
server.contextPath=/api
http://localhost:8080/api/home 뒤의 모든 요청된 URL에 "/api"가 추가됩니다.
리다이렉션의 경우
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/", "/home");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
super.addViewControllers(registry);
}
이 코드 묶음을 WebMVCConfig.java에 넣습니다.
@Configuration bean에서 Servlet Registration Bean을 추가하여 /api/* resquest 전용 스프링 서버를 만들 수 있습니다.컨트롤러에서는 추가할 필요가 없습니다.
@Bean
public ServletRegistrationBean dispatcherRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(
dispatcherServlet());
registration.addUrlMappings("/api/*");
registration.setLoadOnStartup(1);
registration.setName("mvc-dispatcher");
return registration;
}
이유는 모르겠지만 root url "/"는 코드를 조금 더 추가하지 않으면 해결되지 않습니다.결국 이렇게 된 거야
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.CacheControl;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;
@EnableWebMvc
@Configuration
public class MvcConfiguration 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");
}
});
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");
}
});
}
}
그럼 질문의 간단한 부분부터 시작하겠습니다.
매번 api를 쓸 필요가 없도록 모든 컨트롤러에 api를 붙이는 방법이 있나요?
은 "예입니다. 로 하면 됩니다. 컨트롤러에 "글로벌" 마크를 붙이면 됩니다.@RequestMapping
예를 다음과 같이 합니다.
@RestController
@RequestMapping("/api")
public class ApiController{
@RequestMapping("/hello")
public String hello(){
return "hello simple controller";
}
@RequestMapping("/hello2")
public String hello2(){
return "hello2 simple controller";
}
}
할 수 URL은 "hello" 입니다./api/hello
두 입니다./api/hello2
ㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇ./api
프레픽스
이제 질문의 더 복잡한 부분으로 넘어가겠습니다.
「Da't 」로 입니다./api
프리픽스?
Redirect의 HTTP 상태 코드(302)를 반환하면 결과적으로 rest가 네이티브하게 "스파이크"하기 때문에 Java/Spring 코드에서 리다이렉트를 강제할 수 없습니다.
그런 다음 상태 코드 302와 각도로 HTTP 메시지를 반환합니다.JS는 실제 리다이렉션을 수행합니다.
예를 들어 다음과 같습니다.
On Angular(각진 상태)JS:
var headers = {'Content-Type':'application/json', 'Accept':'application/json'}
var config = {
method:'GET'
url:'http://localhost:8080/hello',
headers:headers
};
http(config).then(
function onSuccess(response){
if(response.status == 302){
console.log("Redirect");
$location("/")
}
}, function onError(response){
console.log("An error occured while trying to open a new game room...");
});
봄:
@RestController
@RequestMapping("/api")
public class ApiController{
@RequestMapping("/hello")
public ResponseEntity<String> hello(){
HttpHeaders header = new HttpHeaders();
header.add("Content-Type", "application/json");
return new ResponseEntity<String>("", header, HttpStatus.FOUND);
}
}
물론 프로젝트에 맞게 커스터마이즈해야 합니다.
'만들면 요'라는 글씨만 넣으면 돼요.index.html
로로 합니다.src/main/resources/static/
예시를 참조: https://github.com/reflexdemon/shop/tree/master/src/main/resources/static
의 마마 my에서는package.josn
이 위치에 복사하려고 합니다.
'패키지 J」손: https://github.com/reflexdemon/shop/blob/master/package.json#L14
언급URL : https://stackoverflow.com/questions/43913753/spring-boot-with-redirecting-with-single-page-angular2
'programing' 카테고리의 다른 글
터미널에서 이메일을 보내는 방법 (0) | 2023.04.11 |
---|---|
왜 이 단순한 Angular는JS ng-show가 안 돼요? (0) | 2023.04.06 |
열거를 문자열로 직렬화 (0) | 2023.04.06 |
Spring-Data-MongoDB를 취득하여 오브젝트를 검증하려면 어떻게 해야 합니까? (0) | 2023.04.06 |
각도 이해JS ng-src (0) | 2023.04.06 |