[java][작성중]Spring boot에서 Redirect와 Forward 를 이용해 보자
spring맹으로써 다른 컨트롤러에 데이터를 넘기려면 어떻게 해야하나 싶었다.
intro
-
들어온 요청을 다른 곳으로 넘기는 방안 2가지
- Redirect
- 서버에 요청이 들어오면 클라이언트로 HTTP Stauts Code 302를 Location 헤더에 이동할 URL로 함께 전송한다.
- 웹브라우저에선 Location 값을 보고 다시 요청 하겠지.
- Forward
- 서버에 요청이 들어온뒤 클라이언트로 값을 바로 내려주지 않고 서버에서 원하는 url로 포워딩 시킨다.
- 이동한 url에서 응답을 만들어 내려주겠지
- 서버에 요청이 들어온뒤 클라이언트로 값을 바로 내려주지 않고 서버에서 원하는 url로 포워딩 시킨다.
spring 에서 구현
- redirect:/url_, forward:/url_와 같은 String을 리턴하면 알아서 동작한다.
- 이렇게 동작하는것은 보려면 아래의 UrlBasedViewResolver.java 에 createView 메소드를 보면 어떻게 처리되는지 알 수 있을듯 .
package org.springframework.web.servlet.view;
// . . .
/**
* Simple implementation of the {@link org.springframework.web.servlet.ViewResolver}
* interface, allowing for direct resolution of symbolic view names to URLs,
* without explicit mapping definition. This is useful if your symbolic names
* match the names of your view resources in a straightforward manner
* (i.e. the symbolic name is the unique part of the resource's filename),
* without the need for a dedicated mapping to be defined for each view.
*
* <p>Supports {@link AbstractUrlBasedView} subclasses like {@link InternalResourceView}
* and {@link org.springframework.web.servlet.view.freemarker.FreeMarkerView}.
* The view class for all views generated by this resolver can be specified
* via the "viewClass" property.
*
* <p>View names can either be resource URLs themselves, or get augmented by a
* specified prefix and/or suffix. Exporting an attribute that holds the
* RequestContext to all views is explicitly supported.
*
* <p>Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" ->
* "/WEB-INF/jsp/test.jsp"
*
* <p>As a special feature, redirect URLs can be specified via the "redirect:"
* prefix. E.g.: "redirect:myAction" will trigger a redirect to the given
* URL, rather than resolution as standard view name. This is typically used
* for redirecting to a controller URL after finishing a form workflow.
*
* <p>Furthermore, forward URLs can be specified via the "forward:" prefix.
* E.g.: "forward:myAction" will trigger a forward to the given URL, rather than
* resolution as standard view name. This is typically used for controller URLs;
* it is not supposed to be used for JSP URLs - use logical view names there.
*
* <p>Note: This class does not support localized resolution, i.e. resolving
* a symbolic view name to different resources depending on the current locale.
*
* <p><b>Note:</b> When chaining ViewResolvers, a UrlBasedViewResolver will check whether
* the {@link AbstractUrlBasedView#checkResource specified resource actually exists}.
* However, with {@link InternalResourceView}, it is not generally possible to
* determine the existence of the target resource upfront. In such a scenario,
* a UrlBasedViewResolver will always return View for any given view name;
* as a consequence, it should be configured as the last ViewResolver in the chain.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @since 13.12.2003
* @see #setViewClass
* @see #setPrefix
* @see #setSuffix
* @see #setRequestContextAttribute
* @see #REDIRECT_URL_PREFIX
* @see AbstractUrlBasedView
* @see InternalResourceView
* @see org.springframework.web.servlet.view.freemarker.FreeMarkerView
*/
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
/**
* Prefix for special view names that specify a redirect URL (usually
* to a controller after a form has been submitted and processed).
* Such view names will not be resolved in the configured default
* way but rather be treated as special shortcut.
*/
public static final String REDIRECT_URL_PREFIX = "redirect:";
/**
* Prefix for special view names that specify a forward URL (usually
* to a controller after a form has been submitted and processed).
* Such view names will not be resolved in the configured default
* way but rather be treated as special shortcut.
*/
public static final String FORWARD_URL_PREFIX = "forward:";
// . . .
/**
* Overridden to implement check for "redirect:" prefix.
* <p>Not possible in {@code loadView}, since overridden
* {@code loadView} versions in subclasses might rely on the
* superclass always creating instances of the required view class.
* @see #loadView
* @see #requiredViewClass
*/
@Override
protected View createView(String viewName, Locale locale) throws Exception {
// If this resolver is not supposed to handle the given view,
// return null to pass on to the next resolver in the chain.
if (!canHandle(viewName, locale)) {
return null;
}
// Check for special "redirect:" prefix.
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
RedirectView view = new RedirectView(redirectUrl,
isRedirectContextRelative(), isRedirectHttp10Compatible());
String[] hosts = getRedirectHosts();
if (hosts != null) {
view.setHosts(hosts);
}
return applyLifecycleMethods(REDIRECT_URL_PREFIX, view);
}
// Check for special "forward:" prefix.
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
InternalResourceView view = new InternalResourceView(forwardUrl);
return applyLifecycleMethods(FORWARD_URL_PREFIX, view);
}
// Else fall back to superclass implementation: calling loadView.
return super.createView(viewName, locale);
}
}
- 코드를 보면 redirect:, forward:으로 시작하는 경우를 확인한 후, 적절한 RedirectView 나 InternalResourceView를 만들어서 리턴함해서 포워딩한다.
실전예제
@Slf4j
@Controller
public class SampleVersionController extends VersionController {
protected final AntPathMatcher pathMatcher = new AntPathMatcher();
@Getter
private final List<String> supportVersions = Arrays.asList("v1.0", "v1.1", "v1.2", "v1.3"); // Check
@Getter
private final Set<String> fadeoutVersions = Collections.emptySet(); // Check
@Getter
private final String contextPath = "/sample"; // Check
@ApiIgnore
@RequestMapping(contextPath + "/{version}/**")
public String forward(final @PathVariable String version, final HttpServletRequest request) {
//원하는 버전을 찾아서 forward uri에 세팅하는 방식.
String forwardUri = forwardToPreviousVersion(version,
pathMatcher.extractPathWithinPattern(contextPath + "/{version}/**", request.getRequestURI()));
//forward:
return forwardUri;
}
}
- 가령
/sample/v1.3/...
란 요청이 들어왔을때forward:/sample/v1.2/...
로 찾아서 실제하는 컨트롤러로 리턴하는 샘플