一、RESTful风格支持
1、 RESTful概述
REST(Representational State Transfer,表现层状态转移)是一种软件架构风格,其核心思想是通过HTTP动词来描述操作,URL定位资源。
传统URL模式:
RESTful风格:
-
DELETE http://127.0.0.1/user/1
RESTful风格通过统一的URL和不同的HTTP请求方法实现对资源的CRUD操作,URL中使用占位符传递参数。
2、 @PathVariable注解
SpringMVC通过@PathVariable注解实现RESTful风格URL的参数绑定:
java
@Controller
@RequestMapping("/account")
public class AccountController {
@RequestMapping(value="/findAccount7/{id}")
public String findAccount11(@PathVariable Integer id, Model model){
model.addAttribute("msg", "接收到的ID是:" + id);
return "success";
}
}
前端访问:
java
<a href="/account/findAccount7/123">RESTful传参</a>
**运行结果:** 页面显示"接收到的ID是:123"
注意: URL中的占位符名称{id}必须与@PathVariable参数名一致,或者通过@PathVariable("id")指定。
二、请求参数乱码问题处理
1、 POST请求乱码解决方案
POST请求提交的表单数据需要统一编码处理,SpringMVC提供了CharacterEncodingFilter过滤器:
web.xml配置:
XML
<filter>
<filter-name>CharacterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
**过滤器作用原理:** CharacterEncodingFilter会在请求到达DispatcherServlet之前,对请求和响应的字符编码进行统一设置,确保中文参数能正确解析。
2、 GET请求乱码解决方案
GET请求的参数是附在URL后的,Tomcat默认使用ISO-8859-1编码,需要单独配置:
pom.xml中配置Tomcat插件:
XML
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
<!--关键配置:按UTF-8进行URL编码-->
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
注意: 实际部署时,Tomcat服务器的server.xml配置文件中也需要设置URIEncoding="UTF-8"。
三、自定义类型转换器
1、使用场景
当SpringMVC内置的类型转换器无法满足需求时,需要自定义转换器。常见场景包括:
-
字符串到日期类型的转换
-
特殊格式字符串到复杂对象的转换
-
前端特殊格式数据到后台Java类型的转换
示例场景: 表单提交的日期字符串"2023-10-12"需要转换为java.util.Date对象:
表单代码:
html
<form action="account/saveAccount" method="post">
账户名称:<input type="text" name="name"><br/>
开户日期:<input type="text" name="date"><br/>
<input type="submit" value="保存">
</form>
POJO类:
java
public class Account implements Serializable {
private Integer id;
private String name;
private Date date; // 需要从字符串转换
// getter/setter...
}
如果不配置转换器,会报错:
<img src="assets/image-20211012203811849.png" alt="类型转换错误" style="zoom:67%;" />
2、 实现自定义转换器
步骤1:创建转换器类实现Converter接口
java
import org.springframework.core.convert.converter.Converter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
try {
if(source == null || source.trim().isEmpty()) {
return null;
}
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
return format.parse(source);
} catch (Exception e) {
throw new RuntimeException("日期格式转换失败,格式应为:yyyy-MM-dd");
}
}
}
步骤2:SpringMVC配置文件中注册转换器
XML
<!-- 开启注解驱动,并指定转换服务 -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 配置ConversionServiceFactoryBean,注册自定义转换器 -->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.hg.converter.DateConverter"></bean>
<!-- 可以注册多个转换器 -->
<!-- <bean class="com.hg.converter.OtherConverter"></bean> -->
</set>
</property>
</bean>
**转换器原理:** SpringMVC在参数绑定时,会先检查是否有匹配的Converter,如果有则使用自定义转换器,否则使用默认转换器。
四、使用ServletAPI接收参数
虽然SpringMVC提供了便捷的参数绑定机制,但有时仍需要直接操作ServletAPI:
java
@Controller
@RequestMapping("/account")
public class AccountController {
@RequestMapping("/findAccount8")
public String findAccount8(HttpServletRequest request,
HttpServletResponse response,
HttpSession session) {
// 1. 获取请求参数
String username = request.getParameter("name");
String age = request.getParameter("age");
// 2. 设置请求属性
request.setAttribute("msg", username + " " + age);
// 3. 操作Session
session.setAttribute("user", username);
// 4. 操作响应
// response.setContentType("text/html;charset=utf-8");
return "success";
}
}
前端访问:
html
<a href="/account/findAccount8?name=张三&age=25">ServletAPI接收参数</a>
支持的ServletAPI类型:
-
HttpServletRequest- 获取请求信息 -
HttpServletResponse- 操作响应 -
HttpSession- 会话管理 -
ServletContext- 应用上下文 -
InputStream/OutputStream- 流操作 -
Reader/Writer- 字符流操作
五、数据传递方式
1、 ModelAndView传递数据
ModelAndView对象可以同时封装模型数据和视图名称:
java
@RequestMapping("/findAccount9")
public ModelAndView findAccount9() {
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
// 添加模型数据(相当于request.setAttribute)
mv.addObject("message", "欢迎使用SpringMVC");
mv.addObject("userCount", 100);
// 设置视图名称
mv.setViewName("success");
return mv;
}
简化写法:
java
@RequestMapping("/findAccount9")
public ModelAndView findAccount9(ModelAndView mv) {
mv.addObject("msg", "欢迎你 springmvc");
mv.setViewName("success");
return mv;
}
2、 Model传递数据
Model接口更轻量,只负责数据传递:
java
@RequestMapping("/findAccount10")
public String findAccount10(Model model) {
// 添加单个属性
model.addAttribute("msg", "欢迎你 springmvc");
// 添加多个属性
Map<String, Object> data = new HashMap<>();
data.put("username", "张三");
data.put("age", 25);
model.addAllAttributes(data);
return "success";
}
Model的常见实现:
-
ExtendedModelMap -
BindingAwareModelMap -
ModelMap
3、 使用ServletAPI传递数据
直接操作HttpServletRequest传递数据:
java
@RequestMapping("/findAccount11")
public String findAccount11(HttpServletRequest request,
HttpServletResponse response) {
// 设置请求属性
request.setAttribute("msg", "欢迎你 springmvc");
request.setAttribute("time", new Date());
// 也可以从请求中获取参数
String username = request.getParameter("username");
return "success";
}
六、JSON数据处理
1、 添加JSON依赖
SpringMVC默认使用Jackson处理JSON,需要添加依赖:
XML
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<!-- 可选:JSON视图解析器 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
2、 核心注解
@RequestBody
**作用:** 将HTTP请求体中的JSON字符串转换为Java对象
**位置:** 方法参数前
**支持类型:** 基本类型、POJO、Map、List等
@ResponseBody
**作用:** 将方法返回值转换为JSON格式响应
**位置:** 方法上或类上
**支持类型:** 任意Java对象
3、 JSON处理示例
示例1:接收和返回JSON
java
@Controller
@RequestMapping("/account")
public class AccountController {
// 处理JSON请求,返回JSON响应
@RequestMapping(value = "/saveAccount2", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> saveAccount2(@RequestBody Account account) {
Map<String, Object> result = new HashMap<>();
result.put("status", 200);
result.put("message", "保存成功");
result.put("data", account);
return result;
}
// 返回List的JSON格式
@RequestMapping("/listAccounts")
@ResponseBody
public List<Account> listAccounts() {
List<Account> accounts = new ArrayList<>();
accounts.add(new Account(1, "张三", 1000.0f));
accounts.add(new Account(2, "李四", 2000.0f));
return accounts;
}
}
示例2:RESTful风格API
java
@RestController // 相当于@Controller + 所有方法都添加@ResponseBody
@RequestMapping("/api/users")
public class UserRestController {
// GET /api/users/1
@GetMapping("/{id}")
public User getUser(@PathVariable Integer id) {
User user = userService.findById(id);
return user;
}
// POST /api/users
@PostMapping
public Map<String, Object> createUser(@RequestBody User user) {
userService.save(user);
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("message", "用户创建成功");
return result;
}
// PUT /api/users/1
@PutMapping("/{id}")
public Map<String, Object> updateUser(@PathVariable Integer id,
@RequestBody User user) {
user.setId(id);
userService.update(user);
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("message", "用户更新成功");
return result;
}
// DELETE /api/users/1
@DeleteMapping("/{id}")
public Map<String, Object> deleteUser(@PathVariable Integer id) {
userService.delete(id);
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("message", "用户删除成功");
return result;
}
}
4、 前端AJAX调用示例
HTML页面:
html
<!DOCTYPE html>
<html>
<head>
<title>JSON测试</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<h2>JSON数据交互测试</h2>
<!-- 测试按钮 -->
<input type="button" value="测试保存账户" onclick="saveAccount()"/>
<input type="button" value="测试获取用户列表" onclick="getUserList()"/>
<!-- 结果显示区域 -->
<div id="result"></div>
<script>
// 保存账户
function saveAccount() {
const accountData = {
id: 1,
name: "张三",
money: 999.0,
date: "2023-10-12"
};
axios.post('/account/saveAccount2', accountData)
.then(response => {
if(response.data.status === 200) {
const account = response.data.msg;
document.getElementById("result").innerHTML =
`保存成功:${account.name} - ${account.money}`;
}
})
.catch(error => {
console.error('请求失败:', error);
document.getElementById("result").innerHTML = "请求失败";
});
}
// 获取用户列表
function getUserList() {
axios.get('/api/users')
.then(response => {
const users = response.data;
let html = "<h3>用户列表:</h3><ul>";
users.forEach(user => {
html += `<li>${user.name} - ${user.money}</li>`;
});
html += "</ul>";
document.getElementById("result").innerHTML = html;
})
.catch(error => {
console.error('请求失败:', error);
});
}
</script>
</body>
</html>
5、 JSON相关配置
SpringMVC配置文件中添加JSON支持:
XML
<!-- 开启注解驱动,默认已包含JSON支持 -->
<mvc:annotation-driven>
<!-- 配置消息转换器 -->
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<!-- 设置字符编码 -->
<property name="defaultCharset" value="UTF-8"/>
<!-- 支持的媒体类型 -->
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
6、 常见问题处理
1. 日期格式处理
java
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
2. 忽略某些字段
java
@JsonIgnore // 忽略该字段
private String password;
@JsonIgnoreProperties({"password", "salt"}) // 类级别忽略
public class User {
// ...
}
3. 字段别名
java
@JsonProperty("user_name")
private String username;
总结
从RESTful风格到JSON数据处理的完整流程,SpringMVC提供了全面的Web开发支持:
-
RESTful设计:通过URL设计和HTTP方法实现资源操作
-
参数绑定:支持基本类型、POJO、集合、RESTful参数等多种绑定方式
-
编码处理:统一解决GET/POST请求的乱码问题
-
类型转换:内置转换器+自定义转换器满足各种场景需求
-
数据传递:多种方式在Controller和View之间传递数据
-
JSON处理:完整的JSON请求/响应支持,适用于前后端分离开发
这些功能共同构成了SpringMVC强大的Web开发能力,使得开发者能够高效、优雅地构建企业级Web应用。