当前位置: 首页 > news >正文

第三期:深入理解 Spring Web MVC [特殊字符](数据传参+ 特殊字符处理 + 编码问题解析)

✨前言:传参和状态管理,看似简单其实门道不少

在 Web 开发中,前端和后端最核心的交流方式就是“传参”,而“传参”除了涉及如何写代码获取参数,还藏着很多开发者容易忽略的细节:

  • 为什么 URL 带了中文,后端拿到是乱码?

  • @PathVariable@RequestParam 到底怎么选?

  • 前端传 数据(#),后端拿不到值怎么办?

  • 用户登录后,我要怎么“记住”他?

  • Cookie 和 Session 有啥区别,怎么用才优雅?

这些问题都是你在 Spring MVC 实战中一定会遇到的!本篇内容就是为了解决这些“看起来简单,实际容易踩坑”的问题。


📌 本期我们将系统讲解以下几个关键点:

  1. 多种传参方式(GET、POST、Path、JSON)

  2. 中文、空格、特殊字符(# % & +)等处理方式

  3. 如何在 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 请求。非常适合初学者掌握前后端分离接口开发的基础。


在前后端分离开发中,前端通常使用 fetchaxiosjQuery.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

  • bodydata 是一个 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;
}


🔚 总结
操作工具注解
前端发送 JSONfetch / axios设置 Content-Type: application/json
后端接收 JSONSpring MVC@RequestBody
参数校验JSR-303@Valid + BindingResult
返回 JSONSpring Boot / MVC@ResponseBody@RestController
类型方法
Java ➡️ JSONmapper.writeValueAsString(obj)
JSON ➡️ Javamapper.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.propertiesapplication.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%20BA B

  • /search?kw=A+BA B ✅(但依赖解码器行为)

  • /search?kw=A%2BBA+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%20BA B
A+B/test?value=A%2BBA+B
A#B/test?value=A%23BA#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:
  1. File -> Settings -> Editor -> File Encodings

  2. 设置以下内容为 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-8Postman / Axios / Form
CharacterEncodingFilter 开启Spring Boot 自动或手动配置
JSON 或表单传参编码设置前后端统一
数据库连接设置 UTF-8JDBC URL 参数

✅ 小结一句话:

乱码的本质是编码-解码不一致,确保「前端 → 网络传输 → 后端 → 存储/展示」各环节使用统一编码(UTF-8)即可避免!

 结语:

核心内容总结
  1. 数据传参方式与场景
    Spring Web MVC 支持多种参数绑定方式:

    • 路径变量@PathVariable 处理 URL 中的动态参数(如 /user/{id}),需注意特殊字符(如 /, %)需 URL 编码。

    • 请求参数@RequestParam 获取 ?key=value 形式的参数,特殊字符(如 &, +)需前端编码。

    • 表单提交:通过 POST 提交,Content-Type: application/x-www-form-urlencoded,需配置字符编码过滤器。

    • JSON 数据@RequestBody 接收 JSON 格式参数,默认使用 UTF-8 编码,需确保前后端编码一致。

  2. 特殊字符处理策略

    • URL 保留字符:如 #, ?, & 需通过 URLEncoder 编码(如 %23 代替 #)。

    • 空格与加号问题:URL 中空格默认转为 +,后端需显式处理(如替换为 %20)。

    • JSON 转义:特殊字符(如 ", \)需 JSON 序列化工具(如 Jackson)自动转义。

    • 数据库存储:通过预处理语句(PreparedStatement)或 ORM 框架(如 Hibernate)防止 SQL 注入。

  3. 编码问题根源与解决方案

    • 乱码常见原因

      • 请求/响应未统一编码(如 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 [特殊字符](数据传参+ 特殊字符处理 + 编码问题解析)

✨前言&#xff1a;传参和状态管理&#xff0c;看似简单其实门道不少 在 Web 开发中&#xff0c;前端和后端最核心的交流方式就是“传参”&#xff0c;而“传参”除了涉及如何写代码获取参数&#xff0c;还藏着很多开发者容易忽略的细节&#xff1a; 为什么 URL 带了中文&…...

洛谷题单3-P1075 [NOIP 2012 普及组] 质因数分解-python-流程图重构

题目描述 已知正整数 n n n 是两个不同的质数的乘积&#xff0c;试求出两者中较大的那个质数。 输入格式 输入一个正整数 n n n。 输出格式 输出一个正整数 p p p&#xff0c;即较大的那个质数。 输入输出样例 输入 21输出 7说明/提示 1 ≤ n ≤ 2 1 0 9 1 \le n\…...

Vue组件化开发深度解析:Element UI与Ant Design Vue对比实践

一、Vue组件化开发的核心优势 1.1 组件化架构的天然优势 Vue的组件系统是其最核心的特性之一&#xff0c;采用单文件组件&#xff08;.vue&#xff09;形式&#xff0c;将HTML、CSS和JavaScript组合在同一个文件中&#xff0c;形成高内聚、低耦合的代码单元。这种设计显著提升…...

ctfshow VIP题目限免 robots后台泄露

根据题目提示是 robots后台泄露&#xff0c;所以我们试着访问它的后台文件 robots.txt 访问之后发现了有一个/flagishere.txt 目录文件。接着拼接访问它发现了 flag...

突破传统认知:聚类算法的底层逻辑与高阶应用全景解析

一、维度革命&#xff1a;重新定义聚类分析的认知边界 在人工智能的浩瀚星空中&#xff0c;聚类算法犹如一组精密的星际导航仪&#xff0c;帮助我们在无序的数据宇宙中发现隐藏的秩序。这项起源于人类本能分类需求的技术&#xff0c;经历了从简单分组到智能识别的蜕变&#xf…...

获取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中内容复制到这里 报错&#xff1a; ssh: connect to host github.com port 2…...

MINIQMT学习课程Day7

在上一篇&#xff0c;我们安装好xtquant&#xff0c;qmt以及python后&#xff0c;这一章&#xff0c;我们学习如何使用xtquant 本章学习&#xff0c;如何获取账号的资金使用状况。 首先&#xff0c;打开qmt&#xff0c;输入账号密码&#xff0c;选择独立交易。 进入交易界面&…...

`accept_ra` 和 `autoconf` 和 `forwarding` 的关系 笔记250404

accept_ra 和 autoconf 和 forwarding 的关系 笔记250404 在 Linux 的 IPv6 网络配置中&#xff0c;accept_ra、autoconf 和 forwarding 是三个密切相关的核心参数&#xff0c;它们的组合直接影响设备在网络中的角色&#xff08;主机或路由器&#xff09;和地址配置行为。以下是…...

leetcode数组-二分查找

题目 题目链接&#xff1a;https://leetcode.cn/problems/binary-search/ 文章讲解&#xff1a;https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1fA4y1o715 给定一个 n 个元素有序的&…...

vector的介绍与代码演示

由于以后我们写OJ题时会经常使用到vector&#xff0c;所以我们必不可缺的是熟悉它的各个接口。来为我们未来作铺垫。 首先&#xff0c;我们了解一下&#xff1a; https://cplusplus.com/reference/vector/ vector的概念&#xff1a; 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 是一种基于网络的、分布式的技术&#xff0c;用于在不同的应用程序之间进行通信和数据交换。以下是关于它的详细介绍&#xff1a; 定义与概念 Web Service 是一种通过互联网协议&#xff08;如 HTTP&#xff09;提供服务的软件组件&#xff0c;它使用标准的 XML …...

使用内存数据库来为mapper层的接口编写单元测试

简介 使用内存数据库来测试mapper层的sql代码&#xff0c;这种方式可以让测试案例摆脱对数据库的依赖&#xff0c;进而变得可重复执行。 这里选择的内存数据库是h2&#xff0c;它是纯java编写的关系型数据库&#xff0c;开源免费&#xff0c;而且轻量级的&#xff0c;性能较好…...

PowerMonitor的使用步骤

PowerMonitor是功耗分析中常用的测试和分析工具&#xff0c;不仅精度高&#xff0c;而且遇到需要找方案提功耗单的时候&#xff0c;有时还需要PowerMonitor的数据作为辅助日志。 1.先接上假电池正负极&#xff0c;再按PowerMonior的电源键 2.桌面点击PowerMonitor快捷图标 3.调…...

【C++经典例题】杨辉三角问题

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;C经典例题 期待您的关注 目录 一、问题描述 二、解题思路 解法 1 思路 解法 2 思路 三、代码实现 解法 1 代码 解法 2 代码…...

java自主学习网站(springboot+ssm+mysql)含运行文档

java自主学习网站(springbootssmmysql)含运行文档 该系统是一个专注于Java编程的在线教育平台。系统的主要功能和特点如下&#xff1a; 导航栏&#xff1a;系统顶部设有导航栏&#xff0c;用户可以通过它快速访问不同的页面&#xff0c;包括首页、课程列表、分享资料列表、讲…...

T-SQL语言的链表查找

T-SQL语言的链表查找 在数据库系统中&#xff0c;数据结构的选择对性能优化至关重要。链表作为一种常见的数据结构&#xff0c;具有灵活性和动态存储的优势。尽管在SQL数据库中&#xff0c;传统的表结构已经足够应对大多数场景&#xff0c;但在某些情况下&#xff0c;将链表的…...

浅析 Spring AI 与 Python:企业级 AI 开发的技术分野

一、技术架构与生态体系对比 Spring AI 构建在 Spring Boot 生态之上&#xff0c;其核心架构包含以下模块&#xff1a; 模型适配层&#xff1a;通过统一 API 支持 OpenAI、Anthropic、Hugging Face 等主流模型提供商&#xff0c;实现跨平台模型调用。例如&#xff0c;调用 Cl…...

为 IDEA 设置管理员权限

IDEA 安装目录 兼容性选择管理员身份运行程序 之后 IDEA 中的操作&#xff08;包括终端中的操作&#xff09;都是管理员权限的了...

数据结构|排序算法(一)快速排序

一、排序概念 排序是数据结构中的一个重要概念&#xff0c;它是指将一组数据元素按照特定的顺序进行排列的过程&#xff0c;默认是从小到大排序。 常见的八大排序算法&#xff1a; 插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序、基数排序 二、快速…...

如何计算财富自由所需要的价格?

写在前面&#xff1a;​【财富自由计算器】已上线&#xff0c;快算算财富自由要多少​ 多少钱&#xff0c;才能实现你的财富梦想&#xff1f; 需要多少&#xff0c;才能实现财务安全、财务独立&#xff0c;甚至财务自由&#xff1f; 看到结尾&#xff0c;你会很清楚地看到&…...

南京大学与阿里云联合启动人工智能人才培养合作计划,已将通义灵码引入软件学院课程体系

近日&#xff0c;南京大学与阿里云宣布启动人工智能人才培养合作计划&#xff0c;共同培养适应未来技术变革、具备跨学科思维的AI创新人才。 基于阿里云在云计算和AI大模型领域的技术优势和南京大学在人工智能领域的学科优势&#xff0c;双方将共同设计兼具前瞻性和应用性的人…...

基于 Python 的自然语言处理系列(70):检索增强生成(RAG)

1. 什么是 RAG&#xff1f; 在许多大模型&#xff08;LLM&#xff09;应用场景中&#xff0c;我们需要使用特定的用户数据&#xff0c;而这些数据并未包含在模型的训练集中。检索增强生成&#xff08;Retrieval Augmented Generation&#xff0c;RAG&#xff09;是一种有效的解…...

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的拥塞控制

内容来源&#xff1a;小林coding 本文是对小林coding的TPC拥塞控制的精简总结 为什么要有拥塞控制&#xff1f; 前面的流量控制是避免「发送方」的数据填满「接收方」的缓存&#xff0c;但是并不知道网络的中发生了什么 计算机网络都处在一个共享的环境&#xff0c;因此也…...

ArkTs的UI装饰器(自定义组件生命周期、页面组件生命周期、所有UI装饰器使用及示例)

目录 自定义组件定义 UI装饰器 @Component(V1) 自定义组件生命周期 freezeWhenInactive11+ @Entry(通用) 页面组件生命周期 EntryOptions10+ Component、Entry示例 @Reusable(V1) @Builder(通用) @BuilderParam(通用) 参数 引用传递示例 this指向 尾随…...

#管理Node.js的多个版本

在 Windows 11 上管理 Node.js 的多个版本&#xff0c;最方便的方法是使用 nvm-windows&#xff08;Node Version Manager for Windows&#xff09;。它允许你轻松安装、切换和管理多个 Node.js 版本。 &#x1f4cc; 方法 1&#xff1a;使用 nvm-windows&#xff08;推荐 ✅&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》&#xff0c;根本看不懂&…...

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系统上的安装过程&#xff0c;本…...

关于JVM和OS中的指令重排以及JIT优化

关于JVM和OS中的指令重排以及JIT优化 前言&#xff1a; 这东西应该很重要才对&#xff0c;可是大多数博客都是以讹传讹&#xff0c;全是错误&#xff0c;尤其是JVM会对字节码进行重排都出来了&#xff0c;明明自己测一测就出来的东西&#xff0c;写出来误人子弟… 研究了两天&…...

LeetCode hot 100—柱状图中最大的矩形

题目 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 示例 示例 1: 输入&#xff1a;heights [2,1,5,6,2,3] 输出&#xff1a;10 解释&#xff1a;最…...

从代码学习深度学习 - 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>加入这个头文件就可以调用以下函数&#xff1a; 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年打开赛博古董店的奇妙冒险

各位在代码海洋里捡贝壳的探险家们&#xff01;今天我们要打开一个尘封的Java古董箱——JSON-lib&#xff01;这货可是2003年的老宝贝&#xff0c;比在座很多程序员的工龄还大&#xff01;准备好穿越回Web 1.0时代&#xff0c;感受XML统治时期的余晖了吗&#xff1f; &#x1f…...

实操日志之Windows Server2008R2 IIS7 配置Php7.4.3

Windows7IIS7PHPMySQL - 适用于&#xff08;2008 R2 / 8 / 10&#xff09; 配置需求 操作系统&#xff1a;windows2008IIS版本&#xff1a;7.0 PHP版本&#xff1a;7.4.3 MySQL版本&#xff1a;5.7.12 及以上第一步&#xff1a; 安装 IIS 默认”Internet 信息服务“打勾安…...

Paraformer和SenseVoice模型训练

0.数据准备 如果是训练paraformer模型&#xff0c;我们只需要准备train_wav.scp和train_text.txt以及验证集val_wav.scp和val_text.txt即可。 如果是训练SenseVoice模型&#xff0c;我们需要准备下面几个文件&#xff1a; train_text.txt train_wav.scp train_text_language.…...

Axure数据可视化科技感大屏设计资料——赋能多领域,展示无限价值

可视化大屏如何高效、直观地展示数据&#xff0c;并将其转化为有价值的决策依据&#xff0c;成为了许多企业和组织面临的共同挑战。Axure大屏可视化模板&#xff0c;作为一款强大的数据展示工具&#xff0c;正在以其出色的交互性和可定制性&#xff0c;赋能多个领域&#xff0c…...

C# Winform 入门(7)之简单的抽奖系统邮件

由于比较喜欢英语&#xff0c;这里就把汉字属性名都改成英语了 声明变量&#xff0c;生成随机数 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&#xff09;基本语法 &#xff08;1&#xff09;定义抽象类&#xff1a;abstract class Person{} //通过 abstract 关键字标记抽象类 &#xff08;2&#xff09;定义抽象属性&#xff1a;val|var name:String //一个属性没有初始化&#xf…...

光流 | 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. 常见的设…...

【动态规划】混合背包模板

混合背包问题题解 题目传送门&#xff1a;AcWing 7. 混合背包问题 一、题目描述 有 N 种物品和一个容量是 V 的背包。物品分为三类&#xff1a; 01背包&#xff1a;只能用1次&#xff08;si -1&#xff09;完全背包&#xff1a;可以用无限次&#xff08;si 0&#xff09;多…...

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验证进程结束后&#xff0c;进程中所有的线程都会强制…...

Python 助力人工智能与机器学习的深度融合

技术革新的 “源动力” 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;与机器学习&#xff08;ML&#xff09;无疑是最具影响力的技术领域&#xff0c;它们如同强大的引擎&#xff0c;推动着各个行业的变革与发展。Python 凭借其简洁易读的语法、丰富的库和…...

【GPT写代码】动作视频切截图研究器

目录 背景源代码 end 背景 用python写一个windows环境运行的动作视频切截图研究器&#xff0c;用路径浏览的方式指定待处理的视频文件&#xff0c;然后点击分析按钮&#xff0c;再预览区域显示视频预览画面&#xff0c;然后拖动时间轴&#xff0c;可以在预览区域刷新显示相应的…...

从0到神谕:GPT系列的进化狂想曲——用AI之眼见证人类语言的终极形态

开始&#xff1a;语言模型的星际跃迁 在人工智能的浩瀚星海中&#xff0c;GPT系列如同光年加速器&#xff0c;推动人类语言的理解与生成突破维度限制。从2018年GPT-1的初试啼声&#xff0c;到2025年GPT-4o的全模态智慧&#xff0c;这场进化狂想曲不仅是技术的迭代史&#xff0c…...

Go并发编程终极指南:深入内核与工程实践

Go并发编程终极指南&#xff1a;深入内核与工程实践 Go并发编程终极指南&#xff1a;深入内核与工程实践 Go并发编程终极指南&#xff1a;深入内核与工程实践一、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及配置命令

随着网络规模的不断扩大&#xff0c;网络设备不断增多&#xff0c;企业内不同的用户可能分布在不同的网段&#xff0c;一台 DHCP 服务器在正常情况下无法满足多个网段的地址分配需求。如果还需要通过 DHCP 服务器分配 IP 地址&#xff0c;则需要跨网段发送 DHCP 报文 DHCP Rel…...