diff --git a/commons/common-util/src/main/java/com/schbrain/common/util/ApplicationName.java b/commons/common-util/src/main/java/com/schbrain/common/util/ApplicationName.java index 4c98211be884a2563a03fd11fc42a152aca3246b..f3a9c569786c801c6c198d6f5a439332b3e240f6 100644 --- a/commons/common-util/src/main/java/com/schbrain/common/util/ApplicationName.java +++ b/commons/common-util/src/main/java/com/schbrain/common/util/ApplicationName.java @@ -1,7 +1,6 @@ package com.schbrain.common.util; import cn.hutool.extra.spring.SpringUtil; -import com.schbrain.common.exception.BaseException; import org.springframework.core.env.Environment; import org.springframework.core.env.EnvironmentCapable; @@ -17,11 +16,11 @@ public class ApplicationName { return Optional.ofNullable(SpringUtil.getApplicationContext()) .map(EnvironmentCapable::getEnvironment) .map(ApplicationName::get) - .orElseThrow(() -> new BaseException("Could not get application name")); + .orElseThrow(); } public static String get(Environment environment) { return environment.getRequiredProperty("spring.application.name"); } -} \ No newline at end of file +} diff --git a/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtils.java b/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtils.java index 358b6263a0509ebf8a0184ffac024b3676bbc0a7..751540ccfd1efea7476fd83bf7da79baf97afa0b 100644 --- a/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtils.java +++ b/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtils.java @@ -55,6 +55,25 @@ public class TreeUtils { return doBuildTree(keyExtractor, childrenSetter, childMapper, parentWithSubNodes, childrenComparator, parentId); } + public static List buildNodeList(List treeList, + Function> childrenGetter, + Function mapper) { + List nodes = new ArrayList<>(); + doBuildNodeList(treeList, childrenGetter, mapper, nodes); + return nodes; + } + + private static void doBuildNodeList(List treeList, + Function> childrenGetter, + Function mapper, + List nodes) { + if (CollectionUtils.isEmpty(treeList)) { + return; + } + nodes.addAll(StreamUtils.toList(treeList, mapper)); + treeList.forEach(tree -> doBuildNodeList(childrenGetter.apply(tree), childrenGetter, mapper, nodes)); + } + private static List doBuildTree(Function keyExtractor, BiConsumer> childrenSetter, Function childMapper, diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/ExceptionHandingConfiguration.java b/commons/web-common/src/main/java/com/schbrain/common/web/ExceptionHandingConfiguration.java index 88f62380b6788c008a3de47dc52c9f8c81cf7f75..15f2004f49ae92e9becb96de01c9e44acfff5ad7 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/ExceptionHandingConfiguration.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/ExceptionHandingConfiguration.java @@ -5,6 +5,7 @@ import com.schbrain.common.web.exception.ExceptionHandingWebMvcConfigurer; import com.schbrain.common.web.exception.ExceptionTranslator; import com.schbrain.common.web.exception.GlobalExceptionHandler; import com.schbrain.common.web.properties.WebProperties; +import com.schbrain.common.web.result.ResponseDTO; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -23,13 +24,13 @@ public class ExceptionHandingConfiguration { @Bean @ConditionalOnMissingBean - public ExceptionTranslator defaultExceptionTranslator() { + public ExceptionTranslator> defaultExceptionTranslator() { return new DefaultExceptionTranslator(); } @Bean @ConditionalOnMissingBean - public GlobalExceptionHandler defaultGlobalExceptionHandler(ObjectProvider exceptionTranslators) { + public GlobalExceptionHandler defaultGlobalExceptionHandler(ObjectProvider> exceptionTranslators) { return new GlobalExceptionHandler(exceptionTranslators.orderedStream().collect(Collectors.toList())); } @@ -39,4 +40,4 @@ public class ExceptionHandingConfiguration { return new ExceptionHandingWebMvcConfigurer(webProperties, exceptionHandler); } -} \ No newline at end of file +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/WebCommonAutoConfiguration.java b/commons/web-common/src/main/java/com/schbrain/common/web/WebCommonAutoConfiguration.java index 1c768bd9484ffc6faa4c630997134ab362348f6a..74d0d8a940ef1b491a50380876a00af377eeded7 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/WebCommonAutoConfiguration.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/WebCommonAutoConfiguration.java @@ -3,6 +3,7 @@ package com.schbrain.common.web; import com.schbrain.common.web.argument.BodyParamArgumentResolverWebMvcConfigurer; import com.schbrain.common.web.properties.WebProperties; import com.schbrain.common.web.result.ResponseBodyHandler; +import com.schbrain.common.web.support.converter.Jsr310DateTimeWebMvcConfigurer; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigurationPackages; @@ -40,6 +41,12 @@ public class WebCommonAutoConfiguration { return new BodyParamArgumentResolverWebMvcConfigurer(); } + @Bean + @ConditionalOnMissingBean + public Jsr310DateTimeWebMvcConfigurer defaultJsr310DateTimeWebMvcConfigurer() { + return new Jsr310DateTimeWebMvcConfigurer(); + } + @Bean @Lazy @ConditionalOnMissingBean diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultExceptionTranslator.java b/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultExceptionTranslator.java index da0a6c5aa334602c0df0bf29d60aefcc1ddcc8d4..932b7a683877ed3f3685d0ba33a443f44449a85e 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultExceptionTranslator.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultExceptionTranslator.java @@ -10,7 +10,7 @@ import org.springframework.core.Ordered; * @author liaozan * @since 2023-06-01 */ -public class DefaultExceptionTranslator implements ExceptionTranslator { +public class DefaultExceptionTranslator implements ExceptionTranslator> { private final boolean isProduction; @@ -34,4 +34,4 @@ public class DefaultExceptionTranslator implements ExceptionTranslator { return Ordered.LOWEST_PRECEDENCE; } -} \ No newline at end of file +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultGlobalExceptionResolver.java b/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultGlobalExceptionResolver.java index a96b59202b0d61f1c9c177677e54065767f424b0..6df4b81544ff094c8463913ec7f5658b142e569e 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultGlobalExceptionResolver.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultGlobalExceptionResolver.java @@ -32,8 +32,6 @@ import java.util.concurrent.ConcurrentHashMap; @EqualsAndHashCode(callSuper = true) public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExceptionResolver { - private final boolean wrapResponse; - private final GlobalExceptionHandler exceptionHandler; private final ExceptionHandlerMethodResolver handlerMethodResolver; @@ -44,8 +42,7 @@ public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExcepti private final Map, ExceptionHandlerMethodResolver> exceptionHandlerMethodResolvers = new ConcurrentHashMap<>(64); - public DefaultGlobalExceptionResolver(ExceptionHandlerExceptionResolver handlerMethodResolver, boolean wrapResponse, GlobalExceptionHandler exceptionHandler) { - this.wrapResponse = wrapResponse; + public DefaultGlobalExceptionResolver(ExceptionHandlerExceptionResolver handlerMethodResolver, GlobalExceptionHandler exceptionHandler) { this.exceptionHandler = exceptionHandler; this.handlerMethodResolver = new ExceptionHandlerMethodResolver(exceptionHandler.getClass()); this.argumentResolverComposite = handlerMethodResolver.getArgumentResolvers(); @@ -55,10 +52,6 @@ public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExcepti @Override protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) { - if (!wrapResponse) { - return false; - } - if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; ResponseWrapOption responseWrapOption = HandlerMethodAnnotationUtils.getAnnotation(handlerMethod, ResponseWrapOption.class); @@ -147,4 +140,4 @@ public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExcepti return arguments; } -} \ No newline at end of file +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionHandingWebMvcConfigurer.java b/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionHandingWebMvcConfigurer.java index da716b2ec2949e6f613c9b9e57a91f08a4515fcb..dac27432fa00bd6312e95ba9376bf9d0571da6fa 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionHandingWebMvcConfigurer.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionHandingWebMvcConfigurer.java @@ -49,7 +49,7 @@ public class ExceptionHandingWebMvcConfigurer implements WebMvcConfigurer { } protected HandlerExceptionResolver createExceptionResolver(ExceptionHandlerExceptionResolver adviceExceptionResolver) { - return new DefaultGlobalExceptionResolver(adviceExceptionResolver, webProperties.isWrapResponse(), globalExceptionHandler); + return new DefaultGlobalExceptionResolver(adviceExceptionResolver, globalExceptionHandler); } -} \ No newline at end of file +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionTranslator.java b/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionTranslator.java index 68eab6e1bc4235819473ffc6b6a1283abd91de17..3af7c2742d8d607e9da3340b87f7fa7f03debd2c 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionTranslator.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionTranslator.java @@ -8,16 +8,16 @@ import org.springframework.core.Ordered; * @since 2023-06-01 */ @FunctionalInterface -public interface ExceptionTranslator extends Ordered { +public interface ExceptionTranslator extends Ordered { /** * Translate the exception to {@link ResponseDTO} */ - ResponseDTO translate(Throwable throwable, int code, int action, String message); + T translate(Throwable throwable, int code, int action, String message); @Override default int getOrder() { return Ordered.LOWEST_PRECEDENCE - 100; } -} \ No newline at end of file +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/exception/GlobalExceptionHandler.java b/commons/web-common/src/main/java/com/schbrain/common/web/exception/GlobalExceptionHandler.java index 9f3af3b1e12ec7c3ebd9916802c1b9620a0cb315..5de368ffa58d72f8d793c23660f9b46f6048ddf9 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/exception/GlobalExceptionHandler.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/exception/GlobalExceptionHandler.java @@ -42,78 +42,78 @@ import static com.schbrain.common.util.support.ValidationMessageBuilder.buildCon @ResponseStatus(HttpStatus.OK) public class GlobalExceptionHandler { - private final List exceptionTranslators; + private final List> exceptionTranslators; - public GlobalExceptionHandler(List exceptionTranslators) { + public GlobalExceptionHandler(List> exceptionTranslators) { this.exceptionTranslators = exceptionTranslators; } /************************************* Base Exception Handing *************************************/ @ExceptionHandler(BaseException.class) - public ResponseDTO handleBaseException(BaseException ex) { + public Object handleBaseException(BaseException ex) { logError(ex); return buildResponse(ex, ex.getCode(), ex.getAction(), ex.getMessage()); } /************************************* Common Exception Handing *************************************/ @ExceptionHandler(Throwable.class) - public ResponseDTO handleAll(Throwable ex) { + public Object handleAll(Throwable ex) { return loggingThenBuildResponse(ex, SERVER_ERROR); } @ExceptionHandler(NullPointerException.class) - public ResponseDTO handleNullPointerException(NullPointerException ex) { + public Object handleNullPointerException(NullPointerException ex) { return loggingThenBuildResponse(ex, SERVER_ERROR); } @ExceptionHandler(IllegalArgumentException.class) - public ResponseDTO handleIllegalArgumentException(IllegalArgumentException ex) { + public Object handleIllegalArgumentException(IllegalArgumentException ex) { return loggingThenBuildResponse(ex, SERVER_ERROR); } @ExceptionHandler(IllegalStateException.class) - public ResponseDTO handleIllegalStateException(IllegalStateException ex) { + public Object handleIllegalStateException(IllegalStateException ex) { return loggingThenBuildResponse(ex, SERVER_ERROR); } @ExceptionHandler(NoHandlerFoundException.class) - public ResponseDTO handleNoHandlerFoundException(NoHandlerFoundException ex) { + public Object handleNoHandlerFoundException(NoHandlerFoundException ex) { return loggingThenBuildResponse(ex, PARAM_INVALID); } @ExceptionHandler(AsyncRequestTimeoutException.class) - public ResponseDTO handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex) { + public Object handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex) { return loggingThenBuildResponse(ex, SERVER_ERROR); } /************************************* SQL Exception Handing *************************************/ @ExceptionHandler(SQLException.class) - public ResponseDTO handleSQLException(SQLException ex) { + public Object handleSQLException(SQLException ex) { return loggingThenBuildResponse(ex, SERVER_ERROR); } @ExceptionHandler(DataAccessException.class) - public ResponseDTO handleDataAccessException(DataAccessException ex) { + public Object handleDataAccessException(DataAccessException ex) { return loggingThenBuildResponse(ex, SERVER_ERROR); } /************************************* Http Request Exception Handing *************************************/ @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public ResponseDTO handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) { + public Object handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) { String errorMsg = StrUtil.format("不支持该HTTP方法: {}, 请使用 {}", ex.getMethod(), Arrays.toString(ex.getSupportedMethods())); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(HttpMediaTypeNotSupportedException.class) - public ResponseDTO handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException ex) { + public Object handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException ex) { String errorMsg = StrUtil.format("不支持该媒体类型: {}, 请使用 {}", ex.getContentType(), ex.getSupportedMediaTypes()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(HttpMediaTypeNotAcceptableException.class) - public ResponseDTO handleHttpMediaTypeNotAcceptableException(HttpMediaTypeNotAcceptableException ex) { + public Object handleHttpMediaTypeNotAcceptableException(HttpMediaTypeNotAcceptableException ex) { String errorMsg = StrUtil.format("不支持的媒体类型, 请使用 {}", ex.getSupportedMediaTypes()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); @@ -121,14 +121,14 @@ public class GlobalExceptionHandler { /************************************* Method Parameter Exception Handing *************************************/ @ExceptionHandler(HttpMessageNotReadableException.class) - public ResponseDTO handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) { + public Object handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) { String errorMsg = StrUtil.format("参数解析失败, {}", ex.getMessage()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(MethodArgumentTypeMismatchException.class) - public ResponseDTO handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex) { + public Object handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex) { Object value = ex.getValue(); String variableName = ex.getName(); Class requiredTypeClass = ex.getRequiredType(); @@ -140,42 +140,42 @@ public class GlobalExceptionHandler { } @ExceptionHandler(MissingPathVariableException.class) - public ResponseDTO handleMissingPathVariableException(MissingPathVariableException ex) { + public Object handleMissingPathVariableException(MissingPathVariableException ex) { String errorMsg = StrUtil.format("丢失路径参数, 参数名: {}, 参数类型: {}", ex.getVariableName(), ex.getParameter().getParameterType()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(MissingRequestCookieException.class) - public ResponseDTO handleMissingRequestCookieException(MissingRequestCookieException ex) { + public Object handleMissingRequestCookieException(MissingRequestCookieException ex) { String errorMsg = StrUtil.format("丢失Cookie参数, 参数名: {}, 参数类型: {}", ex.getCookieName(), ex.getParameter().getParameterType()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(MissingRequestHeaderException.class) - public ResponseDTO handleMissingRequestHeaderException(MissingRequestHeaderException ex) { + public Object handleMissingRequestHeaderException(MissingRequestHeaderException ex) { String errorMsg = StrUtil.format("丢失Header参数, 参数名: {}, 参数类型: {}", ex.getHeaderName(), ex.getParameter().getParameterType()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(MissingServletRequestPartException.class) - public ResponseDTO handleMissingServletRequestPartException(MissingServletRequestPartException ex) { + public Object handleMissingServletRequestPartException(MissingServletRequestPartException ex) { String errorMsg = StrUtil.format("丢失参数: {}", ex.getRequestPartName()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(MissingServletRequestParameterException.class) - public ResponseDTO handleServletRequestParameterException(MissingServletRequestParameterException ex) { + public Object handleServletRequestParameterException(MissingServletRequestParameterException ex) { String errorMsg = StrUtil.format("丢失Query参数, 参数名: {}, 参数类型: {}", ex.getParameterName(), ex.getParameterType()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(ServletRequestBindingException.class) - public ResponseDTO handleServletRequestBindingException(ServletRequestBindingException ex) { + public Object handleServletRequestBindingException(ServletRequestBindingException ex) { String errorMsg = StrUtil.format("参数绑定失败: {}", ex.getMessage()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); @@ -183,42 +183,43 @@ public class GlobalExceptionHandler { /************************************* Parameter Binding Exception Handing *************************************/ @ExceptionHandler(BindException.class) - public ResponseDTO handleBindException(BindException ex) { + public Object handleBindException(BindException ex) { String errorMsg = buildBindingErrorMsg(ex.getBindingResult()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } @ExceptionHandler(ConstraintViolationException.class) - public ResponseDTO handleConstraintViolationException(ConstraintViolationException ex) { + public Object handleConstraintViolationException(ConstraintViolationException ex) { String errorMsg = buildConstraintViolationErrorMsg(ex.getConstraintViolations()); log.error(errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg); } - private ResponseDTO loggingThenBuildResponse(Throwable throwable, int code) { + private Object loggingThenBuildResponse(Throwable throwable, int code) { Throwable rootCause = ExceptionUtil.getRootCause(throwable); logError(rootCause); return buildResponse(rootCause, code, rootCause.getMessage()); } - private ResponseDTO buildResponse(Throwable throwable, int code, String message) { + private Object buildResponse(Throwable throwable, int code, String message) { return buildResponse(throwable, code, ResponseActionConstants.ALERT, message); } - private ResponseDTO buildResponse(Throwable throwable, int code, int action, String message) { - ResponseDTO responseDTO = translateException(throwable, code, action, message); - if (responseDTO != null) { - return responseDTO; + private Object buildResponse(Throwable throwable, int code, int action, String message) { + Object translated = translateException(throwable, code, action, message); + if (translated != null) { + return translated; } + // fallback return ResponseDTO.error(message, code, action); } - private ResponseDTO translateException(Throwable throwable, int code, int action, String message) { - for (ExceptionTranslator exceptionTranslator : exceptionTranslators) { - ResponseDTO responseDTO = exceptionTranslator.translate(throwable, code, action, message); - if (responseDTO != null) { - return responseDTO; + private Object translateException(Throwable throwable, int code, int action, String message) { + for (ExceptionTranslator exceptionTranslator : exceptionTranslators) { + Object translated = exceptionTranslator.translate(throwable, code, action, message); + if (translated != null) { + return translated; } } return null; diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/support/converter/Jsr310Converters.java b/commons/web-common/src/main/java/com/schbrain/common/web/support/converter/Jsr310Converters.java new file mode 100644 index 0000000000000000000000000000000000000000..1b88cfd1db4fb8a26eab92eeaae96bbf25a46a4a --- /dev/null +++ b/commons/web-common/src/main/java/com/schbrain/common/web/support/converter/Jsr310Converters.java @@ -0,0 +1,95 @@ +package com.schbrain.common.web.support.converter; + +import org.springframework.core.convert.converter.Converter; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; + +import static java.time.LocalDateTime.ofInstant; +import static java.time.ZoneId.systemDefault; + +/** + * @author liaozan + * @since 2023/8/16 + */ +public class Jsr310Converters { + + public static List> getConverters() { + List> converters = new ArrayList<>(); + + converters.add(LongToLocalDateConverter.INSTANCE); + converters.add(LongToLocalTimeConverter.INSTANCE); + converters.add(LongToLocalDateTimeConverter.INSTANCE); + + converters.add(StringToLocalDateConverter.INSTANCE); + converters.add(StringToLocalTimeConverter.INSTANCE); + converters.add(StringToLocalDateTimeConverter.INSTANCE); + + return converters; + } + + public enum LongToLocalDateConverter implements Converter { + + INSTANCE; + + @Override + public LocalDate convert(Long source) { + return LongToLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate(); + } + } + + public enum LongToLocalTimeConverter implements Converter { + + INSTANCE; + + @Override + public LocalTime convert(Long source) { + return LongToLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime(); + } + } + + public enum LongToLocalDateTimeConverter implements Converter { + + INSTANCE; + + @Override + public LocalDateTime convert(Long source) { + return ofInstant(Instant.ofEpochMilli(source), systemDefault()); + } + } + + public enum StringToLocalDateConverter implements Converter { + + INSTANCE; + + @Override + public LocalDate convert(String source) { + return StringToLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate(); + } + } + + public enum StringToLocalTimeConverter implements Converter { + + INSTANCE; + + @Override + public LocalTime convert(String source) { + return StringToLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime(); + } + } + + public enum StringToLocalDateTimeConverter implements Converter { + + INSTANCE; + + @Override + public LocalDateTime convert(String source) { + return ofInstant(Instant.ofEpochMilli(Long.parseLong(source)), systemDefault()); + } + } + +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/support/converter/Jsr310DateTimeWebMvcConfigurer.java b/commons/web-common/src/main/java/com/schbrain/common/web/support/converter/Jsr310DateTimeWebMvcConfigurer.java new file mode 100644 index 0000000000000000000000000000000000000000..4033ae8a52b8584184cba4c0d88fbb2e98426ae4 --- /dev/null +++ b/commons/web-common/src/main/java/com/schbrain/common/web/support/converter/Jsr310DateTimeWebMvcConfigurer.java @@ -0,0 +1,17 @@ +package com.schbrain.common.web.support.converter; + +import org.springframework.format.FormatterRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @author liaozan + * @since 2023/8/16 + */ +public class Jsr310DateTimeWebMvcConfigurer implements WebMvcConfigurer { + + @Override + public void addFormatters(FormatterRegistry registry) { + Jsr310Converters.getConverters().forEach(registry::addConverter); + } + +}