-
Notifications
You must be signed in to change notification settings - Fork 0
Spring Boot Config
정명주(myeongju.jung) edited this page Jun 28, 2019
·
1 revision
@Configuration
@EnableAsync(proxyTargetClass = true) // 비동기 활성화
@EnableConfigurationProperties(AsyncProperties.class)
public class AsyncConfig implements AsyncConfigurer {
public static final String STORAGE_EXECUTOR = "storage_executor";
private final AsyncProperties asyncProperties;
public AsyncConfig(AsyncProperties asyncProperties) {
this.asyncProperties = asyncProperties;
}
@Override
public Executor getAsyncExecutor() {
return asyncProperties.getBasic().newThreadPoolExecutor(null);
}
@Bean(STORAGE_EXECUTOR)
public ThreadPoolTaskExecutor storageExecutor() {
return asyncProperties.getStorage().newThreadPoolExecutor(null);
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new DefaultAsyncUncaughtExceptionHandler();
}
}
@Slf4j
class DefaultAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(@NonNull Throwable cause, @NonNull Method method, @NonNull Object... params) {
log.error("{}[ASYNC] {}\n{}\n{}", PREFIX_FOR_ALERT, cause.toString(), method, params, cause);
}
}
@ConfigurationProperties(prefix = "async")
@Data
@Validated
public class AsyncProperties {
/**
* 비동기를 위한 기본 threadPoolExecutor 구성 for {@link org.springframework.scheduling.annotation.Async}
*/
@NotNull
private AsyncThreadPoolProperties basic;
/**
* 스토리지 인프라를 위한 threadPoolExecutor 구성 for {@link org.springframework.scheduling.annotation.Async}
*/
@NotNull
private AsyncThreadPoolProperties storage;
/**
* @see java.util.concurrent.ThreadPoolExecutor#setRejectedExecutionHandler(RejectedExecutionHandler)
*/
public enum RejectedExecutionType {
CALLER_RUNS() {
@Override
protected RejectedExecutionHandler rejectedExecutionHandler() {
return new ThreadPoolExecutor.CallerRunsPolicy();
}
},
ABORT() {
@Override
protected RejectedExecutionHandler rejectedExecutionHandler() {
return new ThreadPoolExecutor.AbortPolicy();
}
},
DISCARD() {
@Override
protected RejectedExecutionHandler rejectedExecutionHandler() {
return new ThreadPoolExecutor.DiscardPolicy();
}
},
DISCARD_OLDEST() {
@Override
protected RejectedExecutionHandler rejectedExecutionHandler() {
return new ThreadPoolExecutor.DiscardOldestPolicy();
}
};
protected abstract RejectedExecutionHandler rejectedExecutionHandler();
}
@Data
public static class AsyncThreadPoolProperties {
/**
* 기본 threadPool 사이즈
*/
private int corePoolSize = 32;
/**
* 최대 threadPool 사이즈
*/
private int maxPoolSize = 64;
/**
* 기본 블록킹큐 사이즈
*/
private int queueCapacity = 128;
/**
* 해당 threadPool의 스레드명 접두어
*/
private String threadNamePrefix;
/**
* 비동기 실행 시 Rejected 상황에서의 전략
*/
private RejectedExecutionType rejectedExecutionType;
public ThreadPoolTaskExecutor newThreadPoolExecutor(String beanName) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
if (threadNamePrefix != null) {
executor.setThreadNamePrefix(threadNamePrefix);
}
executor.setWaitForTasksToCompleteOnShutdown(true);
if (rejectedExecutionType != null) {
executor.setRejectedExecutionHandler(rejectedExecutionType.rejectedExecutionHandler());
}
if (beanName != null) {
executor.setBeanName(beanName);
}
executor.initialize();
return executor;
}
}
}
@JsonComponent
public class JacksonConfig {
JacksonConfig() {
// config class
}
@SuppressWarnings("unused")
public static class ZonedDateTimeSerializer extends StdSerializer<ZonedDateTime> {
private static final long serialVersionUID = -771199448470001583L;
public ZonedDateTimeSerializer() {
super(ZonedDateTime.class);
}
@Override
public void serialize(ZonedDateTime zonedDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeString(zonedDateTime.toOffsetDateTime().toString());
}
}
@SuppressWarnings("unused")
public static class ZonedDateTimeDeserializer extends StdDeserializer<ZonedDateTime> {
private static final long serialVersionUID = 7252395096303780674L;
public ZonedDateTimeDeserializer() {
super(ZonedDateTime.class);
}
@Override
public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
return Optional.ofNullable(jsonParser.getValueAsString())
.map(DateTimeFormatter.ISO_OFFSET_DATE_TIME::parse)
.map(Instant::from)
.map(it -> ZonedDateTime.ofInstant(it, ZoneId.systemDefault()))
.orElse(null);
}
}
@SuppressWarnings("unused")
public static class LocalDateTimeSerializer extends StdSerializer<LocalDateTime> {
private static final long serialVersionUID = -8319362646256071330L;
public LocalDateTimeSerializer() {
super(LocalDateTime.class);
}
@Override
public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(localDateTime.toString());
}
}
@SuppressWarnings("unused")
public static class LocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
private static final long serialVersionUID = -3825800866013191618L;
public LocalDateTimeDeserializer() {
super(LocalDateTime.class);
}
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
return Optional.ofNullable(jsonParser.getValueAsString())
.map(DateTimeFormatter.ISO_DATE_TIME::parse)
.map(LocalDateTime::from)
.orElse(null);
}
}
@SuppressWarnings("unused")
public static class LongSerializer extends StdSerializer<Long> {
private static final long serialVersionUID = -7524016618355224119L;
public LongSerializer() {
super(Long.class);
}
@Override
public void serialize(Long aLong, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(aLong.toString());
}
}
@SuppressWarnings("unused")
public static class ValueObjectSerializer extends StdSerializer<ValueObject> {
private static final long serialVersionUID = 465497269532473353L;
public ValueObjectSerializer() {
super(PageCommentId.class);
}
@Override
public void serialize(ValueObject value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(value.getId().toString());
}
}
@SuppressWarnings("unused")
public static class ValueObjectDeserializer extends StdDeserializer<ValueObject> {
private static final long serialVersionUID = -1393674262465789088L;
public ValueObjectDeserializer() {
super(ValueObject.class);
}
@Override
public ValueObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return Optional.ofNullable(p.getValueAsString())
.map(Long::valueOf)
.map(ValueObject::new)
.orElse(null);
}
}
}
@Configuration
@EnableJpaAuditing // For @CreatedAt, @LastModifiedOn
@SuppressWarnings("squid:S1118")
public class JpaConfig {
public static final String TINYINT = "tinyint";
public static final String LONGVARCHAR = "mediumtext";
}
- xml 지원
@Configuration
public class MessageConfig {
/**
* {@link org.springframework.context.MessageSource}
*/
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages/error", "classpath:messages/message");
messageSource.setCacheSeconds(-1);
return messageSource;
}
}
# SpringConfig
```java
@Configuration
@EnableDiscoveryClient // Service Discovery(Registry) 클라이언트 활성화
@EnableHystrix // Circuit Breaker by Netflix Hystrix 활성화
@EnableConfigurationProperties(MyServiceProperties.class)
public class SpringCloudConfig {
public SpringCloudConfig() {
}
/**
* netflix openfeign 구성
*/
@Configuration
@EnableFeignClients(basePackageClasses = MyAppApplication.class)
public static class FeignConfig {
@Component
@Slf4j
public static class DefaultRequestInterceptor implements RequestInterceptor {
public DefaultRequestInterceptor(GlobalProperties globalProperties) {
this.globalProperties = globalProperties;
}
@Override
public void apply(RequestTemplate input) {
input.header(MyAppHeaders.APP_KEY, globalProperties.getAppKey());
input.header(MyAppHeaders.CALLER, MyAppHeaders.CALLER_APP);
String requestId = AppContextHolder.getRequestId();
if (requestId != null) {
input.header(MyAppHeaders.REQUEST_ID, requestId);
}
}
}
}
}
@Configuration
@ConditionalOnWebApplication
@EnableSpringDataWebSupport
@EnableConfigurationProperties(MultipartProperties.class)
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(slf4jMdcLoggingInterceptor());
registry.addInterceptor(myAppContextInterceptor());
}
@Bean
Slf4jMdcLoggingInterceptor slf4jMdcLoggingInterceptor() {
return new Slf4jMdcLoggingInterceptor();
}
@Bean
DoorayContextInterceptor myAppContextInterceptor() {
return new MyAppContextInterceptor();
}
}
JAVA
JPA
- JPA-Create-And-Update
- Optional-Eager
- QueryDsl-Configuration
- QueryDsl-More-Type-safety
- QueryDsl-SubQuery
DDD
Install
Spring
Spring-Boot
- Swagger2-Configuration
- Spring-Restdocs-Configuration
- Spring-Page-Jackson
- JSR310-Guide
- logback-spring.xml
- WebMvcUtils.java
- Spring-Boot-Properties
- Spring-Boot-Hidden-Gems
- Spring-Boot-Config
Spring-Cloud
- Spring-Cloud-Zuul
- Spring-Cloud-Feign
- Spring-Cloud-Hystrix
- Spring-Cloud-Consul
- Spring-Cloud-Ribbon
- Spring-Cloud-Circuit-Breaker
JavaScript
Gradle
Test
Linux
Etc
TODO http://zoltanaltfatter.com/2017/06/09/publishing-domain-events-from-aggregate-roots/