【问题标题】:Architecture pattern for "microservice" with hard logic (Spring boot)具有硬逻辑的“微服务”架构模式(Spring Boot)
【发布时间】:2020-06-03 15:51:39
【问题描述】:

我有一个微服务,它通过多次调用另一个微服务来实现一些优化功能(第二个计算所谓的目标函数值,第一个微服务更改这个 tagrget 函数的参数)

这导致需要在 Rest Controller 层编写一些逻辑。为了清楚起见,下面将表示一些简化的代码

@RestController
public class OptimizerController {
   private OptimizationService service;
   private RestTemplate restTemplate;

   @GetMapping("/run_opt")
   public DailyOptResponse doOpt(){
      Data iniData = service.prepareData(null);
      Result r = restTemplate.postForObject(http://calc-service/plain_calc", iniData, Result.class);

      double dt = service.assessResult(r);

      while(dt > 0.1){
          Data newData = service.preapreData(r);
          r = restTemplate.postForObject(http://calc-service/plain_calc", newData , Result.class);
          dt = service.assessResult(r);
      }

      return service.prepareResponce(r);
   }

正如我在示例中看到的,所有人都在努力使休息控制器尽可能简单,并将所有逻辑移至服务层。但是如果我必须从服务层调用其他一些微服务呢?我应该在服务层中保留数据形式的逻辑并将其返回给控制器层,在服务层中使用 RestTemplate 对象还是其他什么?

感谢您的帮助

【问题讨论】:

    标签: java spring-boot microservices spring-restcontroller


    【解决方案1】:

    这很简单。

    整个逻辑在服务层(包括其他服务)。

    简单示例:

    控制器:

    @RestController
    @RequestMapping("/api/users")
    public class UserController {
    
        private final UserManager userManager;
    
        @Autowired
        public UserController(UserManager userManager) {
            super();
            this.userManager = userManager;
        }
    
        @GetMapping()
        public List<UserResource> getUsers() {
            return userManager.getUsers();
        }
    
        @GetMapping("/{userId}")
        public UserResource getUser(@PathVariable Integer userId) {
            return userManager.getUser(userId);
        }
    
        @PutMapping
        public void updateUser(@RequestBody UserResource resource) {
            userManager.updateUser(resource);
        }
    }
    

    服务:

    @Service
    public class UserManager {
    
        private static final Logger log = LoggerFactory.getLogger(UserManager.class);
    
        private final UserRepository userRepository;
        private final UserResourceAssembler userResourceAssembler;
        private final PictureManager pictureManager;
    
        @Autowired
        public UserManager(
                UserRepository userRepository,
                UserResourceAssembler userResourceAssembler,
                PictureManager pictureManager
        ) {
    
            super();
            this.userRepository = userRepository;
            this.userResourceAssembler = userResourceAssembler;
            this.pictureManager= pictureManager;
        }
    
    
        public UserResource getUser(Integer userId) {
            User user = userRepository.findById(userId).orElseThrow(() -> new NotFoundException("User with ID " + userId + " not found!"));
            return userResourceAssembler.toResource(user);
        }
    
        public List<UserResource> getUsers() {
            return userResourceAssembler.toResources(userRepository.findAll());
        }
    
        public void updateUser(UserResource resource) {
            User user = userRepository.findById(resource.getId()).orElseThrow(() -> new NotFoundException("User with ID " + resource.getId() + " not found!"));
            PictureResource pictureResource = pictureManager.savePicture(user);
            user = userResourceAssembler.fromResource(user, resource);
            user = userRepository.save(user);
    
            log.debug("User {} updated.", user);
        }
    }
    

    服务 2:

    @Service
    public class PictureManager {
    
        private static final Logger log = LoggerFactory.getLogger(PictureManager.class);
        private final RestTemplate restTemplate;
    
        @Autowired
        public PictureManager(RestTemplate restTemplate) {
            super();
            this.restTemplate = restTemplate;
        }
    
    
        public PictureResource savePicture(User user) {
            //do some logic with user
            ResponseEntity<PictureResource> response = restTemplate.exchange(
                "url",
                HttpMethod.POST,
                requestEntity,
                PictureResource.class);
    
            return response.getBody();
        }
    }
    

    存储库:

    public interface UserRepository extends JpaRepository<User, Integer> {
    
        User findByUsername(String username);
    
    }
    

    【讨论】:

    • 感谢您的回复,但您的示例中没有在服务层中使用 Rest 模板。所以我的问题是我应该在哪里调用其他“微服务”来从它们那里获取数据(这是另一个应用程序)
    • 我认为答案已经很清楚了,但我编辑了它,以便您完全理解
    最近更新 更多