• 【零基础入门SpringMVC】第三期——请求域添加数据与视图


    一、域对象共享数据

    • SpringMVC 中有哪些域对象?

      • Request请求域,代表一次请求,从浏览器开启到关闭
      • Session请求域,代表一次会话,从服务器开启到关闭【一次getSession获得了cookie,这个会话没关闭,之后获取的都是这个session
      • Application请求域,代表整个应用的范围,一个项目对应一个
      • pageContext请求域,代表当前的jsp文件
    • 如何选择域对象?

      • 可以实现功能且范围最小的域对象
    • 准备工作:构建我们的SpringMVC的框架

      • 创建新的模块,确定打包方式和配置依赖
      • 添加webapp模块,然后在项目结构中添加web.xml文件
      • web.xml文件中注册过滤器和前端控制器
      • 编写我们SpringMVC的核心配置文件
        • 扫描组件
        • 添加 thymeleaf 的视图解析器
      • 创建我们的控制器【一个类文件】
      • 创建我们的前端页面
    • 我们将数据添加到请求域中了,那么我们如何获取数据呢?

      • 首先我们要知道域中的数据是以键值对的形式存在的
      • 在使用了thymeleafhtml页面中获取共享到request中的数据,我们可以直接通过键值对的key来获取数据
      • 如果是获取session中的数据,采用session.共享数据的键
      • 如果是获取application中的数据,采用application.共享数据的键
    • 在我们原生的 Servlet 中为我们提供了三种操作域中数据的方法:

      • setAttribute 方法,向域中添加数据
      • getAttribute 方法,获取域中数据
      • removeAttribute ,删除域中数据
    • 接下来我们介绍几种向域中添加数据的方式:【如何演示具体操作】

      • 第一步,编写我们在首页中写的超链接,作为请求
      • 第二步,在控制器中编写我们的控制器方法,用作处理请求【向请求域对象中添加数据】
      • 第三步,我们在最后跳转的页面中去获取一下我们添加的数据,验证是否添加成功
    • 因为我们获取域对象的数据根据域的不同在此处分为三种,我在这里直接给出跳转页面的代码

      <!DOCTYPE html>
      <html lang="en" xmlns:th="http://www.thymeleaf.org">
      <head>
          <meta charset="UTF-8">
          <title>用作请求匹配成功后的跳转页面</title>
      </head>
      <body>
      <h1>跳转页面成功</h1>
      <!--我们在前面将数据添加到了共享域中之后,我们可以在显示页面获取这些共享数据-->
      <!--因为我们要获取的是在request中的数据,所以我们直接通过key获取即可,尽管IDEA中会显示报错,但是实际没有问题-->
      <p th:text="${testRequestScope}"></p>
      <p th:text="${session.testSessionScope}"></p>
      <p th:text="${application.testApplicationScope}"></p>
      
      </body>
      </html>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

    $ 向Request域对象共享数据

    $$ ServletAPI

    编写我们的请求

    <a th:href="@{/testRequestByServletAPI}">通过原生ServletAPIRequest请求域添加数据</a><br>
    
    • 1

    编写我们的控制器方法

    // 通过原生的Servlet的API向域中共享数据
    @RequestMapping("/testRequestByServletAPI")
    public String testRequestByServletAPI(HttpServletRequest request){
    	request.setAttribute("testRequestScope", "Hello, Request");
    	return "success";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述
    请添加图片描述

    $$ ModelAndView

    • 模型就是我们要往域中共享数据的对象,视图是我们要往视图解析器里面传递的内容
    • 对于其他几种方式,通过前端控制器处理之后,最后都是包装成了ModelAndView对象

    编写我们的请求

    <a th:href="@{/testModelAndView}">通过ModelAndViewRequest请求域添加数据</a><br>
    
    • 1

    编写我们的控制器方法

    // 通过ModelAndView向域中共享数据
    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView(){
    	/*
    		我们的ModelAndView包含两个方面:
    			(1)M 代表模型,用来向请求域共享数据
    			(2)V 代表视图,用于页面跳转
    	*/
    	// 创建我们ModelAndView的对象
    	ModelAndView mav = new ModelAndView();
    	// 然后为其添加数据,就是向我们的 request请求域添加数据
    	mav.addObject("testRequestScope", "Hello, ModelAndView");
    	// 然后通过这个对象指定视图名称
    	mav.setViewName("success");
    	return mav;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    请添加图片描述

    请添加图片描述

    $$ Model

    编写我们的请求

    <a th:href="@{/testModel}">通过ModelRequest请求域添加数据</a><br>
    
    • 1

    编写我们的控制器方法

    // 通过Model向域中共享数据
        @RequestMapping("/testModel")
        public String testModel(Model model){
            // 添加数据
            model.addAttribute("testRequestScope", "Hello, Model");
            return "success";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    请添加图片描述
    请添加图片描述

    $$ Map集合

    编写我们的请求

    <a th:href="@{/testMap}">通过MapRequest请求域添加数据</a><br>
    
    • 1

    编写我们的控制器方法

    // 通过Map向域中共享数据
    @RequestMapping("/testMap")
    public String testMap(Map<String, Object> map){
    	// 通过map的put方法添加键值对
    	map.put("testRequestScope", "Hello, Map");
    	return "success";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    请添加图片描述
    请添加图片描述

    $$ ModelMap

    编写我们的请求

    <a th:href="@{/testSession}">通过ServletAPISession请求域对象中添加数据</a><br>
    
    • 1

    编写我们的控制器方法

    // 通过ModelMap向域中共享数据
    @RequestMapping("/testModelMap")
    public String testModelMap(ModelMap modelMap){
    	// 通过map的put方法添加键值对
    	modelMap.addAttribute("testRequestScope", "Hello, ModelMap");
    	return "success";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    请添加图片描述

    请添加图片描述

    • 我们的Model、Map、ModelMap之前是存在联系的,两个接口一个类
      • 他们最终都是由同一个类实现的 ,BindingAwareModelMap

    $ 通过ServletAPI向Session域对象共享数据

    编写我们的请求

    <a th:href="@{/testSession}">通过ServletAPISession请求域对象中添加数据</a><br>
    
    • 1

    编写我们的控制器方法

    // 通过ServletAPI向我们的Session请求域中添加共享数据
        @RequestMapping("/testSession")
        public String testSession(HttpSession session){
            session.setAttribute("testSessionScope", "Hello, Session");
            return "success";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述
    请添加图片描述

    $ 通过ServletAPI向Application域对象共享数据

    <a th:href="@{/testApplication}">通过ServletAPIApplication请求域对象中添加数据</a>
    
    • 1
    // 向我们Application请求域中添加数据
    @RequestMapping("/testApplication")
    public String testApplication(HttpSession session){
    	// 通过session的getServletContext方法获取我们的application对象
    	ServletContext application = session.getServletContext();
    	// 然后调用我们的add~方法向域中添加数据
    	application.setAttribute("testApplicationScope", "Hello, Application");
    	// 返回页面
    	return "success";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    请添加图片描述
    请添加图片描述


    二、视图

    • 什么是视图?

      • SpringMVC中,视图是 View 接口
      • 将模型中的数据经过渲染后展示给用户
    • 视图分为哪些种类?【列举几种常见的】

      • 转发视图
      • 重定向视图
      • 引入 jst 的依赖后,转发视图会自动转化为 jstView
      • 如是通过Thymeleaf解析之后得到的就是 ThymeleafView
    • 接下来我们将展开介绍几种常见的视图

    $ ThymeleafView

    • 我们导入了Thymeleaf的框架的依赖,并且在SpringMVC的核心配置文件中使用了这个视图解析器为前提
    • 如果我们控制器方法返回的视图名没有前缀,那么最后得到的就是ThymeleafView
    • 主要流程:
      • 视图名被SpringMVC配置的视图解析器解析
      • 视图名通过拼接视图前缀和后缀后得到最终路径
      • 最后通过转发的方式实现跳转

    我们之前练习的一直都是 Thymeleaf 的视图

    @RequestMapping("/testThymeleafView")
    public String testThymeleafView(){
    	return "success";
    }
    
    • 1
    • 2
    • 3
    • 4

    可以看到控制器方法返回时没有任何前缀,我们获得的就是ThymeleafView

    如果想进行测试可以在我们的首页写一条超链接,请求地址为 /testThymeleaf,运行后点击超链接就可以查看效果

    在这里插入图片描述

    $ 转发视图

    • SpringMVC中默认的转发视图为 InternalResourceView 【网络资源视图】

    • 当我们为控制器方法返回的视图名添加 forward: 前缀,得到的就是 InternalResourceView

    • 这种视图不会通过核心配置文件中的视图解析器解析,而是将前缀后面的路径作为最终路径通过转发的方式实现跳转

    • 转发可以转发到一个页面,也可以转发到一个请求上

    主页编写发起请求的超链接

    <a th:href="@{/testForward}">测试InternalResourceView</a><br>
    
    • 1

    控制器实现具体的跳转方法,此处我们跳转到/testThymeleafView请求上,因为我们的html页面的位置浏览器访问不到

    @RequestMapping("/testForward")
    public String testForward(){
    	return "forward:/testThymeleafView";
    }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    • 注意:
      • 因为我们转发到一个 /testThymeleafView 请求上
        • 所以我们先生成的是 InternalResourceView
        • 后生成的是 ThymeleafView
      • 尽管我们是跳到 /testThymeleafView 请求上进一步获得页面的
        • 但是我们的转发地址栏显示testForward,页面是success

    $ 重定向视图

    • SpringMVC中默认的重定向视图是 RedirectView
    • 与转发视图使用方式类似,只是将前缀替换为 redirect:
    • 通过重定向的方式实现跳转
    • 重定向视图在解析时,会判断剩余部分是否以正斜杠 / 开头,若是则会自动拼接上下文路径

    我们直接重定向到 /testForward 请求上去

    @RequestMapping("/testRedirect")
    public String testRedirect(){
    	return "redirect:/testForward";
    }
    
    • 1
    • 2
    • 3
    • 4

    发起请求页要写一个超链接

    <a th:href="@{/testRedirect}">测试RedirectView</a>
    
    • 1

    在这里插入图片描述

    • 对于重定向来说,重定向后的地址拼接上上下文就是最后页面地址栏中的地址
    • 重定向和转发有什么区别呢?
      • 浏览器请求次数不同
        • 转发:当浏览器收到请求后,完成响应跳转到另一个地址
        • 重定向:浏览器向服务器发送一个请求收到响应后,再向一个新地址发送请求
      • 跳转地址不同
        • 转发:只能在本站点资源内进行跳转
        • 重定向:可以跳转到任意的地址 【其他站点】
      • 地址栏显示不同:
        • 转发:地址栏不会变化
        • 重定向:地址栏会发生变化
      • 数据共享规则不同:
        • 转发:在一次请求中共享数据
        • 重定向:在两次请求中不共享数据
      • 发生行为不同
        • 转发:服务器行为
        • 重定向:客户端行为

    $ 视图控制器

    • 是一种可以代替控制器方法实现简单页面跳转的方式
    • 简单体现在请求直接返回一个视图名,没有啥其他业务功能

    我们可以在springMVC的核心配置文件中进行声明

    <!--尽管此处success报错,但是不影响使用:配置了这个后控制器中的方法就会失效-->
    <!--我当前想到的作用就是将上下文路径定位到一个页面-->
    <mvc:view-controller path="/success" view-name="success"></mvc:view-controller>
    
    • 1
    • 2
    • 3
    • 这个标签有两个常用的属性:

      • path 代表我们的请求地址
      • view-name 代表我们要跳转的视图名
    • 当我们设置了这个标签后,控制器里的所有方法都会失效

      • 我们需要开启 mvc 的注解驱动才能解决这个问题
      <mvc:annotation-driven />
      
      • 1
      • 根据使用情景不同这个注解驱动还有很多其他作用
    • 在此之前我们一直都是使用的都是html页面进行演示,如果是jsp文件,我们又将如何处理呢?

    $ 使用JSP

    • JSP 本身就是一个Servlet,可以直接访问,所以我们不需要去设置首页了
    • JSP 中只存在转发视图和重定向视图
    • 需求:我们要通过一个 jsp 模块演示如何显示 jsp 文件的视图

    我们新建一个模块,然后将打包方式设置为 war,然后导入依赖,添加web模块,添加xml文件

    web.xml 中依旧注册解决乱码问题的过滤器和前端控制器 Dispatcher

    对于springMVC的核心配置文件所有变化,我们不在使用之前的视图解析器,而是替换为 InternalResourceViewResolver

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--扫描组件-->
        <context:component-scan base-package="com.atguigu.mvc.controller"/>
    
        <!--
            在jsp中,不设置任何前缀自身也是一个转发视图,所以直接采用InternalResolver解析器
        -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--也需要我们指定前缀和后缀-->
            <property name="prefix" value="/WEB-INF/templates/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    webapp 目录下,我们编写 index.jsp 文件

    • 上面我们了解到当前 jsp 页面就是一个最小的域对象 pageContext

    • jsp 页面中动态获取上下文路径 pageContext.request.contextPath【使用EL表达式】

    • 那么什么是 EL 表达式呢?

      • 全称 Expression Language,语法格式 ${表达式},我们将其使用在jsp页面中,表达式通过为域对象的key
      • 代替 JSP 进行数据的输出,只能用来获取数据,如果存在多个域对象,那么从低级向高级域搜索【先从pageContext查找key】
    <%--
      Created by IntelliJ IDEA.
      User: npc
      Date: 2022/11/23
      Time: 17:37
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>第一个使用jdp的springMVC模块</title>
    </head>
    <body>
    
    <h1>首页</h1>
    <a href="${pageContext.request.contextPath}/success">点击跳转我们指定的jsp页面</a>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    编写我们请求跳转后的页面 success.jsp

    <%--
      Created by IntelliJ IDEA.
      User: npc
      Date: 2022/11/23
      Time: 17:42
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>成功</h1>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

  • 相关阅读:
    👋 和我一起学 Three.js【初级篇】:0. 总论
    7.nodejs--egg框架简介、以及get、post请求
    [洛谷] P1141 01迷宫
    旅游卡小程序开发搭建
    如何对pdf文件进行压缩?
    asp.net web api2设置默认启动登录页面
    在线问诊 Python、FastAPI、Neo4j — 构建问题分类器
    nodejs--开发自己的项目——5.1——个人中心模块——更新用户信息——设置的url:/my/userinfo ——post请求
    动态规划之线性DP
    Python~Pandas 小白避坑之常用笔记
  • 原文地址:https://blog.csdn.net/qq_61323055/article/details/127989980