Commit c98d8823 authored by liaozan's avatar liaozan 🏀

Polish ExceptionTranslator

parent b7bab0b7
package com.schbrain.common.util; package com.schbrain.common.util;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import com.schbrain.common.exception.BaseException;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable; import org.springframework.core.env.EnvironmentCapable;
...@@ -17,7 +16,7 @@ public class ApplicationName { ...@@ -17,7 +16,7 @@ public class ApplicationName {
return Optional.ofNullable(SpringUtil.getApplicationContext()) return Optional.ofNullable(SpringUtil.getApplicationContext())
.map(EnvironmentCapable::getEnvironment) .map(EnvironmentCapable::getEnvironment)
.map(ApplicationName::get) .map(ApplicationName::get)
.orElseThrow(() -> new BaseException("Could not get application name")); .orElseThrow();
} }
public static String get(Environment environment) { public static String get(Environment environment) {
......
...@@ -55,6 +55,25 @@ public class TreeUtils { ...@@ -55,6 +55,25 @@ public class TreeUtils {
return doBuildTree(keyExtractor, childrenSetter, childMapper, parentWithSubNodes, childrenComparator, parentId); return doBuildTree(keyExtractor, childrenSetter, childMapper, parentWithSubNodes, childrenComparator, parentId);
} }
public static <T, E> List<E> buildNodeList(List<T> treeList,
Function<T, List<T>> childrenGetter,
Function<T, E> mapper) {
List<E> nodes = new ArrayList<>();
doBuildNodeList(treeList, childrenGetter, mapper, nodes);
return nodes;
}
private static <E, T> void doBuildNodeList(List<T> treeList,
Function<T, List<T>> childrenGetter,
Function<T, E> mapper,
List<E> nodes) {
if (CollectionUtils.isEmpty(treeList)) {
return;
}
nodes.addAll(StreamUtils.toList(treeList, mapper));
treeList.forEach(tree -> doBuildNodeList(childrenGetter.apply(tree), childrenGetter, mapper, nodes));
}
private static <E, K, T> List<E> doBuildTree(Function<T, K> keyExtractor, private static <E, K, T> List<E> doBuildTree(Function<T, K> keyExtractor,
BiConsumer<E, List<E>> childrenSetter, BiConsumer<E, List<E>> childrenSetter,
Function<T, E> childMapper, Function<T, E> childMapper,
......
...@@ -5,6 +5,7 @@ import com.schbrain.common.web.exception.ExceptionHandingWebMvcConfigurer; ...@@ -5,6 +5,7 @@ import com.schbrain.common.web.exception.ExceptionHandingWebMvcConfigurer;
import com.schbrain.common.web.exception.ExceptionTranslator; import com.schbrain.common.web.exception.ExceptionTranslator;
import com.schbrain.common.web.exception.GlobalExceptionHandler; import com.schbrain.common.web.exception.GlobalExceptionHandler;
import com.schbrain.common.web.properties.WebProperties; import com.schbrain.common.web.properties.WebProperties;
import com.schbrain.common.web.result.ResponseDTO;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
...@@ -23,13 +24,13 @@ public class ExceptionHandingConfiguration { ...@@ -23,13 +24,13 @@ public class ExceptionHandingConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ExceptionTranslator defaultExceptionTranslator() { public ExceptionTranslator<ResponseDTO<String>> defaultExceptionTranslator() {
return new DefaultExceptionTranslator(); return new DefaultExceptionTranslator();
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public GlobalExceptionHandler defaultGlobalExceptionHandler(ObjectProvider<ExceptionTranslator> exceptionTranslators) { public GlobalExceptionHandler defaultGlobalExceptionHandler(ObjectProvider<ExceptionTranslator<?>> exceptionTranslators) {
return new GlobalExceptionHandler(exceptionTranslators.orderedStream().collect(Collectors.toList())); return new GlobalExceptionHandler(exceptionTranslators.orderedStream().collect(Collectors.toList()));
} }
......
...@@ -3,6 +3,7 @@ package com.schbrain.common.web; ...@@ -3,6 +3,7 @@ package com.schbrain.common.web;
import com.schbrain.common.web.argument.BodyParamArgumentResolverWebMvcConfigurer; import com.schbrain.common.web.argument.BodyParamArgumentResolverWebMvcConfigurer;
import com.schbrain.common.web.properties.WebProperties; import com.schbrain.common.web.properties.WebProperties;
import com.schbrain.common.web.result.ResponseBodyHandler; 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.BeanFactory;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages; import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
...@@ -40,6 +41,12 @@ public class WebCommonAutoConfiguration { ...@@ -40,6 +41,12 @@ public class WebCommonAutoConfiguration {
return new BodyParamArgumentResolverWebMvcConfigurer(); return new BodyParamArgumentResolverWebMvcConfigurer();
} }
@Bean
@ConditionalOnMissingBean
public Jsr310DateTimeWebMvcConfigurer defaultJsr310DateTimeWebMvcConfigurer() {
return new Jsr310DateTimeWebMvcConfigurer();
}
@Bean @Bean
@Lazy @Lazy
@ConditionalOnMissingBean @ConditionalOnMissingBean
......
...@@ -10,7 +10,7 @@ import org.springframework.core.Ordered; ...@@ -10,7 +10,7 @@ import org.springframework.core.Ordered;
* @author liaozan * @author liaozan
* @since 2023-06-01 * @since 2023-06-01
*/ */
public class DefaultExceptionTranslator implements ExceptionTranslator { public class DefaultExceptionTranslator implements ExceptionTranslator<ResponseDTO<String>> {
private final boolean isProduction; private final boolean isProduction;
......
...@@ -32,8 +32,6 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -32,8 +32,6 @@ import java.util.concurrent.ConcurrentHashMap;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExceptionResolver { public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExceptionResolver {
private final boolean wrapResponse;
private final GlobalExceptionHandler exceptionHandler; private final GlobalExceptionHandler exceptionHandler;
private final ExceptionHandlerMethodResolver handlerMethodResolver; private final ExceptionHandlerMethodResolver handlerMethodResolver;
...@@ -44,8 +42,7 @@ public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExcepti ...@@ -44,8 +42,7 @@ public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExcepti
private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerMethodResolvers = new ConcurrentHashMap<>(64); private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerMethodResolvers = new ConcurrentHashMap<>(64);
public DefaultGlobalExceptionResolver(ExceptionHandlerExceptionResolver handlerMethodResolver, boolean wrapResponse, GlobalExceptionHandler exceptionHandler) { public DefaultGlobalExceptionResolver(ExceptionHandlerExceptionResolver handlerMethodResolver, GlobalExceptionHandler exceptionHandler) {
this.wrapResponse = wrapResponse;
this.exceptionHandler = exceptionHandler; this.exceptionHandler = exceptionHandler;
this.handlerMethodResolver = new ExceptionHandlerMethodResolver(exceptionHandler.getClass()); this.handlerMethodResolver = new ExceptionHandlerMethodResolver(exceptionHandler.getClass());
this.argumentResolverComposite = handlerMethodResolver.getArgumentResolvers(); this.argumentResolverComposite = handlerMethodResolver.getArgumentResolvers();
...@@ -55,10 +52,6 @@ public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExcepti ...@@ -55,10 +52,6 @@ public class DefaultGlobalExceptionResolver extends AbstractHandlerMethodExcepti
@Override @Override
protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) { protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) {
if (!wrapResponse) {
return false;
}
if (handler instanceof HandlerMethod) { if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler; HandlerMethod handlerMethod = (HandlerMethod) handler;
ResponseWrapOption responseWrapOption = HandlerMethodAnnotationUtils.getAnnotation(handlerMethod, ResponseWrapOption.class); ResponseWrapOption responseWrapOption = HandlerMethodAnnotationUtils.getAnnotation(handlerMethod, ResponseWrapOption.class);
......
...@@ -49,7 +49,7 @@ public class ExceptionHandingWebMvcConfigurer implements WebMvcConfigurer { ...@@ -49,7 +49,7 @@ public class ExceptionHandingWebMvcConfigurer implements WebMvcConfigurer {
} }
protected HandlerExceptionResolver createExceptionResolver(ExceptionHandlerExceptionResolver adviceExceptionResolver) { protected HandlerExceptionResolver createExceptionResolver(ExceptionHandlerExceptionResolver adviceExceptionResolver) {
return new DefaultGlobalExceptionResolver(adviceExceptionResolver, webProperties.isWrapResponse(), globalExceptionHandler); return new DefaultGlobalExceptionResolver(adviceExceptionResolver, globalExceptionHandler);
} }
} }
...@@ -8,12 +8,12 @@ import org.springframework.core.Ordered; ...@@ -8,12 +8,12 @@ import org.springframework.core.Ordered;
* @since 2023-06-01 * @since 2023-06-01
*/ */
@FunctionalInterface @FunctionalInterface
public interface ExceptionTranslator extends Ordered { public interface ExceptionTranslator<T> extends Ordered {
/** /**
* Translate the exception to {@link ResponseDTO} * Translate the exception to {@link ResponseDTO}
*/ */
ResponseDTO<String> translate(Throwable throwable, int code, int action, String message); T translate(Throwable throwable, int code, int action, String message);
@Override @Override
default int getOrder() { default int getOrder() {
......
...@@ -42,78 +42,78 @@ import static com.schbrain.common.util.support.ValidationMessageBuilder.buildCon ...@@ -42,78 +42,78 @@ import static com.schbrain.common.util.support.ValidationMessageBuilder.buildCon
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
private final List<ExceptionTranslator> exceptionTranslators; private final List<ExceptionTranslator<?>> exceptionTranslators;
public GlobalExceptionHandler(List<ExceptionTranslator> exceptionTranslators) { public GlobalExceptionHandler(List<ExceptionTranslator<?>> exceptionTranslators) {
this.exceptionTranslators = exceptionTranslators; this.exceptionTranslators = exceptionTranslators;
} }
/************************************* Base Exception Handing *************************************/ /************************************* Base Exception Handing *************************************/
@ExceptionHandler(BaseException.class) @ExceptionHandler(BaseException.class)
public ResponseDTO<String> handleBaseException(BaseException ex) { public Object handleBaseException(BaseException ex) {
logError(ex); logError(ex);
return buildResponse(ex, ex.getCode(), ex.getAction(), ex.getMessage()); return buildResponse(ex, ex.getCode(), ex.getAction(), ex.getMessage());
} }
/************************************* Common Exception Handing *************************************/ /************************************* Common Exception Handing *************************************/
@ExceptionHandler(Throwable.class) @ExceptionHandler(Throwable.class)
public ResponseDTO<String> handleAll(Throwable ex) { public Object handleAll(Throwable ex) {
return loggingThenBuildResponse(ex, SERVER_ERROR); return loggingThenBuildResponse(ex, SERVER_ERROR);
} }
@ExceptionHandler(NullPointerException.class) @ExceptionHandler(NullPointerException.class)
public ResponseDTO<String> handleNullPointerException(NullPointerException ex) { public Object handleNullPointerException(NullPointerException ex) {
return loggingThenBuildResponse(ex, SERVER_ERROR); return loggingThenBuildResponse(ex, SERVER_ERROR);
} }
@ExceptionHandler(IllegalArgumentException.class) @ExceptionHandler(IllegalArgumentException.class)
public ResponseDTO<String> handleIllegalArgumentException(IllegalArgumentException ex) { public Object handleIllegalArgumentException(IllegalArgumentException ex) {
return loggingThenBuildResponse(ex, SERVER_ERROR); return loggingThenBuildResponse(ex, SERVER_ERROR);
} }
@ExceptionHandler(IllegalStateException.class) @ExceptionHandler(IllegalStateException.class)
public ResponseDTO<String> handleIllegalStateException(IllegalStateException ex) { public Object handleIllegalStateException(IllegalStateException ex) {
return loggingThenBuildResponse(ex, SERVER_ERROR); return loggingThenBuildResponse(ex, SERVER_ERROR);
} }
@ExceptionHandler(NoHandlerFoundException.class) @ExceptionHandler(NoHandlerFoundException.class)
public ResponseDTO<String> handleNoHandlerFoundException(NoHandlerFoundException ex) { public Object handleNoHandlerFoundException(NoHandlerFoundException ex) {
return loggingThenBuildResponse(ex, PARAM_INVALID); return loggingThenBuildResponse(ex, PARAM_INVALID);
} }
@ExceptionHandler(AsyncRequestTimeoutException.class) @ExceptionHandler(AsyncRequestTimeoutException.class)
public ResponseDTO<String> handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex) { public Object handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex) {
return loggingThenBuildResponse(ex, SERVER_ERROR); return loggingThenBuildResponse(ex, SERVER_ERROR);
} }
/************************************* SQL Exception Handing *************************************/ /************************************* SQL Exception Handing *************************************/
@ExceptionHandler(SQLException.class) @ExceptionHandler(SQLException.class)
public ResponseDTO<String> handleSQLException(SQLException ex) { public Object handleSQLException(SQLException ex) {
return loggingThenBuildResponse(ex, SERVER_ERROR); return loggingThenBuildResponse(ex, SERVER_ERROR);
} }
@ExceptionHandler(DataAccessException.class) @ExceptionHandler(DataAccessException.class)
public ResponseDTO<String> handleDataAccessException(DataAccessException ex) { public Object handleDataAccessException(DataAccessException ex) {
return loggingThenBuildResponse(ex, SERVER_ERROR); return loggingThenBuildResponse(ex, SERVER_ERROR);
} }
/************************************* Http Request Exception Handing *************************************/ /************************************* Http Request Exception Handing *************************************/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class) @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ResponseDTO<String> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) { public Object handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) {
String errorMsg = StrUtil.format("不支持该HTTP方法: {}, 请使用 {}", ex.getMethod(), Arrays.toString(ex.getSupportedMethods())); String errorMsg = StrUtil.format("不支持该HTTP方法: {}, 请使用 {}", ex.getMethod(), Arrays.toString(ex.getSupportedMethods()));
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(HttpMediaTypeNotSupportedException.class) @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
public ResponseDTO<String> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException ex) { public Object handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException ex) {
String errorMsg = StrUtil.format("不支持该媒体类型: {}, 请使用 {}", ex.getContentType(), ex.getSupportedMediaTypes()); String errorMsg = StrUtil.format("不支持该媒体类型: {}, 请使用 {}", ex.getContentType(), ex.getSupportedMediaTypes());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class) @ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
public ResponseDTO<String> handleHttpMediaTypeNotAcceptableException(HttpMediaTypeNotAcceptableException ex) { public Object handleHttpMediaTypeNotAcceptableException(HttpMediaTypeNotAcceptableException ex) {
String errorMsg = StrUtil.format("不支持的媒体类型, 请使用 {}", ex.getSupportedMediaTypes()); String errorMsg = StrUtil.format("不支持的媒体类型, 请使用 {}", ex.getSupportedMediaTypes());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
...@@ -121,14 +121,14 @@ public class GlobalExceptionHandler { ...@@ -121,14 +121,14 @@ public class GlobalExceptionHandler {
/************************************* Method Parameter Exception Handing *************************************/ /************************************* Method Parameter Exception Handing *************************************/
@ExceptionHandler(HttpMessageNotReadableException.class) @ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseDTO<String> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) { public Object handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
String errorMsg = StrUtil.format("参数解析失败, {}", ex.getMessage()); String errorMsg = StrUtil.format("参数解析失败, {}", ex.getMessage());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(MethodArgumentTypeMismatchException.class) @ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseDTO<String> handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex) { public Object handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex) {
Object value = ex.getValue(); Object value = ex.getValue();
String variableName = ex.getName(); String variableName = ex.getName();
Class<?> requiredTypeClass = ex.getRequiredType(); Class<?> requiredTypeClass = ex.getRequiredType();
...@@ -140,42 +140,42 @@ public class GlobalExceptionHandler { ...@@ -140,42 +140,42 @@ public class GlobalExceptionHandler {
} }
@ExceptionHandler(MissingPathVariableException.class) @ExceptionHandler(MissingPathVariableException.class)
public ResponseDTO<String> handleMissingPathVariableException(MissingPathVariableException ex) { public Object handleMissingPathVariableException(MissingPathVariableException ex) {
String errorMsg = StrUtil.format("丢失路径参数, 参数名: {}, 参数类型: {}", ex.getVariableName(), ex.getParameter().getParameterType()); String errorMsg = StrUtil.format("丢失路径参数, 参数名: {}, 参数类型: {}", ex.getVariableName(), ex.getParameter().getParameterType());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(MissingRequestCookieException.class) @ExceptionHandler(MissingRequestCookieException.class)
public ResponseDTO<String> handleMissingRequestCookieException(MissingRequestCookieException ex) { public Object handleMissingRequestCookieException(MissingRequestCookieException ex) {
String errorMsg = StrUtil.format("丢失Cookie参数, 参数名: {}, 参数类型: {}", ex.getCookieName(), ex.getParameter().getParameterType()); String errorMsg = StrUtil.format("丢失Cookie参数, 参数名: {}, 参数类型: {}", ex.getCookieName(), ex.getParameter().getParameterType());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(MissingRequestHeaderException.class) @ExceptionHandler(MissingRequestHeaderException.class)
public ResponseDTO<String> handleMissingRequestHeaderException(MissingRequestHeaderException ex) { public Object handleMissingRequestHeaderException(MissingRequestHeaderException ex) {
String errorMsg = StrUtil.format("丢失Header参数, 参数名: {}, 参数类型: {}", ex.getHeaderName(), ex.getParameter().getParameterType()); String errorMsg = StrUtil.format("丢失Header参数, 参数名: {}, 参数类型: {}", ex.getHeaderName(), ex.getParameter().getParameterType());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(MissingServletRequestPartException.class) @ExceptionHandler(MissingServletRequestPartException.class)
public ResponseDTO<String> handleMissingServletRequestPartException(MissingServletRequestPartException ex) { public Object handleMissingServletRequestPartException(MissingServletRequestPartException ex) {
String errorMsg = StrUtil.format("丢失参数: {}", ex.getRequestPartName()); String errorMsg = StrUtil.format("丢失参数: {}", ex.getRequestPartName());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(MissingServletRequestParameterException.class) @ExceptionHandler(MissingServletRequestParameterException.class)
public ResponseDTO<String> handleServletRequestParameterException(MissingServletRequestParameterException ex) { public Object handleServletRequestParameterException(MissingServletRequestParameterException ex) {
String errorMsg = StrUtil.format("丢失Query参数, 参数名: {}, 参数类型: {}", ex.getParameterName(), ex.getParameterType()); String errorMsg = StrUtil.format("丢失Query参数, 参数名: {}, 参数类型: {}", ex.getParameterName(), ex.getParameterType());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(ServletRequestBindingException.class) @ExceptionHandler(ServletRequestBindingException.class)
public ResponseDTO<String> handleServletRequestBindingException(ServletRequestBindingException ex) { public Object handleServletRequestBindingException(ServletRequestBindingException ex) {
String errorMsg = StrUtil.format("参数绑定失败: {}", ex.getMessage()); String errorMsg = StrUtil.format("参数绑定失败: {}", ex.getMessage());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
...@@ -183,42 +183,43 @@ public class GlobalExceptionHandler { ...@@ -183,42 +183,43 @@ public class GlobalExceptionHandler {
/************************************* Parameter Binding Exception Handing *************************************/ /************************************* Parameter Binding Exception Handing *************************************/
@ExceptionHandler(BindException.class) @ExceptionHandler(BindException.class)
public ResponseDTO<String> handleBindException(BindException ex) { public Object handleBindException(BindException ex) {
String errorMsg = buildBindingErrorMsg(ex.getBindingResult()); String errorMsg = buildBindingErrorMsg(ex.getBindingResult());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
@ExceptionHandler(ConstraintViolationException.class) @ExceptionHandler(ConstraintViolationException.class)
public ResponseDTO<String> handleConstraintViolationException(ConstraintViolationException ex) { public Object handleConstraintViolationException(ConstraintViolationException ex) {
String errorMsg = buildConstraintViolationErrorMsg(ex.getConstraintViolations()); String errorMsg = buildConstraintViolationErrorMsg(ex.getConstraintViolations());
log.error(errorMsg); log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg); return buildResponse(ex, PARAM_INVALID, errorMsg);
} }
private ResponseDTO<String> loggingThenBuildResponse(Throwable throwable, int code) { private Object loggingThenBuildResponse(Throwable throwable, int code) {
Throwable rootCause = ExceptionUtil.getRootCause(throwable); Throwable rootCause = ExceptionUtil.getRootCause(throwable);
logError(rootCause); logError(rootCause);
return buildResponse(rootCause, code, rootCause.getMessage()); return buildResponse(rootCause, code, rootCause.getMessage());
} }
private ResponseDTO<String> buildResponse(Throwable throwable, int code, String message) { private Object buildResponse(Throwable throwable, int code, String message) {
return buildResponse(throwable, code, ResponseActionConstants.ALERT, message); return buildResponse(throwable, code, ResponseActionConstants.ALERT, message);
} }
private ResponseDTO<String> buildResponse(Throwable throwable, int code, int action, String message) { private Object buildResponse(Throwable throwable, int code, int action, String message) {
ResponseDTO<String> responseDTO = translateException(throwable, code, action, message); Object translated = translateException(throwable, code, action, message);
if (responseDTO != null) { if (translated != null) {
return responseDTO; return translated;
} }
// fallback
return ResponseDTO.error(message, code, action); return ResponseDTO.error(message, code, action);
} }
private ResponseDTO<String> translateException(Throwable throwable, int code, int action, String message) { private Object translateException(Throwable throwable, int code, int action, String message) {
for (ExceptionTranslator exceptionTranslator : exceptionTranslators) { for (ExceptionTranslator<?> exceptionTranslator : exceptionTranslators) {
ResponseDTO<String> responseDTO = exceptionTranslator.translate(throwable, code, action, message); Object translated = exceptionTranslator.translate(throwable, code, action, message);
if (responseDTO != null) { if (translated != null) {
return responseDTO; return translated;
} }
} }
return null; return null;
......
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<Converter<?, ?>> getConverters() {
List<Converter<?, ?>> 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<Long, LocalDate> {
INSTANCE;
@Override
public LocalDate convert(Long source) {
return LongToLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate();
}
}
public enum LongToLocalTimeConverter implements Converter<Long, LocalTime> {
INSTANCE;
@Override
public LocalTime convert(Long source) {
return LongToLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime();
}
}
public enum LongToLocalDateTimeConverter implements Converter<Long, LocalDateTime> {
INSTANCE;
@Override
public LocalDateTime convert(Long source) {
return ofInstant(Instant.ofEpochMilli(source), systemDefault());
}
}
public enum StringToLocalDateConverter implements Converter<String, LocalDate> {
INSTANCE;
@Override
public LocalDate convert(String source) {
return StringToLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate();
}
}
public enum StringToLocalTimeConverter implements Converter<String, LocalTime> {
INSTANCE;
@Override
public LocalTime convert(String source) {
return StringToLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime();
}
}
public enum StringToLocalDateTimeConverter implements Converter<String, LocalDateTime> {
INSTANCE;
@Override
public LocalDateTime convert(String source) {
return ofInstant(Instant.ofEpochMilli(Long.parseLong(source)), systemDefault());
}
}
}
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);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment