Erlo

Spring MVC 获取三个域(request请求域,session 会话域,application 应用域)对象的方式

2024-06-30 17:29:20 发布   41 浏览  
页面报错/反馈
收藏 点赞

1. Spring MVC 获取三个域(request请求域,session 会话域,application 应用域)对象的方式

@


2. Servlet中的三个域对象

Servlet 中的三个域对象分别是:

请求域:request
会话域:session
应用域:application
三个域都有以下三个方法:

// 向域中存储数据
void setAttribute(String name, Object obj);

// 从域中读取数据
Object getAttribute(String name);

// 删除域中的数据
void removeAttribute(String name);

主要是通过:setAttribute + getAttribute 方法来完成在域中数据的传递和共享。

request:

接口名:HttpServletRequest
简称:request
request对象代表了一次请求。一次请求一个request。

使用请求域的业务场景:

在A资源中通过转发的方式跳转到B资源,因为是转发,因此从A到B是一次请求,如果想让A资源和B资源共享同一个数据,可以将数据存储到request域中。

session:

接口名:HttpSession
简称:session
session对象代表了一次会话。从打开浏览器开始访问,到最终浏览器关闭,这是一次完整的会话。每个会话session对象都对应一个JSESSIONID,而JSESSIONID生成后以cookie的方式存储在浏览器客户端。浏览器关闭,JSESSIONID失效,会话结束。

使用会话域的业务场景:

  1. 在 A 资源中通过重定向(重定向是一次新的请求)的方式转到 B 资源,因为是重定向,因此从 A到 B 是两次请求,如果想让 A 资源和 B 资源共享同一个数据,可以将数据存储到 session域中
  2. 登录成功后保存用户的登录状态

application

接口名:ServletContext
简称:application
application对象代表了整个 web 应用,服务器启动的创建,服务器关闭时销毁,对于一个 web 应用来说,application 对象只有一个。

使用应用域的业务场景:记录网站的在线人数。

3. 准备工作

3.1 创建模块,添加依赖

在这里插入图片描述



    4.0.0

    com.rainbowsea
    springmvc-004-blog
    1.0-SNAPSHOT
    war

    
        17
        17
    

    
        
        
            org.springframework
            spring-webmvc
            6.1.4
        
        
        
            ch.qos.logback
            logback-classic
            1.5.3
        
        
        
            jakarta.servlet
            jakarta.servlet-api
            6.0.0
            provided
        
        
        
            org.thymeleaf
            thymeleaf-spring6
            3.1.2.RELEASE
        
    



3.2 添加 web 支持

先在 main 目录下,添加名为 webapp 的目录(文件夹),只能是这个 webapp 目录名,不可以是其他的。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


3.3 编写 web.xml 文件

在这里插入图片描述




    
    
        springmvc
        org.springframework.web.servlet.DispatcherServlet
        
        
            contextConfigLocation
            classpath:springmvc.xml
        
        
        1
    
    
        springmvc

        /
    


3.4 创建 IndexController 类

创建 IndexController 类作为 首页来使用

在这里插入图片描述

package com.rainbowsea.springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller // 交给 Spring IOC 容器管理
public class IndexController {


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

3.5 编写 springmvc.xml

在 springmvc.xml 当中配置两个信息:

  • 组件扫描
  • 视图解析器

在这里插入图片描述




    
    

    
    
        
        
        
        
        
        
            
                
                
                    
                        
                        
                        
                        
                        
                        
                        
                        
                    
                
            
        
    


3.6 编写 index.html 文件视图

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试 request 域对象

3.7 部署测试

在这里插入图片描述


4. Spring MVC 获取 request 请求域对象的五种方式

在SpringMVC中,在request域中共享数据有以下五种方式:

  1. 使用原生Servlet API方式。
  2. 使用Model接口。
  3. 使用Map接口。
  4. 使用ModelMap类。
  5. 使用ModelAndView类。

4.1 第一种方式:使用原生Servlet API方式 获取到 request 请求域,同时获取到请求域当中对应的内容

第一种方式: 在Spring MVC 中使用原生的 Servlet API 可以完成 request 域数据共享
,在处理器方法上添加 HttpServletRequest 参数即可。

将 HttpServletRequest 作为参数,定义到方法上,Spring MVC 框架会自动从 Tomcat 服务器当中获取到这个 HttpServletRequest 对象的值,然后,传递给这个方法的 HttpServletRequest 参数值上,完成赋值。

创建一个 RequestScopeTestController 类,注意要交给 Spring IOC 容器管理起来

在这里插入图片描述

package com.rainbowsea.springmvc.controller;


import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交给Spring IOC 容器管理
public class RequestScopeTestController {


    // request 请求域
    @RequestMapping("/testServletAPI")
    public String testServletAPI(HttpServletRequest request) {

        // 将共享的数据存储到 request域当中
        // 跳转视图,在视图页面将request域中的数据取出,这样就完成了,Controller和View在同一个请求当中两个组件之间的数据共享

        // 将共享的数据存储到request域当中
        request.setAttribute("testRequestScope", "在SpringMVC当中使用原生Servlet API 完成 request域的数据共享");
        System.out.println(request);
        System.out.println(request.getClass().getName());

        // 跳转视图,在视图页面将 request 域中的数据取出来,这样就完成了,Controller 和 View 在同
        // 一个请求当中两个组件之间数据的共享

        // 注意:这个是跳转,默认情况下是,转发的方式,(转发 forward 是一次请求)
        // 这个返回的是一个逻辑视图名称,经过视图解析器解析,变成物理视图名称,/WEB-INF/templates/ok.html
        return "ok";
    }

}

index页面超链接的编写:

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试 request 域对象

测试在SpringMVC当中使用原生 Servlet API 完成 request 域的数据共享

ok 页面获取 request 请求域的展示

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试 request 域对象

测试在SpringMVC当中使用原生 Servlet API 完成 request 域的数据共享

测试结果:

在这里插入图片描述

这种方式当然可以,用 SpringMVC 框架,不建议使用原生 Servlet API

4.2 第二种方式:使用 Model 接口 获取到 request 请求域,同时获取到请求域当中对应的内容

在这里插入图片描述


import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交给Spring IOC 容器管理
public class RequestScopeTestController {

    @RequestMapping(value = "/testModel")
    public String testModel(Model model) {
        // 向 request 域当中绑定数据
        model.addAttribute("testRequestScope", "在SpringMVC 当中使用 Model 接口完成 request 域数据共享");
        System.out.println(model);
        System.out.println(model.getClass().getName());
        // 转发
        return "ok";
    }
}

index 页面超链接的编写:

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试 request 域对象

测试在SpringMVC当中使用原生 Servlet API 完成 request 域的数据共享
测试在 Spring MVC 当中使用 Model 接口完成 request 域数据共享

ok 页面获取 request 请求域的展示

在这里插入图片描述




    
    OK


启动 Tomcat 服务器测试结果:

在这里插入图片描述

4.3 第三种方式:使用Map接口 获取到 request 请求域,同时获取到请求域当中对应的内容

在这里插入图片描述

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交给Spring IOC 容器管理
public class RequestScopeTestController {
    @RequestMapping(value = "/testMap")
    public String testMap(Map map) {

        // 向 request 域当中的存储数据
        map.put("testRequestScope", "在Spring MVC 当中使用 Map接口完成 request 域数据共享");
        System.out.println(map);
        System.out.println(map.getClass().getName());
        // 转发
        return "ok";
    }
}

index 页面超链接的编写:

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试 request 域对象

测试在SpringMVC当中使用原生 Servlet API 完成 request 域的数据共享
测试在 Spring MVC 当中使用 Model 接口完成 request 域数据共享
测试在Spring MVC 当中使用 Map 接口完成 request 域数据共享

ok 页面获取 request 请求域的展示 保持不变

启动 Tomcat 服务器测试结果:

在这里插入图片描述

4.4 第四种方式:使用 ModelMap 类 获取到 request 请求域,同时获取到请求域当中对应的内容

在这里插入图片描述



import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交给Spring IOC 容器管理
public class RequestScopeTestController {

    @RequestMapping(value = "/testModelMap")
    public String testModelMap(ModelMap modelMap) {
        // 向 request 域当中存储数据
        modelMap.addAttribute("testRequestScope", "在Spring MVC 当中 ModelMap类完成request 域数据共享");
        System.out.println(modelMap);
        System.out.println(modelMap.getClass().getName());
        return "ok";
    }
}

index 页面超链接的编写:

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试 request 域对象

测试在SpringMVC当中使用原生 Servlet API 完成 request 域的数据共享
测试在 Spring MVC 当中使用 Model 接口完成 request 域数据共享
测试在Spring MVC 当中使用 Map 接口完成 request 域数据共享
测试在Spring MVC当中使用 ModelMap 类完成 request 域数据共享

ok 页面获取 request 请求域的展示 保持不变

启动 Tomcat 服务器测试结果:

在这里插入图片描述

4.5 补充:Model、Map、ModelMap的关系

可以在以上Model、Map、ModelMap的测试程序中将其输出,看看输出什么:

在这里插入图片描述

看不出来什么区别,从输出结果上可以看到都是一样的。
可以将其运行时类名输出:

在这里插入图片描述

在这里插入图片描述

通过输出结果可以看出,无论是Model、Map还是ModelMap,底层实例化的对象都是:BindingAwareModelMap。

可以查看 BindingAwareModelMap的继承结构:

在这里插入图片描述

通过继承结构可以看出:BindingAwareModelMap继承了ModelMap,而ModelMap又实现了Map接口。
另外,请看以下源码:

在这里插入图片描述

可以看出ModelMap又实现了Model接口。因此表面上是采用了不同方式,底层本质上是相同的。
SpringMVC之所以提供了这些方式,目的就是方便程序员的使用,提供了多样化的方式,可见它的重要性。

4.6 第五种方式:使用 ModelAndView 类获取到 request 请求域,同时获取到请求域当中对应的内容

在 Spring MVC 框架中为了更好的体现 MVC 架构模式,提供了一个类:ModelAndView。

这个类的实例封装了 Model 和 View 。也就是说 这个类封装业务处理之后的数据,也体现了跳转到哪个视图。使用它也可以完成 request 域数据共享。

使用这种方式的注意事项:

  1. 方法的返回值类型不是 String 了,而是 ModelAndView 对象
  2. ModelAndView 不是出现在方法的参数位置上了,而是在方法体中 new 出来的
  3. 需要调用 addObject() 向域中存储数据
  4. 需要调用 setViewName() 设置视图的名字
  5. 最后需要将 ModelAndView 作为参数,返回。

在这里插入图片描述


import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交给Spring IOC 容器管理
public class RequestScopeTestController {



    @RequestMapping(value = "/testModelAndView")
    public ModelAndView testModelAndView() {
        // 创建模型视图对象
        ModelAndView modelAndView = new ModelAndView();
        // 给模型视图对象绑定数据
        modelAndView.addObject("testRequestScope", "在SpringMVC当中使用 ModelAndView 类完成 request 域数据共享");

        // 给模型视图对象 绑定视图(绑定逻辑视图名称)
        modelAndView.setViewName("ok");

        // 返回模型视图对象
        return modelAndView;
    }
}

index页面超链接的编写:

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试 request 域对象

测试在SpringMVC当中使用原生 Servlet API 完成 request 域的数据共享
测试在 Spring MVC 当中使用 Model 接口完成 request 域数据共享
测试在Spring MVC 当中使用 Map 接口完成 request 域数据共享
测试在Spring MVC当中使用 ModelMap 类完成 request 域数据共享
测试在Spring MVC当中使用 ModelAndView 类完成 request 域数据共享

ok 页面获取 request 请求域的展示的编写:

在这里插入图片描述




    
    OK


启动 Tomcat 服务器测试结果:

在这里插入图片描述

4.7 补充:ModelAndView 源码分析

以上我们通过了五种方式完成了request域数据共享,包括:原生 Servlet API,Model、Map、ModelMap、ModelAndView
其中后四种:Model、Map、ModelMap、ModelAndView。

这四种方式在底层DispatcherServlet调用我们的Controller之后,返回的对象都是ModelAndView,

这个可以通过源码进行分析。

在以上四种方式中,拿Model举例,添加断点进行调试:

在这里插入图片描述

启动服务器,发送请求,走到断点:

在这里插入图片描述

查看VM Stack信息:

在这里插入图片描述

查看 DispatcherServlet 的1089行,源码如下:
在这里插入图片描述

可以看到这里,无论你使用哪种方式,最终都要返回一个ModelAndView对象。

对于 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 处理器方法来说,不管你使用的参数是 Model接口,还是Map接口,还是ModelMap类,还是ModelAndView类,最终处理器方法执行结束之前
返回的都是 ModelAndView对象,这个返回的ModelAndView对象给DispatcherServlet类了
当请求路径不是JSP的时候,都会走前端控制器 DispatcherServlet
DispatcherServlet 中有一个核心方法 doDispatch(),这个方法用来通过请求路径找到对应的处理器方法
然后调用处理器方法,处理器方法返回一个逻辑视图名称(可能也会直接返回一个ModelAndView对象)
,返回给DispatcherServlet

提醒:大家可以通过以下断点调试方式,采用一级一级返回,最终可以看到都会返回ModelAndView对象。

在这里插入图片描述

5. Spring MVC 获取 session 会话域对象的二种方式

在SpringMVC中使用session域共享数据,实现方式有多种,其中比较常见的两种方式:

  1. 使用原生Servlet API
  2. 使用SessionAttributes注解

5.1 第一种方式:使用原生Servlet API 获取到 session 会话域,同时获取到 session 会话域当中的信息

使用原生Servlet API ,就是将 HttpSession 作为方法的参数形式,Spring MVC 会自动获取到 Tomcat 服务器当中的 HttpSession 对象,赋值到这个方法的对应的 HttpSession 参数上。

创建:SessionScopeTestController 类

在这里插入图片描述


import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;



@Controller // 交给 Spring IOC 容器管理
public class SessionScopeTestController {


    @RequestMapping("/testSessionServletAPI")
    public String testServletAPI(HttpSession session) {
        // 处理核心业务...
        //将数据存储到 Session中
        session.setAttribute("testSessionScope","在Spring MVC 当中使用原生 Servlet API 完成 session 域数据共享");
        // 返回逻辑视图(这是一个转发的行为)
        return "ok";
    }
}

index 页面超链接的编写:
在这里插入图片描述

ok 页面获取 request 请求域的展示的编写

在这里插入图片描述




    
    OK


启动 Tomcat 服务器测试结果:
在这里插入图片描述

5.2 第二种方式:使用 @SessionAttributes 注解 获取到 session 会话域,同时获取到 session 会话域当中的信息

使用 @SessionAttributes 注解标注 Controller:

在这里插入图片描述

@SessionAttributes(value = {"x","y","testSessionScope"}) // 标注 x 和 y 都是存放到 session 域中,而不是 request域

**注意:@SessionAttributes 注解使用在Controller类上。标注了当 key是 x 或者 y 时,该(x 或 y)的数据将被存储到会话 session域当中中。而如果没有 SessionAttributes注解,默认存储到 request域中。 **
在这里插入图片描述


import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;


@SessionAttributes(value = {"x","y","testSessionScope"}) // 标注 x 和 y 都是存放到 session 域中,而不是 request域
@Controller // 交给 Spring IOC 容器管理
public class SessionScopeTestController {



    @RequestMapping(value = "/testSessionAttributes")
    public String testSessionAttributes(ModelMap modelMap) {
        // 处理业务
        // 将数据存储到 Session域当中
        modelMap.addAttribute("testSessionScope","在Spring MVC 当中使用@SessionAttributes 注解完成 session 域数据共享");
        modelMap.addAttribute("x","李华");
        modelMap.addAttribute("y","小红");
        return "ok";
    }
}

index 页面超链接的编写:

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试Session域对象

测试在Spring MVC 当中使用 @SessionAttributes 注解完成 session域数据共享

ok 页面获取 request 请求域的展示的编写:

在这里插入图片描述




    
    OK


启动 Tomcat 服务器测试结果:

在这里插入图片描述

6. Spring MVC 获取 application 应用域对象的方式

在SpringMVC实现application域数据共享,最常见的方案就是直接使用Servlet API了:

这个 application 域使用较少,如果使用的话,一般是采用 ServletAPI的方式使用

创建:ApplicationScopeTestController 类

将 HttpServletRequest 作为参数,定义到方法上,Spring MVC 框架会自动从 Tomcat 服务器当中获取到这个 HttpServletRequest 对象的值,然后,传递给这个方法的 HttpServletRequest 参数值上,完成赋值。
在这里插入图片描述

package com.rainbowsea.springmvc.controller;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller // 交给 Spring IOC 容器管理
public class ApplicationScopeTestController {


    @RequestMapping("/testApplicationScope")
    public String testApplicationScope(HttpServletRequest request) {
        // 将数据存储到application域当中
        // 获取application对象,其实就是获取 ServletContext对象
        // 怎么获取 ServletContext对象/通过 request,通过 session都可以用
        ServletContext application = request.getServletContext();
        application.setAttribute("testApplicationScope", "在Spring MVC 中使用 Servlet API中实现application域共享");
        return "ok";
    }
}

index 页面超链接的编写:

在这里插入图片描述




    
    测试三个对象


测试三个域对象


测试Application应用域对象

测试在Spring MVC 当中使用 Servlet API 实现application域数据共享

ok 页面获取 request 请求域的展示的编写

在这里插入图片描述

启动 Tomcat 服务器测试结果:
在这里插入图片描述

7. 总结:

  1. 三个域:request 请求域,session 会话域,application 应用域

  2. 三者域的使用,从最小范围的域,来判断使用,可以用范围更小的域,就用范围更小的域来解决问题,传数据资源。如果域的范围不够,就一点的扩大。

  3. 在SpringMVC中,在request域中共享数据有以下五种方式:

    1. 使用原生Servlet API方式。
    2. 使用Model接口。
    3. 使用Map接口。
    4. 使用ModelMap类。
    5. 使用ModelAndView类。
  4. 在SpringMVC中使用session域共享数据,实现方式有多种,其中比较常见的两种方式:

    1. 使用原生Servlet API
    2. 使用SessionAttributes注解
  5. Spring MVC 获取 application 应用域对象的方式

8. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认