Compare commits
7 Commits
feature/ge
...
feature/ge
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd14666c8b | ||
|
|
3ea3b88b1f | ||
|
|
09cb4a3767 | ||
|
|
648638860c | ||
|
|
6f14c96931 | ||
|
|
e009c2786c | ||
|
|
cb79ec5e57 |
35
README.md
35
README.md
@@ -1,5 +1,5 @@
|
||||
# 🍿 Ticketing
|
||||
영화 예매 서비스
|
||||
영화 예매 사이트를 대용량 트래픽에 대응할 수 있도록 설계.
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -8,13 +8,37 @@
|
||||
- 기획 및 설계 : 22.04.13 ~
|
||||
- 프로젝트 구현 :
|
||||
|
||||
<br/>
|
||||
|
||||
<br/><br/>
|
||||
## 🎯 프로젝트 주요 관심사
|
||||
- OOP(객체 지향 프로그래밍)의 장점을 최대한 활용
|
||||
- 테스트 코드를 통한 믿을 수 있는 코드 작성
|
||||
- 대용량 트래픽을 고려한 확장 가능한 설계 및 성능 튜닝
|
||||
- 코드리뷰를 통해 코드 품질 향상
|
||||
- 코드 컨벤션 준수하여 코드 통일성 유지
|
||||
|
||||
## 🎯 프로젝트 목표
|
||||
<br/>
|
||||
|
||||
## 🛠 기술스택
|
||||
- Java 11
|
||||
- Spring Boot 2.6.7 (당시 최신 GA 버전)
|
||||
- Gradle Kotlin DSL
|
||||
- Spring Security
|
||||
- Junit 5
|
||||
- Hibernate / SpringJPA
|
||||
- MySQL 8.0
|
||||
- Redis
|
||||
|
||||
<br/><br/>
|
||||
<br/>
|
||||
|
||||
## Wiki
|
||||
- [Git Branch 전략](https://github.com/f-lab-edu/Ticketing/wiki#-git-branch-%EC%A0%84%EB%9E%B5)
|
||||
- [Code Convention](https://github.com/f-lab-edu/Ticketing/wiki#-code-convention)
|
||||
- [패키지 구조](https://github.com/f-lab-edu/Ticketing/wiki#-%ED%8C%A8%ED%82%A4%EC%A7%80-%EA%B5%AC%EC%A1%B0)
|
||||
- [Use Case](https://github.com/f-lab-edu/Ticketing/wiki/Use-Case)
|
||||
- [Prototype](https://github.com/f-lab-edu/Ticketing/wiki/Prototype)
|
||||
|
||||
<br/>
|
||||
|
||||
## 🧩 ERD
|
||||
|
||||
@@ -51,7 +75,6 @@ erDiagram
|
||||
bigint id PK "상영시간표 ID"
|
||||
bigint movie_id FK "영화 ID"
|
||||
bigint theater_id FK "상영관 ID"
|
||||
date running_date "상영 날짜"
|
||||
int round "회차"
|
||||
time start_at "시작 시간"
|
||||
time end_at "종료 시간"
|
||||
@@ -94,5 +117,3 @@ erDiagram
|
||||
datetime updated_at "수정일시"
|
||||
}
|
||||
```
|
||||
|
||||
<br/><br/>
|
||||
|
||||
@@ -23,8 +23,6 @@ repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||
@@ -32,14 +30,15 @@ dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
implementation("org.springframework.boot:spring-boot-starter-actuator")
|
||||
implementation("org.springframework.boot:spring-boot-starter-log4j2")
|
||||
implementation("org.projectlombok:lombok:1.18.20")
|
||||
implementation("org.projectlombok:lombok:1.18.24")
|
||||
implementation("io.springfox:springfox-boot-starter:3.0.0")
|
||||
implementation("io.springfox:springfox-swagger-ui:3.0.0")
|
||||
implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.4")
|
||||
implementation("com.lmax:disruptor:3.4.2")
|
||||
implementation("io.jsonwebtoken:jjwt-api:0.11.2")
|
||||
implementation("com.lmax:disruptor:3.4.4")
|
||||
implementation("io.jsonwebtoken:jjwt-api:0.11.5")
|
||||
implementation("com.googlecode.json-simple:json-simple:1.1.1")
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-redis")
|
||||
implementation("com.google.code.findbugs:jsr305:3.0.2")
|
||||
|
||||
modules {
|
||||
module("org.springframework.boot:spring-boot-starter-logging") {
|
||||
@@ -47,18 +46,14 @@ dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
testImplementation("org.springframework.security:spring-security-test")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
|
||||
|
||||
compileOnly("org.projectlombok:lombok")
|
||||
runtimeOnly("mysql:mysql-connector-java")
|
||||
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.2")
|
||||
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.2")
|
||||
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5")
|
||||
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5")
|
||||
annotationProcessor("org.projectlombok:lombok")
|
||||
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
|
||||
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
testImplementation("org.springframework.security:spring-security-test")
|
||||
}
|
||||
@@ -66,3 +61,28 @@ dependencies {
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
create("intTest") {
|
||||
compileClasspath += sourceSets.main.get().output
|
||||
runtimeClasspath += sourceSets.main.get().output
|
||||
}
|
||||
}
|
||||
|
||||
val intTestImplementation by configurations.getting {
|
||||
extendsFrom(configurations.implementation.get())
|
||||
}
|
||||
|
||||
configurations["intTestRuntimeOnly"].extendsFrom(configurations.runtimeOnly.get())
|
||||
configurations["intTestImplementation"].extendsFrom(configurations.testImplementation.get())
|
||||
|
||||
val integrationTest = task<Test>("integrationTest") {
|
||||
description = "Runs integration tests."
|
||||
group = "verification"
|
||||
|
||||
testClassesDirs = sourceSets["intTest"].output.classesDirs
|
||||
classpath = sourceSets["intTest"].runtimeClasspath
|
||||
shouldRunAfter("test")
|
||||
}
|
||||
|
||||
tasks.check { dependsOn(integrationTest) }
|
||||
|
||||
@@ -30,7 +30,7 @@ public class MovieRepositoryTest {
|
||||
@DisplayName("Movie Repository Test - saving movie")
|
||||
void shouldAbleToSaveMovie() {
|
||||
// given
|
||||
Movie movie = new Movie("범죄도시 2", 106);
|
||||
Movie movie = new Movie("범죄도시 2", 106L);
|
||||
|
||||
// when
|
||||
Movie savedMovie = movieRepository.save(movie);
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.ticketing.server.movie.domain.repository;
|
||||
|
||||
public class MovieTimesRepositoryTest {
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public class TheaterRepositoryTest {
|
||||
@DisplayName("Theater Repository Test - saving theater")
|
||||
void ShouldAbleToSaveTheater() {
|
||||
// given
|
||||
Theater theater = new Theater(1, 100);
|
||||
Theater theater = new Theater(1);
|
||||
|
||||
// when
|
||||
Theater savedTheater = theaterRepository.save(theater);
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.ticketing.server.movie.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@SpringBootTest
|
||||
public class TMDBServiceImplTest {
|
||||
|
||||
@Value("${tmdb.api-key}")
|
||||
private String apiKey;
|
||||
|
||||
@Value("${tmdb.read-access-token}")
|
||||
private String readAccessToken;
|
||||
|
||||
@Autowired
|
||||
RestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
@DisplayName("TMDB Service Test - Get [Now Playing] movies")
|
||||
void shouldAbleToGetMovieList() throws Exception {
|
||||
// given
|
||||
assertNotNull(apiKey);
|
||||
assertNotNull(readAccessToken);
|
||||
|
||||
ArrayList<Charset> acceptCharset = new ArrayList<>();
|
||||
acceptCharset.add(StandardCharsets.UTF_8);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAcceptCharset(acceptCharset);
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.setBearerAuth(readAccessToken);
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("api_key", apiKey);
|
||||
params.put("language", "ko");
|
||||
|
||||
HttpEntity<?> request = new HttpEntity<>(headers);
|
||||
|
||||
// when
|
||||
ResponseEntity<?> response = restTemplate.exchange(
|
||||
"https://api.themoviedb.org/3/movie/now_playing?" + mapToUrlParam(params),
|
||||
HttpMethod.GET,
|
||||
request,
|
||||
String.class
|
||||
);
|
||||
|
||||
// JSONParser parser = new JSONParser();
|
||||
// Object obj = parser.parse(String.valueOf(response));
|
||||
// Object results = ((JSONObject) obj).get("results");
|
||||
//
|
||||
// ArrayList<String> movieList = new ArrayList<>();
|
||||
//
|
||||
// ArrayList<JSONObject> jsonMovieList = new ArrayList<>();
|
||||
|
||||
// then
|
||||
assertTrue(response.getStatusCode().is2xxSuccessful());
|
||||
}
|
||||
|
||||
private static String mapToUrlParam(Map<String, String> params) {
|
||||
StringBuffer paramData = new StringBuffer();
|
||||
|
||||
for (Map.Entry<String, String> param : params.entrySet()) {
|
||||
if (paramData.length() != 0) {
|
||||
paramData.append('&');
|
||||
}
|
||||
|
||||
paramData.append(param.getKey());
|
||||
paramData.append('=');
|
||||
paramData.append(param.getValue());
|
||||
}
|
||||
|
||||
return paramData.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ class AuthControllerTest {
|
||||
|
||||
private static final String LOGIN_URL = "/api/auth/token";
|
||||
private static final String REGISTER_URL = "/api/users";
|
||||
private static final String USER_EMAIL = "ticketing@gmail.com";
|
||||
|
||||
@Autowired
|
||||
WebApplicationContext context;
|
||||
@@ -53,7 +54,7 @@ class AuthControllerTest {
|
||||
@DisplayName("로그인 인증 성공")
|
||||
void loginSuccess() throws Exception {
|
||||
// given
|
||||
LoginRequest request = new LoginRequest("ticketing@gmail.com", "qwe123");
|
||||
LoginRequest request = new LoginRequest(USER_EMAIL, "qwe123");
|
||||
|
||||
// when
|
||||
ResultActions actions = mvc.perform(post(LOGIN_URL)
|
||||
@@ -69,7 +70,7 @@ class AuthControllerTest {
|
||||
@DisplayName("로그인 패스워드 인증 실패")
|
||||
void loginPasswordFail() throws Exception {
|
||||
// given
|
||||
LoginRequest request = new LoginRequest("ticketing@gmail.com", "qwe1234");
|
||||
LoginRequest request = new LoginRequest(USER_EMAIL, "qwe1234");
|
||||
|
||||
// when
|
||||
ResultActions actions = mvc.perform(post(LOGIN_URL)
|
||||
@@ -81,10 +82,6 @@ class AuthControllerTest {
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
private String asJsonString(Object object) throws JsonProcessingException {
|
||||
return objectMapper.writeValueAsString(object);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void init() throws Exception {
|
||||
mvc = MockMvcBuilders
|
||||
@@ -92,7 +89,7 @@ class AuthControllerTest {
|
||||
.apply(springSecurity())
|
||||
.build();
|
||||
|
||||
SignUpRequest signUpRequest = new SignUpRequest("ticketing", "ticketing@gmail.com", "qwe123", "010-2240-7920");
|
||||
SignUpRequest signUpRequest = new SignUpRequest("ticketing", USER_EMAIL, "qwe123", "010-1234-5678");
|
||||
|
||||
mvc.perform(post(REGISTER_URL)
|
||||
.content(asJsonString(signUpRequest))
|
||||
@@ -104,4 +101,8 @@ class AuthControllerTest {
|
||||
refreshRedisRepository.deleteAll();
|
||||
}
|
||||
|
||||
private String asJsonString(Object object) throws JsonProcessingException {
|
||||
return objectMapper.writeValueAsString(object);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ticketing.server.user.application;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class UserControllerTest {
|
||||
|
||||
}
|
||||
37
server/src/intTest/resources/application.yml
Normal file
37
server/src/intTest/resources/application.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:3306/ticketing_test?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
|
||||
username: ENC(LowN1n4w0Ep/DqLD8+q5Bq6AXM4b8e3V)
|
||||
password: ENC(OMvGcpZLpggFTiGNkqNe66Zq/SmJXF6o)
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
|
||||
jpa:
|
||||
properties:
|
||||
hibernate:
|
||||
show_sql: true
|
||||
format_sql: true
|
||||
hibernate:
|
||||
ddl-auto: create
|
||||
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
|
||||
jasypt:
|
||||
encryptor:
|
||||
bean: jasyptStringEncryptor
|
||||
|
||||
jwt:
|
||||
access-header: Authorization
|
||||
refresh-header: REFRESH_TOKEN
|
||||
prefix: Bearer
|
||||
secret-key: Zi1sYWItdGlja2V0aW5nLXByb2plY3Qtc3ByaW5nLWJvb3Qtc2VjdXJpdHktand0LXNlY3JldC1rZXktZi1sYWItdGlja2V0aW5nLXByb2plY3Qtc3ByaW5nLWJvb3Qtc2VjdXJpdHktand0LXNlY3JldC1rZXkK
|
||||
access-token-validity-in-seconds: 60
|
||||
refresh-token-validity-in-seconds: 259200
|
||||
|
||||
tmdb:
|
||||
api-key: 0d1503b6dcbfe1c514299b5564c649b8
|
||||
read-access-token: eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIwZDE1MDNiNmRjYmZlMWM1MTQyOTliNTU2NGM2NDliOCIsInN1YiI6IjYyOWYwODRlNzI2ZmIxMTA2NDA4MjI2NCIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.rs8KZea8QLyashILiggWFx2s46lgUtzo-xSWoDgE58A
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.ticketing.server.movie.domain;
|
||||
|
||||
import com.ticketing.server.global.dto.repository.AbstractEntity;
|
||||
import com.ticketing.server.movie.service.dto.MovieDto;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.validation.constraints.NotNull;
|
||||
@@ -15,11 +14,11 @@ import lombok.NoArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
public class Movie extends AbstractEntity {
|
||||
|
||||
@NotNull
|
||||
@Column(unique = true)
|
||||
private String title;
|
||||
@NotNull
|
||||
@Column(unique = true)
|
||||
private String title;
|
||||
|
||||
@NotNull
|
||||
private Integer runningTime;
|
||||
@NotNull
|
||||
private Long runningTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
package com.ticketing.server.movie.domain;
|
||||
|
||||
import com.ticketing.server.global.dto.repository.AbstractEntity;
|
||||
import com.ticketing.server.movie.service.dto.MovieTimeDto;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class MovieTime extends AbstractEntity {
|
||||
|
||||
@NotNull
|
||||
@@ -32,4 +37,26 @@ public class MovieTime extends AbstractEntity {
|
||||
@NotNull
|
||||
private LocalDateTime endAt;
|
||||
|
||||
@OneToMany(mappedBy = "movieTime", cascade = CascadeType.ALL)
|
||||
private List<Ticket> tickets = new ArrayList<>();
|
||||
|
||||
private MovieTime(Movie movie, Theater theater, int round, LocalDateTime startAt, LocalDateTime endAt) {
|
||||
this.movie = movie;
|
||||
this.theater = theater;
|
||||
this.round = round;
|
||||
this.startAt = startAt;
|
||||
this.endAt = endAt;
|
||||
}
|
||||
|
||||
public static MovieTime of(Movie movie, Theater theater, int round, LocalDateTime startAt) {
|
||||
Long runningTime = movie.getRunningTime();
|
||||
LocalDateTime endAt = startAt.plusMinutes(runningTime);
|
||||
|
||||
return new MovieTime(movie, theater, round, startAt, endAt);
|
||||
}
|
||||
|
||||
public List<Seat> getSeats() {
|
||||
return this.theater.getSeats();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class Seat extends AbstractEntity {
|
||||
|
||||
@NotNull
|
||||
@@ -22,4 +24,14 @@ public class Seat extends AbstractEntity {
|
||||
@NotNull
|
||||
private Integer seatRow;
|
||||
|
||||
public Seat(Integer seatColumn, Integer seatRow, Theater theater) {
|
||||
this.seatColumn = seatColumn;
|
||||
this.seatRow = seatRow;
|
||||
setTheater(theater);
|
||||
}
|
||||
|
||||
private void setTheater(Theater theater) {
|
||||
this.theater = theater;
|
||||
theater.addSeat(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,32 @@
|
||||
package com.ticketing.server.movie.domain;
|
||||
|
||||
import com.ticketing.server.global.dto.repository.AbstractEntity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Theater extends AbstractEntity {
|
||||
|
||||
@NotNull
|
||||
private Integer theaterNumber;
|
||||
|
||||
private Integer seatCount;
|
||||
@OneToMany(mappedBy = "theater", cascade = CascadeType.ALL)
|
||||
private List<Seat> seats = new ArrayList<>();
|
||||
|
||||
public Theater(Integer theaterNumber) {
|
||||
this.theaterNumber = theaterNumber;
|
||||
}
|
||||
|
||||
public void addSeat(Seat seat) {
|
||||
seats.add(seat);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,13 +3,17 @@ package com.ticketing.server.movie.domain;
|
||||
import com.ticketing.server.global.dto.repository.AbstractEntity;
|
||||
import com.ticketing.server.payment.domain.Payment;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class Ticket extends AbstractEntity {
|
||||
|
||||
@NotNull
|
||||
@@ -27,9 +31,21 @@ public class Ticket extends AbstractEntity {
|
||||
private Payment payment;
|
||||
|
||||
@NotNull
|
||||
@Enumerated(EnumType.STRING)
|
||||
private TicketStatus status;
|
||||
|
||||
@NotNull
|
||||
private Integer ticketPrice;
|
||||
|
||||
private Ticket(Seat seat, MovieTime movieTime, Integer ticketPrice) {
|
||||
this.seat = seat;
|
||||
this.movieTime = movieTime;
|
||||
this.ticketPrice = ticketPrice;
|
||||
this.status = TicketStatus.SALE;
|
||||
}
|
||||
|
||||
public static Ticket of(Seat seat, MovieTime movieTime, Integer ticketPrice) {
|
||||
return new Ticket(seat, movieTime, ticketPrice);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@ import lombok.Getter;
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TicketStatus {
|
||||
SALE("판매가능"),
|
||||
SCHEDULED("환불"),
|
||||
SOLD("판매완료");
|
||||
|
||||
private String name;
|
||||
SALE("판매가능"),
|
||||
SCHEDULED("환불"),
|
||||
SOLD("판매완료");
|
||||
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@ public interface MovieTimeRepository extends JpaRepository<MovieTime, Long> {
|
||||
+ "FROM MovieTime mt "
|
||||
+ "JOIN FETCH mt.movie "
|
||||
+ "WHERE mt.movie = :movie "
|
||||
+ "AND mt.startAt "
|
||||
+ "BETWEEN :startOfDay AND :endOfDay", nativeQuery = false)
|
||||
+ "AND mt.startAt BETWEEN :startOfDay AND :endOfDay ")
|
||||
List<MovieTime> findValidMovieTimes(Movie movie, LocalDateTime startOfDay, LocalDateTime endOfDay);
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import lombok.Getter;
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class MovieTimeDto {
|
||||
|
||||
private long movieTimeId;
|
||||
private Long movieTimeId;
|
||||
|
||||
private Integer theaterNumber;
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ticketing.server.movie.setup;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Profile(value = {"local"})
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class MovieSetupController {
|
||||
|
||||
private final MovieSetupService movieSetupService;
|
||||
|
||||
@PostConstruct
|
||||
public void setup() {
|
||||
movieSetupService.init();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.ticketing.server.movie.setup;
|
||||
|
||||
import com.ticketing.server.movie.domain.Movie;
|
||||
import com.ticketing.server.movie.domain.MovieTime;
|
||||
import com.ticketing.server.movie.domain.Seat;
|
||||
import com.ticketing.server.movie.domain.Theater;
|
||||
import com.ticketing.server.movie.domain.Ticket;
|
||||
import com.ticketing.server.movie.domain.repository.MovieRepository;
|
||||
import com.ticketing.server.movie.domain.repository.MovieTimeRepository;
|
||||
import com.ticketing.server.movie.domain.repository.TheaterRepository;
|
||||
import com.ticketing.server.movie.domain.repository.TicketRepository;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MovieSetupService {
|
||||
|
||||
private final MovieRepository movieRepository;
|
||||
private final MovieTimeRepository movieTimeRepository;
|
||||
private final TheaterRepository theaterRepository;
|
||||
private final TicketRepository ticketRepository;
|
||||
|
||||
@Transactional
|
||||
public void init() {
|
||||
initMovie();
|
||||
initTheater();
|
||||
initMovieTime();
|
||||
initTicket();
|
||||
}
|
||||
|
||||
private void initMovie() {
|
||||
List<Movie> movies = Arrays.asList(
|
||||
new Movie("탑건: 매버릭", 130L),
|
||||
new Movie("헤어질 결심", 138L),
|
||||
new Movie("마녀2", 137L),
|
||||
new Movie("범죄도시2", 106L),
|
||||
new Movie("버즈 라이트이어", 105L)
|
||||
);
|
||||
|
||||
movieRepository.saveAll(movies);
|
||||
}
|
||||
|
||||
private void initTheater() {
|
||||
List<Theater> theaters = Arrays.asList(
|
||||
new Theater(1),
|
||||
new Theater(2)
|
||||
);
|
||||
|
||||
for (Theater theater : theaters) {
|
||||
for (int i = 1; i <= 2; i++) {
|
||||
for (int j = 1; j <= 10; j++) {
|
||||
new Seat(i, j, theater);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theaterRepository.saveAll(theaters);
|
||||
}
|
||||
|
||||
private void initMovieTime() {
|
||||
List<Movie> movies = movieRepository.findAll();
|
||||
List<Theater> theaters = theaterRepository.findAll();
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
List<MovieTime> movieTimes = new ArrayList<>();
|
||||
for (Theater theater : theaters) {
|
||||
movieTimes.add(MovieTime.of(movies.get(0), theater, 1, LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 8, 0)));
|
||||
movieTimes.add(MovieTime.of(movies.get(0), theater, 3, LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 12, 0)));
|
||||
movieTimes.add(MovieTime.of(movies.get(1), theater, 2, LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 10, 0)));
|
||||
movieTimes.add(MovieTime.of(movies.get(2), theater, 4, LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 14, 0)));
|
||||
movieTimes.add(MovieTime.of(movies.get(0), theater, 5, LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 16, 0)));
|
||||
movieTimes.add(MovieTime.of(movies.get(3), theater, 6, LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 18, 0)));
|
||||
movieTimes.add(MovieTime.of(movies.get(0), theater, 7, LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 21, 0)));
|
||||
movieTimes.add(MovieTime.of(movies.get(4), theater, 8, LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 23, 0)));
|
||||
}
|
||||
|
||||
movieTimeRepository.saveAll(movieTimes);
|
||||
}
|
||||
|
||||
private void initTicket() {
|
||||
List<MovieTime> movieTimes = movieTimeRepository.findAll();
|
||||
|
||||
List<Ticket> tickets = new ArrayList<>();
|
||||
Integer ticketPrice = 15_000;
|
||||
for (MovieTime movieTime : movieTimes) {
|
||||
for (Seat seat : movieTime.getSeats()) {
|
||||
tickets.add(Ticket.of(seat, movieTime, ticketPrice));
|
||||
}
|
||||
}
|
||||
|
||||
ticketRepository.saveAll(tickets);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,4 +11,4 @@ spring:
|
||||
show_sql: true
|
||||
format_sql: true
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
ddl-auto: create
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.ticketing.server;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class ServerApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.ticketing.server.movie.domain;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
class MovieTimeTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@DisplayName("영화상영시간 생성")
|
||||
@ValueSource(longs = {130L, 140L, 30L})
|
||||
void createMovieTime(Long runningTime) {
|
||||
// given
|
||||
Movie movie = new Movie("범죄도시2", runningTime);
|
||||
Theater theater = new Theater(1);
|
||||
LocalDateTime startAt = LocalDateTime.of(2022, 7, 4, 8, 10);
|
||||
|
||||
// when
|
||||
MovieTime movieTime = MovieTime.of(movie, theater, 1, startAt);
|
||||
|
||||
// then
|
||||
assertThat(movieTime.getEndAt()).isEqualTo(startAt.plusMinutes(runningTime));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,7 +35,8 @@ public class MovieServiceImplTest {
|
||||
@DisplayName("Movie Service Test - get movies when there is no movie")
|
||||
void shouldGetEmptyList() {
|
||||
// given
|
||||
when(movieRepository.findValidMovies()).thenReturn(Collections.emptyList());
|
||||
when(movieRepository.findValidMovies())
|
||||
.thenReturn(Collections.emptyList());
|
||||
|
||||
// when
|
||||
List<MovieDto> movieDtoList = movieService.getMovies();
|
||||
@@ -48,12 +49,13 @@ public class MovieServiceImplTest {
|
||||
@DisplayName("Movie Service Test - get movies")
|
||||
void shouldAbleToGetMovies() {
|
||||
// given
|
||||
movie = new Movie("범죄도시2", 106);
|
||||
movieDto = MovieDto.from(movie);
|
||||
movie = new Movie("범죄도시2", 106L);
|
||||
movieDto = movieDto.from(movie);
|
||||
movies.add(movie);
|
||||
movieDtos.add(movieDto);
|
||||
|
||||
when(movieRepository.findValidMovies()).thenReturn(movies);
|
||||
when(movieRepository.findValidMovies())
|
||||
.thenReturn(movies);
|
||||
|
||||
// when
|
||||
List<MovieDto> movieDtoList = movieService.getMovies();
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package com.ticketing.server.movie.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
||||
import com.ticketing.server.movie.domain.Movie;
|
||||
import com.ticketing.server.movie.domain.MovieTime;
|
||||
import com.ticketing.server.movie.domain.Theater;
|
||||
import com.ticketing.server.movie.domain.repository.MovieRepository;
|
||||
import com.ticketing.server.movie.domain.repository.MovieTimeRepository;
|
||||
import com.ticketing.server.movie.service.dto.MovieTimeDto;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -20,13 +22,12 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class MovieTimeServiceImplTest {
|
||||
|
||||
LocalDateTime startOfDay = LocalDate.now().atStartOfDay().plusHours(6);
|
||||
LocalDateTime endOfDay = startOfDay.plusDays(1);
|
||||
String title = "범죄도시2";
|
||||
List<MovieTime> movieTimes = new ArrayList<>();
|
||||
|
||||
@Mock
|
||||
MovieRepository movieRepository;
|
||||
@@ -40,10 +41,12 @@ public class MovieTimeServiceImplTest {
|
||||
@Test
|
||||
@DisplayName("MovieTime Service Test - get empty list when there is no valid movie times")
|
||||
void shouldGetEmptyList() {
|
||||
String title = "범죄도시2";
|
||||
Movie movie = new Movie(title, 106);
|
||||
// given
|
||||
Movie movie = new Movie(title, 106L);
|
||||
|
||||
when(movieRepository.findByTitle(title))
|
||||
.thenReturn(Optional.of(movie));
|
||||
|
||||
when(movieRepository.findByTitle(title)).thenReturn(Optional.of(movie));
|
||||
when(movieTimeRepository.findValidMovieTimes(any(), any(), any()))
|
||||
.thenReturn(Collections.emptyList());
|
||||
|
||||
@@ -52,7 +55,31 @@ public class MovieTimeServiceImplTest {
|
||||
|
||||
// then
|
||||
assertTrue(movieTimeDtoList.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("MovieTime Service Test - get list when there is valid movie times")
|
||||
void shouldGetMovieTimeList() {
|
||||
// given
|
||||
Movie movie = new Movie(title, 106L);
|
||||
Theater theater = new Theater(1);
|
||||
MovieTime movieTime = MovieTime.of(movie, theater, 1,
|
||||
LocalDateTime.of(2022, 7, 1, 17, 0, 0)
|
||||
);
|
||||
|
||||
movieTimes.add(movieTime);
|
||||
|
||||
when(movieRepository.findByTitle(title))
|
||||
.thenReturn(Optional.of(movie));
|
||||
|
||||
when(movieTimeRepository.findValidMovieTimes(any(), any(), any()))
|
||||
.thenReturn(movieTimes);
|
||||
|
||||
// when
|
||||
List<MovieTimeDto> movieTimeDtoList = movieTimeService.getMovieTimes(title, LocalDate.of(2022, 07, 01));
|
||||
|
||||
// then
|
||||
assertTrue(!movieTimeDtoList.isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.ticketing.server.user.domain.repository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.ticketing.server.user.domain.User;
|
||||
import com.ticketing.server.user.domain.UserGrade;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@SpringBootTest
|
||||
@Transactional
|
||||
class UserRepositoryTest {
|
||||
|
||||
@Autowired
|
||||
UserRepository userRepository;
|
||||
|
||||
@Test
|
||||
void 유저레포지토리테스트() {
|
||||
// given
|
||||
User user = new User("유저1", "email@gmail.com", "testPassword01", UserGrade.GUEST, "010-1234-5678");
|
||||
|
||||
// when
|
||||
userRepository.save(user);
|
||||
|
||||
// then
|
||||
assertThat(user).isNotNull();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +1,3 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:3306/ticketing_test?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
|
||||
username: ENC(LowN1n4w0Ep/DqLD8+q5Bq6AXM4b8e3V)
|
||||
password: ENC(OMvGcpZLpggFTiGNkqNe66Zq/SmJXF6o)
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
|
||||
jpa:
|
||||
properties:
|
||||
hibernate:
|
||||
show_sql: true
|
||||
format_sql: true
|
||||
hibernate:
|
||||
ddl-auto: create
|
||||
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
|
||||
jasypt:
|
||||
encryptor:
|
||||
bean: jasyptStringEncryptor
|
||||
|
||||
jwt:
|
||||
access-header: Authorization
|
||||
|
||||
3
test/.idea/.gitignore
generated
vendored
3
test/.idea/.gitignore
generated
vendored
@@ -1,3 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
6
test/.idea/misc.xml
generated
6
test/.idea/misc.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
test/.idea/modules.xml
generated
8
test/.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/test.iml" filepath="$PROJECT_DIR$/test.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
10
test/.idea/runConfigurations.xml
generated
10
test/.idea/runConfigurations.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
6
test/.idea/vcs.xml
generated
6
test/.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
Binary file not shown.
@@ -1,148 +0,0 @@
|
||||
public class SnowFlake {
|
||||
|
||||
//Data center (machine room) id
|
||||
private long datacenterId;
|
||||
//Machine ID
|
||||
private long workerId;
|
||||
//Same time series
|
||||
private long sequence;
|
||||
|
||||
public SnowFlake(long workerId, long datacenterId) {
|
||||
this(workerId, datacenterId, 0);
|
||||
}
|
||||
|
||||
public SnowFlake(long workerId, long datacenterId, long sequence) {
|
||||
//Legal judgment
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
|
||||
}
|
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) {
|
||||
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
|
||||
}
|
||||
System.out.printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",
|
||||
timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId);
|
||||
|
||||
this.workerId = workerId;
|
||||
this.datacenterId = datacenterId;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
//Start timestamp
|
||||
private long twepoch = 1420041600000L;
|
||||
|
||||
//Machine room number, the number of digits occupied by the ID of the machine room is 5 bits, the maximum is 11111 (binary) - > 31 (decimal)
|
||||
private long datacenterIdBits = 5L;
|
||||
|
||||
//Machine ID所占的位数 5个bit 最大:11111(2进制)--> 31(10进制)
|
||||
private long workerIdBits = 5L;
|
||||
|
||||
//5 bit can only have 31 digits at most, that is, the machine ID can only be within 32 at most
|
||||
private long maxWorkerId = -1L ^ (-1L << workerIdBits);
|
||||
|
||||
//5-bit can only have 31 digits at most, and the machine room ID can only be within 32 at most
|
||||
private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
|
||||
|
||||
//Same time series所占的位数 12个bit 111111111111 = 4095 最多就是同一毫秒生成4096个
|
||||
private long sequenceBits = 12L;
|
||||
|
||||
//Offset of workerid
|
||||
private long workerIdShift = sequenceBits;
|
||||
|
||||
//Offset of datacenter ID
|
||||
private long datacenterIdShift = sequenceBits + workerIdBits;
|
||||
|
||||
//Offset of timestampleft
|
||||
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
|
||||
|
||||
//Serial number mask 4095 (0b111111 = 0xfff = 4095)
|
||||
//It is used for the sum operation of serial number to ensure that the maximum value of serial number is between 0-4095
|
||||
private long sequenceMask = -1L ^ (-1L << sequenceBits);
|
||||
|
||||
//Last timestamp
|
||||
private long lastTimestamp = -1L;
|
||||
|
||||
|
||||
//Get machine ID
|
||||
public long getWorkerId() {
|
||||
return workerId;
|
||||
}
|
||||
|
||||
|
||||
//Get machine room ID
|
||||
public long getDatacenterId() {
|
||||
return datacenterId;
|
||||
}
|
||||
|
||||
|
||||
//Get the latest timestamp
|
||||
public long getLastTimestamp() {
|
||||
return lastTimestamp;
|
||||
}
|
||||
|
||||
|
||||
//Get the next random ID
|
||||
public synchronized long nextId() {
|
||||
//Gets the current timestamp in milliseconds
|
||||
long timestamp = timeGen();
|
||||
|
||||
if (timestamp < lastTimestamp) {
|
||||
System.err.printf("clock is moving backwards. Rejecting requests until %d.", lastTimestamp);
|
||||
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
|
||||
lastTimestamp - timestamp));
|
||||
}
|
||||
|
||||
//Weight removal
|
||||
if (lastTimestamp == timestamp) {
|
||||
|
||||
sequence = (sequence + 1) & sequenceMask;
|
||||
|
||||
//Sequence sequence is greater than 4095
|
||||
if (sequence == 0) {
|
||||
//Method called to the next timestamp
|
||||
timestamp = tilNextMillis(lastTimestamp);
|
||||
}
|
||||
} else {
|
||||
//If it is the first acquisition of the current time, it is set to 0
|
||||
sequence = 0;
|
||||
}
|
||||
|
||||
//Record the last timestamp
|
||||
lastTimestamp = timestamp;
|
||||
|
||||
//Offset calculation
|
||||
return ((timestamp - twepoch) << timestampLeftShift) |
|
||||
(datacenterId << datacenterIdShift) |
|
||||
(workerId << workerIdShift) |
|
||||
sequence;
|
||||
}
|
||||
|
||||
private long tilNextMillis(long lastTimestamp) {
|
||||
//Get latest timestamp
|
||||
long timestamp = timeGen();
|
||||
//If the latest timestamp is found to be less than or equal to the timestamp whose serial number has exceeded 4095
|
||||
while (timestamp <= lastTimestamp) {
|
||||
//If not, continue
|
||||
timestamp = timeGen();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
private long timeGen() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SnowFlake worker = new SnowFlake(1, 1);
|
||||
long timer = System.currentTimeMillis();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
worker.nextId();
|
||||
}
|
||||
System.out.println(System.currentTimeMillis());
|
||||
System.out.println(System.currentTimeMillis() - timer);
|
||||
for(int i=0; i<200; i++) {
|
||||
System.out.println( );
|
||||
System.out.println(worker.nextId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Reference in New Issue
Block a user