Spring Web MVC基础理论和使用

news2025/5/12 0:04:45

目录

什么是MVC

什么是SpringMVC

SpringMVC基础使用

建立连接

@RequestMapping介绍

请求

传递参数

传递对象

参数重命名

传递数组

传递JSON数据

获取URL中参数

上传文件

获取Cookie/Session

获取Header

响应

返回静态页面

 @RestController和@Controller的区别

返回数据@ResponseBody

设置状态码


什么是MVC

MVC是一种架构模式,全称是Model(模型) View(视图) Controller(控制) 

  • Model(模型):是应用程序的主体,用来存储数据和处理用户请求的业务逻辑。
  • View(视图):用来和浏览器交互的部分,展示模型中的数据,比如jsp和html
  • Controller(控制) 用来接收视图发来的请求,将数据交给Model处理,并且将处理后的结果返回给视图

相当于用户通过浏览器输入数据,由View发送给Controller,在有Controller分发给对应Model板块对数据进行处理,之后,Model再把处理完的数据交给Controller,Controller可能对数据进行进一步封装,最后交给View,由View最后返回给用户展示。

什么是SpringMVC

SpringMVC和MVC并不是一个东西,MVC是一种架构思想,而SpringMVC则是实现这种思想的web框架,所以SpringMVC就是一个实现了MVC的Web框架

就好像是食物和饺子的关系,食物是能被人类使用的东西的统称,而饺子则是食物的具体实现,食物不光有饺子,还有其他实现,比如包子,汤圆,西湖醋鱼等

关于官方的定义是这样的

SpringWebMVC是基于ServletAPI构建的原始Web框架,从⼀开始就包含在Spring框架中。它的
正式名称“SpringWebMVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring
MVC".

从这句话可以知道SpringMVC是Spring Framework的一部分,底层则是servlet

SpringMVC基础使用

我们在之前创建SpringBoot项目时,勾选的SpringWeb依赖其实就是SpringMVC

这时就有了一个问题SpringWeb和SpringMVC到底是什么关系

SpringBoot是一个自动化配置的工具,SpringMVC是一个Web框架

SpringBoot为SpringMVC提供了便捷的开发和部署方式,SpringMVC相当于是Spring框架的一部分,用于开发Web程序,而SpringBoot是基于Spring的框架,为了快速搭建Spring应用,SpringBoot只是实现SpringMVC的其中⼀种⽅式⽽已.所以这三个的关系可以理解为SpringBoot > Spring > SpringMVC.

Spring在实现MVC架构时做了一些调整,用户通过浏览器直接把数据发给Controller,之后由Model处理再返回给Controller,最后再返回通过View显示给用户。

建立连接

我们首先现在浏览器上输出一个hello world,在输出前我们要先建立和浏览器的连接,让浏览器可以找到我们运行的SpringMVC项目。

在SpringMVC里使用@RequestMapping来实现浏览器的URL路由映射,具体代码如下

@RestController
@RequestMapping("/test")
public class UserController {
    @RequestMapping("hello")
    public String test(){
        return "hello world";
    }
}

结果

@RequestMapping介绍

@RequestMapping里传的字符串就是浏览器搜索的url路径,@RequestMapping既可以用来修饰类也可以用来修饰方法,当当前类里即用@RequestMapping修饰了类又修饰了类里的方法,那么我们想要让浏览器访问该类里的方法时所使用的url路径就是(类修饰名+方法修饰名)。就和刚刚的例子一样,而且是类修饰在前,方法修饰在后。

@RequestMapping的URL路径最前⾯加不加/ (斜杠)都可以,Spring程序启动时,会进行判段,如果前面没有加/,Spring也会帮你拼接一个,不过一般也不加/

@RequestMapping的url路径也可以是多层的,但是最终访问路径依然是类路径+方法路径

@RestController
@RequestMapping("/test/test2")
public class UserController {
    @RequestMapping("hello1/hello2")
    public String test(){
        return "hello world";
    }
}

也可以只写方法路径,浏览器也可以访问到(但是不建议这样写)

@RestController
//@RequestMapping("/test/test2")
public class UserController {
    @RequestMapping("hello1/hello2")
    public String test(){
        return "hello world";
    }
}

@RequestMapping既可以接收所以类型的请求包括get/post,如果想要只接收某一种类型的请求可以使用对应的@GetMapping或者@PostMappping,使用方法和@RequestMapping一样,但是只能接收对应类型的请求,或者指定mothod方法

@RequestMapping(value = "/test/test2",method = RequestMethod.GET)

我们也可以点进这个注解看看

 

可以看到mothod返回的是一个枚举类型,而枚举的就是使用请求类型,同时如果我们想要设置两种方法就可以传入两个枚举类型

@RequestMapping(value = "/test/test2",method = {RequestMethod.GET,RequestMethod.POST})

请求

刚刚我们的例子里是直接把数据发送给浏览器,并没有从浏览器接收数据然后加工返回,在项目中发送来的请求很可能带有数据,那么我们就需要用对应的参数来接收。

在Servlet中我们通过request.getParameter(name)获取请求参数,当参数过多时代码会变得十分的臃肿,而SpringMVC则是通过参数注入的方式用于获取请求数据,即将请求参数直接封装到方法的参数当中。如果有了解过Servlet就会觉得这种方式对于开发者的开发来说十分的友好。

传递参数

@RestController
@RequestMapping(value = "test")
public class UserController {
    @RequestMapping("hello")
    public String test(String str){
        return str;
    }
}

成功返回

我们的路径127.0.0.1:8080/test/hello?str=hello,看以看到这里的参数名和我们方法的参数名是一样的,如果不一致则无法收到。

使⽤基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误类型不匹配时,会报400错误,反之包装类则不用。

@RestController
@RequestMapping("test")
public class UserController {
    @RequestMapping("hello")
    public String test(int num){
        return "num: " + num;
    }
}

 

当有多个参数时至于要在后面加上对应类型,切记名字一定要一样。

传递对象

处理传递基本数据类型外,SpringMVC还可以传递对象。SpringMVC可以实现自动给对象里的属性赋值,比如一个user对象里有一个name属性,浏览器只传了一个name=张三,那么SpringMVC就会从对象参数里的字段找和请求数据同名的字段,找到了就会直接赋值。

public class User {
    private String name;
    private String gender;
    private int age;
}
@RestController
@RequestMapping("test")
public class UserController {
    @RequestMapping("user")
    public String test(User user){
        return user.toString();
    }
}

看以看到我们只有name属性被赋值,而password因为没有找到有对应名字的字段所以无法赋值。

Spring会根据参数名称自动绑定到对象的各个属性上,如果某个属性未传递,则赋值为null(基本类型则赋值为默认初识值,比如int类型的属性,会被赋值为0)。

还可以接收关联对象

就是方法参数是一个对象,而这个对象里有一个属性也是一个对象


public class User {
    private String name;
    private String gender;
    private int age;
    private Phone phone;
}
public class Phone {
    private String type;
    private String color;
    private String phoneNum;
}
@RestController
@RequestMapping("test")
public class UserController {
    @RequestMapping("user")
    public String test(User user){
        return user.toString();
    }
}

 看以看到依然成功接收,规则也和之前一样,只不过有一个参数变成了对象

参数重命名

在之前传递参数的过程中都要求前端传递参数的参数名和我们的方法的参数名一致,但是如果不一致呢,或者说有没有不一致但是依然可以完成参数传递的方法呢?有的兄弟有的,只需要使用@RequestParam给参数重命名就行.

@RestController
@RequestMapping("test")
public class UserController {
    @RequestMapping("gender")
    public String test1(@RequestParam("sex") String gender){
        return "gender: " + gender;
    }
}

只需要@RequestParam里的参数的前端传来的参数一致就行,这样方法的参数就可以随意命名了。不过如果加了@RequestParam注解重命名,那么前端里的参数名就必须和@RequestParam里的一样,和方法里的参数名就没有关系了,换言之如果请求参数名只是和方法参数名和一样而和@RequestParam里的参数名不同,那么依然无法正确赋值

传递数组

SpringMVC依然可以自动绑定 

@RestController
@RequestMapping("test")
public class UserController {
    @RequestMapping("array")
    public String array(String[] array){
        return Arrays.toString(array);

    }

}

传递JSON数据

JSON:就是⼀种数据格式,有自己的格式和语法,使用文本表示⼀个对象或数组的信息,因此JSON本质是字符串,主要负责在不同的语言中数据传递和交换。

SpringMVC已经帮我们把JSON转换工具引入进来了,直接使用就行,如果脱离SpringMVC使用就需要引入依赖

<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-databind</artifactId>
 <version>2.13.5</version>
</dependency>

 使用提供的ObjectMapper对象来进行JSON字符串得转化

  • writeValueAsString():把对象转化为JSON字符串
  • readValue():把JSON转化为对象

我们得服务器接收JSON对象,需要使用 @RequestBody 注解 

@RequestMapping("json")
    public Object json(@RequestBody User user){
        return user.toString();
    }

 使用PostMan来发送请求

 

成功返回数据

然后如果我们去掉@RequestBody呢

可以看到依然可以成功返回但是未能成功赋值

如果后端想要返回一个json数据也可以直接以HashMap的方式返回

获取URL中参数

使用@PathVariable注解就可以拿到url中的参数,默认传递参数写在url上,SpringMVC就可以获取

@RequestMapping("pathVal/{gender}/{newName}")
    public String pathVal(@PathVariable String gender,@PathVariable("newName") String name){
        return "gender: " + gender + "name: " + name;

    }

 

@PathVariable也具有重命名得功能,url路径里的参数需要和{}里的名字对应,同时也要和方法名对应(如果@PathVariable重命名了的话则要和重命名得参数名对应)

上传文件

使用注解@RequestPart

@RequestMapping("file")
    public String getFile(@RequestPart("file") MultipartFile file) throws IOException {
        //获取文件名
        String fileName = file.getOriginalFilename();
        //上传文件到指定路径
        file.transferTo((new File("D:/" + file.getOriginalFilename())));
        return "文件名:" + fileName;
    }

 MultipartFile是Spring封装得一个用来处理文件得接口,可以通过这个接口对文件进行一系列操作

看以看到文件成功上传到本地文件夹

获取Cookie/Session

获取Cookie

@RequestMapping("/cookie")
    public String demo1(HttpServletResponse response, HttpServletRequest request){
        // 获取所有 cookie 信息
        Cookie[] cookies = request.getCookies();
        //打印Cookie信息
        StringBuilder builder = new StringBuilder();
        if (cookies!=null){
            for (Cookie ck:cookies) {
                builder.append(ck.getName()+":"+ck.getValue());
            }
        }
        return "Cookie信息:"+builder;

    }

结果 

 我们也可以直接使用@CookieValue注解来获取cookie

@RequestMapping("/getCookie")
    public String cookie(@CookieValue("name") String name) {
        return "name:" + name;
    }

 @CookieValue里的字符就对应这cookie里面的key

Session存储

@RequestMapping("/setSess")
    public String setsess(HttpServletRequest request) {
        // 获取Session对象 
        HttpSession session = request.getSession();
        if (session != null) {
            session.setAttribute("username", "java");
        }
        return "session 存储成功";
    }

通过 session.setAttribute来指定一个名称以键值对的方式绑定一个对象到session会话

HttpSession.getSession(),当参数为true时,当前如果不存在会话就会创建一个新的,如果参数为false,则当不存在会话时会返回null而不会创建新的会话(默认时true)

Session读取

@RequestMapping("/getSess")
    public String sess(HttpServletRequest request) {
        // 如果 session 不存在, 不会⾃动创建
        HttpSession session = request.getSession(false);
        String username = null;
        if (session != null && session.getAttribute("username") != null) {
            username = (String) session.getAttribute("username");
        }
        return "username:" + username;
    }

 

通过session.getAttribute方法来获取我们存储的session,只需要传入key,就可以返回之间存储的value值,不过这里返回的是一个Object对象,需要强转为我们需要的。

而且可以看到此时SessionID也存储在Cookie中。

通过@SessionAttribute注解获取session

@RequestMapping("/getSess2")
public String sess2(@SessionAttribute(value = "username",required = false) 
String username) {
 return "username:"+username;
}

 @SessionAttribute注解就相当于getAttribute,通过传入的值来返回对应的对象,required表示可以为空

通过SpringMVC内置对象获取session

@RequestMapping("/getSess3")
public String sess3(HttpSession session) {
       String username = (String)session.getAttribute("username");
       return "username:"+username;
}

使用方法依然和刚刚的getAttribute一样

获取Header

@RequestMapping("/header")
    public String header(HttpServletRequest request, HttpServletResponse response)
    {
        String name = request.getHeader("name");
        return "name" + ":"+ name;
    }

这里获取的就是http请求报头里的key-value,这里也可以直接使用@RequestHeader注解来获取,使用方法和getHeader一样这里就不演示了

响应

我们可以返回的响应结果并不只有我们处理的一些数据,还可以是静态页面,设置返回报头,状态码等信息。

返回静态页面

首先我们先创建一个html页面

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Index⻚⾯</title>
</head>

<body>
    <h1>Hello,Spring MVC,这是Index⻚⾯</h1>
</body>

</html>

后端代码

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

运行

可以看到好像并不是我们预期的结果,我们应该返回的是一个html页面,现在我们将@RestController注解变成@Controller注解

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

这时我们就得到了我们想要的结果,那为什么呢

 @RestController和@Controller的区别

我们刚刚有提到,SpringMVC可以返回视图但是随着前后端分离,View不在返回视图,而是返回显示视图所需要的数据,而@RestController 其实是返回的数据

我们点开​​​​@RestController的源码可以发现,在里面不加封装了@Controller还封装了@ResponseBody.

所以可以这样说@RestController =@Controller +@ResponseBody

@Controller :定义⼀个控制器,Spring框架启动时加载,把这个对象交给Spring管理.
@ResponseBody :定义返回的数据格式为非视图,返回⼀个text/html信息

所以

  • @RestController一般用来返回数据,这些数据报头中的Content-Type都是text/html格式的。
  • @Controller一般用来返回视图.这个视图一般是用前端的代码写好的文件(视图view).

返回数据@ResponseBody

 刚刚我们直到@ResponseBody是用来返回数据的,如果给刚刚的代码加上一个@ResponseBody就又会把"index.html"当作字符串展示出来。

@ResponseBody注解既可以作用在类上又可以作用在方法上,作用在方法上就只影响当前方法,作用在类上就影响类里的所有方法,同理因为@RestController注解封装了@ResponseBody注解所以也具有类似特征。

如果一个类里既要返回视图又要返回数据该怎么做?很简单,在类上添加@Controller注解,给要返回数据的方法添加@ResponseBod注解,可以认为@ResponseBody的优先级大于@Controller注解。

设置状态码

可以直接通过SpringMVC的内置对象HttpServletResponse提供的方法来进行设置

@RequestMapping("/setStatus")
    @ResponseBody
    public String setStatus(HttpServletResponse response) {
        response.setStatus(400);
        return "设置状态码成功";
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2372382.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

课程审核流程揭秘:确保内容合规与用户体验

业务流程 为什么课程审核通过才可以发布呢&#xff1f; 这样做为了防止课程信息有违规情况&#xff0c;课程信息不完善对网站用户体验也不好&#xff0c;课程审核不仅起到监督作用&#xff0c;也是 帮助教学机构规范使用平台的手段。 如果流程复杂用工作流 说明如下&#xff…

Mac电脑,idea突然文件都展示成了文本格式,导致ts,tsx文件都不能正常加载或提示异常,解决方案详细说明如下

有一天使用clean my mac软件清理电脑 突然发现idea出现了文件都以文本格式展示&#xff0c;如图所示 然后就卸载&#xff0c;计划重新安装&#xff0c;安装了好几个版本&#xff0c;并且setting->file types怎么设置都展示不对&#xff0c;考虑是否idea没卸载干净&#xff…

HarmonyOS开发-组件市场

1. HarmonyOS开发-组件市场 HarmonyOS NEXT开源组件市场是一个独立的插件&#xff0c;需通过DevEco Studio进行安装&#xff0c;可以点击下载&#xff0c;无需解压&#xff0c;直接通过zip进行安装&#xff0c;具体安装和使用方法可参考HarmonyOsNEXT组件市场使用说明。Harmony…

vison transformer vit 论文阅读

An Image is Worth 16x16 Words 20年的论文看成10年的哈斯我了 [2010.11929] 一张图像胜过 16x16 个单词&#xff1a;用于大规模图像识别的转换器 --- [2010.11929] An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 为什么transformer好训练&am…

物理服务器紧急救援:CentOS系统密码重置全流程实战指南

前言 在企业IT运维实践中&#xff0c;物理服务器密码丢失是典型的"低概率高风险"事件。某金融科技公司曾因核心服务器密码遗失导致业务中断36小时&#xff0c;直接损失超过800万元。这起真实案例揭示了系统密码管理的关键性——当承载重要业务的物理服务器遭遇密码丢…

Linux系统下使用Kafka和Zookeeper

Apache Kafka 是一个分布式流处理平台,最初由 LinkedIn 开发,后来成为 Apache 软件基金会的顶级项目。它具有高吞吐量、可扩展性、持久性、容错性等特点,主要用于处理实时数据流。 Linux系统下使用Kafka 1.安装 Java Kafka 和 Zookeeper 都是基于 Java 开发的,所以需要先…

Unity按钮事件冒泡

今天unity写程序时&#xff0c;我做了一个透明按钮&#xff0c;没图片&#xff0c;只绑了点击事件&#xff0c;把子对象文字组件也删了&#xff0c;空留一个透明按钮&#xff0c;此时运行时点击按钮是没有反应的&#xff0c;网上的教程说必须指定target graphic&#xff08;目标…

指令图像编辑模型:ICEdit-MoE-LoRA

ICEdit-MoE-LoRA 一、研究背景与目标 In-Context Edit 是一种新颖的基于指令的图像编辑方法&#xff0c;旨在实现与现有最佳方法相当甚至更优的编辑效果。传统图像编辑技术在处理复杂指令时存在一定局限性&#xff0c;尤其是在多轮编辑任务中&#xff0c;结果的准确性和连贯性…

捌拾叁- 量子傅里叶变换

1. 前言 最近公司地震&#xff0c;现在稍微有点时间继续学习。 看了几个算法&#xff0c;都说是基于 量子傅里叶变换 &#xff0c;好&#xff0c;就是他了 Quantum Fourier。 2. 傅里叶变换 大学是学通信的&#xff0c;对于傅里叶变换还是有所理解的。其实就是基于一个 时域…

2.在Openharmony写hello world

原文链接&#xff1a;https://kashima19960.github.io/2025/03/21/openharmony/2.在Openharmony写hello%20world/ 前言 Openharmony 的第一个官方例程的是教你在Hi3861上编写hello world程序&#xff0c;这个例程相当简单编写 Hello World”程序&#xff0c;而且步骤也很省略&…

STM32外设-串口UART

STM32外设-串口UART 一&#xff0c;串口简介二&#xff0c;串口基础概念1&#xff0c;什么是同步和异步/UART与USART对比2&#xff0c;串行与并行3&#xff0c;波特率 (Baud Rate)4&#xff0c;数据帧 (Data Frame)5&#xff0c;TX 和 RX 三&#xff0c;硬件连接1&#xff0c;u…

MCU存储系统架构解析

今天和大家分享一下MCU存储器层次结构的设计思路。这种分层存储架构通过整合不同特性的存储单元&#xff0c;能够很好地平衡性能与成本需求。 首先是寄存器层&#xff0c;它直接集成在CPU内核里&#xff0c;速度最快&#xff08;纳秒级&#xff09;&#xff0c;但容量比较小&a…

Linux——MySQL基础

基础知识 连接服务器 mysql -h 127.0.0.1 -P 3306 -u root -p -h 指明登录部署了myqsl服务的主机 -P 指明访问的端口号 -u 指明用户 -p 指明登录密码&#xff08;可以不填写&#xff09; 什么是数据库 首先&#xff0c;数据库是分为服务端和客户端的&#xff1a; mysql是客户…

OpenGl实战笔记(2)基于qt5.15.2+mingw64+opengl实现纹理贴图

一、作用原理 1、作用&#xff1a;将一张图片&#xff08;纹理&#xff09;映射到几何体表面&#xff0c;提升视觉真实感&#xff0c;不增加几何复杂度。 2、原理&#xff1a;加载图片为纹理 → 上传到 GPU&#xff1b;为顶点设置纹理坐标&#xff08;如 0~1 范围&#xff09;&…

【计算机视觉】OpenCV实战项目: opencv-text-deskew:实时文本图像校正

opencv-text-deskew&#xff1a;基于OpenCV的实时文本图像校正 一、项目概述与技术背景1.1 核心功能与创新点1.2 技术指标对比1.3 技术演进路线 二、环境配置与算法原理2.1 硬件要求2.2 软件部署2.3 核心算法流程 三、核心算法解析3.1 文本区域定位3.2 角度检测优化3.3 仿射变换…

Java 23种设计模式 - 结构型模式7种

Java 23种设计模式 - 结构型模式7种 1 适配器模式 适配器模式把一个类的接口变换成客户端所期待的另一种接口&#xff0c;从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 优点 将目标类和适配者类解耦增加了类的透明性和复用性&#xff0c;将具体的实现封…

数据库(MySQL)基础

一、登录数据库 在linux系统中登录数据库的指令 mysql -h 127.48.0.236 -P 3306 -u root -p -h&#xff1a;填写IP地址&#xff0c;指明要连接的主机。如果不加该字段表示本地主机-P&#xff1a;填写端口号&#xff0c;指明进程。 如果不加该字段会使用默认的端口号。-u&…

Vue 2.0 详解全教程(含 Axios 封装 + 路由守卫 + 实战进阶)

目录 一、Vue 2.0 简介1.1 什么是 Vue&#xff1f;1.2 Vue 2.x 的主要特性 二、快速上手2.1 引入 Vue2.2 创建第一个 Vue 实例 三、核心概念详解3.1 模板语法3.2 数据绑定3.3 事件绑定3.4 计算属性 & 侦听器 四、组件系统4.1 定义全局组件4.2 单文件组件&#xff08;*.vue …

依赖关系-根据依赖关系求候选码

关系模式R&#xff08;U, F&#xff09;, U{}&#xff0c;F是R的函数依赖集&#xff0c;可以将属性分为4类&#xff1a; L: 仅出现在依赖集F左侧的属性 R: 仅出现在依赖集F右侧的属性 LR: 在依赖集F左右侧都出现的属性 NLR: 在依赖集F左右侧都未出现的属性 结论1: 若X是L类…

uniapp-商城-47-后台 分类数据的生成(通过数据)

在第46章节中&#xff0c;我们为后台数据创建了分类的数据表结构schema&#xff0c;使得可以通过后台添加数据并保存&#xff0c;同时使用云函数进行数据库数据的读取。文章详细介绍了如何通过前端代码实现分类管理功能&#xff0c;包括获取数据、添加、更新和删除分类。主要代…