包含开发编码能用到的一些封装工具,提升开发效率以及代码优雅性。 主要功能含:
<dependency>
<groupId>io.gitee.laoshirenggo</groupId>
<artifactId>tools</artifactId>
<version>1.6</version>
</dependency>
JMap继承Map,JHashMap继承HashMap,JConcurrentHashMap继承ConcurrentHashMap,只做增强,封装了常用方法,让代码更优雅。
//创建HashMap
JMap<String, Object> hashMap = new JHashMap<>();
//创建ConcurrentHashMap
JMap<String, Object> concurrentHashMap = new JConcurrentHashMap<>();
jmap.getString("demo");
jmap.get(Demo::getName);
JMap<String, Object> jmap = new JHashMap<String, Object>()
.set(Demo::getName, "张三")
.set("age", 18);
String name = jmap.getString("name");
Integer age = jmap.getInteger(Demo::getAge);
//key转换为list
JList<String> key = jmap.toList().key();
//value转换为list
JList<Object> value = jmap.toList().value();
Demo demo = jmap.toBean(Demo.class);
JList继承List,增强封装了常用方法的lambda操作,让代码更优雅。
JList<Demo> jlist = new JArrayList<>();
JList<Demo> jlist = new JArrayList<Demo>()
.set(new Demo().setAge(18).setName("张三"))
.set(new Demo().setAge(20).setName("李四"));
//age属性为key转换为map,重复分组
JMap<Integer, List<Demo>> group = jlist.toMap(Demo::getAge).group();
//age属性为key转换为map,重复覆盖
JMap<Integer, Demo> cover = jlist.toMap(Demo::getAge).cover();
//根据age字段去重
JList<Demo> comparing = jlist.comparing(Demo::getAge);
//根据age字段倒序
JList<Demo> desc = jlist.desc(Demo::getAge);
//获取name属性集合
JList<String> property = jlist.getProperty(Demo::getName);
条件表达式支持:eq,lt,gt,le,ge,ne,like,in,notIn,isNull,isNotNull。
查询结果支持:list,object。
//查询age>=18 && name=张三 的数据 返回集合
JList<Demo> zhangsan = jlist.filter()
.ge(Demo::getAge, 18)
.eq(Demo::getName, "张三")
.list();
//查询name=李四 的数据 返回对象
Demo lisi = jlist.filter()
.eq(Demo::getName, "李四")
.object();
JList<Demo> shuffle = jlist.shuffle();
int index = list.getIndex(new Demo().setAge(18).setName("张三"));
//按长度1切割
JList<JList<Demo>> partition = jlist.partition(1);
JList<Demo> jlist1 = new JArrayList<Demo>()
.set(new Demo().setAge(18).setName("张三"))
.set(new Demo().setAge(20).setName("李四"));
JList<Demo> list2 = new JArrayList<Demo>()
.set(new Demo().setAge(18).setName("张三"));
//差集
JList<Demo> diff = jlist1.diff(list2);
//交集
JList<Demo> section = jlist1.section(list2);
更优雅的使用线程池,支持如下:
创建线程池:
public ThreadPoolTaskExecutor test() {
return JThreadPool.newPoll()
.coreSize(10)
.maxSize(100)
.keepAlive(60)
.queueSize(200)
.name("test")
.rejected(new ThreadPoolExecutor.CallerRunsPolicy())
.builder();
}
手动执行线程池1:
public void demo() {
//参数1为:线程池名称,参数2为:任务数
JThreadPool.excPoll("test", 3)
.execute(() -> System.out.println(1))
.execute(() -> System.out.println(2))
.execute(() -> System.out.println(3))
//阻塞等待
.await();
System.out.println("执行完毕~");
}
手动执行线程池2:
public void demo() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
//参数1为:线程池名称,参数2为:任务数
JThreadPool.Execute test = JThreadPool.excPoll("test", list.size());
for (Integer integer : list) {
test.execute(() -> System.out.println(integer));
}
//阻塞等待,最多等5秒
test.await(5);
System.out.println("执行完毕~");
}
数据判断的封装,让任意数据类型基本判断只需使用JEmpty.check()这一个方法即可,判断数据变为无脑,支持功能如下:
Object obj = null;
String str = "";
BigDecimal number = new BigDecimal(0);
//任意数据类型判空
boolean check = JEmpty.check(obj);
//字符串 最小长度=1 最大长度=10
boolean check2 = JEmpty.check(str, 1, 10);
//字符串 正则匹配
boolean check3 = JEmpty.check(str, "[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\\.[a-zA-Z0-9]+)+");
//数值 最小=1 最大=10
boolean check4 = JEmpty.check(number, 1, 10);
顾名思义就是一组数据,当有多个值且数据类型不同时,使用Map并不能准确的表达值的数据类型,元祖就是为了解决这一问题,一共提供了五维元祖,足够满足大多数需求:
//二维元祖,同时放入两种数据类型
JTuple.Tuple2<Integer, String> tuple2 = new JTuple.Tuple2<>(200, "操作成功");
Integer v21 = tuple2.getV1();
String v22 = tuple2.getV2();
入参自动用aes或rsa私钥解密或返参自动用aes或rsa私钥加密,开发不用做任何加解密操作。
注:启动类上需加上@JEnableSecurity,解密入参方法必须有@RequestBody修饰,加密返参必须为json方式,yml需配置aes密钥或rsa私钥公钥。
#aes对称
encrypt:
#是否开启加解密 默认true
open: true
#是否将加解密日志输出到控制台 默认false
showLog: false
aes:
#获取密钥可使用类 JAES
key: GLfx0TH5zhQpnHQnNtrW1w==
#rsa非对称
encrypt:
#是否开启加解密 默认true
open: true
#是否将加解密日志输出到控制台 默认false
showLog: false
rsa:
#获取密钥可使用类 JRSA
publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv370hnpEizK5IUtTxCQVFsEPz2ZFuys4x6zR/2mpS/MooLecSyqsiF8kLUs+ZLqnZrtTRzuMZ5TowP6QeYqsWiAI9tv7x/Pahxi7BEYx/CQx3T7RZRZsnEuprxbmyCkW5WWjrF7NitMSGMSq8fi8DANUeV0aLV8lVz4b3LhCPqwIDAQAB
privateKey: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOz+7RPUvKUGfWnsWN+p6N27uzkLOuQyAiaMhxVN+IpMR6A+BHzGPSM+je/xLdoJLlaqoZXLhmtyH9EjQlIOcrPlP933OuTGwNDa9rXxjRI9r1nsfhorvVxmWk8Lq2EEP9pSsj4c83ilcoYIMB4dzPf/XN2DEhozNbth+sPZfIE/AgMBAAECgYBbqtr+camp1xHJV66kjG7S3Rs0nEBiJWmpiW9ycR8yNwD5XSOVM4RQTpDN/yZyEF0JDqTDcN6ETrc5yH6NiKMabXHtn4OD7Uciu46c3VOAAT8x3KAWqldMh0XwPWmepu9B1ajtWzEuytFG/aTscWrBd2zf3EBStS7ctLpLZmqmOQJBAP1EA6a3q+Jl2uoQlZSpmqQlfAPtn2gYHLpnbY4mev6TdbHnq0id4dZ5zQIASQgzGDuaG3lyzNWg063+H+nCaqsCQQDvjfHKTirqxH7OViu2+ms9ufJ4zI5AQfTcywE1MP7Hg861gb1BEzqGDlOUkEwbo2YMrBfG6AP7IXRJGU9pG0O9AkBxhshgNhrNTDz6CN8UGYahJ9BUbnKzFYPjJrOcMbGWZgEu8xr7XRI7srNrvzb9fvHQ3b6NDSG2bPYWG0Cw5x4rAkEA0rFMjTuNAalLQl2F20yLD+JBAcAgCSI5pAwkhs0N+RrTrs5qTxcDbS6iklMLrW9cbR7bVsVv4uu8pCJPtskVHQJBAIg0NHL72U8fbRfh2Oo4hYMk2NP1KcH/LscehaNrrIOF71dX5aOYwalX2Q0rEBvawlJptv33xbDP+M8lTB+ecHM=
控制层按需增加@JDecode或@JEncode
//@JEncode
@JDecode
@GetMapping("test")
public Map<String, Object> test(Map<String, Object> map) {
System.out.println(map);
return map;
}
启动类加@JEnableSecurity
@JEnableSecurity
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
提供工具类,方便生成密钥以及加解密调试。
aes例子:
//获取密钥
String aesKey = JAES.getKey();
//加密
String encode = JAES.encode("{\"name\": \"张三\"}", aesKey);
//解密
String decode = JAES.decode(encode, aesKey);
rsa例子:
//获取密钥对
Map<String, String> rsaMap = JRSA.getKey();
//私钥
String privateKey = rsaMap.get("privateKey");
//公钥
String publicKey = rsaMap.get("publicKey");
//公钥加密
String publicEncode = JRSA.publicEncode("{\"name\": \"张三\"}", publicKey);
//公钥解密
String publicDecode = JRSA.publicDecode(publicEncode, publicKey);
//私钥加密
String privateEncode = JRSA.privateEncode("{\"name\": \"张三\"}", privateKey);
//私钥解密
String privateDecode = JRSA.privateDecode(privateEncode, privateKey);
根据顶级对象递归获取子级树。
方法:JBean.tree(最顶层父级对象, 全部数据集合, 父级关联子级属性名, 子级关联父级属性名, 存放子级集合属性名)
例子:
public static void main(String[] args) {
//生成测试数据
List<Entity> datas = new ArrayList<>();
datas.add(new Entity().setId(1).setName("顶级1"));
datas.add(new Entity().setId(3).setName("子级1").setPid(1));
datas.add(new Entity().setId(4).setName("子级2").setPid(3));
datas.add(new Entity().setId(5).setName("子级3").setPid(1));
//获取顶级菜单
Entity top = datas.get(0);
//获取子级集合
List<Entity> tree = JBean.tree(top, datas, Entity::getId, Entity::getPid, Entity::getSonEntitys);
//存入下级集合
top.setSonEntitys(tree);
//转json,方便观察结果
JSONArray array = JSONUtil.parseArray(list);
//输出[{"name":"顶级1","id":1,"sonEntitys":[{"pid":1,"name":"子级1","id":3,"sonEntitys":[{"pid":3,"name":"子级2","id":4,"sonEntitys":[]}]},{"pid":1,"name":"子级3","id":5,"sonEntitys":[]}]},{"name":"顶级2","id":2,"sonEntitys":[]}]
System.out.println(array.toString());
}
@Data
@Accessors(chain = true)
public class Entity {
//id
private Integer id;
private String name;
//上级id 为null则表示顶级,规则是你自己定义
private Integer pid;
//下级集合
private List<Entity> sonEntitys;
}
lambda解析工具,避免硬编码:
public static void main(String[] args) {
//获取class
Class<Demo> claszz = JLambda.getClass(Demo::getId);
//获取属性名 id
String property = JLambda.getProperty(Demo::getId);
//获取方法名 getName
String getMethod = JLambda.getMethod(Demo::getName);
}
@Data
public class Demo {
private Integer id;
private String name;
}
类名JSpringBean,运行时动态管理bean,api如下:
getBean(Class<T>) 根据类型获取bean
getBean(String beanName) 根据名称获取bean
getBean(String beanName, Class<T> clazz) 根据名称+类型获取bean
registerBean(T obj) 根据类型注册bean
registerBean(String name, T obj) 根据类型注册bean
registerBean(Class<T> clazz, Map<String, Object> args) 根据类型注册bean,map为bena实体参数列表
registerBean(String name, Class<T> clazz, Map<String, Object> args) 根据名称+类型注册bean,map为bena实体参数列表
removeBean(String name) 根据名称删除bean
例子:
/**
* bean对象
*/
@Data
public class TestBean {
private Integer id;
private String name;
}
@RestController
public class TestService {
@GetMapping("test")
public void test() {
//注册bean
Map<String, Object> map = new HashMap<>();
map.put("id", 1);
map.put("name", "小张");
TestBean testBean = JSpringBean.registerBean(TestBean.class, map);
//获取bean
TestBean testBean1 = JSpringBean.getBean(TestBean.class);
System.out.println(testBean1);
Object testBean2 = JSpringBean.getBean("testBean");
System.out.println(testBean2);
//删除bean
JSpringBean.removeBean("testBean");
}
}
spring接口代理封装,封装抽象了接口代理相关的操作,继承使用即可。
/**
* 测试bean,主要演示代理实现类获取spring bean
*/
@Service
public class TestBean {
/**
* 输出泛型class名称
*/
public void test(Class<?> clazz) {
System.out.println(clazz.getName());
}
}
下面开始编写代理类:
/**
* 代理接口,用于给其他接口继承
* @param <T>
*/
public interface DemoService<T> {
void test();
}
/**
* 代理接口实现
*
* @param <T>
*/
public class DemoServiceImpl<T> extends JInvocationHandler<T> implements DemoService<T> {
public DemoServiceImpl(Class interfaceType) {
super(interfaceType);
}
/**
* 实现接口方法,调用测试bean,输出泛型class名称
*/
@Override
public void test() {
//classa为JInvocationHandler父类提供的泛型实例,JInvocationHandler2对应classa、classb,JInvocationHandler3对应classa、classb、classc
//因该代理类不受spring管理,所以使用JInvocationHandler提供的getBean()手动获取用于演示的TestBean
TestBean testBean = getBean(TestBean.class);
testBean.test(classa);
}
}
此时代理类已经完成,下面编写测试类:
/**
* 声明一个接口,并继承代理类,指定泛型String
*/
public interface TestService extends DemoService<String> {
}
/**
* 测试控制层
*/
@RestController
public class TestServiceImpl {
@Autowired
private TestService testService;
@GetMapping("test")
public void test() {
//输出java.lang.String
testService.test();
}
}
@JFilter一个注解实现过滤器,支持传入基本参数,你只需保证注解参数能强转为形参即可,可选择返回布尔值或抛出异常来实现请求是否继续,如返回false则中断请求并抛出JFilterError异常。
@JLFilter参数:
1. values 方法参数,顺序对应方法参数的顺序,仅支持常用数据类型。
2. excludes[] 过滤的url
3. order 执行顺序
4. error 返回false的异常错误信息
@Service
@AllArgsConstructor
public class Test {
private HttpServletRequest request;
@JFilter(error = "test过滤器异常")
public boolean test() {
System.out.println("请求url:" + request.getRequestURI());
return true;
}
}
@JInterceptor一个注解实现拦截器,支持传入基本参数,你只需保证注解参数能强转为形参即可,可选择返回布尔值或抛出异常来实现请求是否继续,如返回false则中断请求并抛出JInrerceptorError异常。
@JLInterceptor参数:
1. values 方法参数,顺序对应方法参数的顺序,仅支持常用数据类型。
2. excludes[] 过滤的url
3. order 执行顺序
4. error 返回false的异常错误信息
5. before 拦截方法之前(默认)
6. after 拦截方法之后
@Service
@AllArgsConstructor
public class Test {
private HttpServletRequest request;
@JInterceptor(excludes = {"/login", "/register"})
public boolean test() {
System.out.println("请求url:" + request.getRequestURI());
return true;
}
}
注解@Check,简化版的@validated,基本思路和使用同@validated,基于aop,使用更简单,主要功能如下:
@Check参数:
value 校验不通过抛出异常的属性名称
max 最大,支持:数值、字符串、List
min 最小,支持:数值、字符串、List
regex 正则表达式,支持:字符串、数值
isValid 是否有效,有效才会校验。
isEmpty 是否可为空
groups[] 分组,同组才会被校验
例子:
public class OrderServiceimpl {
@PostMapping("test")
public void test(@RequestBody @Check(min = 1, max = 5) List<User> user) {
//指定user集合最小长度=1 最大长度=5
}
@Data
@Check//指定全局非空校验
public static class User {
//指定数值最小=1 最大=10000
@Check(min = 1, max = 10000)
private BigDecimal id;
//指定字符最小长度=1 最大长度=20
@Check(min = 1, max = 20)
private String name;
//自定义属性名称,校验不通过会使用该名称抛出异常
@Check("订单集合")
private List<Order> order;
//指定集合最小长度=1 最大长度=10 并自定义属性名称
@Check(min = 1, max = 10, value = "测试名称")
private List<Integer> ints;
private Boolean wq;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime time;
}
@Data
@Check//指定全局非空校验
public static class Order {
private BigDecimal id;
private String no;
private Money money;
}
@Data
@Check//指定全局非空校验
public static class Money {
private BigDecimal id;
private String cal;
}
}
使用分组功能:
public class OrderServiceimpl {
@PostMapping("test")
public void test(@RequestBody @Check(groups = {TestGroup.class}) List<User> user) {
//指定校验只被TestGroup分组修饰的属性
}
@Data
@Check
public static class User {
@Check(groups = {TestGroup.class})
private BigDecimal id;
//该属性就不参与test接口的校验
private String name;
@Check(groups = {TestGroup.class})
private List<Order> order;
}
@Data
@Check
public static class Order {
@Check(groups = {TestGroup.class})
private BigDecimal id;
//该属性就不参与test接口的校验
private String no;
@Check(groups = {TestGroup.class})
private Money money;
}
@Data
@Check(groups = {TestGroup.class})
public static class Money {
private BigDecimal id;
private String cal;
}
/**
* 分组接口
*/
interface TestGroup {
}
}
方法JBean.copy(),纯反射实现的bean拷贝,支持功能:
public static void main(String[] args) {
User user = new User()
.setId("1")
.setName("test")
.setMoney(99.99)
.setTime(LocalDateTime.now());
//对象拷贝
UserVo1 userVo1 = JBean.copy(UserVo1.class, user);
//对象拷贝 属性数据类型不一样,但能保证数据类型可以转换,同样可以拷贝
UserVo2 userVo2 = JBean.copy(UserVo2.class, user);
//集合拷贝
List<UserVo2> userVo2s = JBean.copy(UserVo2.class, Arrays.asList(user));
}
@Data
@Accessors(chain = true)
public static class User {
private String id;
private String name;
private Double money;
private LocalDateTime time;
}
@Data
@Accessors(chain = true)
public static class UserVo1 extends User {
}
@Data
@Accessors(chain = true)
public static class UserVo2 {
private Integer id;
private String name;
private BigDecimal money;
private String time;
}
类JIo,整合了字节流的操作,链式调用,使用方便些。 api列表:
InputStreamMethod inputStream(String path) 字节输入流,读取路径,支持项目相对路径、服务器绝对路径、网络url。
InputStreamMethod inputStream(File file) 字节输入流,读取file
OutputStreamMethod outputStream(String path) 字节输出流,输出到路径
OutputStreamMethod outputStream(File file) 字节输出流,输出到File
OutputStreamMethod outputStream(String path, boolean append) 字节输出流,输出到路径,append为是否追加输出
OutputStreamMethod outputStream(File file, boolean append) 字节输出流,输出到File,append为是否追加输出
InputStreamMethod方法列表:
InputStream get() 获取字节输入流
String content() 字符串形式获取读取文件的内容
OutputStreamMethod方法列表:
OutputStream get() 获取字节输出流
void save(String content) 保存字符串内容到文件
void save(InputStream inputStream) 保存字节输入流到文件
例子:
//获取字节输入流
InputStream inputStream = JIo.inputStream("d://test.txt").get();
//获取字节输入流内容
String testContent = JIo.inputStream("d://test.txt").content();
//读取demo.txt文件内容,追加到test.txt文件
JIo.outputStream("d://demo.txt", true).save(inputStream);
注解JRunner,项目启动成功后执行的方法执行被注解的方法。
@Service
public class Test {
@JLRunner
public void demo() {
System.out.println("demo");
}
@JRunner({"张三", "18"})
public void test(String name, Integer age) {
System.out.println(name);
System.out.println(age);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。