diff --git a/commons/common-util/pom.xml b/commons/common-util/pom.xml
index d6d10b4ec741ef86f5729815c633c825a625e6e9..211d183b4c06654aa1cf3fae7f2f53a049dfd511 100644
--- a/commons/common-util/pom.xml
+++ b/commons/common-util/pom.xml
@@ -82,6 +82,11 @@
apm-toolkit-trace
true
+
+ org.hibernate.validator
+ hibernate-validator
+ true
+
com.baomidou
mybatis-plus-extension
diff --git a/commons/common-util/src/main/java/com/schbrain/common/util/support/ValidationMessageBuilder.java b/commons/common-util/src/main/java/com/schbrain/common/util/support/ValidationMessageBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..16678339eedf6cb3cfbe5144d6dd453fd83c2e93
--- /dev/null
+++ b/commons/common-util/src/main/java/com/schbrain/common/util/support/ValidationMessageBuilder.java
@@ -0,0 +1,41 @@
+package com.schbrain.common.util.support;
+
+import org.hibernate.validator.internal.engine.path.PathImpl;
+import org.springframework.validation.*;
+
+import javax.validation.ConstraintViolation;
+import java.util.*;
+
+/**
+ * @author liaozan
+ * @since 2023-07-04
+ */
+public class ValidationMessageBuilder {
+
+ public static String buildBindingErrorMsg(BindingResult bindingResult) {
+ String prefix = "参数验证失败: ";
+ StringJoiner joiner = new StringJoiner(", ");
+ for (ObjectError error : bindingResult.getAllErrors()) {
+ String errorMessage = Optional.ofNullable(error.getDefaultMessage()).orElse("验证失败");
+ String source;
+ if (error instanceof FieldError) {
+ source = ((FieldError) error).getField();
+ } else {
+ source = error.getObjectName();
+ }
+ joiner.add(source + " " + errorMessage);
+ }
+ return prefix + joiner;
+ }
+
+ public static String buildConstraintViolationErrorMsg(Set> constraintViolations) {
+ String prefix = "参数验证失败: ";
+ StringJoiner joiner = new StringJoiner(", ");
+ for (ConstraintViolation> violation : constraintViolations) {
+ PathImpl propertyPath = (PathImpl) violation.getPropertyPath();
+ joiner.add(propertyPath.asString() + " " + violation.getMessage());
+ }
+ return prefix + joiner;
+ }
+
+}
\ 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 0b6f76696535ae4ca12a27974ec6c30bf041e5e4..9853a2cffffa8a77a48a652bcfab33791fb9c42b 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
@@ -4,14 +4,14 @@ import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.schbrain.common.constants.ResponseActionConstants;
import com.schbrain.common.exception.BaseException;
+import com.schbrain.common.util.support.ValidationMessageBuilder;
import com.schbrain.common.web.result.ResponseDTO;
import lombok.extern.slf4j.Slf4j;
-import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.ClassUtils;
-import org.springframework.validation.*;
+import org.springframework.validation.BindException;
import org.springframework.web.*;
import org.springframework.web.bind.*;
import org.springframework.web.bind.annotation.*;
@@ -20,10 +20,10 @@ import org.springframework.web.method.annotation.MethodArgumentTypeMismatchExcep
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;
-import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.sql.SQLException;
-import java.util.*;
+import java.util.Arrays;
+import java.util.List;
import static com.schbrain.common.constants.ResponseCodeConstants.*;
@@ -178,14 +178,14 @@ public class GlobalExceptionHandler {
/************************************* Parameter Binding Exception Handing *************************************/
@ExceptionHandler(BindException.class)
public ResponseDTO handleBindException(BindException ex) {
- String errorMsg = buildBindingErrorMsg(ex.getBindingResult());
+ String errorMsg = ValidationMessageBuilder.buildBindingErrorMsg(ex.getBindingResult());
log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg);
}
@ExceptionHandler(ConstraintViolationException.class)
public ResponseDTO handleConstraintViolationException(ConstraintViolationException ex) {
- String errorMsg = buildBindingErrorMsg(ex.getConstraintViolations());
+ String errorMsg = ValidationMessageBuilder.buildConstraintViolationErrorMsg(ex.getConstraintViolations());
log.error(errorMsg);
return buildResponse(ex, PARAM_INVALID, errorMsg);
}
@@ -218,32 +218,6 @@ public class GlobalExceptionHandler {
return null;
}
- private String buildBindingErrorMsg(BindingResult bindingResult) {
- String prefix = "参数验证失败: ";
- StringJoiner joiner = new StringJoiner(", ");
- for (ObjectError error : bindingResult.getAllErrors()) {
- String errorMessage = Optional.ofNullable(error.getDefaultMessage()).orElse("验证失败");
- String source;
- if (error instanceof FieldError) {
- source = ((FieldError) error).getField();
- } else {
- source = error.getObjectName();
- }
- joiner.add(source + " " + errorMessage);
- }
- return prefix + joiner;
- }
-
- private String buildBindingErrorMsg(Set> constraintViolations) {
- String prefix = "参数验证失败: ";
- StringJoiner joiner = new StringJoiner(", ");
- for (ConstraintViolation> violation : constraintViolations) {
- PathImpl propertyPath = (PathImpl) violation.getPropertyPath();
- joiner.add(propertyPath.asString() + " " + violation.getMessage());
- }
- return prefix + joiner;
- }
-
private void logError(Throwable throwable) {
String exMsg = ExceptionUtil.getMessage(throwable);
log.error(exMsg, throwable);
diff --git a/pom.xml b/pom.xml
index 2eaa27841d604c6c7f728fe82db86b9e4db2c177..72cecf0e5792254b8bcc642784a51a52105bc893 100644
--- a/pom.xml
+++ b/pom.xml
@@ -268,16 +268,6 @@
commons-pool2
${commons-pool2.version}
-
- org.apache.dubbo
- dubbo
- ${dubbo.version}
-
-
- org.apache.dubbo
- dubbo-spring-boot-starter
- ${dubbo.version}
-
org.apache.dubbo
dubbo-common
diff --git a/starters/dubbo-spring-boot-starter/pom.xml b/starters/dubbo-spring-boot-starter/pom.xml
index 6e3aefeafc2b3a228a8135db4af0f13e53bcd6be..64ac0bbdcf57cbed91f5c67e5011edd678a5de31 100644
--- a/starters/dubbo-spring-boot-starter/pom.xml
+++ b/starters/dubbo-spring-boot-starter/pom.xml
@@ -19,8 +19,8 @@
apollo-spring-boot-starter
- org.springframework.boot
- spring-boot-starter-validation
+ org.hibernate.validator
+ hibernate-validator
org.apache.zookeeper
@@ -42,6 +42,10 @@
org.apache.dubbo
dubbo-common
+
+ org.apache.dubbo
+ dubbo-filter-validation
+
org.apache.dubbo
dubbo-config-spring
diff --git a/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/filter/DubboExceptionFilter.java b/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/filter/DubboExceptionFilter.java
index a8959fc8356d451eb77f82a529271cae31e113fc..fab9a82443a98e2ba72293105c0e369b57aeb098 100644
--- a/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/filter/DubboExceptionFilter.java
+++ b/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/filter/DubboExceptionFilter.java
@@ -2,6 +2,8 @@ package com.schbrain.framework.autoconfigure.dubbo.filter;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.schbrain.common.exception.BaseException;
+import com.schbrain.common.exception.ParamInvalidException;
+import com.schbrain.common.util.support.ValidationMessageBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
@@ -9,6 +11,7 @@ import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.filter.ExceptionFilter;
import org.apache.dubbo.rpc.service.GenericService;
+import javax.validation.ConstraintViolationException;
import java.util.Arrays;
/**
@@ -26,8 +29,13 @@ public class DubboExceptionFilter extends ExceptionFilter {
}
Throwable cause = ExceptionUtil.getRootCause(appResponse.getException());
+
+ if (cause instanceof ConstraintViolationException) {
+ cause = createParamInvalidException(invocation, (ConstraintViolationException) cause);
+ }
+
appResponse.setException(cause);
- logErrorDetail(invoker, cause);
+ logErrorDetail(invocation, cause);
if (cause instanceof BaseException) {
return;
@@ -36,15 +44,22 @@ public class DubboExceptionFilter extends ExceptionFilter {
super.onResponse(appResponse, invoker, invocation);
}
- private void logErrorDetail(Invoker> invoker, Throwable exception) {
+ protected ParamInvalidException createParamInvalidException(Invocation invocation, ConstraintViolationException cause) {
+ String serviceName = invocation.getInvoker().getInterface().getSimpleName();
+ String methodName = invocation.getMethodName();
+ String errorMsg = ValidationMessageBuilder.buildConstraintViolationErrorMsg(cause.getConstraintViolations());
+ return new ParamInvalidException(String.format("%s.%s %s", serviceName, methodName, errorMsg));
+ }
+
+ protected void logErrorDetail(Invocation invocation, Throwable exception) {
RpcServiceContext context = RpcContext.getCurrentServiceContext();
+ String serviceName = invocation.getInvoker().getInterface().getSimpleName();
+ String methodName = invocation.getMethodName();
String arguments = Arrays.toString(context.getArguments());
- String serviceName = invoker.getInterface().getSimpleName();
- String methodName = context.getMethodName();
String remoteHost = context.getRemoteHost();
String remoteApplication = context.getRemoteApplicationName();
String errorMessage = ExceptionUtil.getMessage(exception);
log.error("Catch rpc exception: {}, client: {}@{}, target: {}#{}, args: {}", errorMessage, remoteApplication, remoteHost, serviceName, methodName, arguments, exception);
}
-}
+}
\ No newline at end of file
diff --git a/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/initializer/DubboValidationInitializer.java b/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/initializer/DubboValidationInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..332c11bd60426b9b8d0c98a6ed7e7580fc103827
--- /dev/null
+++ b/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/initializer/DubboValidationInitializer.java
@@ -0,0 +1,26 @@
+package com.schbrain.framework.autoconfigure.dubbo.initializer;
+
+import com.schbrain.common.util.properties.OrderedMapPropertySource;
+import org.springframework.util.ClassUtils;
+
+/**
+ * 暂时以编程的方式配置参数校验。待所有服务都升级到指定版本时,再通过配置开启
+ *
+ * @author liaozan
+ * @since 2023-07-04
+ */
+public class DubboValidationInitializer {
+
+ private static final String VALIDATION_FILTER_CLASS_NAME = "org.apache.dubbo.validation.filter.ValidationFilter";
+
+ private static final String PROVIDER_VALIDATION_PROPERTY = "dubbo.provider.validation";
+
+ public static void initialize(OrderedMapPropertySource propertySource) {
+ if (ClassUtils.isPresent(VALIDATION_FILTER_CLASS_NAME, DubboValidationInitializer.class.getClassLoader())) {
+ if (!propertySource.containsProperty(PROVIDER_VALIDATION_PROPERTY)) {
+ propertySource.addProperty(PROVIDER_VALIDATION_PROPERTY, Boolean.TRUE.toString());
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/listener/DubboConfigLoadedEventListener.java b/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/listener/DubboConfigLoadedEventListener.java
index 5aefdc319c76b203b9e6a9b316ec6bde99cdc37a..e29d5aee8a89511c76a650e51d5206e1e7618d6b 100644
--- a/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/listener/DubboConfigLoadedEventListener.java
+++ b/starters/dubbo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/dubbo/listener/DubboConfigLoadedEventListener.java
@@ -3,6 +3,7 @@ package com.schbrain.framework.autoconfigure.dubbo.listener;
import com.schbrain.common.util.properties.OrderedMapPropertySource;
import com.schbrain.framework.autoconfigure.apollo.event.ConfigLoadedEvent;
import com.schbrain.framework.autoconfigure.apollo.event.listener.GenericConfigLoadedEventListener;
+import com.schbrain.framework.autoconfigure.dubbo.initializer.DubboValidationInitializer;
import com.schbrain.framework.autoconfigure.dubbo.properties.DubboProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
@@ -29,6 +30,7 @@ public class DubboConfigLoadedEventListener extends GenericConfigLoadedEventList
@Override
protected void onConfigLoaded(ConfigLoadedEvent event, DubboProperties properties) {
addRequiredProperties(event.getSpringApplication(), event.getPropertySource());
+ DubboValidationInitializer.initialize(event.getPropertySource());
}
private void addRequiredProperties(SpringApplication application, OrderedMapPropertySource propertySource) {