# RestResponse REST响应服务
MornBoot提供注解式接口响应控制,用于简化甚至免除响应消息的构建过程。响应消息默认支持国际化、异常解释。
Since:v1.2.2
# 必要配置
pom.xml
<dependencies>
<!--Web模块-->
<dependency>
<groupId>site.morn.boot</groupId>
<artifactId>morn-boot-web</artifactId>
<version>${morn.version}</version>
</dependency>
</dependencies>
# 推荐配置
pom.xml
<dependencies>
<!--异常解释[可选]-->
<dependency>
<groupId>site.morn.boot</groupId>
<artifactId>morn-boot-interpreter</artifactId>
<version>${morn.version}</version>
</dependency>
</dependencies>
# 构建响应消息
# 构建正常响应
使用@RestResponse
注解标注@RestController
的类或方法,接口映射方法将会返回标准的RestMessage格式消息。
@RestResponse
@RestController
@RequestMapping("test/rest")
public class TestRestController {
/**
* 返回用户数据
*/
@GetMapping("data")
public TestUser returnData() {
return new TestUser(1L, "Timely");
}
}
响应结果
{
"status": 200,
"code": "success",
"level": "info",
"message": "操作成功",
"data": {
"id": 1,
"departmentId": null,
"username": "Timely",
"password": null
}
}
当引入morn-boot-web模块后,MornBoot内置了
RestControllerAdvice
和ResponseBodyAdvice
用于处理接口映射的响应体。因此建议在项目中移除对响应体的全局处理,在后续文档中,将会介绍如何构建自定义响应消息。
# 构建异常响应
直接抛出异常即可,同时也支持使用ApplicationMessage构建异常。以RuntimeException
为例:
@RestResponse
@RestController
@RequestMapping("test/rest")
public class TestRestController {
/**
* 抛异常
*/
@GetMapping("ex")
public SerialMessage returnException() {
throw new RuntimeException("This is exception.");
}
}
Response Body
{
"status": 500,
"code": "failure",
"level": "error",
"message": "This is exception.",
"data": null
}
当Rest方法返回值的声明类型是
void|String
,且实际返回类型是void|String|null|throw
,可能导致响应text/plain
消息,而不是application/json
,比较好的做法是将返回值声明为SerialMessage
。响应消息默认支持国际化,参考:RestMessage
# 解析异常消息
当引入morn-boot-interpreter模块后,系统会自动解析已收录的第三方异常,并暴露给开发人员。以javax.validation
为例:
@RestResponse
@RestController
@RequestMapping("test/rest")
public class TestRestController {
/**
* 抛异常 - 可解释异常
*/
@GetMapping("resolvable/ex")
@RestResponse
public void returnResolvableException(@Valid TestUser user) {
}
}
使用无效参数访问test/rest/resolvable/ex
接口,会得到易于识别的提示信息。
{
"status": 500,
"code": "validate",
"level": "error",
"message": "username must not be null",
"data": null
}
# 构建自定义响应
业务框架中通常定义了自己的响应消息格式,MornBoot也支持将RestMessage转换为业务消息格式。 以百度的REST消息为例,在@RestResponse
注解中指定转换类型,即可返回指定格式的消息。
@RestResponse
@RestController
@RequestMapping("test/rest")
public class TestRestController {
/**
* 返回用户数据 - 百度格式
*/
@GetMapping("baidu/data")
@RestResponse(BaiduMessage.class)
public TestUser returnBaiduData() {
return new TestUser(2L, "Baidu");
}
}
Response Body
百度error
为0表示访问成功,其它字段也与RestMessage
略有差别。
{
"error": "0",
"msg": "操作成功",
"data": {
"creator": null,
"createTime": null,
"modifier": null,
"modifyTime": null,
"departmentId": null,
"id": 2,
"username": "Baidu",
"password": null,
"display": null
}
}
为达到转换的效果,还需要编写消息类和转换类。
点击查看代码
/**
* 百度REST消息
*/
@Getter
@Setter
@ToString
public class BaiduMessage {
/**
* 状态码
*/
private String error;
/**
* 消息内容
*/
private String msg;
/**
* 消息数据
*/
private Object data;
}
/**
* 百度消息转换器
*/
@Component
@Source(RestMessage.class)
@Target(BaiduMessage.class)
public class BaiduMessageConverter implements RestMessageConverter<BaiduMessage> {
@Override
public BaiduMessage convert(RestMessage restMessage) {
BaiduMessage baiduMessage = new BaiduMessage();
baiduMessage.setError(RestMessageConstants.isSuccess(restMessage.getStatus()) ? "0" : "-1");
baiduMessage.setMsg(restMessage.getMessage());
baiduMessage.setData(restMessage.getData());
return baiduMessage;
}
@Override
public RestMessage revert(BaiduMessage baiduMessage) {
RestMessage restMessage = new SimpleRestMessage();
boolean success = isSuccess(baiduMessage);
restMessage.setStatus(success ? RestMessageConstants.SUCCESS : RestMessageConstants.FAILURE);
restMessage.setLevel(success ? RestMessageLevel.INFO : RestMessageLevel.ERROR);
restMessage.setCode(baiduMessage.getError());
restMessage.setMessage(baiduMessage.getMsg());
restMessage.setData(baiduMessage.getData());
return restMessage;
}
private boolean isSuccess(BaiduMessage baiduMessage) {
return Objects.equals(baiduMessage.getError(), "0");
}
}
# 响应消息标准化
除了将RestMessage
转换为业务消息格式外,MornBoot也支持反向转换,将业务消息转换为RestMessage
对象。
@RestResponse
@RestController
@RequestMapping("test/rest")
public class TestRestController {
/**
* 返回用户数据 - Morn格式
*/
@GetMapping("morn/data")
@RestResponse(RestMessage.class)
public BaiduMessage returnMornData() {
TestUser user = new TestUser(3L, "Morn");
BaiduMessage baiduMessage = new BaiduMessage();
baiduMessage.setError("0");
baiduMessage.setData(user);
return baiduMessage;
}
}
# Rest全局配置
# 配置说明
# 若force-serial为true,无论是否标注@RestResponse,都会响应为SerialMessage
morn.rest.force-serial=false
# 全局响应类型(默认),优先级:方法注解 > 类注解 > 全局配置
morn.rest.response-class=site.morn.rest.RestMessage