• Spring Boot DTO 示例 - 实体到 DTO 的转换


    在本教程中,我们将学习如何在Spring Boot 应用程序中创建 DTO(数据传输对象)类,以及如何使用 ModelMapper 库将实体转换为 DTO,反之亦然。

    数据传输对象设计模式是一种常用的设计模式。它基本上用于一次性将具有多个属性的数据从客户端传递到服务器,以避免多次调用远程服务器。

    在用Java编写的RESTful API上使用DTO(以及在Spring Boot上)的另一个优点是,它们可以帮助隐藏域对象(JPA实体)的实现细节。如果我们不仔细处理可以通过哪些操作更改哪些属性,则通过终结点公开实体可能会成为安全问题。

    让我们从介绍ModelMapper Java库开始,我们将使用它来将实体转换为DTO,反之亦然。

    模型映射器库

    ModelMapper 旨在通过根据约定自动确定一个对象模型如何映射到另一个对象模型,使对象映射变得容易,就像人类一样,同时提供一个简单的、重构安全的 API 来处理特定的用例。
    ModelMapper - Simple, Intelligent, Object Mapping. 阅读有关模型映射器库的更多信息。

    我们将在pom中需要这种依赖.xml:

    1. org.modelmapper
    2. modelmapper
    3. 2.3.5

    第 1 步:将模型映射器库添加到 Pom.xml

    我们将在pom中需要这种依赖.xml:

    1. org.modelmapper
    2. modelmapper
    3. 2.3.5

    步骤 2:定义 JPA 实体 - Post.java

    让我们创建一个Post实体类并向其添加以下内容:
    1. package net.javaguides.springboot.model;
    2. import java.util.HashSet;
    3. import java.util.Set;
    4. import javax.persistence.Column;
    5. import javax.persistence.Entity;
    6. import javax.persistence.GeneratedValue;
    7. import javax.persistence.GenerationType;
    8. import javax.persistence.Id;
    9. import javax.persistence.Table;
    10. import javax.persistence.UniqueConstraint;
    11. import lombok.AllArgsConstructor;
    12. import lombok.Data;
    13. import lombok.NoArgsConstructor;
    14. @Data
    15. @NoArgsConstructor
    16. @AllArgsConstructor
    17. @Entity
    18. @Table(name = "posts", uniqueConstraints = {@UniqueConstraint(columnNames = {"title"})})
    19. public class Post {
    20. @Id
    21. @GeneratedValue(strategy = GenerationType.IDENTITY)
    22. private Long id;
    23. @Column(name = "title")
    24. private String title;
    25. @Column(name = "description")
    26. private String description;
    27. @Column(name = "content")
    28. private String content;
    29. }

    步骤 3:定义 DTO 类 - PostDto.java

    让我们创建PostDto类并向其添加以下内容:
    1. package net.javaguides.springboot.payload;
    2. import java.util.HashSet;
    3. import java.util.Set;
    4. import lombok.Data;
    5. @Data
    6. public class PostDto {
    7. private long id;
    8. private String title;
    9. private String description;
    10. private String content;
    11. }

    仅包含客户端所需的 DTO 类中的那些详细信息。实体和 DTO 字段看起来相同,但您将向客户端添加所需的字段。

    步骤 4:存储库层

    让我们创建一个PostRepository来与Post实体的数据库进行通信:
    1. package com.springboot.blog.repository;
    2. import com.springboot.blog.entity.Post;
    3. import org.springframework.data.jpa.repository.JpaRepository;
    4. public interface PostRepository extends JpaRepository {
    5. }

    第 5 步:服务层

    在服务层中,我们将只使用Post实体,而不使用PostDto类:

    PostService 接口

    1. package net.javaguides.springboot.service;
    2. import java.util.List;
    3. import net.javaguides.springboot.model.Post;
    4. public interface PostService {
    5. List getAllPosts();
    6. Post createPost(Post post);
    7. Post updatePost(long id, Post post);
    8. void deletePost(long id);
    9. Post getPostById(long id);
    10. }

    PostServiceImpl Class

    1. package net.javaguides.springboot.service.impl;
    2. import java.util.List;
    3. import java.util.Optional;
    4. import org.springframework.stereotype.Service;
    5. import net.javaguides.springboot.exception.ResourceNotFoundException;
    6. import net.javaguides.springboot.model.Post;
    7. import net.javaguides.springboot.repository.PostResository;
    8. import net.javaguides.springboot.service.PostService;
    9. @Service
    10. public class PostServiceImpl implements PostService{
    11. private final PostResository postRepository;
    12. public PostServiceImpl(PostResository postRepository) {
    13. super();
    14. this.postRepository = postRepository;
    15. }
    16. @Override
    17. public List getAllPosts() {
    18. return postRepository.findAll();
    19. }
    20. @Override
    21. public Post createPost(Post post) {
    22. return postRepository.save(post);
    23. }
    24. @Override
    25. public Post updatePost(long id, Post postRequest) {
    26. Post post = postRepository.findById(id)
    27. .orElseThrow(() -> new ResourceNotFoundException("Post", "id", id));
    28. post.setTitle(postRequest.getTitle());
    29. post.setDescription(postRequest.getDescription());
    30. post.setContent(postRequest.getContent());
    31. return postRepository.save(post);
    32. }
    33. @Override
    34. public void deletePost(long id) {
    35. Post post = postRepository.findById(id)
    36. .orElseThrow(() -> new ResourceNotFoundException("Post", "id", id));
    37. postRepository.delete(post);
    38. }
    39. @Override
    40. public Post getPostById(long id) {
    41. Optional result = postRepository.findById(id);
    42. if(result.isPresent()) {
    43. return result.get();
    44. }else {
    45. throw new ResourceNotFoundException("Post", "id", id);
    46. }
    47. // Post post = postRepository.findById(id)
    48. // .orElseThrow(() -> new ResourceNotFoundException("Post", "id", id));
    49. //return post;
    50. }
    51. }
    请注意,我们不是在服务层中使用实体到 DTO,反之亦然。

    步骤 6:将 ModelMapper 类配置为 Spring Bean

    让我们将ModelMapper类配置为 Spring bean,以便我们可以将其注入到控制器类中
    1. package net.javaguides.springboot;
    2. import org.modelmapper.ModelMapper;
    3. import org.springframework.boot.SpringApplication;
    4. import org.springframework.boot.autoconfigure.SpringBootApplication;
    5. import org.springframework.context.annotation.Bean;
    6. @SpringBootApplication
    7. public class SpringbootBlogApiApplication {
    8. @Bean
    9. public ModelMapper modelMapper() {
    10. return new ModelMapper();
    11. }
    12. public static void main(String[] args) {
    13. SpringApplication.run(SpringbootBlogApiApplication.class, args);
    14. }
    15. }

    步骤 7:控制器层

    在下面的PostController类中,我们注入了ModelMapper类,并在不同的REST API中将其用于实体到DTO的转换,反之亦然:
    1. package net.javaguides.springboot.contoller;
    2. import java.util.List;
    3. import java.util.stream.Collectors;
    4. import org.modelmapper.ModelMapper;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.http.HttpStatus;
    7. import org.springframework.http.ResponseEntity;
    8. import org.springframework.web.bind.annotation.DeleteMapping;
    9. import org.springframework.web.bind.annotation.GetMapping;
    10. import org.springframework.web.bind.annotation.PathVariable;
    11. import org.springframework.web.bind.annotation.PostMapping;
    12. import org.springframework.web.bind.annotation.PutMapping;
    13. import org.springframework.web.bind.annotation.RequestBody;
    14. import org.springframework.web.bind.annotation.RequestMapping;
    15. import org.springframework.web.bind.annotation.RestController;
    16. import net.javaguides.springboot.model.Post;
    17. import net.javaguides.springboot.payload.ApiResponse;
    18. import net.javaguides.springboot.payload.PostDto;
    19. import net.javaguides.springboot.service.PostService;
    20. @RestController
    21. @RequestMapping("/api/posts")
    22. public class PostController {
    23. @Autowired
    24. private ModelMapper modelMapper;
    25. private PostService postService;
    26. public PostController(PostService postService) {
    27. super();
    28. this.postService = postService;
    29. }
    30. @GetMapping
    31. public List getAllPosts() {
    32. return postService.getAllPosts().stream().map(post -> modelMapper.map(post, PostDto.class))
    33. .collect(Collectors.toList());
    34. }
    35. @GetMapping("/{id}")
    36. public ResponseEntity getPostById(@PathVariable(name = "id") Long id) {
    37. Post post = postService.getPostById(id);
    38. // convert entity to DTO
    39. PostDto postResponse = modelMapper.map(post, PostDto.class);
    40. return ResponseEntity.ok().body(postResponse);
    41. }
    42. @PostMapping
    43. public ResponseEntity createPost(@RequestBody PostDto postDto) {
    44. // convert DTO to entity
    45. Post postRequest = modelMapper.map(postDto, Post.class);
    46. Post post = postService.createPost(postRequest);
    47. // convert entity to DTO
    48. PostDto postResponse = modelMapper.map(post, PostDto.class);
    49. return new ResponseEntity(postResponse, HttpStatus.CREATED);
    50. }
    51. // change the request for DTO
    52. // change the response for DTO
    53. @PutMapping("/{id}")
    54. public ResponseEntity updatePost(@PathVariable long id, @RequestBody PostDto postDto) {
    55. // convert DTO to Entity
    56. Post postRequest = modelMapper.map(postDto, Post.class);
    57. Post post = postService.updatePost(id, postRequest);
    58. // entity to DTO
    59. PostDto postResponse = modelMapper.map(post, PostDto.class);
    60. return ResponseEntity.ok().body(postResponse);
    61. }
    62. @DeleteMapping("/{id}")
    63. public ResponseEntity deletePost(@PathVariable(name = "id") Long id) {
    64. postService.deletePost(id);
    65. ApiResponse apiResponse = new ApiResponse(Boolean.TRUE, "Post deleted successfully", HttpStatus.OK);
    66. return new ResponseEntity(apiResponse, HttpStatus.OK);
    67. }
    68. }
    我们在createPost()方法中使用ModelMapper将实体转换为DTO,反之亦然:
            @PostMapping
    	public ResponseEntity createPost(@RequestBody PostDto postDto) {
    
    		// convert DTO to entity
    		Post postRequest = modelMapper.map(postDto, Post.class);
    
    		Post post = postService.createPost(postRequest);
    
    		// convert entity to DTO
    		PostDto postResponse = modelMapper.map(post, PostDto.class);
    
    		return new ResponseEntity(postResponse, HttpStatus.CREATED);
    	}
    我们在更新Post() 方法中使用 ModelMapper 将实体转换为 DTO,反之亦然:
    	// change the request for DTO
    	// change the response for DTO
    	@PutMapping("/{id}")
    	public ResponseEntity updatePost(@PathVariable long id, @RequestBody PostDto postDto) {
    
    		// convert DTO to Entity
    		Post postRequest = modelMapper.map(postDto, Post.class);
    
    		Post post = postService.updatePost(id, postRequest);
    
    		// entity to DTO
    		PostDto postResponse = modelMapper.map(post, PostDto.class);
    
    		return ResponseEntity.ok().body(postResponse);
    	}
    我们在 getPostById() 方法中使用 ModelMapper 将实体转换为 DTO,反之亦然:
    	@GetMapping("/{id}")
    	public ResponseEntity getPostById(@PathVariable(name = "id") Long id) {
    		Post post = postService.getPostById(id);
    
    		// convert entity to DTO
    		PostDto postResponse = modelMapper.map(post, PostDto.class);
    
    		return ResponseEntity.ok().body(postResponse);
    	}
    
    我们在getAllPosts()方法中使用ModelMapper将实体转换为DTO,反之亦然:
            @GetMapping
    	public List getAllPosts() {
    
    		return postService.getAllPosts().stream().map(post -> modelMapper.map(post, PostDto.class))
    				.collect(Collectors.toList());
    	}

    结论

    本教程演示了如何在 Spring 引导 REST API 项目中执行从实体到 DTO 以及从 DTO 到实体的转换。我们使用了模型映射器库,而不是手动编写这些转换。

    引用

  • 相关阅读:
    Three光线投射实例
    Vite+React搭建开发构建环境实践
    Promise异步编程
    音频的各项指标
    有车型(CarModel),车厂(CarFactory),经销商(Distributor)三个表
    Shiro:中的filterChainDefinitions详解。
    JavaScript
    电脑怎么截图,4种简单常用的截图方法
    C++编程常见错误及处理
    RichView TRVUnits 图像显示单位
  • 原文地址:https://blog.csdn.net/allway2/article/details/127786646