编写自己的jdbc数据库连接池

2023-11-05

1、为什么要使用数据库连接池

在使用jdbc的一般开发中,每次都要从数据库获取连接,典例的查询的做法如下:

		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		try{
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");
			String sql = "SELECT * FROM persons";
			st = conn.prepareStatement(sql);
			rs = st.executeQuery();
			while(rs.next()){
				//在这里将查询到的数据封装或者做一些其他的事情
				//.....
			}
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{//close resource
			if(rs != null){
				try {
					rs.close();
				} catch (Exception e) {
					e.printStackTrace();
				}finally{
					rs = null;
				}
			}
			if(st != null){
				try {
					st.close();
				} catch (Exception e) {
					e.printStackTrace();
				}finally{
					st = null;
				}
			}
			if(conn != null){
				try {
					conn.close();
				} catch (Exception e) {
					e.printStackTrace();
				}finally{
					conn = null;
				}
			}
		}


这样写一次两次次还好,如果存在几百个这样的方法,那真的是一件痛苦的事情。每次都要去创建连接,不仅难以管理,而且每次创建连接都需要较长的时间,降低了性能。有没有可能将这些链接统一的管理,每次获取链接时不再自己手动的去获取连接,而是直接的去缓存里面拿连接呢?

2、开始编写自己的数据库连接池

首先编写一些用于获取连接的工具类:

<pre name="code" class="java">package cn.zq.util;

import java.sql.Connection;
import java.sql.DriverManager;

public class JdbcUtil {
	private static Connection conn;
	
	static{
		try {
			/* jdbc4.0规范:
			 * 如果在jdbc驱动的jar包的
			 *   META-INF/services/java.sql.Driver文件中写入相应的驱动的类名,
			 *  则Class.forName("com.mysql.jdbc.driver")就可以不用写了,
			 *  不过为了保险起见,建议这句话最好还是写上
			 */
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");
		} catch (Exception e) {
			 throw new ExceptionInInitializerError(e);
		}
	}
	
	public static Connection getConnection(){
		return conn;
	}
}

 
每次获取连接时,直接用JdbcUtil.getConnection()去获取连接,相比前面的直接去获取连接要简单点,这个工具类只维护一个Connection,而且每次用完连接还不能关闭该连接,要不然下次再去获取连接再做一些其他的事情时就会抛出com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed异常多个线程用这个连接,这几个线程的事务也会存在问题。仅仅就这个连接根本就满足不了要求,那么就需要用一个容器来缓存多个连接,改造后: 

package cn.zq.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;

public class JdbcUtil {
	private static ArrayList<Connection> pool = new ArrayList<Connection>();
	
	static{
		try {
			/* jdbc4.0规范:
			 * 如果在jdbc驱动的jar包的
			 *   META-INF/services/java.sql.Driver文件中写入相应的驱动的类名,
			 *  则Class.forName("com.mysql.jdbc.driver")就可以不用写了,
			 *  不过为了保险起见,建议这句话最好还是写上
			 */
			Class.forName("com.mysql.jdbc.Driver");
			
			String url = "jdbc:mysql://localhost:3306/test";
			String user = "root";
			String pwd = "123456";
			int initialSize = 3;
			for(int i = 0; i < initialSize; i++){
				Connection conn = DriverManager.getConnection(url, user, pwd);
				pool.add(conn);
			}
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
	public static  synchronized Connection getConnection(){
		return pool.remove(0);
	}
}
这样初始化时就可以获取3个连接,这样做还有一个问题:只能从里面拿3个连接,如果再拿第4个连接时就会抛出异常,还需要改造。应该提供一个方法,让程序员手动的还连接
package cn.zq.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;

public class JdbcUtil2 {
	private static ArrayList<Connection> pool = new ArrayList<Connection>();
	
	static{
		try {
			/* jdbc4.0规范:
			 * 如果在jdbc驱动的jar包的
			 *   META-INF/services/java.sql.Driver文件中写入相应的驱动的类名,
			 *  则Class.forName("com.mysql.jdbc.driver")就可以不用写了,
			 *  不过为了保险起见,建议这句话最好还是写上
			 */
			Class.forName("com.mysql.jdbc.Driver");
			
			String url = "jdbc:mysql://localhost:3306/test";
			String user = "root";
			String pwd = "123456";
			int initialSize = 3;
			for(int i = 0; i < initialSize; i++){
				Connection conn = DriverManager.getConnection(url, user, pwd);
				pool.add(conn);
			}
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
	public static  synchronized Connection getConnection(){
		return pool.remove(0);
	}
	
	public static synchronized void close(Connection conn){
		if(conn != null){
			pool.add(conn);
		}
	}
}
虽然这样能解决问题,但是程序员不一定会安装要求去调用这个方法,一般喜欢调用Connection.close()方法,能不能让程序员调用这个方法时就还连接呢?那么就需要对Connection的close方法进行增强,一般有这几个方式:继承、包装、代理。下面就演示下用代理来增强:

package cn.zq.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;

/**
 * @author zq
 *
 */
public class JdbcUtil2 {
	
	//Connection pool
	private static LinkedList<Connection> pool = new LinkedList<Connection>();
	
	static{
		try {
			String driver = "com.mysql.jdbc.Driver";
			String url = "jdbc:mysql:///test";
			String user = "root";
			String pwd = "123456";
			int initialSize = 3;
			
			Class.forName(driver);
			for(int i = 0; i < initialSize; i++){
				final Connection conn = DriverManager.getConnection(url, user, pwd);
				
				//proxy
				Object connProxy = Proxy.newProxyInstance(JdbcUtil.class.getClassLoader(),
									new Class[]{Connection.class}, 
									new InvocationHandler() {
										
										public Object invoke(Object proxy, Method method, Object[] args)
												throws Throwable {
											
											//只对close方法进行增强
											if(method.getName().equals("close")){
												synchronized (pool) {
													pool.addLast((Connection) proxy);
													pool.notify();
													return null;
												}
											}
											
											return method.invoke(conn, args);
										}
									});
				
				pool.addLast((Connection) connProxy);										
			}
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}
	
	public static Connection getConnection(){
		synchronized (pool) {
			if(pool.size() == 0){
				try {
					pool.wait();
				} catch (InterruptedException e) {
					throw new RuntimeException(e.getMessage(), e);
				}
			}
			Connection conn = pool.removeFirst();;
			return conn;
		}
	}
	
	public static void release(ResultSet rs, Statement st, Connection conn){
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				rs = null;
			}
		}
		
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				conn = null;
			}
		}
		
		if(st != null){
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				st = null;
			}
		}
		
	}
}

上面的代码还有可以优化的地方,比如驱动,用户名、密码等等都应该从一个配置文件里面读取,还有上面的连接在类加载的时候进行放到连接池中的,那么为什么不在获取连接的时候进行代理呢?那么就可以减少内存的消耗。改造后如下:

package cn.zq.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.Properties;

/**
 * @author zq
 *
 */
public class JdbcUtil {
	
	//Connection pool
	private static LinkedList<Connection> pool = new LinkedList<Connection>();
	
	static{
		try {
			Properties prop = loadJdbcConfig("jdbc.properties");
			String driver = prop.getProperty("driver");
			String url = prop.getProperty("url");
			String user = prop.getProperty("user");
			String pwd = prop.getProperty("pwd");
			int poolSize = new Integer(prop.getProperty("initialSize"));
			
			Class.forName(driver);
			for(int i = 0; i < poolSize; i++){
				Connection conn = DriverManager.getConnection(url, user, pwd);
				pool.addLast((Connection) conn);										
			}
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
	private static Properties loadJdbcConfig(String filename) throws IOException{
		InputStream in = null;
		try {
			in = JdbcUtil.class
								.getClassLoader()
								.getResourceAsStream(filename);
			Properties prop = new Properties();
			prop.load(in);
			return prop;
		}finally{
			if(in != null){
				in.close();
			}
		}
	}
	
	public static Connection getConnection(){
		synchronized (pool) {
			if(pool.size() == 0){
				try {
					pool.wait();
				} catch (InterruptedException e) {
					throw new RuntimeException(e.getMessage(), e);
				}
			}
			final Connection conn = pool.removeFirst();;
			//proxy
			Object connProxy = Proxy.newProxyInstance(JdbcUtil.class.getClassLoader(),
								new Class[]{Connection.class}, 
								new InvocationHandler() {
									
									public Object invoke(Object proxy, Method method, Object[] args)
											throws Throwable {
										if(method.getName().equals("close")){
											synchronized (pool) {
												pool.addLast(conn);
												pool.notify();
												return null;
											}
										}
										return method.invoke(conn, args);
									}
								});
			return (Connection) connProxy;
		}
	}
	
	public static void release(ResultSet rs, Statement st, Connection conn){
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				rs = null;
			}
		}
		
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				conn = null;
			}
		}
		
		if(st != null){
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				st = null;
			}
		}
		
	}
}

jdbc.properties

driver = com.mysql.jdbc.Driver
url = jdbc:mysql:///contacts?characterEncoding=UTF8
username = root
pwd =123456
initialSize=2
使用包装来完成上面的事情:

package cn.zq.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;

/**
 * @author zq
 *
 */
public class JdbcUtil3 {
	
	//Connection pool
	private static LinkedList<Connection> pool = new LinkedList<Connection>();
	
	static{
		try {
			Properties prop = loadJdbcConfig("jdbc.properties");
			String driver = prop.getProperty("driver");
			String url = prop.getProperty("url");
			String user = prop.getProperty("user");
			String pwd = prop.getProperty("pwd");
			int poolSize = new Integer(prop.getProperty("initialSize"));
			
			Class.forName(driver);
			for(int i = 0; i < poolSize; i++){
				Connection conn = DriverManager.getConnection(url, user, pwd);
				pool.addLast((Connection) conn);										
			}
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
	private static Properties loadJdbcConfig(String filename) throws IOException{
		InputStream in = null;
		try {
			in = JdbcUtil3.class
								.getClassLoader()
								.getResourceAsStream(filename);
			Properties prop = new Properties();
			prop.load(in);
			return prop;
		}finally{
			if(in != null){
				in.close();
			}
		}
	}
	
	public static Connection getConnection(){
		synchronized (pool) {
			if(pool.size() == 0){
				try {
					pool.wait();
				} catch (InterruptedException e) {
					throw new RuntimeException(e.getMessage(), e);
				}
			}
			Connection conn = pool.removeFirst();;
			
			return new ConnectionWrapper(conn);
		}
	}
	
	public static void release(ResultSet rs, Statement st, Connection conn){
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				rs = null;
			}
		}
		
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				conn = null;
			}
		}
		
		if(st != null){
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				st = null;
			}
		}
		
	}
	
  static class ConnectionWrapper implements Connection {

		private Connection conn;
		
		public void close() throws SQLException {
			synchronized (pool) {
				pool.addLast(conn);
				pool.notify();
			}
		}
		
		public ConnectionWrapper(Connection conn) {
			this.conn = conn;
		}
		public <T> T unwrap(Class<T> iface) throws SQLException {
			return conn.unwrap(iface);
		}

		public boolean isWrapperFor(Class<?> iface) throws SQLException {
			return conn.isWrapperFor(iface);
		}

		public Statement createStatement() throws SQLException {
			return conn.createStatement();
		}

		public PreparedStatement prepareStatement(String sql)
				throws SQLException {
			return conn.prepareStatement(sql);
		}

		public CallableStatement prepareCall(String sql) throws SQLException {
			return conn.prepareCall(sql);
		}

		public String nativeSQL(String sql) throws SQLException {
			return conn.nativeSQL(sql);
		}

		public void setAutoCommit(boolean autoCommit) throws SQLException {
			conn.setAutoCommit(autoCommit);
		}

		public boolean getAutoCommit() throws SQLException {
			return conn.getAutoCommit();
		}

		public void commit() throws SQLException {
			conn.commit();
		}

		public void rollback() throws SQLException {
			conn.rollback();
		}

		public boolean isClosed() throws SQLException {
			return conn.isClosed();
		}

		public DatabaseMetaData getMetaData() throws SQLException {
			return conn.getMetaData();
		}

		public void setReadOnly(boolean readOnly) throws SQLException {
			conn.setReadOnly(readOnly);
		}

		public boolean isReadOnly() throws SQLException {
			return conn.isReadOnly();
		}

		public void setCatalog(String catalog) throws SQLException {
			conn.setCatalog(catalog);
		}

		public String getCatalog() throws SQLException {
			return conn.getCatalog();
		}

		public void setTransactionIsolation(int level) throws SQLException {
			conn.setTransactionIsolation(level);
		}

		public int getTransactionIsolation() throws SQLException {
			return conn.getTransactionIsolation();
		}

		public SQLWarning getWarnings() throws SQLException {
			return conn.getWarnings();
		}

		public void clearWarnings() throws SQLException {
			conn.clearWarnings();

		}

		public Statement createStatement(int resultSetType,
				int resultSetConcurrency) throws SQLException {
			return conn.createStatement(resultSetType, resultSetConcurrency);
		}

		public PreparedStatement prepareStatement(String sql,
				int resultSetType, int resultSetConcurrency)
				throws SQLException {
			return conn.prepareStatement(sql, resultSetConcurrency);
		}

		public CallableStatement prepareCall(String sql, int resultSetType,
				int resultSetConcurrency) throws SQLException {
			return conn.prepareCall(sql, resultSetType, resultSetConcurrency);
		}

		public Map<String, Class<?>> getTypeMap() throws SQLException {
			return conn.getTypeMap();
		}

		public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
			conn.setTypeMap(map);
		}

		public void setHoldability(int holdability) throws SQLException {
			conn.setHoldability(holdability);
		}

		public int getHoldability() throws SQLException {
			return conn.getHoldability();
		}

		public Savepoint setSavepoint() throws SQLException {
			return conn.setSavepoint();
		}

		public Savepoint setSavepoint(String name) throws SQLException {
			return conn.setSavepoint(name);
		}

		public void rollback(Savepoint savepoint) throws SQLException {
			conn.rollback(savepoint);
		}

		public void releaseSavepoint(Savepoint savepoint) throws SQLException {
			conn.releaseSavepoint(savepoint);
		}

		public Statement createStatement(int resultSetType,
				int resultSetConcurrency, int resultSetHoldability)
				throws SQLException {
			return conn.createStatement(resultSetType, resultSetConcurrency,
					resultSetHoldability);
		}

		public PreparedStatement prepareStatement(String sql,
				int resultSetType, int resultSetConcurrency,
				int resultSetHoldability) throws SQLException {
			return conn.prepareStatement(sql, resultSetType,
					resultSetConcurrency, resultSetHoldability);
		}

		public CallableStatement prepareCall(String sql, int resultSetType,
				int resultSetConcurrency, int resultSetHoldability)
				throws SQLException {
			return conn.prepareCall(sql, resultSetType, resultSetConcurrency,
					resultSetHoldability);
		}

		public PreparedStatement prepareStatement(String sql,
				int autoGeneratedKeys) throws SQLException {
			return conn.prepareStatement(sql, autoGeneratedKeys);
		}

		public PreparedStatement prepareStatement(String sql,
				int[] columnIndexes) throws SQLException {

			return conn.prepareStatement(sql, columnIndexes);
		}

		public PreparedStatement prepareStatement(String sql,
				String[] columnNames) throws SQLException {
			return conn.prepareStatement(sql, columnNames);
		}

		public Clob createClob() throws SQLException {
			return conn.createClob();
		}

		public Blob createBlob() throws SQLException {
			return conn.createBlob();
		}

		public NClob createNClob() throws SQLException {
			return conn.createNClob();
		}

		public SQLXML createSQLXML() throws SQLException {
			return conn.createSQLXML();
		}

		public boolean isValid(int timeout) throws SQLException {
			return conn.isValid(timeout);
		}

		public void setClientInfo(String name, String value)
				throws SQLClientInfoException {
			conn.setClientInfo(name, value);
		}

		public void setClientInfo(Properties properties)
				throws SQLClientInfoException {
			conn.setClientInfo(properties);
		}

		public String getClientInfo(String name) throws SQLException {
			return conn.getClientInfo(name);
		}

		public Properties getClientInfo() throws SQLException {
			return conn.getClientInfo();
		}

		public Array createArrayOf(String typeName, Object[] elements)
				throws SQLException {
			return conn.createArrayOf(typeName, elements);
		}

		public Struct createStruct(String typeName, Object[] attributes)
				throws SQLException {
			return conn.createStruct(typeName, attributes);
		}
	}
	
}


java提供了标准的数据库连接池的接口javax.sql.DataSource,定义了数据库连接池的一些方法,读者可以自行完成标准的数据库连接池。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编写自己的jdbc数据库连接池 的相关文章

随机推荐

  • ECharts3使用入门

    最近项目中有用到百度ECharts 目前版本已经到3了 很多人说百度的这个东西是他最有良心的产品 用起来要比国外的插件简单点 这里主要讲一些简单的应用 算是简单的入门级别的 如果要是想更加的深入可以去看看范例 1 前期准备 1 相较于以前好
  • unix网络编程卷一:第四章——基本TCP套接口编程

    基本TCP套接口编程 4 1 过程 4 2 socket include
  • 数据挖掘分析概述

    目录 什么是数据挖掘分析 数据挖掘能够干什么 描述 评估 预测 分类 聚类 关联 数据挖掘的一般流程 业务理解阶段 数据理解阶段 数据准备阶段 建模阶段 评估阶段 部署阶段 什么是数据挖掘分析 数据挖掘是指从大量的数据中通过算法搜索隐藏于其
  • 关于在IDEA和jar包下MD5加密不一致问题

    关于在IDEA和jar包下MD5加密不一致问题 服务端 java 移动端 安卓 苹果 问题 MD5加密中文 在jar包下和idea下加密结果不一致问题 描述 移动端和服务端数据传输数据需要加解密 其中用到了AES RSA MD5 IDEA编
  • mysql导出表结构到excel

    1 执行如下sql 查询出想要的表信息 select c table name as 表名 t TABLE COMMENT as 表名描述 c column name as 字段名称 c column type as 数据类型 c COLU
  • vuecli2.0完成多页面应用中遇到的问题

    1 ECHO off SETLOCAL CALL find dp0 IF EXIST dp0 node exe SET prog dp0 node exe max old space size 4096 ELSE SET prog node
  • 拳王公社:知识付费项目!个体操作可年入千万!简单可复制!

    昨天 拳王分享了一篇 小白零基础靠副业年赚30W玩法 看懂一半至少年赚10W 揭秘了一个由个体思维转变到平台思维的网创人是怎么练就的 今天 我们分享的是 知识付费项目 个体操作可年入千万 简单可复制 这是在互联网上的一个纯粹的好项目 顺应互
  • 微服务可观测平台设计-总体设计

    背景 服务可观测性 预测与发现系统性能瓶颈 透视系统状态 为系统调优和查故障提供可靠数据支撑 参考和关键词 参考资料 https www cnblogs com erda p 15204516 html Metrics Metrics 计算
  • 嵌入式之fastboot的初步学习笔记

    注 如下内容参考朱老师物联网大讲堂课件 1 什么是fastboot 1 fastboot是android使用的一种刷机方法 android系统设计了2种刷机方式 fastboot和recovery fastboot是一种线刷 就是使用USB
  • 免费生成ios证书,利用Hbuilder打包ipa

    虽然xcode现在可以免证书进行测试了 但众多跨平台开发者 如果还没注册苹果开发者账号 想安装到自己非越狱手机测试是无能为力了 不过新技术来了 只需要普通免费的苹果账号无需付费成为开发者就可以申请ios证书打包ipa安装到自己手机测试 强大
  • Java猜数小游戏

    用java实现猜数1 99 package Random import java util Random import java util Scanner public class numgame public static void ma
  • qt for android程序调用腾讯接口实现短信验证功能

    为实现保留用户信息 手机号码 的功能 采用了短信验证的方式 选择了讯云短信平台 通过调用他的接口实现 之前使用过js java本地调用的方式因为各种原因均未完全实现 在客户端本地也可以实现 自己慢慢研究吧 现在采用新的思路如下 1 在公网服
  • Android学习记录044_监听Android截屏或者录屏

    一 源代码 package com study capturescreenlistener import android annotation SuppressLint import android content ContentResol
  • 金九银十?我来试试水。。。

    有没有觉得今年过的很快 新的跳槽季又要到了 今年 金九银十 我自己先冲在了面试一线 先说下面试感受 求职确实比往年卷 不过面试机会肯定有 据职友集显示 前端在招岗位累计24万 上周我共约到5场面试 周末复盘发现 卷的根源在于 面试官想要的多
  • 蓝桥杯比赛常考算法_经验分享

    大家好 我是韩龙 来自大连东软信息学院计算机与软件学院软件工程专业软件17006班 今天分享一下我获得蓝桥杯省赛C C 一等奖的经验和体会 1 首先是准备阶段 想在蓝桥杯取得好成绩 那就只有一种途径 刷题 建议大家在报名时就开始刷题 算法能
  • 三刺激值——XYZ

    三刺激值tristimulus values是引起人体 视网膜对某种颜色 感觉的三种原色的 刺激程度之量的表示 中文名 三刺激值 外文名 tristimulus values 引 起 人体 视网膜刺激 释 义 三种原色的 刺激
  • 基于nat协议下通过端口映射实现外网访问内网网站

    实验拓扑结构图 实验要求 1 R2为ISP设备 只能再该设备上配置ip 不得在进行其它任何配置 2 PC1可以正常pingRC2 3 R1仅拥有一个共有ip地址 在G0 0 1接口上 4 client 浏览器 可以通过http访问到两台se
  • mipi和isp处理_VS-RK3399 在linux系统下面调试Mipi camera接口介绍

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 debian系统目前支持Usb camera是没有问题 走UVC功能接口 那么mipi 接口camera和并口接口的camera 在Debian系统怎么设置呢 其实原理一样 也走uvc接口封装函
  • Network Error .Tap to load again.:-1202

    分析原因 1 可能是网络问题 确认网络是否正常 2 如果电脑上尝试没有问题 但是微信端有问题 可能是手机域名过期的问题 3 可能是域名证书未配置成功 导致微信认证被拦截了 配置即可
  • 编写自己的jdbc数据库连接池

    1 为什么要使用数据库连接池 在使用jdbc的一般开发中 每次都要从数据库获取连接 典例的查询的做法如下 Connection conn null PreparedStatement st null ResultSet rs null tr