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;
}
网友评论