分享一些系统的面试题,大家可以拿去刷一刷,准备面试涨薪。
这些面试题相对应的技术点:
- JVM
- MySQL
- Mybatis
- MongoDB
- Redis
- Spring
- Spring boot
- Spring cloud
- Kafka
- RabbitMQ
- Nginx
- …
大类就是:
- Java基础
- 数据结构与算法
- 并发编程
- 数据库
- 设计模式
- 微服务
- 消息中间件
本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录
需要这份系统化的资料的朋友,可以点击这里获取
官方介绍
首先我们打开 的官网地址,映入眼帘的就是下边的三步曲:
What is it?
是一个代码生成器,它基于约定优先于配置的方法大大简化了 类型之间映射的实现。生成的映射代码使用普通方法调用,因此速度快、类型安全且易于理解。
Why?
多层应用程序通常需要在不同的对象模型(例如实体和 )之间进行映射。编写这样的映射代码是一项乏味且容易出错的任务。 旨在通过尽可能自动化来简化这项工作。
与其他映射框架不同, 在编译时生成 映射,这确保了高性能,允许快速的开发人员反馈和彻底的错误检查。
How?
是插入 编译器的注释处理器,可以在命令行构建(、等)中使用,也可以在首选 中使用。它使用合理的默认值,但在配置或实现特殊行为时,用户可以自定义实现。
官网的解释总是咬文嚼字,晦涩难懂的,看到这你只需要记住 是用来做实体类映射——实体类拷贝 的就可以了。
源码地址:https://github.com/mapstruct/mapstruct
官网推荐的 Demo:https://github.com/mapstruct/mapstruct-examples
简单实现
我们注意到官网中有涉及到简单样例的实现,我们用2分钟来分析一波:
1. 引入依赖
org.mapstruct
mapstruct-jdk8
1.3.0.Final
//注解处理器,根据注解自动生成mapper的实现
org.mapstruct
mapstruct-processor
1.2.0.Final
我们在编译时会报 错误,经过查阅资料发现 和 的版本需要统一一下:: , :。
2. 准备实体类 和 数据传输类
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CarDto {
private String make;
private int seatCount;
private String type;
}
3. 创建映射器接口,里边定义映射方法
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mapping(source = “numberOfSeats”, target = “seatCount”)
CarDto carToCarDto(Car car);
}
解析分析:
-
将接口标记为映射接口,并允许 处理器在编译期间启动。这里的 注解不是 的注解,而是 的;
-
实际映射方法 期望源对象 作为参数,并返回目标对象 ,方法名可以自由选择;
-
对于源对象和目标对象中具有不同名称的属性,可以使用 注释来配置名称;
-
对于源对象和目标对象中具有不同类型的属性,也可以使用 注释来进行转换,比如:类型属性将从枚举类型转换为字符串;
-
一个接口中可以有多个映射方法,对于所有的这些方法, 将生成一个实现;
-
该接口的实现实例可以从 中获得,接口声明一个 ,为客户端提供对映射器实现的访问。
4. 实现类
从代码中可以看出 为我们自动生成了 代码,并且对枚举类进行了特殊处理。
5. 客户端
@Test
public void shouldMapCarToDto() {
Car car = new Car( “Morris”, 5, CarType.SEDAN );
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
System.out.println(carDto);
}
小结: 基于 接口,在编译期动态生成 代码的 文件 ,在运行时直接调用该 文件。
MapStruct 配置
@Mapper
我们翻开上边提到的 注释的源码,该注释的解释是:将接口或抽象类标记为映射器,并通过 激活该类型实现的生成。我们找到其中的 componentModel 属性,默认值为 ,它有四种值供我们选择:
-
default:映射器不使用组件模型,实例通常通过 获取;
-
cdi:生成的映射器是 的,可以通过 获取;
-
spring:生成的映射器是 ,可以通过 获取;
-
jsr330:生成的映射器被 和 注释,可以通过 获取;
上边我们用的就是默认的方法,当然我们也可以用 来引入接口依赖,此处不再举例,有兴趣的小伙伴可以自己试试!
另外我们可以看下 属性:可以通过定义其他类来完成字段转换,接下来我们来个小例子演示一下:
1. 定义一个 CarVo.java 类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CarVo {
private String make;
private int seatCount;
private boolean type;
}
2. 在 mapper 中定义一个 vo 转为 dto 的方法
当不加 属性时,查看编译后生成的实现类
public CarDto carVoToCarDto(CarVo carVo) {
if (carVo == null) {
return null;
} else {
CarDto carDto = new CarDto();
carDto.setMake(carVo.getMake());
carDto.setSeatCount(carVo.getSeatCount());
carDto.setType(String.valueOf(carVo.isType()));
return carDto;
}
}
- 在 上增加 属性,并指定自定义的处理类,代码如下:
@Mapper(uses = {BooleanStrFormat.class})
public interface CarMapper {
…
}
@Component
public class BooleanStrFormat {
public String toStr(boolean type) {
if(type){
return “Y”;
}else{
return “N”;
}
}
public boolean toBoolean(String type) {
if (type.equals(“Y”)) {
return true;
} else {
return false;
}
}
}
public CarDto carVoToCarDto(CarVo carVo) {
if (carVo == null) {
return null;
} else {
CarDto carDto = new CarDto();
carDto.setMake(carVo.getMake());
carDto.setSeatCount(carVo.getSeatCount());
//调用自定义的类中的方法
carDto.setType(this.booleanStrFormat.toStr(carVo.isType()));
return carDto;
}
}
4.客户端代码
@Test
public void shouldMapCarVoToDto() {
CarVo carVo = new CarVo( “Morris”, 5, false );
CarDto carDto = CarMapper.INSTANCE.carVoToCarDto( carVo );
System.out.println(carDto);
}
@Mapping
可以用来配置一个 属性或枚举常量的映射,默认是将具有相同名称的属性进行映射,当然也可以用 、 或者 属性手动指定,接下来我们来分析下常用的属性值。
-
target:属性的目标名称,同一目标属性不能映射多次。如果用于映射枚举常量,则将给出常量成员的名称,在这种情况下,源枚举中的多个值可以映射到目标枚举的相同值。
-
source:属性的源名称,
-
如果带注释的方法有多个源参数,则属性名称必须使用参数名称限定,例如;
-
当找不到匹配的属性时, 将查找匹配的参数名称;
-
当用于映射枚举常量时,将给出常量成员的名称;
-
该属性不能与 或 一起使用;
-
dateFormat:通过 实现 到 日期之间相互转换。
-
numberFormat:通过 实现 与 的数值格式化。
-
constant:设置指定目标属性的常量字符串,当指定的目标属性的类型为: 或 (例如 )时, 检查是否可以将该 作为有效的文本分配给 或 类型。如果可能, 将分配为文字;如果不可能, 将尝试应用用户定义的映射方法。另外, 将常量作为字符串处理,将通过应用匹配方法、类型转换方法或内置转换来转换该值。此属性不能与 、、 或 一起使用。
-
expression:是一个表达式,根据该表达式设置指定的目标属性。他的属性不能与 、 、、 一起使用。
-
ignore: 忽略这个字段。
我们用 这个属性来实现一下上边用 实现的案例:
1. 在 mapper 中定义方法
@Mapping(target = “type”, expression = “java(new com.ittest.controller.BooleanStrFormat().toStr(carVo.isType()))”)
CarDto carVoToDtoWithExpression(CarVo carVo);
2. 生成的实现类
@Override
public CarDto carVoToDtoWithExpression(CarVo carVo) {
if ( carVo == null ) {
return null;
}
CarDto carDto = new CarDto();
carDto.setMake( carVo.getMake() );
carDto.setSeatCount( carVo.getSeatCount() );
carDto.setType( new com.ittest.controller.BooleanStrFormat().toStr(carVo.isType()) );
最后
笔者已经把面试题和答案整理成了面试专题文档
本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录
需要这份系统化的资料的朋友,可以点击这里获取
arVo.getSeatCount() );
carDto.setType( new com.ittest.controller.BooleanStrFormat().toStr(carVo.isType()) );
最后
笔者已经把面试题和答案整理成了面试专题文档
[外链图片转存中…(img-9uv40QvE-1715444565695)]
[外链图片转存中…(img-FCAPDYs8-1715444565695)]
[外链图片转存中…(img-jAGJwrM7-1715444565695)]
[外链图片转存中…(img-u8dooLg6-1715444565696)]
[外链图片转存中…(img-hyLdJWQA-1715444565696)]
[外链图片转存中…(img-ncLa6W41-1715444565696)]
本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录