JAVA轻量级错误码设计最佳实践

2021-10-31日志、错误码、异常设计 异常的作用 异常应当描述导致当前异常发生的原因 根据异常栈快速定位到异常发生的位置 结合异常描述和异常栈解决异常 异常的处理流程图 try代码块中可能会抛出多种异常,该怎么捕获? 如果多种异常共有一个父类,并且处理它们的方式是一致的,那么我们可以catch这个父类并进行处理;如果多种异常的处理方式并不相同,那么先catch子类异常,然后逐步升级,最后catch级别最高的父类异常,并在每个catch中定义相应的处理逻辑。 Throwable的抓取规约 【强制】在调用RPC、二方包、或动态生成类的相关方法 阅读详情

概述

目前公司团队项目中返回异常都没有错误码,如果遇到错误提示只会返回一个错误信息。随着微服务组件越来越多,这样给不同团队之间沟通交流、排查错误带来了极大的困难。于是在网上搜索了一番以后,决心要重新设计下错误码机制.

设计目标

先谈公司现状,我们目前就是通过抛出Java异常,将异常信息Message返回给其他服务或者前端,这样有什么问题?

  1. 不好交流沟通,本来只要通过一个明确的错误码就能沟通清楚,用异常信息会带来模糊性。
  2. 只有异常消息,很难定位具体是哪个服务的原因,具体原因是什么,因为异常消息比较灵活,可能是不同服务、同服务不同模块都有相似的。

因此,我们需要设计一套错误码机制,那一个优秀的错误码设计应该达到什么目标或者有什么原则呢?

我们可以参考下阿里巴巴《Java 开发手册》- 异常日志-错误码的内容。

错误码的制定原则:快速溯源、简单易记、沟通标准化。

说明:错误码想得过于完美和复杂,就像康熙字典中的生僻字一样,用词似乎精准,但是字典不容易随身携带并且简单易懂。

正例:错误码回答的问题是谁的错?错在哪?

1)错误码必须能够快速知晓错误来源,可快速判断是谁的问题。

2)错误码易于记忆和比对(代码中容易 equals)。

3)错误码能够脱离文档和系统平台达到线下轻量化地自由沟通的目的。

错误码设计

错误码设计,主要考虑下面几个点:

  1. 错误码的格式该是什么样?
  2. 错误码在java中该如何表示,枚举,常量?
  3. 错误码怎么保证唯一性,开发可能不知道已经被占用了,该如何避免?
  4. 错误码该如何返回?

错误码格式

错误码格式一方面要求精简,同时也要体现出它的服务组件和模块信息。

错误码的数据类型可以是字符串,比如"SDM_USER_001", 也可以用数值表示10203等,他们可以利弊,用字符串可能比较直观,用数字比较精简,但是使用纯数字来进行错误码编排不利于感性记忆和分类。

我们本例采用了6位数字的方式演示,前面两位是项目编码,中间两位是模块编码,最后3位是错编码:

错误码在项目中表示

错误码在项目中该如何呈现呢?

  1. 错误码统一通过枚举类表现,可以轻松的表示枚举的代码和对应的含义,易于维护。
  2. 按照项目+模块粒度定义成多个错误码枚举类,也就是一个模块一个错误码的枚举类。
  3. 定义出公共的错误码的接口,让各个服务组件、模块实现,统一错误码的参数。
  4. 分离出项目模块编码,增加模块编码枚举的复用性。

模块接口代码如下:

public interface ProjectModule {

    /**
     * 项目编码
     */
    int getProjectCode();

    /**
     * 模块编码
     */
    int getModuleCode();

    /**
     * 项目名称
     */
    String getProjectName();

    /**
     * 模块名称
     */
    String getModuleName();
}

 具体的模块:

@Getter
@AllArgsConstructor
public enum UserProjectCodes implements ProjectModule {
    /**
     * 登录模块
     */
    LOGIN(1, 1, "用户中心", "登录模块"),
    /**
     * 用户管理模块
     */
    USER(1, 2, "用户中心", "用户模块");

    private int projectCode;
    private int moduleCode;
    private String projectName;
    private String moduleName;

}

错误码接口代码如下:

public interface ErrorCode {

    /**
     * 最细粒度code,不包含project、module信息
     */
    int getNodeNum();

    /**
     * 异常信息 英文
     */
    String getMsg();

    /**
     * 拼接project、module、node后的完整的错误码
     */
    default int getCode() {
        return ErrorManager.genCode(this);
    }

    default ProjectModule projectModule(){
        return ErrorManager.projectModule(this);
    }
}

具体错误码枚举:

@Getter
public enum UserErrorCodes implements ErrorCode {
    /**
     * 用户不存在
     */
    USER_NOT_EXIST(0, "用户名不存在"),
    /**
     * 密码错误
     */
    PASSWORD_ERROR(1, "密码错误");

    private final int nodeNum;
    private final String msg;
    
    UserErrorCodes(int nodeNum, String msg) {
        this.nodeNum = nodeNum;
        this.msg = msg;
        // 注册错误码,也就是绑定这个错误码属于哪个模块的
        ErrorManager.register(UserProjectCodes.USER, this);
    }
}

错误码防重校验

错误码要求全局唯一,不能存在重复冲突,那么怎么通过程序来做一个校验。

我们在上面定义错误码枚举的构造函数中,有了一个注册错误码的操作,我们其实可以在这里做重复校验的逻辑。

ErrorManager.register(UserProjectCodes.USER, this);
public static void register(ProjectModule projectModule, ErrorCode errorCode) {
        Preconditions.checkNotNull(projectModule);
        Preconditions.checkArgument(projectModule.getProjectCode() >= 0);
        Preconditions.checkArgument(projectModule.getModuleCode() >= 0);
        Preconditions.checkArgument(errorCode.getNodeNum() >= 0);
        int code = genCode(projectModule, errorCode);
        // 如果存在重复,抛出异常
        Preconditions.checkArgument(!GLOBAL_ERROR_CODE_MAP.containsKey(code), "错误码重复:" + code);
        GLOBAL_ERROR_CODE_MAP.put(code, errorCode);
        ERROR_PROJECT_MODULE_MAP.put(errorCode, projectModule);
    }

这样就会抛出异常,提前知道存在重复的错误码。

返回错误码信息

接口调用后,该如何返回错误码信息呢? 一般我们的项目中都会定义统一的返回对象,该对象一般会有code, msg信息,如下:

public class Result<T> extends ErrorInfo {

	private int code;

    private String msg;

    private T data;

    .....
    
}
  1. 可以直接通过调用Result方法返回

  1. 通过统一异常处理返回,下面详细讲解

错误码和异常

错误码和异常往往是分不开的,可以通过设计良好的异常体系,将错误码优雅的返回给调用方:

  1. 自定义异常, 自定义异常中包含了错误信息的属性字段
  2. 如果程序逻辑中出错,可以设置对应的错误码信息,抛出自定义异常
  3. 统一拦截自定义异常,后去其中的异常信息,返回给请求方

异常体系:

抽象出异常的统一接口:

public interface IErrorCodeException {
    /**
     * 错误信息,获取异常的错误信息
     */
    ErrorInfo getErrorInfo();

    /**
     * 模块信息,获取异常属于哪个模块的
     */
    ProjectModule projectModule();
}

 

public class ErrorInfo {
    static final Map<Integer, ErrorInfo> NO_PARAM_CODES_MAP = new ConcurrentHashMap<>();
    static final Map<String, ErrorInfo> ERROR_MSG_CODES_MAP = new ConcurrentHashMap<>();
    /**
     * 错误码
     */
    @Getter
    private final int code;
    /**
     * 返回错误信息 英文
     */
    @Getter
    private final String msg;
    
    .......
}

自定义运行时异常抽象基类:

@Getter
public abstract class BaseRuntimeException extends RuntimeException implements IErrorCodeException{

    final ErrorInfo errorInfo;

    protected BaseRuntimeException(String message) {
        super(message);
        this.errorInfo = ErrorInfo.parse(message);
    }

    protected BaseRuntimeException(String message, Throwable cause) {
        super(message, cause);
        this.errorInfo = ErrorInfo.parse(message);
    }

    protected BaseRuntimeException(Throwable cause) {
        super(cause);
        this.errorInfo = ErrorInfo.parse(cause.getMessage());
    }

    protected BaseRuntimeException(ErrorInfo errorInfo) {
        super(errorInfo.toString());
        this.errorInfo = errorInfo;
    }

    protected BaseRuntimeException(ErrorCode errorCode) {
        this(ErrorInfo.parse(errorCode));
        ProjectModule.check(projectModule(), errorCode.projectModule());
    }

    protected BaseRuntimeException(ErrorCode errorCode, Object... args) {
        this(ErrorInfo.parse(errorCode, args));
        ProjectModule.check(projectModule(), errorCode.projectModule());
    }

    @Override
    public ErrorInfo getErrorInfo() {
        return errorInfo;
    }
}

具体的模块异常:

public class UserException extends BaseRuntimeException {

    protected UserException(String message) {
        super(message);
    }

    protected UserException(String message, Throwable cause) {
        super(message, cause);
    }

    protected UserException(Throwable cause) {
        super(cause);
    }

    protected UserException(ErrorInfo errorInfo) {
        super(errorInfo);
    }

    protected UserException(ErrorCode errorCode) {
        super(errorCode);
    }

    protected UserException(ErrorCode errorCode, Object... args) {
        super(errorCode, args);
    }

    @Override
    public ProjectModule projectModule() {
        return UserProjectCodes.USER;
    }
}

这里的异常体系中绑定了属于哪个模块,主要是从严谨性的角度出发,因为错误码本身是绑定了模块的,这时候再将错误码设置到异常中,可以做一个校验,是否是属于同一个模块。

统一拦截异常返回

通过spring提供的异常拦截注解 @ControllerAdvice ,实现对异常的统一处理。

@ResponseBody
    @ExceptionHandler(value = Throwable.class)
    public ResponseEntity<Result<?>> processException(HttpServletRequest request, Exception e) {
        Pair<Throwable, String> pair = getExceptionMessage(e);
        // 如果是自定义异常
        if (e instanceof IErrorCodeException) {
            if (e.getCause() != null) {
                log.error("error, request: {}", parseParam(request), e.getCause());
            } else {
                log.error("error: {}, request: {}", pair.getRight(), parseParam(request));
            }
            ErrorInfo errorInfo = ((IErrorCodeException) e).getErrorInfo();
            Result<?> apiResult;
            if (errorInfo == null) {
                apiResult = Result.error(SystemErrorCodes.SYSTEM_ERROR.getCode(), pair.getRight());
            } else {
                apiResult = Result.error(errorInfo.getCode(), errorInfo.getMsg());
            }
            return new ResponseEntity<>(apiResult, HttpStatus.OK);
        }
        log.error("error, request: {}", parseParam(request), e);
        // 返回系统异常
        Result<String> errorResult = Result.error(SystemErrorCodes.SYSTEM_ERROR.getCode(), pair.getLeft().getClass().getSimpleName() + ": " + pair.getRight());
        return new ResponseEntity<>(errorResult, HttpStatus.OK);
    }

系统错误码处理

因为不同模块会存在一些公共的系统异常,针对这种,我们需要内置定义一个系统的错误码:

public enum SystemErrorCodes implements ErrorCode {

    SUCCESS(0, "ok"),
    SYSTEM_ERROR(1, "system error");

    private final int nodeNum;
    private final String msg;

    SystemErrorCodes(int nodeNum, String msg) {
        this.nodeNum = nodeNum;
        this.msg = msg;
        ErrorManager.register(SystemProjectModule.INSTANCE, this);
    }

}

方便查看错误码表

最后这个也很关键,往往我们需要看下系统中全量的错误码,这时候我们可以开放一个接口获取系统中全量错误码,或者将他们展示到前端页面中。

public static List<TreeNode> getAllErrorCodes() {
        return ERROR_PROJECT_MODULE_MAP.entrySet().stream()
                .sorted((it1, it2) -> ERROR_CODE_COMPARATOR.compare(it1.getKey(), it2.getKey()))
                .collect(Collectors.groupingBy(Map.Entry::getValue,
                        Collectors.mapping(Map.Entry::getKey, Collectors.toList())))
                .entrySet()
                .stream()
                .sorted((it1, it2) -> PROJECT_MODULE_COMPARATOR.compare(it1.getKey(), it2.getKey()))
                .collect(Collectors.groupingBy(
                                e -> new TreeNode(e.getKey().getProjectCode(), e.getKey().getProjectName()),
                                Collectors.groupingBy(
                                        it -> new TreeNode(it.getKey().getModuleCode(), it.getKey().getModuleName()),
                                        Collectors.mapping(Map.Entry::getValue, Collectors.toList())
                                )
                        )
                )
                .entrySet()
                .stream()
                .map(e -> {
                    TreeNode top = e.getKey();
                    List<TreeNode> middleNode = e.getValue()
                            .entrySet()
                            .stream()
                            .map(e1 -> {
                                TreeNode key = e1.getKey();
                                List<TreeNode> leftNode = e1.getValue().stream()
                                        .flatMap(Collection::stream)
                                        .map(errorCode -> new TreeNode(errorCode.getCode(), errorCode.getMsg()))
                                        .collect(Collectors.toList());
                                key.setNodes(leftNode);
                                return key;
                            })
                            .collect(Collectors.toList());
                    top.setNodes(middleNode);
                    return top;
                })
                .collect(Collectors.toList());
    }

\

更多的想法和注意事项

在参考了阿里巴巴关于错误码和异常的规范后,梳理出了有效的几条,得出了更多的想法,大家可以根据自己的实际项目去做抉择:

  1. 错误码分类的另外一种格式规范, 也很合理,这样调用方基本知道是自己的问题还是谁的问题了。

2. 很多大型公司,会有统一开发平台,上面可以维护错误码,这样所以服务组件可以快捷查询、新建错误码,也不会重现重复的情况,当然,这一般都是中大型公司会有。

  1. 其实如果单纯是服务内部的前后端交互,可以直接通过异常抛出,更加简单。

总结

本文主要讲解了错误码设计的方案,希望对大家有帮助,如果有更好的方案设计,也可以留言,一起成长提高。

U盘安装单系统ubuntu10.04之全过程&拔掉U盘后系统无法启动 借助U盘把电脑装成ubuntu单系统之过程记录,以及遇到拔掉U盘后系统无法启动问题,电脑就显示: Non-System disk or disk error, replace and strike any key when ready 阅读详情

相关推荐

Unity程序化河流生成工具Waterways:从算法到实践的全流程解析

程序化内容生成(PCG)是游戏开发与三维建模领域的关键技术,它通过算法自动创建游戏内容,显著提升开发效率。其核心原理是将设计规则转化为可执行的代码逻辑,从而生成复杂、多样且符合自然规律的环境资产。在开放世界游戏和模拟经营类项目中,程序化生成技术能够快速构建大规模、高一致性的自然场景,如山川、森林与水体网络。Unity引擎作为广泛使用的开发平台,其地形系统与着色器管线为程序化工具的集成提供了强大基础。本文聚焦于利用Waterways这一Unity工具集,深入探讨如何通过模拟重力驱动、流量累积等自然水力原理,在

weixin_33690963的博客 684

怎么定义一套完成标准的JAVA枚举类型

在java代码中,接口返回有各种各样的状态,比如400 401 200 500 403等常见的http状态码,也有我们自定义的很多业务状态码。如果系统比较复杂,制定一套完整的标准的状态码是非常有必要的,这样比较方面BUG排查。

JAVA领域优质创作者,基于分片网络查询方法专利发明者。 1774

STM32超声波避障小车硬件设计与实时测距实现

超声波测距是嵌入式系统中经典的环境感知技术,其原理基于声波在空气中的传播时间与距离的线性关系,通过精确计时实现非接触式距离测量。该技术具备成本低、抗光干扰强、算法简洁等优势,广泛应用于智能小车、机器人避障、液位监测等场景。工程落地的关键在于硬件信号完整性(如5V/3.3V电平匹配)、微秒级定时精度(依赖高稳定外部晶振与输入捕获模式)以及强干扰环境下的数据鲁棒性(需软硬协同滤波)。本文以STM32F103C8T6为平台,深入解析HC-SR04模块的时序闭环控制、TIM3输入捕获双沿测量、L298N电机状态机驱

weixin_42578963的博客 295

Java枚举

本文章主要介绍了何为枚举,以及枚举的背景和定义、枚举的优缺点,以及将枚举与我们上节课所学的反射联系起来。

xinhang10的博客 1690

Enterprise Architect 中文经典教程

本文使用到的EA工程文件下载 一、Enterprise Architect简介 Enterprise Architect是一个对于软件系统开发有着极好支持的CASE软件(Computer Aided Software Engineering)。EA不同于普通的UML画图工具(如VISIO),它将支撑系统开发的全过程。在需求分析阶段,系统分析与设计阶段,系统开发及部署等方面有着强大的支持,...

2万+

别再手动折腾了!PICO Unity SDK 一键配置开发环境保姆级教程(含PDC串流调试)

本文详细介绍了PICO Unity SDK的一键配置功能,帮助开发者快速搭建VR开发环境。通过自动化配置流程,大幅减少手动设置时间,提升开发效率。文章还涵盖了PDC串流调试技巧和常见问题解决方案,是PICO VR开发的实用指南。

weixin_30335575的博客 453

java开发中异常处理的几种手段

然后在异常的地方将错误码和错误描述返回: 这是项目中经常使用的一种简单的手段,定义好枚举的错误码和错误描述直接返回给前端即可。有点简单,缺点是增加或者修改均需要编译、打包、重新部署等。 使用枚举的错误码 定义配置文件:errorCodeConfig.properties 读取配合文件的工具类: 返回值拦截器: 当发生异常时便可以将错误码转成错误描述返回给前端。该办法有一个好处是可以修改配置文件,然后重新启动程序就可以实现错误描述的修改,免去了编译代码和重新发版的麻烦。但是拦

weixin_41670928的博客 1341

基于YOLOv8的城市违建识别系统:从数据集构建到UI界面实现

YOLOv8是Ultralytics公司于2023年推出的最新一代YOLO(You Only Look Once)系列目标检测算法。更高效的骨干网络设计改进的锚框机制更精确的损失函数支持分类、检测、分割等多任务YOLOv8特别适合像违建识别这样的实时检测任务,能够在保持高精度的同时实现快速推理。

YOLO 675

错误码如何设计才合理?

一 前言 在工作中,接触过不少外部接口,其中包括:支付宝,微信支付,微博开发平台,阿里云等等。每家公司错误码风格都不尽相同,有使用纯数字的,有使用纯英文的,也有使用字母和数字组合的。也接触过很多内部系统,错误码设计也不尽相同。 错误码的输出路径 面向日志输出 服务内传递,最终是输出到日志。 域内服务间,比如同时大麦电商之间的系统,最终目的是输出到日志。 面向外部传递 域内向域外 服务端传递到前端 OpenAPI 错误码 内部不同域之间 错误码使用场景 通过错误码配置监控大

A1373712651的博客 2122

Swin Transformer 与 CNN 结合实现图像分类

Swin Transformer 与 CNN 结合实现图像分类。(含swin transformer 结构讲解,cnn网络搭建,代码)

这里是Mae。 5027

innovus:像ICC2一样设置placement label

ICC2有placement label/placement rule功能,能控制各种类型cell 之间的spacing规则,包括top和bottom edge的spacing。innovus也有相同的功能,以下示例方便大家了解用法。我们需要给所有OAI* cell之间设置一个spacing rule,让他们不要上下或者挨着。效果如下图,这个spacing指的是同一边的间距,不是cell间距。我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?

m0_61544122的博客 833

Java异常处理和最佳实践(含案例分析)

Java异常处理和最佳实践(含案例分析)

小虚竹的专栏 1874

拆解全球18大“支付清算”体系:CLS、中国、美国、欧洲、日本、mBridge...

拆解全球18大“支付清算”体系:CLS、中国、美国、欧洲、日本、mBridge...

银行信息系统应用架构详解 884

BizAssert:一个轻量级、生产就绪的 Java 业务断言工具类

BizAssert 是一个专为业务逻辑校验设计的轻量级 Java 断言库,灵感源自 Spring 的 Assert 类。它通过抛出带错误码的业务异常(而非标准异常)来优化企业应用中的服务层校验。核心特性包括:支持错误码枚举、Label 简化消息生成、占位符消息、返回值穿透式设计,以及可插拔的异常工厂机制。该库提供丰富的断言方法覆盖常见校验场景,零依赖且兼容 Java 8+,适合在复杂业务系统中实现一致的错误处理模式。

2403_89785620的博客 378

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

优雅的参数校验:如何设计一个轻量级断言工具类

为什么需要自定义断言工具类? 在业务系统开发中,参数校验是保证代码健壮性的第一道防线。尽管市面上已有类似Apache Commons Lang的Validate或Spring的Assert工具类,但实际开发中我们仍需自定义断言工具,主要原因包括: 统一异常体系:对接企业内部的错误码规范 业务语义强化:针对特定场景的校验逻辑封装 代码简洁性:避免重复的if-throw代码块

qq_62775328的博客 728

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

孤尽T31项目第5天-Java异常机制规约

文章目录前言一、Java异常机制1. 使用异常,日志为系统保驾护航2. C语言的“异常”烦恼3. Java异常处理流程4. Java异常处理机制5. Java异常体系二、异常处理设计与实践1. 异常抛出与捕获的原则2. try-catch-finally流程分析3. try with resource关闭资源的执行流程3. 特殊NPE场景及其处理对策三、日志设计1. 日志的功能2. 日志时效性规约3. 日志记录规约3. logback框架使用4. 日志通知5. 日志输出规约四、错误码设计1. 错误码规约五、

gzdxtantao的博客 470

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Web API国际化设计:从Accept-Language协商到多语言错误码

Web API国际化不是简单的前端语言切换,而是贯穿HTTP协议、数据建模与内容协商的系统工程。其核心在于遵循RFC 7231标准,利用Accept-Language请求头实现语义化内容协商,并通过区域设置(Locale)解耦语言、区域、时区与货币四维属性。技术价值体现在缓存友好性提升、跨系统集成合规性增强及错误处理可维护性升级;典型应用场景包括跨境电商API、SaaS多租户服务与出海移动应用后端。本文深入解析Accept-Language权重解析、ResolvedLocale四维建模、UTC时间存储与动态

391

枚举在编程中的应用与最佳实践

枚举(Enumeration)是编程中用于定义一组命名常量的数据类型,通过具名化处理提升代码可读性和安全性。其核心原理是将离散值映射为有意义的标识符,编译器可进行类型检查,避免魔法数字带来的维护难题。在工程实践中,枚举特别适用于状态机、配置管理等场景,如电商订单状态流转或命令行工具的参数选项。通过Java、Python等语言的枚举实现,开发者可以附加属性和方法,构建更强大的错误码体系或轻量级策略模式。合理使用枚举能显著提升代码质量,但需注意序列化兼容性和性能优化。本文通过实际案例,展示了枚举在提升代码可维护

weixin_33922672的博客 449

Java原生HttpURLConnection对接企业微信API:轻量级打卡数据拉取实战

在Java应用开发中,调用外部HTTP API是常见的集成需求。其核心原理是基于HTTP/HTTPS协议进行网络通信,通过请求-响应模型交换数据。掌握底层HTTP客户端技术,对于构建高可控性、低依赖的微服务或数据对接组件具有重要价值,尤其在需要避免第三方库依赖冲突或追求极致轻量的场景下。本文聚焦于企业微信打卡记录API对接这一具体应用,深入探讨如何使用Java标准库中的HttpURLConnection,从零构建一个稳健的HTTP请求引擎。内容涵盖Access Token管理、请求重试、分页处理及常见错误码

weixin_30231327的博客 323

轻量级开票系统数据库与API设计实战

开票系统是典型的业务驱动型财务应用,其核心在于准确表达法律效力、税务合规与资金流意图。理解发票(Invoicing)的本质——即作为债权凭证的结构化单据——是设计合理数据库与API的前提;在此基础上,轻量(Lightweight)并非功能删减,而是通过精准建模(如分离issue_date/due_date)、冗余固化(如unit_price锁定)、动词优先路由(如POST /invoice/issue)等手段,规避过度工程。这种设计直接支撑中小企业多币种、多税率、PDF交付、审计追溯等真实场景,同时保障高并

djph26741的博客 391

嵌入式轻量级规则引擎设计与实现

规则引擎是一种将业务逻辑与代码解耦的通用技术范式,其核心原理是通过可配置、可组合的条件判断单元实现动态策略执行。在资源受限的嵌入式系统中,传统硬编码if-else链导致维护困难、测试覆盖不足与部署僵化,而轻量级规则引擎凭借零动态内存、确定性执行和短路机制,在保障实时性(<5ms)与安全性(MISRA-C合规)的同时,显著提升固件策略迭代效率。该技术广泛应用于工业边缘网关、MCU端设备准入控制、OTA升级校验等场景,尤其适合需运行时策略隔离与跨平台复用的C/C++嵌入式环境,是嵌入式固件架构演进的关键实践方向

weixin_31688273的博客 239

进程、轻量级进程和线程的深度辨析

早期操作系统(如 DOS)一次只能运行一个程序,程序 = 进程,完全独占资源。随着多任务需求(如边听音乐边写文档),用户空间的线程需要内核支持才能被调度,早期操作系统(如 Solaris)引入cloneCLONE_VMLinux 内核用结构体描述一个 “执行单元”,它既可以是进程,也可以是线程(LWP)。pidmmmm_structmmstackparentchildrenLinux 内核调度器(CFS,完全公平调度器)以niceclonegettid()ps -eLf。

Mr_-G,一名勤奋底层软件开发工程师的博客 993

java 开源 server_simplewebserver: SimpleWebServer 是一款使用Java基于NIO编写的超轻量级开源Web Application Server...

SimpleWebServerSimpleWebServer 是一款使用Java基于NIO编写的超轻量级开源Web Application Server是否遇到有时候想做一些小的Web程序,但是迫于Java运行环境过于繁琐而迟迟没有下手,那么现在除了SpringBoot,广大的Java程序员又多了一个选择轻量级并不基于servlet,源代码仅3000行左右,jar包仅 0.1m 左右,零依赖,无x...

weixin_39554775的博客 419
上一篇: 关于Java 同步工具和组合类的线程安全性分析
下一篇: Java基础知识(知识点)
java_lujj
博客等级 码龄4年 18粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值