ModelAndView与RedirectView无共同父类,如何实现通用返回函数?
优雅解决ModelAndView与RedirectView的通用返回问题
我完全理解你的困扰——org.springframework.web.servlet.ModelAndView和org.springframework.web.servlet.view.RedirectView确实没有除了Object之外的共同父类,而且你不想通过扩展原有类或者返回Object这种不够严谨的方式来妥协。这里有几个实用且优雅的方案,完全符合你的要求:
方案一:用ModelAndView统一包裹(最简单直接)
你可能忽略了ModelAndView的一个原生特性:它的构造方法可以直接接收一个View对象作为参数,而RedirectView本身就是View接口的实现类。我们可以把RedirectView直接包装进ModelAndView里,这样通用函数就能统一返回ModelAndView类型,完美兼容两种场景:
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.RedirectView; public ModelAndView getCommonResult(boolean needRedirect) { if (needRedirect) { // 将RedirectView包装进ModelAndView,还能附加重定向参数 RedirectView redirectView = new RedirectView("/target-page"); return new ModelAndView(redirectView).addObject("traceId", "12345"); } else { // 返回常规的视图+模型组合 return new ModelAndView("normal-view") .addObject("userInfo", currentUser); } }
这个方案完全依托Spring原生API,不需要额外编写任何扩展类或适配器,代码简洁易维护,Spring MVC也能完美识别并处理返回的ModelAndView。
方案二:自定义通用接口+适配器模式(扩展性更强)
如果未来你可能需要支持更多视图类型,或者想要更灵活的抽象,可以定义一个通用接口,通过静态方法把ModelAndView和RedirectView适配成接口实例,无需修改原有类:
第一步:定义通用渲染接口
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @FunctionalInterface public interface ViewRenderer { void render(HttpServletRequest request, HttpServletResponse response) throws Exception; }
第二步:编写适配工具方法
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.view.RedirectView; // 可将此类注册为Spring组件,自动注入ViewResolver public class ViewRendererAdapter { private final ViewResolver viewResolver; public ViewRendererAdapter(ViewResolver viewResolver) { this.viewResolver = viewResolver; } public ViewRenderer fromModelAndView(ModelAndView mav) { return (req, res) -> { // 自动解析视图(兼容视图名/直接View对象两种模式) org.springframework.web.servlet.View view = mav.getView() != null ? mav.getView() : viewResolver.resolveViewName(mav.getViewName(), req.getLocale()); view.render(mav.getModelMap(), req, res); }; } public ViewRenderer fromRedirectView(RedirectView redirectView) { return (req, res) -> redirectView.render(new org.springframework.ui.ModelMap(), req, res); } }
第三步:通用函数返回ViewRenderer
@Autowired private ViewRendererAdapter rendererAdapter; public ViewRenderer getCommonRenderer(boolean needRedirect) { if (needRedirect) { RedirectView redirectView = new RedirectView("/login"); return rendererAdapter.fromRedirectView(redirectView); } else { ModelAndView mav = new ModelAndView("dashboard").addObject("stats", dashboardStats); return rendererAdapter.fromModelAndView(mav); } }
如果是在Spring MVC控制器中使用,还需要自定义HandlerMethodReturnValueHandler让Spring识别ViewRenderer类型,但这个方案的扩展性极强,适合复杂场景的长期迭代。
内容的提问来源于stack exchange,提问作者payloc91
相关产品推荐
相关产品推荐

