专栏名称: Java极客技术
Java 人的社区,专注 Java 一百年!
目录
相关文章推荐
卢克文工作室  ·  男人的千年斗争史 ·  昨天  
参考消息  ·  古特雷斯“深感悲伤和震惊” ·  2 天前  
参考消息  ·  肯尼迪遇刺案记录公布 ·  3 天前  
51好读  ›  专栏  ›  Java极客技术

年轻人不讲武德,竟然重构出这么优雅后台 API 接口

Java极客技术  · 公众号  ·  · 2020-11-24 07:30

正文

每天早上 七点三十 ,准时推送干货

Hello,早上好,我是阿粉~

最近偶然间在看到 Spring 官方文档的时候,新学到一个注解 @ControllerAdvice ,并且成功使用这个注解重构我们项目的对外 API 接口,去除繁琐的重复代码,使其开发更加优雅。

展示具体重构代码之前,我们先来看下原先对外 API 接口是如何开发的。

这个 API 接口主要是用来与我们 APP 交互,这个过程我们统一定义一个交互协议,APP 端与后台 API 接口统一都使用 JSON 格式。

另外后台 API 接口对 APP 返回时,统一一些错误码,APP 端需要根据相应错误码,在页面弹出一些提示。

下面展示一个查询用户信息返回的接口数据:

{
    "code""000000",
    "msg""success",
    "result": {
        "id""1",
        "name""test"
    }
}

code 代表对外的错误码, msg 代表错误信息, result 代表具体返回信息。

前端 APP 获取这个返回信息,首先判断接口返回 code 是否为 「000000」 ,如果是代表查询成功,然后获取 result 信息作出相应的展示。否则,直接弹出相应的错误信息。

重构之前

下面我们来看下,重构之前的,后台 API 层的如何编码。

/**
 * V1 版本
 *
 * @return
 */

@RequestMapping("testv1")
public APIResult testv1() {
    try {
        User user = new User();
        user.setId("1");
        user.setName("test");
        return APIResult.success(user);
    } catch (APPException e) {
        log.error("内部异常", e);
        return APIResult.error(e.getCode(), e.getMsg());
    } catch (Exception e) {
        log.error("系统异常", e);
        return APIResult.error(RetCodeEnum.FAILED);
    }
}

上面的代码其实很简单,内部统一封装了一个工具类 APIResult ,然后用其包装具体的结果。

@Data
public class APIResult<Timplements Serializable {

    private static final long serialVersionUID = 4747774542107711845L;

    private String code;

    private String msg;

    private T result;


    public static  APIResult success(T result) {
        APIResult apiResult = new APIResult();
        apiResult.setResult(result);
        apiResult.setCode("000000");
        apiResult.setMsg("success");
        return apiResult;
    }

    public static APIResult error(String code, String msg) {
        APIResult apiResult = new APIResult();
        apiResult.setCode(code);
        apiResult.setMsg(msg);
        return apiResult;
    }

    public static APIResult error(RetCodeEnum codeEnum) {
        APIResult apiResult = new APIResult();
        apiResult.setCode(codeEnum.getCode());
        apiResult.setMsg(codeEnum.getMsg());
        return apiResult;
    }

除了这个以外,还定义一个异常对象 APPException ,用来统一包装内部的各种异常。

上面的代码很简单,但是呢可以说比较繁琐,重复代码也比较多,每个接口都需要使用 try...catch 包装,然后使用 APIResult 包括正常的返回信息与错误信息。

第二呢,接口对象只能返回 APIResult ,真实业务对象只能隐藏在 APIResult 中。这样不太优雅,另外不能很直观知道真实业务对象。

重构之后

下面我们开始重构上面的代码,主要目的是去除重复的那一坨 try...catch 代码。

这次重构我们需要使用Spring 注解 @ControllerAdvice 以及 ResponseBodyAdvice ,我们先来看下重构的代码。

ps: ResponseBodyAdvice 来自 Spring 4.2 API,如果各位同学需要使用这个的话,可能需要升级 Spring 版本。

改写返回信息

首先我们需要实现 ResponseBodyAdvice ,实现我们自己的处理类。

@ControllerAdvice
public class CustomResponseAdvice implements ResponseBodyAdvice {
    /**
     * 是否需要处理返回结果
     * @param methodParameter
     * @param aClass
     * @return
     */

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        System.out.println("In supports() method of " + getClass().getSimpleName());
        return true;
    }

    /**
     * 处理返回结果
     * @param body
     * @param methodParameter
     * @param mediaType
     * @param aClass
     * @param serverHttpRequest
     * @param serverHttpResponse
     * @return
     */

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        System.out.println("In beforeBodyWrite() method of "






请到「今天看啥」查看全文