티스토리 뷰
저번 시간에 이어서 이번에는 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는 저번에 진행한 방식과 동일하게 진행됩니다.
진행 시 같은 결과값을 받는 것을 확인 할 수 있습니다.
-회원등록-
-주문-
-로그인-
-주문목록-
감사합니다.
'웹 프로그래밍 > MSA 학개론' 카테고리의 다른 글
[MSA] ErrorDecoder 를 이용한 예외 처리 (0) | 2022.04.27 |
---|---|
[MSA] FeignClient의 예외처리 (0) | 2022.04.27 |
[MSA] RestTemplate를 활용한 MSA 서비스간의 통신 - 1 - (0) | 2022.04.27 |
[MSA Part2] 비대칭키를 이용한 암호화 처리를 통한 고도화 작업 (0) | 2022.04.26 |
[MSA Part2] 대칭키를 이용한 암호화 처리를 통한 고도화 작업 (0) | 2022.04.26 |
- Total
- Today
- Yesterday
- git
- 운동
- Logstash 활용
- 빅-오
- 미래의나에게동기부여
- producer
- Feign
- prometheus
- consumer
- Gateway
- config
- LoadBalancer
- springcloud
- 루틴기록
- 오늘저녁 삼겹살
- Spring + ELK
- Kafka Connect
- rabbitmq
- elasticSearch
- UserService
- JWT
- kafka
- Logstash to ElasticSearch
- MariaDB
- github
- docker
- ACTUATOR
- 운동일기
- MSA
- zipkin
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |