1. 自定义视图**:** 创建一个 View 的 bean, 该 bean 需要继承自 AbstractView, 并实现
renderMergedOutputModel 方法**.**
2. 并把自定义 View 加入到 IOC 容器中
3. 自定义视图的视图处理器,使用 BeanNameViewResolver**, 这个视图处理器也需要配置**
到 ioc 容器
4. BeanNameViewResolver 的调用优先级需要设置一下,设置 order 比 Integer.MAX_VAL
小的值**.** 以确保其在 InternalResourceViewResolver 之前被调用
/** * 老师解读 * 1. MyView继承了AbstractView, 就可以作为一个视图使用 * 2. @Component(value = "myView"),该视图会注入到容器中, 名字/id是 myView */ @Component(value = "hspView") public class MyView extends AbstractView { @Override protected void renderMergedOutputModel(Mapmodel, HttpServletRequest request, HttpServletResponse response) throws Exception { //完成视图渲染 //并且可以确定我们要跳转的页面 [请求转发] /WEB-INF/pages/my_view.jsp System.out.println("进入到自己的视图.."); //老师解读 //1. 下面就是进行请求转发到 /WEB-INF/pages/my_view.jsp //2. /WEB-INF/pages/my_view.jsp 会被springmvc解析 // /springmvc/WEB-INF/pages/my_view.jsp request.getRequestDispatcher("/WEB-INF/pages/my_view.jsp") .forward(request, response); } }
使用
@RequestMapping(value = "/buy") public String buy() { System.out.println("------buy()-----"); return "hspView";//填写自定义视图id }
@Nullable protected View resolveViewName(String viewName, @Nullable Mapmodel, Locale locale, HttpServletRequest request) throws Exception { if (this.viewResolvers != null) { for (ViewResolver viewResolver : this.viewResolvers) {//viewResolvers存放了两个视图解析器(1)InternalResourceViewResolver默认视图解析器 (2)BeanNameViewResolver自定义视图解析器 View view = viewResolver.resolveViewName(viewName, locale); if (view != null) {//如果返回的视图为空,那么会继续遍历所有的视图解析器; //注意:如果 默认视图解析器 优先级在前,那么不管怎样,它都不会再执行 自定义视图解析器 //原因:默认视图解析器 一定会返回视图,因为它是通过传入的视图名build一个视图 return view; } } } return null; }
@Override protected AbstractUrlBasedView buildView(String viewName) throws Exception { InternalResourceView view = (InternalResourceView) super.buildView(viewName);//根据viewName创建视图 if (this.alwaysInclude != null) { view.setAlwaysInclude(this.alwaysInclude); } view.setPreventDispatchLoop(true); return view; }
注意:如果 默认视图解析器 优先级在前,那么不管怎样,它都不会再执行 自定义视图解析器 (因为:默认视图解析器 一定会返回视图,因为它是通过传入的视图名build一个视图)
public View resolveViewName(String viewName, Locale locale) throws BeansException { ApplicationContext context = obtainApplicationContext();//context实质上就类似于ioc容器 if (!context.containsBean(viewName)) {//判断context(ioc)中是否有id为viewName的bean // Allow for ViewResolver chaining... return null; } if (!context.isTypeMatch(viewName, View.class)) {//判断context(ioc)中是否有id为viewName并实现View接口的bean if (logger.isDebugEnabled()) { logger.debug("Found bean named '" + viewName + "' but it does not implement View"); } // Since we're looking into the general ApplicationContext here, // let's accept this as a non-match and allow for chaining as well... return null; } return context.getBean(viewName, View.class); }
1.拿到context对象,实质上类似于ioc容器
2.//判断context(ioc)中是否有id为viewName的bean, 没有就返回null; 有就接着往下走
3.//判断context(ioc)中是否有id为viewName并实现View接口的bean 有就返回该视图 ,如果不存在传入的viewName对应的自定义视图,那么就返回null,接着走其他视图解析器