千家信息网

SpringBoot自定义异常的处理方式

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,本篇内容主要讲解"SpringBoot自定义异常的处理方式",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"SpringBoot自定义异常的处理方式"吧!I.
千家信息网最后更新 2025年12月02日SpringBoot自定义异常的处理方式

本篇内容主要讲解"SpringBoot自定义异常的处理方式",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"SpringBoot自定义异常的处理方式"吧!

I. 环境搭建

首先得搭建一个web应用才有可能继续后续的测试,借助SpringBoot搭建一个web应用属于比较简单的活;

创建一个maven项目,pom文件如下

    org.springframework.boot    spring-boot-starter-parent    2.1.7         UTF-8    UTF-8    Finchley.RELEASE    1.8            org.springframework.boot        spring-boot-starter-web                com.alibaba        fastjson        1.2.45                                            org.springframework.boot                spring-boot-maven-plugin                                    spring-milestones        Spring Milestones        https://repo.spring.io/milestone                    false            

II. HandlerExceptionResolver

1. 自定义异常处理

HandlerExceptionResolver顾名思义,就是处理异常的类,接口就一个方法,出现异常之后的回调,四个参数中还携带了异常堆栈信息

@NullableModelAndView resolveException(                HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);

我们自定义异常处理类就比较简单了,实现上面的接口,然后将完整的堆栈返回给调用方

public class SelfExceptionHandler implements HandlerExceptionResolver {    @Override    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,            Exception ex) {        String msg = GlobalExceptionHandler.getThrowableStackInfo(ex);        try {            response.addHeader("Content-Type", "text/html; charset=UTF-8");            response.getWriter().append("自定义异常处理!!! \n").append(msg).flush();        } catch (Exception e) {            e.printStackTrace();        }        return null;    }}// 堆栈信息打印方法如下public static String getThrowableStackInfo(Throwable e) {    ByteArrayOutputStream buf = new ByteArrayOutputStream();    e.printStackTrace(new java.io.PrintWriter(buf, true));    String msg = buf.toString();    try {        buf.close();    } catch (Exception t) {        return e.getMessage();    }    return msg;}

仔细观察上面的代码实现,有下面几个点需要注意

  • 为了确保中文不会乱码,我们设置了返回头 response.addHeader("Content-Type", "text/html; charset=UTF-8"); 如果没有这一行,会出现中文乱码的情况

  • 我们纯后端应用,不想返回视图,直接想Response的输出流中写入数据返回 response.getWriter().append("自定义异常处理!!! \n").append(msg).flush();; 如果项目中有自定义的错误页面,可以通过返回ModelAndView来确定最终返回的错误页面

  • 上面一个代码并不会直接生效,需要注册,可以在WebMvcConfigurer的子类中实现注册,实例如下

@SpringBootApplicationpublic class Application implements WebMvcConfigurer {    @Override    public void configureHandlerExceptionResolvers(List resolvers) {        resolvers.add(0, new SelfExceptionHandler());    }    public static void main(String[] args) {        SpringApplication.run(Application.class);    }}

2. 测试case

我们依然使用上篇博文的用例来测试

@Controller@RequestMapping(path = "page")public class ErrorPageRest {    @ResponseBody    @GetMapping(path = "divide")    public int divide(int sub) {        return 1000 / sub;    }}

下面分别是404异常和500异常的实测情况

500异常会进入我们的自定义异常处理类, 而404依然走的是默认的错误页面,所以如果我们需要捕获404异常,依然需要在配置文件中添加

# 出现错误时, 直接抛出异常spring.mvc.throw-exception-if-no-handler-found=true# 设置静态资源映射访问路径spring.mvc.static-path-pattern=/statics/**# spring.resources.add-mappings=false

为什么404需要额外处理?

下面尽量以通俗易懂的方式说明下这个问题

  • java web应用,除了返回json类数据之外还可能返回网页,js,css

  • 我们通过 @ResponseBody来表明一个url返回的是json数据(通常情况下是这样的,不考虑自定义实现)

  • 我们的@Controller中通过@RequestMapping定义的REST服务,返回的是静态资源

  • 那么js,css,图片这些文件呢,在我们的web应用中并不会定义一个REST服务

  • 所以当接收一个http请求,找不到url关联映射时,默认场景下不认为这是一个NoHandlerFoundException,不抛异常,而是到静态资源中去找了(静态资源中也没有,为啥不抛NoHandlerFoundException呢?这个异常表示这个url请求没有对应的处理器,但是我们这里呢,给它分配到了静态资源处理器了ResourceHttpRequestHandler)

针对上面这点,如果有兴趣深挖的同学,这里给出关键代码位置

// 进入方法: `org.springframework.web.servlet.DispatcherServlet#doDispatch`// debug 节点Determine handler for the current request.mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {        noHandlerFound(processedRequest, response);        return;}// 核心逻辑// org.springframework.web.servlet.DispatcherServlet#getHandler@Nullableprotected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {        if (this.handlerMappings != null) {                for (HandlerMapping hm : this.handlerMappings) {                        if (logger.isTraceEnabled()) {                                logger.trace(                                                "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");                        }                        HandlerExecutionChain handler = hm.getHandler(request);                        if (handler != null) {                                return handler;                        }                }        }        return null;}

到此,相信大家对"SpringBoot自定义异常的处理方式"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0