【Java面试篇】Spring中@Transactional注解事务失效的常见场景
文章目录
- `@Transactional`注解的失效场景
- ☁️前言
- 🍀前置知识
- 🍁场景一:`@Transactional`应用在非 public 修饰的方法上
- 🍁场景二: `propagation` 属性设置错误
- 🍁场景三:`rollbackFor`属性设置错误
- 🍁场景四:方法调用导致`@Transactional`失效
- 🍁场景五:异常捕获导致`@Transactional`失效
- 🍁场景六:数据库引擎不支持事务
- 🍁场景七:未启用事务
- 🍁场景八:Bean没有纳入Spring容器管理
- 🍁场景九:事务方法启动新线程进行异步操作
- 🍃总结
@Transactional
注解的失效场景
☁️前言
最初学习Spring时,B站的杨老师就说过“在工作中不要过于依赖
@Transactional
注解实现事务,我们不仅要掌握注解实现事务,还需要掌握通过配置文件实现事务”,当时他没有明确说为什么,现在我应该是大致了解了,因为@Transactional
注解对于新手而言是存在很多坑的,在很多情况下@Transactional
注解都会失效,现在就让我们来详细学习哪些情况下@Transactional
注解实现的事务会失效吧😄。PS:关于如何通过配置文件实现事务请参考Spring学习笔记
🍀前置知识
-
事务:指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。可以理解事务就是一段代码块或者一行SQL,这段代码或这行SQL会更新数据库,事务具有基本的ACID特性,以此保障数据的安全性。
-
事务管理:由事务管理器1、恢复管理器2、锁管理器3、死锁管理器4、缓存管理器5构成
-
事务管理的作用:管理事务相关的资源;更容易处理复杂的事务;简化事务相关的操作,让程序员更关注业务
-
Spring中提供了两种事务管理机制:
- 编程式事务:是指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强。(Spring提供了TransactionTemplate模板,利用该模板我们可以通过编程的方式实现事务管理,而无需关注资源获取、复用、释放、事务同步及异常处理等操作。相对于声明式事务来说,这种方式相对麻烦一些,但是好在更为灵活,我们可以将事务管理的范围控制的更为精确)
- 声明式事务:基于
AOP
面向切面的,它将具体业务与事务处理部分解耦,代码侵入性很低。而声明式事务有两种方式实现,方式一是基于@Transaction
注解实现,方式二是基于XML
实现。(Spring事务管理的亮点在于声明式事务管理,它允许我们通过声明的方式,在IoC配置中指定事务的边界和事务属性,Spring会自动在指定的事务边界上应用事务属性。相对于编程式事务来说,这种方式十分的方便,只需要在需要做事务管理的方法上,增加@Transactional注解,以声明事务特征即可)
大多数 Spring 框架的用户选择声明式事务管理,因为它对应用代码的影响最小, 因此更符合一个无侵入的轻量级容器的思想。声明式事务管理要优于编程式事务 管理,虽然比编程式事务管理(这种方式允许你通过代码控制事务)少了一点灵 活性。
-
@Transactional:可以作用在接口、类、方法
- 作用于接口:不推荐这种使用方法,因为一旦标注在
Interface
上并且配置了Spring AOP 使用CGLib
动态代理,将会导致@Transactional
注解失效 - 作用于类:当把
@Transactional
注解放在类上时,代表这个类所有公共(public)非静态(static)的方法都将启用事务功能,且都会被 Spring 的事务管理器进行管理 - 作用于方法:当把
@Transactional
配置在方法上,该方法被当成一个独立的事务,且被事务管理器管理。当类配置了@Transactional
,方法也配置了@Transactional
,此时方法的事务会覆盖类的事务配置信息
- 作用于接口:不推荐这种使用方法,因为一旦标注在
-
@Transactional的属性
-
propagation
属性propagation
代表事务的传播行为,默认值为Propagation.REQUIRED
,其他的属性信息如下:-
Propagation.REQUIRED
:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。 也就是说如果A方法和B方法都添加了注解,在默认传播模式下,A方法内部调用B方法,会把两个方法的事务合并为一个事务 -
Propagation.SUPPORTS
:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行 -
Propagation.MANDATORY
:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常 -
Propagation.REQUIRES_NEW
:重新创建一个新的事务,如果当前存在事务,暂停当前的事务。( 当类A中的 a 方法用默认Propagation.REQUIRED
模式,类B中的 b方法加上采用Propagation.REQUIRES_NEW
模式,然后在 a 方法中调用 b方法操作数据库,然而 a方法抛出异常后,b方法并没有进行回滚,因为Propagation.REQUIRES_NEW
会暂停 a方法的事务 ) -
Propagation.NOT_SUPPORTED
:以非事务的方式运行,如果当前存在事务,暂停当前的事务 -
Propagation.NEVER
:以非事务的方式运行,如果当前存在事务,则抛出异常 -
Propagation.NESTED
:和Propagation.REQUIRED
效果一样
-
-
isolation
属性事务的隔离级别,默认值为
Isolation.DEFAULT
-
Isolation.DEFAULT
:使用底层数据库默认的隔离级别。 -
Isolation.READ_UNCOMMITTED
:读取未提交数据(会出现脏读, 不可重复读) 基本不使用 -
Isolation.READ_COMMITTED
:读取已提交数据(会出现不可重复读和幻读) -
Isolation.REPEATABLE_READ
:可重复读(会出现幻读) -
Isolation.SERIALIZABLE
:串行化
-
-
timeout
属性:事务的超时时间,默认值为 -1。如果超过该时间限制但事务还没有完成,则自动回滚事务 -
readOnly
属性:指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置readonly
为true
-
rollbackFor
属性:用于指定能够触发事务回滚的异常类型,可以指定多个异常类型 -
noRollbackFor
属性:抛出指定的异常类型,不回滚事务,也可以指定多个异常类型
-
🍁场景一:@Transactional
应用在非 public 修饰的方法上
@Transactional
注解修饰的方法必须是public
修饰的,同样的@Transactional
修饰类时,也只有类中使用pulbic
修饰的方法才能成为事务。须知:使用@Transactional修饰的方法,必须是public修饰、非static修饰、非final修饰的,一个不满足就会导致事务失效
原因:
由于Spring的事务是通过AOP实现的,在AOP代理时,事务拦截器TransactionInterceptor
在目标方法执行前后进行拦截,DynamicAdvisedInterceptor
(CGlib动态代理时的事务拦截器)的 intercept
方法或 JdkDynamicAopProxy
(JDK动态代理时的代理对象)的 invoke
方法都会间接调用 AbstractFallbackTransactionAttributeSource
的 computeTransactionAttribute
方法,获取Transactional
注解的事务配置信息,如下图所示:
备注:在老版本的Spring中,这个需要十分注意,因为当我们在非pulic
方法上加@Transactional
,它在编译阶段是没有任何报错信息的,但是新版的Spring是能够在编译阶段就能够进行报错,所以只要是使用较新版本的版本,基本没可能会犯这种错误,比如我当前使用的Spring版本是5.2.15,直接就在编译阶段报错了:
🍁场景二: propagation
属性设置错误
当我们将
propagation
属性的值设置为一下几种取值就会导致事务失效:
Propagation.NOT_SUPPORTED
:以非事务的方式运行,如果当前存在事务,暂停当前的事务
Propagation.NEVER
:以非事务的方式运行,如果当前存在事务,则抛出异常
🍁场景三:rollbackFor
属性设置错误
Spring默认抛出了未检查
unchecked
异常(继承自RuntimeException
的异常)或者Error
才回滚事务;其他异常不会触发回滚事务。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定rollbackFor
属性;若在目标方法中抛出的异常是rollbackFor
指定的异常的子类,事务同样会回滚。
[
Spring底层通过getDepth
方法来判断出现异常是否需要进行事务回滚
🍁场景四:方法调用导致@Transactional
失效
同一个类中,A方法是非事务性方法,但是B方法是事务性方法,此时A调用B就会导致B的事务失效。
原因:
这个和场景一的原因是类似的,事务的实现是基于AOP的,而AOP的实现又是基于动态代理的,而动态代理的本质就算对方法的增强,如果想要使用增强的方法(也就是想要使用事务方法),就必须是通过代理对象去触发目标对象的方法,这个我相信只要学过设计模式都是能够理解的。
解决方案:
通过
AopContext.currentProxy()
这个API获取当前类的代理对象
示例:
@Service
Class ServiceImpl implements IService{// 普通方法@Overridepublic Result A() {......IService proxy = (Iservice) AopContext.currentProxy();return proxy.B();}// 事务方法@Override@Transactionalpublic Result B() {......return Result.ok();}
}
推荐阅读:每日一个设计模式之【代理模式】
🍁场景五:异常捕获导致@Transactional
失效
当一个事务方法中抛出了异常,此时该异常通过
try...catch
进行了捕获,此时就会导致该方法的事务注解@Transactional
失效
示例:
@Resource
private IBService bService;@Service
Class AServiceImpl implements IAService{@Transactionalpublic Result A(Student s) {try {bService.save(s);} catch (Exception e) {e.printStackTrace();}return Result.ok();}
}
此时会报错org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
原因:因为bService执行save方法过程中出现了异常,所以bService告诉事务管理器,当前事务需要被rollback
,但是aService中使用try...catch
捕获了异常,它认为当前事务并没有发生异常,程序是处于正常状态,于是aService就告诉事务管理器,当前事务需要被commit
,结果事务管理器发现收到两个矛盾的信号,它也搞不清是该rollback还是该commit,于是就抛了个UnexpectedRollbackException
异常。
也就是说Spring中,事务是在方法调用时开始的,业务方法执行完毕后才执行rollback或commit操作,事务是否被回滚取决于是否抛出异常,且该异常是否满足场景三(也就是说抛出的异常是否有被rollbackFor
指定,或rollbackFor
指定异常的子类)。如果一定要使用try..catch
时,一定要抛出异常(且抛出的异常必须满足场景三,一般直接抛一个运行时异常就可以了 throw new RuntimeException()
,运行时异常是rollbackFor
默认指定的异常),而不只是打印异常信息。
综上所诉:在Service层中,方法中最好不要随便写try...catch
,如果写了则一定要手动抛异常
🍁场景六:数据库引擎不支持事务
Spring的事务本质还是得靠数据库引擎的支持,如果数据库引擎不支持事务,那么Spring就算使用事务也是白搭。常用的MySQL数据库默认使用支持事务的
innodb
引擎。一旦数据库引擎切换成不支持事务的myisam
,那事务就从根本上失效了。当然相信这个问题出现的概率很小,但并不代码没有,我们还是需要有一定了解的
注意:从 MySQL 5.5.5 开始的默认存储引擎是:InnoDB,之前默认的都是:MyISAM。也就是说是从MySQL5.5.5开始,MySQL才支持事务
🍁场景七:未启用事务
想要
@Transactional
注解实现声明式事务,首先就需要开启事务,开启事务就三步:
- 配置事务管理器
- 开启事务的注解驱动
- 使用
@Transactional
PS:这个事件对于向我这种初学者来说概率还是存在的,对于老手应该不太可能会出现这种低级错误了😄
开启事务相关配置:
<!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSourceRef"></property></bean><!--开启事务的注解驱动,将事务管理器中的环绕通知作用到连接点,连接点使用@Transactional进行标识transaction-manager属性用于指定事务管理器,默认是transactionManager这个id名--><tx:annotation-driven transaction-manager="transactionManager"/>
备注:在SpringBoot中,只需要在启动类上添加@EnableAspectJAutoProxy(exposeProxy = true)
这个注解,就能使用基于注解实现的声明式事务了,等价于上面的配置
🍁场景八:Bean没有纳入Spring容器管理
Spring的事务管理核心是动态代理,不是动态代理的Bean是无法进行被Spring进行事务管理的
将Bean纳入Spring容器管理的方法:
-
方式一:配置XML
<bean id="xxx" class="xxx.xxx.xxx"></bean>
-
方式二:添加注解,比如:@Controller、@Service、@Repository、@Conponent……
🍁场景九:事务方法启动新线程进行异步操作
spring 的事务是通过LocalThread来保证线程安全的,事务和当前线程绑定,此时开启新线程执行业务,这个新线程的业务就会事务失效,因为事务是基于动态代理的,要想有事务,需要被动态代理。这里提供一种解决方法,可以将新的业务单独封装成一个方法,然后改方法上添加一个@Transactional,或者将这个无法单独抽取到一个类中,将该类交给IOC容器进行管理,这样就能让新线程的业务具有事务了
🍃总结
@Transactional
使用事务具有几个基本的要求:
- 必须开启注解事务
- 事务所在类,必须要交给IOC容器进行管理
- 事务所在目标,必须要进行动态代理
- 事务所在方法必须要是public
总而言之,使用@Transactional来启动事务,有很多坑,对于简单的业务还是推荐直接使用注解进行事务管理,对于复杂的业务还是推荐使用XML进行事务管理
参考文章:
- 一口气说出 6种,@Transactional注解的失效场景 - 掘金 (juejin.cn)
- 咱们从头到尾说一次 Spring 事务管理(器) - 掘金 (juejin.cn)
- spring 事务失效的 12 种场景-CSDN博客
在此致谢(^^ゞ🌹🌹🌹
事务管理器:负责产生事务并为其分配事务标识 ↩︎
恢复管理器:子事务提交时,负责将子事务的日志链接到父事务的日志上,确保事务的一致性原则 ↩︎
锁管理器:事务申请锁时,负责判断锁的相容性 ↩︎
死锁管理器:负责检测死锁 ↩︎
缓存管理器:提供对事务标识的缓存 ↩︎
相关文章:
【Java面试篇】Spring中@Transactional注解事务失效的常见场景
文章目录Transactional注解的失效场景☁️前言🍀前置知识🍁场景一:Transactional应用在非 public 修饰的方法上🍁场景二: propagation 属性设置错误🍁场景三:rollbackFor属性设置错误dz…...
【C】分配内存的函数
#include <stdlib.h>//分配所需的内存空间,并返回一个指向它的指针。 void *malloc(size_t size);//分配所需的内存空间,并返回一个指向它的指针。并且calloc负责把这块内存空间用字节0填//充,而malloc并不负责把分配的内存空间清零 vo…...
IDEA 断点总是进入class文件没有进入源文件解决
前言 idea 断点总是进入class文件没有进入源文件解决 问题 在源文件里打了断点,断点模式启动时却进入了class文件里的断点,而没有进入到java源文件里的断点。 比如:我在 A.java 里打了断点,调试时却进入到了 jar 包里的 A.clas…...
【flink】 flink入门教程demo 初识flink
文章目录通俗解释什么是flink及其应用场景flink处理流程及核心APIflink代码快速入门flink重要概念什么是flink? 刚接触这个词的同学 可能会觉得比较难懂,网上搜教程 也是一套一套的官话, 如果大家熟悉stream流,那或许会比较好理解…...
LeetCode 1487. 保证文件名唯一
【LetMeFly】1487.保证文件名唯一 力扣题目链接:https://leetcode.cn/problems/making-file-names-unique/ 给你一个长度为 n 的字符串数组 names 。你将会在文件系统中创建 n 个文件夹:在第 i 分钟,新建名为 names[i] 的文件夹。 由于两个…...
详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路
袋鼠云数栈从2016年发布第⼀个版本开始,就始终坚持着以技术为核⼼、安全为底线、提效为⽬标、中台为战略的思想,坚定不移地⾛国产化信创路线,不断推进产品功能迭代、技术创新、服务细化和性能升级。 在数栈过去的产品迭代中受限于当前组件的…...
【C++PrimerPlus】第三章 处理数据
文章目录前言内容目录3.1 简单变量3.1.2 变量名3.1.2 整形3.1.3 整形short,int,long,long long3.1.4 无符号类型3.1.5 选择整形类型3.1.6 整形字面值3.1.7 C如何确定常量的类型3.1.8 char类型:字符和小整数3.1.9 bool类型3.2 const修饰符3.3浮点数3.3.1 书写浮点数3…...
【基础算法】单链表的OJ练习(1) # 反转链表 # 合并两个有序链表 #
文章目录前言反转链表合并两个有序链表写在最后前言 上一章讲解了单链表 -> 传送门 <- ,后面几章就对单链表进行一些简单的题目练习,目的是为了更好的理解单链表的实现以及加深对某些函数接口的熟练度。 本章带来了两个题目。一是反转链表&#x…...
离散数学笔记(1)命题逻辑
文章目录1.命题符号化及联结词基本概念本节题型2.命题公式及分类基本概念本节题型1.命题符号化及联结词 基本概念 命题的定义:能够判断真假的陈述句称为命题。 备注:感叹句、疑问句、祈使句和类似于xy>5之类真值不唯一的句子都不是命题。 真值的真假…...
IDEA Android 网格布局(GridLayout)示例(计算器界面布局)
网格布局(GridLayout) 示例程序效果(实现类似vivo手机自带计算器UI) 真机和模拟器运行效果: 简述: GridLayout(网格布局)和TableLayout(表格布局)有类似的地方,通俗来讲可以理解为…...
【蓝桥杯嵌入式】拓展板之数码管显示
文章目录硬件电路连接方式函数实现文章福利硬件电路 通过上述原理图,可知拓展板上的数码管是一个共阴数码管,也就是说某段数码管接上高电平时,就会点亮。 上述原理图还给出一个提示,即:三个数码管分别与三个74HC59…...
Web Spider案例 网洛克 第三题 AAEncode加密 练习(七)
声明 此次案例只为学习交流使用,抓包内容、敏感网址、数据接口均已做脱敏处理,切勿用于其他非法用途; 文章目录声明一、资源推荐二、逆向目标三、抓包分析 & 下断分析逆向3.1 抓包分析3.2 下断分析逆向拿到混淆JS代码3.3 AAEncode解决方…...
【javaScript面试题】2023前端最新版javaScript模块,高频24问
🥳博 主:初映CY的前说(前端领域) 🌞个人信条:想要变成得到,中间还有做到! 🤘本文核心:博主收集的关于javaScript的面试题 目录 一、2023javaScript面试题精选 1.js的数据类型…...
Hadoop集群启动从节点没有DataNode
一、问题背景 之前启动hadoop集群的时候都没有问题,今天启动hadoop集群的时候,从节点的DataNode没有启动起来。 二、解决思路 遇见节点起不来的情况,可以去看看当前节点的日志文件 我进入当前从节点的hadoop安装目录的Logs文件下去查看日…...
FIFO IP Core
FIFO IP Core 先进先出的缓存器常常被用于数据的缓存,或者高速异步数据交互(跨时钟信号传递)和RAM和ROM的区别是没有地址线,无法指定地址 写时钟(Write Clock Domain),读时钟写复位(wr_rst),读…...
从FPGA说起的深度学习(四)
这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工智能领域的热门话题。在本教程中,旨在加深对深度学习和 FPGA 的理解。用 C/C 编写深度学习推理代码高级综合 (HLS) 将 C/C 代码转换为硬…...
pytorch入门7--自动求导和神经网络
深度学习网上自学学了10多天了,看了很多大神的课总是很快被劝退。终于,遇到了一位对小白友好的刘二大人,先附上链接,需要者自取:https://b23.tv/RHlDxbc。 下面是课程笔记。 一、自动求导 举例说明自动求导。 torch中的…...
QT 之wayland 事件处理分析基于qt5wayland5.14.2
1. Qt wayland 初始化 接收鼠标/案件,触摸屏等事件事件 QWaylandNativeInterface : public QPlatformNativeInterface 在QWaylandNativeInterface 继承qpa 接口类QPlatformNativeInterface; 1.1 初始化鼠标: void *QWaylandNativeInterface::nativeR…...
【this 和 super 的区别】
在 Java 中,this 和 super 都是关键字,表示当前对象和父类对象。 this 关键字可以用于以下几种情况: 引用当前对象的成员变量,方法和构造方法,用于区分局部变量和成员变量重名的情况; 调用当前类的另外一…...
K8s:Monokle Desktop 一个集Yaml资源编写、项目管理、集群管理的 K8s IDE
写在前面 Monokle Desktop 是 kubeshop 推出的一个开源的 K8s IDE相关项目还有 Monokle CLI 和 Monokle Cloud相比其他的工具,Monokle Desktop 功能较全面,涉及 k8s 管理的整个生命周期博文内容:Monokle Desktop 下载安装,项目管理…...
自动化测试实战篇(8),jmeter并发测试登录接口,模拟从100到1000个用户同时登录测试服务器压力
首先进行使用jmeter进行并发测试之前就需要搞清楚线程和进程的区别还需要理解什么是并发、高并发、并行。还需要理解高并发中的以及老生常谈的,TCP三次握手协议和TCP四次握手协议**TCP三次握手协议指:****TCP四次挥手协议:**进入Jmeter&#…...
ATTCK v12版本战术实战研究—持久化(二)
一、前言前几期文章中,我们介绍了ATT&CK中侦察、资源开发、初始访问、执行战术、持久化战术的知识。那么从前文中介绍的相关持久化子技术来开展测试,进行更深一步的分析。本文主要内容是介绍攻击者在运用持久化子技术时,在相关的资产服务…...
python函数式编程
1 callable内建函数判断一个名字是否为一个可调用函数 >>> import math >>> x 1 >>> y math.sqrt >>> callable(x) False >>> callable(y) True 2 记录函数(文档字符串) >>> def square(x): …...
3.linux下安装mysql
1.安装前的环境准备 查看是否安装过mysql 首先检测Linux操作系统中是否安装了MySQL: # rpm -qa | grep -i mysql 卸载安装包 如果有信息出现,则进行删除,命令如下: # rpm -e --nodeps 包名 删除老版本mysql的开发头文件和…...
17、MySQL分库分表,原理实战
MySQL分库分表,原理实战 1.MyCAT分布式架构入门及双主架构1.1 主从架构1.2 MyCAT安装1.3 启动和连接1.4 配置文件介绍2.MyCAT读写分离架构2.1 架构说明2.2 创建用户2.3 schema.xml2.4 连接说明2.5 读写测试2.6 当前是单节点3.MyCAT高可用读写分离架构3.1 架构说明3.3 schema.xm…...
【C++的OpenCV】第九课-OpenCV图像常用操作(六):图像形态学-阈值的概念、功能及操作(threshold()函数))
目录一、阈值(thresh)的概念二、阈值在图形学中的用途三、阈值的作用和操作3.1 在OpenCV中可以进行的阈值操作3.2 操作实例3.2.1 threshold()函数介绍3.2.2 实例3.2.3 结果上节课的内容(作者还是鼓励各位同学按照顺序进行学习哦)&…...
[Java代码审计]—MCMS
环境搭建 MCMS 5.2.4:https://gitee.com/mingSoft/MCMS/tree/5.2.4/利用 idea 打开项目 创建数据库 mcms,导入 doc/mcms-5.2.8.sql 修改 src/main/resources/application-dev.yml 中关于数据库设置参数 启动项目登录后台 http://localhost:8080/ms/l…...
《程序员面试金典(第6版)》面试题 01.08. 零矩阵
题目描述 编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。 示例1: 输入:[1, 2, 3, 3, 2, 1] 输出:[1, 2, 3] -示例2: 输入:[1, 1, 1, 1, 2] 输出:[1, 2] 提示: 链表长度在[0, 20000]范…...
初识 Python
文章目录简介用途解释器命令行模式交互模式输入和输出简介 高级编程语言,解释型语言代码在执行时会逐行翻译成 CPU 能理解的机器码代码精简,但运行速度慢基础代码库丰富,还有大量第三方库代码不能加密 用途 网络应用工具软件包装其他语言开…...
常用sql语句分享
SELECT COUNT(DISTINCT money) FROM ac_association_course;#COUNT() 函数返回匹配指定条件的行数SELECT AVG(money) FROM ac_association_course;#AVG 函数返回数值列的平均值。NULL 值不包括在计算中SELECT id FROM ac_association_course order by id desc limit 1;#返回最大…...
企业搭建pc端网站/简单网站建设优化推广
感谢Sunny秋刀鱼。https://www.cnblogs.com/527289276qq/p/5595798.html 在页面或者窗口Unloaded事件中关闭串口即可。转载于:https://www.cnblogs.com/dotnetHui/p/8513592.html...
市住房和城乡建设委员会官方网站/优化的意思
离散数学集合运算C或C语言实验报告离散数学实验报告1.【实验2.【实验目的3.【实验内容实验1)用数组A,B,C,E表示集合。假定A{1,3,4,5,6,7,9&#x…...
cnzz网站代做/下载百度网盘app最新版
文章目录一、C的const关键字二、const在类中的含义一、C的const关键字 这里可以分为两种情况: 一种是类似与C语言里面的 const char*,char* const; 一种是C用于类里面限定函数的。 const int* // const关键字 const int MAX_AGE 100; con…...
沈阳专业网站制作/seo任务平台
第6章——集合引用类型6.本章内容将浏览器偏好语言设置为英文6.1 Object6.1.1 使用new Object()创建实例6.1.2 使用对象字面量表示法创建实例6.1.3 两种创建方式的区别——用字面量更好6.1.4 使用对象中的属性——点语法/中括号6.2 Array6.2.1 创建数组6.2.2 数组空位——不建议…...
徐州网站建设公司/关键词搜索工具app
springboot 默认 只支持模板引擎。 有时候我们可能需要引入 jsp,那么就得整合jsp了。 1.pom里面添加: <dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId></dependency><!-- jasper …...