微服务架构之API接口统一返回结果ApiResult
今天的学习内容是搭建微服务公共模块并创建api接口统一放回结果对象ApiResult。
一、创建公共模块common步骤
1. 在spring-demo项目中新建一个cloud-common模块:
微服务搭建步骤请参考前面章节: https://editor.csdn.net/md/?articleId=109426982
2、common模块的pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sping-demo</artifactId>
<groupId>yooo.yun.com</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-common</artifactId>
<properties>
<shiro.version>1.4.1</shiro.version>
<java-jwt.version>3.7.0</java-jwt.version>
<nimbus-jose-jwt.version>8.16</nimbus-jose-jwt.version>
<springfox-swagger.version>2.9.2</springfox-swagger.version>
</properties>
<dependencies>
<!-- springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-swagger.version}</version>
</dependency>
<!-- Shiro+JWT start -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<!--JWT(Json Web Token)登录支持-->
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>${nimbus-jose-jwt.version}</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${java-jwt.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
</dependencies>
<!-- Spring Boot-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<!-- 先指定 src/main/resources下所有文件及文件夹为资源文件 -->
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.14</version>
<configuration>
<imageName>${project.name}</imageName>
<dockerDirectory>${project.name}/src/main/docker</dockerDirectory>
<dockerHost>${docker.host}</dockerHost>
<skipDockerBuild>true</skipDockerBuild>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
</project>
3、common目录如下
二、在api中新建一个ApiCode枚举和ApiResult
ApiCode用于定义业务处理发生异常时的错误码和异常信息
三、ApiCode与ApiResult编码如下
package yooo.yun.com.common.api;
/**
* REST API 响应码
*
* @author wangjiao
* @since 2020/11/14
*/
public enum ApiCode {
/** 系统级Code: 5000内 */
SUCCESS(200, "操作成功"),
UNAUTHORIZED(401, "非法访问"),
NOT_PERMISSION(403, "没有权限"),
NOT_FOUND(404, "你请求的资源不存在"),
FAIL(500, "操作失败"),
LOGIN_EXCEPTION(4000, "登陆失败"),
SYSTEM_EXCEPTION(5000, "系统异常"),
/** 参数校验级Code: 5001 - 6000 */
PARAMETER_EXCEPTION(5001, "请求参数校验异常"),
/** 业务级Code: 6001 - 7000 */
USER_UNAUTHORIZED(6001, "未授权,请先授权再访问"),
USER_TWO_PASSWORDS_INCONSISTENT(6002, "两次输入密码不一致"),
USER_ACCOUNT_REGISTERED(6003, "该账号已被注册"),
;
private final int code;
private final String msg;
ApiCode(final int code, final String msg) {
this.code = code;
this.msg = msg;
}
public static ApiCode getApiCode(int code) {
ApiCode[] ecs = ApiCode.values();
for (ApiCode ec : ecs) {
if (ec.getCode() == code) {
return ec;
}
}
return SUCCESS;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
ApiResult代码如下:
package yooo.yun.com.common.api;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* REST API 返回结果
*
* @author wangjiao
* @since 2020/11/14
*/
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
public class ApiResult implements Serializable {
/** 响应码: 状态码为200才算请求成功 */
private int code;
/** 响应消息 */
private String msg;
/** 是否成功 */
private boolean success;
/** 响应数据 */
private Object data;
/** 响应时间 */
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date time;
public ApiResult() {
this.success = true;
this.msg = ApiCode.SUCCESS.getMsg();
this.code = ApiCode.SUCCESS.getCode();
this.time = new Date(System.currentTimeMillis());
}
public static ApiResult of() {
return new ApiResult();
}
public static ApiResult of(final boolean result) {
ApiResult commonResponse = ApiResult.of();
commonResponse.setSuccess(result);
commonResponse.setData(null);
return commonResponse;
}
public static ApiResult of(final String msg) {
ApiResult commonResponse = ApiResult.of();
commonResponse.setSuccess(false);
commonResponse.setCode(ApiCode.FAIL.getCode());
commonResponse.setMsg(msg);
return commonResponse;
}
public static ApiResult of(final Object data) {
ApiResult commonResponse = ApiResult.of();
commonResponse.setData(data);
return commonResponse;
}
public static ApiResult of(final ApiCode resultCode) {
return of(false, resultCode);
}
public static ApiResult of(final ApiCode resultCode, final Object data) {
ApiResult commonResponse = of(false, resultCode);
commonResponse.setData(data);
return commonResponse;
}
public static ApiResult of(final boolean result, final ApiCode resultCode) {
ApiResult commonResponse = ApiResult.of();
commonResponse.setSuccess(result);
commonResponse.setMsg(resultCode.getMsg());
commonResponse.setCode(resultCode.getCode());
return commonResponse;
}
public static ApiResult of(final boolean result, final Object data) {
ApiResult commonResponse = ApiResult.of();
commonResponse.setSuccess(result);
commonResponse.setData(data);
return commonResponse;
}
public static ApiResult of(final boolean result, final Object data, final ApiCode resultCode) {
ApiResult commonResponse = of(result, resultCode);
commonResponse.setData(data);
return commonResponse;
}
public static ApiResult ok() {
return of(true);
}
public static ApiResult ok(final Object data) {
return of(data);
}
public static ApiResult ok(final ApiCode data) {
return of(data);
}
public static ApiResult ok(final Object data, final ApiCode resultCode) {
return of(true, data, resultCode);
}
public static ApiResult fail() {
return of(false, ApiCode.FAIL);
}
public static ApiResult fail(final ApiCode data) {
return of(false, data);
}
public static ApiResult fail(final String msg) {
return of(msg);
}
public static ApiResult fail(ApiCode apiCode, Object data) {
if (ApiCode.SUCCESS == apiCode) {
throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
}
return of(apiCode, data);
}
public static ApiResult okMap(String key, Object value) {
Map<String, Object> map = new HashMap<>();
map.put(key, value);
return ok(map);
}
}
四、在UserController中写个测试方法进行测试
package yooo.yun.com.user.controller.saas;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import yooo.yun.com.common.api.ApiCode;
import yooo.yun.com.common.api.ApiResult;
import yooo.yun.com.common.entity.pojo.UserPoJo;
import yooo.yun.com.common.entity.request.UserLoginReq;
import yooo.yun.com.common.entity.request.UserReq;
import yooo.yun.com.user.service.UserService;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Objects;
/**
* @author WangJiao
* @since 2020/10/14
*/
@Slf4j
@RequestMapping(value = "/saas/user")
@RestController("sUserC")
public class UserController {
@Resource private UserService service;
/**
* test
*
* @param status status
* @return res
*/
@PostMapping("/test-api")
@ApiOperation("测试api返回结果类型")
public ApiResult testApiResult(@RequestParam(value = "status") int status) {
log.info("testApiResult:[status:{}]", status);
return Objects.equals(status, 1)
? ApiResult.ok(status)
: ApiResult.fail(ApiCode.USER_ACCOUNT_REGISTERED);
}
}
五、启动user模块,启动项目顺序请参考【微服务项目搭建】
https://blog.csdn.net/qq_38066812/article/details/109426982
六、在浏览器中输入swagger访问地址
http://localhost:5050/user/swagger-ui.html
- 点击【Try it out!】进行测试,参数输入1,返回正常数据
- 参数输入2,返回失败的数据
七、注解使用解释
- @Data : 实体上使用该注解需要idea引入lombok插件,在实体类中可以不用谢get与set方法就可以直接调用,简化实体类。
快捷键:【Ctrl alt + S】打开setting界面,如果未安装就在搜索lombok安装后重启idea即可。
- pom文件中引入
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
-
@Accessors(chain = true) :用来配置lombok如何产生和显示getters和setters的方法。
chain为一个布尔值,如果为true生成的set方法返回this,为false生成的set方法是void类型。默认为false,除非当fluent为true时,chain默认则为true。
参考来源:https://blog.csdn.net/linjpg/article/details/94588483 -
@Builder :build()方法调用ApiResult 类的全参构造方法来生成ApiResult 实例,不需些太多的set方法来定义属性内容。
ApiResult commonResponse = ApiResult.builder().success(false).code(ApiCode.FAIL.getCode()).msg(msg).build();
- @AllArgsConstructor : 为类提供一个全参构造方法,不需要写一个全部参数的构造方法。
已经到底部了喔,相信你已经get到了!