Spring Boot -- 使用 ModelMapper 将实体映射到 DTO
在企业应用程序中,我们使用 RESTful 服务来建立客户端和服务器之间的通信。一般的想法是客户端将请求发送到服务器,服务器对该请求做出响应。通常,我们在大多数应用程序中有三个不同的层: Web 层 、业务层 和数据库层 。这些层中的对象大多彼此不同。例如 ,Web 层对象与数据库层中的相同对象完全不同。因为数据库对象可能包含 Web 层对象中不需要的字段,例如自动生成的字段、密码字段等。
什么是 DTO?
DTO 代表数据传输对象,这些对象从一个层移动到另一个层。DTO 还可用于隐藏数据库层对象的实现细节。将实体暴露给 Web 层而没有正确处理响应可能会成为安全问题。例如 ,如果我们有一个端点,它暴露了名为 User 的实体类的详细信息。该端点处理GET请求。如果 GET 端点没有正确处理响应,人们就可以获取 User 类的所有字段甚至密码,这对于编写 RESTful 服务来说不是一个好习惯。为了克服这些问题,DTO 应运而生,通过 DTO 我们可以选择需要将哪些字段暴露给 Web 层。
ModelMapper 是一个 maven 库,用于将实体对象转换为 DTO 以及反之亦然。
在这个例子中,我们将为用户服务创建一个 restful 应用程序,该应用程序使用模型映射器库将实体转换为 DTO。
逐步实施
步骤1:创建Spring Boot项目
在此步骤中,我们将创建一个 Spring Boot 项目。
第 2 步:添加依赖项
在此步骤中,我们将依赖项添加到我们的项目中。我们将添加以下依赖项。
步骤 3:创建数据库模式
我们将使用 MySQL 作为应用程序的数据库。我们需要创建一个数据库模式。在这里,我们将使用 MySQL Workbench 创建数据库模式。为此,**打开 MySQL Workbench >**Schemas > Right-Click > Create Schema.
这将打开一个弹出窗口,我们需要在其中填写模式的名称。在这里,我们将模式命名为model_mapper_db。
一旦添加了模式的名称,我们就需要单击"应用"按钮,它将弹出另一个窗口,我们需要再次单击"应用"按钮。这将创建我们的模式。
步骤4:配置数据库
在此步骤中,我们将在 Spring Boot 应用程序中配置数据库。我们需要在application.properties文件中写入以下属性。
server.port = 9090
#database configuration
spring.datasource.url=jdbc:mysql://localhost:3306/model_mapper_db
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
#the ddl-auto=update : It will create the entity schema and map it to db automatically
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
此后,我们将运行我们的应用程序,以查看我们的应用程序是否配置为数据库。为此,转到Spring Boot 中的主类(此处为 ModelMapperApplication.java)右键单击 > 以 Java 应用程序身份运行。
一旦我们将我们的应用程序作为 Java 应用程序运行,我们就可以在控制台中看到我们的应用程序已启动并建立了与数据库的连接。
步骤 5:创建实体类
现在,我们需要创建实体类。对于我们的应用程序,我们将使用User 类作为实体类 。它将具有以下字段id、name、email 和 password。
User.java
Java
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="user-id")
private int id;
@Column(name="user-name")
private String name;
@Column(name="user-email")
private String email;
@Column(name="user-password")
private String password;
// NoArgsConstructor
public User() {
super();
}
// Getters & Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
一旦,我们编写了实体类。我们将运行我们的应用程序,由于我们已经完成了数据库配置,JPA 将使用我们添加到实体类的注释自动在数据库中创建 User 表。
步骤 6:创建用户存储库
在此步骤中,我们将创建一个接口并将其命名为UserRepository ,并将该类扩展至JPA存储库。这样,我们就可以轻松进行 CRUD 操作。
UserRepository.java
Java
import org.springframework.data.jpa.repository.JpaRepository;
import com.geeksforgeeks.ModelMapper.data.User;
// In the arguments we need to pass our model class and
// the second argument is the type of id we have used
// in our model class
public interface UserRepository extends JpaRepository<User, Integer> {
}
步骤 7:创建用户服务
现在,我们将创建一个服务接口并将其命名为 UserService。我们将只向其中添加两个方法。一个用于添加用户,另一个用于获取用户。
UserService.java
Java
import com.geeksforgeeks.ModelMapper.data.User;
public interface UserService {
public User createUser(User user);
public User getUser(int userId);
}
此后,我们将添加用户服务接口的实现。
UserServiceImpl.java
Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.geeksforgeeks.ModelMapper.data.User;
import com.geeksforgeeks.ModelMapper.repository.UserRepository;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
public User createUser(User user) {
User userSavedToDB = this.userRepository.save(user);
return userSavedToDB;
}
@Override
public User getUser(int userId) {
User user = this.userRepository.getById(userId);
return user;
}
}
步骤 8:创建控制器
在此步骤中,我们将创建一个用户控制器来处理和映射我们的请求。
UserController.java
Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.geeksforgeeks.ModelMapper.data.User;
import com.geeksforgeeks.ModelMapper.service.UserService;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
@GetMapping("/{userId}")
public User getUser(@PathVariable int userId) {
return userService.getUser(userId);
}
}
步骤 9:运行应用程序
在此步骤中,我们将使用 postman 运行我们的应用程序并测试我们的 restful 服务。
1.创建用户:
一旦发送了请求,我们将获得以下输出。
我们还可以检查数据库中是否有新用户条目。
2. 获取用户:
我们将使用 GET 端点和用户 ID 从数据库中检索用户。
正如我们在上面的响应中看到的,我们还将收到密码,这对于编写 RESTful API 来说不是一个好习惯。为了解决这个问题,我们将使用 DTO。
步骤10:创建DTO
在此步骤中,我们将创建 UserDTO 类,其中仅包含 Web 层所需和必要的字段。
UserDto.java
Java
public class UserDto {
private String name;
private String email;
// NoArgsConstructor
public UserDto() {
super();
}
// Getters & Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
步骤11:添加模型映射器依赖项
我们需要在 pom.xml 文件中添加以下依赖项。
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.1.1</version>
</dependency>
步骤 12:修改类
现在,要使用 UserDto,我们需要修改我们的 UserService、UserServiceImpl 和 UserController 类。
UserService.java
Java
import com.geeksforgeeks.ModelMapper.data.User;
import com.geeksforgeeks.ModelMapper.dto.UserDto;
public interface UserService {
public User createUser(User user);
// updated it with UserDto
public UserDto getUser(int userId);
}
UserServiceImpl.java
Java
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.geeksforgeeks.ModelMapper.data.User;
import com.geeksforgeeks.ModelMapper.dto.UserDto;
import com.geeksforgeeks.ModelMapper.repository.UserRepository;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private ModelMapper modelMapper;
@Override
public User createUser(User user) {
User userSavedToDB = this.userRepository.save(user);
return userSavedToDB;
}
// update it with UserDto
@Override
public UserDto getUser(int userId) {
User user = this.userRepository.findById(userId).get();
UserDto userDto = this.modelMapper.map(user, UserDto.class);
return userDto;
}
}
UserController.java
Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.geeksforgeeks.ModelMapper.data.User;
import com.geeksforgeeks.ModelMapper.dto.UserDto;
import com.geeksforgeeks.ModelMapper.service.UserServiceImpl;
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserServiceImpl userServiceImpl;
@PostMapping("/create")
public ResponseEntity<User> createUser(@RequestBody User user){
User userCreated = this.userServiceImpl.createUser(user);
return new ResponseEntity<User>(userCreated, HttpStatus.CREATED);
}
// update it with UserDto
@GetMapping("/get/{id}")
public ResponseEntity<UserDto> getUser(@PathVariable("id") int userId){
UserDto userDto = this.userServiceImpl.getUser(userId);
return new ResponseEntity<UserDto>(userDto, HttpStatus.OK);
}
}
步骤13:添加Model Mapper Bean
在此步骤中,我们将Model Mapper Bean 添加到我们的主要 spring boot 类中。
Java
import org.modelmapper.ModelMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class ModelMapperApplication {
public static void main(String[] args) {
SpringApplication.run(ModelMapperApplication.class, args);
}
@Bean
public ModelMapper getModelMapper() {
return new ModelMapper();
}
}
步骤 14:运行应用程序
现在,我们将再次运行我们的应用程序并使用 GET 端点来查看响应。
从上面的响应中我们可以看出,我们只获取了 Web 层所需的必要字段。虽然我们将创建一个包含所有字段的新用户,但只会将必需的字段发送到 Web 层。