[java][작성중]Spring boot에서 Redirect와 Forward 를 이용해 보자

spring맹으로써 다른 컨트롤러에 데이터를 넘기려면 어떻게 해야하나 싶었다.

intro

  • 들어온 요청을 다른 곳으로 넘기는 방안 2가지

  • Redirect
    • 서버에 요청이 들어오면 클라이언트로 HTTP Stauts Code 302를 Location 헤더에 이동할 URL로 함께 전송한다.
    • 웹브라우저에선 Location 값을 보고 다시 요청 하겠지.
  • Forward
    • 서버에 요청이 들어온뒤 클라이언트로 값을 바로 내려주지 않고 서버에서 원하는 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/... 로 찾아서 실제하는 컨트롤러로 리턴하는 샘플