1. 개요
이 기사는 Spring에서 Redirect 를 구현하는 데 초점을 맞추고 각 전략의 추론을 논의합니다.
2. 리디렉션을 수행하는 이유는 무엇입니까?
먼저 Spring 애플리케이션에서 리디렉션을 수행해야하는 이유를 고려해 보겠습니다 .
물론 가능한 많은 예와 이유가 있습니다. 하나의 간단한 방법은 양식 데이터를 게시하거나, 이중 제출 문제를 해결하거나, 실행 흐름을 다른 컨트롤러 메서드에 위임하는 것입니다.
여기서 간단한 참고 사항은 일반적인 Post / Redirect / Get 패턴은 이중 제출 문제를 적절하게 해결하지 못한다는 것입니다. 초기 제출이 완료되기 전에 페이지를 새로 고치는 것과 같은 문제는 여전히 이중 제출로 이어질 수 있습니다.
3. RedirectView로 리디렉션
이 간단한 접근 방식으로 시작하여 바로 예를 들어 보겠습니다 .
@Controller
@RequestMapping("/")
public class RedirectController {
@GetMapping("/redirectWithRedirectView")
public RedirectView redirectWithUsingRedirectView(
RedirectAttributes attributes) {
attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectView");
attributes.addAttribute("attribute", "redirectWithRedirectView");
return new RedirectView("redirectedUrl");
}
}
이면에서 RedirectView 는 실제 리디렉션을 수행 하는 HttpServletResponse.sendRedirect ()를 트리거합니다 .
여기 에서 리다이렉트 속성을 메소드에 주입하는 방법에 주목하십시오 . 프레임 워크는 여기서 무거운 작업을 수행하고 이러한 속성과 상호 작용할 수 있도록합니다.
HTTP 쿼리 매개 변수로 노출 될 모델 속성 속성을 추가합니다 . 모델에는 객체 (일반적으로 문자열 또는 문자열로 변환 할 수있는 객체) 만 포함되어야합니다.
이제 간단한 curl 명령을 사용하여 리디렉션을 테스트 해 보겠습니다 .
curl -i http://localhost:8080/spring-rest/redirectWithRedirectView
결과는 다음과 같습니다.
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectView
4. 접두사로 리디렉션 리디렉션 :
RedirectView를 사용하는 이전 접근 방식 은 몇 가지 이유로 차선책입니다.
먼저, 코드에서 직접 RedirectView를 사용하고 있기 때문에 이제 Spring API에 연결되었습니다 .
둘째-이제 컨트롤러 작업을 구현할 때 처음부터 결과가 항상 리디렉션이 될 것임을 알아야합니다. 항상 그런 것은 아닙니다.
더 나은 옵션은 리디렉션 접두사를 사용하는 것입니다 . – 리디렉션보기 이름은 다른 논리적보기 이름과 마찬가지로 컨트롤러에 삽입됩니다. 컨트롤러는 리디렉션이 발생하고 있다는 사실조차 인식하지 못합니다 .
다음과 같이 표시됩니다.
@Controller
@RequestMapping("/")
public class RedirectController {
@GetMapping("/redirectWithRedirectPrefix")
public ModelAndView redirectWithUsingRedirectPrefix(ModelMap model) {
model.addAttribute("attribute", "redirectWithRedirectPrefix");
return new ModelAndView("redirect:/redirectedUrl", model);
}
}
뷰 이름이 접두사로 반환 될 때 리디렉션 : - 하는 UrlBasedViewResolver (과 모든 하위 클래스) 리디렉션 요구가 발생하는 것을 특별 지시로 인식됩니다. 나머지보기 이름은 리디렉션 URL로 사용됩니다.
여기에서 빠르지 만 중요한 메모는 – 여기서이 논리적 뷰 이름을 사용할 때 – redirect : / redirectedUrl – 현재 서블릿 컨텍스트에 상대적인 리디렉션을 수행한다는 것 입니다.
절대 URL로 리디렉션해야하는 경우 리디렉션 과 같은 이름을 사용할 수 있습니다 . http : // localhost : 8080 / spring-redirect-and-forward / redirectedUrl .
이제 curl 명령 을 실행할 때 :
curl -i http://localhost:8080/spring-rest/redirectWithRedirectPrefix
즉시 리디렉션됩니다.
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectPrefix
5. 접두사로 앞으로 전달 :
이제 약간 다른 것을하는 방법을 살펴 보겠습니다 – 포워드.
코드를 시작하기 전에 forward vs. redirect의 의미에 대한 간략한 개요를 살펴 보겠습니다 .
- 리디렉션 은 302 및 Location 헤더 의 새 URL로 응답합니다 . 그러면 브라우저 / 클라이언트가 새 URL에 대한 또 다른 요청을합니다.
- 앞으로는 전적으로 서버 측에서 발생합니다. 서블릿 컨테이너는 동일한 요청을 대상 URL로 전달합니다. URL은 브라우저에서 변경되지 않습니다.
이제 코드를 살펴 보겠습니다.
@Controller
@RequestMapping("/")
public class RedirectController {
@GetMapping("/forwardWithForwardPrefix")
public ModelAndView redirectWithUsingForwardPrefix(ModelMap model) {
model.addAttribute("attribute", "forwardWithForwardPrefix");
return new ModelAndView("forward:/redirectedUrl", model);
}
}
동일 리디렉션 : 는 앞으로 : 접두사에 의해 해결 될 것입니다 하는 UrlBasedViewResolver 와 그 서브 클래스. 내부적으로 이것은 새로운 뷰에 RequestDispatcher.forward () 를 수행 하는 InternalResourceView 를 생성합니다 .
curl로 명령을 실행할 때 :
curl -I http://localhost:8080/spring-rest/forwardWithForwardPrefix
HTTP 405 (허용되지 않는 메서드)를 받게됩니다.
HTTP/1.1 405 Method Not Allowed
Server: Apache-Coyote/1.1
Allow: GET
Content-Type: text/html;charset=utf-8
요약하자면 리디렉션 솔루션의 경우에 있었던 두 개의 요청과 비교하여이 경우에는 브라우저 / 클라이언트에서 서버 측으로 나가는 단일 요청 만 있습니다. 물론 이전에 리디렉션에 의해 추가 된 속성도 누락되었습니다.
6. RedirectAttribute가있는 속성
다음 – RedirectAttribures로 프레임 워크를 최대한 활용하여 리디렉션에서 속성 을 전달하는 방법을 자세히 살펴 보겠습니다 .
@GetMapping("/redirectWithRedirectAttributes")
public RedirectView redirectWithRedirectAttributes(RedirectAttributes attributes) {
attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectAttributes");
attributes.addAttribute("attribute", "redirectWithRedirectAttributes");
return new RedirectView("redirectedUrl");
}
앞서 살펴본 것처럼 메서드에 속성 개체를 직접 삽입 할 수 있으므로이 메커니즘을 매우 쉽게 사용할 수 있습니다.
또한 플래시 속성도 추가하고 있습니다. 이것은 URL에 포함되지 않는 속성입니다. 이러한 종류의 속성으로 얻을 수있는 것은 – 나중에 리디렉션의 최종 대상인 메서드에서만 @ModelAttribute ( "flashAttribute")를 사용하여 플래시 속성에 액세스 할 수 있습니다 .
@GetMapping("/redirectedUrl")
public ModelAndView redirection(
ModelMap model,
@ModelAttribute("flashAttribute") Object flashAttribute) {
model.addAttribute("redirectionAttribute", flashAttribute);
return new ModelAndView("redirection", model);
}
정리하자면 curl로 기능을 테스트하면 다음과 같습니다.
curl -i http://localhost:8080/spring-rest/redirectWithRedirectAttributes
새 위치로 리디렉션됩니다.
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=4B70D8FADA2FD6C22E73312C2B57E381; Path=/spring-rest/; HttpOnly
Location: http://localhost:8080/spring-rest/redirectedUrl;
jsessionid=4B70D8FADA2FD6C22E73312C2B57E381?attribute=redirectWithRedirectAttributes
이렇게 하면 ModelMap 대신 RedirectAttribures 를 사용 하면 리디렉션 작업에 관련된 두 메서드간에 일부 속성 만 공유 할 수 있습니다.
7. 접두사가없는 대체 구성
이제 접두사를 사용하지 않는 리디렉션 인 대체 구성을 살펴 보겠습니다.
이를 위해서는 org.springframework.web.servlet.view.XmlViewResolver 를 사용해야합니다 .
<bean class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="location">
<value>/WEB-INF/spring-views.xml</value>
</property>
<property name="order" value="0" />
</bean>
org.springframework.web.servlet.view.InternalResourceViewResolver 대신 이전 구성에서 사용했습니다.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>
또한 구성에서 RedirectView 빈 을 정의해야 합니다.
<bean id="RedirectedUrl" class="org.springframework.web.servlet.view.RedirectView">
<property name="url" value="redirectedUrl" />
</bean>
이제 우리는 id로이 새로운 bean을 참조하여 리디렉션을 트리거 할 수 있습니다 .
@Controller
@RequestMapping("/")
public class RedirectController {
@GetMapping("/redirectWithXMLConfig")
public ModelAndView redirectWithUsingXMLConfig(ModelMap model) {
model.addAttribute("attribute", "redirectWithXMLConfig");
return new ModelAndView("RedirectedUrl", model);
}
}
이를 테스트하기 위해 curl 명령을 다시 사용합니다 .
curl -i http://localhost:8080/spring-rest/redirectWithRedirectView
결과는 다음과 같습니다.
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectView
8. HTTP POST 요청 리디렉션
은행 결제와 같은 사용 사례의 경우 HTTP POST 요청을 리디렉션해야 할 수 있습니다. 반환 된 HTTP 상태 코드에 따라 POST 요청은 HTTP GET 또는 POST로 리디렉션 될 수 있습니다.
HTTP 1.1 프로토콜 참조에 따라 상태 코드 301 (영구 이동) 및 302 (찾음)를 통해 요청 메서드를 POST에서 GET으로 변경할 수 있습니다. 사양은 또한 요청 방법이 POST에서 GET으로 변경되는 것을 허용하지 않는 해당 307 (임시 리디렉션) 및 308 (영구 리디렉션) 상태 코드를 정의합니다.
이제 게시 요청을 다른 게시 요청으로 리디렉션하는 코드를 살펴 보겠습니다.
@PostMapping("/redirectPostToPost")
public ModelAndView redirectPostToPost(HttpServletRequest request) {
request.setAttribute(
View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT);
return new ModelAndView("redirect:/redirectedPostToPost");
}
@PostMapping("/redirectedPostToPost")
public ModelAndView redirectedPostToPost() {
return new ModelAndView("redirection");
}
이제 curl 명령을 사용하여 POST의 리디렉션을 테스트 해 보겠습니다 .
curl -L --verbose -X POST http://localhost:8080/spring-rest/redirectPostToPost
예정된 위치로 리디렉션됩니다.
> POST /redirectedPostToPost HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.0
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 08 Aug 2017 07:33:00 GMT
{"id":1,"content":"redirect completed"}
9. 매개 변수로 전달
이제 정방향 접두사 가있는 다른 RequestMapping 으로 일부 매개 변수를 전송하려는 시나리오를 고려해 보겠습니다 .
이 경우 HttpServletRequest 를 사용하여 호출 사이에 매개 변수를 전달할 수 있습니다 .
param1 및 param2 를 forwardedWithParams 다른 매핑 으로 보내는 데 필요한 forwardWithParams 메서드는 다음과 같습니다 .
@RequestMapping(value="/forwardWithParams", method = RequestMethod.GET)
public ModelAndView forwardWithParams(HttpServletRequest request) {
request.setAttribute("param1", "one");
request.setAttribute("param2", "two");
return new ModelAndView("forward:/forwardedWithParams");
}
실제로 forwardedWithParams 매핑 은 완전히 새로운 컨트롤러에 존재할 수 있으며 동일한 컨트롤러에있을 필요는 없습니다.
@RequestMapping(value="/forwardWithParams", method = RequestMethod.GET)
@Controller
@RequestMapping("/")
public class RedirectParamController {
@RequestMapping(value = "/forwardedWithParams", method = RequestMethod.GET)
public RedirectView forwardedWithParams(
final RedirectAttributes redirectAttributes, HttpServletRequest request) {
redirectAttributes.addAttribute("param1", request.getAttribute("param1"));
redirectAttributes.addAttribute("param2", request.getAttribute("param2"));
redirectAttributes.addAttribute("attribute", "forwardedWithParams");
return new RedirectView("redirectedUrl");
}
}
설명을 위해 다음 curl 명령을 시도해 보겠습니다 .
curl -i http://localhost:8080/spring-rest/forwardWithParams
결과는 다음과 같습니다.
HTTP/1.1 302 Found
Date: Fri, 19 Feb 2021 05:37:14 GMT
Content-Language: en-IN
Location: http://localhost:8080/spring-rest/redirectedUrl?param1=one¶m2=two&attribute=forwardedWithParams
Content-Length: 0
보시다시피 param1 과 param2 는 첫 번째 컨트롤러에서 두 번째 컨트롤러로 이동했습니다. 마지막으로 forwardedWithParams가 가리키는 redirectedUrl이라는 리디렉션 에 표시 되었습니다.
10. 결론
이 기사에서는 Spring 에서 리디렉션을 구현하는 세 가지 접근 방식 , 이러한 리디렉션을 수행 할 때 속성을 처리 / 전달하는 방법 및 HTTP POST 요청의 리디렉션을 처리하는 방법을 설명했습니다.
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/spring-redirect-and-forward
'Java' 카테고리의 다른 글
Java 8 forEach 사용방법 (0) | 2021.03.08 |
---|---|
JPA의 다 대다 관계 (0) | 2021.03.08 |
스프링 JDBC (0) | 2021.03.07 |
Java 경고 "Unchecked Cast" (0) | 2021.03.07 |
Spring을 사용한 REST 오류 처리 (0) | 2021.03.07 |