Przeglądaj źródła

异常升级完成

xujunwei 3 lat temu
rodzic
commit
4c04ef0fb7

+ 9 - 1
framework-boot/src/main/java/com/mrxu/framework/boot/entity/RpcRequestInfo.java

@@ -2,8 +2,10 @@ package com.mrxu.framework.boot.entity;
 
 import lombok.Data;
 
+import java.io.Serializable;
+
 @Data
-public class RpcRequestInfo {
+public class RpcRequestInfo implements Serializable {
 
     private static ThreadLocal<RpcRequestInfo> rpcRequestInfo = new ThreadLocal<RpcRequestInfo>();
 
@@ -28,6 +30,8 @@ public class RpcRequestInfo {
 
     protected String ip;
 
+    protected String fromServiceName;
+
     public static String getTrackId() {
        return get().trackId;
     }
@@ -44,4 +48,8 @@ public class RpcRequestInfo {
         return get().ip;
     }
 
+    public static String getFromServiceName() {
+        return get().fromServiceName;
+    }
+
 }

+ 42 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/feign/FeignProviderException.java

@@ -0,0 +1,42 @@
+package com.mrxu.framework.boot.feign;
+
+import com.mrxu.framework.boot.entity.RpcRequestInfo;
+import com.mrxu.framework.common.util.BaseCode;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.Serializable;
+
+/**
+ * @Author: xujunwei
+ * @Description: rpc 服务端异常
+ */
+@Data
+@Component
+public class FeignProviderException implements Serializable {
+
+    // 是否是业务异常
+    private boolean isBusinessException;
+
+    // rpc调用方 服务名称
+    private String fromServiceName;
+
+    // 当前服务名称
+    @Value("${spring.application.name:未知(未配置spring.application.name)}")
+    private String serviceName;
+
+    private int code;
+
+    private String msg;
+
+    public FeignProviderException(){}
+
+    public FeignProviderException(boolean isBusinessException, BaseCode baseCode) {
+        this.isBusinessException = isBusinessException;
+        this.fromServiceName = RpcRequestInfo.getFromServiceName();
+        this.code = baseCode.getCode();
+        this.msg = baseCode.getMsg();
+    }
+    
+}

+ 3 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/feign/FeignRequestInterceptor.java

@@ -25,6 +25,9 @@ public class FeignRequestInterceptor implements RequestInterceptor {
         if(StringUtils.isNotBlank(RpcRequestInfo.getTenantId())){
             requestTemplate.header(HeaderConstant.TENANT_ID,RpcRequestInfo.getTenantId());
         }
+        if(StringUtils.isNotBlank(RpcRequestInfo.getFromServiceName())){
+            requestTemplate.header(HeaderConstant.FROM_SERVICE_NAME,RpcRequestInfo.getFromServiceName());
+        }
         if(StringUtils.isNotBlank(RpcRequestInfo.getUsername())){
             requestTemplate.header(HeaderConstant.USER_NAME,RpcRequestInfo.getUsername());
         }

+ 5 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/feign/HeaderConstant.java

@@ -18,6 +18,11 @@ public interface HeaderConstant {
      */
     public static final String TENANT_ID = "tenant_id";
 
+    /**
+     * 调用方服务名称
+     */
+    public static final String FROM_SERVICE_NAME = "from_service_name";
+
     /**
      * 当前登录名称
      */

+ 18 - 4
framework-boot/src/main/java/com/mrxu/framework/boot/handle/FeignErrorDecoder.java

@@ -1,10 +1,12 @@
 package com.mrxu.framework.boot.handle;
 
 import com.alibaba.fastjson.JSONObject;
+import com.mrxu.framework.boot.feign.FeignProviderException;
 import com.mrxu.framework.common.util.BusinessException;
 import feign.Response;
 import feign.Util;
 import feign.codec.ErrorDecoder;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
@@ -12,6 +14,11 @@ import org.springframework.context.annotation.Import;
 import java.io.IOException;
 import java.lang.annotation.*;
 
+/**
+ * @Author: xujunwei
+ * @Date: 2022/5/16
+ * @Description: rpc 调用方 处理500错误时的编码
+ */
 @Slf4j
 @Configuration
 public class FeignErrorDecoder implements ErrorDecoder {
@@ -19,19 +26,26 @@ public class FeignErrorDecoder implements ErrorDecoder {
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.TYPE})
     @Documented
-    @Import({FeignErrorDecoder.class})
+    @Import({FeignErrorDecoder.class,FeignProviderExceptionHandler.class})
     public @interface EnableFeignErrorDecoder {
     }
 
+    @SneakyThrows
     @Override
     public Exception decode(String methodKey, Response response) {
         try {
             String rs = Util.toString(response.body().asReader());
-            log.error(rs);
-            JSONObject result = JSONObject.parseObject(rs);
-            return new BusinessException(result.getString("message"));
+            FeignProviderException feignProviderException = JSONObject.parseObject(rs, FeignProviderException.class);
+            log.info("rpc 远程调用返回错误:{}",rs);
+            if(feignProviderException.isBusinessException()) {
+                throw new BusinessException(feignProviderException.getCode(),feignProviderException.getMsg());
+            }
+            else {
+                throw new Exception(feignProviderException.getMsg());
+            }
         }
         catch (IOException ignored) {
+            log.error("rpc 返回数据异常",ignored);
             return new BusinessException("数据异常");
         }
     }

+ 78 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/handle/FeignProviderExceptionHandler.java

@@ -0,0 +1,78 @@
+package com.mrxu.framework.boot.handle;
+
+
+import com.mrxu.framework.boot.feign.FeignProviderException;
+import com.mrxu.framework.boot.web.ServletUtils;
+import com.mrxu.framework.common.util.BaseCode;
+import com.mrxu.framework.common.util.BusinessException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @Author: xujunwei
+ * @Description: 此异常拦截给微服务提供方使用,不能与WebExceptionHandler 同时使用
+ */ 
+@ControllerAdvice
+@RestController
+@Slf4j
+public class FeignProviderExceptionHandler {
+
+    /*@Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE})
+    @Documented
+    @Import({FeignProviderExceptionHandler.class})
+    public @interface EnableFeignProviderExceptionHandler {
+    }*/
+
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(Exception.class)
+    public Object handleException(Exception e) {
+        log.error("系统错误:{}",e.getMessage(), e);
+        return rendError(false,BaseCode.ERROR);
+    }
+
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(BusinessException.class)
+    public Object handleLogicalException(BusinessException e) {
+        log.warn(e.getMessage());
+        return rendError(true,new BaseCode(e.getCode(),e.getMsg()));
+    }
+
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public Object handleValidException(MethodArgumentNotValidException e) {
+        BindingResult result = e.getBindingResult();
+        FieldError error = result.getFieldError();
+        log.warn("请求参数错误:{}",error.getDefaultMessage());
+        return rendError(true,BaseCode.ERR_PARAMS_VALID);
+    }
+
+    /**
+     * 缺少必要参数
+     * @param e
+     * @return
+     */
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(MissingServletRequestParameterException.class)
+    public Object handleValidException(MissingServletRequestParameterException e) {
+        log.warn("请求缺少参数:{}",e.getMessage());
+        return rendError(true,BaseCode.ERR_PARAMS_MISS);
+    }
+
+    public Object rendError(boolean isBusinessException,BaseCode code) {
+        HttpServletRequest request = ServletUtils.getRequest();
+        FeignProviderException exception = new FeignProviderException(isBusinessException,code);
+        return exception;
+    }
+
+}

+ 6 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/handle/UserInfoHandler.java

@@ -4,6 +4,7 @@ import com.mrxu.framework.boot.entity.RpcRequestInfo;
 import com.mrxu.framework.boot.feign.HeaderConstant;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
 import javax.servlet.http.HttpServletRequest;
@@ -18,6 +19,10 @@ import javax.servlet.http.HttpServletResponse;
 @Slf4j
 public class UserInfoHandler extends HandlerInterceptorAdapter {
 
+    // 当前服务名称
+    @Value("${spring.application.name:未知(未配置spring.application.name)}")
+    private String fromServiceName;
+
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
         //获取设置头部信息
@@ -26,6 +31,7 @@ public class UserInfoHandler extends HandlerInterceptorAdapter {
             return true;
         }
         RpcRequestInfo requestInfo = RpcRequestInfo.get();
+        requestInfo.setFromServiceName(fromServiceName);
         String trackId = request.getHeader(HeaderConstant.TRACK_ID);
         if (StringUtils.isNotBlank(trackId)) {
             requestInfo.setTrackId(trackId);

+ 5 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/handle/WebExceptionHandler.java

@@ -22,6 +22,11 @@ import org.springframework.web.servlet.ModelAndView;
 import javax.servlet.http.HttpServletRequest;
 import java.lang.annotation.*;
 
+/**
+ * @Author: xujunwei
+ * @Date: 2022/5/16
+ * @Description: 此异常处理器给 gateway使用,不能与FeignProviderExceptionHandler 同时使用
+ */ 
 @ControllerAdvice
 @RestController
 public class WebExceptionHandler {