第三期:深入理解 Spring Web MVC [特殊字符](数据传参+ 特殊字符处理 + 编码问题解析)
✨前言:传参和状态管理,看似简单其实门道不少
在 Web 开发中,前端和后端最核心的交流方式就是“传参”,而“传参”除了涉及如何写代码获取参数,还藏着很多开发者容易忽略的细节:
-
为什么 URL 带了中文,后端拿到是乱码?
-
@PathVariable
和@RequestParam
到底怎么选? -
前端传 数据(#),后端拿不到值怎么办?
-
用户登录后,我要怎么“记住”他?
-
Cookie 和 Session 有啥区别,怎么用才优雅?
这些问题都是你在 Spring MVC 实战中一定会遇到的!本篇内容就是为了解决这些“看起来简单,实际容易踩坑”的问题。
📌 本期我们将系统讲解以下几个关键点:
-
多种传参方式(GET、POST、Path、JSON)
-
中文、空格、特殊字符(
# % & +
)等处理方式 -
如何在 Spring MVC 中正确获取和管理 Cookie/Session
不仅让你学会“怎么用”,还帮你彻底搞懂“为什么这样用”。
📎 适合人群:
-
初学 Spring MVC 的小伙伴
-
使用前后端分离开发时遇到参数/状态问题的开发者
-
想彻底理解请求细节、编码和状态管理原理的同学、
🧭 第一章:Spring MVC 中的多种数据传参方式
前后端交互的核心是“请求—响应”,而传参方式直接决定了后端能否正确拿到前端发送的数据。Spring MVC 支持多种传参方式,每种方式都各有使用场景和注意事项。
🔹 1.1 Query 参数(GET 请求)
在 Web 开发中,最常见的请求类型之一就是 GET 请求,用于向后端“索取资源”。GET 请求通常会将参数拼接在 URL 的末尾,形式如下:
/search?keyword=java&page=1
这类参数就叫做 Query 参数,也称为 URL 查询参数。
✅ 使用 @RequestParam
获取参数
Spring MVC 中可以使用 @RequestParam
注解来接收 GET 请求的参数。
@GetMapping("/search")
public String search(@RequestParam("keyword") String keyword,@RequestParam("page") int page) {System.out.println("搜索关键词:" + keyword + ",页码:" + page);return "searchResult";
}
如果你访问:
http://localhost:8080/search?keyword=springmvc&page=2
控制台输出将会是:
搜索关键词:springmvc,页码:2
🛠️ 默认值 & 是否必传配置
有些参数可能不是必传的。比如分页的 page
参数,默认展示第一页。这时候可以设置参数为可选,并给一个默认值:
@GetMapping("/search")
public String search(@RequestParam(defaultValue = "spring") String keyword,@RequestParam(required = false, defaultValue = "1") int page) {System.out.println("搜索关键词:" + keyword + ",页码:" + page);return "searchResult";
}
解释:
-
required = false
:表示这个参数不是必须要传的。 -
defaultValue = "..."
:如果参数没有传,则使用默认值。
🔍 小细节提示:
-
@RequestParam
不区分 GET/POST,本质上是从参数中提取数据。 -
如果你传的是数组/列表,可以直接使用
List<String>
或String[]
接收。
@GetMapping("/tags")
public String tags(@RequestParam List<String> tag) {// /tags?tag=java&tag=spring&tag=webSystem.out.println(tag); // [java, spring, web]return "tagList";
}
🔹 1.2 传递参数(POST 请求)
✅传递单个参数
接收单个参数,在SpringMVC中直接⽤⽅法中的参数就可以,⽐如以下代码:
@RequestMapping("/user")
public class user {@RequestMapping("/m1")public String m1(String name) {return "接受参数name"+ name;}
}
咱们使⽤浏览器发送请求并传参
http://127.0.0.1:8080/user/m1?name=spring
可以看到,后端程序正确拿到了name参数的值.
SpringMVC会根据⽅法的参数名,找到对应的参数,赋值给⽅法
如果参数不⼀致,是获取不到参数的.
⽐如请求URL:http://127.0.0.1:8080/user/m1?name1=spring
注意事项
使⽤基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误 类型不匹配时,会报400错误
@RequestMapping("/age")public String age(int age) {return "接受的数字为age "+ age;}
1. 正常传递参数
http://127.0.0.1:8080/user/age?age=1
浏览器响应情况:
通过Fiddler观察请求和响应,HTTP响应状态码为200,Content-Type 为text/html
2. 不传递age参数
http://127.0.0.1:8080/user/age
浏览器响应情况:
通过Fiddler观察请求和响应,HTTP响应状态码为500
3. 传递参数类型不匹配
http://127.0.0.1:8080/user/age?age=abc
浏览器响应情况:
通过Fiddler观察请求和响应, HTTP响应状态码为400
对于包装类型,如果不传对应参数,Spring接收到的数据则为null
所以企业开发中,对于参数可能为空的数据,建议使⽤包装类型
✅传递多个参数
和接收单个参数⼀样,直接使⽤⽅法的参数接收即可.使⽤多个形参.
@RequestMapping("/m2")public String m2(String name,String password) {return "返回的参数 + name" + name +" password" + password;}
使⽤浏览器发送请求并传参:http://127.0.0.1:8080/user/m2?name=zhangsan&password=123456
可以看到,后端程序正确拿到了name和password参数的值
当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置是不影响后 端获取参数的结果.
⽐如访问:http://127.0.0.1:8080/user/m2?password=123456&name=zhangsan
✅传递对象
如果参数⽐较多时,⽅法声明就需要有很多形参.并且后续每次新增⼀个参数,也需要修改⽅法声明. 我们不妨把这些参数封装为⼀个对象.
SpringMVC也可以⾃动实现对象参数的赋值
@RequestMapping("/m3")public String m3(Info info) {return info.toString();}
package com.example.demo;public class Info {private String user;public String getPassword() {return password;}@Overridepublic String toString() {return "Info{" +"user='" + user + '\'' +", password='" + password + '\'' +", age=" + age +'}';}public void setPassword(String password) {this.password = password;}public String getUser() {return user;}public void setUser(String user) {this.user = user;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}private String password;private int age;
}
使⽤浏览器发送请求并传参: http://127.0.0.1:8080/user/m3?age=5&name=zhangsan&password=123456
可以看到,后端程序正确拿到了Info对象⾥各个属性的值
✅传递数组
SpringMVC可以⾃动绑定数组参数的赋值
后端实现代码:
@RequestMapping("/m5")
public String method5(String[] arrayParam) {return Arrays.toString(arrayParam);
}
使⽤浏览器发送请求并传参:
数组参数:请求参数名与形参数组名称相同且请求参数为多个,后端定义数组类型形参即可接收参数
http://127.0.0.1:8080/param/m5?arrayParam=zhangsan&arrayParam=lisi&arrayParam=wangwu
或者使⽤http://127.0.0.1:8080/param/m6?listParam=zhangsan%2clisi%2cwangwu
浏览器响应结果:
✅传递集合
集合参数:和数组类似,同⼀个请求参数名有为多个,且需要使⽤@RequestParam 绑定参数关系
默认情况下,请求中参数名相同的多个值,是封装到数组.如果要封装到集合,要使⽤ @RequestParam 绑定参数关系
请求⽅式和数组类似:
浏览器传参:
⽅式⼀:http://127.0.0.1:8080/param/m6?listParam=zhangsan&listParam=lisi&listParam=wangwu
⽅式⼆:http://127.0.0.1:8080/param/m6?listParam=zhangsan%2clisi%2cwangwu
%2c是逗号的转义编码,解码后的url为:http://127.0.0.1:8080/param/m6?listParam=zhangsan,lisi,wangwu
后端接收代码:
@RequestMapping("/m6")
public String method6(@RequestParam List<String> listParam){return "size:"+listParam.size() + ",listParam:"+listParam;
}
✅传递JSON数据
好的,这里我们来专门总结一下如何在 Spring MVC 中传递 JSON 数据(即:前端 → 后端)以及后端如何正确解析这些 JSON 请求。非常适合初学者掌握前后端分离接口开发的基础。
在前后端分离开发中,前端通常使用 fetch
、axios
、jQuery.ajax
等方式向后端发送 JSON 数据,而不是传统的表单提交。Spring MVC 提供了强大的机制来处理这些 JSON 请求。
1.2.1 前端如何发送 JSON 数据
使用 fetch
示例(原生 JS):
fetch("/api/user", {method: "POST",headers: {"Content-Type": "application/json"},body: JSON.stringify({username: "jack",password: "123456"})
});
使用 axios
示例:
axios.post("/api/user", {username: "jack",password: "123456"
});
关键点:
-
必须设置请求头
Content-Type: application/json
-
body
或data
是一个 JSON 对象(会被序列化成字符串)
1.2.2 后端 Spring MVC 接收 JSON 数据
后端通过 @RequestBody
注解来接收请求体中的 JSON 数据,并将其绑定到一个 Java 对象。
示例 Controller:
@RestController
@RequestMapping("/api")
public class UserController {@PostMapping("/user")public String createUser(@RequestBody User user) {System.out.println("用户名:" + user.getUsername());System.out.println("密码:" + user.getPassword());return "用户创建成功";}
}
示例实体类:
public class User {private String username;private String password;// Getter & Setter
}
⚠️ 注意:使用
@RequestBody
表示数据是从 请求体中提取 的,不能再用来接收 URL 参数或表单字段。
1.2.3 常见问题排查
问题 | 可能原因 |
---|---|
接收不到数据 | 前端请求头没设置 Content-Type: application/json |
报错 HttpMessageNotReadableException | 请求体不是合法 JSON 或字段不匹配 |
校验不生效 | 忘了加 @Valid 或 @Validated |
返回乱码 | 没设置响应编码或响应类型 |
1.2.4 结合参数校验(推荐)
可以在实体类中添加注解如 @NotBlank
、@Size
,然后在 Controller 中使用 @Valid
自动进行参数校验:
@PostMapping("/user")
public String createUser(@Valid @RequestBody User user, BindingResult result) {if (result.hasErrors()) {return "参数错误:" + result.getFieldError().getDefaultMessage();}return "用户创建成功";
}
1.2.5 返回 JSON 数据给前端
可以直接返回一个对象,Spring 会自动将其转为 JSON(前提是使用了 @RestController
或方法上加了 @ResponseBody
):
@PostMapping("/user")
public User createUser(@RequestBody User user) {user.setUsername(user.getUsername().toUpperCase());return user;
}
1.2.6 JSON字符串 和 Java对象的互相转换(Jackson)
Spring MVC(尤其是 Spring Boot)默认集成了 Jackson 作为 JSON 解析器,支持 Java 对象和 JSON 字符串之间的自动转换。
1.2.6.1 Java 对象 ➡️ JSON 字符串
使用 ObjectMapper
(Jackson 提供)进行对象序列化:
import com.fasterxml.jackson.databind.ObjectMapper;public class JsonDemo {public static void main(String[] args) throws Exception {User user = new User();user.setUsername("Alice");user.setPassword("123456");ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(user);System.out.println("JSON 字符串:" + json);}
}
🧾 输出示例:
{"username":"Alice","password":"123456"}
1.2.6.2 JSON 字符串 ➡️ Java 对象
使用 ObjectMapper.readValue()
将 JSON 字符串反序列化成 Java 对象:
String json = "{\"username\":\"Bob\",\"password\":\"654321\"}";
User user = mapper.readValue(json, User.class);System.out.println("用户名:" + user.getUsername());
1.2.6.3 List / Map 类型转换
JSON 数组转为 List:
String json = "[{\"username\":\"Tom\"},{\"username\":\"Jerry\"}]";
List<User> users = mapper.readValue(json, new TypeReference<List<User>>() {});
JSON 对象转为 Map:
String json = "{\"id\":1,\"name\":\"Java\"}";
Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {});
1.2.6.4 自定义 ObjectMapper(可选)
你可以自定义 ObjectMapper
来格式化输出、修改时间格式、字段命名等:
@Bean
public ObjectMapper objectMapper() {ObjectMapper mapper = new ObjectMapper();mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);return mapper;
}
🔚 总结
操作 | 工具 | 注解 |
---|---|---|
前端发送 JSON | fetch / axios | 设置 Content-Type: application/json |
后端接收 JSON | Spring MVC | @RequestBody |
参数校验 | JSR-303 | @Valid + BindingResult |
返回 JSON | Spring Boot / MVC | @ResponseBody 或 @RestController |
类型 | 方法 |
---|---|
Java ➡️ JSON | mapper.writeValueAsString(obj) |
JSON ➡️ Java | mapper.readValue(json, Class.class) |
自动处理 | 使用 @RequestBody / @ResponseBody |
常用库 | Jackson(Spring 默认)、Gson、Fastjson(需手动集成) |
🔹 1.3 路径参数(REST 风格)
随着 RESTful API 的流行,很多接口不再使用传统的 Query 参数来传值,而是将参数嵌入在 URL 路径中,以表达资源之间的关系:
GET /user/1001
GET /order/1001/items/5001
Spring MVC 通过 @PathVariable
注解,可以轻松提取路径中的动态参数。
✅ 使用 @PathVariable
获取单个参数
@GetMapping("/user/{id}")
public String getUser(@PathVariable("id") Long userId) {System.out.println("获取用户ID:" + userId);return "userDetail";
}
✨ 说明:
-
{id}
是路径中的占位符,实际访问时用具体数字或字符串替代。 -
@PathVariable("id")
中的"id"
要和 URL 中的{id}
一致。 -
如果参数名和占位符相同,可以简写为:
@GetMapping("/user/{id}")
public String getUser(@PathVariable Long id) {return "userDetail";
}
✅ 绑定多个路径参数
当路径中包含多个动态段时,可以绑定多个参数:
@GetMapping("/order/{userId}/item/{itemId}")
public String getOrderItem(@PathVariable Long userId,@PathVariable Long itemId) {System.out.println("用户ID:" + userId + ",商品ID:" + itemId);return "orderItemDetail";
}
访问 URL 示例:
/order/2001/item/888
控制台输出:
用户ID:2001,商品ID:888
🔍 常见用法拓展:
✅ 路径参数 + Query 参数组合使用:
@GetMapping("/product/{id}")
public String getProduct(@PathVariable Long id,@RequestParam(defaultValue = "1") int page) {// 访问 /product/10?page=2System.out.println("商品ID:" + id + ",评论页码:" + page);return "productDetail";
}
🧱 小结:
特性 | @PathVariable |
---|---|
来源 | URL 路径 |
类型支持 | 数字、字符串、UUID 等 |
常用于 | RESTful 风格接口 |
可与其他注解混用 | ✅ 支持与 @RequestParam 、@RequestBody 一起使用 |
🔹1.4 文件上传:使用 @RequestPart
接收文件 & JSON
在实际开发中,经常会遇到这样的需求:前端上传一个文件,同时还需要提交一些 JSON 格式的表单数据。这时候,我们就可以使用:
-
@RequestPart
接收 Multipart 表单中的文件和 JSON 字段 -
MultipartFile
类型接收上传的文件
✅ 示例:上传头像 + 用户资料
前端发送一个包含文件和 JSON 的 multipart 请求(Content-Type: multipart/form-data
)
💡 控制器:
@RestController
@RequestMapping("/api")
public class UploadController {@PostMapping("/upload")public String uploadUserInfo(@RequestPart("file") MultipartFile file,@RequestPart("user") User user) throws IOException {System.out.println("接收到用户:" + user.getUsername());System.out.println("上传文件名:" + file.getOriginalFilename());return "上传成功";}
}
🧾 示例实体类:
public class User {private String username;private String email;// Getter & Setter
}
✅ 前端请求示例(使用 JavaScript + fetch + FormData):
const formData = new FormData();
formData.append("file", document.querySelector("#fileInput").files[0]);
formData.append("user", new Blob([JSON.stringify({username: "alice",email: "alice@example.com"})
], { type: "application/json" }));fetch("/api/upload", {method: "POST",body: formData
});
✅ 请求格式说明
-
file
是文件上传字段,对应MultipartFile
-
user
是一个 JSON 字符串包装成的 Blob,对应@RequestPart("user")
自动反序列化为 Java 对象 -
请求头 不需要设置
Content-Type
,浏览器会自动生成multipart/form-data
并带上 boundary。
✅ 注意事项
问题 | 说明 |
---|---|
JSON 必须为 Blob 类型 | 如果直接 append JSON 字符串,会作为普通字段而不是 part |
不可使用 @RequestParam 接 JSON | @RequestParam 只能接简单类型或文件,无法处理复杂 JSON |
请求方式必须是 multipart/form-data | 否则文件不会被正确识别 |
✅ 配置文件大小限制(Spring Boot 示例)
在 application.properties
或 application.yml
中设置上传限制:
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=20MB
🧱 小结
内容 | 注解 | 类型 |
---|---|---|
文件上传 | @RequestPart("file") | MultipartFile |
JSON 数据 | @RequestPart("user") | Java 对象 |
普通字段 | @RequestParam("name") | String / 基本类型 |
请求类型 | multipart/form-data | 浏览器自动生成 |
👣 到此,我们已经覆盖了多种常见的数据传参方式:
-
Query 参数:使用
@RequestParam
从 URL 中获取查询参数。 -
表单参数:通过
@ModelAttribute
获取表单数据,并结合BindingResult
进行校验。 -
路径参数:使用
@PathVariable
从 URL 路径中提取参数。 -
JSON 请求体:通过
@RequestBody
获取前端传来的 JSON 数据,并可与数据校验结合使用。
第二章:特殊字符处理 & 编码问题解析
、
当然可以!这是 2.1 常见特殊字符 的详细讲解,适用于博客中“Spring MVC 数据传参中的特殊字符处理”章节 ✅
🔹 2.1 常见特殊字符解析(中文、空格、#、% 等)
在使用 Spring MVC 开发 Web 接口时,我们经常会通过 URL 传递参数,例如:
http://localhost:8080/search?name=张三#abc
但是,如果参数中包含 中文、空格、#、%、&、= 等特殊字符,就可能出现参数截断、乱码、无法接收等问题。了解这些字符在 URL 中的表现和解决方法非常关键。
✅ 一、特殊字符的常见类型
字符 | 描述 | 问题 |
---|---|---|
中文 | 非 ASCII 字符 | 会出现乱码 |
空格 | 空白字符 | 会变成 + 或 %20 |
# | 锚点符号 | 浏览器不传给服务器 |
% | 转义符号开头 | 若不正确使用会解析失败 |
& | 参数分隔符 | 用于多个参数 |
= | 参数赋值符号 | 不能出现在值中 |
? | 查询字符串开始 | 只能出现一次 |
✅ 二、示例问题分析
请求示例:
/search?name=张三#abc
实际情况:
-
浏览器会 截断
#
后的内容,它认为#abc
是页面锚点,不会发送到后端。 -
后端接收到的请求其实是:
/search?name=张三
-
如果没编码,Spring MVC 控制器中打印参数会变成乱码(如
å¼ ä¸‰
)
✅ 三、如何解决?
1. 对 URL 进行 URL 编码(encode)
-
使用前端 JS 或其他工具对参数进行编码:
const name = encodeURIComponent("张三#abc");
// 结果:%E5%BC%A0%E4%B8%89%23abc
-
发送请求时变成:
/search?name=%E5%BC%A0%E4%B8%89%23abc
-
后端接收到参数后自动解码
2. Spring MVC 端设置编码(避免乱码)
-
如果是 Spring Boot,在
application.properties
中添加:
spring.http.encoding.enabled=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.force=true
3. 使用过滤器统一设置编码(传统 Spring MVC)
public class EncodingFilter implements Filter {public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");chain.doFilter(request, response);}
}
✅ 四、常见特殊字符编码表
字符 | 编码 |
---|---|
空格 | %20 或 + |
中文 | %E5%BC%A0%E4%B8%89 (张三) |
# | %23 |
% | %25 |
& | %26 |
= | %3D |
✅ 五、后端示例(使用 @RequestParam 接收参数)
@GetMapping("/search")
public String search(@RequestParam("name") String name) {System.out.println("接收到参数 name = " + name);return "ok";
}
若前端发送的是未经编码的中文或特殊字符,控制器可能会收到乱码或不完整内容。通过前端 encodeURIComponent()
编码 + 后端统一 UTF-8 解码即可避免这些问题。
✅ 六、测试建议
测试内容 | 预期结果 |
---|---|
/search?name=张三 | 后端接收到 “张三” |
/search?name=张三#abc | 实际只收到 “张三” |
/search?name=%E5%BC%A0%E4%B8%89%23abc | 后端接收到 “张三#abc” |
🔹2.2 GET 请求中的编码问题解析(%20、+、%23 的区别)
在 Web 开发中,GET 请求的参数直接拼接在 URL 中。当 URL 包含中文、空格或特殊字符时,浏览器和服务器之间的编码解码处理就变得非常关键。
✅ 一、浏览器对 URL 的自动编码行为
浏览器会自动对 URL 中 非 ASCII 字符 和 部分特殊字符 进行编码,例如:
/search?keyword=Java 编码
浏览器实际发送请求时,会自动将其编码为:
/search?keyword=Java%20%E7%BC%96%E7%A0%81
-
中文“编码” →
%E7%BC%96%E7%A0%81
-
空格 →
%20
(或有些场景中为+
)
✅ 二、Spring MVC 如何解析这些编码
Spring MVC 默认使用 UTF-8 对 URL 进行解码(如果配置正确),即:
@GetMapping("/search")
public String search(@RequestParam String keyword) {System.out.println("关键词:" + keyword);return "ok";
}
请求 /search?keyword=Java%20%E7%BC%96%E7%A0%81
后端接收到的参数会被正确解析为:
Java 编码
✅ 所以只要前端编码正确,Spring 后端是可以自动解析的。
✅ 三、重点区别:%20
vs +
vs %23
表达形式 | 代表含义 | 用途说明 |
---|---|---|
%20 | 空格(编码) | URL 中最标准的空格编码方式 |
+ | 空格(表单风格) | 仅适用于 application/x-www-form-urlencoded 表单编码 |
%23 | # 字符本身 | 因为 # 是锚点标记,需转义才能被服务器接收到 |
示例解析:
-
/search?kw=A%20B
→A B
✅ -
/search?kw=A+B
→A B
✅(但依赖解码器行为) -
/search?kw=A%2BB
→A+B
✅(如果真要传+
本身) -
/search?kw=A#B
→ 浏览器只会发送A
,不会包含#B
-
/search?kw=A%23B
→ 后端会收到A#B
✅ 四、如何避免乱码和错误
场景 | 建议处理 |
---|---|
中文参数 | 使用 encodeURIComponent 编码 |
空格 | 推荐使用 %20 而非 + (更标准) |
# 符号 | 必须编码为 %23 |
后端乱码 | 确保 Spring Boot 配置了 UTF-8 解码(默认已支持) |
Spring Boot 配置参考:
spring.servlet.encoding.charset=UTF-8
spring.servlet.encoding.enabled=true
spring.servlet.encoding.force=true
✅ 五、简单测试表格
原始字符 | URL 编码 | 解码结果(Spring) |
---|---|---|
空格 | %20 | 空格 |
空格 | + | 空格(表单风格) |
+ | %2B | + |
# | %23 | # |
中文“张三” | %E5%BC%A0%E4%B8%89 | 张三 |
🧪 示例 Controller 方法(用于调试测试):
@GetMapping("/test")
public String test(@RequestParam String value) {return "收到参数:" + value;
}
可以测试这些 URL:
/test?value=A%20B
/test?value=A+B
/test?value=A%2BB
/test?value=A%23B
✅六 URL 编码常见字符对照表(开发必备小抄)
字符原文 | 编码后 | 解码结果 | 说明 |
---|---|---|---|
空格(半角) | %20 | 空格 | 推荐使用 %20 表示空格 |
空格(表单场景) | + | 空格 | 仅在 x-www-form-urlencoded 中解析为空格 |
加号 + | %2B | + | 若想传“+”本身,必须使用 %2B |
井号 # | %23 | # | 避免被浏览器视为锚点 |
中文 “张三” | %E5%BC%A0%E4%B8%89 | 张三 | 需要 UTF-8 编码 |
百分号 % | %25 | % | 编码开头符号自身的转义 |
与号 & | %26 | & | 避免作为参数分隔符 |
等号 = | %3D | = | 避免参数赋值误解析 |
✅ 建议用
encodeURIComponent()
对所有参数值进行编码,避免问题。
🔸 前端 JS 测试代码(复制即可用)
这是一个简单的前端测试页面,能快速测试各种字符编码的行为:
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>GET 编码测试</title>
</head>
<body><h2>GET 参数编码测试</h2><input type="text" id="input" placeholder="输入内容,如:张三 + # & = 空格"><button onclick="sendRequest()">测试请求</button><p id="result"></p><script>function sendRequest() {const raw = document.getElementById("input").value;const encoded = encodeURIComponent(raw);const url = `/test?value=${encoded}`;fetch(url).then(res => res.text()).then(res => {document.getElementById("result").innerText = "服务端返回: " + res;});}</script>
</body>
</html>
🔸 Spring Boot Controller 示例代码(配合前端测试)
@RestController
public class EncodingTestController {@GetMapping("/test")public String test(@RequestParam String value) {return "服务端收到参数:" + value;}
}
🔸 实际测试示例
输入 | 实际请求 URL | 后端收到 |
---|---|---|
张三 | /test?value=%E5%BC%A0%E4%B8%89 | 张三 |
A B | /test?value=A%20B | A B |
A+B | /test?value=A%2BB | A+B |
A#B | /test?value=A%23B | A#B |
%25 | /test?value=%2525 | %25 |
✅ 小贴士
-
永远不要手动拼接 URL 参数,使用
encodeURIComponent()
-
浏览器不会发送
#
后的内容,必须提前编码为%23
-
表单提交推荐用
POST
,GET 仅用于短、简单的查询参数
🔸 2.3 POST 请求中的编码设置(CharacterEncodingFilter 全解析)
虽然 GET 请求中浏览器会自动进行 URL 编码,但在 POST 请求中,请求体的数据编码依赖客户端和服务端的配置是否匹配,否则会出现中文乱码等问题。
✅ 一、为什么 POST 请求容易出现编码问题?
-
GET 请求参数放在 URL 中,浏览器会自动进行 UTF-8 编码。
-
POST 请求的参数通常放在 请求体 body 中,如表单数据、JSON 数据等。
-
若服务端未正确设置编码方式,则无法按预期解析参数,例如表单提交中文可能乱码。
✅ 二、传统 Spring MVC 中的解决方案:CharacterEncodingFilter
在不使用 Spring Boot 的老项目中,开发者必须手动配置字符编码过滤器 CharacterEncodingFilter
,否则 Spring MVC 默认使用 ISO-8859-1 解码表单参数,导致乱码。
示例配置方式(web.xml):
<filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param>
</filter>
<filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
或使用 Java Config:
@Bean
public FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilter() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");filter.setForceEncoding(true);FilterRegistrationBean<CharacterEncodingFilter> bean = new FilterRegistrationBean<>(filter);bean.setOrder(Ordered.HIGHEST_PRECEDENCE);return bean;
}
✅ 三、Spring Boot 的自动配置(默认已支持)
Spring Boot 已经默认为你配置好了 CharacterEncodingFilter
,你只需确保配置项存在即可:
application.properties 中配置:
spring.servlet.encoding.enabled=true
spring.servlet.encoding.charset=UTF-8
spring.servlet.encoding.force=true
这些配置会自动启用 CharacterEncodingFilter
,确保所有请求(包括 POST 表单)都使用 UTF-8 编码。
✅ 四、实测对比如下:
场景 | 是否乱码 | 原因 |
---|---|---|
Spring MVC 未配置编码 | ❌乱码 | 默认使用 ISO-8859-1 解码 |
手动添加 CharacterEncodingFilter | ✅正常 | 统一使用 UTF-8 |
Spring Boot 默认配置 | ✅正常 | 自动注入编码过滤器 |
Spring Boot 配置关闭 encoding.enabled=false | ❌乱码 | 无过滤器生效 |
✅ 五、编码生效的两个关键点
条件 | 说明 |
---|---|
CharacterEncodingFilter.forceEncoding=true | 强制使用你设置的编码解析请求体 |
客户端 Content-Type 正确 | 表单应为 application/x-www-form-urlencoded; charset=UTF-8 ,JSON 为 application/json; charset=UTF-8 |
✅ 六、示例控制器验证 POST 编码
@PostMapping("/submit")
public String submit(@RequestParam String name) {System.out.println("接收到 name = " + name);return "ok";
}
使用表单或 Postman 发送中文数据,可以观察是否成功接收。
✅ 总结一句话:
GET 编码靠浏览器自动,POST 编码必须服务端主动设定;用 Spring Boot 就别怕,它自动帮你搞定!
📷 POST 中文乱码演示(Postman 测试案例)
我们用一个简单的 Spring MVC 控制器来测试:
✅ 控制器代码
@RestController
public class PostTestController {@PostMapping("/submit")public String submit(@RequestParam String name) {System.out.println("收到参数 name = " + name);return "服务器已收到:" + name;}
}
📤 测试用例 1:无编码过滤器(或未设置 forceEncoding)
💬 Postman 请求设置:
-
请求方式:
POST
-
请求地址:
http://localhost:8080/submit
-
类型:
x-www-form-urlencoded
-
参数:
name=张三
-
Headers:未设置 charset
⚠️ 后台打印:
收到参数 name = ???
👉 出现乱码!因为 Spring 默认解码方式是 ISO-8859-1。
📤 测试用例 2:配置 CharacterEncodingFilter + UTF-8
✅ Spring Boot 自动配置(或你手动加上):
spring.servlet.encoding.charset=UTF-8
spring.servlet.encoding.enabled=true
spring.servlet.encoding.force=true
💬 Postman 请求相同,但 header 手动添加:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
✅ 后台打印:
收到参数 name = 张三
成功 ✅
🔸 2.4 遇到乱码怎么办?全流程排查 + 解决方案 ✅
乱码问题在 Web 开发中常见,尤其是在多语言环境、前后端交互复杂时。这里为你总结一份统一编码 + 排查方案清单,帮助你快速定位与解决乱码。
✅ 一、配置统一的字符编码过滤器(服务端核心)
在 Spring 项目中,CharacterEncodingFilter 是解决乱码的关键组件。
💡 Spring Boot 自动配置(推荐):
spring.servlet.encoding.charset=UTF-8
spring.servlet.encoding.enabled=true
spring.servlet.encoding.force=true
✔ 适用于 GET、POST、文件上传等请求
🧰 非 Spring Boot 项目(传统配置):
@Bean
public FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilter() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");filter.setForceEncoding(true);return new FilterRegistrationBean<>(filter);
}
✅ 二、IDE 配置统一编码(避免开发阶段引入乱码)
IDE 设置不对,直接导致
.java
或.html
文件保存就是乱码!
🌟 IntelliJ IDEA 设置 UTF-8:
-
File -> Settings -> Editor -> File Encodings
-
设置以下内容为
UTF-8
:-
Global Encoding
-
Project Encoding
-
Default encoding for properties files
-
Transparent native-to-ascii conversion ✔
-
✅ 三、页面文件声明编码(前端页面不能少)
对于 Thymeleaf / JSP 等后端渲染页面:
HTML 示例:
<meta charset="UTF-8">
JSP 页面开头:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
✅ 四、客户端请求编码设置(特别是 POST)
表单提交(需带 charset):
<form method="post" accept-charset="UTF-8" action="/submit">
Postman 请求 Header 添加:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
或 JSON:
Content-Type: application/json; charset=UTF-8
✅ 五、数据库连接设置编码(从根上解决保存乱码)
MySQL 示例:
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
characterEncoding=utf8
一定不要忘!
🧭 六、乱码排查流程图(逻辑全链路)
[客户端输入]↓
[前端页面编码] <— HTML charset / Content-Type↓
[请求编码方式] <— GET (URL) / POST (Body)↓
[Spring Filter: CharacterEncodingFilter]↓
[Servlet 解码]↓
[Controller 获取参数]↓
[打印日志 or 存储数据库]↓
[页面展示编码] <— View Resolver / Template Engine
✅ 七、一键 Checklist(乱码排查清单)
检查项 | 描述 | 是否完成 |
---|---|---|
页面 <meta charset="UTF-8"> | HTML 编码声明 | ✅ |
IDEA 文件保存编码 UTF-8 | 保证源码无乱码 | ✅ |
请求头中 charset=UTF-8 | Postman / Axios / Form | ✅ |
CharacterEncodingFilter 开启 | Spring Boot 自动或手动配置 | ✅ |
JSON 或表单传参编码设置 | 前后端统一 | ✅ |
数据库连接设置 UTF-8 | JDBC URL 参数 | ✅ |
✅ 小结一句话:
乱码的本质是编码-解码不一致,确保「前端 → 网络传输 → 后端 → 存储/展示」各环节使用统一编码(UTF-8)即可避免!
结语:
核心内容总结
-
数据传参方式与场景
Spring Web MVC 支持多种参数绑定方式:-
路径变量:
@PathVariable
处理 URL 中的动态参数(如/user/{id}
),需注意特殊字符(如/
,%
)需 URL 编码。 -
请求参数:
@RequestParam
获取?key=value
形式的参数,特殊字符(如&
,+
)需前端编码。 -
表单提交:通过
POST
提交,Content-Type: application/x-www-form-urlencoded
,需配置字符编码过滤器。 -
JSON 数据:
@RequestBody
接收 JSON 格式参数,默认使用 UTF-8 编码,需确保前后端编码一致。
-
-
特殊字符处理策略
-
URL 保留字符:如
#
,?
,&
需通过URLEncoder
编码(如%23
代替#
)。 -
空格与加号问题:URL 中空格默认转为
+
,后端需显式处理(如替换为%20
)。 -
JSON 转义:特殊字符(如
"
,\
)需 JSON 序列化工具(如 Jackson)自动转义。 -
数据库存储:通过预处理语句(PreparedStatement)或 ORM 框架(如 Hibernate)防止 SQL 注入。
-
-
编码问题根源与解决方案
-
乱码常见原因:
-
请求/响应未统一编码(如 GET 请求的 URI 编码与 POST 的 Body 编码不一致)。
-
Tomcat 等容器默认使用 ISO-8859-1 解码 URI。
-
-
全局编码配置:
-
添加
CharacterEncodingFilter
并设置forceEncoding=true
(UTF-8)。 -
配置 Tomcat 的
URIEncoding="UTF-8"
(server.xml
中<Connector>
节点)。
-
-
局部编码覆盖:
-
使用
String
类型接收参数后手动解码:
-
-
@RequestParam String name) {String decodedName = new String(name.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
}
实战建议
-
前端协作:
-
使用
encodeURIComponent()
对动态参数编码(如路径变量)。 -
表单提交设置
<form accept-charset="UTF-8">
。
-
-
后端防御:
-
对用户输入进行合法性校验(如正则表达式过滤非法字符)。
-
使用拦截器或 AOP 统一处理参数解码。
-
-
测试工具:
-
通过 Postman 发送含特殊字符的请求(如
%0A
换行符),观察后端日志解析结果。 -
使用 Wireshark 抓包检查原始 HTTP 请求编码。
-
结语
Spring Web MVC 的参数处理机制灵活强大,但特殊字符和编码问题往往隐藏于细节之中。理解 HTTP 协议层与框架行为的交互是解决问题的关键:从 URL 编码规则到 Servlet 容器的默认配置,再到 Spring 的过滤器链,每一步都可能成为乱码的“罪魁祸首”。通过统一全局编码、严格校验输入输出,并结合自动化测试,可以有效构建高鲁棒性的 Web 应用。
相关文章:
第三期:深入理解 Spring Web MVC [特殊字符](数据传参+ 特殊字符处理 + 编码问题解析)
✨前言:传参和状态管理,看似简单其实门道不少 在 Web 开发中,前端和后端最核心的交流方式就是“传参”,而“传参”除了涉及如何写代码获取参数,还藏着很多开发者容易忽略的细节: 为什么 URL 带了中文&…...
洛谷题单3-P1075 [NOIP 2012 普及组] 质因数分解-python-流程图重构
题目描述 已知正整数 n n n 是两个不同的质数的乘积,试求出两者中较大的那个质数。 输入格式 输入一个正整数 n n n。 输出格式 输出一个正整数 p p p,即较大的那个质数。 输入输出样例 输入 21输出 7说明/提示 1 ≤ n ≤ 2 1 0 9 1 \le n\…...
Vue组件化开发深度解析:Element UI与Ant Design Vue对比实践
一、Vue组件化开发的核心优势 1.1 组件化架构的天然优势 Vue的组件系统是其最核心的特性之一,采用单文件组件(.vue)形式,将HTML、CSS和JavaScript组合在同一个文件中,形成高内聚、低耦合的代码单元。这种设计显著提升…...
ctfshow VIP题目限免 robots后台泄露
根据题目提示是 robots后台泄露,所以我们试着访问它的后台文件 robots.txt 访问之后发现了有一个/flagishere.txt 目录文件。接着拼接访问它发现了 flag...
突破传统认知:聚类算法的底层逻辑与高阶应用全景解析
一、维度革命:重新定义聚类分析的认知边界 在人工智能的浩瀚星空中,聚类算法犹如一组精密的星际导航仪,帮助我们在无序的数据宇宙中发现隐藏的秩序。这项起源于人类本能分类需求的技术,经历了从简单分组到智能识别的蜕变…...
获取ssh密钥
git bash GitHub官网: Redirecting… ssh-keygen -t rsa -C “git账号” 出现id_rsa.pub 登录github添加 将id_rsa.pub中内容复制 点击SSH and GPG keys 点击New SSH key 起个名字 将id_rsa.pub中内容复制到这里 报错: ssh: connect to host github.com port 2…...
MINIQMT学习课程Day7
在上一篇,我们安装好xtquant,qmt以及python后,这一章,我们学习如何使用xtquant 本章学习,如何获取账号的资金使用状况。 首先,打开qmt,输入账号密码,选择独立交易。 进入交易界面&…...
`accept_ra` 和 `autoconf` 和 `forwarding` 的关系 笔记250404
accept_ra 和 autoconf 和 forwarding 的关系 笔记250404 在 Linux 的 IPv6 网络配置中,accept_ra、autoconf 和 forwarding 是三个密切相关的核心参数,它们的组合直接影响设备在网络中的角色(主机或路由器)和地址配置行为。以下是…...
leetcode数组-二分查找
题目 题目链接:https://leetcode.cn/problems/binary-search/ 文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html 视频讲解:https://www.bilibili.com/video/BV1fA4y1o715 给定一个 n 个元素有序的&…...
vector的介绍与代码演示
由于以后我们写OJ题时会经常使用到vector,所以我们必不可缺的是熟悉它的各个接口。来为我们未来作铺垫。 首先,我们了解一下: https://cplusplus.com/reference/vector/ vector的概念: 1. vector是表示可变大小数组的序列容器…...
SDK中窗口调用
存在窗口A和B的win32程序 , 当点击窗口A中的按钮后会弹出窗口B #include <windows.h>// 窗口 B 的窗口过程 LRESULT CALLBACK WindowProcB(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {switch (uMsg) {case WM_DESTROY:PostQuitMessage(0);break;default:ret…...
Web Service技术
Web Service 是一种基于网络的、分布式的技术,用于在不同的应用程序之间进行通信和数据交换。以下是关于它的详细介绍: 定义与概念 Web Service 是一种通过互联网协议(如 HTTP)提供服务的软件组件,它使用标准的 XML …...
使用内存数据库来为mapper层的接口编写单元测试
简介 使用内存数据库来测试mapper层的sql代码,这种方式可以让测试案例摆脱对数据库的依赖,进而变得可重复执行。 这里选择的内存数据库是h2,它是纯java编写的关系型数据库,开源免费,而且轻量级的,性能较好…...
PowerMonitor的使用步骤
PowerMonitor是功耗分析中常用的测试和分析工具,不仅精度高,而且遇到需要找方案提功耗单的时候,有时还需要PowerMonitor的数据作为辅助日志。 1.先接上假电池正负极,再按PowerMonior的电源键 2.桌面点击PowerMonitor快捷图标 3.调…...
【C++经典例题】杨辉三角问题
💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:C经典例题 期待您的关注 目录 一、问题描述 二、解题思路 解法 1 思路 解法 2 思路 三、代码实现 解法 1 代码 解法 2 代码…...
java自主学习网站(springboot+ssm+mysql)含运行文档
java自主学习网站(springbootssmmysql)含运行文档 该系统是一个专注于Java编程的在线教育平台。系统的主要功能和特点如下: 导航栏:系统顶部设有导航栏,用户可以通过它快速访问不同的页面,包括首页、课程列表、分享资料列表、讲…...
T-SQL语言的链表查找
T-SQL语言的链表查找 在数据库系统中,数据结构的选择对性能优化至关重要。链表作为一种常见的数据结构,具有灵活性和动态存储的优势。尽管在SQL数据库中,传统的表结构已经足够应对大多数场景,但在某些情况下,将链表的…...
浅析 Spring AI 与 Python:企业级 AI 开发的技术分野
一、技术架构与生态体系对比 Spring AI 构建在 Spring Boot 生态之上,其核心架构包含以下模块: 模型适配层:通过统一 API 支持 OpenAI、Anthropic、Hugging Face 等主流模型提供商,实现跨平台模型调用。例如,调用 Cl…...
为 IDEA 设置管理员权限
IDEA 安装目录 兼容性选择管理员身份运行程序 之后 IDEA 中的操作(包括终端中的操作)都是管理员权限的了...
数据结构|排序算法(一)快速排序
一、排序概念 排序是数据结构中的一个重要概念,它是指将一组数据元素按照特定的顺序进行排列的过程,默认是从小到大排序。 常见的八大排序算法: 插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序、基数排序 二、快速…...
如何计算财富自由所需要的价格?
写在前面:【财富自由计算器】已上线,快算算财富自由要多少 多少钱,才能实现你的财富梦想? 需要多少,才能实现财务安全、财务独立,甚至财务自由? 看到结尾,你会很清楚地看到&…...
南京大学与阿里云联合启动人工智能人才培养合作计划,已将通义灵码引入软件学院课程体系
近日,南京大学与阿里云宣布启动人工智能人才培养合作计划,共同培养适应未来技术变革、具备跨学科思维的AI创新人才。 基于阿里云在云计算和AI大模型领域的技术优势和南京大学在人工智能领域的学科优势,双方将共同设计兼具前瞻性和应用性的人…...
基于 Python 的自然语言处理系列(70):检索增强生成(RAG)
1. 什么是 RAG? 在许多大模型(LLM)应用场景中,我们需要使用特定的用户数据,而这些数据并未包含在模型的训练集中。检索增强生成(Retrieval Augmented Generation,RAG)是一种有效的解…...
Flink CDC Pipeline mysql to doris
flink 与 flink-cdc版本兼容 运行同步程序 最终在 flink-1.20.1 与 flink-cdc-3.1.1 跑通测试 配置yaml文件 [rootchb1 flink-cdc-3.1.1]# cat mysql2doris.yaml ################################################################################ # Description: Sync…...
计算机网络-TCP的拥塞控制
内容来源:小林coding 本文是对小林coding的TPC拥塞控制的精简总结 为什么要有拥塞控制? 前面的流量控制是避免「发送方」的数据填满「接收方」的缓存,但是并不知道网络的中发生了什么 计算机网络都处在一个共享的环境,因此也…...
ArkTs的UI装饰器(自定义组件生命周期、页面组件生命周期、所有UI装饰器使用及示例)
目录 自定义组件定义 UI装饰器 @Component(V1) 自定义组件生命周期 freezeWhenInactive11+ @Entry(通用) 页面组件生命周期 EntryOptions10+ Component、Entry示例 @Reusable(V1) @Builder(通用) @BuilderParam(通用) 参数 引用传递示例 this指向 尾随…...
#管理Node.js的多个版本
在 Windows 11 上管理 Node.js 的多个版本,最方便的方法是使用 nvm-windows(Node Version Manager for Windows)。它允许你轻松安装、切换和管理多个 Node.js 版本。 📌 方法 1:使用 nvm-windows(推荐 ✅&a…...
Transformer由入门到精通(一):基础知识
基础知识 0 前言1 EncoderDecoder2 Bahdanau Attention3 Luong Attention4 Self Attention/Masked Self Attention5 MultiHead Self Attention6 Key-Value Attention7 ResNet8 总结 0 前言 我之前看transformer的论文《Attention Is All You Need》,根本看不懂&…...
Windows安装Node.js+Express+Nodemon
Windows安装Node.jsExpressNodemon 陈拓 2025/4/3-2025/4/4 1. 概述 在《Node.jsExpressNodemonSocket.IO构建Web实时通信》 https://blog.csdn.net/chentuo2000/article/details/134651743?spm1001.2014.3001.5502 一文中我们介绍了在Linux系统上的安装过程,本…...
关于JVM和OS中的指令重排以及JIT优化
关于JVM和OS中的指令重排以及JIT优化 前言: 这东西应该很重要才对,可是大多数博客都是以讹传讹,全是错误,尤其是JVM会对字节码进行重排都出来了,明明自己测一测就出来的东西,写出来误人子弟… 研究了两天&…...
LeetCode hot 100—柱状图中最大的矩形
题目 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 示例 示例 1: 输入:heights [2,1,5,6,2,3] 输出:10 解释:最…...
从代码学习深度学习 - GRU PyTorch版
文章目录 前言一、GRU模型介绍1.1 GRU的核心机制1.2 GRU的优势1.3 PyTorch中的实现二、数据加载与预处理2.1 代码实现2.2 解析三、GRU模型定义3.1 代码实现3.2 实例化3.3 解析四、训练与预测4.1 代码实现(utils_for_train.py)4.2 在GRU.ipynb中的使用4.3 输出与可视化4.4 解析…...
重要头文件下的函数
1、<cctype> #include<cctype>加入这个头文件就可以调用以下函数: 1、isalpha(x) 判断x是否为字母 isalpha 2、isdigit(x) 判断x是否为数字 isdigit 3、islower(x) 判断x是否为小写字母 islower 4、isupper(x) 判断x是否为大写字母 isupper 5、isa…...
JSON-lib考古现场:在2025年打开赛博古董店的奇妙冒险
各位在代码海洋里捡贝壳的探险家们!今天我们要打开一个尘封的Java古董箱——JSON-lib!这货可是2003年的老宝贝,比在座很多程序员的工龄还大!准备好穿越回Web 1.0时代,感受XML统治时期的余晖了吗? …...
实操日志之Windows Server2008R2 IIS7 配置Php7.4.3
Windows7IIS7PHPMySQL - 适用于(2008 R2 / 8 / 10) 配置需求 操作系统:windows2008IIS版本:7.0 PHP版本:7.4.3 MySQL版本:5.7.12 及以上第一步: 安装 IIS 默认”Internet 信息服务“打勾安…...
Paraformer和SenseVoice模型训练
0.数据准备 如果是训练paraformer模型,我们只需要准备train_wav.scp和train_text.txt以及验证集val_wav.scp和val_text.txt即可。 如果是训练SenseVoice模型,我们需要准备下面几个文件: train_text.txt train_wav.scp train_text_language.…...
Axure数据可视化科技感大屏设计资料——赋能多领域,展示无限价值
可视化大屏如何高效、直观地展示数据,并将其转化为有价值的决策依据,成为了许多企业和组织面临的共同挑战。Axure大屏可视化模板,作为一款强大的数据展示工具,正在以其出色的交互性和可定制性,赋能多个领域,…...
C# Winform 入门(7)之简单的抽奖系统邮件
由于比较喜欢英语,这里就把汉字属性名都改成英语了 声明变量,生成随机数 int key 0;Random random new Random(); 窗体加载 private void Form1_Load(object sender, EventArgs e) {timer1.Enabledfalse; } 开始按钮 private void txt_begin_Click(ob…...
scala编程语言
一、抽象类 1、抽象属性和抽象方法 1)基本语法 (1)定义抽象类:abstract class Person{} //通过 abstract 关键字标记抽象类 (2)定义抽象属性:val|var name:String //一个属性没有初始化…...
光流 | Farneback、Horn-Schunck、Lucas-Kanade、Lucas-Kanade DoG四种光流算法对比(附matlab源码)
🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅 以下是对四种光流算法的对比分析及MATLAB验证方案,包含原理说明、应用场景和可执行代码🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅🍅 🍓🍓🍓🍓🍍🍍🍍🍍🍍🍍🍍🍍🍍🍍…...
146. LRU 缓存 带TTL的LRU缓存实现(拓展)
LRU缓存 方法一:手动实现双向链表 哈希表 struct Node{int val;int key;Node* prev;Node* next;Node(int a, int b): key(a), val(b), prev(nullptr), next(nullptr) {}Node():key(0), val(0), prev(nullptr), next(nullptr) {} }; class LRUCache { private:Node* removeTai…...
【C++代码整洁之道】第九章 设计模式和习惯用法
文章目录 1. 设计原则与设计模式2. 常见的设计模式及应用场景2.1 单例模式2.2 依赖注入2.3 Adapter模式2.4 Strategy模式2.5 Command模式2.6 Command处理器模式2.7 Composite模式2.8 Observer模式2.9 Factory模式2.10 Facade模式2.11 Money Class模式2.12 特例模式 3. 常见的设…...
【动态规划】混合背包模板
混合背包问题题解 题目传送门:AcWing 7. 混合背包问题 一、题目描述 有 N 种物品和一个容量是 V 的背包。物品分为三类: 01背包:只能用1次(si -1)完全背包:可以用无限次(si 0)多…...
Linux 线程1-线程的概念、线程与进程区别、线程的创建、线程的调度机制、线程函数传参
目录 1.线程概念 1.1 线程的核心特点 1.2线程的工作模型 1.3线程的潜在问题 1.4 进程和线程区别 1.4.1执行与调度 1.4.2进程和线程区别对比表 1.4.3应用场景 1.4.4总结 2.线程的创建 2.1验证进程结束后,进程中所有的线程都会强制…...
Python 助力人工智能与机器学习的深度融合
技术革新的 “源动力” 在当今数字化时代,人工智能(AI)与机器学习(ML)无疑是最具影响力的技术领域,它们如同强大的引擎,推动着各个行业的变革与发展。Python 凭借其简洁易读的语法、丰富的库和…...
【GPT写代码】动作视频切截图研究器
目录 背景源代码 end 背景 用python写一个windows环境运行的动作视频切截图研究器,用路径浏览的方式指定待处理的视频文件,然后点击分析按钮,再预览区域显示视频预览画面,然后拖动时间轴,可以在预览区域刷新显示相应的…...
从0到神谕:GPT系列的进化狂想曲——用AI之眼见证人类语言的终极形态
开始:语言模型的星际跃迁 在人工智能的浩瀚星海中,GPT系列如同光年加速器,推动人类语言的理解与生成突破维度限制。从2018年GPT-1的初试啼声,到2025年GPT-4o的全模态智慧,这场进化狂想曲不仅是技术的迭代史,…...
Go并发编程终极指南:深入内核与工程实践
Go并发编程终极指南:深入内核与工程实践 Go并发编程终极指南:深入内核与工程实践 Go并发编程终极指南:深入内核与工程实践一、Goroutine调度器深度解构1.1 调度器演进史1.2 调度器源码级解析1.3 调度器可视化诊断 二、Channel底层实现揭秘2.1…...
Neo4j操作数据库(Cypher语法)
Neo4j数据库操作语法 使用的数据库版本 (终端查询) >neo4j --version 2025.03.0批量上传数据 UNWIND [{name: Alice, age: 30},{name: Bob, age: 25} ] AS person CREATE (p:Person) SET p.name = person.name, p.age = person.age RETURN p;查询结点总数 MATCH (n) RETU…...
DHCP之中继 Relay-snooping及配置命令
随着网络规模的不断扩大,网络设备不断增多,企业内不同的用户可能分布在不同的网段,一台 DHCP 服务器在正常情况下无法满足多个网段的地址分配需求。如果还需要通过 DHCP 服务器分配 IP 地址,则需要跨网段发送 DHCP 报文 DHCP Rel…...