分享

知识点-Spring Boot 统一异常处理汇总

 太极混元天尊 2018-05-24

在实际开发中,我们会遇到很多异常,在发生异常的时候Spring Boot默认提供了错误页面展示给用户。看似比较友好,其实页面很丑。

上面讲的是做页面开发的时候遇到的问题,还有一种情况就是用来开发Rest接口,当错误的时候我们希望返回给用户的是我们接口的标准格式,不是返回一段html代码。

接下来分别给大家介绍下解决方案:

页面处理

首先我们来看页面错误的处理情况,当我们的程序内部报错的时候或者访问的页面找不到的时候,我们可以看到下面的错误页面:

1.png

我们可以自己设计好看一点的页面来替换这个页面,这样会更友好点,比如我们看今日头条的页面:

2.png

以前用Spring MVC时都是直接配置web.xml

error-page>
   error-code>404error-code>
   location>/WEB-INF/view/404.jsplocation>
error-page>
error-page>
   error-code>400error-code>
   location>/WEB-INF/view/400.jsplocation>
error-page>
error-page>
   error-code>500error-code>
   location>/WEB-INF/view/500.jsplocation>
error-page>

在Spring Boot中也非常简单,直接编写对应的错误页面,进行覆盖即可:

/**
* 自定义错误页面覆盖spring boot中的错误页面
* @author yinjihuan
*
*/

@Controller
public class ErrorController {
   @GetMapping('/400')
   public String badRequest() {
       return 'error/400';
   }
   @GetMapping('/404')
   public String notFound() {
       return 'error/404';
   }
   @GetMapping('/500')
   public String serverError() {
       return 'error/500';
   }
}

页面内容可以自己写:

body>
   section id='error' class='container text-center' style='height:800px;'>
       h1>404, 页面没有找到h1>
       p>您正在寻找的页面不存在或发生其他错误。p>
       a class='btn btn-primary' href='http://pan.'>回到网站首页a>
   section>
body>

REST接口处理

在开发rest接口时,我们往往会定义统一的返回格式,列如:

{
 'status': true,
 'code': 200,
 'message': null,
 'data': [
   {
     'id': '101',
     'name': 'jack'
   },
   {
     'id': '102',
     'name': 'jason'
   }
 ]
}


但是如果调用方请求我们的api时把接口地址写错了,就会得到一个404错误页面,最友好的方式就是返回固定的JSON格式,里面有个code为404。

所以我们需要在发生这种系统错误时也能返回我们自定义的那种格式

定义一个异常处理类

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class GlobalExceptionHandler {
   private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
   /**
    * 系统异常处理,比如:404,500
    * @param req
    * @param resp
    * @param e
    * @return
    * @throws Exception
    */

   @ExceptionHandler(value = Exception.class)
   @ResponseBody
   public ResponseData defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
       logger.error('', e);
       ResponseData r = new ResponseData();
       r.setMessage(e.getMessage());
       if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
            r.setCode(404);
       } else {
            r.setCode(500);
       }
       r.setData(null);
       r.setStatus(false);
       return r;
   }
}

ResponseData是我们返回格式的实体类

public class ResponseData {
   private Boolean status = true;
   private int code = 200;
   private String message;
   private Object data;
}

这种在发生错误时这边会捕获到,然后封装好返回格式,返回给调用方

最后关键的一步是在spring boot的配置文件中加上如下配置:

#出现错误时, 直接抛出异常
spring.mvc.throw-exception-if-no-handler-found=true
#不要为我们工程中的资源文件建立映射
spring.resources.add-mappings=false

然后我们调用一个不存在的接口时,返回的错误信息就是我们自定义的那种格式了

{
 'status': false,
 'code': 404,
 'message': 'No handler found for GET /rest11/auth',
 'data': null
}

页面错误和REST错误共存

当我们加好rest接口处理的方式后,访问页面不存在就会返回一段json数据,如果你的项目中既有rest接口,又有页面,这个时候就有冲突了。

我们可以通过为rest接口增加统一的访问前缀,比如:/rest/xxxx来区分请求,然后用@ControllerAdvice来分别处理:

import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
   private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
   /**
    * 系统异常处理,比如:404,500
    *
    * @param req
    * @param resp
    * @param e
    * @return
    * @throws Exception
    */

   @ExceptionHandler(value = Exception.class)
   // @ResponseBody
   public Object defaultErrorHandler(HttpServletRequest req, HttpServletResponse response, Exception e)
           throws Exception {
       logger.error('', e);
       if (req.getRequestURI().startsWith('/rest')) {
           ResponseData r = new ResponseData();
           r.setMessage(e.getMessage());
           if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
               r.setCode(404);
           } else {
               r.setCode(500);
           }
           r.setData(null);
           r.setStatus(false);
           PrintWriter writer = response.getWriter();
           writer.println(JsonUtils.toJson(r));
           writer.flush();
           writer.close();
           return null;
       } else {
           if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
               return 'error/404';
           } else {
               return 'error/500';
           }
       }
   }
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多