在线工具
- https://nowjava.com/jar/ 根据jar包名称,查看jar包中文件名信息,如查看druid-1.1.17.jar
Hutool
Bean/JSON操作
- Bean/Map/JSON相互转化
1 | // 注意:Hutool在处理JSON时对Null做了处理 |
- 复制Bean
1 | // 忽略NULL值(即NULL值不会覆盖目标对象,但不会忽略空值),和忽略部分属性。痛点:像 org.springframework.beans.BeanUtils.copyProperties 则无法忽略NULL值 |
- JSON
1 | // 根据路径获取值. 更强大的工具类:https://github.com/json-path/JsonPath 类似xpath获取json值 |
集合
- 快速组装Map
1 | Dict dict = Dict.create().set("key1", 1).set("key2", 1000L); // Dict继承HashMap,其key为String类型,value为Object类型 |
- 交/并/差等
1 | // ## 做减法,如:[1, 2] - [2, 3] = [1]。不建议使用 CollUtil.subtract(偶尔会报Null) |
- 分组
- 暂未找到基于字段值分组成数组的方法,可参考MiscU.groupByMapKey和MiscU.groupByBeanKey
1 | // 但是被分组的集合只能是对象集合,不能是Map集合,可使用 MiscU.fieldValueMap 代替 |
类型转化
1 | // ==> List转成数组 |
验证
- 断言
1 | // 不满足会抛出 IllegalArgumentException 异常 |
- 字段验证器
1 | // 判断验证 |
字符串
1 | // (成对)剥掉前后字符 |
构建树结构
1 | List<SysRouter> sysRouters = queryAll(); |
数字操作
1 | // NumberUtil会将double转为BigDecimal后计算,解决float和double类型无法进行精确计算的问题;BigDecimal并不能解决小数点问题 |
日期操作
1 | DateUtil.isIn(thisDate, DateUtil.offsetDay(new Date(), -10), new Date()); // 判断 thisDate 是否为最近10天的时间 |
加解密
1 | // ################# AES 对称加密 |
文件工具类-FileUtil
1 | // 获取类同级目录下文件 |
Excel工具-ExcelUtil
1 | // 读取Excel |
Http请求-HttpRequest
1 | String apiResult = HttpRequest.post("http://api.test.com/hello") |
FTP客户端封装-Ftp
1 | // 一次定时操作:创建新的FTP客户端 - 获取文件 - 关闭客户端 |
线程工具
- 线程工具-ThreadUtil
- Hutool使用
GlobalThreadPool
持有一个全局的线程池,默认所有异步方法在这个线程池中执行 - 基于
SynchronousQueue
实现: 这是一个没有容量的阻塞队列。每个插入操作都必须等待另一个线程的对应移除操作,因此此队列维持着零元素
- Hutool使用
1 | // 使用GlobalThreadPool执行(无队列概念), 无返回值 |
- 自定义线程池-ExecutorBuilder
1 | ExecutorService executor = ExecutorBuilder.create() |
模板引擎封装-TemplateUtil
- 可以操作Beetl、Enjoy、Rythm、FreeMarker、Velocity、Thymeleaf,只需引入相应的jar包
- 模板规则参考Velocity、FreeMarker、Thymeleaf
- 使用
1 | // 此处从classpath查找模板渲染(也可通过字符串模板、本地文件等方式渲染内容) |
Spring工具类
1 | // 处理url字符串(必须完整路径):提取参数 |
commons-tools
commons-lang
1 | // 截取字符串. 直接 str.substring 时长度不足会报错 |
集合(commons-collections)
- commons-collections#commons-collections
- Map处理
1 | // map取值减少强转 |
Sa-Token
- 官网:https://sa-token.cc/
- 默认将数据保存在内存中,分布式环境可设置成保存到Redis;和JWT集成支持Stateless无状态模式
Excel/Word/Pdf操作
poi
- 其他基本都是基于此衍生而来
- Excel基本使用
1 | // 合并单元格:将第2行的第1-2列合并 |
- Word基本使用(poi 5.2.2)
1 | // 表格操作 org.apache.poi.xwpf.usermodel.XWPFTable |
poi-tl基于模板生成Word
- github、文档
- 基于模板操作Word
- 技巧
- 区块支持内嵌子区块(原代码貌似会有问题,修复一下NumberingContinue.java即可)
- 对于图片引用,WPS无法修改文字,可将图片文件名改成对于模板变量在拖到WPS,如
.png
- 对于部分排版场景可考虑无边框表格,循环渲染更方便
- 貌似如果
builder.useSpringEL();
开启SpringEL,则都必须使用这种模式,则不支持自带的表格(实际是#table,由于hexo编译会报错,改成”井号table”)等写法
- 表格行循环和表格列循环
1 | LoopRowTableRenderPolicy rowPolicy = new LoopRowTableRenderPolicy(); |
- 动态增加换页符(参考上文案例图)
1 | // 参考:https://blog.csdn.net/wzw114/article/details/127545483 |
Easypoi基于模板生成Excel
- Easypoi、文档(已关闭)
- 优点
- 基于变量模板导出
- excel和html互转。html转excel需要导入org.jsoup#jsoup包,支持将多个table生成到多个sheet中,每个table标签设置一个sheetName属性
- 缺点
- BUG较多
- pdf导出文档不详
- 测试demo运行不完整
- excel转html不灵活,无法设置转出的页面样式,如宽度
- html转excel不完善,仅支持table转换,其他html标签不支持,且有些样式会丢失
- 使用(v4.2.0)
1 | // ==> 简单的列表循环 |
说明
- 常量在Excel中为
'常量值'
,由于可能存在转义,所有需要设置成''常量值'
解决EasyPoi通过
]]
换行报错的问题,参考修改源码
ExcelExportOfTemplateUtil.java
的setForeachRowCellValue方法1
2
3
4
5
6
7
8
9
10
11
12
13
14// 修改前
row = row.getSheet().getRow(row.getRowNum() - rowspan + 1);
// 修改后
Row tmpRow = row;
row = row.getSheet().getRow(row.getRowNum() - rowspan + 1);
if(row == null || row.getRowNum() < tmpRow.getRowNum()) {
row = tmpRow;
}
// 使用如
// 第一列 // 第二列
{{$fe: list t.username ]]
t.password }}
- 常量在Excel中为
Excel转PDF
- Aspose 需要收费,有水印文字。破解参考下文Aspose
- 转换后字体、样式、打印边距都可以达到和Excel基本一致
- spire 需要收费(国产),使用 Free Spire 对应的依赖 class文件也加密了
- jacob: 需要jacob.jar以及jacob.dll(未测试)
- 需要jacob.jar来调用activex控件,本机需安装Office/WPS/pdfcreator(wps有linux版,office到现在为止还没有linux版)
- poi+itext 效果可能不太好
Aspose
- 组件介绍
- Aspose.Cells 操作Excel
- 如果需要将Excel转成PDF也只需要引入Cells,无需引入Aspose.PDF
- Aspose.Words 操作Word
- 如果需要将Word转成PDF也只需要引入Words,无需引入Aspose.PDF
- Aspose.PDF 操作PDF
- Aspose.Slides
- …
- Aspose.Cells 操作Excel
- Linux上默认没有微软雅黑等中文字体,可将Windows中的字体复制过去然后进行安装
- Windows字体目录:C:\Windows\Fonts,simsun.ttc(宋体),msyf.ttc(微软雅黑)
- 安装参考 https://zhuanlan.zhihu.com/p/360014306
Excel转成PDF案例
- 配置
1 | <!-- 操作Excel --> |
- 使用
1 | import com.aspose.cells.License; |
Word转PDF案例
- Linux上默认没有微软雅黑等中文字体,可将Windows中的字体复制过去然后进行安装
- Windows字体目录:C:\Windows\Fonts,simsun.ttc(宋体),msyf.ttc(微软雅黑)
- 安装参考 https://zhuanlan.zhihu.com/p/360014306
1 | // 参考Excel转成PDF案例 |
破解(仅供学习)
- 网上较多结合org.apache.pdfbox去除水印,但是测试下来效果不好
- 直接破解源码参考(Word/Excel/Pdf)
- 原理
- 使用 javassist 修改 aspose-cells-21.11.jar 源码
- License#setLicense 最终会进入
this.a
方法,而此方法大部分都是校验逻辑,如果通过都会进入zblc.a
方法,因此修改this.a
方法即可
- 破解之后还是正常导入License,只是破解之后就不会校验License正确性,从而不会生成水印
数据库
liquibase数据库版本管理
- 数据库版本管理 https://www.liquibase.org/
jsqlparser
- 官网: https://jsqlparser.sourceforge.net/
- SQL解析: net.sf.jsqlparser.parser
语言
Yaml解析(基于jyaml)
- json-yaml互转工具:https://www.bejson.com/json/json2yaml
- 依赖
1 | <dependency> |
- yaml
1 | name: smale |
- 代码
1 | // model |
jackson
- 其他说明
- 像fastjson、jackson等工具类,将对象转成json字符串时,如果继承了Map即可,则默认会忽略其他属性,仅会序列化Map的值,貌似可以显示指定
- Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,当升级到 2.x 版本时,包名变为 com.fasterxml.jackson
- 依赖(jackson-databind 依赖 jackson-core 和 jackson-annotations)
1 | <dependency> |
- 示例
1 | // 使用 |
fastjson
- 官网
- 文档
- 自定义序列化之过滤器,参考上述文档,案例参考下文
- 可以在每次 JSON.toJSONString 的时候单独传入过滤器
- 其他说明
- 像fastjson、jackson等工具类,将对象转成json字符串时,如果继承了Map即可,则默认会忽略其他属性,仅会序列化Map的值,貌似可以显示指定
- 示例
1 | JSON.toJSONString(obj); // 序列化 |
- 全局配置(序列化/反序列化)案例
1 |
|
其他
字节码操作
- ASM、Javassist、Byte-buddy以及JavaAgent
- https://blog.csdn.net/luanlouis/article/details/24589193
- https://www.cnblogs.com/rickiyang/p/11336268.html
- https://blog.csdn.net/chosen0ne/article/details/50790372
JEXL执行字符串JAVA代码
- Java Expression Language (JEXL):是一个表达式语法解析引擎
- 旨在促进在用Java编写的应用程序和框架中,实现动态和脚本功能
- JEXL实现了 JSTL 中 EL 的延伸版本,不过也采用了一些 Velocity 的概念
- 支持shell脚本或ECMAScript(js)中的大多数构造
- 更推荐使用ScriptEngineManager进行java-js的交互,参考javax.script)
- commons-jexl官网
- 语法文档
- 案例
- 依赖
1 | <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-jexl3 --> |
- 简单案例
1 | //创建或者取回一个引擎。线程安全,虽然每次create的对象不一样(但是内部创建对象时会进行copy) |
- 其他案例
1 | // ==> Jexl引擎能够创建两种解析器:脚本和表达式,其中JexlExpression不能使用 if、for、while 语句块。 |
Ureport报表
- ureport、ureport文档
- 参考文档
- ureport2整合到springboot: https://www.cnblogs.com/Jimc/p/12101035.html
- ureport2数据源及自定义存储器(如数据库存储): https://www.cnblogs.com/Jimc/category/1621054.html
- https://www.cnblogs.com/niceyoo/p/14311257.html
- ureport2整合到springboot
1 | <!-- 目前maven最新为2.2.9. gitee(https://gitee.com/youseries_admin/ureport)上有最新的2.3.0-SNAPSHOT, 但是需要自行编译打包 --> |
配置
1 |
|
- 存在问题
- UReport2部分功能不可用,包括导出及多条件表达式SQL查询(错误信息会直接暴露)
- Ureport2支持打印报表,不过存在bug,数据会显示不全,导出为Word文档同样存在问题,数据不全且当有合并单元格时数据会混乱展示
- 不支持邮件发送
- 本身不支持权限控制
- 路径
- 设计器路径
http://localhost:8800/api/ureport/designer
- 预览路径
http://localhost:8800/api/ureport/preview?_u=file:test.ureport.xml
- 注意需要带上
file:
,且文件名不要出现#[]
等特殊字符串(.
是可以的) - 参数
_u=file:xxx
指定报表配置资源名 - 参数
_i=1
表示分页预览第一页 - 参数
_t=0
表示不显示导航条(顶部打印导出等按钮)
- 注意需要带上
- 设计器路径
数据源和数据集
- 配置数据源和数据集
- 每个报表需要配置各自的数据源和数据集
- 内置数据源只需要在创建报表的时候添加到当前报表即可使用
带动态参数的SQL
${}
会作为表单时解析,但是不能和纯SQL语句联合使用(如下文案例中相同部分SQL不能写到${}
外部)- 字符串拼接SQL时注意空格
- 参数不支持动态默认值;日期区间需要定义两个参数,且必须通过
param("tk_create_time_start")
方式取值(字符串中有单引号时必须转义)
1
2
3
4
5
6
7
8
9
10${
" select ttu.user_id, ttu.tbk_nickname, tto.*"+
" from tk_taoke_order tto"+
" left join tk_taoke_user ttu on ttu.tbk_special_id = tto.special_id"+
" where 1=1" +
(param("user_id") != null && param("user_id") != '' ? " and ttu.user_id=:user_id" : "")+
(param("tk_create_time_start") != null && param("tk_create_time_start") != '' ? " and tto.tk_create_time >= str_to_date(\'"+ param("tk_create_time_start") +" 00:00:00.000\', \'%Y-%m-%d %H:%i:%s.%f\')" : "") +
(param("tk_create_time_end") != null && param("tk_create_time_end") != '' ? " and tto.tk_create_time <= str_to_date(\'"+ param("tk_create_time_end") +" 23:59:59.999\', \'%Y-%m-%d %H:%i:%s.%f\')" : "") +
" order by tto.tk_create_time desc"
}
- 配置数据源和数据集
列属性
- 链接配置
- 支持表达式,如
${'https:' + order.select(item_img)}
(order为数据集,item_img为字段)
- 支持表达式,如
- 单元格类型为图片
- 图片来源为路径时支持
http(s)://
的网络图片 - 图片来源为表达式支持从数据集中读取后再获取图片数据
- 如
'https:' + order.select(item_img)
(order为数据集,item_img为字段,返回格式为//example.com/demo.png
) - 注意:此时显示获取图片路径字符串,然后通过服务器获取图片数据转成base64到前台显示(此时图片流量全部会经过服务器)
- 如
- 链接配置
- 过滤条件:符合条件时,当前列才显示,否则当前列显示空白
开发工具
Lombok
- Lombox 简化代码工具
引入
- maven项目中需要加入对应的依赖,从而打包时生成相应代码
- idea需要安装Lombox插件,从而编译时生成相应代码,不会报错
@SneakyThrows
修饰方法,捕获方法中的Throwable异常,并抛出一个RuntimeException- @SneakyThrows(UnsupportedEncodingException.class) 捕获方法中的UnsupportedEncodingException异常,并抛出RuntimeException
@NoArgsConstructor
、@AllArgsConstructor
、@RequiredArgsConstructor
结合Spring注入- @AllArgsConstructor 会将所有的成员放到构造函数中,Spring会自动注入所有的字段(部分场景会出现无法注入,此时可通过@RequiredArgsConstructor完成)
@RequiredArgsConstructor 生成该类下被final修饰或者non-null修饰(@NonNull)字段生成一个构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ConstructorDemo {
// Spring 会自动注入(final修饰)
private final BeanTest1 beanTest1;
// Spring 会自动注入(non-null修饰);@NonNull 生成的代码会判空,为空则报空指针异常
private BeanTest2 beanTest2;
// Spring 不会自动注入(没有final或者no-null修饰)
private BeanTest3 beanTest3;
// Spring 不会自动注入(如果用 @AllArgsConstructor 则会报错找不到这个类型的bean)
private Integer sex = 1;
// Spring 不会自动注入(如果用 @AllArgsConstructor 则会报错找不到这个类型的bean)
"${constructor.name:hello}") (
private String name;
}
使用Builder构造器模式
- 添加
@Builder
,需要额外添加以下注解@NoArgsConstructor
、@AllArgsConstructor
,缺一不可。否则子类继承报错”无法将类中的构造器应用到给定类型” - 在父类和子类中同时使用
@SuperBuilder
(v1.18.4)解决子类在链式赋值时无法设置父类的字段问题 ^1 @Builder(toBuilder = true)
表示相应对象会附带toBuilder
方法,将其转换成功Builder对象继续进行链式赋值。默认只能通过MyClass.builder()获取链式调用入口- 无法设置默认值,如实体类属性设置的值无效
- 添加
@Accessors(fluent = true, chain = true, prefix = "p")
- fluent属性表示生成getId/setId方法均省略前缀(get/set),最终的方法名为id
- chain属性表示setter方法返回当前对象
- prefix属性表示生成的get/set方法会忽略前缀。即字段名为pId时,会生成为getId的方法
- 如果作用在entity上,会导致mybatis的xml中resultMap字段无法识别
sdkman
- 官网
- sdkman 包管理工具
- sdkman可以更方便的按照、更改sdk(如jdk)版本
ProGuard
- 源码优化、混淆器
- 源码、ProGuard官网手册
参考文章