# mysql **Repository Path**: mjlfto/mysql ## Basic Information - **Project Name**: mysql - **Description**: 自定义项目,瞎起名 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-09-13 - **Last Updated**: 2021-10-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # eCode #### 介绍 错误码配置,以往的项目中, 我们通常是将错误码用一个枚举类进行统计,这样这样使用方便,但是随着项目组件增大,对与错误码的关联和查看相对不是那么方便,更多的时候可能出现相同的错误有多个描述,而且如果多个系统协同工作, 设计错误码转换,我们也没有办法进行错误码关联,如果能用一个统一的错误码管理系统将所有系统的错误码进行管理, 这样可以邮箱的规范化这些错误码 这里我们不描述如何统一管理错误码,而是解决另一个问题, 当错误码被统一管理起来后, 我们如何才能向原理一样方便快捷的对对这些错误码进行使用,而且不用编写过多的代码,这里想到了lombok工具,他是如何通过注解的方式使得我们在编写代码的使用可以省去编写很多雷同的代码,原理不多说,大家可以去看一下lombok的源码和了解一下jsr269 该项目中ecny-lombok为错误码模块,主要用途是通过向lombok @Getter注解相同的方式可以将统一管理起来的错误码在编译时生成到我们的class文件中,注意不要在意模块命名 通过该模块完成编译后, 还有一个很严峻的问题, 那就是我们在idea工具中并没有编写这些错误码, 那么我们如果才能通过ENUM.xxx的方式使用这些枚举值, 答案时学习lombok插件, 我们同样需要需要一个关于错误码的插件,这里我直接fork idea-lombok-plugin插件,在此基础上进行扩展,但是针对enum的属性操作太过麻烦,所以实现结果有点不敬人意。 https://gitee.com/mjlfto/lombok-intellij-plugin #### 原理 首先定义一个注解类,通过该注解类配置错误码数据来源,目前支持Mysql数据库,http服务,项目resources配置, 本地文件配置,以及自定义数据来源 支持的数据格式有text文本格式,JSON数据格式, 同时还支持自定义数据格式, 需要注解的是,mysql配置是, 需要使用json格式对数据进行解析 ####数据源配置类型 ~~~ MYSQL("MYSQL", "mysql数据库配置"), HTTP("HTTP", "HTTP服务器配置"), PROJECT("PROJECT", "项目配置"), LOCALPATH("LOCALPATH", "本地配置"), OTHER("OTHER", "其他数据来源配置") ~~~ #### 数据格式配置 ~~~ JSON("JSON", "json配置类型"), TEXT("TEXT", "TEXT配置类型"), OTHER("OTHER", "自定义配置类型") ~~~ ``` /** * @ClassName ErrorCode * @Author mjlft * @Date 2021/9/25 8:42 * @Version 1.0 * @Description 错误码注解 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface ErrorCode { //默认数据类型 CodeDataTypeEnum dataType() default CodeDataTypeEnum.JSON;; //数据来源 CodeDataFromEnum dataFROM() default CodeDataFromEnum.PROJECT; //mysql数据地址 String mysqlUrl() default ""; String mysqlTableName() default ""; String mysqlUserName() default ""; String mysqlUserPass() default ""; //项目中数据配置路径 String projectConfigPath() default "code.conf"; //本地配置路径 String localPath() default ""; //Http 配置url String configUrl() default ""; //其他配置数据格式,需要自行解析使用 String otherConfig() default ""; //数据获取构建,要求集成CodeDataPullBuilder String customDataPullBuilder() default ""; //自定义数据解析类 String customDataParseClass() default ""; String sys() default ""; String model() default ""; String version() default ""; } ``` #### class代码生成核心代码 以下部分是代码生成部分, 其中有一个问题, 那就是创建枚举数据非常复杂,所以我这里需要在枚举类中添加一个名为DEFAULT_ERROR_CODE值, 并且在生成 数据时通过这个数据进行拷贝,然后更改其中部分参数,如果有大能知道怎么直接创建,可以办法进行改善 ~~~ @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes("com.ecode.annotation.ErrorCode") @AutoService(Processor.class) public class ErrorCodeProcessor extends AbstractProcessor { private Messager messager; // 编译时期输入日志的 private JavacTrees javacTrees; // 提供了待处理的抽象语法树 private TreeMaker treeMaker; // 封装了创建AST节点的一些方法 private Names names; // 提供了创建标识符的方法 private ErrorCode errorCode; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); this.messager = processingEnv.getMessager(); this.javacTrees = JavacTrees.instance(processingEnv); Context context = ((JavacProcessingEnvironment) processingEnv).getContext(); this.treeMaker = TreeMaker.instance(context); this.names = Names.instance(context); } @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { Set elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(ErrorCode.class); elementsAnnotatedWith.forEach(e -> { ErrorCode errorCode = e.getAnnotation(ErrorCode.class); JCTree tree = javacTrees.getTree(e); tree.accept(new TreeTranslator() { @Override public void visitClassDef(JCTree.JCClassDecl jcClassDecl) { List jcVariableDeclList = List.nil(); for (JCTree jcTree : jcClassDecl.defs) { if (jcTree.getKind().equals(Tree.Kind.VARIABLE)) { JCTree.JCVariableDecl jcVariableDecl = (JCTree.JCVariableDecl) jcTree; if(jcVariableDecl.name.toString().equals("DEFAULT_ERROR_CODE")){ ErrorCodeBuilder builder = new DefaultErrorCoderBuilder(); Set errorCodeDOS = builder.parseErrorCode(errorCode); errorCodeDOS.forEach(errorCodeDO -> { jcClassDecl.defs = jcClassDecl.defs.prepend(makeVariableDecl(errorCodeDO, jcClassDecl, jcVariableDecl)); }); } jcVariableDeclList = jcVariableDeclList.append(jcVariableDecl); } } super.visitClassDef(jcClassDecl); } }); }); return true; } public JCTree.JCVariableDecl makeVariableDecl(ErrorCodeDO errorCodeDO, JCTree.JCClassDecl jcClassDecl, JCTree.JCVariableDecl jcVariableDecl ){ JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) jcVariableDecl.clone(); var.name = names.fromString(errorCodeDO.buildCode()); JCTree.JCExpression paramCode = treeMaker.Literal(errorCodeDO.buildCode()); JCTree.JCExpression paramMsg = treeMaker.Literal(errorCodeDO.getMsg()); List params = List.of(paramCode, paramMsg); JCTree.JCNewClass newItem = treeMaker.NewClass( null, List.nil(), treeMaker.Ident(names.fromString(jcClassDecl.name.toString())), params, null ); var.init = newItem; return var; } } ~~~ #### 使用 代码中加入该模块作为一来,然后编写向如下这样的枚举类,并添加@ErrorCode注解,配置相应的数据来源,数据解析格式,然后 编译在对应的class文件中就会出现相应的错误码属性 ![img.png](img.png) ```aidl @ErrorCode( dataType = CodeDataTypeEnum.JSON, dataFROM = CodeDataFromEnum.MYSQL, mysqlUrl = "jdbc:mysql://xxx:3306/sql_Test", mysqlUserName = "xxx", mysqlUserPass = "xxx", mysqlTableName = "code" ) public enum ErrorException { DEFAULT_ERROR_CODE("DEFAULT_ERROR_CODE", "默认错误"); private String code; private String msg; ErrorException(String code, String msg) { this.code = code; this.msg = msg; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } } ``` 如果需要在idea中出现自动代码提示, 那么还需要结合上述描述中的插件使用 #### 注意 目前插件只是做了粗陋的实现,效率非常地下,并且枚举类型的PSI创建非常复杂,个人还没有研究透,插件暂时使用 常量的方式代替,能做到代码提示,并且能正常编译运行, 但是目前比较消耗资源,感兴趣的朋友可以自行优化,’ 如果知道创建枚举的属性创建方式,感谢赐教! #### 问题 软件架构说明 #### 安装教程 1. xxxx 2. xxxx 3. xxxx #### 使用说明 1. xxxx 2. xxxx 3. xxxx #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)