티스토리 뷰
드디어 보안과 관련한 항목이 끝나고 기술적인 부분을 다시 진행 하려 합니다.
시작하기에 앞서 RestTemplate부분 부터 진행하실분이라면 아래의 WorkSpace를 받아주세요.
-Main Work Space-
-Configuration Yml Files-
해당 파일의 위치를 D: 바로 밑으로 두고 있습니다. 위치를 변경 하실분은 Main Work Space에서 변경해주셔야합니다.
개요
개요를 간단히 말씀드리면, 일단 UserService와 OrderService간에 데이터 통신을 목적으로 두고있습니다.
간단한 예시로 만약 OrderService에서 주문을 진행하게 되면 해당 주문 정보를 UserService로 보내야 합니다.
이를 RestTemplate를 활용해서 구현하려는게 이번 포스팅의 핵심입니다!
#UserServiceApplication.java
가장 처음으로는 UserServiceApplication.java 클래스를 조금 수정해주려 합니다.
먼저 @Bean을 활용해 Restemplate를 Return 받을 수 있는 객체를 생성해줍니다.
package com.example.userservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
public class UserserviceApplication {
public static void main(String[] args) {
SpringApplication.run(UserserviceApplication.class, args);
}
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
이렇게 @Bean 등록하면 다른 쪽에서 활용 할 수 있습니다.
#UserServiceImpl.java
다음으로는 Service를 살펴보려 합니다.
기존에 getUserById(String userId)를 참조하면, Orders라는 List를 통해서 주문 정보를 받아 올 수 있게 했지만, 만들 당시에는 아무런 기능도 주지 않아서 ArrayList로 초기화만 됐지만, 이번에는 내용을 채우려 합니다.
package com.example.userservice.serviceimpl;
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.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 java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Service
public class UserServiceImpl implements UserService {
UserRepository userRepository;
BCryptPasswordEncoder passwordEncoder;
- 중략 -
@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 = "http://127.0.0.1:8000/order-service/%s/orders"
userDto.setOrders(orders);
return userDto;
}
- 중략 -
}
다음과 같이 String orderUrl을 먼저 지정해줍니다. 오류가 나도 걱정하지마세요! 일단 선언만 해둔겁니다.
해당 Url은 Order-Service에 있네요 내용을 한번 확인해볼까요?
@GetMapping에 getOrder라는 이름으로 userId에 기반해 주문정보를 return하고 있네요.
그럼 이제 해당 정보를 RestTemplate를 통해서 가져와보도록 해봅시다!
먼저 해당 생성자에 Envirment와 RestTemplate 변수를 등록 해줍니다.
Environment env;
RestTemplate restTemplate;
@Autowired
public UserServiceImpl(UserRepository userRepository,
BCryptPasswordEncoder passwordEncoder,
Environment env,
RestTemplate restTemplate){
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.env = env;
this.restTemplate = restTemplate;
}
다음으로는 orderList를 받아 올 수 있도록 코드를 작성해줍니다.
@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 = "http://127.0.0.1:8000/order-service/%s/orders";
/*RestTemplate*/
// List<ResponseOrder>는 OrderService 에서 Order 정보를 가져올때 해당 형태로 담기 때문에 맞춰줘야 합니다.
ResponseEntity<List<ResponseOrder>> orderListResponse =
restTemplate.exchange(orderUrl, HttpMethod.GET, null,
new ParameterizedTypeReference<List<ResponseOrder>>() {
});
// orderListReponse는 그대로 가져올 수 없기에 타입에 맞게 Body값을 가져옵니다.
List<ResponseOrder> orderList = orderListResponse.getBody();
userDto.setOrders(orderList);
return userDto;
}
제일 중요하다고 생각되는 RestTemplate부분을 살펴볼게요.
restTemplate.exchange(orderUrl, HttpMethod.GET, null,
new ParameterizedTypeReference<List<ResponseOrder>>()
총 4개의 입력값이 있는데 아래와 같은 역할 입니다.
orderUrl ( 통신을 원하는 URL ) , HttpMethod.GET ( 메서드 타입 ) , null ( 입력 Entity ) , new Parmeter~ ( 결과값을 Return할 객체 )
지금 입력 Entity를 null값으로 준 이유는 이미, Body값으로 아무것도 안줘도 되는 상황이기 떄문입니다.
#user-service.yml
다만 URL을 저런식으로 그냥 노출 시키는 방식은 좋은 방법은 아닙니다.
그래서 user-service.yml 파일을 조금 수정하려합니다.
아까 생성자에 env를 추가했으니, 해당 env값을 이용해서 Url을 받아 올 수 있도록 설정을 추가해줍니다.
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb
username: sa
password: '{cipher}AQA3Wlcwu01k0p9/hdLhSv5L/WKKo452yh576T+I/AV5kiNckUu6PBPdmetCB0zecb7AkoktLfqZPt6ziznW3slrKHkIb39vyQjFcn0wKTdp6t38e84uoQbWp5SH7BXsT3pTYrmSwPGDvgr3K3NgPAnfZ0zOntmjR/ImO1YetawqFD3OQUqVxMYB93l6z6lG92vSbZpRRp2tJ9lke1u6zeV+vG3tEeFuezk3nb/r8dk8SGtRjru41tUD/g0fQ9R3Rf/i/0Sly9eN9Q2NAAVJ1Be6ohOMexth1oSQoeKQqmwPVCXxwglpDWvntxfanmsK5oavLeOeglkoXFg9JWVst2A9hJHPke6jyTabzuiz+kv3gHcNrih9bJ9RrEifJ4Xl2a8='
token:
expiration_time: 864000000
secret: user_token_user_service_native
gateway:
ip: 0.0.0.0
order_service:
url: http://127.0.0.1:8000/order-service/%s/orders
다만 url에서 확인할 수 있듯이 %s가 들어가 있으니 String.format 함수를 이용해서 받아 올 수 있도록 합시다.
#UserServiceImpl
orderUrl을 다음과 같이 변경해주면 완료입니다. 해당 orderUrl은 기존에 작성한 것과 동일한 값을 담고 있습니다!
짧막하게 알고가기 env를 활용하면 서버설정 파일의 값을 가져올 수 있다. 반드시 생성자에 등록하는 것은 잊지 말것!
String orderUrl = String.format(env.getProperty("order_service.url"),userId);
#TEST
그럼 이제 Test를 위해서 프로젝트를 실행시켜줍니다. 실행에 필요한 프로젝트는 아래와 같습니다.
Eureka-Server(ecommerce), Micro-Service( User,Order,Gateway), Config-Server
-회원 등록-
위와 같이 POST 요청으로 회원 등록을 진행해준 뒤 userId값을 복사할게요.
다음으로는 주문을 위해서 OrderService를 바로 호출 합니다.
-주문 등록-
복사한 ID값을 활용해 POST 메소드로 다음과 같은 요청을 보내면 주문에 대한 내용이 H2-DataBase에 저장됩니다.
-로그인 & 토큰 복사-
-회원 주문 정보 조회-
Authorization에서 받아온 토큰을 Bearer Token으로 등록하는 것도 잊지 말아주세요.
마지막으로 User정보를 조회 시 다음과 같이 주문정보를 출력한다면 성공입니다!
감사합니다.
'웹 프로그래밍 > MSA 학개론' 카테고리의 다른 글
[MSA] FeignClient의 예외처리 (0) | 2022.04.27 |
---|---|
[MSA] FeignClient 를 활용한 Micro Service 간의 통신 (0) | 2022.04.27 |
[MSA Part2] 비대칭키를 이용한 암호화 처리를 통한 고도화 작업 (0) | 2022.04.26 |
[MSA Part2] 대칭키를 이용한 암호화 처리를 통한 고도화 작업 (0) | 2022.04.26 |
[MSA]Spring Cloud Bus을 이용한 Configuration 설정 -1- (0) | 2022.04.26 |
- Total
- Today
- Yesterday
- Gateway
- 운동
- 빅-오
- 루틴기록
- github
- Spring + ELK
- prometheus
- ACTUATOR
- Logstash 활용
- MSA
- UserService
- elasticSearch
- springcloud
- JWT
- producer
- git
- Logstash to ElasticSearch
- Kafka Connect
- zipkin
- rabbitmq
- 오늘저녁 삼겹살
- consumer
- docker
- 미래의나에게동기부여
- LoadBalancer
- config
- 운동일기
- MariaDB
- Feign
- kafka
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |