springboot安全收集

Springboot全局异常与全局响应

2019-11-08  本文已影响0人  jackcooper

1.全局异常

将返回值统一封装时我们没有考虑当接口抛出异常的情况。当接口抛出异常时让用户直接看到服务端的异常肯定是不够友好的,而我们也不可能每一个接口都去try/catch进行处理,此时只需要使用@ExceptionHandler注解即可无感知的全局统一处理异常。


import com.chehejia.framework.beans.exception.BizException;
import com.chehejia.framework.beans.model.Response;
import com.saos.wo.consts.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * @author jack-cooper
 * @version 1.0.0
 * @ClassName GlobalExceptionHandler.java
 * @Description 全局异常处理器
 * @createTime 2019年11月01日 09:08:00
 */
@Slf4j
@RestController
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
@ResponseBody
    public Response defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        log.error("---BaseException Handler---Host {} invokes url {} ERROR: ",req.getRemoteHost(),req.getRequestURL(),e);
        return Response.fail(StatusCode.SYS_SERVICE_ERROR.getCode(), ExceptionUtils.getFullStackTrace(e));
    }

    @ExceptionHandler(value = BizException.class)
@ResponseBody
    public Response jsonErrorHandle(HttpServletRequest req, BizException e) {
        log.warn("---BaseException Handler---Host {} invokes url {}  ",req.getRemoteHost(),req.getRequestURL());
        return Response.fail(e.getCode(),e.getMessage());
    }

}

2.全局响应

在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。下面通过实现SpringBoot中为我们提供好的解决方法,只需要在项目中加上一下代码,即可实现相关功能。主要是实现接口ResponseBodyAdvice


import com.chehejia.framework.beans.model.Response;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;


/**
 * @author jack-cooper
 * @version 1.0.0
 * @ClassName GlobalReturnConfig.java
 * @Description 全局返回统一封装
 * @createTime 2019年11月08日 15:51:00
 */
@EnableWebMvc
@Configuration
@RestControllerAdvice
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof Response) {
            return body;
        } else {
            return Response.success(body);
        }
    }
}

3.统一返回对象


import com.chehejia.framework.beans.exception.BizException;
import com.chehejia.framework.beans.exception.BizRuntimeException;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;

import java.io.Serializable;
import java.util.Optional;
import java.util.function.Supplier;


@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel("统一返回")
public class Response<T> implements Serializable {

    private static final long serialVersionUID = -6724401478874316373L;

    public static <T> Response<T> success() {
        return Response.success(RestfulCode.SUCCESS, null, null);
    }

    public static <T> Response<T> success(T data) {
        return Response.success(RestfulCode.SUCCESS, null, data);
    }

    public static <T> Response<T> success(RestfulCode rc, T data) {
        return Response.success(rc, null, data);
    }

    public static <T> Response<T> success(RestfulCode rc, String msg, T data) {
        return Response.<T>builder()
                .code(rc.getCode())
                .msg(Optional.ofNullable(msg).orElse(rc.getMessage()))
                .data(data)
                .build();
    }

    public static <T> Response<T> fail(BizException e) {
        return Response.<T>builder()
                .code(e.getCode())
                .msg(e.getMessage())
                .build();
    }

    public static <T> Response<T> fail(BizRuntimeException e) {
        return Response.<T>builder()
                .code(e.getCode())
                .msg(e.getMessage())
                .build();
    }

    public static <T> Response<T> fail(Integer code, String msg) {
        return Response.<T>builder()
                .code(code)
                .msg(msg)
                .build();
    }

    public static <T> Response<T> fail(RestfulCode rs) {
        return Response.<T>builder()
                .code(rs.getCode())
                .msg(rs.getMessage())
                .build();
    }

    public static <T> Response<T> fail(Integer code, String msg, T data) {
        return Response.<T>builder()
                .code(code)
                .msg(msg)
                .data(data)
                .build();
    }

    public static <T> Response<T> fail(RestfulCode rs, T data) {
        return Response.<T>builder()
                .code(rs.getCode())
                .msg(rs.getMessage())
                .data(data)
                .build();
    }

    public static <T> Response<T> fail(Response source) {
        return Response.<T>builder()
                .code(source.getCode())
                .msg(source.getMsg())
                .build();
    }

    /**
     * 判断返回码是否相同,与是否成功无关
     *
     * @param restfulCode
     *
     * @return
     */
    public boolean codeEquals(RestfulCode restfulCode) {
        if (this.getCode() == null || restfulCode == null) {
            return false;
        }
        return this.getCode().equals(restfulCode.getCode());
    }

    /**
     * 如果成功则返回data,失败则抛出异常
     * @return data
     * @throws BizRuntimeException 失败抛出
     */
    public T orFailThrow() throws BizRuntimeException {
        if (isSuccess()) {
            return getData();
        } else {
            throw new BizRuntimeException(getCode(), getMsg());
        }
    }

    public <X extends Throwable> T orFailThrow(Supplier<? extends X> supplier) throws X {
        if (isSuccess()) {
            return getData();
        } else {
            throw supplier.get();
        }
    }

    /**
     * 期望有data
     * @return data
     * @throws BizRuntimeException 失败或data为null 抛出异常
     */
    public T forceData(RestfulCode error) throws BizRuntimeException {
        return Optional.ofNullable(orFailThrow()).orElseThrow(() -> new BizRuntimeException(error));
    }

    public boolean isSuccess() {
        return RestfulCode.SUCCESS.isEquals(getCode());
    }

    /**
     * 状态码
     */
    @ApiModelProperty("状态码")
    private Integer code = RestfulCode.SUCCESS.getCode();

    /**
     * 描述信息
     */
    @ApiModelProperty("描述信息")
    private String msg = RestfulCode.SUCCESS.getMessage();

    /**
     * 返回数据
     */
    @ApiModelProperty("返回数据")
    private T data;
}

上一篇 下一篇

猜你喜欢

热点阅读