【Spring MVC】Spring MVC程序开发教程:常见的注解及使用方式详情

news2024/11/19 1:36:27

前言

 Spring MVC是一种常用的Web框架,它可以帮助开发人员快速构建可扩展的Web应用程序。为了提供更好的开发体验和更高的代码效率,Spring MVC提供了各种注解。这些注解可以用于控制器、请求参数、响应类型、表单数据验证、异常处理等方面。在本文中,我们将介绍Spring MVC中常用的注解及使用方式。了解这些注解的作用,可以帮助我们更好地理解Spring MVC框架的工作原理,进而提高我们的开发效率。
表情包


文章目录

  • 前言
  • 1 Spring MVC 简介
  • 2 Spring MVC 创建与连接
    • 2.1 创建一个 Spring MVC 项目
    • 2.2 @RequestMapping 注解
      • 2.2.1 @RequestMapping 基本使用
      • 2.2.2 GET 请求 还是 POST 请求?
      • 2.2.3 @GetMapping 与 @PostMapping
  • 3 获取参数
    • 3.1 传递单个参数/多个参数
    • 3.2 传递对象
    • 3.3 后端参数重命名(@RequestParam 参数映射)
    • 3.4 @RequestParam 参数必传设置
    • 3.5 @RequestBody 接收JSON对象
    • 3.6 @PathVariable 获取URL中参数
    • 3.7 @RequestPart 上传⽂件
    • 3.8 获取Cookie/Session/header
  • 4 返回数据
    • 4.1 返回静态页面
    • 4.2 返回 text/html
    • 4.3 返回 JSON 对象
    • 4.4 请求重定向与请求转发
    • 4.5 组合注解:@RestController
  • 写在最后


1 Spring MVC 简介

什么是 MVC?
MVC是一种软件架构模式,它分为三个部分:模型(Model)、视图(View)和控制器(Controller)。它的主要思想是将应用程序分成三个主要的部分:模型(数据和业务逻辑)、视图(用户界面)和控制器(请求处理器),以实现分离关注点和松散耦合。通过这种分层架构,可以更好地维护和扩展应用程序,并且使应用程序更易于测试和设计。
MVC设计模式

Spring MVC 又是什么?
Spring MVC是一个基于Java的Web框架,用于构建Web应用程序。它是Spring框架的一部分,具有灵活性、可扩展性和强大的可配置性。Spring MVC通过使用MVC(模型-视图-控制器)设计模式来分离应用程序的不同层。
模型层代表数据或业务逻辑,视图层代表UI元素,控制器层充当这两个层之间的中介。这种分离允许更好的模块化和易于维护的代码。Spring MVC还提供了丰富的特性,如表单处理、文件上传、安全性、国际化和验证,可以方便地集成到Web应用程序中。总的来说:

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

SpringMVC
如何学 Spring MVC?
对于 Spring MVC 来说,掌握了以下 3 个功能就相当于掌握了 Spring MVC。

  • 连接的功能: 将⽤户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调⽤到我们的
    Spring 程序。
  • 获取参数的功能: ⽤户访问的时候会带⼀些参数,在程序中要想办法获取到参数。
  • 输出数据的功能: 执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤户。

2 Spring MVC 创建与连接

2.1 创建一个 Spring MVC 项目

Spring MVC项目的创建方式不唯一,这里使用基于Spring Boot的方式快速搭建 Spring MVC环境。也就是在创建Spring Boot项目的时候,勾选上Spring Web模块。
创建 Spring MVC 项目

2.2 @RequestMapping 注解

@RequestMapping 注解是 Spring MVC 框架中最常用的注解之一,它是⽤来注册接⼝的路由映射的。

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

它可以用于类级别和方法级别上。在类级别上,可以设置一个基础 URL 映射,以便在方法级别上定义特定的请求路径。在方法级别上,可以定义处理请求的具体行为和方法参数等。

@RequestMapping 注解有多种参数设置,例如:

  • value: 指定该方法处理的请求 URL,可以是一个字符串数组,支持占位符。
  • method: 指定该方法处理的请求方法,比如 GET、POST 等。
  • params:指定必须包含的参数及其值,用于限定请求的条件。
  • headers:指定必须包含的请求头及其值,用于限定请求的条件。
  • consumes:指定请求的 Content-Type,用于限定请求的条件。
  • produces:指定响应的 Content-Type,用于限定响应的条件。

通过这些参数设置,我们可以更加精确地控制请求的映射和处理,从而实现不同的业务逻辑。

2.2.1 @RequestMapping 基本使用

@RequestMapping 既可以用在类上,也可以用在方法上。当二者都添加上该注解时,访问地址就是 类 + 方法

接下来,我们实现的功能是 访问地址:http://localhost:8080/user/hi,能够打印 “Hello, 黄小黄~” 信息。

创建⼀个 UserController 类,实现⽤户到 Spring 程序的互联互通,具体实现代码如下:

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

@Controller // Spring 启动时加载
@ResponseBody // 返回非页面数据
@RequestMapping("/user") // 路由规则注册
public class UserController {
	// 路由规则注册
    @RequestMapping("/hi")
    public String sayHello() {
        return "Hello, 黄小黄~";
    }
}

实现结果01

2.2.2 GET 请求 还是 POST 请求?

这里直接说结论,默认情况下,@RequestMapping 注解既可以接收 GET请求,又可以接收 POST请求。如果需要指定接收请求方式,则需要对 method 参数进行指定 GET/POST ⽅法类型。

指定接收 POST 请求

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

@Controller // Spring 启动时加载
@ResponseBody // 返回非页面数据
@RequestMapping("/user") // 路由规则注册
public class UserController {
    // 指定 POST
    @RequestMapping(value = "/showPost", method = RequestMethod.POST)
    public String showPost() {
        return "接收到了 POST 请求~";
    }
}

结果2

2.2.3 @GetMapping 与 @PostMapping

SpringMVC同时提供了 @GetMapping 与 @PostMapping注解,分别对应接收请求 GET类型 与 POST类型。以下代码演示了指定接收GET请求:

// 指定 GET
@GetMapping("/showGet")
public String showGet() {
    return "接收到了 GET 请求~";
}

3 获取参数

3.1 传递单个参数/多个参数

在 Spring MVC 中,可以直接使用方法中的参数列表来实现参数的传递,示例代码如下:

// 传递单个参数
@GetMapping("/method01")
public String method01(int num) {
    return "num: " + num;
} 

实现结果3
可以看到,参数正常的传递过去了。
但是,对于基本数据类型来说,有坑点! 如果忘记传参数呢?
实现结果4
可以看到,服务器返回500状态码。如何解决呢?我们可以对于所有的基本数据类型,采用包装类的方式传递参数, 示例代码如下:

// 传递单个参数
@GetMapping("/method02")
public String method02(Integer num) {
    return "num: " + num;
}

这样,如果前端忘记传递参数,只会返回 null。问题就很清晰:是因为忘记传递 num 值造成的~
结果5

如何传递多个参数?
只需要增加方法参数列表的参数即可。当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置是不影响后端获取参数的结果。

3.2 传递对象

Spring MVC中,可以自动实现参数传递的赋值。例如,传递一个 Student 对象:

import lombok.Data;

@Data
public class Student {
    private String name;
    private String password;
}

传递对象代码实现:

// 传递对象
@GetMapping("/student")
public String showStudent(Student student) {
    String name = student.getName();
    String password = student.getPassword();
    return name + " : " + password;
}

结果6

3.3 后端参数重命名(@RequestParam 参数映射)

某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不⼀致, ⽐如前端传递了⼀个 name 给后端,⽽后端⼜是有 curName 字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使⽤ @RequestParam 来重命名前后端的参数值。示例代码如下:

// 参数映射
@GetMapping("/para")
public String showCurName(@RequestParam("name") String curName) {
    return "curName = " + curName;
}

这时,即使前端传过来的参数是 name, 也可以正常映射了:
结果7

3.4 @RequestParam 参数必传设置

上述例子中,如果传递一个非 name 值,就会出现如下错误:
结果7
这是什么原因呢?通过查看 @RequestParam 注解的实现细节就可以发现端倪:
实现细节
可以看到,required 默认为 true,即不传递该参数会报 400 错误。

设置非必传参数
只需要设置 @RequestParam 中的 required=false 来避免不传递时报错:

// 参数映射
@GetMapping("/para")
public String showCurName(@RequestParam(value = "name", required = false) String curName) {
    return "curName = " + curName;
}

结果8

3.5 @RequestBody 接收JSON对象

// 传递 JSON
@PostMapping("/set-student")
public String setStudent(@RequestBody Student student) {
    System.out.println(student);
    return "Student Set Success.";
}

使用 PostMan 构造 JSON 传递给后端:
结果9

3.6 @PathVariable 获取URL中参数

有时,参数并不是以 name=xxx&password=xxx 形式传递的。
例如:http://localhost:8080/user/login/黄小黄/123123
其中,黄小黄表示name的值,123123表示password的值。这种情况我们该如何获取参数呢?可以使用 @PathVariable 实现,后端实现代码:

// 获取 URL 中的参数
@GetMapping("/login/{name}/{password}")
public String login(@PathVariable String name, @PathVariable String password) {
    return "name = " + name + "<br>" +
            "password = " + password + "<br>" +
            "Login Success.";
}

结果10

3.7 @RequestPart 上传⽂件

@RequestPart 注解可以用于处理multipart/form-data类型的请求,常用于上传文件。可以将该注解与@RequestBody注解合并使用,用于传递文件和其他表单数据。例如:

@PostMapping("/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file) {
    // 处理文件上传的逻辑
    return "success";
}

这里@RequestParam(“file”)表示从请求中获取名为"file"的文件,上传的文件将被存储在MultipartFile对象中。我们可以使用MultipartFile对象的方法来处理上传的文件。

案例:上传一个图片到本机的某个目录

// 上传文件Demo
@RequestMapping("/upFile")
public String upFile(@RequestParam("myFile") MultipartFile file) throws IOException {
    // 上传的路径根目录
    String path = "D:\\info\\";
    // 路径+【唯一文件名】
    path += UUID.randomUUID().toString().replace("-", "");
    // 路径+文件名+【后缀】
    path += file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
    // 保存文件
    file.transferTo(new File(path));
    return path + "上传成功!";
}

结果11

3.8 获取Cookie/Session/header

传统获取 header/cookie

// 传统获取 header/cookie
@RequestMapping("/method04")
public String method04(HttpServletRequest req, HttpServletResponse resp) {
    String name = req.getParameter("name");
    // 获取所有 Cookie 信息
    Cookie[] cookies = req.getCookies();
    // 获取 header 信息
    String userAgent = req.getHeader("User-Agent");
    return name + " : " + userAgent;
}

@CookieValue 获取 cookie

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

@RequestHeader 获取 header

// @RequestHeader 获取 header
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String userAgent) {
    return "User-Agent: " + userAgent;
}

Session 可以使⽤ HttpServletRequest,如下代码所示:

@RequestMapping("/sess1")
public String sess1(HttpServletRequest req) {
    // 如果 session 不存在, 不会自动创建
    HttpSession session = req.getSession(false);
    String username = "默认值";
    if (session != null && session.getAttribute("username") != null) {
        username = (String) session.getAttribute("username");
    }
    return username;
}

获取 Session 简洁方式

// 更简洁方式获取 Session
@RequestMapping("/sess2")
public String sess2(@SessionAttribute(value = "username", required = false) String username) {
    return username;
}

4 返回数据

4.1 返回静态页面

创建一个静态页面 index.html
静态页面

创建控制器,并实现相应的方法:

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

@Controller
@RequestMapping("/test")
public class TestController {
    // 返回静态页面
    @RequestMapping("/index")
    public Object index() {
        // 执行业务
        // 返回 View -> index.html
        return "/index.html";
    }
}

结果12

4.2 返回 text/html

 // 返回 test/html
 @RequestMapping("/method1")
 @ResponseBody
 public String method1() {
     return "<h1>Hello, world!</h1>";
 }

结果13

4.3 返回 JSON 对象

在下面的示例中,@ResponseBody 注解告诉 SpringMVC 将返回的 Map 对象转换成 JSON 对象,并将其作为 HTTP 响应返回给客户端。

@RequestMapping("/method2")
@ResponseBody
public Map<String, String> method2() {
    Map<String, String> map = new HashMap<>();
    map.put("黄小黄", "111");
    map.put("蒲小七", "777");
    return map;
}

结果14

4.4 请求重定向与请求转发

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

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

示例代码如下:

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

请求转发与请求重定向的区别?

  1. 请求转发是在服务器内部完成的,客户端浏览器只发出了一次请求,服务器接收到请求后直接将请求转发给另一个资源进行处理, 这个过程对于浏览器来说是透明的;而请求重定向是客户端发出了两次请求,第一次请求得到服务器响应后,服务器会告诉浏览器要转向到新的资源,浏览器收到响应后会再次发起请求。

  2. 对于请求转发,客户端浏览器地址栏不会改变,仍然是原来的地址;而请求重定向会将地址栏改变为新的地址。

  3. 请求转发使用的是forward方法,它只能在同一个Web应用程序内部实现;而请求重定向使用的是sendRedirect方法,它可以实现跨域跳转。

  4. 请求转发是在服务器内部进行的,因此可以共享同一个request域中的数据,而请求重定向是两个完全独立的请求,不能共享request域中的数据。

  5. 请求重定向与直接访问新地址效果一致,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问。

4.5 组合注解:@RestController

@RestController = @Controller + @ResponseBody

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

更多注解:https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-requestmapping.html


写在最后

本文被 JavaEE编程之路 收录点击订阅专栏 , 持续更新中。
 以上便是本文的全部内容啦!创作不易,如果你有任何问题,欢迎私信,感谢您的支持!

在这里插入图片描述

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

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

相关文章

卡尔曼滤波(附C++代码)

是什么 任何时候对于动态系统存在不确定信息&#xff0c;都可使用卡尔曼滤波&#xff08;Kalman Filter&#xff0c;下面简称为KF&#xff09;对系统下一步要做什么做出有根据的猜测。 KF对于连续变化的系统是理想的&#xff0c;优点是占用内存小而且速度快&#xff0c;非常适…

在Linux中安装RabbitMQ

RabbitMQ下载网址 Socat下载网址 erlang下载网址 RabbitMQ安装包依赖于Erlang语言包的支持&#xff0c;所以需要先安装Erlang语言包&#xff0c;再安装RabbitMQ安装包 通过Xftp软件将这三个压缩包上传到linux中的opt目录下 ,双击即可 在安装之前先查询…

Android oss policy上传

OSS Policy方式上传 一、 流程对比1.1 普通上传1.2 服务端签名后直传 二、获取上传的policy签名配置三、请求OSS上传文件四、调用应用服务器接口同步文件五、关于上传OSS报错注意事项六、附送链接 一、 流程对比 1.1 普通上传 缺点&#xff1a; 上传慢&#xff1a;用户数据需…

数学建模常用模型(五):多元回归模型

数学建模常用模型&#xff08;五&#xff09;&#xff1a;多元回归模型 由于客观事物内部规律的复杂性及人们认识程度的限制&#xff0c;无法分析实际对象内在的因果关系&#xff0c;建立合乎机理规律的数学模型。所以在遇到有些无法用机理分析建立数学模型的时候&#xff0c;…

docker中运行RabbitMq的启用插件指南

我们使用 Docker 来运行 RabbitMQ&#xff0c;有时需要启用一些插件&#xff0c;这个与正常安装的启用插件的步骤会有所不同。以下是在 Docker 中启用 RabbitMQ 插件的一般步骤&#xff1a; 首先&#xff0c;确认已经将 rabbitmq_delayed_message_exchange-3.12.0.ez 插件文件复…

raid5两块磁盘掉线导致阵列崩溃的服务器数据恢复案例

服务器数据恢复环境&#xff1a; DELL PowerVault系列某型号存储&#xff0c;15块硬盘搭建了一组RAID5磁盘阵列。 服务器故障&检测&#xff1a; 存储设备raid5阵列中一块磁盘由于未知原因离线&#xff0c;管理员对该磁盘阵列进行了同步操作。在同步的过程中又有一块磁盘指示…

使用 hbuilderx 配置 MuMu模拟器进行调试

第一步 先安装MuMu模拟器&#xff0c;调成手机模式。 第二步 查看MuMu模拟器监听的端口。 在安装目录下 /vms/MuMuPlayer-12.0-0/MuMuPlayer-12.0-0 旧端口7555&#xff0c;新端口号16384 切换到安装目录下的 /shell&#xff0c;然后shift右击&#xff0c;打开 powershell&a…

【服务器数据恢复】raid5崩溃的redhat linux系统数据恢复案例

服务器数据恢复环境&#xff1a; 一台ibm某型号服务器&#xff0c;5块硬盘组建一组raid5磁盘阵列&#xff0c;redhat linux操作系统&#xff0c;上层部署有oracle数据库。 服务器故障&#xff1a; raid5阵列中两块硬盘离线&#xff0c;服务器崩溃。经过初检发现故障服务器中的…

基于SpringBoot的医护人员排班系统【附开题(bao告)和万字文档(Lun文)和搭建文档】

主要功能 前台登录&#xff1a; ①首页&#xff1a;医院信息展示、医护信息展示、排班信息展示、投诉信息展示 ②医院信息&#xff1a;名称查询、医院查看、医院简介、可以点赞、可以评论、点我收藏 ③医护信息&#xff1a;根据工号、姓名查询、点击查看医护信息、可以收藏 ④…

Simulink仿真模块 - Band-Limited White Noise

Band-Limited White Noise模块的功能是在连续系统中引入白噪声。它所在的库为: Simulink / Sources 如图所示: Band-Limited White Noise 模块生成适合在连续系统或混合系统中使用的正态分布随机数。 白噪声仿真 从理论上讲,连续白噪声的相关时间为 0,功率谱密度 …

飞利浦的护眼台灯好用吗?南卡/飞利浦/雷士对比测评,看看哪款更好用!

日常生活中&#xff0c;灯光对于我们重要性不用多说。不管是学习还是办公等环境都需要合适的光线&#xff0c;而台灯作为补充光线小型家电&#xff0c;基本每个家庭里都会备着一台&#xff0c;特别是对于长期使用电脑的上班族或者需要长时间学习的学生这类人员。但是台灯的种类…

【大数据技术】hive 窗口函数sum range between的详细介绍

【大数据技术】hive 窗口函数sum range between的详细介绍 数据准备 建表 create table range_test( name string, month int , sales int ) row format delimited fields terminated by "," ;插入数据 load data local inpath "/home/xx/test/1.t…

双击就能运行的Win95,流畅稳定还内置大型游戏

像咱这样的新时代互联网民工&#xff0c;上班面对 Win10/11 下班也还是一样&#xff0c;难免有时候觉得腻。 回味起当初的 Win7、Win8、Win XP &#xff0c;不管当初受过什么伤&#xff0c;现在只有美好的回忆。 大家可能还想象过&#xff0c;用现在配置去运行老系统。 不知高…

uniapp 小程序 vue TypeError: Cannot read property ‘toString‘ of undefined

是因为对字符串使用toString的时候页面中的数据还没有加载 。错误代码&#xff1a; 可以使用 v-if 修改为&#xff1a;

AR是现实的商业创新,还是虚幻的电子梦境?

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 封面 / 姝琦Midjourney 产品统筹 / bobo 在本期节目中&#xff0c;我们将深入探讨AVAR的创始人胡雅婷的创业故事。 我们从年轻人偏爱虚拟偶像和热衷元宇宙创业的社会话题出发&…

递归的深层次理解+初始搜索算法

1)什么是递归:就是函数自己调用自己的过程 2)为什么会使用到递归:主问题->相同的子问题&#xff0c;相同的子问题->一样相同的子问题 3)递归结束的条件:也就是细节和出口最小的不能在继续进行分割的子问题 4)宏观看待递归的过程: 1)不要在意递归展开的细节图 2)那递归的函…

全面分析MySQL?ERROR?1045出现的原因及解决

目录 通常从网上都能找到解决方案 1.停止服务2.跳过验证3.修改密码4.重启服务原因分析 SO 解决办法 在命令行输入mysql -u root –p&#xff0c;输入密码&#xff0c;或通过工具连接数据库时&#xff0c;经常出现下面的错误信息&#xff0c;相信该错误信息很多人在使用MySQL…

使用Kali Linux 暴力破解wifi密码详细步骤

使用Kali Linux 暴力破解wifi密码详细步骤所谓暴力破解就是穷举法&#xff0c;将密码字典中每一个密码依次去与握手包中的密码进行匹配&#xff0c;直到匹配成功。所以能否成功破解wifi密码取决于密码字典本身是否包含了这个密码。破解的时间取决于CPU的运算速度以及密码本身的…

信息安全-数据安全-数据安全平台建设实践

背景 在大数据时代&#xff0c;数据已经成为公司的核心竞争力。此前&#xff0c;我们介绍了美团酒旅起源数据治理平台的建设与实践&#xff0c;主要是通过各种数据分析挖掘手段&#xff0c;为公司发展决策和业务开展提供数据支持。 近期&#xff0c;业内数据安全事件频发&…

日本社交网络市场:Facebook 与本土巨头的竞争分析

摘要&#xff1a;Facebook作为全球最大的社交媒体平台之一&#xff0c;成功地击败了日本的本土社交网站&#xff0c;包括Mixi、DeNA和Gree等。 社交媒体在全球范围内迅速崛起&#xff0c;改变了人们的社交方式和信息传播方式。然而&#xff0c;在不同国家和地区&#xff0c;由于…