Spring Boot Config - redutan/redutan.github.io GitHub Wiki

AsyncConfig

@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;
        }
    }
}

JacksonConfig

@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);
        }
    }
}

JpaConfig

@Configuration
@EnableJpaAuditing  // For @CreatedAt, @LastModifiedOn
@SuppressWarnings("squid:S1118")
public class JpaConfig {
    public static final String TINYINT = "tinyint";
    public static final String LONGVARCHAR = "mediumtext";
}

MessageConfig

  • 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);
                }
            }
        }
    }
}

WebMvcConfig

@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();
    }
}
โš ๏ธ **GitHub.com Fallback** โš ๏ธ