JavaEE--Spring MVC

目录

[一、Spring MVC概述](#一、Spring MVC概述)

二、建立连接

[1. @RequestController注解](#1. @RequestController注解)

[2. @RequestMapping注解](#2. @RequestMapping注解)

[3. Postman](#3. Postman)

[3.1 下载与安装](#3.1 下载与安装)

[3.2 创建请求](#3.2 创建请求)

​编辑

三、请求

[1. 传递单个参数](#1. 传递单个参数)

[2. 传递多个参数](#2. 传递多个参数)

[3. 传递对象](#3. 传递对象)

[4. 后端参数重命名](#4. 后端参数重命名)

[5. 传递数组](#5. 传递数组)

[6. 传递集合](#6. 传递集合)

[7. 传递JSON数据](#7. 传递JSON数据)

[7.1 JSON概念](#7.1 JSON概念)

[7.2 JSON 语法规则](#7.2 JSON 语法规则)

[7.3 JSON 与 Java 对象互转](#7.3 JSON 与 Java 对象互转)

[7.4 JSON优点](#7.4 JSON优点)

[7.5 传递JSON对象](#7.5 传递JSON对象)

[8. 从URL中获取参数](#8. 从URL中获取参数)

[9. 上传文件](#9. 上传文件)

[10. 获取Cookie](#10. 获取Cookie)

[11. 获取session](#11. 获取session)

[12. 获取Header](#12. 获取Header)

四、响应

[1. 返回静态页面](#1. 返回静态页面)

[2. 返回数据](#2. 返回数据)

[3. 返回HTML代码片段](#3. 返回HTML代码片段)

[4. 返回JSON](#4. 返回JSON)

[5. 设置状态码](#5. 设置状态码)

[6. 设置Header](#6. 设置Header)


一、Spring MVC概述

官网https://docs.spring.io/spring-framework/reference/web/webmvc.html

Spring MVC 是 Spring 框架的一个模块,专门用于构建基于 Java 的 Web 应用程序。它基于模型-视图-控制器(MVC)设计模式,提供了一种灵活、可扩展的方式来开发动态网页应用。

简单来说,Spring MVC是一个Web框架。

既然是Web框架,那么当用户在浏览器中输入了url之后,我们的Spring MVC项目就可以感知到用户的请求,并给予响应。

学习Spring MVC,也就是学习如何通过浏览器和用户程序进行交互。

交互主要分以下三个方面:

  1. 建立连接:将用户(浏览器)和Java程序连接起来,也就是访问一个地址能够调用到我们的Spring程序;
  2. 请求:用户请求的时候会带一些参数,在程序中要想办法获取到参数,所以请求主要是获取参数的功能;
  3. 响应:执行了业务逻辑之后,要把程序执行的结果返回给用户。

二、建立连接

在Spring MVC中使用@RequestMapping注解来是想URL路由映射,也就是浏览器连接程序的作用。

先创建一个Spring Boot项目,再创建一个UserController类,实现用户通过浏览器和程序的交互,代码如下:

java 复制代码
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello() {
        return "Hello World";
    }
}

方法名和路径名无需一致。

运行程序后,接下来在浏览器访问http://127.0.0.1:8080/hello:

1. @RequestController注解

@RequestController是 Spring MVC 中的一个组合注解,主要用于简化 RESTful Web 服务的开发,将方法的返回值直接序列化为 JSON 或 XML 响应体,无需额外的视图解析。

核心特性:

  • 自动将方法返回值转换为 HTTP 响应体。
  • 默认使用@ResponseBody注解效果,无需显式声明。
  • 适用于返回 JSON/XML 数据的 API 场景。

2. @RequestMapping注解

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

当服务收到请求时,路径为/hello的请求就会调用hello这个方法的代码。

路由映射:当用户访问一个URL时,将用户的请求对应到程序中某个类的某个方法的过程。

@RequestMapping既可修饰类,也可以修饰方法,当修饰类和方法时,访问的地址是类路径+方法路径。

@RequestMapping标识一个类:设置映射请求的请求路径的初始信息

@RequestMapping标识一个方法:设置映射请求请求路径的具体信息

java 复制代码
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/Spring")
@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello() {
        return "Hello World";
    }
}

访问地址:http://127.0.0.1:8080/Spring/hello

@RequestMapping的URL路径最前面加不加/(斜杠)都可以,Spring程序启动时,会进行判断,如果前面没有加/,Spring会拼接上一个/。

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

java 复制代码
@RequestMapping("/Spring/1")
@RestController
public class HelloController {

    @RequestMapping("/hello/2")
    public String hello() {
        return "Hello World";
    }
}

访问地址:http://127.0.0.1:8080/Spring/1/hello/2

@RequestMapping既支持Get请求,又支持Post请求。同理,也支持其他的请求方式。可以通过method参数或者@GetMapping/@PostMapping来指定。

java 复制代码
import org.springframework.web.bind.annotation.*;

@RequestMapping("user")
@RestController
public class UserController {
    //既支持get,又支持post
    @RequestMapping("/m1")
    public String m1() {
        return "m1";
    }
    //只支持get
    @RequestMapping(value = "/m2", method = RequestMethod.GET)
    public String m2() {
        return "m2";
    }
    //相当于
    @GetMapping("/m4")
    public String m4() {
        return "m4";
    }
    //只支持post
    @RequestMapping(value = "/m3", method = RequestMethod.POST)
    public String m3() {
        return "m3";
    }
    //相当于
    @PostMapping("/m5")
    public String m5() {
        return "m5";
    }
}

3. Postman

为了更加方便的测试后端方法,我们可以使用 API 开发与测试工具--Postman。

3.1 下载与安装

官网下载,安装过程很简单,这里就不赘述了。

3.2 创建请求

如何操作:

普通传参,也就是通过查询字符串来传参。

学习HTTP环节时,我们通过URL来访问互联网上的某一个资源,URL的格式如下:

其中,查询字符串就是请求的参数。

在Postman上可以这样设置:

与此同时,URL也会变化:

三、请求

访问不同的路径,就是发送不同的请求.在发送请求时,可能会带一些参数,所以学习Spring的请求,主要是学习如何传递参数到后端以及后端如何接收。

1. 传递单个参数

传递单个参数,在SpringMVC中直接用方法中的参数就可以,比如以下代码:

java 复制代码
@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r1")
    public String r1(String keyword){
        return "接收参数:" + keyword;
    }
}

可以在URL中自定义keyword=spring访问地址:

也可以使用Postman:

先输入URL:

再输入参数:

点击send:

可以看到,后端程序正确地拿到了参数值。

注意事项:

  1. 参数名一定要一致;
  2. 使用基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误类型,不匹配时,会报400错误类型,所以企业开发中,对于参数可能为空的数据,建议使用包装类型。

| | 包装类 | 基本数据类型 |
| 代码 | java @RequestMapping("/r3") public String r3(Integer number){ return "接收参数: " + number; } | java @RequestMapping("/r4") public String r4(int number){ return "接收参数: " + number; } |
| 正常传参 | | |

非正常传参

2. 传递多个参数

java 复制代码
@RequestMapping("/r2")
public String r2(String username, String password){
    return "接收参数: username:" + username + ", password:" + password;
}

URL中参数的顺序可以调换,不影响正常传参。

3. 传递对象

创建一个UserInfo对象类:

java 复制代码
public class UserInfo {

    private String name;
    private Integer gender;
    private Integer age;

    public UserInfo(){
    }

    public UserInfo(String name, Integer age, Integer gender) {
        this.age = age;
        this.gender = gender;
        this.name = name;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", gender=" + gender +
                '}';
    }
}

传参代码:

java 复制代码
@RequestMapping("/r5")
public String r5(UserInfo userInfo){
    return "接收参数: " + userInfo.toString();
}

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

4. 后端参数重命名

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

java 复制代码
//此时q为必传参数
@RequestMapping("/r6")
public String r6(@RequestParam("q") String keyword){
    return "接收参数: keyword=" + keyword;
}
//此时q为非必传参数
@RequestMapping("/r7")
public String r7(@RequestParam(value = "q", required = false) String keyword){
    return "接收参数: keyword=" + keyword;
}

5. 传递数组

java 复制代码
//传递数组
@RequestMapping("/r8")
public String r8(String[] arr){
    return "接收参数:arr=" + Arrays.toString(arr);
}

可以用',',也可以一个一个地传递。

6. 传递集合

和数组类似,同一个请求参数名有为多个,且需要使用@RequestParam绑定参数关系。

java 复制代码
//传递集合
@RequestMapping("/r9")
public String r9(@RequestParam List<Integer> list){
    return "接收参数:list=" + list;
}

7. 传递JSON数据

7.1 JSON概念

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用文本格式存储和传输数据,易于人阅读和编写,也便于机器解析和生成。它基于 ECMAScript 的子集,但独立于编程语言,广泛用于 Web 应用和 API 交互。

7.2 JSON 语法规则
  • 数据以键值对形式表示,键名用双引号包裹,例如 "name": "Alice"
  • 数据之间用逗号分隔,例如 {"name": "Alice", "age": 25}
  • 花括号 {} 表示对象(Object),方括号 [] 表示数组(Array)。
  • 支持的数据类型:字符串、数字、布尔值、对象、数组、null
java 复制代码
{
  "name": "Alice",
  "age": 30,
  "isStudent": false,
  "hobbies": ["reading", "coding"],
  "address": {
    "city": "New York",
    "country": "USA"
  }
}
7.3 JSON 与 Java 对象互转
java 复制代码
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

public class JsonTest {

    @Test
    void testObject2Json() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        //创建java对象
        UserInfo userInfo = new UserInfo("zhangsan", 15, 1);
        //对象转json
        String s = objectMapper.writeValueAsString(userInfo);
        System.out.println(s);
    }

    @Test
    void testJson2Object() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        //创建Json字符串
        String s = "{\"name\":\"ZhangSan\",\"gender\":1,\"age\":15}";
        //Json转对象
        UserInfo userInfo = objectMapper.readValue(s, UserInfo.class);
        System.out.println(userInfo);
    }
}
7.4 JSON优点
  1. 简单易用:语法简单,易于理解和编写,可以快速地进行数据交换。
  2. 跨平台支持:JSON可以被多种编程语言解析和生成,可以在不同的平台和语言之间进行数据交换和传输。
  3. 轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占用带宽较小,可以提高数据传输速度。
  4. 易于扩展:JSON的数据结构灵活,支持嵌套对象和数组等复杂的数据结构,便于扩展和使用。
  5. 安全性:JSON数据格式是一种纯文本格式,不包含可执行代码,不会执行恶意代码,因此具有较高的安全性。
7.5 传递JSON对象

传递JSON对象,需要使用@RequestBody注解。

java 复制代码
//传递Json
@RequestMapping("/r10")
public String r10(@RequestBody UserInfo userInfo){
    return "接收参数:" + userInfo.toString();
}

8. 从URL中获取参数

需要在参数前添加@PathVariable注解。

java 复制代码
//从url中获取参数
@RequestMapping("/article/{articleID}")
public String r11(@PathVariable Integer articleID){
    return "接收文章ID:" + articleID;
}

也可以获取多个参数(没有按照顺序也能正确执行)。

java 复制代码
@RequestMapping("/article/{type}/{articleID}")
public String r12(@PathVariable Integer articleID, @PathVariable String type){
    return "接收文章ID:" + articleID + ",type: " + type;
}

9. 上传文件

文件参数类型使用MultipartFile。

java 复制代码
@RequestMapping("/r13")
public String r13(MultipartFile file) throws IOException {
    file.transferTo(new File("D:\\temp\\" + file.getOriginalFilename()));
    return "文件上传成功: " + file.getOriginalFilename();
}

点击"+ New file from local machine",在本地选择你要上传的文件。

点击send。

D盘temp文件夹中也成功出现了我们想要上传的文件。

10. 获取Cookie

设置Cookie

保存,就获得另一个Cookie。

也可以添加多个Cookie值。

方法一:

java 复制代码
@RequestMapping("/r14")
public String r14(HttpServletRequest request, HttpServletResponse response){
    Cookie[] cookies = request.getCookies();
    if (cookies != null) {
        for (Cookie cookie: cookies) {
            System.out.println(cookie.getName() + ':' + cookie.getValue());
        }
    }
    return "返回Cookie成功!";
}

request:请求,response:响应

这两个参数不是绑定出现的,所以以上代码可以不用谢response。

方法二:

java 复制代码
@RequestMapping("/r15")
public String r15(@CookieValue("name") String name) {
    return "从注解获取到name的值:" + name;
}

这种方法虽然简洁,但是一次只能获取到一个Cookie值。

11. 获取session

Session是服务器端的机制,我们需要先存储,才能再获取。

java 复制代码
//session存储
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request) {
    //从Cookie中获取SessionID,再根据SessionID获取Session对象
    HttpSession session = request.getSession();
    //session默认存储在内存中
    session.setAttribute("name", "zhangsan");
    session.setAttribute("age", 15);
    return "session存储成功!";
}

获取session有两种方式:

java 复制代码
HttpSession getSession(boolean create);

HttpSession getSesion();

参数如果为true,则当不存在会话是新建会话;参数如果为false,则当不存在会话时返回null。

方法一:

java 复制代码
//获取session
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    //若用户登录,session有值,用户未登录,session为null
    if (session == null) {
        return "用户未登录";
    } else {
        String name = (String) session.getAttribute("name");
        return "登录用户为:" + name;
    }
}

方法二:

java 复制代码
@RequestMapping("/getSession2")
public String getSession2(HttpSession session) {
    //相当于getSession参数为true,则不存在session为null的情况
    String name = (String) session.getAttribute("name");
    return "登录用户为:" + name;
}

方法三:

java 复制代码
@RequestMapping("/getSession3")
public String getSession3(@SessionAttribute("name") String name) {
    return "登录用户为:" + name;
}

12. 获取Header

方法一:

java 复制代码
//获取Header
@RequestMapping("/getHeader")
public String getHeader(HttpServletRequest request) {
    String userAgent = request.getHeader("User-Agent");
    return "从header获取userAgent:" + userAgent;
}

方法二:

java 复制代码
@RequestMapping("/getHeader2")
public String getHeader2(@RequestHeader("User-Agent") String userAgent) {
    return "从header获取userAgent:" + userAgent;
}

四、响应

1. 返回静态页面

先创建前端页面,注意在resources/static/路径下创建。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>我是Index页面</h1>
</body>
</html>
java 复制代码
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@RequestMapping("/resp")
@Controller
public class RespController {

    //返回页面
    @RequestMapping("/r1")
    public String returnPage(){
        return "/index.html";
    }
}

但若是把类注解写成@RestController,那么运行之后却发现,页面未正确返回,http响应把"/index.html"当做了http响应正文的数据。

随着互联网的发展,目前项目开发流行"前后端分离"模式,Java主要是用来做后端项目的开发,所以也就不再处理前端相关的内容了。MVC的概念也逐渐发生了变化,View不再返回视图,而是返回显示视图时需要的数据。所以前面使用的@RestController其实是返回的数据。

而@RestController=@Controller+@ResponseBody+......

java 复制代码
//@RestController源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

@ResponseBody既是类注解,又是方法注解。作为类注解的时候,表示该类的所有方法全部返回数据,作为方法注解时,表示该方法返回数据。

如果一个类全部返回数据,可以使用@RestController或者@Controller+@ResponseBody;

如果一个类全部返回页面,使用@Controller。

2. 返回数据

java 复制代码
//返回数据
@ResponseBody
@RequestMapping("/r2")
public String returnData() {
    return "我是前端需要的数据";
}

3. 返回HTML代码片段

java 复制代码
@ResponseBody
@RequestMapping("/r3")
public String returnHTML() {
    return "<h1>我是一级标题</h1>";
}

也可以使用produces设置响应的Content-type:

java 复制代码
@ResponseBody
@RequestMapping(value = "/r4", produces = "text/plain")
public String returnHTML2() {
    return "<h1>我是一级标题</h1>";
}

4. 返回JSON

java 复制代码
@ResponseBody
@RequestMapping("/r5")
public UserInfo returnJSON() {
    return new UserInfo("zhangsan", 20, 1);
}

5. 设置状态码

java 复制代码
@ResponseBody
@RequestMapping("/r6")
public UserInfo setStatus(HttpServletResponse response) {
    response.setStatus(401);
    return new UserInfo("zhangsan", 20, 1);
}

使用postman观察,可以看出,状态码不影响页面的显示。

6. 设置Header

java 复制代码
@ResponseBody
@RequestMapping("/r7")
public String setHeader(HttpServletResponse response) {
    response.setHeader("myHeader", "myHeader");
    return "设置Header成功";
}

创作不易,给个三连支持一下吧

相关推荐
Java水解4 小时前
深入剖析Spring Boot依赖注入顺序:从原理到实战
后端·spring
椎4956 小时前
web后端开发——原理
spring boot·spring·mybatis
Wade_Crab6 小时前
第二章:动态 Prompt 管理与多科室智能问答系统
人工智能·spring·prompt
技术猴小猴8 小时前
如何使用Python实现LRU缓存
python·spring·缓存
hrrrrb10 小时前
【Spring Security】Spring Security 密码编辑器
java·hive·spring
Elsa️74620 小时前
个人项目开发(1):使用Spring Secruity实现用户登录
java·后端·spring
码界奇点21 小时前
Spring Web MVC构建现代Java Web应用的基石
java·前端·spring·设计规范
陈一Tender1 天前
JavaWeb后端实战(IOC+DI)
java·spring boot·spring
Seven971 天前
Spring AOP、MVC高频面试题解析
java·spring