msgList) throws CustomizeException {
+ if (CollectionUtils.isEmpty(fieldList) || CollectionUtils.isEmpty(msgList) || fieldList.size() != msgList.size()) {
+ return "参数错误";
+ }
+
+ StringBuilder message = new StringBuilder();
+ for (int i = 0; i < fieldList.size(); i++) {
+ String field = fieldList.get(i);
+ String msg = msgList.get(i);
+ if (i == fieldList.size() - 1) {
+ message.append(field).append(":").append(msg);
+ } else {
+ message.append(field).append(":").append(msg).append(",");
+ }
+ }
+ return message.toString();
+ }
+
+
+}
diff --git a/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/filter/HttpServletRequestInputStreamFilter.java b/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/filter/HttpServletRequestInputStreamFilter.java
new file mode 100644
index 0000000..e6c7399
--- /dev/null
+++ b/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/filter/HttpServletRequestInputStreamFilter.java
@@ -0,0 +1,35 @@
+package xyz.hlh.crypto.common.filter;
+
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import xyz.hlh.crypto.common.utils.InputStreamHttpServletRequestWrapper;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * @author wn
+ * @description:
+ * 请求流转换为多次读取的请求流 过滤器
+ */
+@Component
+@Order(Ordered.HIGHEST_PRECEDENCE + 1) // 优先级最高
+public class HttpServletRequestInputStreamFilter implements Filter {
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+
+ // 转换为可以多次获取流的request
+ HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ InputStreamHttpServletRequestWrapper inputStreamHttpServletRequestWrapper = new InputStreamHttpServletRequestWrapper(httpServletRequest);
+
+ // 放行
+ chain.doFilter(inputStreamHttpServletRequestWrapper, response);
+ }
+}
diff --git a/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/utils/InputStreamHttpServletRequestWrapper.java b/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/utils/InputStreamHttpServletRequestWrapper.java
new file mode 100644
index 0000000..d803a98
--- /dev/null
+++ b/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/utils/InputStreamHttpServletRequestWrapper.java
@@ -0,0 +1,89 @@
+package xyz.hlh.crypto.common.utils;
+
+import org.apache.commons.io.IOUtils;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * 请求流支持多次获取
+ */
+public class InputStreamHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+ /**
+ * 用于缓存输入流
+ */
+ private ByteArrayOutputStream cachedBytes;
+
+ public InputStreamHttpServletRequestWrapper(HttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ if (cachedBytes == null) {
+ // 首次获取流时,将流放入 缓存输入流 中
+ cacheInputStream();
+ }
+
+ // 从 缓存输入流 中获取流并返回
+ return new CachedServletInputStream(cachedBytes.toByteArray());
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ return new BufferedReader(new InputStreamReader(getInputStream()));
+ }
+
+ /**
+ * 首次获取流时,将流放入 缓存输入流 中
+ */
+ private void cacheInputStream() throws IOException {
+ // 缓存输入流以便多次读取。为了方便, 我使用 org.apache.commons IOUtils
+ cachedBytes = new ByteArrayOutputStream();
+ IOUtils.copy(super.getInputStream(), cachedBytes);
+ }
+
+ /**
+ * 读取缓存的请求正文的输入流
+ *
+ * 用于根据 缓存输入流 创建一个可返回的
+ */
+ public static class CachedServletInputStream extends ServletInputStream {
+
+ private final ByteArrayInputStream input;
+
+ public CachedServletInputStream(byte[] buf) {
+ // 从缓存的请求正文创建一个新的输入流
+ input = new ByteArrayInputStream(buf);
+ }
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener listener) {
+
+ }
+
+ @Override
+ public int read() throws IOException {
+ return input.read();
+ }
+ }
+
+}
diff --git a/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/utils/ValidationUtils.java b/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/utils/ValidationUtils.java
new file mode 100644
index 0000000..63ada53
--- /dev/null
+++ b/spring-boot-interface-crypto/cry-common/src/main/java/xyz/hlh/crypto/common/utils/ValidationUtils.java
@@ -0,0 +1,91 @@
+package xyz.hlh.crypto.common.utils;
+
+import xyz.hlh.crypto.common.exception.CustomizeException;
+import xyz.hlh.crypto.common.exception.ParamException;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author wn
+ * @description 验证工具类
+ */
+public class ValidationUtils {
+
+ private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
+
+ /**
+ * 验证数据
+ * @param object 数据
+ */
+ public static void validate(Object object) throws CustomizeException {
+
+ Set> validate = VALIDATOR.validate(object);
+
+ // 验证结果异常
+ throwParamException(validate);
+ }
+
+ /**
+ * 验证数据(分组)
+ * @param object 数据
+ * @param groups 所在组
+ */
+ public static void validate(Object object, Class> ... groups) throws CustomizeException {
+
+ Set> validate = VALIDATOR.validate(object, groups);
+
+ // 验证结果异常
+ throwParamException(validate);
+ }
+
+ /**
+ * 验证数据中的某个字段(分组)
+ * @param object 数据
+ * @param propertyName 字段名称
+ */
+ public static void validate(Object object, String propertyName) throws CustomizeException {
+ Set> validate = VALIDATOR.validateProperty(object, propertyName);
+
+ // 验证结果异常
+ throwParamException(validate);
+
+ }
+
+ /**
+ * 验证数据中的某个字段(分组)
+ * @param object 数据
+ * @param propertyName 字段名称
+ * @param groups 所在组
+ */
+ public static void validate(Object object, String propertyName, Class> ... groups) throws CustomizeException {
+
+ Set> validate = VALIDATOR.validateProperty(object, propertyName, groups);
+
+ // 验证结果异常
+ throwParamException(validate);
+
+ }
+
+ /**
+ * 验证结果异常
+ * @param validate 验证结果
+ */
+ private static void throwParamException(Set> validate) throws CustomizeException {
+ if (validate.size() > 0) {
+ List fieldList = new LinkedList<>();
+ List msgList = new LinkedList<>();
+ for (ConstraintViolation