`
Lincoln
  • 浏览: 81092 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

持久层设计与资源管理模式笔记

阅读更多

     持久层设计与资源管理模式
无论是怎样的应用系统,都无法脱离对资源的管理和使用。而对于持久层而言,资源的合理管理和调度则显得尤为重要。

在大多数应用系统中,80%以上的应用逻辑并不需要特别复杂的数据库访问逻辑(可能只是几条简单的Select或作者Insert/Update语句)。对于这些占到多数的简单逻辑而言,如果SQL语句和数据库本身的设计不是太糟糕(合适的关联,字段索引以及数据库分区策略),在特定的硬件环境下,我们认为数据库的性能基本稳定。
此时,导致持久层性能地下的罪魁祸首可能并不是数据库本身,而是在于失败的资源管理调度机制。

Connection Pool
即使对于我们而言,通过JDBC获取数据库连接实在是件再简单不过的事情,但对于JDBC Driver来说,连接数据库却并非一件轻松差事。数据库连接不仅仅是在应用服务器与数据库服务器之间建立一个Socket Connection(对于Type4 的JDBC Driver而言),连接建立之后,应用服务器和数据库服务器之间还需要交换若干次数据(验证用户密码,权限等),然后,数据库开始初始化连接会话句柄,记录联机日志,为此连接分配相应得处理进程和系统资源。

系统如此忙碌,如果我们只是简单地仍过去两个SQL语句,然后就将此连接抛弃,实在可惜,而数据库连接池技术正是为了解决这个问题。
数据库连接池的基本原理是在内部对象池中维护一定数量的数据库连接,并对外暴露数据库连接获取或返回方法。如图

   数据库连接池基本原理示意
外部使用者可以通过getConnection方法获取连接,使用完毕后再通过releaseConnection方法将连接返回,注意此时连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备。
数据连接池技术带来下面的优势:
1. 资源重用
由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。
2. 更快的系统响应速度
数据库连接池仔初始化过程中,往往已经创建了若干数据库连接池置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。
3. 新的资源分配手段
对于应用共享同一个数据库的系统而言,可在应用曾通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。
4. 统一的连接管理,避免数据库连接泄露
在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用连接。从而避免了常规数据库连接操作中可能出现的资源泄露。
一个最小化的数据库连接池实现:

package net.wanjin.lab.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;

public class ConnectionPool {
	
	private static Vector pool;
	private final int POOL_MAX_SIZE =20;
	/**
	 * 获取数据库连接
	 * 如果当前池中有可用连接,则将池中最后一个返回,如果没有,则新建一个返回
	 * @return
	 * @throws DBException
	 */
	public synchronized Connection getConnection() throws DBException{
		
		if(pool ==null){
			pool = new Vector();
		}
		Connection conn;
		if(pool.isEmpty()){
			conn = createConnection();
		}else{
			int last_idx = pool.size() -1;
			conn =(Connection)pool.get(last_idx);
			pool.remove(pool.get(last_idx));
			
		}
		return conn;
	}
	/**
	 * 将使用完毕的数据库连接放回备用池
	 * 
	 * 判断当前池中连接数是否已经超过阀值
	 * 如果超过,则关闭该连接
	 * 否则放回池中以备下次重用
	 * @param conn
	 */
	public synchronized void releaseConnection(Connection conn){
		
		if(pool.size()>POOL_MAX_SIZE){
			try{
				conn.close();
			}catch(SQLException e){
				e.printStackTrace();
			}
		}else{
			pool.add(conn);
		}
	}
	/**
	 * 读取数据库配置信息,并从数据库连接池中获得数据库连接
	 * @return
	 * @throws DBException
	 */
	private static Connection createConnection() throws DBException{
		Connection conn;
		try{
			Class.forName("oracle.jdbc.driver.OracleDriver");
			conn = DriverManager.getConnection("jdbc:oracle:thin:@1521:oracle","personal","personal");
			return conn;
		}catch(ClassNotFoundException e){
			throw new DBException("ClassNotFoundException when loading JDBC Driver");
		}catch(SQLException e){
			throw new DBexception("SQLException when loading JDBC Driver");
		}
	}

}

完备的连接池实现固然错综复杂,但就其根本而言,还是源自同样的思想。

先脱离连接池本身的具体实现,我们看看这段代码在实际应用中可能产生的问题,注意到,由于getConnection方法返回的是一个标准的JDBC Connection,程序员由于编成习惯,可能会习惯性的调用其close方法关闭连接。如此一来,连接无法得到重用,数据库连接池机制形同虚设。为了解决这个问题,比较好的途径有:
1. Decorator 模式
2. Dynamic Proxy 模式
下面我们就这两种模式进行一些探讨:
“Decorator模式的主要目的是利用一个对象,透明地为另一个对象添加新的功能”。
这句话是从GOF关于设计模式的经典著作《设计模式-可复用面向对象软件的基础》一书中关于Decorator模式的描述直译而来,可能比较难以理解。简单来讲,就是通过一个Decorator对原有对象进行封装,同时实现与原有对象相同的接口,从而得到一个基于原有对象的,对既有接口的增强性实现。


对于前面所讨论的Connection释放的问题,理所当然,我们首先想到的是,如果能让JDBC Connection在执行close操作时自动返回到数据库连接池中,那么所有问题都将迎刃而解,但是,JDBC Connection自己显然无法根据实际情况判断何去何从。此时,引入Decorator模式来解决我们所面对的问题就非常合适。

首先,我们引入一个ConnectionDecorator类:
import java.sql.Connection;
import java.sql.SQLException;



public class ConnectionDecorator implements Connection {
	Connection dbconn;
	
	public ConnectionDecorator(Connection conn){
		this.dbconn = conn; //实际从数据库获得的Connection引用
	}
	
	/**
	 * 此方法将被子类覆盖,以实现数据库连接池的连接返回操作
	 * @see java.sql.Connection#close()
	 */
	public void close() throws SQLException{
		this.dbconn.close();
	}
	/**
	 * (non-Javadoc)
	 * @see java.sql.Connectionn#commit()
	 */
	public void commit() throws SQLException{
		this.dbconn.commit(); //调用实际连接的commit方法
	}
	//以下各个方法类似,均调用dbconn.xxx方法作为Connection接口中方法的简单实现.

}

可以看到,ConnectionDecorator类实际上的对传入的数据库连接加上一个外壳,他实现了java.slq.Connection接口,不过本身并没有实现任何实际内容,只是简单的把方法的实现委托给运行期实际获得的Connection实例,,而从外部来看,ConnctionDecorator与普通Connection实例并没有什么区别,因为他们实现了同样的接口,对外提供了同样的功能调用。

目标很清楚,通过这样的封装,我们的ConnectionDecorator对于外部的程序员而言,调用方法与普通的JDBC Connection完全相同,而在内部通过对ConnectionDecorator的修改,我们就可以透明地改变现有实现,为了增加新的特性:

package net.wanjin.lab.persistence.Decorator;

import java.sql.Connection;

import net.wanjin.lab.utils.ConnectionPool;

public class PooledConnection extends ConnectionDecorator implements Connection{
	
	private ConnectionPool connPool;
	
	public PooledConnection(ConnectionPool pool,Connection conn){
		super(conn);
		connPool = pool;	
	}
	/**
	 * 覆盖Close方法,将数据库连接返回连接池,而不是直接关闭连接
	 */
	public void close() throws SQLException{
		connPool.releaseConnection(this.dbconn);
	}
}
为了应用新的PooledConnection ,我们需要对原本的DBConnectionPool.getConnection和releaseConnection方法稍做改造:

	/**
	 * 获取数据库连接
	 * 如果当前池中有可用连接,则将池中最后一个返回,如果没有,则新建一个返回
	 * @return
	 * @throws DBException
	 */
	public synchronized Connection getConnection() throws DBException{
		
		if(pool ==null){
			pool = new Vector();
		}
		Connection conn;
		if(pool.isEmpty()){
			conn = createConnection();
		}else{
			int last_idx = pool.size() -1;
			conn =(Connection)pool.get(last_idx);
			pool.remove(pool.get(last_idx));
			
		}
		//return conn;
		return new PooledConnection(this,conn);
	}
	/*
	 * 将使用完毕的数据库连接放回备用池
	 * 
	 * 判断当前池中连接数是否已经超过阀值
	 * 如果超过,则关闭该连接
	 * 否则放回池中以备下次重用
	 * @param conn
	 */
	public synchronized void releaseConnection(Connection conn){
		
		if(conn instanceof PooledConnection||pool.size()>POOL_MAX_SIZE){
			try{
				conn.close();
			}catch(SQLException e){
				e.printStackTrace();
			}
		}else{
			pool.add(conn);
		}
	}
此时获取数据库连接后,调用这只需要按照JDBC Connection的标准用法进行调用即可,从而实现了数据库连接的透明化。同样的道理,我们甚至可以利用Decorator模式对DriverManager类进行同样的改造,从而最小化数据库连接池实现对传统JDBC编码方式的影响。

Dynamic Proxy 模式
DynamicProxy是JDK1.3版本中新引入的一种代理机制。严格来讲,DynamicProxy本身并非一种模式,只能算是Proxy模式的一种动态实现方式,不过为了与传统Proxy模式相区分,这里暂且将其称为“Dynamic Proxy模式”,来泛指通过Dynamic Proxy机制实现的Proxy模式。
回到上面的问题,我们的目标是在引入数据库连接池机制的同时,保持JDBCConnection对外接口不变。前面通过Decorator接口中定义的方法众多,我们也只是能照单全收,在ConnecionDecorator中逐一实现这些方法,虽然只是简单的委托实现,也实在是件恼人的工作。
Dynamic Proxy模式则良好地解决了这一问题。通过实现一个邦定到Connection对象的InvocationHandler接口实现,我们可以在Connection.close方法被调用时将其截获,并以我们自己实现的Close方法将其代替,使连接返回到数据库连接池等待下次重用,而不是直接关闭。

下面是ConnectionHandler类,它实现了InvocationHandler接口,按照DynamicProxy机制的定义,Invoke方法将截获所有代理对象的方法调用操作,这里我们通过invoke方法截获close方法进行处理。

package net.wanjin.lab.utils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;



public class ConnectionHandler implements InvocationHandler {
	
	Connection dbconn;
	ConnectionPool pool;
	
	public ConnectionHandler(ConnectionPool connPool){
		this.pool = connPool;
	}
	/**
	 * 
	 */
	public Connection bind(Connection conn){
		this.dbconn = conn;
		
		Connection proxyConn =(Connection)Proxy.newProxyInstance(
				conn.getClass().getClassLoader(),conn.getClass().getInterfaces(),this);
		
		return proxyConn;
	}
	
	public Object invoke(Object proxy,Method method,Object[] args)
	throws Throwable{
		Object obj =null;
		//如果调用的是close方法,则用pool.releaseConnection方法将其替换
		if("close".equals(method.getName())){
			pool.releaseConnection(dbconn);
		}else{
			obj = method.invoke(dbconn, args);
		}
		return obj;
		
	}

}

配合Dynamic Proxy模式,我们的DBConnectionPool.getConnection方法也做了一点小的修改:
	/**
	 * 获取数据库连接
	 * 如果当前池中有可用连接,则将池中最后一个返回,如果没有,则新建一个返回
	 * @return
	 * @throws DBException
	 */
	public synchronized Connection getConnection() throws DBException{
		
		if(pool ==null){
			pool = new Vector();
		}
		Connection conn;
		if(pool.isEmpty()){
			conn = createConnection();
		}else{
			int last_idx = pool.size() -1;
			conn =(Connection)pool.get(last_idx);
			pool.remove(pool.get(last_idx));
			
		}
		//return conn;
		//return new PooledConnection(this,conn);
		ConnectionHandler connHandler = new ConnectionHandler(this);
		return connHandler.bind(conn);
	}

可以看到,基于Dynamic Proxy 模式的实现相对Decorator更加简洁明了。
分享到:
评论

相关推荐

    win64 CC2022.zip

    SmartTools InDesign插件

    深度学习课程的课程设计-------基于ResNet优化模型的阿尔茨海默症的识别.zip

    深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。

    机械设计课程设计说明书_带式输送机传送装置_西北工业大学.doc

    机械设计课程设计说明书_带式输送机传送装置_西北工业大学.doc

    风格化欧洲城镇建筑场景模型:Modular European Town v1.1

    使用 “模块化欧洲小镇” 包来改变你的游戏世界!这个套装提供了你设计一个充满活力的低多边形城市所需的一切。 套装包括: 模块化建筑:各种结构可创造多样化的建筑设计。 自然元素:树木、灌木丛和植物,以增加你的小镇的绿色景观。 基础设施:道路、人行道、边界和墙壁,以构建一个逼真的布局。 不同的道具:很多物品,如消防栓、路灯、咖啡馆桌椅、垃圾桶、长椅等等。 所有模型都采用低多边形美学制作,确保出色的性能和独特的视觉风格。这个套装非常适合所有平台上的游戏:移动设备、桌面电脑和虚拟现实。它易于使用且高度可定制,让你轻松构建自己独特的欧洲风格小镇。用 “模块化欧洲小镇” 将你的愿景变为现实!(解释说明:“lowpoly” 即低多边形,是一种在游戏和数字艺术中常用的风格,以较少的多边形数量来呈现模型,通常具有简洁的外观和较好的性能表现。

    机械工艺课程设计 挂轮架轴自由锻工艺设计(全套图纸).doc

    机械工艺课程设计 挂轮架轴自由锻工艺设计(全套图纸).doc

    nvm-window v1.1.12

    nvm-window v1.1.12

    python自动化测试10: multipart类型接口

    multipart类型接口的介绍与使用

    机械创新课程设计_自动翻书机设计.doc

    机械创新课程设计_自动翻书机设计.doc

    “机械原理”课程设计自动打印机的设计.doc

    “机械原理”课程设计自动打印机的设计.doc

    SAP系统中采购订单‘确认控制’的操作指南

    内容概要:介绍了两种不同类型的采购订单‘确认控制’操作——‘确认控制’一步法(0004)和两步法(0001),并且阐述了它们各自的操作流程以及后台配置方式。还涵盖了另一种收货类型'粗收货'(0002),并通过具体的系统功能与菜单选项展示了一般性的操作步骤,并解释了它的背景及意义。 适合人群:需要理解并能够执行采购确认控制流程的供应链管理从业人员以及系统管理员。 使用场景及目标:帮助用户理解采购流程,特别是涉及到确认步骤以及粗收货的情形。目的是保证采购流程的准确性,提升仓库收货效率。 其他说明:文章详细描述了一系列系统功能与配置,包括采购订单的创建与更新,通过特定的功能码实现采购确认,内向交货单的处理和收货的具体操作,强调每一种确认控制方法背后的原理及其应用场景。

    【6层】4837.9平米六层框架综合办公楼(含计算书、建筑、结构图纸).zip

    【6层】4837.9平米六层框架综合办公楼(含计算书、建筑、结构图纸) 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。

    AP9569GH-VB一款P-Channel沟道TO252的MOSFET晶体管参数介绍与应用说明

    -40V;-65A;RDS(ON)=10mΩ@VGS=10V;VGS=20V;Vth=-1.6V

    玻璃瓶印花机的设计机械原理课程设计.docx

    玻璃瓶印花机的设计机械原理课程设计.docx

    基于springboot+Vue的旅游推荐系统设计与实现源码+数据库(98分毕业设计)

    基于springboot+Vue的旅游推荐系统设计与实现源码+数据库(98分毕业设计),含有代码注释,小白都可以看懂,个人98分毕业设计。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 基于springboot+Vue的旅游推荐系统设计与实现源码+数据库(98分毕业设计),含有代码注释,小白都可以看懂,个人98分毕业设计。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 基于springboot+Vue的旅游推荐系统设计与实现源码+数据库(98分毕业设计),含有代码注释,小白都可以看懂,个人98分毕业设计。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。基于springboot+Vue的旅游推荐系统设计与实现源码+数据库(98分毕业设计),含有代码注释,小白都可以看懂,个人98分毕业设计。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。基于springboot+Vue的旅游推荐系统设计与实现源码+数据库(98分毕业设计),含有代码注释,小白都可以看懂,个人98分毕业设计。毕业

    阅读《Python深度学习-基于PyTorch》时的代码.zip

    深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。

    2024年中国低轨通信星座产业及海外拓展前景研究报告.pdf.zip

    2024年中国低轨通信星座产业及海外拓展前景研究报告.pdf

    基于几何约束的车辆3D检测的实现.zip

    基于几何约束的车辆3D检测的实现.zip

    【5层】4352.4平米框架办公楼(含计算书,建筑、结构图).zip

    【5层】4352.4平米框架办公楼(含计算书,建筑、结构图) 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 、本项目3比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 、3本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REaDme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REaDme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。

    Suricata 下载 安装、使用- windows系统、linux系统 wincap或ncap软件需要另外下载安装

    Suricata 下载 安装、使用- windows系统、linux系统 wincap或ncap软件需要另外下载安装

    U.S.-infra-jobs-report(英文原版+中文翻译)美国电动汽车充电基础设施就业岗位的增长情况报告.zip

    美国充电基础设施

Global site tag (gtag.js) - Google Analytics