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

简介: 公司从大厂挖了一个资深工程师,他写的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!老哥们三连点个赞!



相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
人工智能 安全 API
Agent 工程师绕不开的必修课:API 网关 vs API 管理
本文探讨了“API管理”与“API网关”的起源、发展及差异,二者分别服务于API生命周期的不同阶段。API网关从流量网关演进至AI网关,承担运行时请求控制;API管理则从接口文档化发展到商业化平台,关注全生命周期治理。两者在实际应用中协同工作,通过分层架构和策略联动实现高效运营。未来,随着大模型应用的兴起,AI网关和MCP Server管理将成为新趋势,推动API技术迈入智能化和服务化的新阶段。
Agent 工程师绕不开的必修课:API 网关 vs API 管理
|
9月前
|
人工智能 安全 机器人
麻省理工科技评论发布2026年十大突破性技术,AI独占四席
《麻省理工科技评论》2026年“十大突破性技术”榜单发布,AI技术占据四席,涵盖超大规模数据中心、机制可解释性、AI陪伴与生成式编码,彰显其主导地位。榜单不仅反映技术从“能做”到“该做”的转向,更揭示AI正深度融入社会骨骼,推动算力、伦理与产业变革,开启智能新纪元。
2362 7
|
存储 Java 数据库连接
技术好文:quartz基本介绍和使用
技术好文:quartz基本介绍和使用
775 0
|
9月前
|
存储 编解码 Cloud Native
全链路解析:基于云原生架构的 Bilibili 视频下载引擎实现
本文深入解析基于云原生架构的B站视频下载引擎,涵盖DASH协议分析、音视频分片下载、FFmpeg无损合成及阿里云Serverless部署。结合异步任务编排、OSS存储与反爬策略,实现高效、合规的全链路流媒体解析,适用于离线学习与弱网播放场景。(238字)
|
10月前
|
人工智能 IDE 数据可视化
携手中国科学院青年科学家,我们上线了这款AI科研助手
中国科学院大学他山协会推出AI科研助手「他山科研IDE」,已登陆阿里云云工开物平台及云市场。该工具支持文献检索、数据分析、论文撰写等全流程,助力科研自动化。同期,“Agent for Science”实训营将于12月启动,提供系统课程与前沿讲座,由阿里云提供模型与算力支持,推动AI赋能科研创新。
706 0
|
9月前
|
存储 Linux 文件存储
深入理解Linux文件系统(从零开始掌握文件存储与管理)
本教程深入浅出地讲解Linux文件系统核心机制,涵盖ext4文件系统、inode结构、磁盘管理及常用命令(如df、ls -i、lsof等),揭示文件存储原理与常见问题(如删除文件后空间未释放)的根源,助你掌握Linux底层知识,提升系统管理能力。
|
11月前
在基于DEB的系统如Debian 11和Debian上,如何移除Swap分区
在执行这些步骤的过程中,应当以谨慎为原则,保证每个步骤都被正确完成。如果不确定某些操作,建议进行必要的备份,或在专业人士的指导下操作。
469 3
|
数据采集 存储 人工智能
AI 模型:数据收集和清洗
AI 模型:数据收集和清洗
2119 2
|
机器学习/深度学习 人工智能 运维
金融系统宕机一分钟,损失就是百万?聊聊智能化运维该怎么玩!
金融系统宕机一分钟,损失就是百万?聊聊智能化运维该怎么玩!
408 11
|
存储 监控 数据可视化

热门文章

最新文章