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 {

    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
        return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
            @Override
            public 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 500
                factory.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})
    @ResponseBody
    public 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})
    @ResponseBody
    public 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放到异常中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2025蓝桥杯(单片机)备赛--扩展外设之DS1302的使用(九)

1.DS1302数据手册的使用 a. DS1302 features: 工作电压&#xff1a;2V-5.5V 通信协议&#xff1a;3线接口&#xff08;CE、IO、SCLK&#xff09; 计时&#xff1a;秒、分、小时、月日期、月、星期、年&#xff08;闰年补偿器期至2100年&#xff09; b.原理图接线说明&#xff…

MCU中的定时器

第一章 定时器的应用场景 第二章 定时器的原理 2.1 定时器的计数原理 1. 定时器的本质是一个计数器&#xff1b; 2. 计数器是对输入的系统频率信号进行计数&#xff1b; 3. 每来一个周期的信号&#xff0c;计数器的cnt 加一。如果周期T表示为1s&#xff0c;来三个周期就表示…

类和对象——static 成员,匿名对象(C++)

1.static成员 a&#xff09;⽤static修饰的成员变量&#xff0c;称之为静态成员变量&#xff0c;静态成员变量⼀定要在类外进行初始化。 b&#xff09;静态成员变量为所有类对象所共享&#xff0c;不属于某个具体的对象&#xff0c;不存在对象中&#xff0c;存放在静态区。 …

POD-Transformer多变量回归预测(Matlab)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现POD-Transformer多变量回归预测&#xff0c;本征正交分解数据降维融合Transformer多变量回归预测&#xff0c;使用SVD进行POD分解&#xff08;本征正交分解&#xff09;&#xff1b; 2.运行环境Matlab20…

C#中的二维数组的应用:探索物理含义与数据结构的奇妙融合

在C#编程中&#xff0c;二维数组&#xff08;或矩阵&#xff09;是一种重要的数据结构&#xff0c;它不仅能够高效地存储和组织数据&#xff0c;还能通过其行、列和交叉点&#xff08;备注&#xff1a;此处相交处通常称为“元素”或“单元格”&#xff0c;代表二维数组中的一个…

【网络安全 | 漏洞挖掘】通过密码重置污染实现账户接管

未经许可,不得转载。 文章目录 密码重置污染攻击漏洞挖掘的过程目标选择与初步测试绕过 Cloudflare 的尝试发现两个域名利用 Origin 头部污染实现账户接管攻击流程总结在今天的文章中,我们将深入探讨一种 账户接管 漏洞,并详细分析如何绕过 Cloudflare 的保护机制,利用密码…

uniapp 相关的swiper的一些注意事项

先推荐一个一个对标pc端swiper的uniapp版本 zebra-swiper 缺点是自定义分页器不是很好处理 不知道怎么弄 优点:可以进行高度自适应 &#xff08;这个uniapp原生swiper没有 只能动态修改 采用js 或者只有几种固定高度时采用变量修改&#xff09; <swiperref"lifeMiddle…

机器学习笔记——聚类算法(Kmeans、GMM-使用EM优化)

本笔记介绍机器学习中常见的聚类算法&#xff08;Kmeans、GMM-使用EM优化&#xff09;。 文章目录 聚类K-Means工作原理特点 K-Medoids工作原理特点 Mini-Batch K-Means工作原理特点 K-Means&#xff08;重要&#xff09;工作原理特点 总结K的选值1. 肘部法则&#xff08;Elbow…

SpringBoot项目升级到3.*,并由JDK8升级到JDK21

文章目录 技术选型说明JDK21的Demo项目下载升级过程出现的问题及解决1、程序包javax.servlet.http不存在1.1、java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter1.2、javax.validation包替换为jakarta.validation1.3、jakarta的名字由来 2、mybatis-plus升级3…

谈一谈QThread::CurrentThread和this->thread

QThread::CurrentThread是指的当前函数调用者者所在的线程 this->thread是指的当前对象所在的线程&#xff08;对象创建出来的时候所在的线程&#xff09; Qt文档说明 CurrentThread返回一个指向管理当前执行线程的QThread的指针 thread返回对象所在的线程 这两个函数所…

每日论文23-24ESSERC 6.4-16.1Ghz混合并联-串联谐振器

《A 6.4-to-16.1GHz Hybrid Parallel-Series Resonator Mode-Switching Oscillator with 206.6dBc/Hz FoMT at 1MHz Offset in 40nm CMOS》 24ESSERC 首先这篇文章有个地方我其实没太明白&#xff0c;它在title和行文的时候都写的是“ hybrid parallel-series resonator mode-…

数据结构C语言描述3(图文结合)--双链表、循环链表、约瑟夫环问题

前言 这个专栏将会用纯C实现常用的数据结构和简单的算法&#xff1b;有C基础即可跟着学习&#xff0c;代码均可运行&#xff1b;准备考研的也可跟着写&#xff0c;个人感觉&#xff0c;如果时间充裕&#xff0c;手写一遍比看书、刷题管用很多&#xff0c;这也是本人采用纯C语言…

深入理解Flutter生命周期函数之StatefulWidget(一)

目录 前言 1.为什么需要生命周期函数 2.开发过程中常用的生命周期函数 1.initState() 2.didChangeDependencies() 3.build() 4.didUpdateWidget() 5.setState() 6.deactivate() 7.dispose() 3.Flutter生命周期总结 1.调用顺序 2.函数调用时机以及主要作用 4.生…

uniapp vue3小程序报错Cannot read property ‘__route__‘ of undefined

在App.vue里有监听应用的生命周期 <script>// 只能在App.vue里监听应用的生命周期export default {onError: function(err) {console.log(AppOnError:, err); // 当 uni-app 报错时触发}} </script>在控制台打印里无意发现 Cannot read property ‘__route__‘ of …

ESP32移植Openharmony外设篇(5)aht20温湿度传感器

模块简介 产品概述 AHT20&#xff0c;新一代温湿度传感器在尺寸与智能方面建立了新的标准&#xff1a;它嵌入了适于回流焊的双列扁平无引脚SMD封装&#xff0c;底面 3 x 3mm &#xff0c;高度1.0mm。传感器输出经过标定的数字信号&#xff0c;标准 I2 C 格式。 AHT20 配有一个…

量子计算来袭:如何保护未来的数字世界

目录 前言 一、量子计算安全的学习方向 1. 量子物理学基础 2. 量子计算原理与技术 3. 传统网络安全知识 4. 量子密码学 5. 量子计算安全政策与法规 二、量子计算的漏洞风险 1. 加密算法被破解风险 2. 区块链安全风险 3. 量子密钥分发风险 4. 量子计算系统自身风险 …

Git入门图文教程 -- 深入浅出 ( 保姆级 )

01、认识一下Git&#xff01;—简介 Git是当前最先进、最主流的分布式版本控制系统&#xff0c;免费、开源&#xff01;核心能力就是版本控制。再具体一点&#xff0c;就是面向代码文件的版本控制&#xff0c;代码的任何修改历史都会被记录管理起来&#xff0c;意味着可以恢复…

C++之异常

1.异常的概念及其使用 1.1 异常的概念 异常是一种用于处理错误的机制&#xff0c;它允许程序在检查到错误条件时&#xff0c;能够从一个代码块转到另一个代码块&#xff0c;以处理改错误&#xff0c;而不是直接崩溃返回不确定的结果。 C的异常处理机制依赖于三个关键字&#x…

Golang语言整合jwt+gin框架实现token

1.下载jwt go get -u github.com/dgrijalva/jwt-go2.新建生成token和解析token文件 2.1 新建common文件夹和jwtConfig文件夹 新建jwtconfig.go文件 2.2 jwtconfig.go文件代码 /* Time : 2021/8/2 下午3:03 Author : mrxuexi File : main Software: GoLand */ package jwtC…

河工oj(1101-1113)

1101 求组合数&#xff08;函数专题&#xff09; 代码 #include<bits/stdc.h> using namespace std;int fact(int n) {int res 1;while(n) {res * n--;}return res; } int main() {int m, k;cin >> m >> k;cout << fact(m)/fact(k)/fact(m-k) <&l…