build: result code

This commit is contained in:
chenjianxing 2023-05-19 11:02:56 +08:00 committed by 刘瑞斌
parent 181bfb4921
commit 3000e68c4f
17 changed files with 271 additions and 16 deletions

View File

@ -59,6 +59,11 @@
<artifactId>metersphere-workstation</artifactId> <artifactId>metersphere-workstation</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>io.metersphere</groupId>
<artifactId>metersphere-issue-management</artifactId>
<version>${revision}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -1,7 +1,10 @@
package io.metersphere.sdk.controller.handler; package io.metersphere.sdk.controller.handler;
import io.metersphere.sdk.controller.handler.result.IResultCode;
import io.metersphere.sdk.controller.handler.result.MsHttpResultCode;
import io.metersphere.sdk.exception.MSException;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError; import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
@ -15,6 +18,13 @@ import java.util.Map;
@RestControllerAdvice @RestControllerAdvice
public class RestControllerExceptionHandler { public class RestControllerExceptionHandler {
/**
* 处理数据校验异常
* 返回具体字段的校验信息
* http 状态码返回 400
* @param ex
* @return
*/
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class) @ExceptionHandler(MethodArgumentNotValidException.class)
public ResultHolder handleValidationExceptions(MethodArgumentNotValidException ex) { public ResultHolder handleValidationExceptions(MethodArgumentNotValidException ex) {
@ -24,7 +34,34 @@ public class RestControllerExceptionHandler {
String errorMessage = error.getDefaultMessage(); String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage); errors.put(fieldName, errorMessage);
}); });
// 错误码待定 return ResultHolder.error(MsHttpResultCode.VALIDATE_FAILED.getCode(),
return ResultHolder.error(40000, "Validation failed", errors); MsHttpResultCode.VALIDATE_FAILED.getMessage(), errors);
}
/**
* 根据 MSException 中的 errorCode
* 设置对应的 Http 状态码以及业务状态码和错误提示
* @param e
* @return
*/
@ExceptionHandler(MSException.class)
public ResponseEntity<ResultHolder> handlerMSException(MSException e) {
IResultCode errorCode = e.getErrorCode();
if (errorCode == null) {
// 如果抛出异常没有设置状态码则返回错误 message
return ResponseEntity.ok()
.body(new ResultHolder(MsHttpResultCode.FAILED.getCode(),
MsHttpResultCode.FAILED.getMessage(), e.getMessage()));
}
if (errorCode instanceof MsHttpResultCode) {
// 如果是 MsHttpResultCode, 则设置响应的状态码
return ResponseEntity.status(errorCode.getCode() % 1000) // 取状态码的后三位
.body(new ResultHolder(errorCode.getCode(), errorCode.getMessage(), e.getMessage()));
} else {
// 业务错误返回 200以及业务状态码
return ResponseEntity.ok()
.body(new ResultHolder(errorCode.getCode(), errorCode.getMessage(), e.getMessage()));
}
} }
} }

View File

@ -0,0 +1,29 @@
package io.metersphere.sdk.controller.handler.result;
/**
* 通用功能状态码
* 通用功能返回的状态码
* @author jianxing
*/
public enum CommonResultCode implements IResultCode {
PLUGIN_GET_INSTANCE(100001, "get_plugin_instance_error");
private int code;
private String message;
CommonResultCode(int code, String message) {
this.code = code;
this.message = message;
}
@Override
public int getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,45 @@
package io.metersphere.sdk.controller.handler.result;
import io.metersphere.sdk.util.Translator;
/**
* API 接口状态码
* @author jianxing
*
* 1. 如果想返回具有 Http 含义的状态码使用 MsHttpResultCode
* 2. 业务状态码各模块定义自己的状态码枚举类各自管理
* 3. 业务错误码定义规则为 6 位数字
* 4. 业务错误码前三位表示模块名称最后三位表示错误码例如101001 101: 系统设置 001: 资源池校验失败
* 5. 当需要抛出异常时给异常设置状态码枚举对象
*
* 业务状态码列表
* 100: 通用功能
* 101: 系统设置
* 102: 项目设置
* 103: 性能测试
* 104: 接口测试
* 105: 测试跟踪
* 106: UI 测试
* 107: 测试计划
* 108: 缺陷管理
* 109: 工作台
*/
public interface IResultCode {
/**
* 返回状态码
*/
int getCode();
/**
* 返回状态码信息
*/
String getMessage();
/**
* 返回国际化后的状态码信息
* 如果没有匹配则返回原文
*/
default String getTranslationMessage(String message) {
return Translator.get(message, message);
}
}

View File

@ -0,0 +1,33 @@
package io.metersphere.sdk.controller.handler.result;
/**
* 具有 Http 含义的状态码
* 抛异常时使用会将 http 状态码设置成当前的状态码的后三位数字
* @author jianxing
*/
public enum MsHttpResultCode implements IResultCode {
SUCCESS(100200, "http_result_success"),
FAILED(100500, "http_result_unknown_exception"),
VALIDATE_FAILED(100400, "http_result_validate"),
UNAUTHORIZED(100401, "http_result_unauthorized"),
FORBIDDEN(100403, "http_result_forbidden");
private int code;
private String message;
MsHttpResultCode(int code, String message) {
this.code = code;
this.message = message;
}
@Override
public int getCode() {
return code;
}
@Override
public String getMessage() {
return getTranslationMessage(this.message);
}
}

View File

@ -1,13 +1,24 @@
package io.metersphere.sdk.exception; package io.metersphere.sdk.exception;
import io.metersphere.sdk.controller.handler.result.IResultCode;
import org.apache.commons.lang3.StringUtils;
public class MSException extends RuntimeException { public class MSException extends RuntimeException {
private MSException(String message) { protected IResultCode errorCode;
protected MSException(String message) {
super(message); super(message);
} }
private MSException(Throwable t) { protected MSException(IResultCode errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
protected MSException(IResultCode errorCode, Throwable t) {
super(t); super(t);
this.errorCode = errorCode;
} }
public static void throwException(String message) { public static void throwException(String message) {
@ -15,6 +26,22 @@ public class MSException extends RuntimeException {
} }
public static void throwException(Throwable t) { public static void throwException(Throwable t) {
throw new MSException(t); throw new MSException(null, t);
}
public static void throwException(IResultCode errorCode) {
throw new MSException(errorCode, StringUtils.EMPTY);
}
public static void throwException(IResultCode errorCode, String message) {
throw new MSException(errorCode, message);
}
public static void throwException(IResultCode errorCode, Throwable t) {
throw new MSException(errorCode, t);
}
public IResultCode getErrorCode() {
return errorCode;
} }
} }

View File

@ -1,7 +1,9 @@
package io.metersphere.sdk.plugin.loader; package io.metersphere.sdk.plugin.loader;
import io.metersphere.sdk.controller.handler.result.CommonResultCode;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.plugin.storage.StorageStrategy; import io.metersphere.sdk.plugin.storage.StorageStrategy;
import io.metersphere.sdk.util.LogUtils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -88,12 +90,11 @@ public class PluginManager {
Class<T> clazz = getImplClass(pluginId, superClazz); Class<T> clazz = getImplClass(pluginId, superClazz);
return clazz.getConstructor().newInstance(); return clazz.getConstructor().newInstance();
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
// todo log and LogUtils.error(e);
// LogUtils.error(e); MSException.throwException(CommonResultCode.PLUGIN_GET_INSTANCE, e.getTargetException().getMessage());
MSException.throwException(e.getTargetException());
} catch (Exception e) { } catch (Exception e) {
// LogUtil.error(e); LogUtils.error(e);
MSException.throwException(e.getMessage()); MSException.throwException(CommonResultCode.PLUGIN_GET_INSTANCE, e.getMessage());
} }
return null; return null;
} }
@ -103,11 +104,11 @@ public class PluginManager {
Class<T> clazz = getImplClass(pluginId, superClazz); Class<T> clazz = getImplClass(pluginId, superClazz);
return clazz.getConstructor(param.getClass()).newInstance(param); return clazz.getConstructor(param.getClass()).newInstance(param);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
// LogUtil.error(e.getTargetException()); LogUtils.error(e.getTargetException());
MSException.throwException(e.getTargetException()); MSException.throwException(CommonResultCode.PLUGIN_GET_INSTANCE, e.getTargetException().getMessage());
} catch (Exception e) { } catch (Exception e) {
// LogUtil.error(e); LogUtils.error(e);
MSException.throwException(e.getMessage()); MSException.throwException(CommonResultCode.PLUGIN_GET_INSTANCE, e.getMessage());
} }
return null; return null;
} }

View File

@ -18,4 +18,11 @@ public class Translator {
public static String get(String key) { public static String get(String key) {
return messageSource.getMessage(key, null, "Not Support Key: " + key, LocaleContextHolder.getLocale()); return messageSource.getMessage(key, null, "Not Support Key: " + key, LocaleContextHolder.getLocale());
} }
/**
* 单Key翻译并设置默认值
*/
public static String get(String key, String defaultMessage) {
return messageSource.getMessage(key, null, defaultMessage, LocaleContextHolder.getLocale());
}
} }

View File

@ -72,3 +72,14 @@ jira_auth_error=
# issue template copy # issue template copy
target_issue_template_not_checked= target_issue_template_not_checked=
source_issue_template_is_empty= source_issue_template_is_empty=
#plugin
get_plugin_instance_error=
#result message
http_result_success=
http_result_unknown_exception=
http_result_validate=
http_result_unauthorized=
http_result_forbidden=

View File

@ -380,3 +380,13 @@ can_not_move_to_repository_node=Can not move to repository node
# issue template copy # issue template copy
target_issue_template_not_checked=Cannot copy, target project not checked target_issue_template_not_checked=Cannot copy, target project not checked
source_issue_template_is_empty=Copy error, source project is empty source_issue_template_is_empty=Copy error, source project is empty
#plugin
get_plugin_instance_error=Get the plugin instance error!
#result message
http_result_success=operate success
http_result_unknown_exception=system unknown exception
http_result_validate=parameter validate failure
http_result_unauthorized=user authentication failure
http_result_forbidden=permission authentication failure

View File

@ -377,3 +377,13 @@ name_already_exists_in_module=同层级下已经存在
# issue template copy # issue template copy
target_issue_template_not_checked=无法复制,未选中目标项目 target_issue_template_not_checked=无法复制,未选中目标项目
source_issue_template_is_empty=复制错误,源项目为空 source_issue_template_is_empty=复制错误,源项目为空
#plugin
get_plugin_instance_error=获取插件接口实现类错误!
#result message
http_result_success=操作成功
http_result_unknown_exception=系统未知异常
http_result_validate=参数校验失败
http_result_unauthorized=用户认证失败
http_result_forbidden=权限认证失败

View File

@ -376,3 +376,13 @@ name_already_exists_in_module=同層級下已存在
# issue template copy # issue template copy
target_issue_template_not_checked=無法複製,未選中目標項目 target_issue_template_not_checked=無法複製,未選中目標項目
source_issue_template_is_empty=複製錯誤,源項目為空 source_issue_template_is_empty=複製錯誤,源項目為空
#plugin
get_plugin_instance_error=獲取插件接口實現類錯誤!
#result message
http_result_success=操作成功
http_result_unknown_exception=系統未知異常
http_result_validate=參數校驗失敗
http_result_unauthorized=用戶認證失敗
http_result_forbidden=權限認證失敗

View File

@ -0,0 +1 @@
issue_exists=

View File

@ -0,0 +1 @@
issue_exists=The issue already exists under this project

View File

@ -0,0 +1 @@
issue_exists=该项目下已存在该缺陷

View File

@ -0,0 +1 @@
issue_exists=該項目下已存在該缺陷

View File

@ -0,0 +1,26 @@
package io.metersphere.issue.controller.result;
import io.metersphere.sdk.controller.handler.result.IResultCode;
public enum IssueResultCode implements IResultCode {
ISSUE_EXIST_EXCEPTION(108001, "issue_exists");
private int code;
private String message;
IssueResultCode(int code, String message) {
this.code = code;
this.message = message;
}
@Override
public int getCode() {
return code;
}
@Override
public String getMessage() {
return getTranslationMessage(this.message);
}
}