Skip to content
ww20081120 edited this page Mar 11, 2020 · 5 revisions

简介

定义公用的常量、工具类 采用了spring-boot方式启动, 启动类为Application, 也可以支持web方式启动

异常的定义

异常的顶级API是FrameworkException, 该类继承了RuntimeException,建议项目里面的异常都在最外层进行统一处理。

常见的异常有:

  • UtilException 工具类异常
  • ServiceException 业务服务异常
  • AssertException 断言错误
  • DaoException 数据库异常
  • InitializationException 初始化启动异常

另外每个异常都需要定义错误码, 系统提供的错误码在com.hbasesoft.framework.common.ErrorCodeDef, 框架的错误码在5位之内, 成功的错误码4位以内,错误的在10000~99999之间。 项目的错误码需要大于6位数字。

错误文件的描述在errorMessage.properties中维护, 如果想定义自己的项目的错误描述,可以在application.yml中 extend.errorMessage.files 扩张配置,多个用英文逗号分隔。

extend:
  errorMessage:
    files: errorMessage_msg.properties

资源文件获取

资源文件支持使用properties和yml两种方式进行配置,两种都写只从yml中读取。 application.yml文件中配置的内容可以使用com.hbasesoft.framework.common.utils.PropertyHolder中的方法来获取

PropertyHolderTest.java

@Test
public void getProperty() {
    String a = PropertyHolder.getProperty("test.str.str2");
    Assert.equals(a, "bcd", ErrorCodeDef.SYSTEM_ERROR_10001);

    a = PropertyHolder.getProperty("test.str.none", "abcdefg");
    Assert.equals(a, "abcdefg", ErrorCodeDef.SYSTEM_ERROR_10001);

    a = PropertyHolder.getProperty("test.int.int2");
    Assert.equals(a, "-1", ErrorCodeDef.SYSTEM_ERROR_10001);

    a = PropertyHolder.getProperty("test.long.long2");
    Assert.equals(a, "3000", ErrorCodeDef.SYSTEM_ERROR_10001);

    a = PropertyHolder.getProperty("test.bool.bool2");
    Assert.equals(a, "false", ErrorCodeDef.SYSTEM_ERROR_10001);
}

额外扩展的配置文件,可以在application.yml中通过extend.property.files 来扩展,多个用英文逗号分隔,代码中获取同application.yml一样

application.yml

project:
  name: demo

test:
  str:
    str1: abc
    str2: bcd
  int:
    int1: 1
    int2: -1
  long:
    long1: 1000
    long2: 3000
  bool:
    bool1: true
    bool2: false
    
extend:
  property:
    files: ext01.properties, ext02.yml
  errorMessage:
    files: ext_errorMessage.properties

项目启动时监听工具

项目中经常能遇到启动时就需要加载xxx功能的场景,例如项目启动时需要检查数据库表有没有创建,没有创建则需要创建相应的数据。 Spring默认已经支持了这种加载方式,但有些场景我们可能需要在Spring容器加载之前启动,我们提供了com.hbasesoft.framework.common.StartupListener接口来支撑这种场景

StartupListener.java

public interface StartupListener {

    // 定义多个Listener之间的先后顺序
    default LoadOrder getOrder() {
        return LoadOrder.LAST;
    }

    // Spring 容器加载之前
    default void init() {
    }

    // Spring 容器加载完成之后
    default void complete(ApplicationContext context) {
    }

    // 项目销毁前
    default void destory() {
    }

    enum LoadOrder {
        FIRST, MIDDLE, LAST
    }

}

如何使用?

  1. 编写业务代码继承 StartupListener
  2. 在项目的src/main/resources/META-INF/services中需要新建一个com.hbasesoft.framework.common.StartupListener文件,里面的内容是具体的实现类的全称,多个实现类需要换行

断言

断言使用com.hbasesoft.framework.common.utils.Assert工具类

AssertTest.java

@Test
public void notNull() {
    Object obj = new Object();
    Assert.notNull(obj, ErrorCodeDef.SYSTEM_ERROR_10001);
    System.out.println("obj 不是null");
}

@Test
public void isNull() {
    Object obj = null;
    Assert.isNull(obj, ErrorCodeDef.SYSTEM_ERROR_10001);
    System.out.println("obj 是null对象");
}

日志工具

框架提供了两种方式打印日志

  1. 在项目中实例化com.hbasesoft.framework.common.utils.logger.Logger类,适用于需要将日志打印到固定文件中的场景。
  2. 另外提供了一个工具类com.hbasesoft.framework.common.utils.logger.LoggerUtil可以方便的直接打印日志

日期处理

提供了场景日期格式转化的方法,com.hbasesoft.framework.common.utils.date.DateUtil

DateUtilTest.java

 @Test
    public void string2Date() {
        long t1 = NUM_A;
        long t2 = NUM_B;
        long t3 = NUM_C;
        String d8 = "20180912";
        Date date = DateUtil.string2Date(d8);
        Assert.isTrue(date.getTime() == t1, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d11 = "2018年09月12日";
        date = DateUtil.string2Date(d11);
        Assert.isTrue(date.getTime() == t1, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d10 = "2018-09-12";
        date = DateUtil.string2Date(d10);
        Assert.isTrue(date.getTime() == t1, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d102 = "2018/09/12";
        date = DateUtil.string2Date(d102);
        Assert.isTrue(date.getTime() == t1, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d14 = "20180912105355";
        date = DateUtil.string2Date(d14);
        Assert.isTrue(date.getTime() == t2, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d17 = "20180912105355123";
        date = DateUtil.string2Date(d17);
        Assert.isTrue(date.getTime() == t3, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d19 = "2018-09-12 10:53:55";
        date = DateUtil.string2Date(d19);
        Assert.isTrue(date.getTime() == t2, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d192 = "2018/09/12 10:53:55";
        date = DateUtil.string2Date(d192);
        Assert.isTrue(date.getTime() == t2, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d21 = "2018年09月12日 10时53分55秒";
        date = DateUtil.string2Date(d21);
        Assert.isTrue(date.getTime() == t2, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d23 = "2018-09-12 10:53:55.123";
        date = DateUtil.string2Date(d23);
        Assert.isTrue(date.getTime() == t3, ErrorCodeDef.SYSTEM_ERROR_10001);

        String d232 = "2018/09/12 10:53:55.123";
        date = DateUtil.string2Date(d232);
        Assert.isTrue(date.getTime() == t3, ErrorCodeDef.SYSTEM_ERROR_10001);

        String str = "18年9月12号10点53分55秒";
        date = DateUtil.string2Date(str, "yy年M月dd号hh点mm分ss秒");
        Assert.isTrue(date.getTime() == t2, ErrorCodeDef.SYSTEM_ERROR_10001);
    }

    @Test
    public void date2String() {
        Date date = new Date(NUM_C);
        String d8 = DateUtil.date2String(date, DateConstants.DATE_FORMAT_8);
        Assert.equals(d8, "20180912", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d11 = DateUtil.date2String(date, DateConstants.DATE_FORMAT_11);
        Assert.equals(d11, "2018年09月12日", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d10 = DateUtil.date2String(date, DateConstants.DATE_FORMAT_10);
        Assert.equals(d10, "2018-09-12", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d102 = DateUtil.date2String(date, DateConstants.DATE_FORMAT_10_2);
        Assert.equals(d102, "2018/09/12", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d14 = DateUtil.date2String(date, DateConstants.DATETIME_FORMAT_14);
        Assert.equals(d14, "20180912105355", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d17 = DateUtil.date2String(date, DateConstants.DATETIME_FORMAT_17);
        Assert.equals(d17, "20180912105355123", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d19 = DateUtil.date2String(date);
        Assert.equals(d19, "2018-09-12 10:53:55", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d192 = DateUtil.date2String(date, DateConstants.DATETIME_FORMAT_19_2);
        Assert.equals(d192, "2018/09/12 10:53:55", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d21 = DateUtil.date2String(date, DateConstants.DATETIME_FORMAT_21);
        Assert.equals(d21, "2018年09月12日 10时53分55秒", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d23 = DateUtil.date2String(date, DateConstants.DATETIME_FORMAT_23);
        Assert.equals(d23, "2018-09-12 10:53:55.123", ErrorCodeDef.SYSTEM_ERROR_10001);

        String d232 = DateUtil.date2String(date, DateConstants.DATETIME_FORMAT_23_2);
        Assert.equals(d232, "2018/09/12 10:53:55.123", ErrorCodeDef.SYSTEM_ERROR_10001);

        String str = DateUtil.date2String(date, "yy年M月dd号hh点mm分ss秒");
        Assert.equals(str, "18年9月12号10点53分55秒", ErrorCodeDef.SYSTEM_ERROR_10001);
    }

常用工具

提供获取随机数、transId、比较等等常见的方法 com.hbasesoft.framework.common.utils.CommonUtil

CommonUtilTest.java

@Test
public void getTransactionID() {
    String str1 = CommonUtil.getTransactionID();
    String str2 = CommonUtil.getTransactionID();
    Assert.notEquals(str1, str2, ErrorCodeDef.SYSTEM_ERROR_10001);
    System.out.println("生成了两个不一样的串码");
}

文件流

提供了文件读取、流转化、文件拷贝等方法 com.hbasesoft.framework.common.utils.io.IOUtil

模版引擎

提供了Javascript、Velocity、OGNL表达式的解析方法

VelocityParseFactoryTest.java

@Test
public void parse() {
    Bean bean = new Bean("张三", NUM_18);
    Map<String, Object> params = new HashMap<>();
    params.put("b", bean);

    String template = "你好,我的名字叫${b.name}";
    String str = VelocityParseFactory.parse("template01", template, params);
    Assert.equals(str, "你好,我的名字叫张三", ErrorCodeDef.SYSTEM_ERROR_10001);
}

JavaScriptUtilTest.java

@Test
public void eval() {
    String script = "1+1";
    Double result = Double.valueOf(CommonUtil.getString(JavaScriptUtil.eval(script, null)));
    Assert.isTrue(result - 2 == 0, ErrorCodeDef.SYSTEM_ERROR_10001);

    Bean bean = new Bean("张三", NUM_18);
    Map<String, Object> params = new HashMap<>();
    params.put("b", bean);

    script = "b.getAge() + 2";
    result = Double.valueOf(CommonUtil.getString(JavaScriptUtil.eval(script, params)));
    Assert.isTrue(result - NUM_20 == 0, ErrorCodeDef.SYSTEM_ERROR_10001);
}

Http工具

提供了Http Get、Post、下载文件等方法的快速访问 com.hbasesoft.framework.common.utils.io.HttpUtil

HttpUtilTest.java

@Test
public void doGet() {
    System.out
        .println(HttpUtil.doGet("https://jintan.towngasvcc.com/?null&ticket=2ccd00830d4448668b573c803f599c0f"));
    System.out.println(HttpUtil.doGet("https://www.towngasvcc.com", "utf-8"));
}


@Test
public void doPost() {
    Map<String, String> param = new HashMap<>();
    System.out.println(HttpUtil.doPost("http://www.baidu.com", param));
}

@Test
public void doGetDowloadFile() {
    HttpUtil.doGetDowloadFile("https://timgsa.baidu.com/timg?image"
        + "&quality=80&size=b9999_10000&sec=1506669107&di=3f964616fbb30dc8e9090f3921ce6dbf"
        + "&imgtype=jpg&er=1&src=http%3A%2F%2Fimgsrc.baidu.com%2Fbaike%2Fpic%"
        + "2Fitem%2Fcb8065380cd79123ea3a4a45af345982b2b7802d.jpg", "a2.jpg");
}

常用的数据处理工具

提供md5、base64、密码加密、解密、字节转16进制字符等方法 com.hbasesoft.framework.common.utils.security.DataUtil

DataUtilTest.java

@Test
public void md5For16() {
    String str1 = "123456";
    String str2 = DataUtil.md5For16(str1);
    Assert.equals(str2, "49BA59ABBE56E057", ErrorCodeDef.SYSTEM_ERROR_10001);
}

序列化工具

目前采用了protostuff 协议做的序列化和反序列化 com.hbasesoft.framework.common.utils.bean.SerializationUtil

SerializationUtilTest.java

@Test
public void serial() {

    Bean bean = new Bean("hello world", NUM_18);
    byte[] bs = SerializationUtil.serial(bean);
    String hexStr = DataUtil.byte2HexStr(bs);
    Assert.equals(hexStr, "0A0B68656C6C6F20776F726C641012", ErrorCodeDef.SYSTEM_ERROR_10001);
}

@Test
public void unserial() {
    byte[] bs = DataUtil.hexStr2Byte("0A0B68656C6C6F20776F726C641012");
    Bean bean = SerializationUtil.unserial(Bean.class, bs);
    Assert.equals(bean.getName(), "hello world", ErrorCodeDef.SYSTEM_ERROR_10001);
}

Xml处理工具

提供了java bean转xml、xml转java bean的方法 com.hbasesoft.framework.common.utils.xml.XmlBeanUtil

XmlTest.java

@Test
public void bean2xml() {

    Student student = new Student();
    student.setAge(NUM_10);
    student.setName("小明");
    student.setRemark("小明是位好同学,<hello>年年三好学生👩‍🎓");

    System.out.println(XmlBeanUtil.object2Xml(student));
}

@Test
public void xml2bean() {
    String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><student><name>小明</name><age>10</age><remark>"
        + "<![CDATA[小明是位好<abcdedf>同学,年年三好学生👩‍🎓]]></remark></student>";
    Student student = XmlBeanUtil.xml2Object(xml, Student.class);
    System.out.println(student.getAge());
    System.out.println(student.getName());
    System.out.println(student.getRemark());
}

1.简介

        Framework属于企业级底层开发框架,集成了log、cache、db、message、rule、tx,每块都以模块形式组织,可以根据项目需要获取模块。我们的初衷是屏蔽项目中各种第三方库之间的版本冲突,打造一套屏蔽底层中间件的全新API,提高项目代码的适配能力。

  • framework-common 定义公用的常量、工具类 采用了spring-boot方式启动, 启动类为Application, 也可以支持web方式启动。
  • framework-log 分布式集成日志模块,详细的记录了每个方法执行的参数、返回结果、执行时间,可以很方便的排查问题或告警,通过远程接口上传服务器(支持直连服务端,也支持通过kafka发送)
  • framework-cache 定义了缓存的获取。 支持注解方式访问缓存, 支持基于Redis的分布式锁
  • framework-db 是简单易用的轻量级DAO(Data Access Object)框架,它集成了Hibernate实体维护和Mybaits SQL分离的两大优势,提供了非入侵式API,可以与Hibernate、SpringJdbc等数据库框架很好的集成
  • framework-job 定时任务,支持quartz、xxl-job、ElasticJob简单封装的定时器,支持分布式、分片等功能
  • framework-message 消息模块,通过简单的api发布和订阅事件, 目前支持kafka、redis、rocketMq
  • framework-rule 规则引擎,基于json的轻量级规则引擎, 支持多种插件及扩展, 例如:基于状态机的工作流引擎
  • framework-tx 分布式事务,支持各种远程接口、同步异步消息。
  • [framework-dependencies] 项目依赖,解决版本包依赖问题
  • [framework-shell] 控制台方式提供命令操作,支持自定义各种命令,做各种小工具使用。
  • [framework-langchain4j] 对langchain4j的补充,支持国内的大模型,让大家更高效的开发AIGC应用。

jdk1.8请使用framework3.X版本,framework4.X已升级至jdk21版本

2.框架的由来

        Hibernate我用了2年半, 13年下半年去中兴软创用了一年SQL服务(软创内部框架), 14年在京东驻场用了2个月的MyBatis,综合了一下这些项目,各有各的优缺点。例如针对复杂业务SQL,hibernate明显能力不足,简单的功能MyBaties也要弄死人,所以一直在思考一个问题有没有一个框架能扬长避短,把大家的优点都发挥出来。 当时在某网站上看了一个帖子介绍了minidao,思路很新颖,拜读了源码。 从此框架之路走起。( 为什么不直接使用minidao,一是这个项目不火、更新节奏也不快,使用风险较大, 二是软创内部使用的都是自己的框架,连spring都没有,hibernate更不可能,jdk都处于1.4、1.5版本,不可能直接使用minidao )

  • 14年7月份左右在软创内部gitlab上发布了第一个版本easydao,主要是结合软创当时的系统框架在其之上封装了一层。
  • 14年10月份在github上发布了easydao 剥离掉软创内部框架依赖,使其可以不依赖软创的框架,可以结合spring和hibernate,或者可以单独使用jdbc来使用。
  • 15年6月开始framework-0.1版本的设计,数据库已经用的很爽了,但是一个项目不仅仅是数据库,还有很多其他东西, 当时针对的是web项目规划了很多模块,类似于现在的web结构, 做了job可以在线管理,消息、rpc、缓存等等功能
  • 16年1月22日正式发布1.0版本
  • 16年7月21日发布2.0版本,web模块和jeecg合并单独组成framework-manager, framework专门解决项目底层问题
  • 17年9月24日发布3.0版本,升级了spring boot版本至2.0, 去掉了dubbox这个rpc框架,引入spring-cloud框架。前端也放弃了jeecg,基于ant-design-pro 实现的一套web框架(目前还未从项目中分离出来,暂未开源)
  • 20年2月4日发布了3.4版本, 增加了framework-tx模块,正式支持分布式事务。
  • 23年人工智能比较火,又增加了framework-langchain4j,专门扩展国内的一些大模型。

3.采用项目

  1. 中兴视通网上营业厅项目V1.0
  2. 咪咕在线客服V1.0
  3. 中国实践教育平台V2.0
  4. 大丰科创园微信项目V1.0
  5. 苏州市总工会微信V1.0
  6. 佛山港华网上营业厅项目V1.0
  7. 苏州港华网上营业厅项目V1.0
  8. 苏州体育局微信活动运营项目V1.0
  9. 苏州市防汛排涝物资管理系统V1.0
  10. 港华集团网上营业厅项目
  11. E网通项目
  12. 港华紫荆微信项目
  13. 港华物联网平台
Clone this wiki locally