切面+注解优雅接口结果解析

2020-05-16  本文已影响0人  X作业写完了吗

互联网飞速,无论公司大小,内部都会有各种系统,系统间调用随处可见。
作为开发人员每天都跟接口打交道,解析接口结果的代码占满屏幕。
but,接口返回结果格式大同小异,洁癖的毛病是不是又要犯了?

   {
        "data":  "ok",   //data有时是result,不同的系统有不同的名字
        "msg": "ok",    //msg可能是message
        "status": 200   //status可能是code
    }

经常看到的代码是这样的

结果处理起来挺简单的,像这样

        String response ;
        try {
            response = orderListFeign.query(xxx);
        } catch (RpcException e) {
            logger.error("参数:{}  , error:{}", xxx,e);
            throw new BusinessException("xxx");
        }
        JSONObject json = JSONObject.fromObject(response);
        String status =  json.getString("status") ;
        if(!"1".equals(status)) {
            throw new BusinessException(json.getString("msg"));
        }
        JSONArray data = json.getJSONArray("data");
        // resolve data

上面的代码遍布整个项目,这样不好吧[甚至代码更差],let me see?

状态值、错误提示、参数统一处理吧?切面 ,自定义注解试试吧 ?

talk is cheap

先定义个注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseResolve {
    String codeKey() default "status";
    int codeSuccessValue() default 1;
    String dataKey() default "data";
    String messageKey() default "msg";
}

哪里需要@哪里,仔细看两个的区别

@FeignClient(name = "orderName", url = "${xxx1.server.domain}", configuration = CustomFeignConfig.class)
public interface OrderListFeign{
    @ResponseResolve // 接口返回的json是 status,msg,data
    @RequestMapping(value = "/api/order/query", method = RequestMethod.GET)
    String query(@RequestParam String code);
}

@FeignClient(name = "addressName", url = "${xxx2.server.domain}", configuration = CustomFeignConfig.class)
public interface AddressFeign{
    @ResponseResolve(codeKey="code",dataKey="result") // 接口返回的json是 code,msg,result
    @RequestMapping(value = "/api/address/query", method = RequestMethod.GET)
    String query(@RequestParam String code);
}

Aspect处理一下吧

@Slf4j
@Aspect
@Component
public class ResponseAspect {

    private String getArgs(Object[] argsObj){
        return  Arrays.stream(argsObj).filter(e->e!=null).map(e->e.toString()).collect(Collectors.joining(","));
    }

    @Around("@annotation(respResolve)")
    public Object rpcBasicResolve(JoinPoint joinPoint, ResponseResolve respResolve){
        String args = getArgs(joinPoint.getArgs());
        String method = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();
        Object response ;
        try {
            response = ((ProceedingJoinPoint)joinPoint).proceed();
        } catch (Throwable throwable) {
            log.error("api调用异常,method:{} ,args:{} ",method, args);
            throw new RpcException("api调用异常");
        }
        JSONObject result = JSON.parseObject(response.toString());
        if(!Integer.valueOf(respResolve.codeSuccessValue()).equals(result.getInteger(respResolve.codeKey()))){//根据注解中的codeKey与codeSuccessValue 统一判断返回状态
            String message = result.getString(respResolve.messageKey());//根据注解获取提示消息
            log.error("api调用接口 method:{} ,args:{} ,msg : {}",method, args,message);
            throw new BusinessException(message);
        }
        return result.getString(respResolve.dataKey());// 根据注解中的data属性取得结果
    }
}

service开心了,直接取得的结果内容

相比之前一堆代码是不是省劲多了
不用考虑状态码是code还是status ,result还是data了

String data = orderListFeign.query(xxx);

现在看是不是优秀了一点点

上一篇下一篇

猜你喜欢

热点阅读