IntelliJ+SpringBoot项目实战(十)--常量类、自定义错误页、全局异常处理

一、常量类

       在项目开发中,经常需要约定一些常量,比如接口返回响应请求指定状态码、异常类型、默认页数等,为了增加代码的可阅读性以及开发团队中规范一些常量的使用,可开发一些常量类。下面有3个常量类示例,代码位于openjweb-common的org/openjweb/common/constant路径:

下面是接口调用返回的状态码常量类ResponseConst.java:

package org.openjweb.common.constant;public class ResponseConst {//按HTTP返回码定义的常量public static final int STATE_HTTP_SUCCESS = 200;//有的项目设置0为调用成功的返回值public static final int STATE_SUCCESS = 0;//有的项目设置-1为默认的请求失败返回的错误码public static final int STATE_FAIL = -1;}

 下面是异常提示信息常量类ExceptionConst.java:

/*** 异常相关常量*/
public class ExceptionConst {public static final String UNKNOWN_ERROR_MSG = "数据加载失败,请稍后重试";public static final String SQL_ERROR_MSG = "数据异常,请稍后重试";public static final String CONNECT_ERROR_MSG = "连接异常,请稍后重试";public static final String LOGIN_ERROR_MSG = "用户名或密码错误";public static final String CLICK_HOUSE_ERROR_MSG = "clickhouse查询异常";public static final String UPLOAD_FILE_ERROR_MSG = "上传文件失败";public static final String DELETE_FILE_ERROR_MSG = "删除文件失败";public static final String XCX_ERROR_MSG = "小程序维护中,请稍后再试";
}

下面是公共常量类CommonConst.java:

package org.openjweb.common.constant;/*** 公共常量*/
public class CommonConst {/*** 默认显示页数20*/public static final int DEFAULT_PAGE_SIZE = 20;/*** 数据量大时,分页查询数据条数*/public static final int DEFAULT_SEARCH_PAGE_SIZE = 500;/*** 微信支付access-token*/public static final String WX_ACCESS_TOKEN = "wx_access_token";/*** 默认排序*/public static final int DEFAULT_SORT = 1;/*** 状态:0-禁用;1-启用*/public static final int IS_ENABLE_0 = 0;public static final int IS_ENABLE_1 = 1;
}

在项目开发中还可以定义更多的常量类。

二、自定义错误页面

      大家在SpringBoot开发过程中,对下面这个页面应该是很熟悉:

    

       如果我们访问一个不存在的资源的时候,就会显示这个页面。这个页面不太友好,我们如何自定义这个默认的错误页呢?

      现在在openjweb-sys的resources目录下建一个static目录,然后在这个目录下建一个error-404.html页面(特别注意:经测试,如果页面命名为404.html是有问题的,所以不能用404.html文件名):

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>404</title>
</head>
<body>
<div class="text" style=" text-align:center;">页面出错了!!
</div>
</body></html>

     然后在openjweb-sys的org/openjweb/sys/config下面建一个错位页配置类ErrorPageConfig.java:

package org.openjweb.sys.config;import lombok.extern.slf4j.Slf4j;
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
@Slf4j
public class ErrorPageConfig {@Beanpublic WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {@Overridepublic void customize(ConfigurableWebServerFactory factory) {log.info("重新指定404页面................");ErrorPage err404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/error-404.html");//不能直接命名404.html//ErrorPage err500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/error-500.html");////ttpStatus.BAD_REQUEST:400,ttpStatus.INTERNAL_SERVER_ERROR 500factory.addErrorPages(err404Page);//factory.addErrorPages(err404Page,err500Page);}};}
}

        注意在上面的代码中,仅示例了出现404(HttpStatus.NOT_FOUND)的时候跳转到error-404.html,另外这个类只是演示了替代默认的错误处理,并没有根据不同的HttpStatus指定不同的错误处理页。现在重启动SpringBoot,访问一个不存在的链接:http://localhost:8001/demo/api/redis/se1

界面显示: 这个就是我们定义的error-404.html的内容,已经不再显示SpringBoot默认的错误页了。不过在实际项目中,光做到这一步还是不够的。应该针对不同的错误返回不同的错误信息。

三、全局异常处理及升级错误处理页

       在实际开发中,需要做一个全局异常处理,以便通过框架自动处理异常,而不是在每个业务方法中手工处理产生的异常,这样开发效率很低。另外在错误处理页上,需要展示错误码、错误信息等。首先我们需要实现一个全局异常处理类,我们命名为GlobalException,放在openjweb-common的org/openjweb/common/exception下:

        

package org.openjweb.common.exception;import org.openjweb.common.constant.ResponseConst;public class GlobalException extends RuntimeException {private int code = ResponseConst.STATE_FAIL;//默认错误码private String appName;//异常产生的应用名称public GlobalException(String msg) {super(msg);}public GlobalException(String msg, int code) {super(msg);this.code = code;}public GlobalException(String message, String appName) {super(message);this.appName = appName;}public GlobalException(String message, int code, String appName) {super(message);this.code = code;this.appName = appName;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getAppName() {return this.appName;}public void setAppName(String appName) {this.appName = appName;}
}

        接下来我们在oopenjweb-common工程的org.openjweb.common.handler包下创建一个GlobalExceptionHandler类,在这个类中,我们指定GlobalException类的拦截处理以及指定错误视图:

package org.openjweb.common.handler;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import lombok.extern.slf4j.Slf4j;
import org.openjweb.common.exception.GlobalException;
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.servlet.ModelAndView;@Slf4j
@ControllerAdvice(basePackages= {"org.openjweb"})
public class GlobalExceptionHandler {@ExceptionHandler({GlobalException.class})@ResponseBodypublic ModelAndView globalErrorHandler(HttpServletRequest request,HttpServletResponse response,Exception ex) throws Exception {ModelAndView mv = new ModelAndView();if(true) {log.info("自定义全局异常 GlobalException 异常处理........");GlobalException thisException = (GlobalException)ex;int errorCode = thisException.getCode();mv.addObject("errorCode", errorCode);mv.addObject("errorMessage","GlobalException处理异常:"+ex.getMessage());mv.addObject("requestUrl",request.getRequestURL().toString());mv.setViewName("errorPage");}return mv;}}

        在上面的类中,通过增加了@ControllerAdvice注解,通过在方法中增加@ExceptionHandler(GlobalException.class)注解,则凡是在控制层中抛出GlobalException异常,则都会被此类拦截,并返回错误页视图errorPage。

       接下来我们定义一个errorPage错误处理页面,因为我们现在要使用thymeleaf解析视图里的页面错误信息,所以需要在openjweb-sys工程的resources/template目录下创建一个errorPage.html:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>error</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head><body>
<table> 
<tr>
<td>错误码:</td>
<td th:text="${errorCode}"></td>
</tr>
<tr>
<td>错误信息:</td>
<td th:text="${errorMessage}"></td> 
</tr>
<tr>
<td>请求地址:</td><td th:text="${requestUrl}"></td>
</tr>
</table>
</body>
</html>

        在errorPage.html里显示错误码、错误信息、错误请求的URL。然后我们需要实现一个api测试类来演示下效果。在openjweb-sys的org.openjweb.sys.api下创建一个DefaultErrorApi.java:

package org.openjweb.sys.api;import lombok.extern.slf4j.Slf4j;
import org.openjweb.common.exception.GlobalException;
import org.openjweb.sys.entity.CommUser;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 测试:http://localhost:8001/demo/error/testError?flag=1* http://localhost:8001/demo/error/testError?flag=2*  **/
@RestController
@RequestMapping("/demo/error")
@Slf4j
public class DefaultErrorApi {@RequestMapping("testError")public CommUser testError(String flag){CommUser user = new CommUser();if("1".equals(flag)) {throw new GlobalException("演示全局异常", -1);}else {user.setRealName("张三");user.setLoginId("admin");return user;}}}

       在上面的示例代码中,通过传递flag=1演示带自定义错误页的异常显示,传其他值为正常接口调用,访问 http://localhost:8001/demo/error/testError?flag=1 演示自定义错误页:

        

访问http://localhost:8001/demo/error/testError?flag=2为正常的接口调用:

       在实际开发中,控制层一种是返回API JSON数据,第二种就是返回视图,我们在调用数据请求接口时,希望异常时返回统一的错误信息JSON包,请求视图时,异常返回统一的错误视图,这种需求怎么实现?上面的示例是返回视图的异常。接下来我们再实现一个返回JSON的异常处理:

      (1)首先我们再加一个用于JSON处理的异常处理类,命名为GlobalJsonException,内容直接复制GlobalException,然后把构造方法修改下:

   

package org.openjweb.common.exception;import org.openjweb.common.constant.ResponseConst;/*** 用于API调用时统一处理错误异常*/public class GlobalJsonException extends RuntimeException {private int code = ResponseConst.STATE_FAIL;//默认错误码private String appName;//异常产生的应用名称public GlobalJsonException(String msg) {super(msg);}public GlobalJsonException(String msg, int code) {super(msg);this.code = code;}public GlobalJsonException(String message, String appName) {super(message);this.appName = appName;}public GlobalJsonException(String message, int code, String appName) {super(message);this.code = code;this.appName = appName;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getAppName() {return this.appName;}public void setAppName(String appName) {this.appName = appName;}
}

然后在GlobalExceptionHandler.java中增加一个新的方法:

    @ExceptionHandler({GlobalJsonException.class})@ResponseBodypublic JSONObject globalJsonErrorHandler(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {GlobalJsonException thisException = (GlobalJsonException)ex;JSONObject errJson = new JSONObject();errJson.put("code",thisException.getCode());errJson.put("msg",thisException.getMessage());return errJson;}

然后我们在defaultErrorApi中在增加一个方法演示JSON接口调用异常的拦截处理:

    @RequestMapping("testJsonError")public CommUser testJsonError(String flag){CommUser user = new CommUser();if("1".equals(flag)) {throw new GlobalJsonException("演示全局异常", -1);}else {user.setRealName("张三");user.setLoginId("admin");}return user;}

测试地址:http://localhost:8001/demo/error/testJsonError?flag=1

       这样我们就不需要在每个业务接口中专门针对异常来做JSON处理了。只需要在全局异常处理类中做处理即可,不过业务接口中,需要把code、message放到异常中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/476906.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu20.04的arduino+MU编辑器安装教程

arduino 按照这个博客&#xff0c;是2.3版本的&#xff1a; Ubuntu20.04/22.04 安装 Arduino IDE 2.x_ubuntu ide-CSDN博客https://blog.csdn.net/michaelchain/article/details/128744935以下这个博客是1.8版本的 在ubuntu系统安装Arduino IDE的方法_ubuntu arduino ide-CS…

Docker核心概念总结

本文只是对 Docker 的概念做了较为详细的介绍&#xff0c;并不涉及一些像 Docker 环境的安装以及 Docker 的一些常见操作和命令。 容器介绍 Docker 是世界领先的软件容器平台&#xff0c;所以想要搞懂 Docker 的概念我们必须先从容器开始说起。 什么是容器? 先来看看容器较为…

Redis ⽀持哪⼏种数据类型?适⽤场景,底层结构

目录 Redis 数据类型 一、String&#xff08;字符串&#xff09; 二、Hash&#xff08;哈希&#xff09; 三、List&#xff08;列表&#xff09; 四、Set&#xff08;集合&#xff09; 五、ZSet(sorted set&#xff1a;有序集合) 六、BitMap 七、HyperLogLog 八、GEO …

uniapp接入BMapGL百度地图

下面代码兼容安卓APP和H5 百度地图官网&#xff1a;控制台 | 百度地图开放平台 应用类别选择《浏览器端》 /utils/map.js 需要设置你自己的key export function myBMapGL1() {return new Promise(function(resolve, reject) {if (typeof window.initMyBMapGL1 function) {r…

Docker+Nginx | Docker(Nginx) + Docker(fastapi)反向代理

在DockerHub搜 nginx&#xff0c;第一个就是官方镜像库&#xff0c;这里使用1.27.2版本演示 1.下载镜像 docker pull nginx:1.27.2 2.测试运行 docker run --name nginx -p 9090:80 -d nginx:1.27.2 这里绑定了宿主机的9090端口&#xff0c;只要访问宿主机的9090端口&#…

AmazonS3集成minio实现https访问

最近系统全面升级到https&#xff0c;之前AmazonS3大文件分片上传直接使用http://ip:9000访问minio的方式已然行不通&#xff0c;https服务器访问http资源会报Mixed Content混合内容错误。 一般有两种解决方案&#xff0c;一是升级minio服务&#xff0c;配置ssl证书&#xff0c…

人工智能|计算机视觉——微表情识别(Micro expression recognition)的研究现状

一、简述 微表情是一种特殊的面部表情,与普通的表情相比,微表情主要有以下特点: 持续时间短,通常只有1/25s~1/3s;动作强度低,难以察觉;在无意识状态下产生,通常难以掩饰或伪装;对微表情的分析通常需要在视频中,而普通表情在图像中就可以分析。由于微表情在无意识状态…

2024年9月中国电子学会青少年软件编程(Python)等级考试试卷(六级)答案 + 解析

一、单选题 1、下面代码运行后出现的图像是&#xff1f;&#xff08; &#xff09; import matplotlib.pyplot as plt import numpy as np x np.array([A, B, C, D]) y np.array([30, 25, 15, 35]) plt.bar(x, y) plt.show() A. B. C. D. 正确答案&#xff1a;A 答案…

Spring Aop+自定义注解实践(待完善日志)

目录 前言 1.引入依赖 2.SpringAop的用法举例 3. 自定义注解AOP的用法举例 3.1 关于Target注解补充 3.2 关于Retention注解补充 3.3 举例 前言 如果你不太理解aop的知识&#xff0c;请看我写的这篇文章&#xff0c;非常详细&#xff1a; Spring AOP&#xff08;定义、…

OpenCV双目立体视觉重建

本篇文章主要给出使用opencv sgbm重建三维点云的代码&#xff0c;鉴于自身水平所限&#xff0c;如有错误&#xff0c;欢迎批评指正。 环境&#xff1a;vs2015 &#xff0c;opencv3.4.6&#xff0c;pcl1.8.0 原始数据使用D455采集&#xff0c;图像已做完立体校正&#xff0c;如下…

【进阶系列】python简单爬虫实例

python有一个很强大的功能就是爬取网页的信息&#xff0c;这里是CNBlogs 网站&#xff0c;我们将以此网站为实例&#xff0c;爬取指定个页面的大标题内容。代码如下&#xff1a; 首先是导入库&#xff1a; # 导入所需的库 import requests # 用于发送HTTP请求 from bs4 impor…

Ease Monitor 会把基础层,中间件层的监控数据和服务的监控数据打通,从总体的视角提供监控分析

1. 产品定位 Ease Monitor 有如下的产品定位&#xff1a; 关注于整体应用的SLA。 主要从为用户服务的 API 来监控整个系统。 关联指标聚合。 把有关联的系统及其指示聚合展示。主要是三层系统数据&#xff1a;基础层、平台中间件层和应用层。 快速故障定位。 对于现有的系统…

Java学习笔记--数组常见算法:数组翻转,冒泡排序,二分查找

目录 一&#xff0c;数组翻转 二&#xff0c;冒泡排序 三&#xff0c;二分查找&#xff08;一尺之锤&#xff0c;日取其半&#xff0c;万世不竭&#xff09; 一&#xff0c;数组翻转 1.概述:数组对称索引位置上的元素互换&#xff0c;最大值数组序号是数组长度减一 创建跳板…

Python中Tushare(金融数据库)入门详解

文章目录 Python中Tushare&#xff08;金融数据库&#xff09;入门详解一、引言二、安装与注册1、安装Tushare2、注册与获取Token 三、Tushare基本使用1、设置Token2、获取数据2.1、获取股票基础信息2.2、获取交易日历2.3、获取A股日线行情2.4、获取沪股通和深股通成份股2.5、获…

网络编程(JAVA笔记第三十八期)

p.s.这是萌新自己自学总结的笔记&#xff0c;如果想学习得更透彻的话还是请去看大佬的讲解 目录 网络编程概念网络编程三要素IPInetAddress类端口号协议 UDP协议UDP通信程序(发送数据)UDP通信程序(发送数据)使用UDP写聊天室项目UDP的通信方式 TCP协议通过TCP协议实现多发多收通…

Bokeh实现大规模数据可视化的最佳实践

目录 引言 一、Bokeh简介 二、安装Bokeh 三、数据准备 四、性能优化 五、创建图表 六、添加交互功能 七、应用案例 八、高级技巧 九、总结 引言 在数据科学领域,数据可视化是一个至关重要的环节。通过可视化,我们可以直观地理解数据的特征和趋势,为数据分析和决策…

IDEA2023 SpringBoot整合MyBatis(三)

一、数据库表 CREATE TABLE students (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,age INT,gender ENUM(Male, Female, Other),email VARCHAR(100) UNIQUE,phone_number VARCHAR(20),address VARCHAR(255),date_of_birth DATE,enrollment_date DATE,cours…

PVE的优化与温度监控(二)—无法识别移动硬盘S.M.A.R.T信息的思考并解决

前情提要&#xff1a;空闲2.5英寸机械硬盘&#xff0c;直接放到PVE上测试NAS 使用&#xff0c;通过SATA线的方式让小主机不太美观&#xff0c;并且失去了前期调试的安全性。购入移动硬盘盒&#xff0c;缺点&#xff0c;USB 连接&#xff0c;会失去一些特性。比如本文中遇到的问…

记录下jekins新建个前端部署配置项

1 新建个item 2 输入项目名称&#xff0c;选择个新的工程或 或者搜个已存在的现有模板 3 添加一些描述 4 &#xff08;可选&#xff09;配置下构建历史保存情况 5 限制下构建节点和选择gitlab或者github 6 写下git仓库地址、账号密码以及分支 7 选择构建工具node以及版本 8 构建…

文件管理 II(文件的物理结构、存储空间管理)

一、文件的物理结构 文件实际上是一种抽象数据类型&#xff0c;我们要研究它的逻辑结构、物理结构&#xff0c;以及关于它的一系列操作。文件的物理结构就是研究文件的实现&#xff0c;即文件数据在物理存储设备上是如何分布和组织的。同一个问题有两个方面的回答&#xff1a;…