SpringBoot 处理异常的几种方法

2022-10-25 14:46:27

1. 使用 @ControllerAdvice 和 @ExceptionHandler 处理全局异常

①新建异常实体类

publicclassErrorResponse{privateString message;privateString errorTypeName;publicErrorResponse(Exception e){this(e.getClass().getName(), e.getMessage());}publicErrorResponse(String errorTypeName,String message){this.errorTypeName= errorTypeName;this.message= message;}......省略getter/setter方法}

②自定义异常类型
一般我们处理的都是 RuntimeException ,所以如果你需要自定义异常类型的话直接集成这个类就可以了。

publicclassResourceNotFoundExceptionextendsRuntimeException{privateString message;publicResourceNotFoundException(){super();}publicResourceNotFoundException(String message){super(message);this.message= message;}@OverridepublicStringgetMessage(){return message;}publicvoidsetMessage(String message){this.message= message;}}

③新建异常处理类
我们只需要在类上加上@ControllerAdvice注解这个类就成为了全局异常处理类,当然你也可以通过 assignableTypes指定特定的 Controller 类,让异常处理类只处理特定类抛出的异常。

@ControllerAdvice(assignableTypes={ExceptionController.class})@ResponseBodypublicclassGlobalExceptionHandler{ErrorResponse illegalArgumentResponse=newErrorResponse(newIllegalArgumentException("参数错误!"));ErrorResponse resourseNotFoundResponse=newErrorResponse(newResourceNotFoundException("Sorry, the resourse not found!"));@ExceptionHandler(value=Exception.class)// 拦截所有异常, 这里只是为了演示,一般情况下一个方法特定处理一种异常publicResponseEntity<ErrorResponse>exceptionHandler(Exception e){if(einstanceofIllegalArgumentException){returnResponseEntity.status(400).body(illegalArgumentResponse);}elseif(einstanceofResourceNotFoundException){returnResponseEntity.status(404).body(resourseNotFoundResponse);}returnnull;}}

ResponseEntity 可以定义返回的HttpStatus(状态码)和HttpHeaders(消息头:请求头和响应头)。

ResponseEntity的优先级高于@ResponseBody。
在不是ResponseEntity的情况下才去检查有没有@ResponseBody注解。如果响应类型是ResponseEntity可以不写@ResponseBody注解,写了也没有关系。

简单的说
@ResponseBody可以直接返回Json结果,
@ResponseEntity不仅可以返回json结果,还可以定义返回的HttpHeaders和HttpStatus。

④controller模拟抛出异常

@RestController@RequestMapping("/api")publicclassExceptionController{@GetMapping("/illegalArgumentException")publicvoidthrowException(){thrownewIllegalArgumentException();}@GetMapping("/resourceNotFoundException")publicvoidthrowException2(){thrownewResourceNotFoundException();}}

2.@ExceptionHandler 处理 Controller 级别的异常(使用的比较少)

@ExceptionHandler(value=Exception.class)// 拦截所有异常publicResponseEntity<ErrorResponse>exceptionHandler(Exception e){if(einstanceofIllegalArgumentException){returnResponseEntity.status(400).body(illegalArgumentResponse);}elseif(einstanceofResourceNotFoundException){returnResponseEntity.status(404).body(resourseNotFoundResponse);}returnnull;}

3.ResponseStatusException

通过 ResponseStatus注解简单处理异常的方法(将异常映射为状态码)。

ResponseStatusException 提供了三个构造方法:

publicResponseStatusException(HttpStatus status){this(status,null,null);}publicResponseStatusException(HttpStatus status,@NullableString reason){this(status, reason,null);}publicResponseStatusException(HttpStatus status,@NullableString reason,@NullableThrowable cause){super(null, cause);Assert.notNull(status,"HttpStatus is required");this.status= status;this.reason= reason;}
@GetMapping("/resourceNotFoundException2")publicvoidthrowException3(){thrownewResponseStatusException(HttpStatus.NOT_FOUND,"Sorry, the resourse not found!",newResourceNotFoundException());}

在这里插入图片描述

4.实现WebMvcConfigurer 接口,增加异常处理器

importcom.alibaba.fastjson.JSON;importcom.scaffold.test.base.Result;importcom.scaffold.test.base.ResultCode;importcom.scaffold.test.base.ServiceException;importcom.scaffold.test.config.interceptor.AuthenticationInterceptor;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.validation.BindingResult;importorg.springframework.validation.ObjectError;importorg.springframework.web.bind.MethodArgumentNotValidException;importorg.springframework.web.method.HandlerMethod;importorg.springframework.web.servlet.HandlerExceptionResolver;importorg.springframework.web.servlet.ModelAndView;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;importjava.util.List;/**
 * @author alex
 */@ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer{privatefinalLogger logger=LoggerFactory.getLogger(WebMvcConfigurer.class);/**
     * 统一异常处理
     *
     * @param exceptionResolvers
     */@OverridepublicvoidconfigureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers){
        exceptionResolvers.add((request, response, handler, e)->{Result result=newResult();// 异常处理// 参数异常判断if(einstanceofBindingResult|| einstanceofMethodArgumentNotValidException){StringBuilder errorMessage=newStringBuilder();List<ObjectError> allErrors;if(einstanceofBindingResult){
                    allErrors=((BindingResult) e).getAllErrors();}else{BindingResult bindingResult=((MethodArgumentNotValidException) e).getBindingResult();
                    allErrors= bindingResult.getAllErrors();}for(int i=0; i< allErrors.size(); i++){
                    errorMessage.append(allErrors.get(i).getDefaultMessage());if(i!= allErrors.size()-1){
                        errorMessage.append(",");}}
                result.setCode(ResultCode.FAIL).setMessage(errorMessage.toString());
                logger.error(errorMessage.toString());}elseif(einstanceofServiceException){// 1、业务失败的异常,如“账号或密码错误”
                result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
                logger.info(e.getMessage());}elseif(einstanceofServletException){// 2、调用失败
                result.setCode(ResultCode.FAIL).setMessage(e.getMessage());}else{// 3、内部其他错误
                result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 ["+ request.getRequestURI()+"] 内部错误,请联系管理员");String message;if(handlerinstanceofHandlerMethod){HandlerMethod handlerMethod=(HandlerMethod) handler;
                    message=String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
                            request.getRequestURI(),
                            handlerMethod.getBean().getClass().getName(),
                            handlerMethod.getMethod().getName(),
                            e.getMessage());}else{
                    message= e.getMessage();}
                result.setMessage(message);
                logger.error(message, e);}responseResult(response, result);returnnewModelAndView();});}// 处理响应数据格式privatevoidresponseResult(HttpServletResponse response,Result result){
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type","application/json;charset=UTF-8");
        response.setStatus(200);try{
            response.getWriter().write(JSON.toJSONString(result));}catch(IOException ex){
            logger.error(ex.getMessage());}}}
  • 作者:南风知易✓✓✓
  • 原文链接:https://blog.csdn.net/tianynnb/article/details/123847604
    更新时间:2022-10-25 14:46:27