parent
46fa7bf45e
commit
f0a9ba9243
@ -0,0 +1,37 @@
|
|||||||
|
package cn.teammodel.common;
|
||||||
|
|
||||||
|
public enum ErrorCode {
|
||||||
|
|
||||||
|
SUCCESS(0, "ok"),
|
||||||
|
PARAMS_ERROR(40000, "请求参数错误"),
|
||||||
|
NOT_LOGIN_ERROR(40100, "未登录"),
|
||||||
|
NO_AUTH_ERROR(40101, "无权限"),
|
||||||
|
NOT_FOUND_ERROR(40400, "请求数据不存在"),
|
||||||
|
FORBIDDEN_ERROR(40300, "禁止访问"),
|
||||||
|
SYSTEM_ERROR(50000, "系统内部异常"),
|
||||||
|
OPERATION_ERROR(50001, "操作失败");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态码
|
||||||
|
*/
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信息
|
||||||
|
*/
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
ErrorCode(int code, String message) {
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,37 +1,48 @@
|
|||||||
package cn.teammodel.common;
|
package cn.teammodel.common;
|
||||||
|
|
||||||
public class R {
|
import lombok.Data;
|
||||||
private Integer code;
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class R<T> implements Serializable {
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
private T data;
|
||||||
|
|
||||||
private String message;
|
private String message;
|
||||||
private String data;
|
|
||||||
|
|
||||||
public R(Integer code, String message, String data) {
|
public R(int code, T data, String message) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.message = message;
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getCode() {
|
public R(int code, T data) {
|
||||||
return code;
|
this(code, data, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCode(Integer code) {
|
public R(ErrorCode errorCode) {
|
||||||
this.code = code;
|
this(errorCode.getCode(), null, errorCode.getMessage());
|
||||||
|
}
|
||||||
|
public R(ErrorCode errorCode, T data) {
|
||||||
|
this(errorCode.getCode(), data, errorCode.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMessage() {
|
public static <T> R<T> success(T data) {
|
||||||
return message;
|
return new R<>(ErrorCode.SUCCESS, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessage(String message) {
|
public static <T> R<T> error(String msg) {
|
||||||
this.message = message;
|
return new R<>(ErrorCode.SYSTEM_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getData() {
|
public static <T> R<T> error(Integer code, String msg) {
|
||||||
return data;
|
return new R<>(code, null, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(String data) {
|
public static <T> R<T> error(ErrorCode errorCode) {
|
||||||
this.data = data;
|
return new R<>(errorCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
package cn.teammodel.config.exception;
|
||||||
|
|
||||||
|
import cn.teammodel.common.R;
|
||||||
|
import cn.teammodel.manager.NotificationService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
import org.springframework.validation.BindException;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.MissingPathVariableException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局异常处理器
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@RestControllerAdvice
|
||||||
|
@Slf4j
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private NotificationService notificationService;
|
||||||
|
/**
|
||||||
|
* 业务异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(ServiceException.class)
|
||||||
|
public R<?> handleServiceException(ServiceException e, HttpServletRequest request)
|
||||||
|
{
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
Integer code = e.getCode();
|
||||||
|
return ObjectUtils.isNotEmpty(code) ? R.error(code, e.getMessage()) : R.error(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求路径中缺少必需的路径变量
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(MissingPathVariableException.class)
|
||||||
|
public R<?> handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
|
||||||
|
{
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
|
||||||
|
return R.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数类型不匹配
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||||
|
public R<?> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
|
||||||
|
{
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
|
||||||
|
return R.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截未知的运行时异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(RuntimeException.class)
|
||||||
|
public R<?> handleRuntimeException(RuntimeException e, HttpServletRequest request)
|
||||||
|
{
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
log.error("请求地址'{}',发生未知异常.", requestURI, e);
|
||||||
|
notificationService.send("RuntimeException 告警: " + e.getMessage());
|
||||||
|
return R.error(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public R<?> handleException(Exception e, HttpServletRequest request)
|
||||||
|
{
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
log.error("请求地址'{}',发生系统异常.", requestURI, e);
|
||||||
|
|
||||||
|
notificationService.send("Exception 告警: " + e.getMessage());
|
||||||
|
return R.error(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义验证异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(BindException.class)
|
||||||
|
public R<?> handleBindException(BindException e)
|
||||||
|
{
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
String message = e.getAllErrors().get(0).getDefaultMessage();
|
||||||
|
return R.error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义验证异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
|
||||||
|
{
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
String message = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
|
||||||
|
return R.error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package cn.teammodel.manager;
|
||||||
|
|
||||||
|
import com.dingtalk.api.DefaultDingTalkClient;
|
||||||
|
import com.dingtalk.api.DingTalkClient;
|
||||||
|
import com.dingtalk.api.request.OapiRobotSendRequest;
|
||||||
|
import com.taobao.api.ApiException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉告警服务
|
||||||
|
* @author winter
|
||||||
|
* @create 2023-11-14 10:11
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class DingAlertNotifier implements NotificationService{
|
||||||
|
private final DingTalkClient client;
|
||||||
|
@Autowired
|
||||||
|
public DingAlertNotifier(@Value("${ding.server-url}") String dingServerUrl) {
|
||||||
|
this.client = new DefaultDingTalkClient(dingServerUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(String message) {
|
||||||
|
OapiRobotSendRequest request = new OapiRobotSendRequest();
|
||||||
|
// 文本消息
|
||||||
|
request.setMsgtype("text");
|
||||||
|
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
|
||||||
|
text.setContent(message);
|
||||||
|
request.setText(text);
|
||||||
|
// at 管理员提醒异常
|
||||||
|
OapiRobotSendRequest.At atAll = new OapiRobotSendRequest.At();
|
||||||
|
atAll.setIsAtAll(true);
|
||||||
|
request.setAt(atAll);
|
||||||
|
try {
|
||||||
|
client.execute(request);
|
||||||
|
} catch (ApiException e) {
|
||||||
|
log.error("钉钉 robot 推送消息渠道异常: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package cn.teammodel.manager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息通知接口
|
||||||
|
* @author winter
|
||||||
|
* @create 2023-11-14 10:08
|
||||||
|
*/
|
||||||
|
public interface NotificationService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息
|
||||||
|
* @author: winter
|
||||||
|
* @date: 2023/11/14 10:09
|
||||||
|
*/
|
||||||
|
void send(String message);
|
||||||
|
}
|
@ -1,13 +1,19 @@
|
|||||||
package cn.teammodel;
|
package cn.teammodel;
|
||||||
|
|
||||||
|
import cn.teammodel.manager.DingAlertNotifier;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
class TeamModelExtensionApplicationTests {
|
class TeamModelExtensionApplicationTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DingAlertNotifier notifier;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextLoads() {
|
void contextLoads() {
|
||||||
|
notifier.send("告警: 测试消息推送封装模块");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in new issue