从 Spring Boot 中使用 rest api,架构问题

Posted

技术标签:

【中文标题】从 Spring Boot 中使用 rest api,架构问题【英文标题】:consuming rest api from springboot, architecture question 【发布时间】:2020-12-16 02:09:12 【问题描述】:

我想用 springBoot MVC 写一个 REST API 客户端。客户端将向 API 发送数据请求,并将其显示到浏览器中。例如,我将 http://example.com/showItems 映射到 itemsController.show 方法并由 item.html (thymeleaf) 模板呈现。

我的问题是在哪里放置 API 调用以及如何处理 API 响应。 我正在考虑设计,而不仅仅是让它发挥作用。还假设我想扩展到许多返回不同对象的 API 调用。

我正在考虑几个选项:

控制器内的 WebClient。控制器处理返回项目对象的 API 调用。 项目类负责 API 调用。并且可能会调整结果以进行渲染。不同的对象有不同的 API 调用。也许所有人都注入了相同的 WebClient 我创建了一个 itemService,其中包含一个“DAO”,一个调用 API 并返回项目对象的 itemDAO。类似于 DAO 存储库 + 模型。

我不确定采用哪种解决方案。在春季是否有另一种常见的方法,或者其他一些设计模式?或者每种解决方案的优缺点是什么?

【问题讨论】:

【参考方案1】:

在spring boot中遵循MVC的结构有很多方法 在这里,我有一个解决方案,您可以在哪里跟进


这是我的文件结构

UserController 和 @RestController //所有 Get 和 Post API 调用

UserService with @Service //Define Business Logic here

UserRegistrationReqBean @Data //用于 Lombok 并减少样板文件

UserMaster @Entity //对于表架构

UserMasterRepo @Repository //用于 Jpa 查询

UserMasterDao //与服务层交互以进行数据库查询的接口

UserMasterDaoImpl @Component //用于Dao接口定义

首先创建一个控制器类(例如我正在使用用户管理系统)

@RestController
@RequestMapping("/v1.0")
public class UserController 

    @Autowired
    UserService userService;

    @GetMapping("/getUsers")
    public List<UserMaster> getUsers() 
        return userService.getUsers();
    

    @PostMapping("/registerUser")
    public UserMaster registerUser(@RequestBody RegisterUserReqBean reqBean) 
        return userService.registerUser(reqBean);
    

//  @PostMapping("/updateUser")
//  public UserMaster updateUser() 
//      UserMaster updatedUser = new UserMaster();
//      return updatedUser;
//  


一旦您创建了控制器,然后在 Service 层中使用 @Service Annotation 定义其业务逻辑

@Service
public class UserService 

    @Autowired
    UserMasterDao userMasterDao;

    public List<UserMaster> getUsers() 
        List<UserMaster> listOfUser = userMasterDao.findAll();
        return listOfUser;
    

    public UserMaster registerUser(RegisterUserReqBean reqBean) 
        UserMaster userMaster = new UserMaster(reqBean);
        UserMaster updatedUserMaster = userMasterRepo.save(userMaster);
        return updatedUserMaster;
    

//  public UserMaster updateUser() 
//
//  

创建一个带有@Repository 注解的 Repo 类来做一些 db 相关的更改

import org.springframework.data.jpa.repository.JpaRepository;

import com.sample.user.entity.UserMaster;

    @Repository
    public interface UserMasterRepo extends JpaRepository<UserMaster, Integer> 
    
//you can create your own JPA queries here
    

这里我的存储库是空的,因为我正在使用它的预定义查询

than 使用定义数据库表模式的@Entity 注释实现实体类 使用 ma​​ven Lombok 依赖 减少 Entity 和请求 Bean 中的样板代码

    @Entity
    @Data
    @Table(name = "kd_user_master")
    public class UserMaster 
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "user_id")
        private Integer userId;
    
        @Column(name = "first_name")
        private String firstName;
    
        @Column(name = "last_name")
        private String lastName;
    
        @Column(name = "user_name")
        private String userName;
    
        @Column(name = "email")
        private String email;
    
        @Column(name = "mobile_number")
        private String mobileNumber;
    
        @Column(name = "password")
        private String password;
    
        @Column(name = "country")
        private String country;
    
        @Column(name = "created_at")
        private Date createdAt;
    
        @Column(name = "updated_at")
        private Date updatedAt;

//this parameterized cunstructer is used for having new object of userMaster //schema so we can directly save it to db 
public UserMaster(RegisterUserReqBean reqBean) 
        super();
        this.firstName = reqBean.getFirstName();
        this.lastName = reqBean.getLastName();
        this.userName = reqBean.getUserName();
        this.email = reqBean.getEmail();
        this.mobileNumber = reqBean.getMobileNumber();
        this.password = reqBean.getPassword();
        this.country = reqBean.getCountry();
        this.createdAt = new Date();
        this.updatedAt = new Date();
    
    

然后我们将创建一个DAO(数据访问对象)接口及其实现类

public interface UserMasterDao

UserMaster save(userMaster user);

List<UserMaster> findAll();

它的实现类

public class UserMasterDaoImpl implements UserMasterDao

@Autowired
UserMasterRepo repo;

@Override
UserMaster save(UserMaster user)
return repo.save(user);



@Override
List<UserMaster> findAll()
return repo.findAll();


在业务逻辑和数据库模式之后,我们需要为发布请求定义请求 bean,因为它不允许我们请求参数,或者我们可以说查询参数

@Data
public class RegisterUserReqBean 

    private String firstName;

    private String lastName;

    private String userName;

    private String email;

    private String mobileNumber;

    private String password;

    private String country;

    private Date createdAt;

    private Date updatedAt;

我们在控制器类和服务类中使用这个请求 bean 来进行用户注册

【讨论】:

好吧,其实我想CONSUME一个外部API,spring应用真的是一个客户端。【参考方案2】:

一般来说,所有的业务逻辑和任何 API 调用都应该在服务层中完成。您应该在配置类中配置其他服务 bean 并在服务层(适当的 mvc 架构)中进行调用,一旦获得响应,您可以根据您的要求对其进行更改,然后将其返回给控制器。

【讨论】:

以上是关于从 Spring Boot 中使用 rest api,架构问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring Boot 应用程序从 Rest API 返回 html

如何从 Spring Boot REST Controller 获取角度视图中的用户 ID

无法从 Spring Boot REST 中的 Hibernate POJO 返回 JSON

从 Spring Boot Rest Controller 访问 JWT 令牌

使用 Spring Boot 从不同端口提供 REST API 和静态内容

在spring boot应用程序中从自己的rest api调用另一个rest api