Data Transfer Object Design Pattern е често използван шаблон за проектиране. Основно се използва за предаване на данни с множество атрибути в една заявка от клиент към сървър, за да се избегнат множество повиквания към отдалечения сървър.
Предимство на използването на DTO в RESTful API, написани на Java (и със Spring Boot), е че те могат да помогнат да се скрият имплементационните детайли на обектите (JPA entities). Разкриването на тези обекти чрез крайни точки може да се превърне в проблем със сигурността, ако не боравим внимателно с това какви свойства могат да бъдат променяни и чрез какви операции.
ModelMapper e библиотека, която се използва за преобразуване на entity обект в DTO и обратно.
Стъпки за реализация:
Добавяме библиотеката ModelMapper
Copy <dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.1.1</version>
</dependency>
За автоматичното конфигуриране на bean можете да предприемете една от двете стъпки:
в Main класа добавете следния метод, анотиран с @Bean:
Copy @Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
или създайте клас-наследник на ModelMapper, анотиран с @Component
Copy @Component
public class CustomMapper extends ModelMapper {
}
Copy @Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String name;
private String email;
private String password;
}
Copy @Setter
@Getter
@NoArgsConstructor
public class UserDto {
private int id;
private String name;
private String email;
}
UserService.java
Copy public interface UserService {
public User createUser(UserDto userDto);
public UserDto getUser(int userId);
}
UserServiceImpl.java
Copy @Service
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
private ModelMapper modelMapper;
public UserServiceImpl(UserRepository userRepository,
ModelMapper modelMapper){
this.userRepository = userRepository;
this. modelMapper = modelMapper;
}
@Override
public User createUser(UserDto userDto) {
Use user = modelMapper.map(userDto, User.class);
User userSavedToDB = userRepository.save(user);
UserDto userResponse = modelMapper.map(userSavedToDB, UserDto.class);
return userResponse;
}
// update it with UserDto
@Override
public UserDto getUser(int userId) {
User user = userRepository.findById(userId).get();
UserDto userDto = modelMapper.map(user, UserDto.class);
return userDto;
}
}
UserController.java
Copy @RestController
@RequestMapping("/api/user")
public class UserController {
private UserServiceImpl userServiceImpl;
public UserController(UserServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
@PostMapping("/create")
public ResponseEntity<UserDto> createUser(@RequestBody UserDto userDto){
UserDto userCreated = this.userServiceImpl.createUser(userDto);
return new ResponseEntity<UserDto>(userCreated, HttpStatus.CREATED);
}
@GetMapping("/get/{id}")
public ResponseEntity<UserDto> getUser(@PathVariable("id") int userId){
UserDto userDto = this.userServiceImpl.getUser(userId);
return new ResponseEntity<UserDto>(userDto, HttpStatus.OK);
}
}