专栏首页Java编程指南SpringBoot错误页配置及项目全局错误处理

SpringBoot错误页配置及项目全局错误处理

解决俩个问题:

1> 用户体验:当我们请求路径写错时,浏览器显示一个"Whitelabel Error Page",对用户来说体验不友好。

2> 错误码分类:当浏览器请求出现异常时,有时不仅仅是400/404/500..还有Exception异常,对程序员来说不容易识别错误,此时考虑增加全局错误处理。

一 解决用户体验问题:

以编程方式配置嵌入式servlet容器,可以通过注册实现 WebServerFactoryCustomizer 接口的Spring bean,该接口可以直接修改servlet容器配置。例如:

  • 网络设置: 传入HTTP请求的侦听端口(server.port),要绑定的接口地址server.address,等等。
  • 会话设置: 会话是持久性(server.servlet.session.persistence),会话超时(server.servlet.session.timeout),会话数据(server.servlet.session.store-dir)的位置以及会话cookie配置(server.servlet.session.cookie.*)。
  • 错误管理: 错误页面的位置(server.error.path

首先创建一个错误页控制类:MyErrorPageController.java

package com.example.demo.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyErrorPageController {
 
 @RequestMapping("error-404")
 public String toPage404(){
 return "error/error-404";
 }
 @RequestMapping("error-400")
 public String toPage400(){
 return "error/error-400";
 }
 @RequestMapping("error-500")
 public String toPage500(){
 return "error/error-500";
 }
 
}

然后创建错误页类:MyErrorPageConfig.java

package com.example.demo.config;
 
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
 
@Configuration
public class MyErrorPageConfig {
 
 /**
 * 以编程方式配置嵌入式servlet容器,可以通过注册实现该 WebServerFactoryCustomizer 接口的Spring bean
 * TomcatServletWebServerFactory,JettyServletWebServerFactory并且UndertowServletWebServerFactory 是专用变体,
 ConfigurableServletWebServerFactory分别为Tomcat,Jetty和Undertow提供了额外的自定义setter方法。
 * @return
 */
 @Bean
 public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
 return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
 @Override
 public void customize(ConfigurableWebServerFactory factory) {
 // 对嵌入式servlet容器的配置
 // factory.setPort(8081);
 /* 注意:new ErrorPage(stat, path);中path必须是页面名称,并且必须“/”开始。
 底层调用了String.java中如下方法:
 public boolean startsWith(String prefix) {
 return startsWith(prefix, 0);
 }*/
 ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST,
 "/error-400");
 ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND,
 "/error-404");
 ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,
 "/error-500");
 factory.addErrorPages(errorPage400, errorPage404,
 errorPage500);
 }
 };
 }
}

最后创建相关的页面:error/error-404.html/error/error-400.html/error/error-500.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8"/>
 <title>愿世界没有Bug</title>
</head>
<body>
<h1>对不起遇到了错误400</h1>
</body>
</html>

接下来验证我们的错误页:输入错误的访问路径,F12查看请求过程及页面展示!

二 解决错误码分类问题:

首先定义一个错误的对象信息:ErrorInfo.java

package com.example.demo.bean;
public class ErrorInfo {
 // 错误类别码
 public Integer code;
 // 错误信息
 public String message;
 // 映射路径
 public String url;
 // get/set方法省略
}

然后创建一个控制层切面错误处理类:GlobalExceptionHandler.java

package com.example.demo.advice;
 
import com.example.demo.bean.ErrorInfo;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
 
@ControllerAdvice // 作为一个控制层的切面处理
// @RestControllerAdvice // Rest风格,作为一个控制层的切面处理
public class GlobalExceptionHandler {
 
 private static final String DEFAULT_ERROR_VIEW = "error"; // 定义错误显示页,error.html
 private static final Integer INIT_ERROR_CODE = 500; // 定义初始错误码
 
 @ExceptionHandler(value = Exception.class) // 所有的异常都是Exception子类
 public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
 ModelAndView mv = new ModelAndView(DEFAULT_ERROR_VIEW);
 Integer errorCode = INIT_ERROR_CODE;
 // 可以自己定制错误分类对象信息
 ErrorInfo errorInfo = new ErrorInfo();
 // 对错误类型进行分类
 String header = request.getHeader("content-type");
 if(header != null && header.contains("json")){
 errorCode = 300; // json异常
 } else if (e instanceof ArithmeticException) {
 errorCode = 100; // 算术异常
 } else if (e instanceof NullPointerException) {
 errorCode = 200; // 空指针异常
 } else {
 errorCode = 999; // 其他异常
 }
 // 对错误码进行判断
 switch (errorCode) {
 case 100:
 errorInfo.setCode(errorCode); // 将错误码传递过去
 break;
 case 200:
 errorInfo.setCode(errorCode); // 将错误码传递过去
 break;
 case 300:
 errorInfo.setCode(errorCode); // 将错误码传递过去
 break;
 case 500:
 errorInfo.setCode(INIT_ERROR_CODE); // 将错误码传递过去
 break;
 case 999:
 errorInfo.setCode(INIT_ERROR_CODE); // 将错误码传递过去
 break;
 default:
 errorInfo.setCode(1000); // 将错误码传递过去
 break;
 }
 errorInfo.setMessage(e.getMessage());// 将异常对象传递过去
 errorInfo.setUrl(request.getRequestURL().toString());// 获得请求的路径
 mv.addObject("errorInfo", errorInfo);
 mv.setViewName("error/"+DEFAULT_ERROR_VIEW);
 return mv;
 }
 
}

最后创建错误页面:error/error.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8"/>
 <title>愿世界没有Bug</title>
</head>
<body>
<h1>Sorry,异常了(自定义)</h1>
<div>
 <p th:text="'错误码:' + ${errorInfo.code}"/>
 <p th:text="'映射路径:' + ${errorInfo.url}"/>
 <p th:text="'错误信息:' + ${errorInfo.message}"/>
</div>
</body>
</html>

搞定,接下来看一下结果:首先搞一个算术异常,输入访问路径->http://localhost/mul?param=0

@RequestMapping(value = "/mul")
 public int mulParam(int param) {
 return 9/param;
 }

访问结果如下图:

如此可以将所有异常信息展示出来,或是后台搞到数据库中,查找问题时,根据错误码,错误信息精准定位问题。不需要程序员对所有的Exception都了解。上手简单,排难精准。

本文分享自微信公众号 - Java编程指南(JavaXxzyfx),作者:Java编程指南

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 代码片段分享之-Java读取Excel内容

    借助于apathe的poi.jar,由于上传文件不支持.jar所以请下载后将文件改为.jar,在应用程序中添加poi.jar包,并将需要读取的excel文件放入...

    Java编程指南
  • SpringBoot整合ActiveMQ

    MQ的作用在前面文章中我已经介绍过了,那么今天就教大家学习整合ActiveMQ,篇幅有点长希望大家能看完。

    Java编程指南
  • 浅谈lambda表达式<最通俗易懂的讲解>

    lambda体中调用方法的参数列表和返回值类型,要和函数式接口中抽象方法的参数列表和返回值类型保持一致。

    Java编程指南
  • Vue 折腾记 - (10) 给axios做个挺靠谱的封装(报错,鉴权,跳转,拦截,提示)

    不推荐完全copy过去,可以看看我是如何针对我这边业务; 做的一个axios的封装及实现的思路

    CRPER
  • Spring Boot错误处理

    自定义一个类实现ErrorController,当系统发生404或者500错误的时候,就会自动进入到自定义的错误页面中,这要求在resources文件里面的te...

    itlemon
  • SpringBoot2.0 基础案例(05):多个拦截器配置和使用场景

    拦截器,请求的接口被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。 拦截器主要用来按照指定规则拒绝请求。

    知了一笑
  • 淘宝上搜索商品,AI如何窥探你的?

    先说结论:淘宝对每个用户有个精准画像,其中最关键的指标是年龄、性别、购买能力(赤裸裸的欺负人!)。对每个商品有个画像,其中最关键的指标是点击率、价格档位(8档)...

    用户1594945
  • 【专知-Deeplearning4j深度学习教程03】使用多层神经网络分类MNIST数据集:图文+代码

    【导读】主题链路知识是我们专知的核心功能之一,为用户提供AI领域系统性的知识学习服务,一站式学习人工智能的知识,包含人工智能( 机器学习、自然语言处理、计算机视...

    WZEARW
  • 自定义数据库连接池

    秋白
  • JAVA CDI 学习(3) - @Produces及@Disposes

    上一节学习了注入Bean的生命周期,今天再来看看另一个话题: Bean的生产(@Produces)及销毁(@Disposes),这有点象设计模式中的工厂模式。在...

    菩提树下的杨过

扫码关注云+社区

领取腾讯云代金券