欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot错误处理机制以及自定义异常处理详解

程序员文章站 2024-02-25 14:50:57
上篇文章我们讲解了使用hibernate validation来校验数据,当校验完数据后,如果发生错误我们需要给客户返回一个错误信息,因此这节我们来讲解一下springbo...

上篇文章我们讲解了使用hibernate validation来校验数据,当校验完数据后,如果发生错误我们需要给客户返回一个错误信息,因此这节我们来讲解一下springboot默认的错误处理机制以及如何自定义异常来处理请求错误。

一、springboot默认的错误处理机制

我们在发送一个请求的时候,如果发生404 springboot会怎么处理呢?我们来发送一个不存在的请求来验证一下看看页面结果。如下所示:

SpringBoot错误处理机制以及自定义异常处理详解

当服务器内部发生错误的时候,页面会返回什么呢?

 @getmapping("/user/{id:\\d+}")
 public user get(@pathvariable string id) {
  throw new runtimeexception();
 }

SpringBoot错误处理机制以及自定义异常处理详解

我们会发现无论是发生什么错误,springboot都会返回一个状态码以及一个错误页面,这个错误页面是怎么来的呢?
我们来看看springboot错误处理模块的源码就会非常清楚,默认的发生错误,它会将请求转发到basicerrorcontroller控制器来处理请求,下面是该controller类的源码:

@controller
@requestmapping("${server.error.path:${error.path:/error}}")
public class basicerrorcontroller extends abstracterrorcontroller {

 private final errorproperties errorproperties;

 /**
  * create a new {@link basicerrorcontroller} instance.
  * @param errorattributes the error attributes
  * @param errorproperties configuration properties
  */
 public basicerrorcontroller(errorattributes errorattributes,
   errorproperties errorproperties) {
  this(errorattributes, errorproperties,
    collections.<errorviewresolver>emptylist());
 }

 /**
  * create a new {@link basicerrorcontroller} instance.
  * @param errorattributes the error attributes
  * @param errorproperties configuration properties
  * @param errorviewresolvers error view resolvers
  */
 public basicerrorcontroller(errorattributes errorattributes,
   errorproperties errorproperties, list<errorviewresolver> errorviewresolvers) {
  super(errorattributes, errorviewresolvers);
  assert.notnull(errorproperties, "errorproperties must not be null");
  this.errorproperties = errorproperties;
 }

 @override
 public string geterrorpath() {
  return this.errorproperties.getpath();
 }

 @requestmapping(produces = "text/html")
 public modelandview errorhtml(httpservletrequest request,
   httpservletresponse response) {
  httpstatus status = getstatus(request);
  map<string, object> model = collections.unmodifiablemap(geterrorattributes(
    request, isincludestacktrace(request, mediatype.text_html)));
  response.setstatus(status.value());
  modelandview modelandview = resolveerrorview(request, response, status, model);
  return (modelandview == null ? new modelandview("error", model) : modelandview);
 }

 @requestmapping
 @responsebody
 public responseentity<map<string, object>> error(httpservletrequest request) {
  map<string, object> body = geterrorattributes(request,
    isincludestacktrace(request, mediatype.all));
  httpstatus status = getstatus(request);
  return new responseentity<map<string, object>>(body, status);
 }

从上面的源码我们可以看到,它有两个requestmapping方法来映射错误请求,为什么会是两个呢?其实errorhtml方法映射的是浏览器发送来的请求,而error方法映射的是不是浏览器而是其他软件app客户端发送的错误请求。

看了上面的源码后,我们是否可以自己定义404或者500的错误页面返回给客户端呢?当然可以,我们可以在src/main/resources路径下新建文件夹reources/error文件夹,然后新建404.html和500.html然后编写自己的错误内容即可:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>404</title>
</head>
<body>
 亲,您所访问的页面不存在
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>500</title>
</head>
<body>
 服务器内部错误
</body>
</html>

不过注意的是上面的这种自定义页面的方式只在浏览器端有效,而不是浏览器发送的请求不会生效。因此下面我们就讲一下如何自定义异常处理来解决这个问题。

二、自定义异常处理

怎么自定义异常处理客户端发送的错误信息呢?如果我们查询一个用户,该用户不存在,我们是否可以将不存在的用户的id返回给客户呢?这样的效果不是给客户更好地体验吗?下面我们来实现这个功能。
首先我们需要编写一个exception类继承runtimeexception类:

package cn.shinelon.exception;

/**
 * @author shinelon
 *
 */
public class usernotexistexception extends runtimeexception{

 /**
  * 
  */
 private static final long serialversionuid = 1l;
 private string id;
 public usernotexistexception(string id) {
  super("user not exist");
  this.id=id;
 }
public void setid(string id) {
 this.id = id;
}
public string getid() {
 return id;
}
}

接着我们需要编写一个handler类处理controller层抛出的异常:

/**
 * 
 */
package cn.shinelon.exception;

import java.util.hashmap;
import java.util.map;

import org.springframework.http.httpstatus;
import org.springframework.web.bind.annotation.controlleradvice;
import org.springframework.web.bind.annotation.exceptionhandler;
import org.springframework.web.bind.annotation.responsebody;
import org.springframework.web.bind.annotation.responsestatus;

/**
 * 控制器的异常处理类
 * @author shinelon
 *
 */
//这个注解是指这个类是处理其他controller抛出的异常
@controlleradvice
public class controllerexceptionhandler {

 //这个注解是指当controller中抛出这个指定的异常类的时候,都会转到这个方法中来处理异常
 @exceptionhandler(usernotexistexception.class)
 //将返回的值转成json格式的数据
 @responsebody
 //返回的状态码
 @responsestatus(value=httpstatus.internal_server_error)  //服务内部错误
 public map<string,object> handlerusernotexistexception(usernotexistexception ex){
  map<string,object> result=new hashmap<string,object>();
  result.put("id", ex.getid());
  result.put("message", ex.getmessage());
  return result;
 }
}

这个类加上@controlleradvice注解将会处理controller层抛出的对应的异常,这里我们处理controller抛出的usernotexistexception自定义异常,并且将错误信息以及用户id以json串的格式返回给客户。

接着,我们在controller的请求方法中抛出这个异常,会看到在浏览器中的异常是我们自定义的异常返回的json数据。

controller层代码:

@getmapping("/user/{id:\\d+}")
 //@requestmapping(value="/user/{id:\\d+}",method=requestmethod.get)
 @jsonview(user.detailjsonview.class)
 public user get(@pathvariable string id) {
  throw new usernotexistexception(id);
 }

SpringBoot错误处理机制以及自定义异常处理详解

到这里,我们就介绍了springboot默认的错误处理机制以及我们自定义异常来处理错误请求,这更有利于我们的开发,带给用户更佳的使用效果。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。