SpringMVC 框架详解

2023-11-14

1.什么是 Spring MVC?

官方对于 Spring MVC 的描述是这样的:

Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从一开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来自其源模块的名称(Spring-webmvc),但它通常被称为“SpringMVC”。

从上述定义我们可以得出两个关键信息:

  1. Spring MVC 是⼀个 Web 框架。
  2. Spring MVC 是基于 Servlet API 构建的。

然而要真正的理解什么是 Spring MVC?我们首先要搞清楚什么是 MVC?

1.1 什么是MVC

MVCModel View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。

  • Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
  • View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
  • Controller(控制器)是应用程序中处理⽤户交互的部分。通常控制器负责从视图读取数据,控制用户输⼊,并向模型发送数据。

1.2 MVC 和 Spring MVC 的关系

MVC 是一种思想,而 Spring MVC 是对 MVC 思想的具体实现。总的来说,Spring MVC 是一个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。

2.第一个SpringMVC程序

(1) 创建SpringMVC项目
Spring MVC 可以基于 Spring Boot 创建,也就是创建一个 Spring Boot 项目,勾选上 Spring Web 模块即可,详情请参考:SpringBoot项目创建及运行

(2) 创建一个 UserController 类,实现用户到 Spring 程序的互联互通,具体实现代码如下:

@Controller
@ResponseBody
@RequestMapping("/user")    // 路由映射
public class UserController {

    @RequestMapping("/hi")
    public String sayHi() {
        return "<h1>hi, SpringMVC<h1>";
    }
}

(3) 这样实现之后,启动项目,当访问地址:http://localhost:8080/user/hi 时就能打印“hi,SpringMVC”的信息了。

2.1 @RequestMapping 注解

@RequestMapping 是 Spring Web 应用程序中最常被用到的注解之⼀,它是用来注册接口的路由映射的。

路由映射:所谓的路由映射指的是,当用户访问⼀个 url 时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射。

2.2 @ResponseBody 注解

@ResponseBody 返回的值如果是字符会转换成 text/html,如果返回的是对象会转换成 application/json 返回给前端。
@ResponseBody 可以用来修饰方法或者是修饰类,修饰类表示类中的所有方法都会返回 html 或者 json,而不是视图

2.3 get 和 post

@RequestMapping 默认是 get 方式的请求,如果想接收POST请求,我们可以显示的指定 @RequestMapping 来接收 post

@RequestMapping(value = "/hi",method= RequestMethod.POST)

get 请求的 3 种写法:

// 写法1
@RequestMapping("/index") 
// 写法2
@RequestMapping(value = "/index",method = RequestMethod.GET) 
// 写法3
@GetMapping("/index")

post 请求的 2 种写法:

// 写法1
@RequestMapping(value = "/index",method = RequestMethod.POST) 
// 写法2
@PostMapping("/index")

3.获取参数

3.1 传递单个参数

在 Spring MVC 中可以直接用方法中的参数来实现传参,比如以下代码:

    @RequestMapping("/showname")
    public String showName(String name) {
        return "姓名:" + name;
    }

在 postman 中模拟传参:
在这里插入图片描述

3.2 传递对象

Spring MVC 可以自动实现参数对象的赋值,比如 Person 对象:
创建Person类:

@Data
public class Person {
    private int id;
    private String name;
    private String password;
}

传递对象代码实现:

    @RequestMapping("/person")
    public Object getPerson(Person person) {
        return person;
    }

通过url访问并传递参数:
在这里插入图片描述

3.3 表单参数传递/传递多个参数(非对象)

@RequestMapping("/login")
    public String login(String username, String password) {
        return "用户名:" + username + " 密码:" + password;
    }

通过url访问并传递参数:
在这里插入图片描述

3.4 后端参数重命名(后端参数映射)

某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不一致,比如前端传递了⼀个 time 给后端,而后端又是有 createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用 @RequestParam 来重命名前后端的参数值。

    @RequestMapping("/time")
    public String getTime(@RequestParam("time") String createtime) {
        return createtime;
    }

输入url传递参数:
在这里插入图片描述

3.5 设置参数非必传

拿上面的例子,不给time传参数:
在这里插入图片描述

就会报400,为什么会这样呢?
看下@RequestParam源码:
在这里插入图片描述
发现默认情况下参数是必传的,如果不传参数则会报错,我们可以通过设置 @RequestParam 中的 required=false 来设置参数为非必传,具体实现如下:

    @RequestMapping("/time2")
    public String getTime2(@RequestParam(value = "time", required = false) String createtime) {
        return createtime;
    }

通过url访问并不设置参数:
在这里插入图片描述

发现并没有报错,说明设置是有效的。

3.6 接收JSON对象

    @RequestMapping(value = "getjson", method = RequestMethod.POST)
    public Object getJson(@RequestBody Person person) {
        return person;
    }

通过postman传递一个json字符串:
在这里插入图片描述

成功接收。

3.7 获取URL中参数

    @RequestMapping("/geturl/{name}/{password}")
    public String getUrl(@PathVariable String name, @PathVariable String password) {
        return "名称:" + name + " 密码:" + password;
    }

通过url获取参数:
在这里插入图片描述

3.8 上传文件

创建 application.yml 配置文件,配置文件保存路径:

# 图片保存路径
myfile:
  path: E:/Data/

后端实现代码:

    @Value("${myfile.path}")
    private String filePath;    // 从配置文件中获取文件上传路径

    @RequestMapping("/upfile")
    public boolean upFile(String name, @RequestPart("myfile") MultipartFile file) {
        boolean result = false;
        try {
            // 得到原文件的名称和后缀
            String fileType = file.getOriginalFilename();
            if (fileType != null) {
                fileType = fileType.substring(fileType.lastIndexOf("."));
            }
            // 文件保存的名称
            String fileName = UUID.randomUUID().toString() + fileType;
            file.transferTo(new File(filePath + fileName));
            result = true;
            log.info(name + ":图片上传成功!");
        } catch (IOException e) {
            log.error(name + ":图片上传失败!");
        }
        return result;
    }

注意:这里用到了log,要给类上加上@Slf4j注解。

用postman上传文件:
在这里插入图片描述
文件成功保存到路径下:
在这里插入图片描述
在这里插入图片描述

控制台也打印成功日志:
在这里插入图片描述

3.9 获取Cookie/Session/header

获取 Cookie 方法1:

    @RequestMapping("/getck")
    public void getCookie(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        Arrays.stream(cookies).forEach(cookie -> {
            log.info(cookie.getName() + ":" + cookie.getValue());
        });
    }

方法2:

    @RequestMapping("/getck2")
    public String getCookie2(@CookieValue("bite") String bite) {
        return bite;
    }

获取Header:

    @RequestMapping("/header")
    public String getHeader(@RequestHeader("User-Agent") String userAgent) {
        return userAgent;
    }

获取session方法1:

    @RequestMapping("/getsess")
    public String getSession(HttpServletRequest request) {
        String result = "";
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("SESSION_KEY") != null) {
            result = (String) session.getAttribute("SESSION_KEY");
        }
        return result;
    }

方法2:

    @RequestMapping("/getsess2")
    public String getSession2(@SessionAttribute(required = false, name = "SESSION_KEY") String data) {
        return data;
    }

设置session:

    @RequestMapping("/setsess")
    public boolean setSession(HttpServletRequest request) {
        boolean result = false;
        try {
            HttpSession session = request.getSession(true);
            session.setAttribute("SESSION_KEY", "java");
            result = true;
        } catch (Exception e) {
            log.error("出现异常:" + e.getMessage());
        }
        return result;
    }

4.返回数据

4.1 返回静态页面

创建前端页面 index.html:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1 style="color: blue">hello, SpringMVC</h1>
</body>
</html>

创建控制器 Controller:

@Controller
public class IndexController {
    @RequestMapping("/index")
    public Object index() {
        return "/index.html";
    }
}

在浏览器输入url:
在这里插入图片描述

4.2 返回JSON对象

    @RequestMapping("/map")
    @ResponseBody
    public HashMap<String, String> mapJson() {
        HashMap<String, String> map = new HashMap<>();
        map.put("Java", "Java Value");
        map.put("MySQL", "MySQL Value");
        map.put("Redis", "Redis Value");
        return map;
    }

在这里插入图片描述

4.3 请求转发或请求重定向

return 不但可以返回一个视图,还可以实现跳转,跳转的方式有两种:

  • forward:请求转发;
  • redirect:请求重定向。

请求转发和重定向的使用对比:

// 请求重定向
@RequestMapping("/index1")
public String index(){
return "redirect:/index.html"; 
}
// 请求转发
@RequestMapping("/index2") 
public String index2(){
return "forward:/index.html"; 
}

举例说明 forward 和 redirect
例如,你告诉你男/女朋友你想吃雪糕,如果他/她说好,我给你买,这就是forward请求转发,如果他/她说自己买去,那么就是redirect重定向

forward 和 redirect 具体区别如下:

  • 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
  • 请求重定向地址发⽣变化,请求转发地址不发生变化。
  • 请求重定向与直接访问新地址效果⼀致,不存在原来的外部资源不能访问;请求转发服务器端转发,有可能造成原外部资源不能访问。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringMVC 框架详解 的相关文章

  • log4j2 SMTP Appender:如何包含另一个级别的先前消息?

    我正在使用 log4j2 beta9 并且有以下配置 其中一部分
  • 如何通过双击图标来执行JAVA程序?

    我写了一个java程序 现在我想在没有 IDE Eclipse 等的情况下打开我的控制台 java 应用程序 只需双击桌面上的可执行版本即可 我已将 java 项目导出为 Runnable JAR 文件 但无法打开 当我尝试使用cmd打开应
  • Spring boot - 嵌入式 Tomcat - 连接器定制器 - 无法添加 parseBodyMethods 属性

    最初的问题是当我使用 DELETE 方法发送http请求时 正文部分无法发送到服务器 经过谷歌搜索后 我发现本文 https stackoverflow com questions 41205062 requestbody not acce
  • 请放心,如何在 POST 请求后从响应正文中提取生成的令牌并将其设置到标头

    执行任何请求 我需要执行身份验证POST请求正文 username somename password somepass 标头Content Type application json这给了我一个带有生成令牌的响应 我需要将其粘贴为第二个标
  • 转换为 JSON 后保留 XMLGregorianCalendar 日期格式 - Jackson Lib

    我有一个对象 它有 2 个 XMLGregorianCalendar 对象 一个用于日期 另一个用于时间 我使用 Jackson 对象映射器将日期转换为 JSON 格式 转换前的日期为2014年2月10日 时间为11 15 00 转换为 J
  • Spring Boot 删除 Whitelabel 错误页面

    我正在尝试删除白色标签错误页面 所以我所做的是为 error 创建了一个控制器映射 RestController public class IndexController RequestMapping value error public
  • 使用 Windows 锁定屏幕后删除 Kerberos 缓存票证

    无论如何 有没有办法阻止 Kerberos 缓存的票证在 Windows 进入锁定屏幕后被删除 首次登录 Windows 时 klist exe 显示 2 个缓存票证 但是 发生 Windows 锁屏事件后 klist exe 显示 0 个
  • 有没有办法在@Service上使用@ControllerAdvice

    我有一个项目需求 但我没有任何需求 Controller or RestController但我需要为我的服务层提供一个全局异常处理程序 所以我需要配置 ControllerAdvice on Service 请告诉我是否还有其他方法可以做
  • Java setLocation() 事故

    我正处于创建一个程序来操作员工 客户系统的开始阶段 现在我刚刚创建了登录 GUI 但我遇到了一些问题 setLocation 方法 我将其设置为 250 250 但这使我的 GUI 高度变得非常疯狂 如果有人能够解决这个问题 我的代码如下
  • 如何从网上获取源代码?

    我正在尝试从 Web 获取 HTML 源代码 我尝试这样做 u new URL url URLConnection con u openConnection con setRequestProperty User Agent Mozilla
  • 从两个数组中查找公共文件

    我正在尝试从两个数组中查找通用名称文件 我已将两个不同文件夹的文件名保存在两个不同的数组中 现在我正在创建一个通用文件数组 其中包含具有通用名称的文件 filenames 1 包含文件夹 1 中文件名称的数组 filename2 包含文件夹
  • 在同一个容器但不同的耳朵中使用本地EJB

    我正在尝试在同一个 Glassfish 但不同的耳朵中使用本地 EJB 但是Glassfish找不到本地EJB或者无法消费 我读到了这个 根据 JavaEE 教程 Local bean 的客户端 必须在与其访问的企业 bean 相同的 JV
  • 在 Tomcat 中触发内部 ServletRequest

    我正在使用 Quartz 来安排 Web 应用程序的后台任务 其中一些任务只是针对同一 Web 应用程序发出请求 我想避免依赖于任何类型的网络设置 例如 如果从数据中心内发出带有我自己域名的请求 则可能无法正确路由 是否有一个 Java A
  • 使用 testcontainer 作为 Dockerfile 的一部分运行测试

    我的 dockerfile 看起来像这样 FROM maven 3 jdk 11 slim COPY pom xml COPY src src RUN mvn clean install 这意味着构建的一部分是单元测试的执行 一些单元测试使
  • 从 Apache Kafka 中的主题删除消息

    所以我是 Apache Kafka 的新手 我正在尝试创建一个简单的应用程序 以便我可以更好地理解 API 我知道这个问题在这里被问了很多 但是如何清除存储在主题上的消息 记录 我看到的大多数答案都说要更改消息保留时间或删除并重新创建主题
  • 我可以使用本机系统窗口作为父窗口使 JDialog 成为模式吗?

    我有一个 JDialog 窗口 我需要使其成为模态窗口 但父窗口不是 Java 窗口 而是本机 Windows 操作系统窗口 是否可以 不 你不能 您甚至无法不仅引用本机窗口 甚至无法引用运行在其他 JVM 中的 java 应用程序创建的窗
  • java中的Anagram算法

    我想做字谜算法但是 这段代码不起作用 我的错在哪里 例如 des 和 sed 是字谜 但输出不是字谜 同时我必须使用字符串方法 不是数组 public static boolean isAnagram String s1 String s2
  • Spring MVC 和复选框

    我正在使用 Spring MVC 3 0 并且不能完全看到这个问题的所有部分 我的控制器将生成一个域对象列表 假设有一个简单的 User 对象 具有firstName lastName age 和role 属性 我想在表中输出该用户列表 每
  • java银行程序帐户ID不上去?

    每次创建银行帐户时 帐户 ID 都应增加 1 但每次我尝试提取 Id 时 我只会得到帐户 ID 为 0 任何建议 因为我完全按照我学习的书中的方式进行操作而且它仍然没有更新 帐户构造函数 public class BankAccount p
  • 寻找基于循环固定大小数组的双端队列

    我正在寻找一个Deque其具有以下特点 它有固定的大小 如果我在头 尾添加元素 则另一端的元素会丢失 它是基于数组的 所以我可以在恒定时间内访问随机元素 我可以在前面或末尾添加元素 双端队列 我检查了Deque的实施JCF但我没有找到任何合

随机推荐

  • GLSL #define GL_SPIRV 100说明

    GLSL define GL SPIRV 100说明 版权 hankern https blog csdn net hankern article details 90690297 Standard Portable Intermediat
  • 【学习笔记】POST和GET的区别

    吃水不忘挖井人系列之 https mp weixin qq com s N2GStE2ksWUO yzIETTcQQ 在开撸之前吗 让我们先看一下标准答案长什么样子 w3school GET 对比 POST 标准答案很美好 但是在面试的时候
  • Chrome 快捷键大全

    从2013年开始使用 Chrome 浏览器 简洁好用 以前是用来专门科学上网 后来工作发现 Chrome 是开发必备 今天整理了一下Chrome的快捷键 有些挺常用 熟悉掌握快捷键 甚至不要鼠标就可以装逼了 标签和窗口 同个窗口新建标签 C
  • 【Linux】软件安装&卸载

    目录 1 notepad plus plus 2 notepadqq 3 pycharm 4 Anaconda 5 vscode 6 android ndk 7 搜狗输入法 8 卸载vmware 9 GIMP 10 git 11 llvm
  • JAVA 写Excel附件 每天定时发送邮件

    JAVA 写Excel附件 每天定时发送邮件 http hi baidu com star850323 blog item 63c5750f520e05ec37d1228d html http hi baidu com star850323
  • HBuilderX 最新安装使用教程,附详细图解,持续更新

    HBuilderX 安装使用教程 HBuilderX是HBuilder的升级版 它是是DCloud 数字天堂 推出为前端开发者服务的通用IDE 或者称为编辑器 HBuilderX的功能从下图可以直观的了解个大概 官网地址 https ask
  • Java基础总结之各个模块重要知识点

    一 对象模块 一 初始化 1 对this super 构造函数 构造代码块 静态代码块总结 this 代表当前对象 也就是所在函数所属对象的引用 this对象后面加 调用的是对象的成员变量和方法 this say this对象后面加 调用的
  • 毕业设计-基于机器视觉的甘蔗茎秆识别方法-OpenCV

    目录 前言 课题背景和意义 实现技术思路 一 总体思路 二 图像处理 三 甘蔗识别 四 结 语 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几
  • OpenCV中的图像处理

    颜色空间转换 1 基本读写操作 import cv2 import numpy as np img cv2 imread MyPic png cv2 IMREAD GRAYSCALE print img shape cv2 imwrite
  • winusb —— 不再为你的usb设备编写驱动

    blog csdn net lanmanck 曾几何时我们找工作还发现有个驱动工程师职位 月薪也不低 没接触过的人代码压根看不懂 今天可好了 如果不太追求差异化 不用驱动也能让系统与USB设备通信了 Linux就不说了 libusb很好用
  • nginx服务器启动、停止、重启

    启动nginx nginx c path to nginx conf 关闭nginx nginx s stop 快速停止nginx quit 完整有序的停止nginx 重启nginx nginx s reload 修改配置后重新加载生效 n
  • org.springframework.validation.BindException: org.springframework.

    错误信息 org springframework validation BindException org springframework validation BeanPropertyBindingResult 2 errors Fiel
  • Vue实现在页面上添加返回顶部按钮(按钮固定在页面右下角)

    从网站上下载按钮图片 我在图精灵上下载图片到项目src文件夹下的assets文件夹 并命名为topButton png 可以用本地的图片编辑软件 如画图 将按钮图片设置为像素50 50 在App vue文件夹下引入图片 为click事件设置
  • Linux内存宏,linux内核驱动宏定义

    宏符号linux内核中绝大多数初始化函数和变量都利用了各式各样的宏符号 形如 static int init pci porc init void static char version devinitdata drv name modul
  • Eclipse ADT中的logcat不显示解决方法

    1 在Eclipse界面中找到DDMS 然后找到device选项卡 在这个选项卡中选择reset adb 如果不行尝试方法2 2 不用关闭eclipse和模拟器 在Android SDK的tools目录下有个 ddms bat 批处理文件
  • index_join:

    index join index join顾名思义是对index进行关联 oracle通过hash index join的方式实现了避免对表的访问 所有的数据都从索引中直接获得 它不受查询条件影响 可以是唯一索引 也可以是多列索引 SELE
  • [Unity2D/3D]Particle System粒子系统/以实现烟雾效果为例

    Unity3D Particle System粒子系统 首先看一下效果 1 创建一个Particle System 右键Effects gt Particle System Pause暂停播放粒子效果 Restart重新播放粒子系统 Sto
  • Direct3D轮回:游戏特效之全屏泛光(Bloom)

    https www cnblogs com kenkao archive 2011 08 25 2153752 html Bloom 又称 全屏泛光 是大名鼎鼎的虚幻3游戏引擎中最通用的后期特效技术 Bloom特效的实现主要依赖于PostP
  • 用实例给新手讲解RSA加密算法

    http www cfca com cn zhishi wz 012 htm 用实例给新手讲解RSA加密算法 图为 RSA公开密钥算法的发明人 从左到右Ron Rivest Adi Shamir Leonard Adleman 照片摄于19
  • SpringMVC 框架详解

    目录 1 什么是 Spring MVC 1 1 什么是MVC 1 2 MVC 和 Spring MVC 的关系 2 第一个SpringMVC程序 2 1 RequestMapping 注解 2 2 ResponseBody 注解 2 3 g