前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >知识点-Spring Boot 统一异常处理汇总

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

作者头像
猿天地
发布2018-07-25 17:35:14
8370
发布2018-07-25 17:35:14
举报
文章被收录于专栏:猿天地猿天地
在实际开发中,我们会遇到很多异常,在发生异常的时候Spring Boot默认提供了错误页面展示给用户。看似比较友好,其实页面很丑。

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

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

页面处理

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

1.png

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

2.png

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

代码语言:javascript
复制
<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/view/404.jsp</location>
</error-page>
<error-page>
    <error-code>400</error-code>
    <location>/WEB-INF/view/400.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/view/500.jsp</location>
</error-page>

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

代码语言:javascript
复制
/**
 * 自定义错误页面覆盖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";
    }
}

页面内容可以自己写:

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

REST接口处理

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

代码语言:javascript
复制
{
  "status": true,
  "code": 200,
  "message": null,
  "data": [
    {
      "id": "101",
      "name": "jack"
    },
    {
      "id": "102",
      "name": "jason"
    }
  ]
}

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

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

定义一个异常处理类

代码语言:javascript
复制
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是我们返回格式的实体类

代码语言:javascript
复制
public class ResponseData {
    private Boolean status = true;
    private int code = 200;
    private String message;
    private Object data;
}

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

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

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

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

代码语言:javascript
复制
{
  "status": false,
  "code": 404,
  "message": "No handler found for GET /rest11/auth",
  "data": null
}

页面错误和REST错误共存

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

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

代码语言:javascript
复制
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";
            }
        }
    }
}

推荐阅读:

  • 《Spring Boot 1.X和2.X优雅重启实战》
  • 《Spring Boot中快速操作Mongodb》
  • 《Spring JdbcTemplate的升级版》

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 猿天地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 页面处理
  • REST接口处理
  • 页面错误和REST错误共存
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档