咖啡汪日志———搭建灵活的统一响应模型,应对各种响应情况

本汪作为一名资深的哈士奇
每天除了闲逛,拆家,就是啃博客了
作为不是在戏精,就是在戏精的路上的二哈
今天就来给大家说说前后端分离项目-,如何搭建灵活的统一响应模型吧
它将灵活应对各种响应需求
(1)BaseResponse 标准基本响应模块
(2)自定义注解@IgnoreResponseAdvice, 他是对BaseResponse的增强,用来应对非标准返回的需求

一、基本响应类型的定义

思维导图如下,建议大家结合着看
在这里插入图片描述

源码地址:https://github.com/HuskyYue/ConvenienceServices
这个本汪说下,这是本汪自己的一个开源项目Demo,专门提供给大家学习用,内部有RabbitMQ日志记录,邮件发送,基于Redis发布订阅的商户通知等,有需要可以看本汪相关博客

1.编写工具类,借助org.springframework.validation.BindingResult,进行前端传过来参数的统一校验
本汪建议:大家可以多了解一下java8的新特性
闭包,Stream流,可读性不一定好,但代码会有一些简化,推荐《java实战(第二版)》

public class ValidatorUtil {
    
    

    //TODO:统一校验前端传递过来的参数
    public static String checkResult(BindingResult result){
    
    
        StringBuilder sb=new StringBuilder("");
        if (result.hasErrors()){
    
    
            //java8 steam api
            result.getAllErrors().forEach(error -> sb.append(error.getDefaultMessage()).append("\n"));
        }
        return sb.toString();
    }
}

2.创建状态码的维护实体类
code为状态码,msg为错误信息,可根据业务需要添加enum类型,设置响应的code,msg,
本汪说明下:此处配置的msg信息,在异常抛出时会被前端统一拦截,作为 提示内容反馈给用户,篇幅原因,就顺便写了几个examples

public enum StatusCode {
    
    
    Success(200,"success"),
    Fail(500,"false"),
    InvalidParams(300,"非法的参数!"),
    UserNameHasExist(301,"用户名已存在"),
    UserEmailHasExist(302,"用户邮箱已存在")
    ;

    private Integer code;
    private String msg;

    StatusCode(Integer code, String msg) {
    
    
        this.code = code;
        this.msg = msg;
    }

    public void setCode(Integer code) {
    
    
        this.code = code;
    }

3.创建基本响应类实体BaseResponse
因为是统一响应,所以她的data类型选用泛型,data就是我们平时方法调用,返回的数据

public class BaseResponse<T> implements Serializable {
    
    
    private Integer code;
    private String msg;
    private T data;

    public BaseResponse(Integer code, String msg) {
    
    
        this.code = code;
        this.msg = msg;
    }

    public BaseResponse(StatusCode statusCode) {
    
    
        this.code = statusCode.getCode();
        this.msg = statusCode.getMsg();
    }
}

4.写个测试用的controller,测试看看吧

@RequestMapping("base")
public class BaseController {
    
    
    private static final Logger log = LoggerFactory.getLogger(BaseController.class);
    @RequestMapping("info")
    public BaseResponse info(@RequestParam String name) {
    
    
    if (StringUtils.isBlank(name)) {
    
    
            return new BaseResponse(StatusCode.InvalidParams);
        }
        BaseResponse response = new BaseResponse(StatusCode.Success);
        try {
    
    
            //TODO 核心业务逻辑
            if (StringUtil.isBlank(name)){
    
    
                name = "李白最爱安琪拉";
            }
            response.setData(name);
        } catch (Exception e) {
    
    
            response = new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
        }
        return response;
    }
}

看看postman测试结果:
在这里插入图片描述
5.再看个例子
如果插入操作有异常抛出,会直接报500,msg内容即是我们开始配置的 Fail(500,"false"),

 public BaseResponse addUserVip(@RequestBody @Validated User user, BindingResult result) {
    
    
        String checkRes = ValidatorUtil.checkResult(result);
        if (StringUtil.isNotBlank(checkRes)) {
    
    
            return new BaseResponse(StatusCode.InvalidParams.getCode(),checkRes);
        }
        BaseResponse response = new BaseResponse(StatusCode.Success);
        try {
    
    
            //TODO:写真正的核心业务逻辑
            userMapper.insertSelective(user);

        } catch (Exception e) {
    
    
            response = new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
        }
        return response;
    }

本汪说下,这个很简单,很容易看懂,想要整合到自己代码,可以自行查看源码

二、如何应对特殊需求返回类型

1、编写自定义注解@IgnoreResponseAdvice

/**
 * 自定义忽略统一响应注解
 * **
 * Yuezejian  Created in 2020/11/5 下午9:51
 */
@Target({
    
    ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreResponseAdvice {
    
    
}

2、BaseResponseDataAdvice类,对返回数据的增强

扫描二维码关注公众号,回复: 12480905 查看本文章

/**
 * 统一响应模型的增强(应对多变的特殊返回情况))
 * **
 * Yuezejian  Created in 2020/11/5 下午9:55
 */
@RestControllerAdvice
public class BaseResponseDataAdvice implements ResponseBodyAdvice<Object> {
    
    

    /**
     * 判断是否需要对响应进行处理
     * @param methodParameter 当前controller的声明方法
     * @param aClass
     * @return 返回 true 需要对响应进行处理
     */
    @Override
    @SuppressWarnings("all")
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
    
    
        //TODO: if currency class marked the @IgnoreResponseAdvice, no handler
        if (methodParameter.getDeclaringClass().isAnnotationPresent(
                IgnoreResponseAdvice.class
        )) {
    
    
            return false;
        }

        //TODO: if currency method marked the @IgnoreResponseAdvice, no handler
        if (methodParameter.getMethod().isAnnotationPresent(
                IgnoreResponseAdvice.class
        )) {
    
    
            return false;
        }
        //TODO: 对响应进行处理,执行 beforeBodyWrite 方法
        return true;
    }

    /**
     * 如果 supports 返回 true
     * 在 Body 写入响应流之前,进行处理
     * @param o controller 的返回对象
     * @param methodParameter controller 的声明方法
     * @param mediaType
     * @param aClass
     * @param serverHttpRequest
     * @param serverHttpResponse
     * @return
     */
    @Override
    @SuppressWarnings("all")
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
    
    
        //TODO: 定义最终的返回对象
        BaseResponse<Object> response = new BaseResponse<>(
                0,""
        );
            // if Object o is null, resopnse won't need to set data
        if ( o == null ) {
    
    
            return response;
            // if Object o has been BaseResponse, no handler
        } else if ( o instanceof BaseResponse) {
    
    
            response = (BaseResponse<Object>) o;
        } else {
    
    
            // overthen , set Object o as the data of response
            response.setData(o);
        }
        return response;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42994251/article/details/108302377