【零基础入门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>
    

$ 向Request域对象共享数据

$$ ServletAPI

编写我们的请求

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

编写我们的控制器方法

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

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

$$ ModelAndView

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

编写我们的请求

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

编写我们的控制器方法

// 通过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;
}

请添加图片描述

请添加图片描述

$$ Model

编写我们的请求

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

编写我们的控制器方法

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

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

$$ Map集合

编写我们的请求

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

编写我们的控制器方法

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

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

$$ ModelMap

编写我们的请求

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

编写我们的控制器方法

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

请添加图片描述

请添加图片描述

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

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

编写我们的请求

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

编写我们的控制器方法

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

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

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

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

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


二、视图

  • 什么是视图?

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

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

$ ThymeleafView

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

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

@RequestMapping("/testThymeleafView")
public String testThymeleafView(){
	return "success";
}

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

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

在这里插入图片描述

$ 转发视图

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

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

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

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

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

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

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

@RequestMapping("/testForward")
public String testForward(){
	return "forward:/testThymeleafView";
}

在这里插入图片描述

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

$ 重定向视图

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

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

@RequestMapping("/testRedirect")
public String testRedirect(){
	return "redirect:/testForward";
}

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

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

在这里插入图片描述

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

$ 视图控制器

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

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

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

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

    • 我们需要开启 mvc 的注解驱动才能解决这个问题
    <mvc:annotation-driven />
    
    • 根据使用情景不同这个注解驱动还有很多其他作用
  • 在此之前我们一直都是使用的都是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>

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>

编写我们请求跳转后的页面 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>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bow.贾斯汀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值