JavaWeb 后端 <十> 之 数据池 C3P0 DPCB JNDI

一、数据库连接池原理:(理解)

//模拟数据库连接池的原理
public class ConnectionPoolDemo {
    private static List<Connection> pool = new ArrayList<Connection>();
    static{
        try {
            for(int i=0;i<10;i++){
                Connection conn = JdbcUtil.getConnection();//创建的新连接
                pool.add(conn);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //从池中取出一个链接
    public synchronized static Connection getConnection(){
        if(pool.size()>0){
            Connection conn = pool.remove(0);
            return conn;
        }else{
            throw new RuntimeException("服务器真忙");
        }
    }
    //把链接还回池中
    public static void release(Connection conn){
        pool.add(conn);
    }
     
}

二、编写数据源(DataSource)(很重要)

编写一个类实现javax.sql.DataSource

public class MyDataSource1 implements DataSource {
     
    private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>());
    static{
        try {
            for(int i=0;i<10;i++){
                Connection conn = JdbcUtil.getConnection();//创建的新连接
                pool.add(conn);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     
    //从池中获取链接  >  com.mysql.jdbc.Connection
    public Connection getConnection() throws SQLException {
        if(pool.size()>0){
            Connection conn = pool.remove(0);
            MyConnection1 mconn = new MyConnection1(conn,pool);
            return mconn;
        }else{
            throw new RuntimeException("服务器真忙");
        }
    }
     
     
     
     
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }
 
    public void setLogWriter(PrintWriter out) throws SQLException {
 
    }
 
    public void setLoginTimeout(int seconds) throws SQLException {
 
    }
 
    public int getLoginTimeout() throws SQLException {
        return 0;
    }
 
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }
 
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
 
     
    public Connection getConnection(String username, String password)
            throws SQLException {
        return null;
    }
     
     
}

三、编程的难点:(设计模式)

难点:用一个实现了javax.sql.DataSource类的实例时,用户如果调用Connection.close()方法,会把链接关闭,失去了连接池的意义。

明确一个问题:用户得到Connection的实现是:数据库驱动对Connection接口的实现。因此,调用的close方法都是数据库驱动的,它会把链接给关闭。(这不是我们要的,我们要把该链接换回池中)。

解决方案:改写驱动原有的close方法。对已知类的某个/某些方法进行功能上的改变,有以下几种编码方案:

a、继承:此处行不通。

到底针对哪个驱动的实现写子类(很多)

数据库驱动对Connection接口的实现类,不允许被继承

丢失了原有对象的信息。捡了芝麻丢了西瓜。

b、装饰(包装)设计模式:(基础IO)

保持被包装对象的原有信息,又可以对某个/某些方法进行改写。

口诀:

1、编写一个类,实现与被包装类(数据库驱动对Connection的实现)相同的接口。(使这个类和数据库的驱动实现有着相同的行为)

2、定义一个变量,引用被包装类的实例。

3、定义构造方法,传入被包装类的实例。

4、对于要改写的方法,编写自己的代码即可。

5、对于不需要改写的方法,调用原有对象的对应方法。

//目前要包装的是:com.mysql.jdbc.Connection
 
//1、编写一个类,实现与被包装类(数据库驱动对Connection的实现)相同的接口。(使这个类和数据库的驱动实现有着相同的行为)
public class MyConnection implements Connection {
//  2、定义一个变量,引用被包装类的实例
    private Connection conn;//引用具体的数据库驱动
     
    private List<Connection> pool;
     
//  3、定义构造方法,传入被包装类的实例。
    public MyConnection(Connection conn,List<Connection> pool){//依赖注入
        this.conn = conn;
        this.pool = pool;
    }
    //把链接还回池中
//  4、对于要改写的方法,编写自己的代码即可。
    public void close() throws SQLException {
        pool.add(conn);
    }
    public Statement createStatement() throws SQLException {
        return conn.createStatement();
    }
    //5、对于不需要改写的方法,调用原有对象的对应方法。
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return conn.unwrap(iface);
    }

c、默认适配器:(为了后来做准备)

//默认的适配器
/*
本身也是一个包装类,但并没有对任何的方法进行改写
1、编写一个类,实现与被包装类(数据库驱动对Connection的实现)相同的接口。(使这个类和数据库的驱动实现有着相同的行为)
2、定义一个变量,引用被包装类的实例。
3、定义构造方法,传入被包装类的实例。
4、全部调用原有对象的对应方法
 */
public class ConnectionAdapter implements Connection {
    private Connection conn;
    public ConnectionAdapter(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);
    }
/*
这也是包装:对ConnectionAdapter进行包装。
 
包装类即是被包装类的包装,又是他的子类。
 
1、编写一个类,继承已经是包装类的类。
2、定义一个变量,引用被包装类的实例。
3、定义构造方法,传入被包装类的实例。
4、覆盖掉需要改写的方法
 */
public class MyConnection1 extends ConnectionAdapter {
    private Connection conn;
    private List<Connection> pool;
    public MyConnection1(Connection conn,List<Connection> pool){
        super(conn);
        this.conn = conn;
        this.pool = pool;
    }
    public void close() throws SQLException {
        pool.add(conn);
    }
     
}

d、动态代理:(很重要 AOP--Aspect-Oriented Programming 核心技术)

l  基于接口的动态代理:Proxy

如果一个类没有实现任何的接口,此种代理就不能使用了。

package com.itheima.proxy;
 
public interface Human {
    void sing(float money);
    void dance(float money);
}
package com.itheima.proxy;
 
public class SpringBrother implements Human {
 
    public void sing(float money) {
        System.out.println("拿到钱:"+money+"开唱");
    }
 
    public void dance(float money) {
        System.out.println("拿到钱:"+money+"开跳");
    }
 
}
package com.itheima.proxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class Client1 {
 
    public static void main(String[] args) {
        final Human sb = new SpringBrother();
         
        //代理人:如何动态产生代理人
         
        /*
        ClassLoader loader:动态代理,必须有字节码class。加到内存中运行,必须有类加载器。固定:和被代理人用的是一样的
        Class<?>[] interfaces:代理类要实现的接口,要和被代理对象有着相同的行为。固定:和被代理人用的是一样的
        InvocationHandler h:如何代理。他是一个接口。策略设计模式。
         
         */
        //产生代理类,得到他的实例
        Human proxyMan = (Human)Proxy.newProxyInstance(sb.getClass().getClassLoader(),
                sb.getClass().getInterfaces(),
                new InvocationHandler() {
                    //匿名内部类,完成具体的代理策略
                    //调用代理类的任何方法,都会经过该方法。  拦截
             
                    /*
                     Object proxy:对代理对象的引用。
                     Method method:当前执行的方法
                     Object[] args:当前方法用到的参数
                      
                      
                     返回值:当前调用的方法的返回值
                     */
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        //判断出场费
                        if("sing".equals(method.getName())){
                            //唱歌
                            float money = (Float)args[0];
                            if(money>10000){
                                method.invoke(sb, money/2);
                            }
                        }
                        if("dance".equals(method.getName())){
                            //唱歌
                            float money = (Float)args[0];
                            if(money>20000){
                                method.invoke(sb, money/2);
                            }
                        }
                        return null;
                    }
                }
        );
        proxyMan.sing(20000);
        proxyMan.dance(100000);
    }
 
}

l  基于子类的动态代理:CGLIB

前提:被代理类的要求

1、不能是final的

2、必须是public的

package com.itheima.cglib;
 
public class SpringBrother{
 
    public void sing(float money) {
        System.out.println("拿到钱:"+money+"开唱");
    }
 
    public void dance(float money) {
        System.out.println("拿到钱:"+money+"开跳");
    }
 
}
package com.itheima.cglib;
 
import java.lang.reflect.Method;
 
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
public class Client1 {
 
    public static void main(String[] args) {
         
        final SpringBrother sb = new SpringBrother();
         
        //产生sb的代理:
        /*
        Class type:代理类的父类型
        Callback cb:回调,如何代理
         */
        SpringBrother proxy = (SpringBrother) Enhancer.create(SpringBrother.class,new MethodInterceptor(){
 
            public Object intercept(Object proxy, Method method, Object[] args,
                    MethodProxy arg3) throws Throwable {
                //判断出场费
                if("sing".equals(method.getName())){
                    //唱歌
                    float money = (Float)args[0];
                    if(money>10000){
                        method.invoke(sb, money/2);
                    }
                }
                if("dance".equals(method.getName())){
                    //唱歌
                    float money = (Float)args[0];
                    if(money>20000){
                        method.invoke(sb, money/2);
                    }
                }
                return null;
            }
        });
        System.out.println(proxy instanceof SpringBrother);
        proxy.dance(100000);
        proxy.sing(50000);
         
    }
 
}

比如普通的JavaBean就可能没有实现任何的接口。代理类是被代理类的子类。

四、开源数据源的使用:(很重要,非常简单)

1、DBCP:

Apache组织开发的。DBCP:DataBase Connection Pool,对数据源的一种实现。

a、拷贝jar包

b、编写配置文件

dbcpconfig.properties

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=sorry
 
#<!-- 初始化连接 -->
initialSize=10
 
#最大连接数量
maxActive=50
 
#<!-- 最大空闲连接 -->
maxIdle=20
 
#<!-- 最小空闲连接 -->
minIdle=5
 
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
 
 
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=utf8
 
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
 
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
 
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=REPEATABLE_READ

c、使用即可

public class DBCPUtil {
    private static DataSource dataSource;
    static{
        try {
            InputStream in = DBCPUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            Properties props = new Properties();
            props.load(in);
            dataSource = BasicDataSourceFactory.createDataSource(props);
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
     
    public static DataSource getDataSource(){
        return dataSource;
    }
     
    public static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

2、C3P0:

开源数据源的实现。

c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql:///test</property>
        <property name="user">root</property>
        <property name="password">sorry</property>
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>
    </default-config>
    <named-config name="day15">
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>
    </named-config>
</c3p0-config>
public class C3P0Util {
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
     
    public static DataSource getDataSource(){
        return dataSource;
    }
     
    public static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

3、更接近实际开发:JNDI管理数据源

JNDI:Java Naming and Directory Interface。属于JavaEE技术之一,目的模仿window系统中的注册表。

a、在服务器中注册JNDI数据源

1、拷贝数据库的驱动到Tomcat\lib目录下

2、在web应用的META-INF目录下建立一个名称为context.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource"
               maxActive="20" maxIdle="5" maxWait="10000"
               username="root" password="sorry" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/test"/>
</Context>

 3、获取JNDI容器中的资源

public class JndiDsUtil {
    public static Connection getConnection() throws Exception {
        Context initContext = new InitialContext();
        DataSource ds = (DataSource) initContext
                .lookup("java:/comp/env/jdbc/test");
        Connection conn = ds.getConnection();
        return conn;
    }
}

五、编写自己的JDBC框架(为学习DBUtil框架、Spring JDBCTemplate做准备)

1、数据库元信息的获取(为写框架而准备)

元信息:数据库的一些定义信息。比如用的是什么数据库等,表的定义信息等。

 DatabaseMetaData    PreparedStatement    ResultSetMetaData getColumnCount

//数据库元信息的获取
public class Demo {
    //数据库本身信息的获取
    @Test
    public void test1() throws Exception{
        Connection conn = DBCPUtil.getConnection();
        DatabaseMetaData dmd = conn.getMetaData();
        String name = dmd.getDatabaseProductName();//能知道说什么方言
        System.out.println(name);
        int isolation = dmd.getDefaultTransactionIsolation();
        System.out.println(isolation);
    }
    //参数元数据信息:PreparedStatement时
    @Test
    public void test2() throws Exception{
        Connection conn = DBCPUtil.getConnection();
        PreparedStatement stmt = conn.prepareStatement("??????????");
         
        ParameterMetaData pmd = stmt.getParameterMetaData();
        int count = pmd.getParameterCount();
        System.out.println(count);//统计语句中的占位符个数
    }
    //结果集元数据信息:
    @Test
    public void test3()throws Exception{
        Connection conn = DBCPUtil.getConnection();
        PreparedStatement stmt = conn.prepareStatement("select * from account");
        ResultSet rs = stmt.executeQuery();
        ResultSetMetaData rsmd = rs.getMetaData();
        int count = rsmd.getColumnCount();//有几列
        System.out.println(count);
         
        for(int i=0;i<count;i++){
            String fieldName = rsmd.getColumnName(i+1);
            int type = rsmd.getColumnType(i+1);
            System.out.println(fieldName+":"+type);
        }
    }
}

2、编写JDBC框架:(策略设计模式)

/**
 * 框架的核心类
 * @author wzhting
 *
 */
public class DBAssist {
    private DataSource dataSource;
    public DBAssist(DataSource dataSource){
        this.dataSource = dataSource;
    }
    //写:添加、删除、修改
    //params参数要和sql中的占位符对应
    public void update(String sql,Object...params) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try{
            conn = dataSource.getConnection();
            stmt = conn.prepareStatement(sql);
            //设置参数
                //得到sql中的参数
                ParameterMetaData pmd = stmt.getParameterMetaData();
                int count = pmd.getParameterCount();
                if(count>0){
                    if(params==null){
                        throw new RuntimeException("必须传入参数的值");
                    }
                    if(count!=params.length){
                        throw new RuntimeException("参数数量不匹配");
                    }
                    for(int i=0;i<count;i++){
                        stmt.setObject(i+1, params[i]);
                    }
                     
                }
             
            stmt.executeUpdate();
        }catch(Exception e){
            throw new RuntimeException(e);
        }finally{
            release(rs, stmt, conn);
        }
    }
     
     
    //读:查询
    public Object query(String sql,ResultSetHandler rsh,Object...params) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try{
            conn = dataSource.getConnection();
            stmt = conn.prepareStatement(sql);
            //设置参数
                //得到sql中的参数
                ParameterMetaData pmd = stmt.getParameterMetaData();
                int count = pmd.getParameterCount();
                if(count>0){
                    if(params==null){
                        throw new RuntimeException("必须传入参数的值");
                    }
                    if(count!=params.length){
                        throw new RuntimeException("参数数量不匹配");
                    }
                    for(int i=0;i<count;i++){
                        stmt.setObject(i+1, params[i]);
                    }
                     
                }
             
            rs = stmt.executeQuery();
            //有结果集,要封装到对象中。策略设计模式
            return rsh.handle(rs);
        }catch(Exception e){
            throw new RuntimeException(e);
        }finally{
            release(rs, stmt, conn);
        }
    }
     
     
    private void release(ResultSet rs,Statement stmt,Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stmt = null;
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }
}
public interface ResultSetHandler {
    /**
     * 把结果中的数据封装到指定的对象中
     * @param rs
     * @return 封装了数据的对象
     */
    Object handle(ResultSet rs);
}
/**
 * 适合只有一条查询结果的情况
 * 封装到JavaBean中
 * 满足约定:数据库字段名和JavaBean字段名保持一致
 * @author wzhting
 *
 */
public class BeanHanlder implements ResultSetHandler {
     
    private Class clazz;//目标类型
    public BeanHanlder(Class clazz){
        this.clazz = clazz;
    }
 
    public Object handle(ResultSet rs) {
        try {
            if(rs.next()){
                //有记录
                Object bean = clazz.newInstance();//目标对象
                //有多少列,列名和值又是什么?
                ResultSetMetaData rsmd = rs.getMetaData();
                int count = rsmd.getColumnCount();//列数
                for(int i=0;i<count;i++){
                    String fieldName = rsmd.getColumnName(i+1);//得到数据库字段名,也就得到了JavaBan的字段名
                    Object fieldValue = rs.getObject(fieldName);//字段值
                    //通过字段反射
                    Field f = clazz.getDeclaredField(fieldName);
                    f.setAccessible(true);
                    f.set(bean, fieldValue);
                }
                return bean;
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
 
}
/**
 * 封装到JavaBean中
 * 满足约定:数据库字段名和JavaBean字段名保持一致
 * @author wzhting
 *
 */
public class BeanListHanlder implements ResultSetHandler {
     
    private Class clazz;//目标类型
    public BeanListHanlder(Class clazz){
        this.clazz = clazz;
    }
 
    public Object handle(ResultSet rs) {
        try {
            List list = new ArrayList();
            while(rs.next()){
                //有记录
                Object bean = clazz.newInstance();//目标对象
                //有多少列,列名和值又是什么?
                ResultSetMetaData rsmd = rs.getMetaData();
                int count = rsmd.getColumnCount();//列数
                for(int i=0;i<count;i++){
                    String fieldName = rsmd.getColumnName(i+1);//得到数据库字段名,也就得到了JavaBan的字段名
                    Object fieldValue = rs.getObject(fieldName);//字段值
                    //通过字段反射
                    Field f = clazz.getDeclaredField(fieldName);
                    f.setAccessible(true);
                    f.set(bean, fieldValue);
                }
                list.add(bean);
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
 
}
时间: 2024-11-05 09:07:57

JavaWeb 后端 <十> 之 数据池 C3P0 DPCB JNDI的相关文章

JavaWeb 后端 &lt;十二&gt; 之 过滤器 filter 乱码、不缓存、脏话、标记、自动登录、全站压缩过滤器

一.过滤器是什么?有什么? 1.过滤器属于Servlet规范,从2.3版本就开始有了. 2.过滤器就是对访问的内容进行筛选(拦截).利用过滤器对请求和响应进行过滤 二.编写步骤和执行过程 1.编码步骤: a.编写一个类:实现javax.servlet.Filter接口 public class FilterDemo1 implements Filter {           public FilterDemo1(){         System.out.println("调用了默认的构造方法

JavaWeb 后端 &lt;十四&gt; 文件上传下载

1.文件上传与下载 案例:          注册表单/保存商品等相关模块!          --à 注册选择头像 / 商品图片          (数据库:存储图片路径 / 图片保存到服务器中指定的目录) 1.1 文件上传 文件上传,要点: 前台:          1. 提交方式:post          2. 表单中有文件上传的表单项: <input type="file" />          3. 指定表单类型:                    默认类

涂鸦科技:支撑从零暴增数十亿数据的背后,竟无专职运维!

直播视频 (点击图片查看视频) 幻灯下载地址: https://oss.aliyuncs.com/yqfiles/76d3bb80d4a9da17ababada8f56ecd8b.pdf 3月23日在线实时分享顺利结束,本次由涂鸦科技技术总监柯都敏分享了涂鸦科技云上架构设计和借助阿里云实现轻运维高可用性监控的实战经验,同时也介绍了网络安全.权限控制等特定场景下如何利用阿里云产品解决特定的问题题.本次视频直播的整理文章.视频.幻灯片整理完毕,如下内容. 架构演变历程 初创公司的团队刚起步时一般规模

jdbc-sturts2 怎么链接到数据池

问题描述 sturts2 怎么链接到数据池 我在tomcat6.0的context.xml文件里加了这个 </Context> <Context reloadable="true"> <Resource name="jdbc/ice_db" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait=&quo

因职业角色而异的十大数据科学技能

数据科学的实践需要三个一般领域的技能:商业洞察.计算机技术/编程和统计学/数学.与询问对象有关,具体的重要技能集合总是在变化.Dave Holts描述了得到数据科学家工作所需要的技能,Ferris Jumah通过检查带有"数据科学家"称号的LinkedIn个人资料识别10项技能,BurtchWorks提供了他们的在数据科学领域中获得成功至关 重要的技能列表,RJMetrics也使用LinkedIn数据找出了20个重要的数据科学技能.这些列表.重要技能反映了数据专业人员在他们社交媒体资

《精通QTP——自动化测试技术领航》—第1章1.8节数据池(Data Table)的应用

1.8 数据池(Data Table)的应用 精通QTP--自动化测试技术领航 阶段要点 熟悉测试数据和脚本业务分离的好处和优势. 学会利用Data Table将测试数据与业务分离. Global Sheet与Local Sheet的区别. Test DataTable VS Run-time DataTable. DataTable常用方法指引. 1.8.1 引言 作为一个QTP自动化测试工程师,学会使用Data Table是必不可少的.Data Table其实和Excel非常相似,几乎可以说

resin 数据池被占满问题

问题描述 环境linux,apache,resin,oracle一直运行很好,最近老是出现java.sql.SQLException: Can't open connection with full database pool (20)打开进程一看,oracle进程一堆.是resin连接池被占满了.把resin重启后,数据池立即又被占满了.不知道是什么原因.请朋友门赐教.可能是哪方面的原因.该如何查起了.问题补充:waterdh (初级程序员) 检查数据库连接代码,看哪里没有释放连接不知道该从哪

十大数据可视化站点 改变审视世界角度

文章讲的是十大数据可视化站点 改变审视世界角度,本文所介绍的这些网站将会改变大家观察世界的方式,以实时的.可视化的方式对结论加以审视,也许能为我们带来完全不同的观察视角. 一.全球黑客活动 从黑客活动开始踏上可视化数据工具体验之旅.这份迷人的地图由安全供应商Norse打造,其本质是一套反映全球范围内黑客攻击频率的快照.它利用Norse的"蜜罐"攻击陷阱显示出所有实时渗透攻击活动.(稍等一会儿,DDoS攻击就会点亮你的屏幕!)闪光的霓虹线段与炫丽的彩虹配色营造出了互联网时代下的科技战争氛

全球十大数据中心:美丽图片展示其魅力

数据中心如今紧密与http://www.aliyun.com/zixun/aggregation/6288.html">行业发展联系起来.回顾2012年,在数据中心技术方面隐藏着不一样的"美丽".早在Prentice Hall出版社一篇名为<The Art of the Data Center>上收集了世界最独特的IT设施的照片.随着谷歌数据中心露出神秘的面纱,国外媒体通过图片展示给读者2012年全球十大著名的数据中心的别样魅力. 谷歌数据中心 对于谷歌数据