использование rest api из springboot, вопрос архитектуры

#spring-boot #model-view-controller #design-patterns

#spring-boot #модель-представление-контроллер #шаблоны проектирования

Вопрос:

Я хочу написать клиент REST API с SpringBoot MVC. Клиент отправит запрос к API для получения данных и покажет их в браузере. Например, у меня будетhttp://example.com/showItems сопоставлен с itemsController.показать метод и визуализировать с помощью item.html шаблон (thymeleaf).

Мой вопрос в том, куда поместить вызов API и как обращаться с ответом API. Я думаю о дизайне, а не просто заставляю его работать. Давайте также представим, что я хочу расширить до многих вызовов API, возвращающих разные объекты.

Я думаю о нескольких вариантах:

  • веб-клиент внутри контроллера. Контроллер обрабатывает вызовы API, которые возвращают объект item.
  • класс item обрабатывает вызов API. И, возможно, адаптация результата для рендеринга. Разные объекты имеют разные вызовы API. Возможно, все они внедрили один и тот же веб-клиент
  • Я создаю ItemService, который содержит «DAO», itemDAO, который вызывает API и возвращает объекты item. Аналогично репозиторию DAO модели.

Я не уверен, какое решение принять. Есть ли другой распространенный способ сделать это в spring или какой-либо другой шаблон проектирования? Или каковы могут быть плюсы / минусы каждого решения?

Ответ №1:

Существует множество подходов к использованию структуры MVC в spring boot, здесь у меня есть решение, для которого вы можете следовать этому


вот моя файловая структура

Пользовательский контроллер с @RestController //Все вызовы API Get и Post

Пользовательский сервис с помощью @Service // Определяет бизнес-логику здесь

UserRegistrationReqBean @Data //для Lombok и для уменьшения шаблонности

Мастер пользователя @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
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, чтобы внести некоторые изменения, связанные с БД

 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
    }
  

Здесь мой репозиторий пуст, поскольку я использую его предопределенные запросы

чем реализует класс сущности с @Entity аннотацией, которая определяет схему таблицы базы данных, используйте зависимость maven Lombok для сокращения шаблонного кода в сущности и компоненте запроса

     @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();
}
}
  

После бизнес-логики и схемы базы данных нам нужно определить компонент запроса для запроса post, поскольку он не позволяет нам запрашивать параметры, или мы можем сказать параметры запроса

 @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;
}
  

мы используем этот компонент запроса в классе контроллера, а также в классе обслуживания для регистрации пользователей

Комментарии:

1. ну, на самом деле я хочу использовать внешний API, приложение Spring на самом деле является клиентом.

Ответ №2:

Как правило, вся бизнес-логика и любые вызовы API должны выполняться на уровне сервиса. Вы должны настроить другой компонент service в классе configuration и выполнить вызов на уровне service (надлежащая архитектура mvc), и как только вы получите ответ, вы можете изменить его на основе ваших требований, а затем вернуть его контроллеру.