公司从大厂挖了一个资深工程师,他写的Controller代码同事都说漂亮! 下

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 公司从大厂挖了一个资深工程师,他写的Controller代码同事都说漂亮! 下

2. NOT统一响应

  • 不开启统一响应原因

开发小哥是开心了,可是其他系统就不开心了。举个例子:我们项目中集成了一个健康检测的功能,也就是这货

@RestController
public class HealthController {
    @GetMapping("/health")
    public String health() {
        return "success";
    }
}

公司部署了一套校验所有系统存活状态的工具,这工具就定时发送get请求给我们系统

  • “兄弟,你死了吗?”
  • “我没死,滚”
  • “兄弟,你死了吗?”
  • “我没死,滚”

是的,web项目的本质就是复读机。一旦发送的请求没响应,就会给负责人发信息(企业微信或者短信之类的),你的系统死啦!赶紧回来排查bug吧!让大家感受一下。每次看到我都射射发抖,早上6点!我tm!!!!!

好吧,没办法,人家是老大,人家要的返回不是

{
  "code": 1000,
  "msg": "请求成功",
  "data": "success"
}

人家要的返回只要一个success,人家定的标准不可能因为你一个系统改。俗话说的好,如果你改变不了环境,那你就只能我****

  • 新增不进行封装注解

因为百分之99的请求还是需要包装的,只有个别不需要,写在包装的过滤器吧?又不是很好维护,那就加个注解好了。所有不需要包装的就加上这个注解。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotControllerResponseAdvice {
}

然后在我们的增强过滤方法上过滤包含这个注解的方法

@RestControllerAdvice(basePackages = {"com.bugpool.leilema"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        // response是ResultVo类型,或者注释了NotControllerResponseAdvice都不进行包装
        return !(methodParameter.getParameterType().isAssignableFrom(ResultVo.class)
                || methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class));
    }
    ...

最后就在不需要包装的方法上加上注解

@RestController
public class HealthController {
    @GetMapping("/health")
    @NotControllerResponseAdvice
    public String health() {
        return "success";
    }
}

这时候就不会自动封装了,而其他没加注解的则依旧自动包装

image.png

五、统一异常

每个系统都会有自己的业务异常,比如库存不能小于0子类的,这种异常并非程序异常,而是业务操作引发的异常,我们也需要进行规范的编排业务异常状态码,并且写一个专门处理的异常类,最后通过刚刚学习过的异常拦截统一进行处理,以及打日志

1.异常状态码枚举,既然是状态码,那就肯定要实现我们的标准接口StatusCode

@Getter
public enum  AppCode implements StatusCode {
    APP_ERROR(2000, "业务异常"),
    PRICE_ERROR(2001, "价格异常");
    private int code;
    private String msg;
    AppCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

2.异常类,这里需要强调一下,code代表AppCode的异常状态码,也就是2000;msg代表业务异常,这只是一个大类,一般前端会放到弹窗title上;最后super(message);这才是抛出的详细信息,在前端显示在弹窗体中,在ResultVo则保存在data中

@Getter
public class APIException extends RuntimeException {
    private int code;
    private String msg;
    // 手动设置异常
    public APIException(StatusCode statusCode, String message) {
        // message用于用户设置抛出错误详情,例如:当前价格-5,小于0
        super(message);
        // 状态码
        this.code = statusCode.getCode();
        // 状态码配套的msg
        this.msg = statusCode.getMsg();
    }
    // 默认异常使用APP_ERROR状态码
    public APIException(String message) {
        super(message);
        this.code = AppCode.APP_ERROR.getCode();
        this.msg = AppCode.APP_ERROR.getMsg();
    }
}

3.最后进行统一异常的拦截,这样无论在service层还是controller层,开发人员只管抛出API异常,不需要关系怎么返回给前端,更不需要关心日志的打印

@RestControllerAdvice
public class ControllerExceptionAdvice {
    @ExceptionHandler({BindException.class})
    public ResultVo MethodArgumentNotValidExceptionHandler(BindException e) {
        // 从异常对象中拿到ObjectError对象
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        return new ResultVo(ResultCode.VALIDATE_ERROR, objectError.getDefaultMessage());
    }
    @ExceptionHandler(APIException.class)
    public ResultVo APIExceptionHandler(APIException e) {
        // log.error(e.getMessage(), e); 由于还没集成日志框架,暂且放着,写上TODO
        return new ResultVo(e.getCode(), e.getMsg(), e.getMessage());
    }
}

4.最后使用,我们的代码只需要这么写

if (null == orderMaster) {
  throw new APIException(AppCode.ORDER_NOT_EXIST, "订单号不存在:" + orderId);
}
{
  "code": 2003,
  "msg": "订单不存在",
  "data": "订单号不存在:1998"
}

就会自动抛出AppCode.ORDER_NOT_EXIST状态码的响应,并且带上异常详细信息订单号不存在:xxxx。后端小哥开发有效率,前端妹妹获取到2003状态码,调用对应警告弹窗,title写上订单不存在,body详细信息记载"订单号不存在:1998"。同时日志还自动打上去了!666!老哥们三连点个赞!



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
开发框架 Java .NET
工作这么多年了,我为什么还在考证
毕业以来参加工作后,一直以来认为考证没有啥用处。一方面,因为找工作太过顺利,那会儿找工作也没有看到别人拿什么证去找工作,也没有看到那家公司的招聘广告上写需要什么什么证书。另一方面,由于才从学校出来对于学习考试有种天然的排斥。想想这么多年以来一直都是在学习考试。好不容易毕业了那还不好好放松一下。现在回想起来真是too young,too simple!
232 1
|
12月前
|
运维 架构师 网络架构
公司架构师说不写代码,我直接怼他了!
公司架构师说不写代码,我直接怼他了!
63 2
|
人工智能 运维 中间件
推荐一位阿里朋友的巨作,助你成为顶尖服务端开发者——《服务端开发:技术、方法与实用解决方案》
推荐一位阿里朋友的巨作,助你成为顶尖服务端开发者——《服务端开发:技术、方法与实用解决方案》
566 0
|
消息中间件 JSON 前端开发
公司从大厂挖了一个资深工程师,他写的Controller代码同事都说漂亮! 上
公司从大厂挖了一个资深工程师,他写的Controller代码同事都说漂亮! 上
|
存储 程序员 项目管理
六年团队Leader实战秘诀|程序员最重要的八种软技能
笔者在带团队的六年中发现,程序员们在职场都有一个共同的困扰:“好像写代码都没什么问题了,日常工作基本上都是应付业务需求的开发,好像找不到其他的更大的附加价值了,我应该找一些什么样的发力点才能让我的价值更突出呢?” 。本文将和大家聊聊程序员的软技能。
六年团队Leader实战秘诀|程序员最重要的八种软技能
|
敏捷开发 架构师 程序员
数字化转型项目做了多年,主架构师都绝望了:当初就不应该用外包!
数字化转型已经成为了企业发展的主旋律,甚至成为各国的发展战略,疫情的发生进一步加速了全球数字技术的产业化应用步伐。“数字化”说起来容易做起来难,新兴技术变化如此之快,以至于大多数组织内部 IT 团队缺乏相应的技术能力或业务知识,如若设计或实施不当就有可能将“转型”变为一场灾难。
218 0
数字化转型项目做了多年,主架构师都绝望了:当初就不应该用外包!
|
Java 测试技术 项目管理
15 年经验资深测试经理的经验分享:测试人职场晋升“潜规则”
本文整理自霍格沃兹测试学院「测试开发在线沙龙」主题分享《测试人晋升指南:如何做好个人绩效管理》,略有删减。文末链接进阶学习。
15 年经验资深测试经理的经验分享:测试人职场晋升“潜规则”
|
中间件 程序员
历经外企、创业公司、大厂的程序员告诉你:第一份工作有多重要!
  笔者毕业5年,先后经历了创业公司,外企和国内一线互联网公司。本文用经历告诉你,第一份工作对于你的重要性和怎么选择第一份工作。   笔者第一份工作去了外企,也正是因为去了外企让我学会了很多,也塑造了自己的编程习惯和工作方式,时至现在也未曾改变。其实公司就是学校,第一家公司对你的工作习惯的塑造很重要。因为是外企,公司的文化相对扁平,没有尔虞我诈也没有勾心斗角。举几个具体的公司特质说一下对笔者的职业习惯的塑造。   新人培训:这里的新人培训不同其他公司,它会有6个月试用期,这6个月会有一个老师专门负责你的成长,定期给你 Review 表现。同时每一个月所有和你接触过的人会去一个小黑屋说你“坏
266 0
|
安全 架构师 网络协议
Google 测试总监聊如何经营成功的测试职业生涯
​重温经典:本文是前 Google 测试总监 James A. Whittaker 的经典分享,成文已经快 10 年了,但经典却总是常读常新,推荐给各位测试行业的从业人员。:)
下一篇
无影云桌面