当前位置: 首页 > news >正文

Java异常体系、UncaughtExceptionHandler、Spring MVC统一异常处理、Spring Boot统一异常处理

概述

在这里插入图片描述
所有异常都是继承自java.lang.Throwable类,Throwable有两个直接子类,Error和Exception。

Error用来表示程序底层或硬件有关的错误,这种错误和程序本身无关,如常见的NoClassDefFoundError。这种异常和程序本身无关,不需要检查,属于非受检异常。

Exception表示程序异常,可能是由于程序不严谨导致的,如NPE空指针异常。Exception下面派生RuntimeException和其他异常,其中RuntimeException表示运行时异常,也属于非受检异常。在编译时可以不需要强制检查的异常,不需要显式捕捉或抛出。

除Error和RuntimeException及派生类以外,其他异常都属于受检异常,如IOException、SQLException。在编译时强制进行检查的异常,这种异常需要显式的通过try/catch来捕捉,或通过throws抛出去,否则程序无法通过编译。设计强制检查的异常(受检异常),主要原因是考虑到程序的正确性、稳定性和可靠性。
在这里插入图片描述

try…catch…finally语句块

初中级笔试题可能会出现的知识点。这里直接给出一些结论:

  • 受检异常,需要使用try来包裹可能会抛出异常的代码块,catch用于捕获异常并处理异常的代码块,常见的处理策略包括:打印错误日志、抛出自定义业务异常、释放资源、设置局部变量等
  • 受检异常,还可以直接在方法签名上throws Exception,抛给方法调用者来处理。业务开发中,通常在Service层抛出自定义业务异常,然后在Controller层统一捕获异常并返回errCode和errMsg
  • 不管有没有出现异常,finally仍然会执行
  • 当try和catch中有return时,finally仍然会执行
  • finally常用于释放IO资源、(分布式)锁的持有、

常见异常

初中级Java开发工程师面试中,经常会遇到的一个问题:说说你工作中经常遇到的异常?

面试官指的应该包括Exception和Error,回答问题时,不能只列举Exception。

简单列举Exception如下:

  • NullPointerException:简称NPE。多少人栽在NPE上,多少资金损失是因为NPE。减少(无法杜绝)NPE的方法就是不停地空判断,或使用Optional类。可喜的是,升级到JDK 14以上版本,发生NPE时,JVM会打印具体哪个方法抛的空指针异常,避免同一行代码多个函数调用时无法判断具体是哪个函数抛异常的困扰,方便异常排查;
  • ConcurrentModificationException:简称CME。当有多个迭代器同时遍历和修改Java集合(如ArrayList或HashMap),就有可能抛出CME异常。避免出现CME异常的措施如:加锁,使用CopyOnWriteArrayList,ConcurrentHashMap等集合。
  • IndexOutOfBoundsException:索引越界,实现类有两个ArrayIndexOutOfBoundsException和StringIndexOutOfBoundsException。
  • ClassCastException:类型转换失败。
  • ClassNotFoundException:参考Java学习之NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError

简单列举Error如下:

  • OutOfMemoryError:OOM,报错信息为:java.lang.OutOfMemoryError:Java heap spacess。遇到OOM时,需要先分清楚是内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)。
  • StackOverflowError:栈溢出。栈溢出的原因:递归调用(如求解斐波那契数列问题时),大量循环或死循环,全局变量过多,数组、List、Map数据过大。
  • NoClassDefFoundError:找不到类定义
  • NoSuchMethodError:找不到方法
  • NoSuchFieldError:找不到字段,上面这三种一般都是三方依赖冲突,通过使用maven工具来排查,如mvn dependency:tree > tmp.txt,或使用IDEA的Maven Helper插件

最佳实践

即所谓的Best Practice:

  • 在finally中清理资源;
  • 坚决要杜绝捕获异常后不做任何处理,即catch语句块为空;
  • 捕获异常后的日志打印规范,如记录错误类和方法,记录详细的错误堆栈stacktrace方便排查问题;
  • 使用Try-With-Resource语句,实现AutoCloseable接口的资源;
  • 优先捕获特定的异常,其次再考虑其父类异常;
  • 多使用自定义业务异常,一个异常对应有一个errCode和一个可读性良好的errMsg

进阶

异常表

在JVM中,异常处理不是由字节码指令(早期使用jsr、ret指令)来实现的,而是异常表。

如果一个方法定义有try-catch或try-finally,则会创建异常表,保存异常处理信息:

  • 起始位置
  • 结束位置
  • 程序计数器记录的代码处理的偏移地址
  • 被捕获的异常类在常量池中的索引

Exception table:

Exception table:from    to  target type0    12    15   Class java/lang/Exception

根据不同的type对应到不同的target上。在操作系统里,这个target也称为异常处理程序。就是特定问题出现时,去异常表查询这个问题对应的是哪个处理程序,然后去执行这个程序,完成异常处理。

面试可能会遇到的问题:finally为什么一定会执行?
查看编译后的字节码,可发现编译器把finally语句块里面的代码分别复制到try和catch语句块里面。

异常throw事件

jvmti中提供两个异常的事件,一个是包含throw和catch,一个是catch。选择功能多的那个方便一点。

void JNICALL Exception(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location, jobject exception, jmethodID catch_method, jlocation catch_location)

通过方法签名,可以知道异常的线程,出异常的方法,行号,异常对象,catch的方法和行号。这里由于是触发的throw事件,所以如果只是new Exception的操作是不会触发事件的。有些代码通过创建Exception或Error来控制逻辑,只要不是throw,catch的这种逻辑,这里是检测不到的。如果异常只throw没有catch的话,catch的字段就是空的。

拓展

UncaughtExceptionHandler

在虚拟机中,当一个线程没有显式处理(即try catch)异常而抛出时,会将该异常事件报告给该线程对象的java.lang.Thread.UncaughtExceptionHandler进行处理,如果线程没有设置UncaughtExceptionHandler,则默认会把异常栈信息输出到终端而使程序直接崩溃。所以如果想在线程意外崩溃时做一些处理就可以通过实现UncaughtExceptionHandler来满足需求。

public class Thread {/*** 当一个线程因未捕获的异常而即将终止时虚拟机将使用 Thread.getUncaughtExceptionHandler()* 获取已经设置的 UncaughtExceptionHandler 实例,并通过调用其 uncaughtException(...) 方法而传递相关异常信息。* 如果一个线程没有明确设置其 UncaughtExceptionHandler,则将其 ThreadGroup 对象作为其handler,如果 ThreadGroup 对象对异常没有什么特殊的要求,则 ThreadGroup 会将调用转发给默认的未捕获异常处理器(即 Thread 类中定义的静态未捕获异常处理器对象)。*/@FunctionalInterfacepublic interface UncaughtExceptionHandler {/*** 未捕获异常崩溃时回调此方法*/void uncaughtException(Thread t, Throwable e);}/*** 静态方法,用于设置一个默认的全局异常处理器*/public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {SecurityManager sm = System.getSecurityManager();if (sm != null) {sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler"));}defaultUncaughtExceptionHandler = eh;}/*** 针对某个Thread对象的方法,用于对特定的线程进行未捕获的异常处理*/public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {checkAccess();uncaughtExceptionHandler = eh;}/*** 当Thread崩溃时会调用该方法获取当前线程的 handler,获取不到就会调用 group(handler 类型)。* group是Thread类的ThreadGroup类型属性,在Thread构造中实例化*/public UncaughtExceptionHandler getUncaughtExceptionHandler() {if (isTerminated()) {// uncaughtExceptionHandler may be set to null after thread terminatesreturn null;} else {UncaughtExceptionHandler ueh = uncaughtExceptionHandler;return (ueh != null) ? ueh : getThreadGroup();}}/*** 线程全局默认handler*/public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {return defaultUncaughtExceptionHandler;}
}

线程崩溃时异常抛出的顺序:

  • 先调用Thread.getUncaughtExceptionHandler()查看是否有自己对象特有的handler,如果有就直接处理
  • 如果没有就调用ThreadGroup(UncaughtExceptionHandler的默认实现类)
  • 如果ThreadGroup没啥特殊处理就会继续调用Thread.getDefaultUncaughtExceptionHandler()获取handler进行处理
  • 如果默认handler也没有处理就直接执行正常的异常流程使程序崩溃。

ThreadGroup核心实现源码:

// ThreadGroup在Thread对象构造方法中实例化
public class ThreadGroup implements Thread.UncaughtExceptionHandler {public void uncaughtException(Thread t, Throwable e) {// parent默认是nullif (parent != null) {parent.uncaughtException(t, e);} else {// 一般走进来,调用Thread.setDefaultUncaughtExceptionHandler(...)方法设置全局 handler进行处理Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler();if (ueh != null) {ueh.uncaughtException(t, e);} else if (!(e instanceof ThreadDeath)) {// 全局handler也不存在就输出异常栈System.err.print("Exception in thread \"" + t.getName() + "\" ");e.printStackTrace(System.err);}}}
}

Spring MVC异常处理机制

参考Spring MVC系列之九大核心组件中的HandlerExceptionResolver部分。

Spring MVC全局异常处理

每个Controller层里的方法都需要进行异常捕获及处理,显然太繁琐且效率低。

自定义类并实现HandlerExceptionResolver接口并重写resolveException方法进行全局异常处理:

@Slf4j
@Component
public class SimpleExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request, @NonNull HttpServletResponse response, Object object, @NonNull Exception e) {// 业务异常对前端可见,否则统一归为系统异常Map<String, Object> map = new HashMap<>();map.put("success", false);// 自定义业务异常,可多次if判断对应多个异常类型,当然也可使用switch语句if (e instanceof BusinessException) {map.put("errorMsg", e.getMessage());} else {map.put("errorMsg", "system exception");}log.error(e.getMessage(), e);// 此处返回ModelandView对象,如error.jsp页面,也可考虑使用其他的模板引擎,如FreeMarker,Thymeleafreturn new ModelAndView("/error", map);}
}

可以以不同的方式将异常结果返回给调用者(前端或其他后端服务)

  • 返回ModelAndView
  • 返回页面的地址
  • 返回JSON
  • 返回HTTP错误码

当然也可以使用下面Spring Boot全局异常处理方案。

Spring Boot全局异常处理

直接给出配置类:

@Slf4j
// 复合注解 = @ControllerAdvice + @ResponseBody
@RestControllerAdvice
public class GlobalExceptionHandler {// 别的方法都处理不了的异常@ExceptionHandler(Exception.class)public Response<Object> otherExceptionHandler(HttpServletResponse response, Exception ex) {response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());log.error(ex.getMessage(), ex);return Response.error("服务器内部异常!");}// 可捕获自定义异常、JDK或Spring异常,支持数组形式捕获多个不同类型的异常,但推荐一种异常对应一个方法@ExceptionHandler({ForbiddenException.class}) // 自定义业务异常// @ExceptionHandler({IllegalArgumentException.class}) // JDK异常// @ExceptionHandler(HttpMessageNotReadableException.class) // Spring异常// 返回Response Status Code@ResponseStatus(HttpStatus.FORBIDDEN)public Response<Object> forbidden(ForbiddenException e) {// 记录错误日志log.error(e.getMessage(), e);return Response.error(e.getMessage());}// 前端(或接口攻击者)使用非法的@RequestBody请求接口,解析异常字段,并将错误日志降级@ExceptionHandler(MethodArgumentNotValidException.class)public Response<Object> validationBodyException(MethodArgumentNotValidException exception) {BindingResult result = exception.getBindingResult();StringBuilder errorMsg = new StringBuilder();if (result.hasErrors()) {List<ObjectError> errors = result.getAllErrors();errors.forEach(p -> {FieldError fieldError = (FieldError) p;errorMsg.append(fieldError.getDefaultMessage()).append("!");// 设置warn而不是error,日志错误降级log.warn("Data check failure : object{" + fieldError.getObjectName() + "},field{" + fieldError.getField() + "},errorMessage{" + fieldError.getDefaultMessage() + "}");});}return Response.error(errorMsg.toString());}
}

Response是自定义的数据统一返回格式:

@Data
@NoArgsConstructor
public class Response<T> implements Serializable {private int code;private String msg;private T data;// 省略其他包装方法 
}

Dubbo处理异常

分布式调用链

参考

  • 谈谈异常
  • 从JVM角度理解try…catch
  • 利用jvmti查看java异常
  • UncaughtExceptionHandler相关问题解析

相关文章:

Java异常体系、UncaughtExceptionHandler、Spring MVC统一异常处理、Spring Boot统一异常处理

概述 所有异常都是继承自java.lang.Throwable类&#xff0c;Throwable有两个直接子类&#xff0c;Error和Exception。 Error用来表示程序底层或硬件有关的错误&#xff0c;这种错误和程序本身无关&#xff0c;如常见的NoClassDefFoundError。这种异常和程序本身无关&#xff0…...

bash终端快捷键

快捷键作用ShiftCtrlC复制ShiftCtrlV粘贴CtrlAltT新建终端ShiftPgUp/PgDn终端上下翻页滚动CtrlC终止命令CtrlD关闭终端CtrlA光标移动到最开始为止CtrlE光标移动到最末尾CtrlK删除此处到末尾的所有内容CtrlU删除此处至开始的所有内容CtrlD删除当前字符CtrlH删除当前字符的前一个…...

【Visual Studio】Visual Studio报错合集及解决办法

目录 Visual Studio报错:error LNK2001 Visual Studio报错:error C2061 Visual Studio报错:error C1075 Visual Studio报错:error C4430 Visual Studio报错error C3867 概述 持续更细Visual Studio报错及解决方法 Visual Studio报错:error LNK2001 问题 : error LNK2001…...

【微信小程序知识点】转发功能的实现

转发功能&#xff0c;主要帮助用户更流畅地与好友分享内容与服务。 想实现转发功能&#xff0c;有两种方式&#xff1a; 1.页面js文件必须声明onShareAppMessage事件监听函数&#xff0c;并自定义转发内容。只有定义了此事件处理函数&#xff0c;右上角菜单才会显示“转发”按…...

用python识别二维码(python实例二十三)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.识别二维码 3.1 代码构思 3.2 代码实例 3.3 运行结果 4.总结 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&…...

电脑文件夹怎么设置密码?让你的文件更安全!

在日常使用电脑的过程中&#xff0c;我们常常会有一些需要保护的个人文件或资料。为了防止这些文件被他人未经授权访问&#xff0c;对重要文件夹设置密码是一种有效的保护措施&#xff0c;可是电脑文件夹怎么设置密码呢&#xff1f;本文将介绍2种简单有效的方法帮助您为电脑文件…...

paddla模型转gguf

在使用ollama配置本地模型时&#xff0c;只支持gguf格式的模型&#xff0c;所以我们首先需要把自己的模型转化为bin格式&#xff0c;本文为paddle&#xff0c;onnx&#xff0c;pytorch格式的模型提供说明&#xff0c;safetensors格式比较简单请参考官方文档&#xff0c;或其它教…...

Memcached vs Redis——Java项目缓存选择

在Java项目开发中&#xff0c;缓存系统作为提升性能、优化资源利用的关键技术之一&#xff0c;扮演着至关重要的角色。Memcached和Redis作为两种流行的缓存解决方案&#xff0c;各有其独特的优势和应用场景。本文旨在通过分析项目大小、用户访问量、业务复杂度以及服务器部署情…...

大模型最新黑书:基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理 PDF

今天给大家推荐一本丹尼斯罗斯曼(Denis Rothman)编写的关于大语言模型&#xff08;LLM&#xff09;权威教程<<大模型应用解决方案> 基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理>&#xff01;Google工程总监Antonio Gulli作序&#xff0c;这含金量不…...

【电子数据取证】电子数据司法鉴定

文章关键词&#xff1a;电子数据取证、司法鉴定服务、司法鉴定流程 一、定义 什么是司法鉴定&#xff1f; 在诉讼活动中鉴定人运用科学技术或者专业知识对诉讼涉及的专门性问题进行鉴别和判断并提供鉴定意见的活动。 电子数据司法鉴定 那么电子数据司法鉴定&#xff0c;就…...

使用 OpenCV 的 inRange 函数进行颜色分割

使用 OpenCV 的 inRange 函数进行颜色分割 在图像处理领域&#xff0c;颜色分割是一个常见的任务&#xff0c;常用于识别和提取图像中的特定颜色区域。OpenCV 提供了一个非常方便的函数 inRange 来实现这一功能。在这篇博客中&#xff0c;我们将详细介绍 inRange 函数的用法&a…...

OpenAI终止对中国提供API服务,对国内AI市场产生重大冲击?

6月25日&#xff0c;OpenAI突然宣布终止向包括中国在内的国家地区提供API服务&#xff0c;本月9日这一政策已经正式生效了&#xff01; 有人说&#xff0c;这个事件给中国AI行业带来很大冲击&#xff01;是这样吗&#xff1f;在展开讨论前&#xff0c;我们先来看看什么是API服务…...

JavaDS —— 栈 Stack 和 队列 Queue

栈的概念 栈是一种先进后出的线性表&#xff0c;只允许在固定的一端进行插入和删除操作。 进行插入和删除操作的一端被称为栈顶&#xff0c;另一端被称为栈底 栈的插入操作叫做进栈/压栈/入栈 栈的删除操作叫做出栈 现实生活中栈的例子&#xff1a; 栈的模拟实现 下面是Jav…...

C++进阶:继承和多态

文章目录 ❤️继承&#x1fa77;继承与友元&#x1f9e1;继承和静态成员&#x1f49b;菱形继承及菱形虚拟继承&#x1f49a;继承和组合 ❤️多态&#x1fa77;什么是多态&#xff1f;&#x1f9e1;多态的定义以及实现&#x1f49b;虚函数&#x1f49a;虚函数的重写&#x1f499…...

【八大排序】java版(上)(冒泡、快排、堆排、选择排序)

文章目录 一、冒泡排序(重点)思路代码 二、快排(面试重点)思路代码 三、堆排序(面试重点)思路代码 四、选择排序思路代码 一、冒泡排序(重点) 思路 前后两两数据进行比较&#xff0c;小的数据往前走&#xff0c;大的数据往后走&#xff0c;每一轮结束之后&#xff0c;最大的数…...

.Net Core 微服务之Consul(二)-集群搭建

引言: 集合上一期.Net Core 微服务之Consul(一)(.Net Core 微服务之Consul(一)-CSDN博客) 。 目录 一、 Consul集群搭建 1. 高可用 1.1 高可用性概念 1.2 高可用集群的基本原理 1.3 高可用集群的架构设计 1.3.1 主从复制架构 1.3.2 共享存储架构 1.3.3 负载均衡…...

C++ --> 类和对象(二)

前言 在前面简单的介绍了OOP&#xff0c;什么是类&#xff0c;在类中的this指针。接下来就深入理解类和对象。 默认成员函数 默认构造函数&#xff1a;用于在创建对象时初始化对象的成员变量。默认拷贝构造函数&#xff1a;用于使用已存在的对象来初始化新创建的对象。默认析构…...

利用宝塔安装一套linux开发环境

更新yum&#xff0c;并且更换阿里镜像源 删除yum文件 cd /etc/yum.repos.d/ 进入yum核心目录 ls sun.repo rm -rf * 删除之前配置的本地源 ls 配置阿里镜像源 wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo 配置扩展包 wge…...

VB 实例:掌握 Visual Basic 编程的精髓

VB 实例:掌握 Visual Basic 编程的精髓 引言 Visual Basic(简称VB)是一种由微软开发的高级编程语言,它结合了易于使用的界面和强大的编程功能,使得初学者和专业人士都能快速开发Windows桌面应用程序。本文将通过一系列实例,深入探讨VB编程的基础知识和高级技巧,帮助读…...

层次分析法:matlab代码实现

计算权重&#xff1a; 一、算术平均法 关于矩阵&#xff1a; 1、矩阵的输入写法 [ ; ; ]同行用空格或逗号隔开&#xff0c;不同行用分号间隔 2、矩阵求和 默认按列求和 asum(E) 等同于 asum(E,1) 得到行向量 按行求和 asum(E,2) 得到列向量 对整个矩阵求和 asum(E,"all&…...

07-7.5.3 处理冲突的方法

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…...

几何距离与函数距离:解锁数据空间中的奥秘

几何距离&#xff1a;直观的空间度量 几何距离&#xff0c;顾名思义&#xff0c;是我们在几何学中熟悉的距离概念&#xff0c;如欧几里得距离、曼哈顿距离和切比雪夫距离等。这些距离度量直接反映了数据点在多维空间中的位置关系。 欧几里得距离&#xff1a;最为人熟知的几何距…...

LabVIEW的Actor Framework (AF) 结构介绍

LabVIEW的Actor Framework (AF) 是一种高级架构&#xff0c;用于开发并发、可扩展和模块化的应用程序。通过面向对象编程&#xff08;OOP&#xff09;和消息传递机制&#xff0c;AF结构实现了高效的任务管理和数据处理。其主要特点包括并发执行、动态可扩展性和强大的错误处理能…...

gitlab 搭建使用

1. 硬件要求 ##CPU 4 核心500用户 8 核心1000用户 ##内存 4 G内存500用户 8 G内存1000用户 2. 下载 链接 3. 安装依赖 yum -y install curl openssh-server postfix wget 4. 安装gitlab组件 yum -y localinstall gitlab-ce-15.9.3-ce.0.el7.x86_64.rpm 5. 修改配置文…...

探索JT808协议在车辆远程视频监控系统中的应用

一、部标JT808协议概述 随着物联网技术的迅猛发展&#xff0c;智能交通系统&#xff08;ITS&#xff09;已成为现代交通领域的重要组成部分。其中&#xff0c;车辆远程监控与管理技术作为ITS的核心技术之一&#xff0c;对于提升交通管理效率、保障道路安全具有重要意义。 JT8…...

视频使用操作说明书-T80005系列视频编码器如何对接海康NVR硬盘录像机,包括T80005系列高清HDMI编码器、4K超高清HDMI编码器

视频使用操作说明书-T80005系列视频编码器如何对接海康NVR硬盘录像机&#xff0c;包括T80005系列高清HDMI编码器、4K超高清HDMI编码器。 视频使用操作说明书-T80005系列视频编码器如何对接海康NVR硬盘录像机&#xff0c;包括T80005系列高清HDMI编码器、4K超高清HDMI编码器 同三…...

keep-alive缓存组件

keep-alive缓存组件是Vue.js中的一个特殊组件&#xff0c;主要用于缓存内部组件的数据状态&#xff0c;以提高应用的性能和用户体验。以下是关于keep-alive缓存组件的详细解析&#xff1a; 一、作用 缓存组件状态&#xff1a;当组件在<keep-alive>内部切换时&#xff0…...

Linux上如何安装ffmpeg视频处理软件

在Linux上安装ffmpeg需要以下步骤&#xff1a; 更新系统 在开始安装之前&#xff0c;首先需要更新系统以获取最新的软件包列表和版本。在终端中执行以下命令&#xff1a; sudo apt update sudo apt upgrade安装依赖库 ffmpeg依赖于一些库和工具&#xff0c;需要先安装它们。在…...

element如何实现自定义表头?

有时候我们需要实现自定义表头,例如表头里加按钮啥的,这时候就需要用到自定义表头,但是官方对自定义表头的使用写的还是比较简单,今天就来详细说说 在需要使用自定义表头的表头上使用:render-header来启用自定义表头: <el-table-column :render-header="button&…...

OTP防重放攻击

OTP本意是一次性口令&#xff0c;比如邮箱验证码&#xff0c;短信验证码&#xff0c;或者根据totp或者hotp生成的默认30秒一变的6位数字。 不过开发者要注意&#xff0c;必须要在验证成功后失效那个验证码&#xff0c;不然就会导致重放攻击。 对于邮箱验证码&#xff0c;服务器…...

自动的小企业网站建设/免费找精准客户的app

原本这些网络工程师考试的参考资料是放在中山大学的某论坛上的&#xff0c;但是论坛管理比较麻烦&#xff0c;而且访问速度比较慢&#xff0c;因此将它们贴到这里来。但是所有的文件还是放在中山大学的服务器上&#xff0c;大家可以使用支持断点续传的下载软件进行下载。虽然现…...

wordpress 防止机器人注册/杭州关键词排名工具

背景 Open-source error tracking that helps developers monitor and fix crashes in real time. Iterate continuously. Boost efficiency. Improve user experience. 总之是一个听起来非常牛逼的开源的报错收集服务&#xff0c;目前公司里有一个比较奇怪的现象&#xff0c;s…...

界首做网站/百度2023免费

HDU2527 构建哈夫曼树的灵巧运用上课老师说了知道哈夫曼树叶子 不构图求二叉树的权 就是在构造哈夫曼树的时候运用构图的方法 把每个结点的值加起来就是该数的权 证明 W∑叶子权*该叶子层数 除了叶子的结点和就是这个树的权构造一个树就知道了 结点的权 肯定是下一层结点的和 就…...

网站模/湖南seo优化首选

** 扑克牌排列** 下面代码模拟了一套扑克牌&#xff08;初始排序A~K&#xff0c;共13张&#xff09;的操作过程。 操作过程是&#xff1a; 手里拿着这套扑克牌&#xff0c;从前面拿一张放在后面&#xff0c;再从前面拿一张放桌子上&#xff0c;再从前面拿一张放在后面&#x…...

网站是什么软件/百度登录账号首页

hibernate缓存机制 sunRainAmazing 一、why&#xff08;为什么要用Hibernate缓存&#xff1f;&#xff09; Hibernate是一个持久层框架&#xff0c;经常访问物理数据库。为了降低应用程序对物理数据源访问的频次&#xff0c; 从而提高应用程序的运行性能。缓存内的数据是对物理…...

网站运营 广告/东莞网站推广营销

题目大意&&思路&#xff1a;快速幂取模&#xff0c;没看题RE了2次&#xff0c;因为指数为0的情况&#xff0c;囧。。还是用自己的模板&#xff0c;虽然有点繁琐&#xff0c;但是自己的更顺眼嘛~~~ AC program&#xff1a;#include<iostream> #include<stdio.…...