目录
目的
准备
注意
相同类型-属性名不同
实体类
映射
使用
验证-查看实现类
测试
不同类型(策略模式)
实体类
映射
工具类
使用:对象拷贝
验证-查看实现类
测试
使用:集合拷贝
测试
策略模式说明
准备-依赖
简化 BeanUtils.copyProperties 属性对拷代码,自动生成空判断,结合策略模式自定义转换
集合对拷:一行代码就能完成以前 先new,再 for循环,再add的多行代码,而且也不用判空
这里我将开发中经常用到的全部依赖都列举出来(若下载不下来依赖,将settings.xml替换成我博客存档的那一份),此处为了不影响观看,放在文章末尾处。
写好转换之后,maven 记得 clean install,查看一下生成的实现类有没有问题
实现类在 target 里面,若target没有,执行下列操作
将 下面 Doctor 中的 i1 s1 分别转给 DoctorDto 中的 i2 s2
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Doctor {
private int id;
private String name;
String s1;
int i1;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DoctorDto {
private int id;
private String name;
private String s2;
private int i2;
}
@Mapper(componentModel = "spring")
public interface BeanConvert {
BeanConvert INSTANCE = Mappers.getMapper(BeanConvert.class);
/**
* 不一致的属性映射
*/
@Mappings({
@Mapping(target = "i2", source = "i1"),
@Mapping(target = "s2", source = "s1")
})
DoctorDto toDto(Doctor doctor);
}
@GetMapping("/test")
public DoctorDto get() {
Doctor doctor = new Doctor();
doctor.setId(1);
doctor.setName("张三");
doctor.setI1(1);
doctor.setS1("1");
return BeanConvert.INSTANCE.toDto(doctor);
}
clean install 重启
可以看到 i1,s1中的值已经过来了
将下面 Sku2 中的 Long date Integer code 分别转给 SkuDTO2 中的 Date date String value
一个是时间戳转换,一个是枚举转换
@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Sku2 {
Long skuId;
String skuCode;
String skuPrice;
List nameList;
Long date;
Integer code;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class SkuDTO2 {
Long skuId;
String skuCode;
String skuPrice;
List nameList;
Date date;
String value;
}
uses 定义了两个策略,一个负责转换时间戳,一个负责转换枚举
@Mapper(componentModel = "spring", uses = {TimeConvertStrategy.class, EnumConvertStrategy.class})
public interface BeanConvert {
/**
* 策略模式测试
*/
@Mapping(target = "value", source = "code")
SkuDTO2 domain2Dto(Sku2 sku2);
}
@Component
public class EnumConvertStrategy {
public String convert(Integer code) {
return MyEnum.getByCode(code);
}
}
@Component
public class TimeConvertStrategy {
public Date date2TimeStamp(Long timeStamp) {
if (timeStamp == null) {
return null;
}
return new Date(timeStamp);
}
}
public enum MyEnum {
A(1,"哈哈"),B(2,"呵呵");
private final Integer code;
private final String msg;
MyEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
public static String getByCode(Integer code) {
if (code == null) {
return null;
}
for (MyEnum value : MyEnum.values()) {
if (value.getCode().equals(code)) {
return value.getMsg();
}
}
return null;
}
}
这里使用工具类,主要是辅助容器中的bean初始化的,包括我们定义的策略的初始化
/**
* ApplicationContextAware 接口可以让 Bean 获取到 ApplicationContext 对象
* 通过这个对象,可以获取 Spring 容器中的其他 Bean实例 或一些组件
*/
@Component
public class ConvertSupport implements ApplicationContextAware {
private static BeanConvert beanConvert;
/**
* 启动的时候,直接获取到 beanConvert 的实例
*/
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
// 这里如果没有执行,说明没有注入容器,但是我有了@Component注解,说明其未生效,主启动类@ComponentScan指定一下
if (beanConvert == null) {
beanConvert = context.getBean(BeanConvert.class);
System.out.println("执行过这里");
}
}
/**
* 列表转换
*/
public static List copyList(List inputList, BiFunction function) {
if (CollectionUtils.isEmpty(inputList)) {
return Collections.emptyList();
}
List resultList = new ArrayList<>(inputList.size());
for (I input : inputList) {
resultList.add(function.apply(beanConvert, input));
}
return resultList;
}
/**
* bean to bean
*/
public static O castBean(I input, BiFunction function) {
return function.apply(beanConvert, input);
}
}
@GetMapping("/test2")
public SkuDTO2 get2() {
Sku2 sku2 = new Sku2();
sku2.setSkuId(1L);
sku2.setSkuCode("2");
sku2.setNameList(Lists.newArrayList("测", "试"));
sku2.setDate(new Date().getTime());
sku2.setCode(1);
return ConvertSupport.castBean(sku2, BeanConvert::domain2Dto);
}
clean install 重启
@GetMapping("/test3")
public List get3() {
List list = Lists.newArrayList(
new Doctor(1, "张三", "1", 1),
new Doctor(2, "李四", "2", 2),
new Doctor(3, "王五", "3", 3));
return ConvertSupport.copyList(list, BeanConvert::toDto);
}
此后,一行代码就能完成以前 先new,再 for循环,再add的多行代码,而且也不用判空
上面使用的是用来处理不同类型,平常去除 if else 的使用方式:
先定义两个 策略,和上面类似,spring管理后,通过策略内部判断决定怎么走,方法再抽象出一层
/**
* 策略1
*/
@Component
public class Situation1 implements Situation {
private static final String value = "用户传过来的值为1";
/**
* 判断进入哪个策略(if)
*/
@Override
public Boolean judge(String val) {
return value.equals(val);
}
/**
* 逻辑处理
*/
@Override
public int logic(int a, int b) {
return a + b;
}
}
/**
* 策略2
*/
@Component
public class Situation2 implements Situation {
private static final String value = "用户传过来的值为2";
/**
* 判断进入哪个策略(if)
*/
@Override
public Boolean judge(String val) {
return value.equals(val);
}
/**
* 逻辑处理
*/
@Override
public int logic(int a, int b) {
return a - b;
}
}
public interface Situation {
/**
* 判断进入哪个策略(if)
*/
Boolean judge(String val);
/**
* 逻辑处理
*/
int logic(int a, int b);
}
@RestController
public class StrategyTest {
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/test/st")
public void test() {
String value = "用户传过来的值为2";
Map beans = applicationContext.getBeansOfType(Situation.class);
beans.forEach((k, Strategy) -> {
// 判断用户传过来的值,从而决定进入哪个策略
if (Strategy.judge(value)) {
int num = Strategy.logic(8, 2);
System.out.println(num);
}
});
}
}
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.6.1
com.mytest
springboot-demo
0.0.1-SNAPSHOT
springboot-demo
springboot-demo
1.5.0.RC1
1.18.22
0.2.0
1.8
1.8
org.springframework.boot
spring-boot-starter-web
cn.hutool
hutool-all
4.1.14
org.springframework.boot
spring-boot-starter-validation
2.3.2.RELEASE
javax.validation
validation-api
2.0.1.Final
org.quartz-scheduler
quartz
com.mchange
c3p0
eu.bitwalker
UserAgentUtils
1.21
com.github.pagehelper
pagehelper-spring-boot-starter
1.4.1
com.alibaba
fastjson
1.2.15
org.apache.httpcomponents
httpclient
org.springframework.boot
spring-boot-configuration-processor
true
com.baomidou
mybatis-plus-boot-starter
3.4.1
joda-time
joda-time
2.9.4
com.baomidou
mybatis-plus-generator
3.4.1
org.apache.velocity
velocity-engine-core
2.3
com.alibaba
easyexcel
3.0.5
cn.afterturn
easypoi-base
4.3.0
cn.afterturn
easypoi-web
4.3.0
cn.afterturn
easypoi-annotation
4.3.0
com.alibaba
druid
1.1.16
com.google.guava
guava
25.1-jre
org.springframework.boot
spring-boot-starter-data-redis
io.lettuce
lettuce-core
redis.clients
jedis
org.redisson
redisson
3.13.3
mysql
mysql-connector-java
8.0.17
org.mapstruct
mapstruct
${org.mapstruct.version}
org.projectlombok
lombok
${org.projectlombok.version}
provided
org.apache.commons
commons-lang3
3.10
commons-collections
commons-collections
3.2.2
com.google.code.google-collections
google-collect
snapshot-20080530
org.springframework.boot
spring-boot-starter-aop
com.alibaba
transmittable-thread-local
2.11.5
org.springframework.boot
spring-boot-starter-test
test
com.google.guava
guava
21.0
javax.persistence
persistence-api
1.0
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
org.projectlombok
lombok
${org.projectlombok.version}
org.projectlombok
lombok-mapstruct-binding
${lombok-mapstruct-binding.version}
org.mapstruct
mapstruct-processor
${org.mapstruct.version}
src/main/java
**/*.properties
**/*.xml
**/*.yml
false
src/main/resources
**/*.properties
**/*.xml
**/*.yml
false