前言

由于返回json api 格式接口,所以我们需要通过java bean封装一个统一数据返回格式,便于和前端约定交互,

状态码枚举ResultCode

  1. package cn.soboys.core.ret;
  2. import lombok.Getter;
  3. /**
  4. * @author kenx
  5. * @version 1.0
  6. * @date 2021/6/17 15:35
  7. * 响应码枚举,对应HTTP状态码
  8. */
  9. @Getter
  10. public enum ResultCode {
  11. SUCCESS(200, "成功"),//成功
  12. //FAIL(400, "失败"),//失败
  13. BAD_REQUEST(400, "Bad Request"),
  14. UNAUTHORIZED(401, "认证失败"),//未认证
  15. NOT_FOUND(404, "接口不存在"),//接口不存在
  16. INTERNAL_SERVER_ERROR(500, "系统繁忙"),//服务器内部错误
  17. METHOD_NOT_ALLOWED(405,"方法不被允许"),
  18. /*参数错误:1001-1999*/
  19. PARAMS_IS_INVALID(1001, "参数无效"),
  20. PARAMS_IS_BLANK(1002, "参数为空");
  21. /*用户错误2001-2999*/
  22. private Integer code;
  23. private String message;
  24. ResultCode(int code, String message) {
  25. this.code = code;
  26. this.message = message;
  27. }
  28. }

结果体Result

  1. package cn.soboys.core.ret;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. /**
  5. * @author kenx
  6. * @version 1.0
  7. * @date 2021/6/17 15:47
  8. * 统一API响应结果格式封装
  9. */
  10. @Data
  11. public class Result<T> implements Serializable {
  12. private static final long serialVersionUID = 6308315887056661996L;
  13. private Integer code;
  14. private String message;
  15. private T data;
  16. public Result setResult(ResultCode resultCode) {
  17. this.code = resultCode.getCode();
  18. this.message = resultCode.getMessage();
  19. return this;
  20. }
  21. public Result setResult(ResultCode resultCode, T data) {
  22. this.code = resultCode.getCode();
  23. this.message = resultCode.getMessage();
  24. this.setData(data);
  25. return this;
  26. }
  27. }

响应结果方法工具类

  1. package cn.soboys.core.ret;
  2. /**
  3. * @author kenx
  4. * @version 1.0
  5. * @date 2021/6/17 16:30
  6. * 响应结果返回封装
  7. */
  8. public class ResultResponse {
  9. private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
  10. // 只返回状态
  11. public static Result success() {
  12. return new Result()
  13. .setResult(ResultCode.SUCCESS);
  14. }
  15. // 成功返回数据
  16. public static Result success(Object data) {
  17. return new Result()
  18. .setResult(ResultCode.SUCCESS, data);
  19. }
  20. // 失败
  21. public static Result failure(ResultCode resultCode) {
  22. return new Result()
  23. .setResult(resultCode);
  24. }
  25. // 失败
  26. public static Result failure(ResultCode resultCode, Object data) {
  27. return new Result()
  28. .setResult(resultCode, data);
  29. }
  30. }

自定义解析controller拦截

注解@ResponseResult

  1. package cn.soboys.core.ret;
  2. import java.lang.annotation.*;
  3. /**
  4. * @author kenx
  5. * @version 1.0
  6. * @date 2021/6/17 16:43
  7. * 统一包装接口返回的值 Result
  8. */
  9. @Target({ElementType.TYPE, ElementType.METHOD})
  10. @Retention(RetentionPolicy.RUNTIME)
  11. @Documented
  12. public @interface ResponseResult {
  13. }

请求拦截ResponseResultInterceptor

  1. package cn.soboys.core.ret;
  2. import org.springframework.web.method.HandlerMethod;
  3. import org.springframework.web.servlet.HandlerInterceptor;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.lang.reflect.Method;
  7. /**
  8. * @author kenx
  9. * @version 1.0
  10. * @date 2021/6/17 17:10
  11. * 请求拦截
  12. */
  13. public class ResponseResultInterceptor implements HandlerInterceptor {
  14. //标记名称
  15. public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";
  16. @Override
  17. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  18. //请求方法
  19. if (handler instanceof HandlerMethod) {
  20. final HandlerMethod handlerMethod = (HandlerMethod) handler;
  21. final Class<?> clazz = handlerMethod.getBeanType();
  22. final Method method = handlerMethod.getMethod();
  23. //判断是否在对象上加了注解
  24. if (clazz.isAnnotationPresent(ResponseResult.class)) {
  25. //设置此请求返回体需要包装,往下传递,在ResponseBodyAdvice接口进行判断
  26. request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class));
  27. //方法体上是否有注解
  28. } else if (method.isAnnotationPresent(ResponseResult.class)) {
  29. //设置此请求返回体需要包装,往下传递,在ResponseBodyAdvice接口进行判断
  30. request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class));
  31. }
  32. }
  33. return true;
  34. }
  35. }

请求全局解析ResponseResultHandler

  1. package cn.soboys.core.ret;
  2. import cn.soboys.core.utils.HttpContextUtil;
  3. import com.alibaba.fastjson.JSON;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.springframework.core.MethodParameter;
  6. import org.springframework.http.MediaType;
  7. import org.springframework.http.converter.HttpMessageConverter;
  8. import org.springframework.http.server.ServerHttpRequest;
  9. import org.springframework.http.server.ServerHttpResponse;
  10. import org.springframework.web.bind.annotation.ControllerAdvice;
  11. import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
  12. import javax.servlet.http.HttpServletRequest;
  13. /**
  14. * @author kenx
  15. * @version 1.0
  16. * @date 2021/6/17 16:47
  17. * 全局统一响应返回体处理
  18. */
  19. @Slf4j
  20. @ControllerAdvice
  21. public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
  22. public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";
  23. /**
  24. * @param methodParameter
  25. * @param aClass
  26. * @return 此处如果返回false , 则不执行当前Advice的业务
  27. * 是否请求包含了包装注解 标记,没有直接返回不需要重写返回体,
  28. */
  29. @Override
  30. public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
  31. HttpServletRequest request = HttpContextUtil.getRequest();
  32. //判断请求是否有包装标志
  33. ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN);
  34. return responseResultAnn == null ? false : true;
  35. }
  36. /**
  37. * @param body
  38. * @param methodParameter
  39. * @param mediaType
  40. * @param aClass
  41. * @param serverHttpRequest
  42. * @param serverHttpResponse
  43. * @return 处理响应的具体业务方法
  44. */
  45. @Override
  46. public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
  47. if (body instanceof Result) {
  48. return body;
  49. } else if (body instanceof String) {
  50. return JSON.toJSONString(ResultResponse.success(body));
  51. } else {
  52. return ResultResponse.success(body);
  53. }
  54. }
  55. }

具体详细内容请参考我这篇文章Spring Boot 无侵入式 实现RESTful API接口统一JSON格式返回

关注公众号猿小叔获取更多干货分享

个人博客开发之blog-api项目统一结果集api封装的更多相关文章

  1. 个人博客开发之xadmin 布局和后台样式

    项目源码下载:http://download.vhosts.cn 一. xadmin 后台配置注册信息 1. 在apps 的blogs 和 users 两个app中添加adminx.py文件 vim ...

  2. 个人博客开发之blog-api 项目全局日志拦截记录

    前言 大型完善项目中肯定是需要一个全局日志拦截,记录每次接口访问相关信息,包括: 访问ip,访问设备,请求参数,响应结果,响应时间,开始请求时间,访问接口描述,访问的用户,接口地址,请求类型,便于项目 ...

  3. 个人博客开发之blog-api 项目整合JWT实现token登录认证

    前言 现在前后端分离,基于session设计到跨越问题,而且session在多台服器之前同步问题,肯能会丢失,所以倾向于使用jwt作为token认证 json web token 导入java-jwt ...

  4. SpringBoot博客开发之AOP日志处理

    日志处理: 需求分析 日志处理需要记录的是: 请求的URL 访问者IP 调用的方法 传入的参数 返回的内容 上面的内容要求在控制台和日志中输出. 在学习这部分知识的时候,真的感觉收获很多,在之前Spr ...

  5. 个人博客开发之xadmin与ueditor集成

    项目源码下载:http://download.vhosts.cn 1. xadmin 添加ueditor 插件 vim extra_apps\xadmin\plugins\ueditor.py #没有 ...

  6. 个人博客开发之 xadmin 安装

    项目源码下载:http://download.vhosts.cn xadmin 下载地址:https://github.com/sshwsfc/xadmin或 https://github.com/s ...

  7. 个人博客开发之 ueditor 安装

  8. iOS开发之MVVM在项目中的应用

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

  9. 文顶顶iOS开发博客链接整理及部分项目源代码下载

    文顶顶iOS开发博客链接整理及部分项目源代码下载   网上的iOS开发的教程很多,但是像cnblogs博主文顶顶的博客这样内容图文并茂,代码齐全,示例经典,原理也有阐述,覆盖面宽广,自成系统的系列教程 ...

随机推荐

  1. [算法] 数据结构 splay(伸展树)解析

    前言 splay学了已经很久了,只不过一直没有总结,鸽了好久来写一篇总结. 先介绍 splay:亦称伸展树,为二叉搜索树的一种,部分操作能在 \(O( \log n)\) 内完成,如插入.查找.删除. ...

  2. 域名更换为itwxe.com

    域名 uukongjian.com 更换为 itwxe.com,笔名 SunnyBear 更改为 IT王小二. 一.前言 4 月 21 号域名备案通过,开始折腾新买的服务器,本来这篇文章在 5 月 1 ...

  3. xss-代码角度理解与绕过filter

    0x00 原理   xss全称为cross site scripting,中文为跨站脚本攻击.它允许web用户将恶意代码植入到提供给用户使用的页面.代码包括HTML代码和客户端脚本. 0x01 危害 ...

  4. AtCoder Regular Contest 121 D - 1 or 2

    题目链接:点我点我 Problem Statement Snuke has a blackboard and NN candies. The tastiness of the ii-th candy ...

  5. 面试侃集合 | SynchronousQueue非公平模式篇

    面试官:好了,你也休息了十分钟了,咱们接着往下聊聊SynchronousQueue的非公平模式吧. Hydra:好的,有了前面公平模式的基础,非公平模式理解起来就非常简单了.公平模式下,Synchro ...

  6. TVM如何训练TinyML

    TVM如何训练TinyML 机器学习研究人员和从业人员对"裸机"(低功耗,通常没有操作系统)设备产生了广泛的兴趣.尽管专家已经有可能在某些裸机设备上运行某些模型,但是为各种设备优化 ...

  7. VB 老旧版本维护系列---读取xml某个节点的值

    读取xml某个节点的值 '定义xml字符串内容地址 Dim xmlFileStr As String = "" '定义所需读取节点的名称 Dim readNodeName As S ...

  8. GVS智能照明再下一城,前方到站贵阳地铁2号线!

    近期,"新基建"又频频刷屏,也为城轨交通建设快速发展提供了广阔的想象空间. 在新基建的导向作用下,越来越多城市加入地铁阵营.如果说普铁和高铁作为城市的发展窗口,那么地铁则是城市交通 ...

  9. 使用regulator_get时的一个小注意事项

    Linux kernel 使用 regulator 框架来管理电源,比如 PMIC 芯片上常见的LDO.使用 regulator 的常规流程如以下代码所示: void set_vbus_voltage ...

  10. 重新整理 .net core 实践篇—————静态中间件[二十一]

    前言 简单整理一下静态中间件. 正文 我们使用静态文件调用: app.UseStaticFiles(); 那么这个默认会将我们根目录下的wwwroot作为静态目录. 这个就比较值得注意的,可能刚开始学 ...