구성: 사용자→게이트웨이→유레카←(이커머스: 회원,주문,재고)←설정 서버,DB서버
1. 프로젝트 생성
2. 유레카 클라이언트로 설정
- UserServiceApplication 설정
package com.example.userservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
- yml 파일 설정
server:
port: 0
spring:
application:
name: user-service
#유레카 클라이언트-> 디스커버리로 등록 부분
eureka:
client:
register-with-eureka: true # 유레카 서버에 등록하기
fetch-registry: true # 유레카 서버에서 서버 상태 지속적 감시
service-url:
defaultZone: http://127.0.0.1:8761/eureka #8761은 유레카 디스커버리 서버 port번호 + /eureka
# 유레카에 보여지는 표시를 이름값으로 설정
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
3. 게이트웨이 서버에 등록
- 게이트웨이 서버 yml파일에 routes에 user-service 정보를 기입
server:
port: 8000
spring:
application:
name: apigateway-server
cloud:
gateway:
default-filters:
- name: GlobalFilter
args:
message: Global Filter Default Message Test
pre: true
post: true
routes: # 개별 마이크로서비스 정보를 routes에 기입함
- id: first-service
uri: lb://FIRST-SERVICE
predicates:
- Path=/first-service/**
filters:
- CustomFilter
- LogFilter
- id: second-service
uri: http://localhost:8002/
predicates:
- Path=/second-service/**
filters:
- CustomFilter2
# 유저 서비스 등록
- id: user-service
uri: lb://USER-SERVICE #직접적인 주소를 등록하지 않고 로드밸런서를 설정해서 디스커버리 유레카를 통한다.
predicates:
- Path=/user-service/**
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
default-zone: http://127.0.0.1:8761/eureka
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
4. User 기능 개발
- userController
package com.example.userservice.controller;
import com.example.userservice.domain.User;
import com.example.userservice.dto.RequestCreateUserDto;
import com.example.userservice.service.UserService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
// MVC 패턴에서 @RequestMapping("user-service")가 없어도 빌드 오류가 발생하지는 않지만
// 게이트웨이서 predicates: - Path=/user-service/** 로 등록되었기 때문에 @RequestMapping("user-service")가 필요함!!
@RequestMapping("user-service")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("health-check")
public String healthCheck(){
return "Server is available!";
}
@PostMapping("users")
public ResponseEntity<?> createUser(@Valid @RequestBody RequestCreateUserDto userDto){
// @RequestBody가 붙으면 RequestCreateUserDto 맞는 필트를 채울 수 있도록 json으로 보내주겠다
// @RequestBody가 안 붙으면 폼에서 들어온 것으로 매핑됨
// @Vaild는 사전의 지정한 양식이 맞는지 검증한 후에 역직렬화를 진행
userService.creatUser(userDto);
return ResponseEntity.ok("회원가입완료");
}
// 가입된 계정을 uuid 기반으로 찾아올 수 있도록 get 요청을 만들어주세요.
// users/{uuid}로 조회했을 때 해당하는 User 엔티티 객체를 받아옵니다.
@GetMapping("users/{uuid}")
public ResponseEntity<?> findUserByUuid(@PathVariable String uuid){
User user = userService.findUserByUuid(uuid);
return ResponseEntity.ok(user);
}
}
- UserService
package com.example.userservice.service;
import com.example.userservice.domain.User;
import com.example.userservice.dto.RequestCreateUserDto;
import com.example.userservice.repoaitory.UserRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
// 회원가입
public void creatUser(RequestCreateUserDto userDto){
// dto를 entity로 변경해주는 작업이 필요
User user = userDto.toEntity();
userRepository.save(user);
}
public User findUserByUuid(String uuid){
User user = userRepository.findUserByUuid(uuid);
return user;
}
}
- UserRepository
package com.example.userservice.repoaitory;
import com.example.userservice.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User,Long> {
User findUserByUuid(String uuid);
}
- RequestCreateUserDto
package com.example.userservice.dto;
// DTO를 사용하여 User 테이블 은닉화
// 네이밍 이유 : 요청/응답 표시 + 어떤 요청(DB)
import com.example.userservice.domain.User;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.time.LocalDateTime;
import java.util.UUID;
@Getter @Setter
@NoArgsConstructor @AllArgsConstructor @Builder
public class RequestCreateUserDto {
@Email
private String email;
@NonNull
@Size(min = 8,max = 20,message = "비밀번호는 최소 8글자이고, 최대 20글자입니다.")
private String pw;
@NonNull
private String name;
@NonNull
private String userId;
// 엔티티로 리턴함으로써 도메인 레이어를 참조
public User toEntity(){
return User.builder()
.emaiil(this.email)
.endPw(this.pw)
.userId(this.userId)
.name(this.name)
.uuid(UUID.randomUUID().toString())
.creatAt(LocalDateTime.now())
.build();
}
}
- User
package com.example.userservice.domain;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Entity
@Getter // @Setter은 엔티티 수정을 막기 위해서, 캡슐화 + 은닉화
@AllArgsConstructor @NoArgsConstructor @Builder
@Table(name="users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
private String emaiil;
private String name;
private String userId;
private String endPw;
private String uuid;
private LocalDateTime creatAt;
}
// 도메인 레이어는 다른 레이어를 참조하면 안 되지만 다른 레이어에서 도메인 레이어를 참조해도 된다.
추가 설명: UUID란
UUID(Universally Unique Identifier)는 전역적으로 고유한 식별자를 생성하기 위한 표준입니다.
엔티티식별자를 생성할 때 주의할 점은 같은 시간에 동시에 식별자를 생성해도 같은 식별자가 만들어지면 안 된다는 점입니다.
외에도 일렬번호로 자동 증가 컬럼에 비하면, DB 이전, 마이그레이션 등의 상황에서 삭제 시에도 번호 공백이 없고, 상품품명과 같은 민감한 내부 정보에 있어 수량 예측을 막는 효과도 줄 수 있습니다.
Java에서는 java.util.UUID 클래스를 사용하여 UUID를 쉽게 생성할 수 있습니다.
'MSA' 카테고리의 다른 글
Spring Cloud Config 서버를 활용한 연동 (1) | 2023.11.01 |
---|---|
JAVA 객체로 먼저 보는Join 없는 연관 관계 이해하기 (0) | 2023.10.30 |
기존 마이크로서비스를 Eureka 클라이언트로 등록 (0) | 2023.10.24 |
스프링 디스커버리를 위한 Eureka 클라이언트 생성 (1) | 2023.10.24 |
스프링 디스커버리를 위한 Eureka 서버 세팅 (1) | 2023.10.24 |