百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

如何应用策略设计模式的思想设计通用的数据库连接类

mhr18 2024-09-18 20:35 17 浏览 0 评论

软件项目实训及课程设计指导——如何应用策略设计模式的思想设计通用的数据库连接类

1、应用属性配置文件分离策略设计模式中的上下文环境类的工作参数

(1)在示例项目中添加一个名称为classNameConfig.properties的属性配置文件

根据Java系统平台中对属性文件(*.properties)解析的基本要求,该属性配置文件应该要存放在软件应用系统的classpath所在的路径中。该路径对于Web方式的应用程序则是在WEB–INFO/classes目录下。

但读者一定要注意属性配置文件(*.properties)的相对路径,否则对属性配置文件进行解析的程序将会由于找不到此属性配置文件而抛出找不到文件的异常错误信息。

因此,读者只需要在MyEclipse开发工具中右击项目的src文件夹,并在弹出的【新建文件】的对话框中输入属性配置文件名 classNameConfig.properties。最后的操作结果的图示请见下图示例图所示。

(2)设计属性配置文件 classNameConfig.properties中的配置项目

由于Java属性配置文件(*.properties)的项目内容是"键/值"对的形式存储,因此根据项目的数据库连接的需要分别提供五个不同的属性项目。

每个项目的内容请见下图所示的内容——它们分别代表MySQL数据库的JDBC驱动程序类、MySQL数据库文件webbank和在该数据库中的账号root和密码root等信息。

2、构建策略设计模式中的上下文环境类的功能实现代码

在本示例中的策略设计模式中的上下文环境类需要从属性配置文件中获得对应的工作参数,因此需要设计一个获得属性配置文件中的各个属性项目的ClassNameConfig程序类。

在java.lang.Class类中的getResourceAsStream方法将直接返回一个InputStream类型的流对象实例,而getResourceAsStream功能方法是查找具有给定名称的资源并返回 InputStream对象。

但要注意的是:getResourceAsStream功能方法在查找和定位属性配置文件时是相对于"/"根路径下的位置——这样的路径是指定绝对路径;如果在标识属性配置文件时不以"/"字符开头,则查找和定位的路径是相对于这个程序类(也就是ClassNameConfig程序类)文件所在包的路径。比如,下面的程序代码示例:

InputStream oneInputStreamObject =
													ClassNameConfig.class.getResourceAsStream("/classNameConfig.properties");

而java.lang.ClassLoader类中的getResource()功能方法则是从系统的classpath的根路径开始查找带有给定名称的资源路径和文件名并返回一个URL类型的对象示例。当然,当指定的程序类名字不能在当前的classpath目录路径中找到时,getResource()功能方法将返回null。

java.lang.Thread类中的contextClassLoader属性则代表线程的上下文 ClassLoader,因为每个运行中的线程都有一个成员contextClassLoader属性对象,用来在运行时动态地载入其它的程序类。并且可以采用下面形式的程序代码获得当前线程的contextClassLoader对象实例。

ClassLoader currentClassLoader= Thread.currentThread().getContextClassLoader();

因此,如果在某个线程中需要应用并加载某个外部的功能类,可以首先利用Thread.currentThread().getContextClassLoader()功能方法获得该线程的对象实例的contextClassLoader;然后再利用所获得的contextClassLoader对象实例请求它的父ClassLoader对象实例来完成外部程序类的载入请求。

完整的ClassNameConfig程序类的功能实现代码请见下面的程序代码示例所示——ClassNameConfig类的功能实现代码示例

package com.px1987.webbank.config;
import java.util.Properties;
import java.io.*;
public class ClassNameConfig {
      public ClassNameConfig() {
      }
      private static Properties onePropertiesObject =null;
      static {
          onePropertiesObject = new Properties();
          try{
                InputStream oneInputStreamObject =
                Thread.currentThread().getContextClassLoader().
                getResource("classNameConfig.properties").openStream();
                onePropertiesObject.load(input);
          }catch(Exception e){
          e.printStackTrace();
          }
      }
      public static String getProperty(String propName){
      		return onePropertiesObject.getProperty(propName);
      }
      public static void setProperty(String propName, String prop Value){
      		onePropertiesObject.setProperty(propName, propValue);
      }
}

请读者注意其中的黑体标识的语句,由于static静态成员属性对象能够达到全局缓存的应用效果,并且static语句块是在该程序类被加载时就执行的、而且也只执行一次。因此,static语句块也能够产生一种"单例"(单一对象实例,也就是单例设计模式)的应用效果,避免重复地对属性配置文件(*.properties)进行加载。另外,下面的语句代码片段:

InputStream oneInputStreamObject =Thread.currentThread().getContextClassLoader().
																						getResource("classNameConfig.properties").openStream();

其实等同于下面的程序代码:

ClassLoader currentClassLoader=Thread.currentThread().getContextClassLoader();
URL oneURL = currentClassLoader.getResource("classNameConfig.properties");
InputStream oneInputStreamObject = oneURL.openStream();

3、设计数据库连接的功能接口——它代表策略设计模式中的"算法"定义

在面向对象OOP的类设计中,一般都倡导面向接口编程功能实现,其基本的目的是为了能够达到分离"类的设计"和"类的功能实现"之间的依赖的基本目的。

因此,对于软件应用系统中的数据库连接的功能实现中,也首先设计一个名称为ConnectDBInterface的接口,然后再对该接口提供对应的功能实现类,实现类的名称为ConnectDBBean。

在MyEclipse开发工具中添加一个名称为ConnectDBInterface的接口,该接口的包名称为com.px1987.webbank.dao.inter。然后再设计和定义该ConnectDBInterface接口中的各个功能方法,最后的操作结果请见下图示例图所示。

4、设计数据库连接接口的具体功能实现类——它代表策略设计模式中的"算法"实现

在策略设计模式中的"算法"实现是可以有多种不同的形式,比如本示例中的数据库连接可以是基于JDBC API实现的数据库连接,也可以根据应用的需要提供基于数据库连接池的数据库连接或者是基于O/R Mapping应用框架的数据库连接等形式。

在本文中,作者只为读者介绍基于JDBC API实现的数据库连接示例。在MyEclipse开发工具中为ConnectDBInterface接口提供一个具体的功能实现类,类名称为ConnectDBBean,该类所在的包名称为com.px1987.webbank.dao.imple。然后再编程该功能实现类的代码。完整的功能实现代码请见下面的程序代码示例所示——ConnectDBInterface接口的功能实现类代码示例。

package com.px1987.webbank.dao.imple;
import java.sql.*;
import java.util.logging.*;
import com.px1987.webbank.config.ClassNameConfig;
import com.px1987.webbank.dao.inter.ConnectDBInterface;
import com.px1987.webbank.exception.WebBankException;
public class ConnectDBBean implements ConnectDBInterface {
      String JDBC_DBDriver_ClassName= null;
      String JDBC_DSN_URL = null;
      String JDBC_dbUserName=null;
      String JDBC_dbUserPassWord=null;
      private java.sql.Connection con = null;
      private Logger logger = Logger.getLogger(this.getClass().getName());
      public ConnectDBBean() throws WebBankException {
          /*利用ClassNameConfig实现从属性文件中获得与数据库相关的连接信息 */
          JDBC_DBDriver_ClassName =
          ClassNameConfig.getProperty("JDBC_DBDriver_ClassName");
          JDBC_DSN_URL = ClassNameConfig.getProperty("JDBC_DSN_URL");
          JDBC_dbUserName = ClassNameConfig.getProperty("JDBC_dbUserName");
          JDBC_dbUserPassWord = ClassNameConfig.getProperty("JDBC_dbUserPassWord");
          try {
          			Class.forName(JDBC_DBDriver_ClassName);
          }
          catch (java.lang.ClassNotFoundException e) {
                logger.log(Level.INFO, e.getMessage());
                throw new WebBankException("不能正确地加载JDBC驱动程序");
          }
          try {
                con = DriverManager.getConnection(JDBC_DSN_URL,
                JDBC_dbUserName, JDBC_dbUserPassWord);
          }
          catch (java.sql.SQLException e) {
                logger.log(Level.INFO, e.getMessage());
                throw new WebBankException("不能正确地连接数据库"+"并且出现SQLException");
          }
          catch (NullPointerException e){
                logger.log(Level.INFO, e.getMessage());
                throw new WebBankException("无法连接数据库"+"并且出现NullPointerException异常");
          }
      }
      public void closeDBCon() throws WebBankException {
          try {
              con.close();
              con = null;
          }
          catch (SQLException e){
              logger.log(Level.INFO, e.getMessage());
              throw new WebBankException("不能正确地关闭数据库连接");
          }
      }
      public Connection getConnection() throws WebBankException {
      		return con;
      }
}

在上面的程序代码中,作者应用JDK系统中所提供的日志处理技术实现错误信息的日志记录——请见其中的黑体部分的代码,但该方法只能将日志信息在控制台中显示输出,而无法保存到文件中。因此,在项目开发的后期将被重构改变为采用Log4J的日志技术实现——在此为了简化代码示例,对日志记录进行了功能实现方面的简化。

由于在数据库连接的功能实现ConnectDBBean类中不再直接以硬编码的方式包含有各种与物理数据库系统相关的连接参数,从而可以使得该ConnectDBBean类适用于连接不同的物理数据库系统,比如MySQL、Oracle或者MS SQLServer等数据库系统。

当软件应用系统最终应用的数据库系统发生变化时,维护人员只需要修改属性配置文件(*.properties)中与数据库连接相关的工作参数,而ConnectDBBean类本身并不需要修改。

因此,ConnectDBBean类可以是一个通用功能的数据库系统连接功能类。据此,读者应该对应用策略设计模式所具有的程序灵活性和通用性有更深刻的理解。

5、应用JUnit单元测试技术对ConnectDBBean组件类进行功能测试

依据体现策略设计模式程序类之间关系的UML类图,读者很容易理解此单元测试用例类TestConnectDBBean(参见如下示例图的代码示例)其实就是模拟策略设计模式中的客户端。在本示例项目中作者应用JUnit4.X版的系统库,因为它提供了许多方便单元测试的各个功能、并使得单元测试用例为一个普通的POJO类型的Java类。

由于在JUnit4.X版的系统库中应用了J2SE5.0新特性之"元数据"(在Java语言中也叫注释或者注解)。比如在单元测试用例中的@Before、@After和@Test等符号。

最后在MyEclipse开发工具中执行该测试用例类TestConnectDBBean的程序代码,该测试用例类的执行结果请见下图示例图所示;然后再将MySQL数据库服务器停止以测试是否出现错误,按照测试的逻辑应该要出现错误状态——为了节省篇幅,在此没有将错误的测试状态图附录出。

从测试用例类的执行结果来看,ConnectDBBean组件类的功能实现是正确的、而且对属性配置文件中的各个属性项目的解析也是正确的。

如何应用策略设计模式分离JDBC数据库连接中的外部环境信息

如何正确地创建和销毁软件应用系统中JDBC数据库连接对象实例

如何应用GOF设计模式中的构建者模式创建复合对象实例

如何应用GOF设计模式中的创建型模式实现松耦合地创建对象实例

如何正确应用Web MVC架构模式分离表示层和模型层耦合关系

相关推荐

redis 7.4.3更新!安全修复+性能优化全解析

一、Redis是什么?为什么选择它?Redis(RemoteDictionaryServer)是一款开源的高性能内存键值数据库,支持持久化、多数据结构(如字符串、哈希、列表等),广泛应用于缓存、消...

C# 读写Redis数据库的简单例子

CSRedis是一个基于C#的Redis客户端库,它提供了与Redis服务器进行交互的功能。它是一个轻量级、高性能的库,易于使用和集成到C#应用程序中。您可以使用NuGet包管理器或使用以下命令行命令...

十年之重修Redis原理

弱小和无知并不是生存的障碍,傲慢才是。--------面试者总结Redis可能都用过,但是从来没有理解过,就像一个熟悉的陌生人,本文主要讲述了Redis基本类型的使用、数据结构、持久化、单线程模型...

高频L2行情数据Redis存储架构设计(含C++实现代码)

一、Redis核心设计原则内存高效:优化数据结构,减少内存占用低延迟访问:单次操作≤0.1ms响应时间数据完整性:完整存储所有L2字段实时订阅:支持多客户端实时数据推送持久化策略:RDB+AOF保障数...

Magic-Boot开源引擎:零代码玩转企业级开发,效率暴涨!

一、项目介绍基于magic-api搭建的快速开发平台,前端采用Vue3+naive-ui最新版本搭建,依赖较少,运行速度快。对常用组件进行封装。利用Vue3的@vue/compiler-sfc单文...

项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!

项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!老铁们!是不是每次面试完都感觉自己像被大厂面试官婉拒的渣男?明明刷了三个月题库,背熟八股文,结果一被问项目就支支吾吾,简历写得像大学生课程设计?...

谷歌云平台:开发者部署超120个开源包

从国外相关报道了解,Google与Bitnami合作为Google云平台增加了一个新的功能,为了方便开发人员快捷部署程序,提供了120余款开源应用程序云平台的支持。这些应用程序其中包括了WordPre...

知名互联网公司和程序员都看好的数据库是什么?

2017年数据库领域的最大趋势是什么?什么是最热的数据处理技术?学什么数据库最有前途?程序员们普遍不喜欢的数据库是什么?本文都会一一揭秘。大数据时代,数据库的选择备受关注,此前本号就曾揭秘国内知名互联...

腾讯云发布云存储MongoDB服务

近日,著名安全专家兼Shodan搜索引擎的创建者JohnMatherly发现,目前至少有35000个受影响的MongoDB数据库暴露在互联网上,它们所包含的数据暴露在网络攻击风险之中。据估计,将近6...

已跪,Java全能笔记爆火,分布式/开源框架/微服务/性能调优全有

前言程序员,立之根本还是技术,一个程序员的好坏,虽然不能完全用技术强弱来判断,但是技术水平一定是基础,技术差的程序员只能CRUD,技术不深的程序员也成不了架构师。程序员对于技术的掌握,除了从了解-熟悉...

面试官:举个你解决冲突的例子?别怂!用这个套路……

面试官:举个你解决冲突的例子?别怂!用这个套路……最近收到粉丝私信,说被问到:团队技术方案有分歧怎么办?当场大脑宕机……兄弟!这不是送命题,是展示你情商+技术判断力的王炸题!今天教你们3招,用真实案例...

面试碰到MongoDB?莫慌,跟面试官这样吹MongoDB 复制集

推荐阅读:吊打MySQL:21性能优化实践+学习导图+55面试+笔记+20高频知识点阿里一线架构师分享的技术图谱,进阶加薪全靠它十面字节跳动,依旧空手而归,我该放弃吗?文末会分享一些MongoDB的学...

SpringBoot集成扩展-访问NoSQL数据库之Redis和MongoDB!

与关系型数据库一样,SpringBoot也提供了对NoSQL数据库的集成扩展,如对Redis和MongoDB等数据库的操作。通过默认配置即可使用RedisTemplate和MongoTemplate...

Java程序员找工作总卡项目关?

Java程序员找工作总卡项目关?3招教你用真实经历写出HR抢着要的简历!各位Java老哥,最近刷招聘软件是不是手都划酸了?简历投出去石沉大海,面试邀请却总在飞别人的简历?上周有个兄弟,13年经验投了5...

Java多租户SaaS系统实现方案

嗯,用户问的是Java通过租户id实现的SaaS方案。首先,我需要理解用户的需求。SaaS,也就是软件即服务,通常是指多租户的架构,每个租户的数据需要隔离。用户可能想知道如何在Java中利用租户ID来...

取消回复欢迎 发表评论: