【Java从零到架构师第③季】【31】SpringMVC-InternalResourceViewResolver_自定义InternalResourceView


持续学习&持续更新中…

守破离


InternalResourceViewResolver

在这里插入图片描述

注意:

  1. InternalResourceViewResolver影响的是没有带forward:redirect:的viewName,而不带forward:redirect:的viewName默认就是转发,因此InternalResourceViewResolver只会影响转发

  2. 配置了InternalResourceViewResolver后,受InternalResourceViewResolver影响的viewName,SpringMVC在解析它时,就会变为:prefix + viewName + suffix


基本使用

在这里插入图片描述

	<mvc:view-controller path="/jsp6" view-name="/jsp6"/>
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	    <property name="prefix" value="/WEB-INF/page/jsp"/>
	    <property name="suffix" value=".jsp"/>
	</bean>
@Controller
@RequestMapping("/IRVR")
public class JspController1 {
    @GetMapping("/jsp1")
    public String jsp1() {
        return "/jsp1";
    }

    @GetMapping("/jsp6")
    public ModelAndView jsp6() {
        return new ModelAndView("/jsp6");
    }
}
配置多个

在这里插入图片描述

虽然说order属性的值越小,优先级就越高。
但是SpringMVC并不会像我们想象的那样:如果在优先级高的里面找不到,就会去从优先级较低的里面去找。
而是在优先级高的里面找不到就直接报404了。
此时,order属性就是一个摆设
但转换角度思考一下,这儿的order可以起到一个开关的作用:你想使用哪个InternalResourceViewResolver,就将它的order值设为最小,让它的优先级最高,这样的话,其他比它优先级低的InternalResourceViewResolver,就永远不会被使用,SpringMVC只会使用优先级最高的那个

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="1"/>
        <property name="prefix" value="/WEB-INF/page/jsp"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="0"/>
        <property name="prefix" value="/public"/>
        <property name="suffix" value=".jsp"/>
    </bean>

在这里插入图片描述

在这里插入图片描述

忽略InternalResourceViewResolver

在这里插入图片描述

方法一

写清楚:是"redirect:"还是"forward:"

一旦写清楚是"redirect:"还是"forward:"之后,就不会受InternalResourceViewResolver的影响了。

	<mvc:view-controller path="/jsp6" view-name="forward:/WEB-INF/page/jsp/jsp6.jsp"/>
	<mvc:view-controller path="/jsp6-redirect" view-name="redirect:/public/jsp6.jsp"/>
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	    <property name="prefix" value="/WEB-INF/page/jsp"/>
	    <property name="suffix" value=".jsp"/>
	</bean>
@Controller
@RequestMapping("/IRVR")
public class JspController1 {
    @GetMapping("/jsp1")
    public String jsp1() {
        // 没有写清楚是forward:还是redirect:的viewName,会受InternalResourceViewResolver的影响
        return "/jsp1";
    }

    @GetMapping("/jsp6")
    public String jsp6() {
        return "redirect:/public/jsp6.jsp";
    }
}
方法二
  • InternalResourceView:转发
  • JstlView:转发(JSP中使用到了JSTL、国际化相关、…)
  • RedirectView:重定向
@Controller
@RequestMapping("/IRVR2")
public class JspController2 {
    @GetMapping("/forward")
    public ModelAndView forward() {
        ModelAndView mv = new ModelAndView();
        mv.setView(new InternalResourceView("/WEB-INF/page/jsp/jsp1.jsp"));
        return mv;
    }

    @GetMapping("/redirect")
    public ModelAndView redirect(HttpServletRequest request) {
        ModelAndView mv = new ModelAndView();
        // 使用RedirectView,必须写上context_path
        mv.setView(new RedirectView(request.getContextPath() + "/public/jsp6.jsp"));
        return mv;
    }
}

自定义InternalResourceView

为什么要自定义InternalResourceView?

我们知道,SpringMVC内部会根据我们的viewName去创建对应的View对象。

我们也知道会创建哪三种View对象:

  • InternalResourceView
  • JstlView
  • RedirectView

在applicationContext.xml中配置的InternalResourceViewResolver,其实还有一个属性,叫做viewClass,该属性的值就可以是:

  • org.springframework.web.servlet.view.InternalResourceView
  • org.springframework.web.servlet.view.JstlView
  • org.springframework.web.servlet.view.RedirectView

在这里插入图片描述

这三个View的父类都是AbstractUrlBasedView

在这里插入图片描述

AbstractUrlBasedView类中,我们可以找到一个方法checkResource

在这里插入图片描述

那么,这个方法checkResource方法是用来干嘛的呢?

  • 当SpringMVC创建View对象时,这个checkResource是用来告诉SpringMVC,viewName是否存在的。

  • 但是我们发现,这个方法始终返回的是true(它的三个子View也都没有覆盖该方法),也就是说,不管我们配置的viewName是否存在,它都会认为该viewName是存在的。

  • 那么,也就解释了,为什么之前order属性不起作用了:因为你不管viewName是否存在,每次返回的都是true,你每次都告诉SpringMVC,这个viewName是存在的,那么SpringMVC肯定不会去其他优先级的InternalResourceViewResolver中去寻找了。

  • 为了解决这个问题,我们就需要自定义一个InternalResourceView了。

自定义InternalResourceView

在这里插入图片描述

在这里插入图片描述

MyView:

public class MyView extends InternalResourceView {
    // 根据实际情况来返回
    // 存在:返回true
    // 不存在:返回false
    @Override
    public boolean checkResource(Locale locale) throws Exception {
        // 拿到打包部署项目之后的真实路径
        String path = getServletContext().getRealPath("/") + getUrl();
        File file = new File(path);
        return file.exists();
    }
}

使用:

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 优先级最低的InternalResourceViewResolver可以不用加:
		<property name="viewClass" value="programmer.lp.view.MyView"/>
		 -->
        <property name="order" value="2"/>
        <property name="prefix" value="/WEB-INF/page/html"/>
        <property name="suffix" value=".html"/>
    </bean>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="programmer.lp.view.MyView"/>
        <property name="order" value="1"/>
        <property name="prefix" value="/WEB-INF/page/jsp"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="programmer.lp.view.MyView"/>
        <property name="order" value="0"/>
        <property name="prefix" value="/public"/>
        <property name="suffix" value=".jsp"/>
    </bean>

通过自定义的InternalResourceViewMyView,重写其checkResource方法之后,将其设置给InternalResourceViewResolverviewClass属性,就可以使order属性生效了:在优先级较高的InternalResourceViewResolver中如果找不到某个viewName的话,就去优先级较低的InternalResourceViewResolver去寻找。

参考

小码哥-李明杰: Java从0到架构师③进阶互联网架构师.


本文完,感谢您的关注支持!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值