From c98d8823ea1e534096fcf2d7e726cff04d031bcf Mon Sep 17 00:00:00 2001 From: liaozan <378024053@qq.com> Date: Thu, 17 Aug 2023 19:23:03 +0800 Subject: [PATCH] Polish ExceptionTranslator --- .../schbrain/common/util/ApplicationName.java | 5 +- .../com/schbrain/common/util/TreeUtils.java | 19 ++++ .../web/ExceptionHandingConfiguration.java | 7 +- .../web/WebCommonAutoConfiguration.java | 7 ++ .../exception/DefaultExceptionTranslator.java | 4 +- .../DefaultGlobalExceptionResolver.java | 11 +-- .../ExceptionHandingWebMvcConfigurer.java | 4 +- .../web/exception/ExceptionTranslator.java | 6 +- .../web/exception/GlobalExceptionHandler.java | 71 +++++++------- .../support/converter/Jsr310Converters.java | 95 +++++++++++++++++++ .../Jsr310DateTimeWebMvcConfigurer.java | 17 ++++ 11 files changed, 189 insertions(+), 57 deletions(-) create mode 100644 commons/web-common/src/main/java/com/schbrain/common/web/support/converter/Jsr310Converters.java create mode 100644 commons/web-common/src/main/java/com/schbrain/common/web/support/converter/Jsr310DateTimeWebMvcConfigurer.java 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 4c98211..f3a9c56 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 358b626..751540c 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 88f6238..15f2004 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 1c768bd..74d0d8a 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 da0a6c5..932b7a6 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 a96b592..6df4b81 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 da716b2..dac2743 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 68eab6e..3af7c27 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 9f3af3b..5de368f 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 0000000..1b88cfd --- /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 0000000..4033ae8 --- /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); + } + +} -- GitLab