SpringBoot全局异常处理方式

目录
  • SpringBoot全局异常处理
  • springboot全局异常处理——@ControllerAdvice+ExceptionHandler
    • 一、全局捕获异常后,返回json给浏览器
    • 二、全局捕获异常后,返回页面给浏览器

SpringBoot全局异常处理

为了让客户端能有一个更好的体验,当客户端发送请求到服务端发生错误时服务端应该明确告诉客户端错误信息。

SpringBoot内置的异常处理返回的界面太杂乱,不够友好。我们需要将异常信息做封装处理响应给前端。本文介绍的为将错误信息统一封装成如下格式json响应给前端。

{
	code:10001,
	message:xxxxx,
	request:GET url
}

自定义异常类

package com.lin.missyou.exception;
public class HttpException extends RuntimeException{
    protected Integer code;
    protected Integer httpStatusCode;
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public Integer getHttpStatusCode() {
        return httpStatusCode;
    }
    public void setHttpStatusCode(Integer httpStatusCode) {
        this.httpStatusCode = httpStatusCode;
    }
}
package com.lin.missyou.exception;
public class NotFoundException extends HttpException{
    public NotFoundException(int code){
        this.httpStatusCode = 404;
        this.code = code;
    }
}
package com.lin.missyou.exception;
public class ForbiddenException extends HttpException{
    public ForbiddenException(int code){
        this.httpStatusCode = 403;
        this.code = code;
    }
}

创建一个用于封装异常信息的类UnifyResponse

package com.lin.missyou.core;
public class UnifyResponse {
    private int code;
    private String message;
    private String request;
    public int getCode() {
        return code;
    }
    public String getMessage() {
        return message;
    }
    public String getRequest() {
        return request;
    }
    public UnifyResponse(int code, String message, String request) {
        this.code = code;
        this.message = message;
        this.request = request;
    }
}

将异常信息写在配置文件exception-code.properties里

lin.codes[10000] = 通用异常
lin.codes[10001] = 通用参数错误

自定义配置类管理配置文件

package com.lin.missyou.core.configuration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@PropertySource(value="classpath:config/exception-code.properties")
@ConfigurationProperties(prefix = "lin")
@Component
public class ExceptionCodeConfiguration {
    private Map<Integer,String> codes = new HashMap<>();
    public Map<Integer, String> getCodes() {
        return codes;
    }
    public void setCodes(Map<Integer, String> codes) {
        this.codes = codes;
    }
    public String getMessage(int code) {
        String message = codes.get(code);
        return message;
    }
}

创建一个全局异常处理类GlobalExceptionAdvice,用@ControllerAdvice标明异常处理类。@ResponseStatus用于指定http状态码。

@ExceptionHandler标明异常处理器,传入参数指定当前函数要处理哪种类型的异常。Springboot会帮我们把这些异常信息传入到函数。第一个函数用于处理未知异常,不需要向前端提供详细的错误原因,只需提示统一的文本信息即可。

第二个函数用于处理已知异常,需要指明具体的错误原因,需要根据Exception传递过来的信息灵活的定制httpStatusCode。ResponseEntity可以自定义很多属性,包括可以设置httpheaders,httpbodys,httpStatus。

package com.lin.missyou.core;
import com.lin.missyou.core.config.ExceptionCodeConfiguration;
import com.lin.missyou.exception.HttpException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
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;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
@ControllerAdvice
public class GlobalExceptionAdvice {
    @Autowired
    ExceptionCodeConfiguration exceptionCodeConfiguration ;
    @ExceptionHandler(Exception.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public UnifyResponse handleException(HttpServletRequest req,Exception e){
        String method = req.getMethod();
        String requestUrl = req.getRequestURI();
        System.out.println(e);
        UnifyResponse unifyResponse = new UnifyResponse(9999,"服务器错误",method+" "+requestUrl);
        return unifyResponse;
    }
    @ExceptionHandler(HttpException.class)
    public ResponseEntity<UnifyResponse> handleHttpException(HttpServletRequest req, HttpException e){
        String method = req.getMethod();
        String requestUrl = req.getRequestURI();
        System.out.println(e);
        UnifyResponse unifyResponse = new UnifyResponse(e.getCode(),exceptionCodeConfiguration.getMessage(e.getCode()),method+" "+requestUrl);
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpStatus httpStatus = HttpStatus.resolve(e.getHttpStatusCode());
        ResponseEntity<UnifyResponse> responseEntity = new ResponseEntity(unifyResponse,httpHeaders,httpStatus);
        return responseEntity;
    }
    //参数校验
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public UnifyResponse handleBeanValidation(HttpServletRequest req, MethodArgumentNotValidException e){
        String method = req.getMethod();
        String requestUrl = req.getRequestURI();
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        String message = formatAllErrorMessages(errors);
        return new UnifyResponse(10001,message,method+" "+requestUrl);
    }
    private String formatAllErrorMessages(List<ObjectError> errors){
        StringBuffer errorMsg = new StringBuffer();
        errors.forEach(error ->
                errorMsg.append(error.getDefaultMessage()).append(";")
        );
        return errorMsg.toString();
    }
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public UnifyResponse handleConstrainException(HttpServletRequest req, ConstraintViolationException e){
        String method = req.getMethod();
        String requestUrl = req.getRequestURI();
        String message = e.getMessage();
        return new UnifyResponse(10001,message,method+" "+requestUrl);
    }
}

响应信息可能会出现乱码现象,修改配置文件编码。在设置面板搜索File Encodings,Default encoding for properties files选择UTF-8,勾选Transparent native-to-ascii conversion

springboot全局异常处理——@ControllerAdvice+ExceptionHandler

一、全局捕获异常后,返回json给浏览器

项目结构:

1、自定义异常类 MyException.java

package com.gui.restful;
/**
 * 自定义异常类
 */
public class MyException extends RuntimeException{
    private String code;
    private String msg;
    public MyException(String code,String msg){
        this.code=code;
        this.msg=msg;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

2、控制器 MyController.java

package com.gui.restful;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
 * controller抛出异常
 */
@RestController
public class MyController {
    @RequestMapping("hello")
    public String hello() throws Exception{
        throw new MyException("101","系统异常");
    }
}

3、全局异常处理类 MyControllerAdvice

package com.gui.restful;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
/**
 * 全局异常捕获处理
 */
@ControllerAdvice //controller增强器
public class MyControllerAdvice {
    @ResponseBody
    @ExceptionHandler(value=MyException.class) //处理的异常类型
    public Map myExceptionHandler(MyException e){
        Map<String,String> map=new HashMap<>();
        map.put("code",e.getCode());
        map.put("msg",e.getMsg());
        return map;
    }
}

4、运行结果

启动应用,访问 http://localhost:8080/hello,出现以下结果,说明自定义异常被成功拦截

二、全局捕获异常后,返回页面给浏览器

1、自定义异常类 MyException.java(同上)

2、控制器 MyController.java(同上)

3、全局异常处理类 MyControllerAdvice

package com.gui.restful;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.util.HashMap;
import java.util.Map;
/**
 * 全局异常捕获处理
 */
@ControllerAdvice //controller增强器
public class MyControllerAdvice {
    @ExceptionHandler(value=MyException.class) //处理的异常类型
    public ModelAndView myExceptionHandler(MyException e){
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("code",e.getCode());
        modelAndView.addObject("msg",e.getMsg());
        return modelAndView;
    }
}

4、页面渲染 error.ftl(用freemarker渲染)

pom.xml中引入freemarker依赖

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>

error.ftl

<!DOCTYPE>
<html>
<head>
<title>错误页面</title>
</head>
<body>
<h1>code:$[code]</h1>
<h1>msg:${msg}</h1>
</body>
</html>

5、运行结果

启动应用,访问 http://localhost:8080/hello,出现以下结果,说明自定义异常被成功拦截

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot配置系统全局异常映射处理

    目录 一.异常分类 1.业务异常 2.系统异常 二.解决应用启动后404界面 1.引入页面Jar包 2.自定义首页接口 3.首页界面 4.运行效果 三.SpringBoot2.0中异常处理 1.项目结构图 2.自定义业务异常类 3.自定义异常描述对象 4.统一异常处理格式 5.简单的测试接口 四.源代码地址 一.异常分类 这里的异常分类从系统处理异常的角度看,主要分类两类:业务异常和系统异常. 1.业务异常 业务异常主要是一些可预见性异常,处理业务异常,用来提示用户的操作,提高系统的可操作性.

  • Java Springboot全局异常处理

    目录 前言 一.思路? 二.步骤 1.自定义接口: 2.自定义错误枚举 3.自定义异常类 4.异常捕获 5.在代码中抛异常 总结 前言 对于作为菜鸟程序员的我来说,经常在controller使用try-catch 来包裹住我的service层代码,首页,他及其的不好看,其次,每个方法都有这种代码块,思考有没有办法去掉它,并且优雅的处理异常.这就是今天要说的全局异常捕获 提示:以下是本篇文章正文内容,下面案例可供参考 一.思路? springboot提供了全局异常处理的注解,我们需要弄明白的是.扑

  • SpringBoot搭建全局异常拦截

    1.异常拦截类的创建 package com.liqi.web.core.exception; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestControllerAdvice; import

  • SpringBoot项目优雅的全局异常处理方式(全网最新)

    前言 在日常项目开发中,异常是常见的,但是如何更高效的处理好异常信息,让我们能快速定位到BUG,是很重要的,不仅能够提高我们的开发效率,还能让你代码看上去更舒服,SpringBoot的项目已经对有一定的异常处理了,但是对于我们开发者而言可能就不太合适了,因此我们需要对这些异常进行统一的捕获并处理. 一.全局异常处理方式一 SpringBoot中,@ControllerAdvice 即可开启全局异常处理,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用@ExceptionHandl

  • springboot框架的全局异常处理方案详解

    系统框架搭建的前期过程中,为了约束代码规范,我们会对一些通用功能做一些处理,比如声明一些系统公用错误类.封装通用返回结果.统一异常处理等,这样做的优势是团队开发过程中能够形成统一的代码规范,增强代码可读性,同时又便于后期代码维护.本文主要介绍下框架中异常的处理: 1.声明全局异常处理类,并添加@ControllerAdvice和@RestController注解 代码如下: @ControllerAdvice @RestController public class GlobalExceptio

  • SpringBoot中如何统一接口返回与全局异常处理详解

    目录 背景 统一接口返回 定义API返回码枚举类 定义正常响应的API统一返回体 定义异常响应的API统一返回体 编写包装返回结果的自定义注解 定义返回结果拦截器 WebMvc配置类拦截器注册者添加返回结果拦截器 编写响应体处理器 接口调用 测试结果 全局异常处理 编写自定义异常基类 编写自定义业务异常类 定义全局异常处理类 接口调用 测试结果 总结 背景 在分布式.微服务盛行的今天,绝大部分项目都采用的微服务框架,前后端分离方式.前端和后端进行交互,前端按照约定请求URL路径,并传入相关参数,

  • SpringBoot配置GlobalExceptionHandler全局异常处理器案例

    1. 创建全局异常处理器类GlobalExceptionHandler @ControllerAdvice: 定义统一的异常处理类,捕获 Controller 层抛出的异常.如果添加 @ResponseBody 返回信息则为JSON格式,这样就不必在每个Controller中逐个定义AOP去拦截处理异常. @RestControllerAdvice: 相当于 @ControllerAdvice 与 @ResponseBody 的结合体. @ExceptionHandler: 统一处理一种类的异常

  • SpringBoot全局异常处理方式

    目录 SpringBoot全局异常处理 springboot全局异常处理--@ControllerAdvice+ExceptionHandler 一.全局捕获异常后,返回json给浏览器 二.全局捕获异常后,返回页面给浏览器 SpringBoot全局异常处理 为了让客户端能有一个更好的体验,当客户端发送请求到服务端发生错误时服务端应该明确告诉客户端错误信息. SpringBoot内置的异常处理返回的界面太杂乱,不够友好.我们需要将异常信息做封装处理响应给前端.本文介绍的为将错误信息统一封装成如下

  • springboot 全局异常处理和统一响应对象的处理方式

    目录 springboot异常处理 SpringBoot 默认的异常处理机制 SpringBoot 全局异常处理 1. 局部异常处理 2. 全局异常处理 自定义异常 统一响应对象 定义统一的响应对象 枚举信息 响应对象 springboot异常处理 SpringBoot 默认的异常处理机制 默认情况,SpringBoot 提供两种不同响应方式 一种是浏览器客户端请求一个不存在的页面或服务端异常时,SpringBoot默认会响应一个html 另一种是使用postman等调试工具请求不存在的url或

  • SpringBoot全局异常处理与定制404页面的方法

    一.错误处理原理分析 使用SpringBoot创建的web项目中,当我们请求的页面不存在(http状态码为404),或者器发生异常(http状态码一般为500)时,SpringBoot就会给我们返回错误信息. 也就是说,在SpringBoot的web项目中,会自动创建一个/error的错误接口,来返回错误信息.但是针对不同的访问方式,会有以下两种不同的返回信息.这主要取决于你访问时的http头部信息的Accept这个值来指定你可以接收的类型有哪些 使用浏览器访问时的头信息及其返回结果 Accep

  • springboot全局异常处理代码实例

    这篇文章主要介绍了springboot全局异常处理代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言: 开发中异常的处理必不可少,常用的就是 throw 和 try catch,这样一个项目到最后会出现很多冗余的代码,使用全局异常处理避免过多冗余代码. 全局异常处理: 1.pom 依赖(延续上一章代码): <dependencies> <!-- Spring Boot Web 依赖 --> <!-- Web 依赖

  • SpringBoot全局异常处理方案分享

    目录 一 业务场景 二 全局系统异常类 一)全局系统异常类 二) 包装异常返回结果给前端,修改自定义异常 三 返回案例 一 业务场景 调用接口时需要对属性进行校验,比如属性长度,当属性为邮箱时校验邮箱格式等,这时候要要用到@Validated注解,在使用这个注解后发现出现了一个问题,调用接口后并没有返回我们想要的报错结果,而是返回了 "message": "Validation failed for object='IMMessageSend'. Error count: 1

  • springboot全局异常处理详解

    一.单个controller范围的异常处理 package com.xxx.secondboot.web; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import

  • SpringBoot学习之全局异常处理设置(返回JSON)

    SpringBoot学习--全局异常处理设置(返回JSON) 需求 现在习惯使用ajax的方式发起请求,所以经常需要服务端返回一个json或者字符串. 控制全局的异常处理. 如果在单个方法中使用try,catch把方法包裹起来,工作量大,而且会异常的抛出而导致@Transactional注解的方法事务不会回滚. 说明 使用@ControllerAdvice注解 使用@ExceptionHandler注解 @ControllerAdvice 该注解是spring2.3以后新增的一个注解,主要是用来

  • SpringBoot实现全局异常处理方法总结

    目录 全局异常处理 配置全局异常 全局异常处理的升级 加入自定义异常处理 处理Controller数据绑定.数据校验的异常 GlobalExceptionHandler全部代码 总结 在项目开发中出现异常时很平常不过的事情,我们处理异常也有很多种方式,可能如下: public int div(int a ,int b){ int c=0; try{ c=a/b; }catch (Exception ex){ ex.printStackTrace(); } return c; } 如果我们这样处理

随机推荐