SpringMVC RedirectView的使用以及源码分析

看一段普通的代码,我们访问controller中的一个方法后,重定向到另外一个controller或者视图。

    @RequestMapping(params="method=index")
    public ModelAndView index() {
        RedirectView redirectView = new RedirectView("/Demo.do?method=index2", true, true);
        ModelAndView mav = new ModelAndView(redirectView);
        mav.addObject("attr1", "attr1Value");
        mav.addObject("attr2", "attr2Value");
        return mav;
    }

浏览器的URL会变成http://localhost:8080/FuDeKang/Demo.do?method=index2&attr2=attr2Value&attr1=attr1Value

也就是说Spring会自定把model中的键值放入到URL当中,那么Spring是如何做到的呢,我么还来看ModelAndViewMethodReturnValueHandler这个类。

public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturnValueHandler {

    public boolean supportsReturnType(MethodParameter returnType) {
        return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
    }

    public void handleReturnValue(
            Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
            throws Exception {

        if (returnValue == null) {
            mavContainer.setRequestHandled(true);
            return;
        }

        ModelAndView mav = (ModelAndView) returnValue;
        if (mav.isReference()) {
            String viewName = mav.getViewName();
            mavContainer.setViewName(viewName);
            if (viewName != null && viewName.startsWith("redirect:")) {
                mavContainer.setRedirectModelScenario(true);
            }
        }
        else {
            View view = mav.getView();
            mavContainer.setView(view);
            if (view instanceof SmartView) {
                if (((SmartView) view).isRedirectView()) {
                    mavContainer.setRedirectModelScenario(true);
                }
            }
        }
        mavContainer.addAllAttributes(mav.getModel());
    }

}

其中最后一句是关键,首先modelandview当中的model数据全部放到ModelAndViewContainer 里面。

因为我们是重定向,所以无论如何底层最后产生的视图对象都是RedirectView实例,我们在看一下它的源码。

    /**
     * Convert model to request parameters and redirect to the given URL.
     * @see #appendQueryProperties
     * @see #sendRedirect
     */
    @Override
    protected void renderMergedOutputModel(
            Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
            throws IOException {

        String targetUrl = createTargetUrl(model, request);

        targetUrl = updateTargetUrl(targetUrl, model, request, response);
        
        FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
        if (!CollectionUtils.isEmpty(flashMap)) {
            UriComponents uriComponents = UriComponentsBuilder.fromUriString(targetUrl).build();
            flashMap.setTargetRequestPath(uriComponents.getPath());
            flashMap.addTargetRequestParams(uriComponents.getQueryParams());
        }

        FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
        flashMapManager.saveOutputFlashMap(flashMap, request, response);

        sendRedirect(request, response, targetUrl.toString(), this.http10Compatible);
    }

其中  targetUrl = updateTargetUrl(targetUrl, model, request, response);  是拼接了URL的代码,最后调用sendRedirect做重定向。

原文地址:https://www.cnblogs.com/daxin/p/4037374.html