处理创建请求
本节内容
@requestBody
映射请求体到java方法参数,可以处理json格式的请求内容- 日期类型参数的处理
@Valid
和BindingResult验证请求参数的合法性并处理校验结果
编写测试用例
@Test
public void whenCreateSuccess() throws Exception {
String content = "{\"username\":\"mrcode\",\"password\":null}";
mockMvc.perform(post("/user")
.contentType(APPLICATION_JSON_UTF8)
.content(content) // 传递json内容
)
.andExpect(status().isOk())
// 因为是创建,一般创建完成后需要返回创建的id
// 预期是返回1
.andExpect(jsonPath("$.id").value("1"));
}
运行测试用例返回
java.lang.AssertionError: Status
Expected :200
Actual :405
<Click to see difference>
405的原因是因为query方法占用了”/user”路径,但是是get请求,这里是post请求,所以报错不支持的方法
编写服务接口
使用 @RequestBody
接收json内容
@PostMapping
public User create(@RequestBody User user) {
System.out.println(ReflectionToStringBuilder.toString(user, ToStringStyle.MULTI_LINE_STYLE));
user.setId("1");
return user;
}
日期类型的处理
解决办法是:传递时间戳,非unix时间戳,也就是毫秒数,可以使用new Date(毫秒数)还原成一个java日期的;
常规的解决办法是
com.example.demo.dto.User 中新增日期类型 private Date birthday;
编写测试用例
@Test
public void whenCreateSuccess() throws Exception {
// long time = new Date().getTime(); 等价于下面的
long birthday = Instant.now().toEpochMilli();
String content = "{\"username\":\"mrcode\",\"password\":null,\"birthday\":" + birthday + "}";
String contentAsString = mockMvc.perform(post("/user")
.contentType(APPLICATION_JSON_UTF8)
.content(content)
)
.andExpect(status().isOk())
// 因为是创建,一般创建完成后需要返回创建的id
// 预期是返回1
.andExpect(jsonPath("$.id").value("1"))
.andReturn().getResponse().getContentAsString();
System.out.println(contentAsString);
}
输出
// 测试用例输出
com.example.demo.dto.User@3f6f3cc[
id=<null>
username=mrcode
password=<null>
birthday=Thu Aug 02 09:54:04 GMT+08:00 2018
]
// api 中使用了 ReflectionToStringBuilder.toString 打印的输出
{"id":"1","username":"mrcode","password":null,"birthday":"2018-08-02T01:54:04.268+0000"}
这里发现,现在这个版本的jackson接收是接收时间戳,但是返回的时候却调用了local默认的格式化格式;这让人很蛋疼;
找了十几分钟,没有找到解决方案;以后再看看能不能返回时间戳;这里添加配置
application.yml
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
添加之后,响应变成了想要格式,但是接收(也就是前段传递)还是需要时间戳
@Valid
使用
对user对象Password限制不能为空
@javax.validation.constraints.NotBlank
private String password;
这里不是 org.hibernate.validator.constraints.NotBlank 在该注解上发现了过时描述。
Deprecated use the standard javax.validation.constraints.NotBlank constraint instead
虽然说这里用的注解是规范注解,使用的验证器 应该是 hibernate-validator-6.0.10.Final.jar版本提供的
api中增加 `@Valid
// javax.validation.Valid
@PostMapping
public User create(@Valid @RequestBody User user) {
用post请求的时候(可以用postman或则视频中讲解的谷歌插件 Restlet Client - REST API Testing );
Restlet Client - REST API Testing 这个谷歌插件可以去了解下,感觉挺好用的,可以项目分类和全部执行测试
{
"timestamp": "2018-08-02 10:41:13",
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"NotBlank.user.password",
"NotBlank.password",
"NotBlank.java.lang.String",
"NotBlank"
],
"arguments": [
{
"codes": [
"user.password",
"password"
],
"arguments": null,
"defaultMessage": "password",
"code": "password"
}
],
"defaultMessage": "不能为空",
"objectName": "user",
"field": "password",
"rejectedValue": null,
"bindingFailure": false,
"code": "NotBlank"
}
],
"message": "Validation failed for object='user'. Error count: 1",
"path": "/user"
}
BindingResult 使用
在上面我们的业务方法都没有进入,就被spring框架给拦截回去了。在实际开发中都是需要进入
我们的业务方法,添加BindingResult入参。能获取到所有的错误信息
@PostMapping
public User create(@Valid @RequestBody User user, BindingResult errors) {
if (errors.hasErrors()) {
// System.out.println(err.getDefaultMessage()); 能获取默认的错误信息
errors.getAllErrors().stream().forEach(System.out::println);
}
再次使用测试用例:打印出来的是这些。自己debug查看就能看到有详情
Field error in object 'user' on field 'password': rejected value [null]; codes [NotBlank.user.password,NotBlank.password,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.password,password]; arguments []; default message [password]]; default message [may not be empty]
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。