程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • SpringMVC

    • SpringMVC 入门
    • Spring MVC 数据接收
      • 1. 使用@RequestParam注解接收查询参数
      • 2. 使用@PathVariable注解接收URL路径参数
      • 3. 使用@RequestBody注解接收JSON数据
      • 4. 使用@RequestHeader注解接收HTTP请求头
      • 5. 使用@ModelAttribute注解接收表单数据
      • 6. 使用MultipartFile处理单文件上传
      • 7. 使用List<MultipartFile\>处理多文件上传
      • 8. 使用@CookieValue注解接收Cookie数据
      • 9. 使用@SessionAttribute注解接收Session属性
      • 10. 使用@DateTimeFormat注解处理日期参数
      • 11. 在对象属性中使用@DateTimeFormat注解处理日期
      • 12. 接收数组或集合类型参数
        • 前端发送数组或集合参数
        • 后端接收数组或集合参数
    • Spring MVC 数据返回
    • Spring MVC 路径匹配规则
    • Spring MVC 内容协商策略
    • Spring MVC 异步请求处理
    • Spring MVC 静态资源处理
    • Spring MVC 自定义格式化器
    • SpringMVC 自定义拦截器
    • SpringMVC 配置跨域(CORS)
    • Spring MVC 自定义视图控制器
    • Spring MVC 自定义视图解析器
    • Spring MVC 自定义方法参数解析器
    • Spring MVC 自定义返回值处理器
    • Spring MVC 自定义消息转换器
    • Spring MVC 消息转换器扩展
    • Spring MVC 自定义异常处理器
    • Spring MVC 自定义异常处理器扩展
  • SpringMVC
  • SpringMVC
scholar
2024-08-17
目录

Spring MVC 数据接收

# Spring MVC 数据接收

注解中的value参数作用

  • value参数作用:指定前端传递的参数名称。当value参数值与前端传递的参数名一致时,后端方法的参数名可以任意设置,不必与前端保持一致。
  • 简写形式:可以使用简写形式如@RequestParam("id")直接指定参数名。
  • 默认映射规则:若不设置value参数,Spring默认使用方法参数名与前端参数名进行映射,此时方法参数名必须与前端传参名称完全一致。

# 1. 使用@RequestParam注解接收查询参数

注解功能:@RequestParam注解用于接收HTTP请求中的查询参数或表单数据,将URL查询字符串或表单中的参数绑定到控制器方法的参数上。

重要配置参数:

  • value:指定要绑定的请求参数名称
  • required:设置参数是否必须提供,默认为true
  • defaultValue:为可选参数提供默认值

前端请求示例:

// 使用Axios发送GET请求并携带参数
axios.get('/api/getUser', {
  params: {
    id: 123,        // 用户ID参数
    name: '张三'     // 用户姓名参数
  }
})
.then(response => {
  console.log('服务器返回数据:', response.data); // 处理服务器响应
})
.catch(error => {
  console.error('请求发送失败:', error); // 处理请求错误
});
1
2
3
4
5
6
7
8
9
10
11
12
13

后端接收参数示例:

@RestController
@RequestMapping("/api")
public class UserController {

    @GetMapping("/getUser")
    public ResponseEntity<String> getUser(
            @RequestParam(value = "id", required = true) int id,  // 必填参数id,绑定前端传递的id参数
            @RequestParam(value = "name", required = false, defaultValue = "匿名用户") String name  // 可选参数name,未提供时使用默认值
    ) {
        // 构建响应数据
        String response = "接收到的用户信息 - ID: " + id + ", 姓名: " + name;
        
        // 返回HTTP 200状态码和响应数据
        return ResponseEntity.ok(response);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

关键点说明:

  • @RequestParam适用于从URL查询字符串、表单数据中提取参数
  • value属性指定要绑定的参数名,是该注解的核心属性
  • 当required=true(默认值)时,如果请求中缺少该参数会返回400错误
  • defaultValue属性允许为可选参数设置默认值,避免空值处理逻辑
  • 注解会自动进行类型转换,如字符串转数字,但转换失败会返回400错误

# 2. 使用@PathVariable注解接收URL路径参数

注解功能:@PathVariable注解用于从URL路径中提取变量值,是实现RESTful API的重要工具,常用于资源定位,如/users/{id}。

重要配置参数:

  • value:指定路径变量名称,通常与URL模板中的占位符名称相同
  • required:指定路径变量是否必须存在,默认为true

前端请求示例:

// 使用Axios发送包含路径参数的GET请求
axios.get('/api/user/123')  // 路径中123为用户ID
.then(response => {
  console.log('服务器返回数据:', response.data); // 处理返回的用户数据
})
.catch(error => {
  console.error('请求发送失败:', error); // 错误处理
});
1
2
3
4
5
6
7
8

后端接收参数示例:

@RestController
@RequestMapping("/api")
public class UserController {

    @GetMapping("/user/{id}")  // URL模板中使用{id}占位符表示路径变量
    public ResponseEntity<String> getUserById(
            @PathVariable(value = "id") int id  // 从URL路径中提取id变量值并转换为int类型
    ) {
        // 根据路径中的id查询用户信息(示例中仅返回id)
        String response = "根据路径参数获取的用户ID: " + id;
        
        // 返回HTTP 200状态码和响应数据
        return ResponseEntity.ok(response);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

关键点说明:

  • @PathVariable是RESTful API的核心组件,用于从URL路径中提取动态部分
  • 路径模板中的占位符(如{id})必须与@PathVariable的value属性值匹配
  • 与@RequestParam类似,Spring会自动进行类型转换
  • 路径变量通常用于标识资源,如用户ID、产品ID等
  • 与查询参数相比,路径变量更适合表示必要的、用于定位资源的参数

# 3. 使用@RequestBody注解接收JSON数据

注解功能:@RequestBody注解用于接收HTTP请求体中的JSON数据并自动转换为Java对象,主要用于处理POST、PUT等请求中的JSON格式数据。

重要配置参数:

  • required:指定请求体是否必须存在,默认为true,设为false时允许请求体为空

前端请求示例:

// 使用Axios发送POST请求,传递JSON格式数据
axios.post('/api/saveUser', {
  id: 123,           // 用户ID
  name: '张三',       // 用户姓名
  age: 25            // 用户年龄
})
.then(response => {
  console.log('保存成功,服务器响应:', response.data); // 处理保存成功的响应
})
.catch(error => {
  console.error('用户数据保存失败:', error); // 处理保存失败的情况
});
1
2
3
4
5
6
7
8
9
10
11
12

后端接收参数示例:

@RestController
@RequestMapping("/api")
public class UserController {

    @PostMapping("/saveUser")
    public ResponseEntity<String> saveUser(
            @RequestBody User user  // 将请求体中的JSON数据反序列化为User对象
    ) {
        // 处理接收到的用户数据(示例中仅构建响应字符串)
        String response = "成功保存用户数据: " + user.toString();
        
        // 返回HTTP 200状态码和响应信息
        return ResponseEntity.ok(response);
    }
}

// 用户数据模型类
class User {
    private int id;       // 用户ID
    private String name;  // 用户姓名
    private int age;      // 用户年龄

    // 必须提供getter和setter方法,供Jackson进行JSON转换使用
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "ID: " + id + ", 姓名: " + name + ", 年龄: " + age;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

关键点说明:

  • @RequestBody主要用于接收JSON格式的请求体数据
  • Spring使用Jackson或其他配置的JSON库自动进行JSON到Java对象的转换
  • 数据绑定遵循松散匹配原则:
    • 前端多余的字段会被忽略
    • 缺少的字段会使用对应类型的默认值(如null、0等)
  • 转换的Java类必须有对应的getter/setter方法或公共字段
  • 在前后端分离架构中,这是最常用的数据传递方式

JSON数据映射规则

  1. 字段名称匹配原则:前端JSON中的字段名须与Java对象的属性名一致(通常是驼峰命名)
  2. 额外字段处理:如果JSON包含目标类中不存在的字段,这些字段会被忽略
  3. 字段缺失处理:如果JSON缺少目标类中的字段,这些字段会被赋予默认值(如null、0等)
  4. 类型转换:Spring会尝试进行合理的类型转换,如String→数字,String→日期等

# 4. 使用@RequestHeader注解接收HTTP请求头

注解功能:@RequestHeader注解用于获取HTTP请求头中的参数值,如获取Authorization、User-Agent、Content-Type等请求头信息。

重要配置参数:

  • value:指定要获取的HTTP请求头名称
  • required:指定请求头是否必须存在,默认为true
  • defaultValue:当请求头不存在且required=false时使用的默认值

前端请求示例:

// 使用Axios发送携带自定义请求头的POST请求
axios.post('/api/secure/saveUser', {
  id: 123,
  name: '张三',
  age: 25
}, {
  headers: {
    Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'  // JWT认证令牌
  }
})
.then(response => {
  console.log('保存成功,响应数据:', response.data);
})
.catch(error => {
  console.error('请求失败:', error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

后端接收参数示例:

@RestController
@RequestMapping("/api/secure")
public class UserController {

    @PostMapping("/saveUser")
    public ResponseEntity<String> saveUserWithAuth(
            @RequestBody User user,  // 接收请求体中的用户数据
            @RequestHeader(value = "Authorization", required = false, defaultValue = "") String authToken  // 获取Authorization请求头
    ) {
        // 验证认证令牌
        if (authToken.isEmpty()) {
            // 如果令牌为空,返回401未授权状态码
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                .body("未提供有效的认证令牌,无法保存用户数据");
        }
        
        // 验证通过,处理用户数据
        String response = "已授权保存用户数据: " + user.toString() + 
                         "\n使用的认证令牌: " + authToken;
        
        // 返回成功响应
        return ResponseEntity.ok(response);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

关键点说明:

  • @RequestHeader专用于获取HTTP请求头中的值
  • 常用于获取认证信息、客户端信息、内容协商相关头等
  • 与其他参数注解一样,支持类型转换
  • 可以设置为非必须并提供默认值,增加API的健壮性
  • 在实现认证、跨域、缓存控制等功能时特别有用

# 5. 使用@ModelAttribute注解接收表单数据

使用场景说明

在现代前后端分离的Web应用中,表单数据通常以JSON格式提交,但某些场景(如文件上传)仍需使用传统表单格式,因此了解@ModelAttribute的使用方法仍然重要。

注解功能:@ModelAttribute用于绑定表单数据到方法参数对象,处理application/x-www-form-urlencoded或multipart/form-data格式的请求数据。

重要配置参数:

  • value:指定绑定的数据名称(一般不常用)
  • binding:控制是否执行数据绑定,默认为true

前端请求示例:

// 使用Axios模拟传统表单提交
// URLSearchParams会将数据格式化为application/x-www-form-urlencoded格式
axios.post('/api/form/saveUser', new URLSearchParams({
  id: 123,             // 用户ID
  name: '张三',         // 用户姓名  
  age: 25              // 用户年龄
}))
.then(response => {
  console.log('表单提交成功:', response.data);
})
.catch(error => {
  console.error('表单提交失败:', error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13

后端接收参数示例:

@RestController
@RequestMapping("/api/form")
public class UserController {

    @PostMapping("/saveUser")
    public ResponseEntity<String> saveUserForm(
            @ModelAttribute User user  // 将表单数据绑定到User对象
    ) {
        // 处理接收到的表单数据
        String response = "已接收表单数据并保存用户: " + user.toString();
        
        // 返回成功响应
        return ResponseEntity.ok(response);
    }
}

// 用户数据类定义(与前面示例相同)
class User {
    private int id;       // 用户ID
    private String name;  // 用户姓名
    private int age;      // 用户年龄
    
    // getter和setter方法(必须提供)
    // ...
    
    @Override
    public String toString() {
        return "ID: " + id + ", 姓名: " + name + ", 年龄: " + age;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

关键点说明:

  • @ModelAttribute主要用于处理传统表单提交的数据
  • 表单字段名必须与Java对象的属性名一致
  • 与@RequestBody不同,它处理的是application/x-www-form-urlencoded和multipart/form-data格式
  • 在文件上传表单中特别有用,可以同时接收普通字段和文件字段
  • 尽管在前后端分离应用中使用较少,但在某些场景下仍然重要(如文件上传)

# 6. 使用MultipartFile处理单文件上传

功能说明:MultipartFile是Spring MVC提供的文件处理接口,通过@RequestParam注解绑定上传的文件,主要用于处理表单中的文件上传。

前端请求示例:

// 使用Axios发送包含文件的表单请求
// 假设已通过input元素选择了文件
let formData = new FormData();
formData.append('file', this.selectedFile);  // 添加文件到FormData对象

// 发送包含文件的POST请求
axios.post('/api/upload/single', formData, {
  headers: {
    'Content-Type': 'multipart/form-data'  // 设置正确的内容类型
  }
})
.then(response => {
  console.log('文件上传成功:', response.data);
})
.catch(error => {
  console.error('文件上传失败:', error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

后端接收文件示例:

@RestController
@RequestMapping("/api/upload")
public class FileUploadController {

    @PostMapping("/single")
    public ResponseEntity<String> uploadSingleFile(
            @RequestParam("file") MultipartFile file  // 接收名为"file"的上传文件
    ) {
        // 检查文件是否为空
        if (file.isEmpty()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body("上传失败:未选择文件或文件为空");
        }

        // 获取文件原始名称
        String fileName = file.getOriginalFilename();
        
        // 构建文件保存路径
        Path filePath = Paths.get("uploads/" + fileName);

        try {
            // 确保目标目录存在
            Files.createDirectories(Paths.get("uploads/"));
            
            // 将上传的文件保存到服务器
            Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
            
            // 返回成功信息
            return ResponseEntity.ok("文件上传成功: " + fileName + 
                               "\n文件大小: " + file.getSize() + " 字节" +
                               "\n文件类型: " + file.getContentType());
        } catch (IOException e) {
            // 处理文件保存过程中的异常
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("文件上传过程中发生错误: " + e.getMessage());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

关键点说明:

  • 前端必须使用FormData对象构建multipart请求
  • 设置正确的Content-Type: multipart/form-data头部
  • 后端使用@RequestParam注解和MultipartFile类型接收文件
  • MultipartFile接口提供了访问文件内容、名称、大小的方法
  • 通常需要进行文件类型验证、大小限制等安全检查
  • 应当添加异常处理来应对文件操作的各种问题

# 7. 使用List<MultipartFile>处理多文件上传

功能说明:Spring MVC支持通过List<MultipartFile>或MultipartFile[]接收多个上传文件,适用于需要一次上传多个文件的场景。

前端请求示例:

// 使用Axios发送多文件上传请求
let formData = new FormData();

// 假设this.selectedFiles是一个包含多个File对象的数组
this.selectedFiles.forEach(file => {
  formData.append('files', file);  // 使用相同的键名'files'添加多个文件
});

// 发送包含多个文件的POST请求
axios.post('/api/upload/multiple', formData, {
  headers: {
    'Content-Type': 'multipart/form-data'  // 设置multipart格式
  }
})
.then(response => {
  console.log('多文件上传成功:', response.data);
})
.catch(error => {
  console.error('多文件上传失败:', error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

后端接收文件示例:

@RestController
@RequestMapping("/api/upload")
public class FileUploadController {

    @PostMapping("/multiple")
    public ResponseEntity<String> uploadMultipleFiles(
            @RequestParam("files") List<MultipartFile> files  // 接收多个文件
    ) {
        // 检查是否有文件被上传
        if (files.isEmpty()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body("上传失败:未选择任何文件");
        }

        // 创建一个列表存储成功上传的文件名
        List<String> fileNames = new ArrayList<>();
        
        // 创建目标目录
        try {
            Files.createDirectories(Paths.get("uploads/"));
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("创建上传目录失败: " + e.getMessage());
        }
        
        // 遍历处理每个文件
        for (MultipartFile file : files) {
            // 跳过空文件
            if (file.isEmpty()) {
                continue;
            }
            
            // 获取文件名
            String fileName = file.getOriginalFilename();
            Path filePath = Paths.get("uploads/" + fileName);
            
            try {
                // 保存文件到服务器
                Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
                fileNames.add(fileName);
            } catch (IOException e) {
                // 如果某个文件保存失败,返回错误信息
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("上传过程中发生错误,部分文件可能未保存成功: " + e.getMessage());
            }
        }

        // 构建包含所有成功上传文件的响应信息
        StringBuilder response = new StringBuilder("成功上传 ")
            .append(fileNames.size())
            .append(" 个文件:\n");
        
        for (String fileName : fileNames) {
            response.append("- ").append(fileName).append("\n");
        }
        
        // 返回成功响应
        return ResponseEntity.ok(response.toString());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

关键点说明:

  • 前端使用相同的参数名多次调用formData.append()添加多个文件
  • 后端使用List<MultipartFile>接收多个文件,比数组更灵活
  • 需要单独处理每个文件的保存和错误情况
  • 建议实施的安全措施:
    • 限制上传文件总数
    • 限制单个文件和所有文件的总大小
    • 验证文件类型
    • 重命名文件以防止覆盖和路径遍历攻击

# 8. 使用@CookieValue注解接收Cookie数据

注解功能:@CookieValue注解用于从请求中获取指定名称的Cookie值,常用于获取会话标识、用户偏好等存储在客户端的数据。

重要配置参数:

  • value:指定要获取的Cookie名称
  • required:指定Cookie是否必须存在,默认为true
  • defaultValue:当Cookie不存在且required=false时使用的默认值

前端请求示例:

// 浏览器会自动发送相关域的Cookie,无需特殊处理
axios.get('/api/user/profile')
.then(response => {
  console.log('获取到用户资料:', response.data);
})
.catch(error => {
  // 可能因未登录(无Cookie)而失败
  console.error('获取用户资料失败:', error);
});
1
2
3
4
5
6
7
8
9

后端接收Cookie示例:

@RestController
@RequestMapping("/api/user")
public class UserController {

    @GetMapping("/profile")
    public ResponseEntity<String> getUserProfile(
            @CookieValue(value = "sessionId", required = false, defaultValue = "未登录") String sessionId  // 获取名为sessionId的Cookie
    ) {
        // 检查会话标识是否为默认值
        if ("未登录".equals(sessionId)) {
            // 用户未登录,返回401未授权状态
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                .body("您尚未登录,请先登录后再访问个人资料");
        }
        
        // 正常情况,根据会话ID查询用户资料
        // 这里简化处理,实际应用中会根据sessionId从数据库或缓存获取用户信息
        String userDetails = "根据会话ID(" + sessionId + ")获取的用户资料:\n" +
                           "- 用户名: 张三\n" +
                           "- 邮箱: zhangsan@example.com\n" +
                           "- 会员等级: 黄金会员";
        
        // 返回用户资料
        return ResponseEntity.ok(userDetails);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

关键点说明:

  • Cookie由浏览器自动发送,前端通常不需要特殊处理
  • @CookieValue用于直接获取特定名称的Cookie值
  • 可以设置为非必须并提供默认值,增强API健壮性
  • 常用于获取会话标识、用户偏好、跟踪标识等
  • 在处理认证相关功能时特别有用

# 9. 使用@SessionAttribute注解接收Session属性

注解功能:@SessionAttribute注解用于从HttpSession中直接获取特定属性,简化了对会话数据的访问,常用于获取登录用户信息等会话状态。

前端请求示例:

// 前端发送普通请求,服务器会通过会话Cookie关联到对应的Session
axios.get('/api/session/getUserInfo')
.then(response => {
  console.log('从会话中获取的用户信息:', response.data);
})
.catch(error => {
  console.error('获取会话信息失败:', error);
});
1
2
3
4
5
6
7
8

后端接收Session属性示例:

@RestController
@RequestMapping("/api/session")
public class SessionController {

    // 设置会话属性的方法(通常由登录接口调用)
    @PostMapping("/setUserInfo")
    public ResponseEntity<String> setUserInfo(HttpSession session) {
        // 向会话中存储用户信息
        session.setAttribute("username", "张三");
        session.setAttribute("userId", 12345);
        session.setAttribute("userRole", "ADMIN");
        
        // 返回成功信息
        return ResponseEntity.ok("用户信息已成功保存到会话中");
    }

    // 获取会话属性的方法
    @GetMapping("/getUserInfo")
    public ResponseEntity<String> getUserInfo(
            @SessionAttribute(value = "username", required = false) String username,  // 获取会话中的username属性
            @SessionAttribute(value = "userId", required = false) Integer userId,     // 获取会话中的userId属性
            @SessionAttribute(value = "userRole", required = false) String userRole   // 获取会话中的userRole属性
    ) {
        // 检查用户是否已登录(会话中是否有用户名)
        if (username == null) {
            // 用户未登录,返回401未授权状态
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                .body("未找到会话中的用户信息,请先登录");
        }
        
        // 构建包含会话信息的响应
        StringBuilder response = new StringBuilder("会话中的用户信息:\n");
        response.append("- 用户名: ").append(username).append("\n");
        
        // 添加用户ID(如果存在)
        if (userId != null) {
            response.append("- 用户ID: ").append(userId).append("\n");
        }
        
        // 添加用户角色(如果存在)
        if (userRole != null) {
            response.append("- 用户角色: ").append(userRole).append("\n");
        }
        
        // 返回会话信息
        return ResponseEntity.ok(response.toString());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

关键点说明:

  • @SessionAttribute简化了从HttpSession中获取特定属性的操作
  • 可以指定required=false使属性变为可选
  • 相比直接注入HttpSession对象更加简洁高效
  • 适合从会话中获取已知属性(如用户标识、权限等)
  • 注意:在分布式系统中使用Session需要特别考虑会话同步问题

# 10. 使用@DateTimeFormat注解处理日期参数

注解功能:@DateTimeFormat注解用于定义日期字符串的解析格式,将前端传递的日期字符串转换为Java日期对象。

重要配置参数:

  • pattern:指定日期格式模式,如yyyy-MM-dd、yyyy-MM-dd HH:mm:ss等

前端请求示例:

// 发送包含日期参数的GET请求
axios.get('/api/getUserByDate', {
  params: {
    birthDate: '2000-01-15'  // 日期格式为yyyy-MM-dd
  }
})
.then(response => {
  console.log('按出生日期查询结果:', response.data);
})
.catch(error => {
  console.error('查询失败:', error);
});
1
2
3
4
5
6
7
8
9
10
11
12

后端接收日期参数示例:

@RestController
@RequestMapping("/api")
public class UserController {

    @GetMapping("/getUserByDate")
    public ResponseEntity<String> getUserByDate(
            @RequestParam("birthDate") 
            @DateTimeFormat(pattern = "yyyy-MM-dd") Date birthDate  // 指定日期格式并转换为Date对象
    ) {
        // 日期格式化工具,用于格式化输出
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        
        // 使用日期参数查询用户(示例中简化为直接返回日期信息)
        String response = "已接收出生日期参数: " + sdf.format(birthDate) + 
                         "\n查询结果: 找到5名用户出生于该日期";
        
        // 返回响应结果
        return ResponseEntity.ok(response);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

关键点说明:

  • @DateTimeFormat注解需要与参数注解(如@RequestParam)一起使用
  • pattern属性定义了日期字符串的预期格式
  • 如果前端传递的日期格式与指定的pattern不匹配,会发生解析错误
  • 支持各种日期时间格式,可以精确到年月日或精确到毫秒
  • 适用于GET请求中的查询参数、表单字段等

# 11. 在对象属性中使用@DateTimeFormat注解处理日期

功能说明:当Java对象中包含日期类型属性时,可以在属性上使用@DateTimeFormat注解来指定日期格式,使Spring能够正确解析前端传来的日期字符串。

前端请求示例:

// 发送包含日期字段的JSON数据
axios.post('/api/saveUser', {
  userName: '张三',
  birthDate: '2000-01-15',  // 日期格式为yyyy-MM-dd
  registrationTime: '2023-08-17 14:30:00'  // 日期时间格式为yyyy-MM-dd HH:mm:ss
})
.then(response => {
  console.log('用户保存成功:', response.data);
})
.catch(error => {
  console.error('用户保存失败:', error);
});
1
2
3
4
5
6
7
8
9
10
11
12

后端对象和接收示例:

// 用户数据模型类
class User {
    private String userName;  // 用户名
    
    @DateTimeFormat(pattern = "yyyy-MM-dd")  // 指定日期格式
    private Date birthDate;   // 出生日期
    
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")  // 指定日期时间格式
    private Date registrationTime;  // 注册时间
    
    // Getter和Setter方法(必须提供)
    public String getUserName() {
        return userName;
    }
    
    public void setUserName(String userName) {
        this.userName = userName;
    }
    
    public Date getBirthDate() {
        return birthDate;
    }
    
    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }
    
    public Date getRegistrationTime() {
        return registrationTime;
    }
    
    public void setRegistrationTime(Date registrationTime) {
        this.registrationTime = registrationTime;
    }
}

@RestController
@RequestMapping("/api")
public class UserController {

    @PostMapping("/saveUser")
    public ResponseEntity<String> saveUser(@RequestBody User user) {
        // 日期格式化工具
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        
        // 构建响应信息
        StringBuilder response = new StringBuilder("用户信息保存成功:\n");
        response.append("- 用户名: ").append(user.getUserName()).append("\n");
        
        // 格式化输出日期
        if (user.getBirthDate() != null) {
            response.append("- 出生日期: ").append(dateFormat.format(user.getBirthDate())).append("\n");
        }
        
        // 格式化输出日期时间
        if (user.getRegistrationTime() != null) {
            response.append("- 注册时间: ").append(dateTimeFormat.format(user.getRegistrationTime())).append("\n");
        }
        
        // 返回响应
        return ResponseEntity.ok(response.toString());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

关键点说明:

  • 在实体类的日期属性上直接使用@DateTimeFormat注解
  • 每个日期属性可以指定不同的格式模式
  • 当使用@RequestBody接收JSON数据时,Spring会根据注解自动解析日期字符串
  • Java 8中也可以使用LocalDate、LocalDateTime等新日期API类型
  • 前端必须确保发送的日期格式与后端定义的格式一致

# 12. 接收数组或集合类型参数

# 前端发送数组或集合参数

注解功能:Spring MVC支持接收数组或集合类型的参数,可以通过URL查询参数或JSON数据传递。

前端GET请求发送数组示例:

// 使用GET请求发送数组参数(查询参数形式)
axios.get('/api/getItems', {
  params: {
    ids: [1, 2, 3, 4, 5]  // 数组参数
  }
})
.then(response => {
  console.log('查询结果:', response.data);
})
.catch(error => {
  console.error('查询失败:', error);
});

// 实际发送的URL:/api/getItems?ids=1&ids=2&ids=3&ids=4&ids=5
1
2
3
4
5
6
7
8
9
10
11
12
13
14

前端POST请求发送数组示例:

// 使用POST请求发送包含数组的JSON数据
axios.post('/api/saveItems', {
  ids: [1, 2, 3, 4, 5],  // 数字数组
  tags: ['促销', '新品', '限时'],  // 字符串数组
  name: '商品批量操作'  // 普通字段
})
.then(response => {
  console.log('保存成功:', response.data);
})
.catch(error => {
  console.error('保存失败:', error);
});
1
2
3
4
5
6
7
8
9
10
11
12

# 后端接收数组或集合参数

1. 使用@RequestParam接收GET请求中的数组参数

@RestController
@RequestMapping("/api")
public class ItemController {

    @GetMapping("/getItems")
    public ResponseEntity<String> getItems(
            @RequestParam List<Integer> ids  // 直接接收数组参数为List<Integer>
    ) {
        // 检查参数是否为空
        if (ids == null || ids.isEmpty()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body("请至少提供一个商品ID");
        }
        
        // 构建响应数据(实际应用中通常会查询数据库)
        StringBuilder response = new StringBuilder("根据ID查询到以下商品:\n");
        
        for (Integer id : ids) {
            response.append("- ID: ").append(id)
                   .append(", 商品名称: 商品").append(id)
                   .append(", 价格: ").append(id * 10).append(".00元\n");
        }
        
        // 返回响应结果
        return ResponseEntity.ok(response.toString());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

2. 使用@RequestBody接收POST请求中的数组或集合参数

@RestController
@RequestMapping("/api")
public class ItemController {

    @PostMapping("/saveItems")
    public ResponseEntity<String> saveItems(
            @RequestBody ItemBatchOperation operation  // 接收整个JSON对象
    ) {
        // 验证数据
        if (operation.getIds() == null || operation.getIds().isEmpty()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body("请至少提供一个商品ID");
        }
        
        // 构建响应信息
        StringBuilder response = new StringBuilder("批量操作成功:\n");
        response.append("- 操作名称: ").append(operation.getName()).append("\n");
        response.append("- 处理的商品ID: ").append(operation.getIds()).append("\n");
        
        // 如果有标签,也添加到响应中
        if (operation.getTags() != null && !operation.getTags().isEmpty()) {
            response.append("- 应用的标签: ").append(operation.getTags()).append("\n");
        }
        
        // 返回操作结果
        return ResponseEntity.ok(response.toString());
    }
}

// 接收批量操作数据的模型类
class ItemBatchOperation {
    private List<Integer> ids;      // 商品ID列表
    private List<String> tags;      // 标签列表
    private String name;            // 操作名称
    
    // Getter和Setter方法
    public List<Integer> getIds() {
        return ids;
    }
    
    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
    
    public List<String> getTags() {
        return tags;
    }
    
    public void setTags(List<String> tags) {
        this.tags = tags;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

3. 直接接收数组类型参数

除了使用集合类型外,也可以直接使用数组类型接收参数:

@RestController
@RequestMapping("/api")
public class ItemController {

    @GetMapping("/getItemsByArray")
    public ResponseEntity<String> getItemsByArray(
            @RequestParam Integer[] ids  // 使用数组而非List接收参数
    ) {
        // 检查参数
        if (ids == null || ids.length == 0) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body("请至少提供一个商品ID");
        }
        
        // 构建响应
        StringBuilder response = new StringBuilder("使用数组接收到以下ID:\n");
        for (Integer id : ids) {
            response.append("- ").append(id).append("\n");
        }
        
        return ResponseEntity.ok(response.toString());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

数组与集合参数处理要点

  1. GET请求中的数组参数:
    • 前端:Axios会自动将数组参数格式化为形如?ids=1&ids=2&ids=3的查询字符串
    • 后端:可以使用List<T>或T[]接收,Spring会自动进行类型转换
  2. POST请求中的JSON数组:
    • 前端:直接在JSON对象中包含数组字段
    • 后端:使用@RequestBody将整个JSON反序列化为对象,对象中使用List<T>或T[]接收数组字段
  3. 类型转换:
    • Spring会自动尝试将字符串转换为目标类型(整数、日期等)
    • 转换失败会导致请求错误,应妥善处理异常
  4. 空值处理:
    • 应检查接收到的数组或集合是否为空,并给出适当的响应
编辑此页 (opens new window)
上次更新: 2025/03/21, 11:11:36
SpringMVC 入门
Spring MVC 数据返回

← SpringMVC 入门 Spring MVC 数据返回→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式