티스토리 뷰

저번 시간에 이어서 이번에는 FeignClient를 활용한 서비스간의 통신을 구현하려 합니다.


개요

FeignClient는 RestTemplate와 비슷하지만, 조금 더 간소화 해서 사용 할 수 있습니다.

REST Call을 추상화한 Spring Cloud Netflix의 라이브러리 입니다.

마찬가지로 User-Service에서 주문 정보를 조회하는 기능을 구현하려고 합니다.

또한 실제 구현에 앞서서 아래의 Dependency를 추가해주세요.

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

#UserServiceApplication.java

먼저 FeignClient를 활용하기위해서 MainClass를 조금 수정해줍시다.

package com.example.userservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class UserserviceApplication {

   public static void main(String[] args) {
      SpringApplication.run(UserserviceApplication.class, args);
   }

   @Bean
   public BCryptPasswordEncoder passwordEncoder(){
      return new BCryptPasswordEncoder();
   }

   @Bean
   @LoadBalanced
   public RestTemplate getRestTemplate(){return new RestTemplate();}

}

@EnableFeignClients 를 추가해 FeignClients임을 메인 클래스에 등록시켜줍니다.


#OrderServiceClient

다음으로는 FeignClient를 활용해 주문정보를 가져오기 위한 Interface를 작성할 예정입니다.

com.example.userservice에 client라는 package를 생성했습니다.

생성 후 OrderServiceClient라는 이름의 인터페이스를 작성해줍니다.

package com.example.userservice.client;

import com.example.userservice.vo.ResponseOrder;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;

/* 사용할 Service name 으로 등록해줍니다. */
@FeignClient(name="order-service")
public interface OrderServiceClient {

    /* getOrders 를 만들어주고 해당경로값을 Mapping 해줍니다.
     * userId는 가변값이기 때문에 PathVariable 으로 등록해줍니다.
     */
    @GetMapping("/order-service/{userId}/orders")
    List<ResponseOrder> getOrders(@PathVariable String userId);


}

 


#UserServiceImpl.java

UserServiceImpl파일을 다음과 같이 변경시켜줍니다.

    UserRepository userRepository;
    BCryptPasswordEncoder passwordEncoder;

    Environment env;
    RestTemplate restTemplate;
	
    /* OrderSevice Client 변수 생성 */
    OrderServiceClient orderServiceClient;
    
    @Autowired
    public UserServiceImpl(UserRepository userRepository,
                           BCryptPasswordEncoder passwordEncoder,
                           Environment env,
                           RestTemplate restTemplate,
                           OrderServiceClient orderServiceClient){
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
        this.env = env;
        this.restTemplate = restTemplate;
        /* OrderSevice Client 생성자 등록 */
        this.orderServiceClient = orderServiceClient;
    }
    -중략-
    @Override
    public UserDto getUserByUserId(String userId) {
        UserEntity userEntity = userRepository.findByUserId(userId);


        if (userEntity == null )
            throw new UsernameNotFoundException("User not found");

        UserDto userDto = new ModelMapper().map(userEntity,UserDto.class);

        String orderUrl = String.format(env.getProperty("order_service.url"),userId);

        /* Feign Client */
        List<ResponseOrder> orderList = orderServiceClient.getOrders(userId);

        userDto.setOrders(orderList);

        return userDto;
    }
    -중략-

RestTeamplate에서는 길었던 코드가 

List<ResponseOrder> orderList = orderServiceClient.getOrders(userId);

해당 코드 한줄로 해결이 됩니다. 단순히 orderServiceClient.getOrders(userId)를 호출하면 저희가 원했던 값을 리턴 받게 됩니다.


#전체코드

package com.example.userservice.serviceimpl;

import com.example.userservice.client.OrderServiceClient;
import com.example.userservice.dto.UserDto;
import com.example.userservice.jpa.UserEntity;
import com.example.userservice.jpa.UserRepository;
import com.example.userservice.service.UserService;
import com.example.userservice.vo.ResponseOrder;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class UserServiceImpl implements UserService {

    UserRepository userRepository;
    BCryptPasswordEncoder passwordEncoder;

    Environment env;
    RestTemplate restTemplate;

    OrderServiceClient orderServiceClient;
    @Autowired
    public UserServiceImpl(UserRepository userRepository,
                           BCryptPasswordEncoder passwordEncoder,
                           Environment env,
                           RestTemplate restTemplate,
                           OrderServiceClient orderServiceClient){
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
        this.env = env;
        this.restTemplate = restTemplate;
        this.orderServiceClient = orderServiceClient;
    }

    @Override
    public UserDto createUser(UserDto userDto) {
        userDto.setUserId(UUID.randomUUID().toString());

        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        UserEntity userEntity = mapper.map(userDto,UserEntity.class);
        userEntity.setEncryptedPwd(passwordEncoder.encode(userDto.getPwd()));

        userRepository.save(userEntity);

        UserDto returnUserDto = mapper.map(userEntity, UserDto.class);

        return returnUserDto;
    }

    @Override
    public UserDto getUserByUserId(String userId) {
        UserEntity userEntity = userRepository.findByUserId(userId);


        if (userEntity == null )
            throw new UsernameNotFoundException("User not found");

        UserDto userDto = new ModelMapper().map(userEntity,UserDto.class);

        String orderUrl = String.format(env.getProperty("order_service.url"),userId);

        /* Feign Client */
        List<ResponseOrder> orderList = orderServiceClient.getOrders(userId);

        userDto.setOrders(orderList);

        return userDto;
    }

    @Override
    public Iterable<UserEntity> getUserByAll() {
        return userRepository.findAll();
    }

    @Override
    public UserDto getUserDetailsByEmail(String email) {
        UserEntity userEntity = userRepository.findByEmail(email);

        if(userEntity == null)
            throw new UsernameNotFoundException(email);
        UserDto userDto = new ModelMapper().map(userEntity,UserDto.class);
        return  userDto;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity userEntity = userRepository.findByEmail(username);

        if(userEntity == null)
            throw new UsernameNotFoundException(username);


        return new User(userEntity.getEmail(), userEntity.getEncryptedPwd()
                        ,true,true,true,true,
                        new ArrayList<>());

    }
}

#TEST

Test는 저번에 진행한 방식과 동일하게 진행됩니다.

진행 시 같은 결과값을 받는 것을 확인 할 수 있습니다.

-회원등록-

-주문-

-로그인-

-주문목록-

감사합니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함