提交 306e3449 编写于 作者: C chenjianxing

JSR-303校验国际化

上级 64d6d11f
...@@ -3,8 +3,12 @@ package io.metersphere.config; ...@@ -3,8 +3,12 @@ package io.metersphere.config;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import javax.validation.Validator;
@Configuration @Configuration
public class I18nConfig { public class I18nConfig {
...@@ -20,4 +24,16 @@ public class I18nConfig { ...@@ -20,4 +24,16 @@ public class I18nConfig {
public CommonBeanFactory commonBeanFactory() { public CommonBeanFactory commonBeanFactory() {
return new CommonBeanFactory(); return new CommonBeanFactory();
} }
/**
* JSR-303校验国际化
* @param messageSource
* @return
*/
@Bean
public LocalValidatorFactoryBean localValidatorFactoryBean(MessageSource messageSource) {
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setValidationMessageSource(messageSource);
return localValidatorFactoryBean;
}
} }
...@@ -20,12 +20,12 @@ public class TestCaseExcelData { ...@@ -20,12 +20,12 @@ public class TestCaseExcelData {
@Length(max=1000) @Length(max=1000)
@ExcelProperty("所属模块") @ExcelProperty("所属模块")
@ColumnWidth(30) @ColumnWidth(30)
@Pattern(regexp = "^(?!.*//).*$", message = "格式不正确") @Pattern(regexp = "^(?!.*//).*$", message = "{incorrect_format}")
private String nodePath; private String nodePath;
@NotBlank @NotBlank
@ExcelProperty("用例类型") @ExcelProperty("用例类型")
@Pattern(regexp = "(^functional$)|(^performance$)|(^api$)", message = "必须为functional、performance、api") @Pattern(regexp = "(^functional$)|(^performance$)|(^api$)", message = "{test_case_type_validate}")
private String type; private String type;
@NotBlank @NotBlank
...@@ -34,12 +34,12 @@ public class TestCaseExcelData { ...@@ -34,12 +34,12 @@ public class TestCaseExcelData {
@NotBlank @NotBlank
@ExcelProperty("优先级") @ExcelProperty("优先级")
@Pattern(regexp = "(^P0$)|(^P1$)|(^P2$)|(^P3$)", message = "必须为P0、P1、P2、P3") @Pattern(regexp = "(^P0$)|(^P1$)|(^P2$)|(^P3$)", message = "{test_case_priority_validate}")
private String priority; private String priority;
@NotBlank @NotBlank
@ExcelProperty("测试方式") @ExcelProperty("测试方式")
@Pattern(regexp = "(^manual$)|(^auto$)", message = "必须为manual、auto") @Pattern(regexp = "(^manual$)|(^auto$)", message = "{test_case_method_validate}")
private String method; private String method;
@ColumnWidth(50) @ColumnWidth(50)
......
...@@ -8,11 +8,16 @@ import com.alibaba.excel.util.StringUtils; ...@@ -8,11 +8,16 @@ import com.alibaba.excel.util.StringUtils;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.excel.utils.ExcelValidateHelper; import io.metersphere.excel.utils.ExcelValidateHelper;
import io.metersphere.excel.domain.ExcelErrData; import io.metersphere.excel.domain.ExcelErrData;
import io.metersphere.i18n.Translator;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*; import java.util.*;
@Component
public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> { public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> {
protected List<ExcelErrData<T>> errList = new ArrayList<>(); protected List<ExcelErrData<T>> errList = new ArrayList<>();
...@@ -26,9 +31,12 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> { ...@@ -26,9 +31,12 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> {
protected Class<T> clazz; protected Class<T> clazz;
@Resource
ExcelValidateHelper excelValidateHelper;
public EasyExcelListener(Class<T> clazz){ public EasyExcelListener(){
this.clazz = clazz; Type type = getClass().getGenericSuperclass();
this.clazz = (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
} }
/** /**
...@@ -43,16 +51,18 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> { ...@@ -43,16 +51,18 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> {
Integer rowIndex = analysisContext.readRowHolder().getRowIndex(); Integer rowIndex = analysisContext.readRowHolder().getRowIndex();
try { try {
//根据excel数据实体中的javax.validation + 正则表达式来校验excel数据 //根据excel数据实体中的javax.validation + 正则表达式来校验excel数据
errMsg = ExcelValidateHelper.validateEntity(t); errMsg = excelValidateHelper.validateEntity(t);
//自定义校验规则 //自定义校验规则
errMsg = validate(t, errMsg); errMsg = validate(t, errMsg);
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
errMsg = "解析数据出错"; errMsg = Translator.get("parse_data_error");
LogUtil.error(e.getMessage(), e); LogUtil.error(e.getMessage(), e);
} }
if (!StringUtils.isEmpty(errMsg)) { if (!StringUtils.isEmpty(errMsg)) {
ExcelErrData excelErrData = new ExcelErrData(t, rowIndex, "第" + rowIndex + "行出错:" + errMsg); ExcelErrData excelErrData = new ExcelErrData(t, rowIndex,
Translator.get("number") + rowIndex + Translator.get("row") + Translator.get("erroer")
+ ":" + errMsg);
errList.add(excelErrData); errList.add(excelErrData);
} else { } else {
list.add(t); list.add(t);
...@@ -101,7 +111,7 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> { ...@@ -101,7 +111,7 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> {
Collection<String> values = headMap.values(); Collection<String> values = headMap.values();
for (String key : fieldNameSet) { for (String key : fieldNameSet) {
if (!values.contains(key)){ if (!values.contains(key)){
throw new ExcelAnalysisException("缺少头部信息:" + key); throw new ExcelAnalysisException(Translator.get("missing_header_information") + ":" + key);
} }
} }
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
...@@ -133,8 +143,10 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> { ...@@ -133,8 +143,10 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> {
} }
public List<ExcelErrData<T>> getErrList() { public List<ExcelErrData<T>> getAndClearErrList() {
return errList; List<ExcelErrData<T>> tmp = this.errList;
this.errList = new ArrayList<>();
return tmp;
} }
} }
\ No newline at end of file
...@@ -6,18 +6,22 @@ import io.metersphere.excel.domain.TestCaseExcelData; ...@@ -6,18 +6,22 @@ import io.metersphere.excel.domain.TestCaseExcelData;
import io.metersphere.base.domain.TestCaseWithBLOBs; import io.metersphere.base.domain.TestCaseWithBLOBs;
import io.metersphere.commons.constants.TestCaseConstants; import io.metersphere.commons.constants.TestCaseConstants;
import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.i18n.Translator;
import io.metersphere.track.service.TestCaseService; import io.metersphere.track.service.TestCaseService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component
public class TestCaseDataListener extends EasyExcelListener<TestCaseExcelData> { public class TestCaseDataListener extends EasyExcelListener<TestCaseExcelData> {
@Resource
private TestCaseService testCaseService; private TestCaseService testCaseService;
private String projectId; private String projectId;
...@@ -26,13 +30,13 @@ public class TestCaseDataListener extends EasyExcelListener<TestCaseExcelData> { ...@@ -26,13 +30,13 @@ public class TestCaseDataListener extends EasyExcelListener<TestCaseExcelData> {
Set<String> userIds; Set<String> userIds;
public TestCaseDataListener(TestCaseService testCaseService, String projectId, public TestCaseDataListener() {}
Set<String> testCaseNames, Set<String> userIds, Class<TestCaseExcelData> clazz) {
super(clazz); public TestCaseDataListener init(String projectId, Set<String> testCaseNames, Set<String> userIds) {
this.testCaseService = testCaseService;
this.projectId = projectId; this.projectId = projectId;
this.testCaseNames = testCaseNames; this.testCaseNames = testCaseNames;
this.userIds = userIds; this.userIds = userIds;
return this;
} }
@Override @Override
...@@ -43,21 +47,22 @@ public class TestCaseDataListener extends EasyExcelListener<TestCaseExcelData> { ...@@ -43,21 +47,22 @@ public class TestCaseDataListener extends EasyExcelListener<TestCaseExcelData> {
if (nodePath != null) { if (nodePath != null) {
String[] nodes = nodePath.split("/"); String[] nodes = nodePath.split("/");
if ( nodes.length > TestCaseConstants.MAX_NODE_DEPTH + 1) { if ( nodes.length > TestCaseConstants.MAX_NODE_DEPTH + 1) {
stringBuilder.append("节点最多为" + TestCaseConstants.MAX_NODE_DEPTH + "层;"); stringBuilder.append(Translator.get("test_case_node_level_tip") +
TestCaseConstants.MAX_NODE_DEPTH + Translator.get("test_case_node_level"));
} }
for (int i = 0; i < nodes.length; i++) { for (int i = 0; i < nodes.length; i++) {
if (i != 0 && StringUtils.equals(nodes[i].trim(), "")) { if (i != 0 && StringUtils.equals(nodes[i].trim(), "")) {
stringBuilder.append("所属模块不能为空格"); stringBuilder.append(Translator.get("module_not_null"));
break; break;
} }
} }
} }
if (!userIds.contains(data.getMaintainer())) { if (!userIds.contains(data.getMaintainer())) {
stringBuilder.append("该工作空间下无该用户:" + data.getMaintainer() + ";"); stringBuilder.append(Translator.get("user_not_exists") + ":" + data.getMaintainer() + "; ");
} }
if (testCaseNames.contains(data.getName())) { if (testCaseNames.contains(data.getName())) {
stringBuilder.append("该项目下已存在该测试用例:" + data.getName() + ";"); stringBuilder.append(Translator.get("test_case_already_exists") + ":" + data.getName() + "; ");
} }
return stringBuilder.toString(); return stringBuilder.toString();
} }
......
package io.metersphere.excel.utils; package io.metersphere.excel.utils;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import org.springframework.stereotype.Component;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import javax.annotation.Resource;
import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default; import javax.validation.groups.Default;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Set; import java.util.Set;
@Component
public class ExcelValidateHelper { public class ExcelValidateHelper {
private ExcelValidateHelper(){} private ExcelValidateHelper(){}
private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); @Resource
LocalValidatorFactoryBean localValidatorFactoryBean;
public static <T> String validateEntity(T obj) throws NoSuchFieldException { public <T> String validateEntity(T obj) throws NoSuchFieldException {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class); Set<ConstraintViolation<T>> set = localValidatorFactoryBean.getValidator().validate(obj, Default.class);
if (set != null && !set.isEmpty()) { if (set != null && !set.isEmpty()) {
for (ConstraintViolation<T> cv : set) { for (ConstraintViolation<T> cv : set) {
Field declaredField = obj.getClass().getDeclaredField(cv.getPropertyPath().toString()); Field declaredField = obj.getClass().getDeclaredField(cv.getPropertyPath().toString());
ExcelProperty annotation = declaredField.getAnnotation(ExcelProperty.class); ExcelProperty annotation = declaredField.getAnnotation(ExcelProperty.class);
//拼接错误信息,包含当前出错数据的标题名字+错误信息 //拼接错误信息,包含当前出错数据的标题名字+错误信息
result.append(annotation.value()[0]+cv.getMessage()).append(";"); result.append(annotation.value()[0]+cv.getMessage()).append("; ");
} }
} }
return result.toString(); return result.toString();
......
...@@ -60,6 +60,9 @@ public class TestCaseService { ...@@ -60,6 +60,9 @@ public class TestCaseService {
@Resource @Resource
TestCaseNodeService testCaseNodeService; TestCaseNodeService testCaseNodeService;
@Resource
TestCaseDataListener testCaseDataListener;
@Resource @Resource
UserMapper userMapper; UserMapper userMapper;
...@@ -187,11 +190,10 @@ public class TestCaseService { ...@@ -187,11 +190,10 @@ public class TestCaseService {
List<User> users = userMapper.selectByExample(userExample); List<User> users = userMapper.selectByExample(userExample);
Set<String> userIds = users.stream().map(User::getId).collect(Collectors.toSet()); Set<String> userIds = users.stream().map(User::getId).collect(Collectors.toSet());
EasyExcelListener easyExcelListener = new TestCaseDataListener(this, projectId, EasyExcelFactory.read(file.getInputStream(), TestCaseExcelData.class,
testCaseNames, userIds, TestCaseExcelData.class); testCaseDataListener.init(projectId, testCaseNames, userIds)).sheet().doRead();
EasyExcelFactory.read(file.getInputStream(), TestCaseExcelData.class, easyExcelListener).sheet().doRead();
List<ExcelErrData<TestCaseExcelData>> errList = easyExcelListener.getErrList(); List<ExcelErrData<TestCaseExcelData>> errList = testCaseDataListener.getAndClearErrList();
//如果包含错误信息就导出错误信息 //如果包含错误信息就导出错误信息
if (!errList.isEmpty()) { if (!errList.isEmpty()) {
excelResponse.setSuccess(false); excelResponse.setSuccess(false);
......
...@@ -5,4 +5,16 @@ test_case_node_level= ...@@ -5,4 +5,16 @@ test_case_node_level=
test_case_module_not_null= test_case_module_not_null=
test_case_create_moule_fail= test_case_create_moule_fail=
test_case_import_template_name= test_case_import_template_name=
test_case_import_template_sheet= test_case_import_template_sheet=
\ No newline at end of file module_not_null=
user_not_exists=
test_case_already_exists=
parse_data_error=
missing_header_information=
number=
row=
erroer=
incorrect_format=
test_case_type_validate=
test_case_priority_validate=
test_case_method_validate=
\ No newline at end of file
...@@ -39,4 +39,16 @@ test_case_node_level=level ...@@ -39,4 +39,16 @@ test_case_node_level=level
test_case_module_not_null=The owned module cannot be empty test_case_module_not_null=The owned module cannot be empty
test_case_create_moule_fail=Failed to create module test_case_create_moule_fail=Failed to create module
test_case_import_template_name=Test case templates test_case_import_template_name=Test case templates
test_case_import_template_sheet=Template test_case_import_template_sheet=Template
\ No newline at end of file module_not_null=The module must not be blank
user_not_exists=The user in this workspace is not exists
test_case_already_exists=The test case in this project is exists
parse_data_error=Parse data error
missing_header_information=Missing header information
number=Number
row=row
erroer=erroer
incorrect_format=Incorrect format
test_case_type_validate=must be functional, performance, api
test_case_priority_validate=must be P0, P1, P2, P3
test_case_method_validate=\ must be manual, auto
\ No newline at end of file
...@@ -41,4 +41,15 @@ test_case_module_not_null=所属模块不能为空 ...@@ -41,4 +41,15 @@ test_case_module_not_null=所属模块不能为空
test_case_create_moule_fail=创建模块失败 test_case_create_moule_fail=创建模块失败
test_case_import_template_name=测试用例模版 test_case_import_template_name=测试用例模版
test_case_import_template_sheet=模版 test_case_import_template_sheet=模版
module_not_null=所属模块不能为空格
user_not_exists=该工作空间下无该用户
test_case_already_exists=该项目下已存在该测试用例
parse_data_error=解析数据出错
missing_header_information=缺少头部信息
number=
row=
incorrect_format=格式不正确
test_case_type_validate=必须为functional、performance、api
test_case_priority_validate=必须为P0、P1、P2、P3
test_case_method_validate=必须为manual、auto
#test case end #test case end
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册