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

以上是 SpringBoot错误处理机制以及自定义异常处理详解 的全部内容, 来源链接: utcz.com/z/328555.html

回到顶部