Skip to content

Commit

Permalink
refactor(to test)
Browse files Browse the repository at this point in the history
  • Loading branch information
inspire12 committed Feb 24, 2023
1 parent 7a830e4 commit 2c0181a
Show file tree
Hide file tree
Showing 44 changed files with 1,467 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM repo.ncsoft.net/paige-docker-dev-local/fp:openjdk-11-base
FROM openjdk:17-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.antMatchers("/", "/css/**", "/images/**", "/js/**", "/h2-console/**", "/actuator/**")
.permitAll()
.antMatchers("/api/v1/**").permitAll()
.antMatchers("/lab/**").permitAll()
.anyRequest().authenticated()
// .and()
// .exceptionHandling()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.inspire12.practice.api.config.web;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.concurrent.Executors;

@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

@Bean
protected WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(getTaskExecutor());
}
};
}

@Bean
protected ConcurrentTaskExecutor getTaskExecutor() {
return new ConcurrentTaskExecutor(Executors.newFixedThreadPool(5));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,15 @@
@RestController
public class LabController {

@GetMapping
public String hi() throws InterruptedException {
int i = 100;
while (i > 0) {
// Thread t = new Thread(, () -> System.out.println("hi"));

// t.start();
i--;
}
return "hi";
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package com.inspire12.practice.api.presentation.controller.sample;

import com.inspire12.practice.api.domain.posts.PostsResponseDto;
import io.micrometer.core.annotation.Timed;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.FluxSink;
import reactor.core.publisher.Mono;

import java.util.List;

@RequiredArgsConstructor
@RestController
@RequestMapping("/flux")
@RequestMapping("/api/v1/flux")
public class WebFluxController {

private final ServerProperties serverProperties;
Expand All @@ -22,8 +27,22 @@ private Mono<PostsResponseDto> getPostResponse() {
WebClient client = WebClient.create("http://localhost:" + port);

return client.get().uri("/api/v1/posts/" + "1")
.retrieve()
.bodyToMono(PostsResponseDto.class);
.retrieve()
.bodyToMono(PostsResponseDto.class);
}

@Timed
@GetMapping("/api")
public Flux<String> getTest() {
List<String> a = List.of("asdfasdfasdfasdf", "asdfasdfasdf");

return Flux.create((FluxSink<String> sink) -> {
sink.onRequest(request -> { // request는 Subscriber가 요청한 데이터 개수
for (int i = 1; i <= request; i++) {
sink.next(a.get(i)); // Flux.generate()의 경우와 달리 한 번에 한 개 이상의 next() 신호 발생 가능
}
});
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.inspire12.practice.api.presentation.controller.sample.ticker;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StopWatch;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@RequiredArgsConstructor
@Repository
public class TestRepository {

private final JdbcTemplate jdbcTemplate;

public <T> void bulkUpsert(Class<?> clz, List<T> dataList) {
if (dataList.isEmpty()) {
return;
}
String query = createQuery(clz);
int fieldCount = dataList.get(0).getClass().getDeclaredFields().length;

StopWatch timer = new StopWatch();
timer.start();
jdbcTemplate.batchUpdate(query, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) {
T data = dataList.get(i);
AtomicInteger index = new AtomicInteger(1);
ReflectionUtils.doWithFields(clz, field -> {
field.setAccessible(true);
try {
ps.setObject(index.get(), ReflectionUtils.getField(field, data));
ps.setObject(index.get() + fieldCount, ReflectionUtils.getField(field, data));
} catch (SQLException e) {
throw new RuntimeException(e);
}
index.getAndIncrement();
});
}

@Override
public int getBatchSize() {
return dataList.size();
}
});
timer.stop();
log.info("batchInsert -> Total time in seconds: " + timer.getTotalTimeSeconds());

}

private String createQuery(Class<?> clz) {
StringBuilder fieldListStr = new StringBuilder(" (");
AtomicInteger fieldCount = new AtomicInteger();
StringBuilder updateQuery = new StringBuilder();

ReflectionUtils.doWithFields(clz, field -> {
// String columnName = field.getDeclaredAnnotation(Column.class) != null ? field.getDeclaredAnnotation(Column.class).name() : field.getName();
fieldListStr.append(field.getName()).append(",");
updateQuery.append(field.getName()).append("=?").append(",");
fieldCount.getAndIncrement();
});
if (!fieldListStr.isEmpty()) {
fieldListStr.deleteCharAt(fieldListStr.length() - 1);
}
fieldListStr.append(")");
fieldListStr.append(" ");

if (!updateQuery.isEmpty()) {
updateQuery.deleteCharAt(updateQuery.length() - 1);
}

StringBuilder values = new StringBuilder("(");
for (int i = 0; i < fieldCount.get(); i++) {
values.append("?,");
}
if (values.length() > 0) {
values.deleteCharAt(values.length() - 1);
}
values.append(")");


String query = """
INSERT INTO %s %s values %s ON DUPLICATE KEY UPDATE %s
""".formatted(clz.getSimpleName(), fieldListStr, values, updateQuery);

System.out.println(query);

return query;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.inspire12.practice.api.presentation.controller.sample.ticker;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;
import org.hibernate.annotations.Comment;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(ignoreUnknown = true)
@Table
@IdClass(TickerTradeId.class)
public class TickerTrade {

@Id
@Comment(value = "거래일자")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate tradeDate;
@Id
@Comment(value = "종목코드")
private String stockCode;
@Comment(value = "종목 이름")
private String stockName;
@Comment(value = "상장된 시장(KOSPI/KOSDAQ)")
private String stockMkt;
@Comment(value = "시가 총액")
private Long mktCap;
@Comment(value = "종가( 해당 거래일 마지막 주식 가격)")
private Long close;
@Comment(value = "종가등락액 (직전 거래일 대비 등락액)")
private Long netChg;
@Comment(value = "종가등락율 (직전 거래일 대비 등락 비율)")
private Double pctChg;

@Comment(value = "딜리버리 날짜")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime deliveryTime;

@CreatedDate
@Column(updatable = false)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdDate;

@LastModifiedDate
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updatedDate;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.inspire12.practice.api.presentation.controller.sample.ticker;

import lombok.*;

import java.io.Serializable;
import java.time.LocalDate;

@Setter
@Getter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TickerTradeId implements Serializable {
private LocalDate tradeDate;
private String stockCode;
}
2 changes: 2 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ spring:
public-url: http://localhost:8000

logging:
config: classpath:logback/logback-${spring.profiles.active:local}.xml
level:
com.inspire12.practice.api: info
root: info


springdoc:
swagger-ui:
path: index.html
Expand Down
19 changes: 19 additions & 0 deletions src/main/resources/logback/logback-access.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

<!-- 로그 위치 -->
<property name="LOG_DIR" value="/usr/local/app/logs" />

<appender name="ACCESS" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/access.log.%d{yyyyMMdd}</fileNamePattern>
<maxHistory>1</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%h %l %u [%date] "%r" %s %b %D "%i{Referer}" "%i{User-Agent}"</pattern>
</encoder>
</appender>

<appender-ref ref="ACCESS" />
</configuration>
37 changes: 37 additions & 0 deletions src/main/resources/logback/logback-dev.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 로그파일 저장 경로 -->
<property name="LOG_DIR" value="/usr/local/app/logs" />

<!-- CONSOLE -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%highlight([%-5level]) %cyan(%d{yyyy-MM-dd HH:mm:ss.SSS}) : %green([%logger{0}:%line]) - %msg%n
</Pattern>
</layout>
</appender>
<!-- // CONSOLE -->
<!-- APPLICATION -->
<appender name="APPLICATION" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/application.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} : [%logger{0}:%line] - %msg%n
</Pattern>
</layout>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/application.log.%d{yyyy-MM-dd}</fileNamePattern>
<maxHistory>10</maxHistory>
</rollingPolicy>
</appender>
<!-- // APPLICATION -->

<root level="INFO">
<appender-ref ref="APPLICATION" />
<appender-ref ref="CONSOLE" />
</root>

<logger name="org.hibernate.SQL" level="DEBUG" />

</configuration>
18 changes: 18 additions & 0 deletions src/main/resources/logback/logback-inspire12.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<!-- CONSOLE -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%highlight([%-5level]) %cyan(%d{yyyy-MM-dd HH:mm:ss.SSS}) : %green([%logger{0}:%line]) - %msg%n
</Pattern>
</layout>
</appender>
<!-- // CONSOLE -->

<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>

</configuration>
Loading

0 comments on commit 2c0181a

Please sign in to comment.