jdbc配置文件---NullPointerException: inStream parameter is null异常解决

抛砖引玉

我们在谈论**""什么时候是什么时间?我记得上一次是IO流的时候,建立缓冲池,加快读取速度/写入速度(实际是减少IO 操作次数)

那么什么时候会用到连接池呢???

连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。

连接池

这就要从java工具类来讲,java功能工具类为我们的开发提供了便利,同理连接池正式基于这种理念进行设计的;

对于大多数客户端请求,进行数据库的相关事务时,仅需要能够访问JDBC连接的 1 个线程。当客户端不需要处理事务时,那么这个连接就会闲置。
这样如果有很多客户端来请求,那么闲置的连接能不能被再次使用呢?
答案是可以的,这样就减少了资源的消耗(当客户端请求时,用已经闲置的连接就可以了),加快了客户端请求的速度;

使用连接池技术能够降低资源消耗,使得cpu能过够更多的用于别的事务;

下面来模拟一个连接缓冲池

创建连接池

连接池的大体描述------

假设这样一个场景,一所学校的选课系统,平时选课系统的并发量很少,只有学期开始选课的时候,并发量才上去了;
我记得当时我们学校(别问哪个学校,反正不是你学校)的限制是同时500人可以进行选课;一个人释放该链接的时候下一个人才能连接到选课系统;

下面开始干活-------

public class MyConnection {
    //准备连接用的
    final static String URL = "jdbc:mysql://127.0.0.1:3306/gavin?";
    final static String USER = "gavin";
    final static String PASSWORD = "root";
    //准备一个池子用于盛放连接
    private static LinkedList<Connection> pool;
    //初始化大小
    private static int initSize = 5;
    //限制池子的最大大小
    private static int maxSize = 10;

    //加载该连接池类信息时就初始化了pool,pool中存放了5个连接实例
    static {
        //加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //开辟空间用于初始化连接池
       pool = new LinkedList<Connection>();
       //往池子中添加5个连接实例
       for (int i = 0; i < initSize; i++) {
       Connection connection = initConnection();
        pool.addLast(connection);
            }
        }
        //初始化一个connection;
public static Connection initConnection(){
Connection connection = null;
    try {
        connection=DriverManager.getConnection(URL, USER, PASSWORD);
    } catch (SQLException e) {
        e.printStackTrace();
        System.out.println("异常");
    }
return connection;

}
    //用于获得连接的方法
    public static Connection getConnection() {
        //怎么获得呢?
        //当连接池中有连接的时候,直接从里面取用
        Connection connection;
        if (pool.size() != 0) {
            connection = pool.removeFirst();
            System.out.println("连接池中--"+connection.hashCode()+"被取走了");

        } else {//当连接池中没有的时候,创建一个
             connection = initConnection();
            System.out.println("连接池已空--"+connection.hashCode()+"被创建了");

        }
        return connection;
    }

    //用户还回去的方法
    public static void returnConnection(Connection connection){

//什么时候往回还,要求池子内少于五个的时候我才接收
        //检测
        if(null!=connection) {//不为空

                try {//检测
                    if (!connection.isClosed()) {//连接未关闭的话
                        //检测
                        //如果池子中少于10个则可以添加进去--始终保证最大化缓冲池
                        if (pool.size() <= maxSize) {
                            //向池中增加该连接
                            connection.setAutoCommit(true);
                            pool.addLast(connection);//
                            System.out.println("归还的连接"+connection.hashCode()+"符合要求,归还成功");
                        }else{//如果归还后池子中连接数大于10,则将该链接关闭
                            System.out.println("池子中已满"+connection.hashCode()+"--将被关闭");
                            connection.close();

                        }
                    }else{//连接关闭
                        System.out.println("归还的连接不能使用,归还失败");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }

        }else{
            System.out.println("归还失败");
        }

    }

    public static void main(String[] args) {
        Connection connection = getConnection();
        Connection connection1 = getConnection();
        try {
            connection1.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        getConnection();
        getConnection();
        getConnection();
        getConnection();
        returnConnection(connection);
        returnConnection(null);
        returnConnection(connection1);
    }
}

测试结果如下-----
在这里插入图片描述
要考虑连接池的健壮性,同时要考虑服务器的承压情况,灵活调整连接池中连接的数量;

连接池的优化

关于连接池的优化,当前代码有一个小小的问题,当我们要设置池的大小的之时,或者修改要连接的数据库时,我们就要停止代码的运行,然后修改,那么为了优化这一点就产生了相应的优化方案----

将这些数据单独妨碍一个配置文件中进行存放,如果哪一天要修改,在配置文件中修改就可以了;
关于配置文件的读取,Java中有一个专门的类用于读取配置文件,在util包下-----Properties
先来看一下该类—

Properties类助力连接池

public class Properties extends Hashtable<Object,​Object>
是Hashtable 的子类,以键值对的方式存储数据;

该类表示一组恒久的属性。可以保存到流或从流加载。属性列表中的每个密钥及其相应值均为字符串。

此类是线程安全的:多个线程可以共享单个对象,而无需外部同步。Properties

构造方法

Properties()
创建没有默认值的空属性列表。

Properties​(int initialCapacity)
创建没有默认值的空属性列表,初始大小可容纳指定数量的元素,无需动态调整大小。

Properties​(Properties defaults)
使用指定的默认值创建空属性列表。

常用方法

在这里插入图片描述

可以试着建立一个jdbc.properties文件,

在这里插入图片描述

文件内容------

在这里插入图片描述

文件内容格式----## 表示注释
文件内内容均默认为文本格式, 具体化格式是 key=value

建一个测试类-----

package com.gavin.dao;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class TestProperties {
    public static void main(String[] args) {
        Properties properties= new Properties();//实力话配置实例
        /**
         * 怎么导入呢?
         * 获取配置文件位置,怎么或获取呢?
         * 通过当前类的字节码文件来获得一个输入流然后通过输入流将配置文件给加载进来
         * 注意文件路径的格式----    /相对路径(最好是相对路径)
         */
        InputStream resourceAsStream = TestProperties.class.getResourceAsStream("/jdbc.properties");
        try {
            properties.load(resourceAsStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String user = properties.getProperty("USER");
        System.out.println(user);
    }
}

在这里插入图片描述

配置文件读取时常见的问题汇总----

1. 获取的结果为null
原因-----代码中要获取的key与配置中的key名称不配写不匹配(大小写),不要有不该有的空格
在这里插入图片描述

2,Exception in thread “main” java.lang.NullPointerException: inStream parameter is null
说明配置文件输入流为空-----
可能是配置文件名或者地址写错了
在这里插入图片描述连接池的具体优化—

package com.gavin.dao;

import com.gavin.UtilTool;


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


public class MyConnection {

    //准备连接用的
    private static String DRIVER ;
   private static String URL ;
    private static String USER;
    private static String PASSWORD ;
    //准备一个池子用于盛放连接
    private static LinkedList<Connection> pool;
    //初始化大小
    private static int initSize ;
    //限制池子的最大大小
    private static int maxSize ;
    //加载该连接池类信息时就初始化了pool,pool中存放了5个连接实例
    static {
     UtilTool utool= new UtilTool("/jdbc.properties");
       DRIVER = utool.getProperties("DRIVER");
       URL = utool.getProperties("URL");
        USER = utool.getProperties("USER");
       PASSWORD= utool.getProperties("PASSWORD");
       initSize=Integer.parseInt(utool.getProperties("iniSize"));
        maxSize=Integer.parseInt(utool.getProperties("maxSize"));
        //加载驱动
        try {

            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //开辟空间用于初始化连接池
       pool = new LinkedList<Connection>();
       //往池子中添加5个连接实例
       for (int i = 0; i < initSize; i++) {
       Connection connection = initConnection();
        pool.addLast(connection);
            }
        }
        //初始化一个connection;
public static Connection initConnection(){
Connection connection = null;
    try {
        connection=DriverManager.getConnection(URL, USER, PASSWORD);
    } catch (SQLException e) {
        e.printStackTrace();
        System.out.println("异常");
    }
return connection;

}
    //用于获得连接的方法
    public static Connection getConnection() {
        //怎么获得呢?
        //当连接池中有连接的时候,直接从里面取用
        Connection connection;
        if (pool.size() != 0) {
            connection = pool.removeFirst();
            System.out.println("连接池中--"+connection.hashCode()+"被取走了");

        } else {//当连接池中没有的时候,创建一个
             connection = initConnection();
            System.out.println("连接池已空--"+connection.hashCode()+"被创建了");

        }
        return connection;
    }

    //用户还回去的方法
    public static void returnConnection(Connection connection){

//什么时候往回还,要求池子内少于五个的时候我才接收
        //检测
        if(null!=connection) {//不为空

                try {//检测
                    if (!connection.isClosed()) {//连接未关闭的话
                        //检测
                        //如果池子中少于10个则可以添加进去--始终保证最大化缓冲池
                        if (pool.size() <= maxSize) {
                            //向池中增加该连接
                            connection.setAutoCommit(true);
                            pool.addLast(connection);//
                            System.out.println("归还的连接"+connection.hashCode()+"符合要求,归还成功");
                        }else{//如果归还后池子中连接数大于10,则将该链接关闭
                            System.out.println("池子中已满"+connection.hashCode()+"--将被关闭");
                            connection.close();

                        }
                    }else{//连接关闭
                        System.out.println("归还的连接不能使用,归还失败");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }

        }else{
            System.out.println("归还失败");
        }

    }

    public static void main(String[] args) {
        Connection connection = getConnection();
        Connection connection1 = getConnection();
        try {
            connection1.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        getConnection();
        getConnection();
        getConnection();
        getConnection();
        returnConnection(connection);
        returnConnection(null);
        returnConnection(connection1);
    }
}

查看,功能正常–说明配置文件成功
在这里插入图片描述
同时我们还可以查看配置文件和代码中相关参数的颜色

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMartain

祝:生活蒸蒸日上!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值