Entiteit naar DTO-conversie voor een Spring REST API

REST Top

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS

1. Overzicht

In deze zelfstudie behandelen we de conversies die moeten plaatsvinden tussen de interne entiteiten van een Spring-applicatie en de externe DTO's (Data Transfer Objects) die terug naar de client worden gepubliceerd.

2. Modelmapper

Laten we beginnen met de introductie van de hoofdbibliotheek die we gaan gebruiken om deze entiteit-DTO-conversie uit te voeren - ModelMapper.

We hebben deze afhankelijkheid nodig in het pom.xml:

 org.modelmapper modelmapper 2.3.5 

Ga hierheen om te controleren of er een nieuwere versie van deze bibliotheek is.

We zullen dan de ModelMapper bean in onze Spring-configuratie:

@Bean public ModelMapper modelMapper () {retourneer nieuwe ModelMapper (); }

3. De DTO

Laten we vervolgens de DTO-kant van dit tweezijdige probleem introduceren - Post DTO:

openbare klasse PostDto {privé statische laatste SimpleDateFormat dateFormat = nieuwe SimpleDateFormat ("jjjj-MM-dd HH: mm"); privé lange id; private String-titel; privé String url; privé String-datum; privé UserDto gebruiker; openbare datum getSubmissionDateConverted (String tijdzone) gooit ParseException {dateFormat.setTimeZone (TimeZone.getTimeZone (tijdzone)); return dateFormat.parse (this.date); } openbare ongeldige setSubmissionDate (Datum datum, String tijdzone) {dateFormat.setTimeZone (TimeZone.getTimeZone (tijdzone)); this.date = dateFormat.format (datum); } // standaard getters en setters} 

Merk op dat de twee aangepaste datumgerelateerde methoden de datumconversie tussen de client en de server afhandelen:

  • getSubmissionDateConverted () methode zet datum om Draad in een Datum in de tijdzone van de server om het te gebruiken in de persisting Post entiteit
  • setSubmissionDate () methode is om de datum van DTO in te stellen op Post‘S Datum in de tijdzone van de huidige gebruiker.

4. De servicelaag

Laten we nu eens kijken naar een serviceniveau-bewerking - die uiteraard zal werken met de entiteit (niet de DTO):

openbare lijst getPostsList (int page, int size, String sortDir, String sort) {PageRequest pageReq = PageRequest.of (page, size, Sort.Direction.fromString (sortDir), sort); Paginaberichten = postRepository .findByUser (userService.getCurrentUser (), pageReq); retourneer posts.getContent (); }

We gaan nu de laag boven de service bekijken - de controllerlaag. Dit is waar de conversie ook daadwerkelijk zal plaatsvinden.

5. De controllerlaag

Laten we nu eens kijken naar een standaard controllerimplementatie, die de eenvoudige REST API voor het Post bron.

We gaan hier een paar eenvoudige CRUD-bewerkingen laten zien: maken, bijwerken, er een ophalen en alles ophalen. En aangezien de operaties vrij eenvoudig zijn, we zijn vooral geïnteresseerd in de Entity-DTO conversieaspecten:

@Controller klasse PostRestController {@Autowired privé IPostService postService; @Autowired private IUserService userService; @Autowired privé ModelMapper modelMapper; @GetMapping @ResponseBody openbare lijst getPosts (...) {// ... List posts = postService.getPostsList (pagina, grootte, sortDir, sortering); retourneer posts.stream () .map (this :: convertToDto) .collect (Collectors.toList ()); } @PostMapping @ResponseStatus (HttpStatus.CREATED) @ResponseBody openbare PostDto createPost (@RequestBody PostDto postDto) {Post post = convertToEntity (postDto); Post postCreated = postService.createPost (post)); return convertToDto (postCreated); } @GetMapping (waarde = "/ {id}") @ResponseBody openbare PostDto getPost (@PathVariable ("id") Lange id) {return convertToDto (postService.getPostById (id)); } @PutMapping (waarde = "/ {id}") @ResponseStatus (HttpStatus.OK) openbare ongeldige updatePost (@RequestBody PostDto postDto) {Post post = convertToEntity (postDto); postService.updatePost (plaatsen); }}

En hier is onze conversie van Post entiteit naar PostDto:

private PostDto convertToDto (Post post) {PostDto postDto = modelMapper.map (post, PostDto.class); postDto.setSubmissionDate (post.getSubmissionDate (), userService.getCurrentUser (). getPreference (). getTimezone ()); retour postDto; }

En hier is de conversie van DTO naar een entiteit:

private Post convertToEntity (PostDto postDto) gooit ParseException {Post post = modelMapper.map (postDto, Post.class); post.setSubmissionDate (postDto.getSubmissionDateConverted (userService.getCurrentUser (). getPreference (). getTimezone ())); if (postDto.getId ()! = null) {Post oldPost = postService.getPostById (postDto.getId ()); post.setRedditID (oldPost.getRedditID ()); post.setSent (oldPost.isSent ()); } retourbericht; }

Dus, zoals u kunt zien, met behulp van de model-mapper, de conversielogica is snel en eenvoudig - we gebruiken de kaart API van de mapper en het omzetten van de gegevens zonder een enkele regel conversielogica te schrijven.

6. Testen van eenheden

Laten we tot slot een heel eenvoudige test doen om er zeker van te zijn dat de conversies tussen de entiteit en de DTO goed werken:

openbare klasse PostDtoUnitTest {privé ModelMapper modelMapper = nieuw ModelMapper (); @Test openbare ongeldig whenConvertPostEntityToPostDto_thenCorrect () {Post post = nieuwe post (); post.setId (1L); post.setTitle (randomAlphabetic (6)); post.setUrl ("www.test.com"); PostDto postDto = modelMapper.map (post, PostDto.class); assertEquals (post.getId (), postDto.getId ()); assertEquals (post.getTitle (), postDto.getTitle ()); assertEquals (post.getUrl (), postDto.getUrl ()); } @Test openbare leegte whenConvertPostDtoToPostEntity_thenCorrect () {PostDto postDto = nieuwe PostDto (); postDto.setId (1L); postDto.setTitle (randomAlphabetic (6)); postDto.setUrl ("www.test.com"); Post post = modelMapper.map (postDto, Post.class); assertEquals (postDto.getId (), post.getId ()); assertEquals (postDto.getTitle (), post.getTitle ()); assertEquals (postDto.getUrl (), post.getUrl ()); }}

7. Conclusie

Dit was een artikel over vereenvoudiging van de conversie van entiteit naar DTO en van DTO naar entiteit in een Spring REST API, door de model-mapper-bibliotheek te gebruiken in plaats van deze conversies met de hand te schrijven.

De volledige broncode voor de voorbeelden is beschikbaar in het GitHub-project.

REST onder

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS