在本文中,您将会了解到关于Springboot2.0处理自定义异常并返回json的新资讯,同时我们还将为您解释springboot自定义异常处理没生效的相关在本文中,我们将带你探索Springboot
在本文中,您将会了解到关于Springboot2.0处理自定义异常并返回json的新资讯,同时我们还将为您解释springboot自定义异常处理没生效的相关在本文中,我们将带你探索Springboot2.0处理自定义异常并返回json的奥秘,分析springboot自定义异常处理没生效的特点,并给出一些关于java springboot 自定义异常、Spring Boot 中自定义异常怎么处理、spring boot 全局异常处理及自定义异常类、Spring Boot 全局异常捕捉,自定义异常并统一返回的实用技巧。
本文目录一览:- Springboot2.0处理自定义异常并返回json(springboot自定义异常处理没生效)
- java springboot 自定义异常
- Spring Boot 中自定义异常怎么处理
- spring boot 全局异常处理及自定义异常类
- Spring Boot 全局异常捕捉,自定义异常并统一返回
Springboot2.0处理自定义异常并返回json(springboot自定义异常处理没生效)
这篇文章主要介绍了Springboot2.0处理自定义异常并返回json,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
这篇文章主要介绍了Springboot2.0处理自定义异常并返回json,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
1. 编写自定义异常类
package cn.jfjb.crud.exception; /** * @author john * @date 2019/11/24 - 9:48 */ public class UserNotExistException extends RuntimeException { public UserNotExistException() { super("用户不存在"); } }
2. 处理自测试异常
package cn.jfjb.crud.handler; import cn.jfjb.crud.exception.UserNotExistException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; import java.util.Map; /** * @author john * @date 2019/11/24 - 10:43 */ @ControllerAdvice public class MyExceptionHandler { @ResponseBody @ExceptionHandler(UserNotExistException.class) public Map handleException(Exception e) { Map map = new HashMap(); map.put("code", "user.notexist"); map.put("message", e.getMessage()); return map; } }3. 配置application.yml文件(不配置的话无法获取exception)server: error: include-exception: true4. 编写测试package cn.jfjb.crud.controller; import cn.jfjb.crud.exception.UserNotExistException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; /** * @author john * @date 2019/11/22 - 19:38 */ @Controller public class HelloController { @RequestMapping({"/testException"}) public String testException(@RequestParam("user") String user) { if (user != "aaa") { throw new UserNotExistException(); } return "index"; } }java springboot 自定义异常
- 自定义返回result
public class CustomResult {
/**
* 状态响应码
*/
private String code;
/**
* 响应信息
*/
private String message;
/**
* 响应数据
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Object data;
/**
* 数据总数
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Long totalCount;
public CustomResult setCode(CustomResultCode customResultCode) {
this.code = customResultCode.code();
return this;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
public CustomResult setMessage(String message) {
this.message = message;
return this;
}
public Object getData() {
return data;
}
public CustomResult setData(Object data) {
this.data = data;
return this;
}
public Long getTotalCount() { return totalCount;}
public CustomResult setTotalCount(Long totalCount) {
this.totalCount = totalCount;
return this;
}
}
- 自定义错误code
public enum CustomResultCode {
Custom_SUCCESS("1"), //成功
Custom_Fail("0"); // 失败
private final String code;
CustomResultCode(String code) {
this.code = code;
}
public String code() {
return code;
}
}
- 测试
@RequestMapping("test-custom-exception")
public void testCustomException() {
throw new CustomException("自定义错误");
}
- 结果
{"code":"0","message":"自定义错误"}
代码
Spring Boot 中自定义异常怎么处理
这篇文章将为大家详细讲解有关Spring Boot 中自定义异常怎么处理,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
在 Spring Boot 项目中 ,异常统一处理,可以使用 Spring 中 @ControllerAdvice 来统一处理,也可以自己来定义异常处理方案。Spring Boot 中,对异常的处理有一些默认的策略,我们分别来看。
默认情况下,Spring Boot 中的异常页面 是这样的:
我们从这个异常提示中,也能看出来,之所以用户看到这个页面,是因为开发者没有明确提供一个 /error 路径,如果开发者提供了 /error 路径 ,这个页面就不会展示出来,不过在 Spring Boot 中,提供 /error 路径实际上是下下策,Spring Boot 本身在处理异常时,也是当所有条件都不满足时,才会去找 /error 路径。那么我们就先来看看,在 Spring Boot 中,如何自定义 error 页面,整体上来说,可以分为两种,一种是静态页面,另一种是动态页面。
静态异常页面
自定义静态异常页面,又分为两种,第一种 是使用 HTTP 响应码来命名页面,例如 404.html、405.html、500.html ....,另一种就是直接定义一个 4xx.html,表示400-499 的状态都显示这个异常页面,5xx.html 表示 500-599 的状态显示这个异常页面。
默认是在 classpath:/static/error/
路径下定义相关页面:
此时,启动项目,如果项目抛出 500 请求错误,就会自动展示 500.html 这个页面,发生 404 就会展示 404.html 页面。如果异常展示页面既存在 5xx.html,也存在 500.html ,此时,发生500异常时,优先展示 500.html 页面。
动态异常页面
动态的异常页面定义方式和静态的基本 一致,可以采用的页面模板有 jsp、freemarker、thymeleaf。动态异常页面,也支持 404.html 或者 4xx.html ,但是一般来说,由于动态异常页面可以直接展示异常详细信息,所以就没有必要挨个枚举错误了 ,直接定义 4xx.html(这里使用thymeleaf模板)或者 5xx.html 即可。
注意,动态页面模板,不需要开发者自己去定义控制器,直接定义异常页面即可 ,Spring Boot 中自带的异常处理器会自动查找到异常页面。
页面定义如下:
页面内容如下:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <Meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>5xx</h2> <table border="1"> <tr> <td>path</td> <td th:text="${path}"></td> </tr> <tr> <td>error</td> <td th:text="${error}"></td> </tr> <tr> <td>message</td> <td th:text="${message}"></td> </tr> <tr> <td>timestamp</td> <td th:text="${timestamp}"></td> </tr> <tr> <td>status</td> <td th:text="${status}"></td> </tr> </table> </body> </html>
默认情况下,完整的异常信息就是这5条,展示 效果如下 :
如果动态页面和静态页面同时定义了异常处理页面,例如 classpath:/static/error/404.html
和 classpath:/templates/error/404.html
同时存在时,默认使用动态页面。即完整的错误页面查找方式应该是这样:
发生了500错误-->查找动态 500.html 页面-->查找静态 500.html --> 查找动态 5xx.html-->查找静态 5xx.html。
自定义异常数据
默认情况下,在Spring Boot 中,所有的异常数据其实就是上文所展示出来的5条数据,这5条数据定义在 org.springframework.boot.web.reactive.error.DefaultErrorAttributes
类中,具体定义在 getErrorAttributes
方法中 :
@Override public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) { Map<String, Object> errorAttributes = new LinkedHashMap<>(); errorAttributes.put("timestamp", new Date()); errorAttributes.put("path", request.path()); Throwable error = getError(request); HttpStatus errorStatus = determineHttpStatus(error); errorAttributes.put("status", errorStatus.value()); errorAttributes.put("error", errorStatus.getReasonPhrase()); errorAttributes.put("message", determineMessage(error)); handleException(errorAttributes, determineException(error), includeStackTrace); return errorAttributes; }
DefaultErrorAttributes 类本身则是在org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration 异常自动配置类中定义的,如果开发者没有自己提供一个 ErrorAttributes 的实例的话,那么 Spring Boot 将自动提供一个ErrorAttributes 的实例,也就是 DefaultErrorAttributes 。
基于此 ,开发者自定义 ErrorAttributes 有两种方式 :
直接实现 ErrorAttributes 接口
继承 DefaultErrorAttributes(推荐),因为 DefaultErrorAttributes 中对异常数据的处理已经完成,开发者可以直接使用。
具体定义如下:
@Component public class MyErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace); if ((Integer)map.get("status") == 500) { map.put("message", "服务器内部错误!"); } return map; } }
定义好的 ErrorAttributes 一定要注册成一个 Bean ,这样,Spring Boot 就不会使用默认的 DefaultErrorAttributes 了,运行效果如下图:
自定义异常视图
异常视图默认就是前面所说的静态或者动态页面,这个也是可以自定义的,首先 ,默认的异常视图加载逻辑在 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController 类的 errorHtml 方法中,这个方法用来返回异常页面+数据,还有另外一个 error 方法,这个方法用来返回异常数据(如果是 ajax 请求,则该方法会被触发)。
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE) 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) ? modelAndView : new ModelAndView("error", model); }
在该方法中 ,首先会通过 getErrorAttributes 方法去获取异常数据(实际上会调用到 ErrorAttributes 的实例 的 getErrorAttributes 方法),然后调用 resolveErrorView 去创建一个 ModelAndView ,如果这里创建失败,那么用户将会看到默认的错误提示页面。
正常情况下, resolveErrorView 方法会来到 DefaultErrorViewResolver 类的 resolveErrorView 方法中:
@Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { ModelAndView modelAndView = resolve(String.valueOf(status.value()), model); if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) { modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); } return modelAndView; }
在这里,首先以异常响应码作为视图名分别去查找动态页面和静态页面,如果没有查找到,则再以 4xx 或者 5xx 作为视图名再去分别查找动态或者静态页面。
要自定义异常视图解析,也很容易 ,由于 DefaultErrorViewResolver 是在 ErrorMvcAutoConfiguration 类中提供的实例,即开发者没有提供相关实例时,会使用默认的 DefaultErrorViewResolver ,开发者提供了自己的 ErrorViewResolver 实例后,默认的配置就会失效,因此,自定义异常视图,只需要提供 一个 ErrorViewResolver 的实例即可:
@Component public class MyErrorViewResolver extends DefaultErrorViewResolver { public MyErrorViewResolver(ApplicationContext applicationContext, ResourceProperties resourceProperties) { super(applicationContext, resourceProperties); } @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { return new ModelAndView("/aaa/123", model); } }
实际上,开发者也可以在这里定义异常数据(直接在 resolveErrorView 方法重新定义一个 model ,将参数中的model 数据拷贝过去并修改,注意参数中的 model 类型为 UnmodifiableMap,即不可以直接修改),而不需要自定义MyErrorAttributes。定义完成后,提供一个名为123的视图,如下图:
如此之后,错误试图就算定义成功了。
关于“Spring Boot 中自定义异常怎么处理”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
spring boot 全局异常处理及自定义异常类
全局异常处理:
controller
层抛出的自定义异常时,可以实现@ControllerAdvice
注解捕获,配合@ExceptionHandler来增强所有的@requestMapping方法。
@ExceptionHandler
:统一处理某一类异常,从而能够减少代码重复率和复杂度该注解作用对象为方法,并且在运行时有效,
value()
可以指定异常类。异常参数:包括一般的异常或特定的异常(即自定义异常),如果注解没有指定异常类,会默认进行映射。
@ControllerAdvice
:异常集中处理,更好的使业务逻辑与异常处理剥离开
例如:@ExceptionHandler(Exception.class) 用来捕获@requestMapping的方法中所有抛出的exception。
代码:
@ControllerAdvice
public class GlobalDefultExceptionHandler {
//声明要捕获的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public String defultExcepitonHandler(HttpServletRequest request,Exception e) {
return “error”;
}
}
这样,全局异常处理类完毕。可以添加自己的逻辑。
然后还有一个问题,有的时候,我们需要业务逻辑时抛出自定义异常,这个时候需要自定义业务异常类。
定义class:BusinessException ,使他继承于RuntimeException.
说明:因为某些业务需要进行业务回滚。但spring的事务只针对RuntimeException的进行回滚操作。所以需要回滚就要继承RuntimeException。
public class BusinessException extends RuntimeException{
}
然后,现在来稍微完善一下这个类。
当我们抛出一个业务异常,一般需要错误码和错误信息。有助于我们来定位问题。
所以如下:
1.首先定义一个枚举类型,把错误码及错误信息,组装起来统一管理。
定义一个业务异常的枚举。
public enum ResultEnum {
CODE_200("200", ""),
CODE_400("400", "错误的请求参数"),
CODE_401("401", "没有登录"),
//CODE_402("402", "用户名或密码错误"),
CODE_403("403", "没有权限"),
//CODE_404("404", "用户不存在"),
CODE_405("405", "用户被冻结"),
//CODE_406("406", "信息重复"),
CODE_500("500", "内部服务器错误");
private Integer code;
private String msg;
ResultEnum(Integer code,String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
2.然后定义一个业务异常。
public class BusinessException extends RuntimeException{
private static final long serialVersionUID = 1L;
private Integer code; //错误码
public BusinessException() {}
public BusinessException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.code = resultEnum.getCode();
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
3.定义一个全局异常处理类:
@ControllerAdvice
public class GlobalDefultExceptionHandler {
// 根据特定的异常返回指定的 HTTP 状态码400
@ResponseStatus(value=HttpStatus.BAD_REQUEST) // 400
@ExceptionHandler(ConstraintViolationException.class)
public ModelAndView handleValidationException(ConstraintViolationException e) {
logger.error(e.getMessage(),e);
Set<ConstraintViolation<?>> errors = e.getConstraintViolations();
return ResultUtil.error(ResultEnum.CODE_400,errors.toString());
}
// 捕捉shiro的异常
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(ShiroException.class)
public ModelAndView handleShiroException(HttpServletResponse resp,HttpServletRequest req,ShiroException e) {
logger.error(e.getMessage(),e);
Object errorMassage = req.getAttribute("error"); //取出shiro异常massage
if(errorMassage !=null) { //返回jwt过滤器异常.(这里只是替换错误Massage而已)
return getRedirect(ResultUtil.error(ResultEnum.CODE_401,errors.toString()));
}
return ResultUtil.error(ResultEnum.CODE_401,errors.toString());
}
// 捕捉UnauthorizedException
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(UnauthorizedException.class)
public ModelAndView handleUnauthorizedException(HttpServletResponse resp,HttpServletRequest req,UnauthorizedException e) {
logger.error(e.getMessage(),e);
return ResultUtil.error(ResultEnum.CODE_403,errors.toString());
}
//声明要捕获的异常(自定义异常和Exception)
@ExceptionHandler(Exception.class)
@ResponseBody
public <T> Result<?> defultExcepitonHandler(HttpServletRequest request,Exception e) {
e.printStackTrace();
if(e instanceof BusinessException) {
Log.error(this.getClass(),"业务异常:"+e.getMessage());
BusinessException businessException = (BusinessException)e;
return ResultUtil.error(businessException.getCode(), businessException.getMessage());
}
//未知错误
return ResultUtil.error(-1, "系统异常:\\n"+e);
}
}
判断这个是否是业务异常。和系统异常就可以分开处理了。
Spring Boot 全局异常捕捉,自定义异常并统一返回
下面代码可直接拷在项目内运行即可,MessageResult 类为一个统一返回类
/**
* 自定义异常处理器
*
* @author 问梦杀帝
*
*/
@RestControllerAdvice
public class ExceptionController {
private static final Logger log = LoggerFactory.getLogger(ExceptionController.class);
MessageResult<String> result = new MessageResult<String>();
/**
* 请求方式不支持
*/
@ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
public MessageResult<String> handleException(HttpRequestMethodNotSupportedException e) {
log.error(e.getMessage(), e);
result.setResultCode(500);
result.setResultMessage ("不支持 ''" + e.getMethod () + "'' 请求");
return result;
}
/**
* 拦截未知的运行时异常
*/
@ExceptionHandler(RuntimeException.class)
public MessageResult<String> notFount(RuntimeException e) {
log.error ("运行时异常:", e);
result.setResultCode(500);
result.setResultMessage ("运行时异常:" + e.getMessage ());
return result;
}
/**
* 系统异常
*/
@ExceptionHandler(Exception.class)
public MessageResult<String> handleException(Exception e) {
log.error(e.getMessage(), e);
result.setResultCode(500);
result.setResultMessage ("服务器错误,请联系管理员");
return result;
}
}
关于Springboot2.0处理自定义异常并返回json和springboot自定义异常处理没生效的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于java springboot 自定义异常、Spring Boot 中自定义异常怎么处理、spring boot 全局异常处理及自定义异常类、Spring Boot 全局异常捕捉,自定义异常并统一返回等相关知识的信息别忘了在本站进行查找喔。
本文标签: