前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深度学习springMVC(五)一篇文章讲清楚 SpringMVC的视图解析器和 自定义视图解析器(看不懂你打我)

深度学习springMVC(五)一篇文章讲清楚 SpringMVC的视图解析器和 自定义视图解析器(看不懂你打我)

作者头像
一写代码就开心
发布2021-07-08 15:23:45
6540
发布2021-07-08 15:23:45
举报
文章被收录于专栏:java和pythonjava和python

目录

SpringMVC的视图解析器

问题:

我们在使用了SpringMVC后,对于请求的处理由以前我们自己声明

Servlet处理,变为声明单元方法来处理。请求处理完成之后,需要将

处理结果响应给浏览器 ,响应方式有直接响应,请求转发,重定向。对于

请求转发和重定向,我们在单元方法中是通过返回值来告诉 DispatcherServlet如何进行此次请求的响应。而方法的返回值只有一个,所 以,我们就需要在返回值值中声明指定的关键字,让DispatcherServlet可以

通过关键字来区分是请求转发还是重定向,那么DispactherServlet底层是

如何来实现请求转发和重定向的区分的呢?

解决:

在DispatcherServlet的底层,增加逻辑代码,根据单元方法的返回值

将其返回值中的forward或者redirect关键字拆分出来,然后根据关键字

以及资源路径,最终完成资源的请求转发或者重定向。而这段逻辑代码

就是根据单元方法的返回值来完成最终的资源的处理,为了让Dispatcher

Servlet的代码结构层次更加清晰,我们可以将这段逻辑代码专门封装

起来,然后在DispatcherServlet中进行调用即可。也就意味着单元方法的

返回值被DispatcherServlet接收后,作为实参传递给了这段封装好的逻辑

代码。

实现:

视图解析器

本质:

视图解析器就是SpringMVC官方封装好的,根据单元方法的返回值

完成对应的请求转发或者重定向的对象。

**由DisatcherServlet来调用。**把返回值作为参数给DisatcherServlet。DisatcherServlet里面会创建一个处理返回值类的对象,这个对象调用里面 的方法就可以处理 返回值了

内容:

InternalResourceView:请求转发

RedirectView:重定向

ModelAndView:请求转发和重定向

回顾没有学视图解析器之前,我们如何实现转发和重定向

使用关键字实现的,使用forward关键字完成响应,使用redirect关键字完成响应。

具体不清楚这些关键字的,看之前的文章

深度学习springMVC(四)springmvc如何实现数据的响应,SpringMVC中使用作用域对象完成数据的流转(看不懂你打我)

每次我们自己写关键字,springmvc框架也想到了,比较的麻烦,所以人家把这些关键字封装到类里面,返回值作为参数给了这些类对象,就可以实现转发或者重定向。

视图解析器代码实现

使用View接口完成请求转发|重定向

代码语言:javascript
复制
  //声明单元方法:使用View接口的子类对象完成请求转发或者重定向

    /**
     * 使用View接口完成请求转发|重定向
     *  解释:
     *      SpringMVC的官方,提供了一个叫做View的接口,告诉开发人员
     *      DispatcherServlet底层会调用View接口的实例化对象中的逻辑方法
     *      来完成对应的请求转发和重定向。
     *  使用:
     *      1. 单元方法的返回值为View接口类型
     *      2.真实return的为View接口的实例化对象(视图解析器)。
     *          官方提供的实现了View接口的视图解析器:
     *              InternalResourceView:请求转发
     *              RedirectView:重定向
     * @return
     */
    @RequestMapping("demoView")
   public View demoView(HttpServletRequest request){
       //处理请求
        System.out.println("MyController.demoView:View接口实例化对象完成请求转发|重定向");
       //响应结果
            //请求转发
                //return  new InternalResourceView("/req.jsp");
            //重定向
                return new RedirectView(request.getContextPath()+"/redirect.jsp");
   }

SpringMVC视图解析器升级:ModelAndView

代码语言:javascript
复制
 /**
     * SpringMVC视图解析器升级:ModelAndView
     *  问题:
     *      在原有的View接口的视图解析器中需要自己在单元方法中根据响应方式
     *      来创建对应的视图解析器对象返回给DispatcherServlet使用,过于麻烦。
     *  解决:
     *      从根据响应方式的不同创建不同的视图解析器对象,变为只创建一个
     *      视图解析器对象,该对象内部自动根据参数来实现请求转发或者重定向。
     *  实现:
     *      ModelAndView
     *   注意:
     *      升级后也就意味着DispatcherServlet使用ModelAndView来接收
     *      单元方法的返回值,为了兼容早期版本,让ModelAndView可以接收
     *      View接口的实例化对象。
     *  特点:
     *    ModelAndView对象是Model和View对象的结合体。既可以作为视图解析器使用
     *    又可以作为数据流转的载体使用。
     */
    @RequestMapping("md")
    public ModelAndView demoModelAndView(){
        //处理请求
        System.out.println("MyController.demoModelAndView:ModelAndView视图解析器");
        //响应结果
            //创建ModelAndView对象
            ModelAndView modelAndView=new ModelAndView();
            modelAndView.addObject("str","我是流转的数据");
            //请求转发
                //modelAndView.setViewName("forward:/mdReq.jsp");
           //重定向
                modelAndView.setViewName("redirect:/mdRedirect.jsp");
            return modelAndView;
    }

SpringMVC视图解析器再次升级:

代码语言:javascript
复制
  /**
     * SpringMVC视图解析器再次升级:
     *  问题:
     *      在使用了ModelAndView对象后,已经很爽了。但是在单元方法中
     *      我们还需要创建ModelAndView对象并将请求转发或者重定向的
     *      路径存储进入,返回给DispatcherServlet使用,而我们真正
     *      想写的是资源路径以及响应方式
     *  解决:
     *      我们在单元方法中直接返回字符串资源路径及其响应方式关键字。
     *      由DispatcherServlet底层帮我们创建ModelAndView来接收
     *      单元方法的返回值。
     *  注意:
     *      虽然我们在单元方法中直接返回的字符串数据,但是DispatcherServlet
     *      并不是直接使用字符串数据而是仍然调用ModelAndView视图解析器完成请求转发或者重定向。
     */
    @RequestMapping("demoString")
    public String demoString(){
        //处理请求
        System.out.println("目前的请求转发或者重定向的方式");
        //响应结果
            //请求转发
                //return "forward:/req.jsp";
            //重定向
                return "redirect:/redirect.jsp";
    }

SpringMVC的自定义视图解析器

问题

目前我们在SpringMVC的响应中,虽然我们直接在单元方法中返回字符串数据来

表明请求转发或者重定向的资源,但是DispatcherServlet的底层默认使用 ModelAndView来完成视图资源的解析和跳转。但是ModelAndView这个视图 解析器比较死板,ModelAndView会将单元方法返回的字符串,根据关键拆分后

来完成资源的跳转,比如:”forward:/index.jsp”,那么ModelAndView就会直接

请求转发index.jsp资源。但是我们在实际生产环境中往往会有很多特殊的需求,

这样ModelAndView就无法满足了,比如,我们在项目下创建一个a文件夹,在

a文件夹下创建b子文件夹,在b下创建一个c子文件夹,然后将项目的页面资 源全部放到c文件夹下,这样我们如果在单元方法中请求转发c文件夹中的资源,

返回值路径就会很麻烦:

”forward:/a/b/c/index.jsp”

”forward:/a/b/c/page.jsp”

“forward:/a/b/c/sel.jsp”…

而且后期一旦资源路径的文件夹名字发生变更,修改起来也会非常的麻烦。

自己写的路径太长,太麻烦

**核心问题:**官方视图 解析器比较死板,只会转发重定向,我们需要灵活 的视图解析器,自己写的路径太长,太麻烦

解决:

使用自定义视图解析器,而我们自定义的视图解析器除了可以让我们根据需求

配置一些路径上的常量参数以外,还需具备ModelAndView的逻辑。所以,

我们自己需要从头创建一个新的视图解析器,在我们自己创建的视图解析器中

声明ModelAndView中的原有逻辑代码,以及我们自己需要的部分常量参数。

但是ModelAndView的逻辑我们是不知道的,那么能不能让SpringMVC官方

提供一个支持部分数据自定义的视图解析器呢,答案是可以的。我们可以通过配置 文件来配置一些我们在视图解析器中的常量数据

实现:

代码语言:javascript
复制
	InternalResourceViewResolver

概念:

因为InternalResourceViewResolver可以让我们通过配置文件来设置一些常量

参数,所以我们将该视图解析器称为自定义视图解析器。

使用:

1.在springmvc.xml文件中进行配置

2.在单元方法中按照指定的格式返回资源路径

代码语言:javascript
复制
 <!--配置自定义视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置资源路径的前缀-->
            <property name="prefix" value="/a/b/c/"></property>
        <!--配置资源路径的后缀-->
            <property name="suffix" value=".jsp"></property>
    </bean>
代码语言:javascript
复制
@Controller
public class MyControllerView {
    //声明单元方法:使用默认的ModelAndView视图解析器
    @RequestMapping("mv")
    public String demoMv(){
        System.out.println("MyControllerView.demoMv:测试使用默认的ModelAndView视图解析器");
        return "forward:/a/b/c/c.jsp";
    }

返回的字符串里面带了forward这些关键字,就调用ModelAndView视图解析器。不带,就使用自定义视图解析器





    //声明单元方法:使用默认的ModelAndView视图解析器
    @RequestMapping("myView")
    public String demoInternalResourceViewResolver(){
        System.out.println("MyControllerView.demoInternalResourceViewResolver:测试使用自定义视图解析器");
        return "c";
    }
}

SpringMVC自定义视图解析器的使用

目前项目资源的声明位置和访问中存在的问题

问题:

目前我们在完成功能开发时,会将项目相关的页面资源及静态资源直接声明

在web目录下,或者web目录下的子文件夹中。而web目录及其声明的子

目录中的资源,在浏览器中是可以直接被访问到的。也就是说,只要我们知道

某个资源的URL地址,在浏览器中是可以直接发起请求访问该资源的,极不安全。

实现方案:

在我们的web项目中造一间密室,将重要的资源放到密室中。而密室是对外不开 放的,也就说密室中的资源必须通过tomcat服务器的内部转发才能进行访问。就 算浏览器听说项目有这样密室,并且密室中也有浏览器想要的资源,浏览器发起的 请求地址是正确的,但是我们可以在服务器端死不承认,我们没有这个资源,在后 台给浏览器响应404.如果是我们觉得靠谱的请求,我们就在服务器端请求转发资 源给浏览器使用。

项目密室:

其实我们的web项目在创建的时候就自动的在web目录下创建了密室,就是

WEB-INF文件夹。也就是说WEB-INF文件夹下的资源浏览器是无法直接访问

的,必须通过内部请求转发才能访问。

代码语言:javascript
复制
   //声明单元方法:检查请求,是否给密室中的资源
    @RequestMapping("getJsp")
    public String getJsp(){
        //处理请求
        System.out.println("MyController.getJsp:检查密室资源请求是否合理");
        //响应结果
        return "forward:/WEB-INF/jsp/cc.jsp";
    }

使用自定义视图解析器优化资源跳转路径

问题:

我们在将重要的项目资源放在WEB-INF文件夹中后,只能通过内部的请求转发来

访问资源。如果WEB-INF下的资源较多,造成请求转发的路径书写麻烦,而且后 期一旦资源的目录发生变更,修改起来会非常的麻烦,怎么办?

解决:

我们真正想在单元方法中想写的是资源的名字,而请求转发WEB-INF下的资源路 径是公共的,每次都要写。而刚好我们的自定义视图解析器就是专门用来进行请求

转发的,而且可以设置转发资源的公共前缀和后缀信息。所以,我们可以使用自定 义视图解析器来完成WEB-INF下的资源的请求转发。

代码实现

代码语言:javascript
复制
  <!--配置自定义视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
代码语言:javascript
复制
    //声明单元方法:使用自定义视图解析器请求转发WEB-INF下的资源
    @RequestMapping("getJsp2")
    public String getJsp2(){
        //处理请求
        System.out.println("MyController.getJsp2:使用自定义视图解析器访问");
        //响应结果
        return "dd";
    }

使用restful声明公共单元方法请求转发WEB-INF下的资源

问题:

在项目中使用了自定义视图解析器后,可以在单元方法中简单的返回一个 WEB-INF下的资源的名字就可以完成资源的请求转发了,美滋滋。但是我们的资 源是非常多的,但是我们的单元方法的返回值只能有一个。总不能我们给WEB-INF

下的每个资源都声明一个对应的单元方法来完成请求转发吧,太麻烦了。

解决:

根据请求,请求转发WEB-INF下的资源的单元方法是肯定要声明的。我们可以

声明一个公共的单元方法,该单元方法不参与请求的逻辑处理,只负责根据请求

转发WEB-INF下的资源。

实现:

使用restful完成

代码

代码语言:javascript
复制
  <!--配置自定义视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
代码语言:javascript
复制
//声明公共单元方法:请求转发WEB-INF下的资源
    @RequestMapping("{url}")
    public String getJsp3(@PathVariable  String url){
        //处理请求
        System.out.println("MyController.getJsp3:公共单元方法,请求转发WEB-INF下的资源");
        //响应结果
        return url;
    }

重新配置springmvc.xml文件中的资源放行

如果把静态资源放到 web-inf 下,我们需要资源放行

代码语言:javascript
复制
    <!--配置静态资源放行-->
    <mvc:resources mapping="/js/**" location="/WEB-INF/js/"></mvc:resources>
    <mvc:resources mapping="/css/**" location="/WEB-INF/css/"></mvc:resources>
    <mvc:resources mapping="/images/**" location="/WEB-INF/images/"></mvc:resources>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-07-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • SpringMVC的视图解析器
    • 问题:
      • 解决:
        • 实现:
          • 本质:
            • 内容:
              • 回顾没有学视图解析器之前,我们如何实现转发和重定向
                • 视图解析器代码实现
                  • 使用View接口完成请求转发|重定向
                  • SpringMVC视图解析器升级:ModelAndView
                  • SpringMVC视图解析器再次升级:
              • SpringMVC的自定义视图解析器
                • 问题
                  • 解决:
                    • 实现:
                      • 概念:
                        • 使用:
                        • SpringMVC自定义视图解析器的使用
                          • 目前项目资源的声明位置和访问中存在的问题
                            • 问题:
                            • 实现方案:
                            • 项目密室:
                          • 使用自定义视图解析器优化资源跳转路径
                            • 问题:
                            • 解决:
                            • 代码实现
                          • 使用restful声明公共单元方法请求转发WEB-INF下的资源
                            • 问题:
                            • 解决:
                            • 实现:
                            • 代码
                          • 重新配置springmvc.xml文件中的资源放行
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档