1.为什么要把结果封装成统一格式?
异常和正常情况无法区分:异常情况返回数据为null,正常情况下查询结果也为null,返回给前端无法区分
显示抛出异常信息:前端需要显示抛出的异常信息
@AllArgsConstructor
public enum ResultCode {
CODE_200(200, "success"),
CODE_1000(1000, "fail");
@Getter
private Integer code;
@Getter
private String msg;
}
@Data
public class Result<T> {
private String msg;
private Integer code;
private T data;
private Result(String msg, Integer code) {
this.msg = msg;
this.code = code;
}
private Result(ResultCode resultCode, String msg) {
this(msg, resultCode.getCode());
}
private Result(ResultCode resultCode) {
this(resultCode.getMsg(), resultCode.getCode());
}
public static <T>Result<T> result(ResultCode resultCode,T data) {
Result result = new Result(resultCode);
result.setData(data);
return result;
}
public static <T>Result<T> fail(ResultCode resultCode,String message) {
Result result = new Result(resultCode, message);
result.setData(null);
return result;
}
public static <T>Result<T> fail(T data) {
Result result = new Result(ResultCode.CODE_1000);
result.setData(data);
return result;
}
public static <T>Result<T> success(T data) {
Result result = new Result(ResultCode.CODE_200);
result.setData(data);
return result;
}
}
不封装:
封装:
2.统一异常接收
为什么要用统一异常接收?
通常在service层抛异常,涉及到事务时不会进行try-catch,需要在controller里处理异常。即使能够进行try-catch的地方也需要统一返回格式,造成重复代码很多,可读性比较差。
如何实现统一的异常接收?
@Slf4j
@RestControllerAdvice
public class GlobalException {
@ExceptionHandler(Exception.class)
public Result<?> handlerException(Exception exception) {
log.info("Exception异常信息:" + exception.getMessage());
return Result.fail(ResultCode.CODE_1000, exception.getMessage());
}
@ExceptionHandler(value = {MyException.class})
public Result<?> handlerMyException(Exception exception) {
log.info("MyException异常信息:" + exception.getMessage());
return Result.fail(ResultCode.CODE_1000, exception.getMessage());
}
}
抛出异常后,会进入到@RestControllerAdvice注解的方法,过滤出和抛出异常相同的class的方法,执行相应的方法。
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception exception) {
//根据异常类型过滤方法
ServletInvocableHandlerMethod exceptionHandlerMethod = this.getExceptionHandlerMethod(handlerMethod, exception);
if (exceptionHandlerMethod == null) {
return null;
} else {
if (this.argumentResolvers != null) {
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
ArrayList<Throwable> exceptions = new ArrayList();
try {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Using @ExceptionHandler " + exceptionHandlerMethod);
}
Throwable cause;
for(Throwable exToExpose = exception; exToExpose != null; exToExpose = cause != exToExpose ? cause : null) {
exceptions.add(exToExpose);
cause = ((Throwable)exToExpose).getCause();
}
Object[] arguments = new Object[exceptions.size() + 1];
exceptions.toArray(arguments);
arguments[arguments.length - 1] = handlerMethod;
//执行方法
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, arguments);
} catch (Throwable var13) {
if (!exceptions.contains(var13) && this.logger.isWarnEnabled()) {
this.logger.warn("Failure in @ExceptionHandler " + exceptionHandlerMethod, var13);
}
return null;
}
if (mavContainer.isRequestHandled()) {
return new ModelAndView();
} else {
ModelMap model = mavContainer.getModel();
HttpStatus status = mavContainer.getStatus();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status);
mav.setViewName(mavContainer.getViewName());
if (!mavContainer.isViewReference()) {
mav.setView((View)mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes)model).getFlashAttributes();
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
return mav;
}
}
}
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(@Nullable HandlerMethod handlerMethod, Exception exception) {
Class<?> handlerType = null;
if (handlerMethod != null) {
handlerType = handlerMethod.getBeanType();
ExceptionHandlerMethodResolver resolver = (ExceptionHandlerMethodResolver)this.exceptionHandlerCache.get(handlerType);
if (resolver == null) {
resolver = new ExceptionHandlerMethodResolver(handlerType);
this.exceptionHandlerCache.put(handlerType, resolver);
}
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method, this.applicationContext);
}
if (Proxy.isProxyClass(handlerType)) {
handlerType = AopUtils.getTargetClass(handlerMethod.getBean());
}
}
//初始化的时候已经将beanType作为key,标注@ExceptionHandler的方法包装成resolve作为value放到exceptionHandlerAdviceCache中
Iterator var9 = this.exceptionHandlerAdviceCache.entrySet().iterator();
while(var9.hasNext()) {
Map.Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry = (Map.Entry)var9.next();
ControllerAdviceBean advice = (ControllerAdviceBean)entry.getKey();
if (advice.isApplicableToBeanType(handlerType)) {
ExceptionHandlerMethodResolver resolver = (ExceptionHandlerMethodResolver)entry.getValue();
//根据class进行筛选
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(advice.resolveBean(), method, this.applicationContext);
}
}
}
return null;
}
直接在service层抛出异常,controller中返回正常的结果,由标注了@RestControllerAdvice的类对异常进行处理
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/test")
public Result<Boolean> testGlobalException() {
globalException.throwException();
return Result.success(Boolean.TRUE);
}
}
以上就是详解java封装返回结果与RestControllerAdvice注解的详细内容,更多关于java RestControllerAdvice 封装返回的资料请关注编程网其它相关文章!