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

 更新时间:2019年05月06日 11:46:09   作者:不清不慎  
这篇文章主要为大家详细介绍了SpringBoot错误处理机制以及自定义异常处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

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

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

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

 @GetMapping("/user/{id:\\d+}")
 public User get(@PathVariable String id) {
  throw new RuntimeException();
 }

我们会发现无论是发生什么错误,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默认的错误处理机制以及我们自定义异常来处理错误请求,这更有利于我们的开发,带给用户更佳的使用效果。

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

相关文章

  • @CacheEvict + redis实现批量删除缓存

    @CacheEvict + redis实现批量删除缓存

    这篇文章主要介绍了@CacheEvict + redis实现批量删除缓存方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Java 从Set里面取出有序的记录详解及实例

    Java 从Set里面取出有序的记录详解及实例

    这篇文章主要介绍了Java 从Set里面取出有序的记录详解及实例的相关资料,需要的朋友可以参考下
    2017-06-06
  • SpringBoot枚举类型参数认证的实现代码

    SpringBoot枚举类型参数认证的实现代码

    项目当中经常需要接口参数是否在一个可选的范围内,也就是验证类枚举参数的需求,所以本文我们将使用SpringBoot实现枚举类型参数认证,文中有详细的代码示例,需要的朋友可以参考下
    2023-12-12
  • spring集成httpclient配置的详细过程

    spring集成httpclient配置的详细过程

    spring框架是一个非常强大的框架这里就不多说了,那么主要是介绍spring与httpclient的整合集成过程,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • IntelliJ IDEA 2022.2最新版本激活教程(亲测可用版)永久激活工具分享

    IntelliJ IDEA 2022.2最新版本激活教程(亲测可用版)永久激活工具分享

    Jetbrains官方发布了 IntelliJ IDEA2022.2 正式版,每次大的版本更新,都会有较大的调整和优化,除本次更新全面拥抱 Java 17 外,还有对IDE UI界面,安全性,便捷性等都做了调整和优化完善,用户体验提升不少,相信后面会有不少小伙伴跟着更新
    2022-08-08
  • Spring Boot使用Druid连接池的示例代码

    Spring Boot使用Druid连接池的示例代码

    Druid是Java语言中最好的数据库连接池。这篇文章主要介绍了Spring Boot使用Druid连接池的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • java实现简易连连看小游戏

    java实现简易连连看小游戏

    这篇文章主要为大家详细介绍了java实现简易连连看小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • java使用Feign实现声明式Restful风格调用

    java使用Feign实现声明式Restful风格调用

    这篇文章主要为大家详细介绍了java使用Feign实现声明式Restful风格调用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • 详解Java实践之抽象工厂模式

    详解Java实践之抽象工厂模式

    抽象工厂模式用于产品族的构建。抽象工厂是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象
    2021-06-06
  • Java成员变量与局部变量(动力节点Java学院整理)

    Java成员变量与局部变量(动力节点Java学院整理)

    这篇文章主要介绍了Java成员变量与局部变量的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-04-04

最新评论