1 FastJson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>x.x.x</version>
</dependency>
kimmking:JSON Best Practice(最佳实践)
1.1 SerializerFeature属性
名称 | 含义 | 备注 |
---|---|---|
QuoteFieldNames | 输出key时是否使用双引号,默认为true | |
UseSingleQuotes | 使用单引号而不是双引号,默认为false | |
WriteMapNullValue | 是否输出值为null的字段,默认为false | |
WriteEnumUsingToString | Enum输出name()或者original,默认为false | |
UseISO8601DateFormat | Date使用ISO8601格式输出,默认为false | |
WriteNullListAsEmpty | List字段如果为null,输出为[],而非null | |
WriteNullStringAsEmpty | 字符类型字段如果为null,输出为”“,而非null | |
WriteNullNumberAsZero | 数值字段如果为null,输出为0,而非null | |
WriteNullBooleanAsFalse | Boolean字段如果为null,输出为false,而非null | |
SkipTransientField | 如果是true,类中的Get方法对应的Field是transient,序列化时将会被忽略。默认为true | |
SortField | 按字段名称排序后输出。默认为false | |
WriteTabAsSpecial | 把\t做转义输出,默认为false | 不推荐 |
PrettyFormat | 结果是否格式化,默认为false | |
WriteClassName | 序列化时写入类型信息,默认为false。反序列化是需用到 | |
DisableCircularReferenceDetect | 消除对同一对象循环引用的问题,默认为false | |
WriteSlashAsSpecial | 对斜杠’/’进行转义 | |
BrowserCompatible | 将中文都会序列化为\uXXXX格式,字节数会多一些,但是能兼容IE 6,默认为false | |
WriteDateUseDateFormat | 全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat); | |
DisableCheckSpecialChar | 一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false | |
NotWriteRootClassName | 含义 | |
BeanToArray | 将对象转为array输出 | |
WriteNonStringKeyAsString | 含义 | |
NotWriteDefaultValue | 含义 | |
BrowserSecure | 含义 | |
IgnoreNonFieldGetter | 含义 | |
WriteEnumUsingName | 含义 |
1.2 $ref 的错误
设置一下序列化特性,DisableCircularReferenceDetect 即可。
2 对象转换(拷贝)
对象转换,都是找到的对应字段的映射关系。这个涉及到字段的类型,字段访问权限(private、protected等) ,特殊类型(日期等);
另外一点,就是深拷贝,浅拷贝问题,不同的转换采取的方式不同。
2.1 org.apache.commons.beanutils.PropertyUtils
http://commons.apache.org/proper/commons-beanutils/
2.2 org.springframework.beans.BeanUtils
2.3 Bull(Bean Utils Light Library)
https://github.com/ExpediaGroup/bull
2.4 Dozer
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.4.0</version>
</dependency>
2.5 mapstruct
https://github.com/mapstruct/mapstruct/
https://mapstruct.org/
...
<properties>
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
</properties>
...
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
...
2.6 Jackson Data Bind
https://github.com/FasterXML/jackson-databind
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
2.7 modelmapper
http://modelmapper.org/getting-started/
https://github.com/modelmapper/modelmapper
java 8
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>com.github.jmnarloch</groupId>
<artifactId>modelmapper-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
modelMapper 主要考虑匹配策略和隐式匹配,不同的规则不同。
3 hutools
模块 | 介绍 | 备注 |
---|---|---|
hutool-aop | JDK动态代理封装,提供非IOC下的切面支持 | |
hutool-bloomFilter | 布隆过滤,提供一些Hash算法的布隆过滤 | |
hutool-cache | 简单缓存实现 | |
hutool-core | 核心,包括Bean操作、日期、各种Util等 | |
hutool-cron | 定时任务模块,提供类Crontab表达式的定时任务 | |
hutool-crypto | 加密解密模块,提供对称、非对称和摘要算法封装 | |
hutool-db | JDBC封装后的数据操作,基于ActiveRecord思想 | |
hutool-dfa | 基于DFA模型的多关键字查找 | |
hutool-extra | 扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等) | |
hutool-http | 基于HttpUrlConnection的Http客户端封装 | |
hutool-log | 自动识别日志实现的日志门面 | |
hutool-script | 脚本执行封装,例如Javascript | 不推荐 |
hutool-setting | 功能更强大的Setting配置文件和Properties封装 | |
hutool-system | 系统参数调用封装(JVM信息等) | |
hutool-json | JSON实现 | |
hutool-captcha | 图片验证码实现 | |
hutool-poi | 针对POI中Excel和Word的封装 | |
hutool-socket | 基于Java的NIO和AIO的Socket封装 | |
hutool-jwt | JSON Web Token (JWT)封装实现 | |
NotWriteRootClassName | 含义 | |
BeanToArray | 将对象转为array输出 | |
WriteNonStringKeyAsString | 含义 | |
NotWriteDefaultValue | 含义 | |
BrowserSecure | 含义 | |
IgnoreNonFieldGetter | 含义 | |
WriteEnumUsingName | 含义 |
4 easyExcel
https://github.com/alibaba/easyexcel/
https://www.yuque.com/easyexcel/doc/easyexcel
https://alibaba-easyexcel.github.io/
5 spring 内置的工具类
主要是 spring-boot-starter 中的
https://spring.io/blog/2021/01/27/ymnnalft-the-spring-utils-classes
package bootiful.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jmx.support.JmxUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.*;
import javax.annotation.PostConstruct;
import java.beans.PropertyDescriptor;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;
@Log4j2
@SpringBootApplication
public class BootifulApplication {
@Data
@AllArgsConstructor
@Component
public static class DemoClass {
@PostConstruct
public void begin() {
log.info("begin()");
}
private final List<Map<String, Object>> list = new ArrayList<>();
}
@Bean
ApplicationListener<ApplicationReadyEvent> ready(DemoClass demo) {
return event -> {
Assert.notNull(demo.getList(), "the list can't be null");
beansUtils(demo);
classUtils();
systemPropertyUtils();
fileCopyUtils();
aop(demo);
reflection();
ensure();
collections();
serialize();
};
}
private void ensure() {
int counter = 2;
Assert.state(counter == 2, () -> "the counter should be 2 or more. Was " + counter);
Assert.hasText("Hello, world!", () -> "this string should be a non-null, non-empty String");
}
private void reflection() {
ReflectionUtils.doWithFields(DemoClass.class, field -> log.info("field = " + field.toString()));
ReflectionUtils.doWithMethods(DemoClass.class, method -> log.info("method = " + method.toString()));
Field list = ReflectionUtils.findField(DemoClass.class, "list");
log.info(Objects.requireNonNull(list).toString());
ResolvableType rt = ResolvableType.forField(list);
log.info(rt.toString());
}
private void aop(DemoClass demoClass) {
Class<?> targetClass = AopUtils.getTargetClass(demoClass);
log.info("Class<?> is " + targetClass);
log.info("is AOP proxy? " + AopUtils.isAopProxy(demoClass));
log.info("is CGlib proxy? " + AopUtils.isCglibProxy(demoClass));
}
private void collections() {
Collection<String> names = Arrays.asList("Tammie", "Kimly", "Josh");
boolean contains = CollectionUtils.containsAny(names, Arrays.asList("Josh"));
Assert.state(contains, () -> "one or more of the names in " + names.toString() + " should be present");
}
private void serialize() {
Customer in = new Customer(593232329, "Josh");
byte[] bytes = SerializationUtils.serialize(in);
Customer out = (Customer) SerializationUtils.deserialize(bytes);
Assert.state(out.getId() == in.getId() && out.getName().equals(in.getName()),
() -> "the " + Customer.class.getName() + " did not serialize correctlyy");
}
private void fileCopyUtils() {
Resource cpr = new ClassPathResource("/application.properties");
try (Reader r = new InputStreamReader(cpr.getInputStream())) {
String contents = FileCopyUtils.copyToString(r);
log.info("application.properties contents: " + contents);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private void systemPropertyUtils() {
String resolvedText = SystemPropertyUtils.resolvePlaceholders("my home directory is ${user.home}");
log.info("resolved text: " + resolvedText);
}
private void classUtils() {
Constructor<DemoClass> demoClassConstructor = ClassUtils.getConstructorIfAvailable(DemoClass.class);
log.info("demoClassConstructor: " + demoClassConstructor);
try {
DemoClass demoClass = demoClassConstructor.newInstance();
log.info("newInstance'd demoClass: " + demoClass);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private void beansUtils(DemoClass demo) {
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(demo.getClass());
for (PropertyDescriptor pd : descriptors) {
log.info("pd: " + pd.getName());
}
}
public static void main(String[] args) {
SpringApplication.run(BootifulApplication.class, args);
}
}
@Data
class Customer implements Serializable {
static final long serialVersionUID = 1L;
private int id;
private String name;
public Customer(int id, String name) {
this.id = id;
this.name = name;
}
}
相关的工具类:
- BeanUtils - useful functions for dealing with JavaBeans
- ClassUtils - useful functions for asking questions reflectively about types
- SystemPropertyUtils - useful functions for dealing with System properties
- FileCopyUtils - useful functions for copying InputStream and OutputStream implementations
- AopUtils - useful functions for dealing with Spring’s AOP proxies
- ReflectionUtils - useful functions for dealing with reflection, broadly
- Assert - useful functions to help with design-by-contract-style assertions
- CollectionUtils - useful functions for working various Java java.util.Collection types
- SerializeUtils - useful functions for working with Java serialization