https://www.baeldung.com/spring-redirect-and-forward
implementing a Redirect in Spring and will discuss the reasoning behind each strategy.
Why Do a Redirect?
Spring 애플리케이션에러 리디렉션을 수행해야하는 이유는 많다
양식 데이터를 POST하거나 이중 제출 문제를 해결하거나, 실행 흐름을 다른 Controller Method에 위임하는 경우 등이 있다
** 일반적으로 Post, Redirect, Get 패턴은 이중 제출 문제를 적절하게 해결하지 못하므로
초기 제출 완료 전에 페이지를 새로 고치는 것과 같은 문제는 여전히 이중 제출로 이어진다.
Redirect With the 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() 를 trigger한다
redirection 특성을 메서드에 주입한다.
HTTP 쿼리 매개변수로 노출될 모델 속성 attribute 를 추가했다.
모델은 객체(일반적으로 문자열 또는 문자열로 변환할 수 있는 객체)만 포함해야한다
curl 명령어를 이용하여 redirection 테스트를 하면
다음과 같은 결과가 나온다
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
Redirect With the Prefix redirect:
앞 선 RedirectView 방식은 최적 방식이 아니다
1. 코드에서 직접 RedirectView를 사용하여 Spring API에 연결된다
2. 처음부터 해당 컨트롤러 작업을 구현할 때 결과가 항상 그렇지 않을 수 있는 리디렉션임을 알아야 한다.
그래서 우리는 Prefix redirect를 사용해야한다
컨트롤러는 리디렉션이 발생하고 있다는 사실조차 인식할 필요 없다.
@Controller
@RequestMapping("/")
public class RedirectController {
@GetMapping("/redirectWithRedirectPrefix")
public ModelAndView redirectWithUsingRedirectPrefix(ModelMap model) {
model.addAttribute("attribute", "redirectWithRedirectPrefix");
return new ModelAndView("redirect:/redirectedUrl", model);
}
}
UrlBasedViewResolver (및 모든 하위 클래스)는 이를 리디렉션 이 발생해야 한다는 특별한 표시로 인식한다
redirect:/redirectedUrl을 사용할 때 현재 서블릿 컨텍스트에 상대적인 리디렉션을 수행한다
절대 URL로 리디렉션해야 하는 경우 http://localhost:8080/spring-redirect-and-forward/redirectedUrl과 같은 리디렉션과 같은 이름을 사용할 수 있다.
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
Forward With the Prefix forward:
다른 방식의 수행 방법이다
정방향 대 리디렉션의 의미 체계에 대한 빠르고 높은 수준의 개요
- 리디렉션은 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);
}
}
redirect: 와 동일하며 forward : 접두사는 UrlBasedViewResolver 및 해당 하위 클래스 에 의해 확인된다.
내부적으로 이것은 새 보기에 대해 RequestDispatcher.forward()를 수행하는 InternalResourceView 를 생성한다
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
리디렉션 솔루션의 경우 두 가지 요청과 비교하여 이 경우에는 브라우저/클라이언트에서 서버 측으로 나가는 단일 요청만 있다.
이전에 리디렉션에 의해 추가된 속성도 누락된다
Attributes With the RedirectAttributes
RedirectAttributes를 사용하면 프레임워크를 최대한 활용하여 redirection 속성을 전달한다
@GetMapping("/redirectWithRedirectAttributes")
public RedirectView redirectWithRedirectAttributes(RedirectAttributes attributes) {
attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectAttributes");
attributes.addAttribute("attribute", "redirectWithRedirectAttributes");
return new RedirectView("redirectedUrl");
}
속성 개체를 메서드에 직접 주입하므로 메커니즘을 사용하기 매우 쉬우며,
** flash Attribute 도 추가해야한다. (URL로 만들지 않기 위해서이다)
이러한 종류의 속성을 사용하면 리디렉션의 최종 대상인 메서드에서만 @ModelAttribute(“flashAttribute”)를 사용하여 나중에 플래시 속성에 액세스할 수 있다
@GetMapping("/redirectedUrl")
public ModelAndView redirection(
ModelMap model,
@ModelAttribute("flashAttribute") Object flashAttribute) {
model.addAttribute("redirectionAttribute", flashAttribute);
return new ModelAndView("redirection", model);
}
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 대신 RedirectAttributes를 사용하면 리디렉션 작업과 관련된 두 메서드 간에 일부 속성 만 공유할 수 있다
An Alternative Configuration Without the Prefix
접두사를 사용하지 않는 리디렉션
a redirect without using the prefix.
To achieve this, we need to use an 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>
새로운 bean을 id로 참조하여 리디렉션을 트리거할 수 있다.
@Controller
@RequestMapping("/")
public class RedirectController {
@GetMapping("/redirectWithXMLConfig")
public ModelAndView redirectWithUsingXMLConfig(ModelMap model) {
model.addAttribute("attribute", "redirectWithXMLConfig");
return new ModelAndView("RedirectedUrl", model);
}
}
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
Redirecting an HTTP POST Request
은행 결제와 같은 예시의 경우 HTTP POST 요청을 리디렉션해야한다
반환된 HTTP 상태 코드에 따라 POST 요청을 HTTP GET 또는 POST로 리디렉션할 수 있다.
HTTP 1.1 프로토콜 참조 에 따라
status codes 301 (Moved Permanently) and 302 (Found) allow
the request method to be changed from 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 -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"}
Forward With Parameters
send some parameters across to another RequestMapping with a forward prefix.
정방향 Prefix 가 있는 다른 RequestMapping에 매개변수를 보내는 방법이다
이 경우 HttpServletRequest를 사용하여 호출 사이에 매개변수를 전달할 수 있다 .
다음은 param1 및 param2를 다른 매핑으로 보내야 하는 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 -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 이라는 리디렉션에 표시된다.
'Web > spring' 카테고리의 다른 글
[Spring Exception] Spring BeanCreationException (0) | 2023.04.07 |
---|---|
[Spring] Async Support with Spring MVC and Spring Security (0) | 2023.04.06 |
[Spring] Spring MVC Custom Validation (0) | 2023.04.05 |
[Spring Security] Handle Spring Security Exceptions (0) | 2023.04.04 |
[Spring] HandlerAdapters in Spring MVC (0) | 2023.04.04 |