티스토리 뷰
사용자 요청을 [API Gateway] 통해 들어오고 [Eureka]를 통해 해당 서비스를 찾습니다.
그 3가지 중 [User Service]라는 Micro Service를 JPA를 활용하여, H2 DB로 개발할 예정입니다.
단, UI없이 작업없이 진행할 예정입니다.
API는 아래와 같습니다
기능 URI(API Gateway 사용 시) URI(API Gateway 미사용 시) HTTP Method
사용자 정보 등록 | /user-service/users | /users | POST |
전체 사용자 조회 | /user-service/users | /users | GET |
사용자 정보, | |||
주문 내역 조회 | /user-service/users/{user_id} | /users/{user_id} | GET |
작동 상태 확인 | /user-service/users/health_check | /users/health_check | GET |
환영 메시지 | /user-service/users/welcome | /users/welcome | GE |
User Microservice 프로젝트 생성
java 11
spring boot: 2.6.3
spring-cloud: 2021.0.7
mysql Ver 8.0.33
dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
UserServiceApplication.java
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
- application.yml에 uereka 서버에 등록한 후, DiscoveryClient로 등록한다.
application.yml
server:
port: 0
spring:
application:
name: user-service
database:
jdbc-url: jdbc:mysql://localhost:3030/testdb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password:
driver-class-name: com.mysql.jdbc.Driver
eureka:
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: <http://localhost:8761/eureka>
greeting:
message: Welcom to the Simple E-commerce.
참고로 eureka서버는 아래와 같이 설정되어있다.
application.yml
server:
port: 8761
spring:
application:
name: discoveryservice
eureka:
client:
register-with-eureka: false
fetch-registry: false
Application.java
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Users MicroService - JPA
기능 | URI(API Gateway 사용 시) | URI(API Gateway 미사용 시) | HTTP Method |
|
1 | 사용자 정보 등록 | /user-service/users | /users | POST |
2 | 전체 사용자 조회 | /user-service/users | /users | GET |
3 | 사용자 정보, 주문 내역 조회 | /user-service/users/{user_id} | /users/{user_id} | GET |
4 | 작동 상태 확인 | /user-service/users/health_check | /users/health_check | GET |
5 | 환영 메시지 | /user-service/users/welcome | /users/welcome | GET |
아래 그림과 같이 용도별로 Entity를 만들것
- RequestUser, ResponseUser는 Controller에서 요청 및 응답 시 사용
- UserDto의 경우 Request, Response와 Entity 사이 DTO역할
- UserEntity : JPA @Entity 객체
RequestUser → UserDto → UserEntity → UserDto → ResponseUser
위 흐름으로 객체들이 흘러간다.
또한 함께 Spring Security도 간단하게 추가한다.
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>
UserServiceApplication.java
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
WebSecurity.java
@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/users/*").permitAll();
}
}
UserController.java
@RestController
@RequestMapping("/")
@RequiredArgsConstructor
public class UserController {
private final Greeting greeting;
private final UserService userService;
@GetMapping("/health_check")
public String status(){
return "It's Working in User Service";
}
@GetMapping("/greeting")
public String getGreeting(){
return greeting.getMessage();
}
@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody UserRequest userRequest){
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
UserDto userDto = modelMapper.map(userRequest, UserDto.class);
userDto = userService.createUser(userDto);
UserResponse userResponse = modelMapper.map(userDto, UserResponse.class);
return new ResponseEntity<>(userResponse, HttpStatus.CREATED);
}
}
UserRequest.java
@Data
public class UserRequest {
@NotNull(message = "Email cannot be null")
@Size(min = 2, message = "Email not be less than two characters")
@Email
private String email;
@NotNull(message = "Name cannot be null")
@Size(min = 2, message = "Name not be less than two characters")
private String name;
@NotNull(message = "Password cannot be null")
@Size(min = 8, message = "Password must be equal or grater than 8 characters and less than 16 characters")
private String pwd;
}
UserDto.java
@Data
public class UserDto {
private String email;
private String name;
private String userId;
private String pwd;
private String encryptedPwd;
private Date createAt;
}
UserEntity.java
@Data
@Entity
@Table(name = "users")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50, unique = true)
private String email;
@Column(nullable = false, length = 50)
private String name;
@Column(nullable = false, unique = true)
private String userId;
@Column(nullable = false)
private String encryptedPwd;
@Column(nullable = false)
private Date createAt;
}
UserRepository.java
@Repository
public interface UserRepository extends CrudRepository<UserEntity, Long> {
}
UserResponse.java
@Data
public class UserResponse {
private String email;
private String name;
private String userId;
}
UserService.java
public interface UserService {
UserDto createUser(UserDto userDto);
}
UserServiceImpl.java
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService{
private final UserRepository userRepository;
private final BCryptPasswordEncoder passwordEncoder;
@Override
public UserDto createUser(UserDto userDto) {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
UserEntity userEntity = modelMapper.map(userDto, UserEntity.class);
userEntity.setUserId(UUID.randomUUID().toString());
userEntity.setEncryptedPwd(passwordEncoder.encode(userDto.getPwd()));
userEntity.setCreateAt(Timestamp.valueOf(LocalDateTime.now()));
userRepository.save(userEntity);
return modelMapper.map(userEntity, UserDto.class);
}
}
하면서 모르겠는부분
RequestUser → UserDto(Service넘김) → UserEntity ( userRepository.save(userEntity) )
RequestUser | UserDto | UserEntity | |
id | O | ||
O | O | O | |
name | O | O | O |
userId | O | O | |
pwd | O | O | |
encryptedPwd | O | O | |
createAt | O | O |
createUser
ModelMapper mapper = new ModelMapper();
maper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
@Data
@Entity
@Table(name = "users")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50, unique = true)
private String email;
@Column(nullable = false, length = 50)
private String name;
@Column(nullable = false, unique = true)
private String userId;
@Column(nullable = false)
private String encryptedPwd;
@Column(nullable = false)
private Date createAt;
}
@Entity ⇒ JPA가 관리할 객체
@Table(name = "users") ⇒ 테이블명
@Id ⇒ 해당 Table의 PK
@GeneratedValue(strategy = GenerationType.IDENTITY)
public interface UserRepository extends CrudRepository<UserEntity, Long> {
}
public class UserServiceImpl implements UserService{
private final UserRepository userRepository;
@Override
public UserDto createUser(UserDto userDto) {
userRepository.save(userEntity);
spring.jpa.hibernate.ddl-auto=update
-> create 하면 table 다 drop삭제되고 다시 만들어짐
-> create-drop 하면 종료시점에 drop
-> update 재시작 시 변경된 table alter 함
drop 은 안됨
-> validate => 확인만함 db랑 구조 확인
개발초기 | create, update |
stage(테스트 서버) | update, validate |
운영 | validate, none |
spring.jpa.generate-ddl=false
spring.jpa.show-sql=true
server.port=0
# DataSource Setting
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=gbitkim
# JPA Setting
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=false
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.properties.hibernate.format_sql=true
# Logging Setting
logging.level.org.hibernate=info
eureka.instance.instance-id=${spring.application.name}:${spring.application.instance_id:${random.value}}
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
greeting.message: Welcom to the Simple E-commerce.
'MSA' 카테고리의 다른 글
Section 7: Configuration Service (0) | 2023.06.07 |
---|---|
Section 6: Users Microservice-2 (1) | 2023.06.07 |
Section 3: E-commerce 애플리케이션 (0) | 2023.06.07 |
Section 2: API Gateway Service (0) | 2023.06.07 |
Section 1: Service Discovery (0) | 2023.06.07 |
- Total
- Today
- Yesterday
- stream
- Intellij
- 자바8
- webpack
- 최종연산
- nginx
- docker
- 차이
- 람다
- 영속성 컨텍스트
- AnnotationConfigApplicationContext
- JPA
- java
- 중간연산
- ngnix
- install
- container
- mvn
- NPM
- BeanFactory
- ApplicationContext
- elasticsearch
- Vuex
- map
- MAC
- 스트림
- springboot
- lambda
- Vue
- vscode
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |