programing

리다이렉트 기능이 있는 스프링 부트 (1페이지 angular 2)

linuxpc 2023. 4. 6. 21:11
반응형

리다이렉트 기능이 있는 스프링 부트 (1페이지 angular 2)

Spring Boot을 탑재한 Angular 앱이 1페이지 있습니다.다음과 같이 표시됩니다.

src
  main
  java
    controller
       HomeController
       CustomerController
       OtherController
  webapp
    js/angular-files.js
    index.html

스프링 부트는 webapp 폴더로 올바르게 기본 설정되며 index.html 파일을 제공합니다.

제가 원하는 것은 다음과 같습니다.

  1. 모든 로컬 REST 요청은 다음 문자로 시작하지 않습니다./api를 덮어쓰고 기본 webapp/index.blash로 수정합니다.나는 어떤 것이든 대접할 계획이다./api스프링 컨트롤러에 접속합니다.

  2. 모든 컨트롤러에 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루팅을 인계합니다.

언급

  • HashLocationStrategyAngular에서 권장하지 않는 문제이므로 이 문제를 해결하려면 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.htmlindex. 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.htmldoes 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

반응형