写点什么

RestFul API 统一格式返回 + 全局异常处理,linux 系统编程视频教程

用户头像
极客good
关注
发布于: 刚刚

}


public Integer getCode() {


return code;


}


public void setCode(Integer code) {


this.code = code;


}


public T getData() {


return data;


}


public void setData(T data) {


this.data = data;


}


public String getMessage() {


return message;


}


public void setMessage(String message) {


this.message = message;


}


@Override


public String toString() {


return "HttpResult{" +


"success=" + success +


", code=" + code +


", data=" + data +


", message='" + message + ''' +


'}';


}


}


复制代码


说明:


  1. 构造器私有,外部不可以直接创建;

  2. 只可以调用统一返回类的静态方法返回对象;

  3. success 是一个Boolean 值,通过这个值,可以直接观察到该次请求是否成功;

  4. data 表示响应数据,用于请求成功后,返回客户端需要的数据。


三、测试及总结



3.1 简单的接口测试

@RestController


@RequestMapping("/httpRest")


@Api(tags = "统一结果测试")


public class HttpRestController {


@ApiOperation(value = "通用返回成功(没有返回结果)", httpMethod = "GET")


@GetMapping("/success")


public HttpResult success(){


return HttpResult.success();


}


@ApiOperation(value = "返回成功(有返回结果)", httpMethod = "GET")


@GetMapping("/successWithD


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


ata")


public HttpResult successWithData(){


return HttpResult.success("风尘博客");


}


@ApiOperation(value = "通用返回失败", httpMethod = "GET")


@GetMapping("/failure")


public HttpResult failure(){


return HttpResult.failure(ResultCodeEnum.NOT_FOUND);


}


}


复制代码


这里 Swagger以及SpringMVC的配置就没贴出来了,详见 Github 示例代码。

3.2 返回结果

[http://localhost:8080/swagger-ui.html#/](


)


{


"code": 200,


"success": true


}


复制代码


{


"code": 200,


"data": "风尘博客",


"success": true


}


复制代码


{


"code": 404,


"message": "not found",


"success": false


}


复制代码


四、全局异常处理




使用统一返回结果时,还有一种情况,就是程序的报错是由于运行时异常导致的结果,有些异常是我们在业务中抛出的,有些是无法提前预知。


因此,我们需要定义一个统一的全局异常,在Controller捕获所有异常,并且做适当处理,并作为一种结果返回。

4.1 设计思路:

  1. 自定一个异常类(如:TokenVerificationException),捕获针对项目或业务的异常;

  2. 使用@ExceptionHandler注解捕获自定义异常和通用异常;

  3. 使用@ControllerAdvice集成@ExceptionHandler的方法到一个类中;

  4. 异常的对象信息补充到统一结果枚举中;

4.2 自定义异常

public class TokenVerificationException extends RuntimeException {


/**


  • 错误码


*/


protected Integer code;


protected String msg;


public Integer getCode() {


return code;


}


public String getMsg() {


return msg;


}


public void setMsg(String msg) {


this.msg = msg;


}


/**


  • 有参构造器,返回码在枚举类中,这里可以指定错误信息

  • @param msg


*/


public TokenVerificationException(String msg) {


super(msg);


}


}


复制代码

4.3 统一异常处理器

@ControllerAdvice注解是一种作用于控制层的切面通知(Advice),能够将通用的@ExceptionHandler@InitBinder@ModelAttributes方法收集到一个类型,并应用到所有控制器上。


@RestControllerAdvice


@Slf4j


public class GlobalExceptionHandler {


/**


  • 异常捕获

  • @param e 捕获的异常

  • @return 封装的返回对象


**/


@ExceptionHandler(Exception.class)


public HttpResult handlerException(Exception e) {


ResultCodeEnum resultCodeEnum;


// 自定义异常


if (e instanceof TokenVerificationException) {


resultCodeEnum = ResultCodeEnum.TOKEN_VERIFICATION_ERROR;


resultCodeEnum.setMessage(getConstraintViolationErrMsg(e));


log.error("tokenVerificationException:{}", resultCodeEnum.getMessage());


}else {


// 其他异常,当我们定义了多个异常时,这里可以增加判断和记录


resultCodeEnum = ResultCodeEnum.SERVER_ERROR;


resultCodeEnum.setMessage(e.getMessage());


log.error("common exception:{}", JSON.toJSONString(e));


}


return HttpResult.failure(resultCodeEnum);


}


/**


  • 获取错误信息

  • @param ex

  • @return


*/


private String getConstraintViolationErrMsg(Exception ex) {


// validTest1.id: id 必须为正数


// validTest1.id: id 必须为正数, validTest1.name: 长度必须在有效范围内


String message = ex.getMessage();


try {


int startIdx = message.indexOf(": ");


if (startIdx < 0) {


startIdx = 0;


}


int endIdx = message.indexOf(", ");


if (endIdx < 0) {


endIdx = message.length();


}


message = message.substring(startIdx, endIdx);


return message;


} catch (Throwable throwable) {


log.info("ex caught", throwable);


return message;


}


}


}


复制代码


  • 说明


  1. 我使用的是@RestControllerAdvice ,等同于@ControllerAdvice + @ResponseBody

  2. 错误枚举类这里省略了,详见[Github 代码](


)。


五、测试及总结



5.1 测试接口

@RestController


@RequestMapping("/exception")


@Api(tags = "异常测试接口")


public class ExceptionRestController {


@ApiOperation(value = "业务异常(token 异常)", httpMethod = "GET")


@GetMapping("/token")


public HttpResult token() {


// 模拟业务层抛出 token 异常


throw new TokenVerificationException("token 已经过期");


}


@ApiOperation(value = "其他异常", httpMethod = "GET")


@GetMapping("/errorException")


public HttpResult errorException() {


//这里故意造成一个其他异常,并且不进行处理


Integer.parseInt("abc123");


return HttpResult.success();


}


}


复制代码

5.2 返回结果

[http://localhost:8080/swagger-ui.html#/](


)


{


"code": 500,


"message": "For input string: "abc123"",


"success": false


}


复制代码


{


"code": 4000,


"message": "token 已经过期",


"success": false


}


复制代码

5.3 小结

@RestControllerAdvice@ExceptionHandler会捕获所有Rest接口的异常并封装成我们定义的HttpResult的结果集返回,但是:处理不了拦截器里的异常


六、总结




没有哪一种方案是适用于各种情况的,如:分页情况,还可以增加返回分页结果的静态方案,具体实现,这里就不展示了。所以,适合自己的,具有一定可读性都是很好的,欢迎持不同意见的大佬给出意见建议。

6.1 示例代码

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
RestFul API 统一格式返回 + 全局异常处理,linux系统编程视频教程