• Mybatis学习之自定义持久层框架(三) 自定义持久层框架:读取并解析配置文件


    前言

    前两篇文章分别讲解了JDBC和Mybatis的基本知识,以及自定义持久层框架的设计思路,从这篇文章开始,我们正式来实现一个持久层框架。

    新建一个项目

    首先我们新建一个maven项目,将其命名为IPersistence,创建以下目录结构:

    完成目录创建工作后,我们首先在pom.xml文件中引入相关依赖:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <modelVersion>4.0.0</modelVersion>
     6 
     7     <groupId>com.hardy</groupId>
     8     <artifactId>IPersistence</artifactId>
     9     <version>1.0-SNAPSHOT</version>
    10 
    11     <properties>
    12         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    13         <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
    14         <java.version>1.8</java.version>
    15         <maven.compiler.source>1.8</maven.compiler.source>
    16         <maven.compiler.target>1.8</maven.compiler.target>
    17     </properties>
    18 
    19     <dependencies>
    20         <dependency>
    21             <groupId>mysql</groupId>
    22             <artifactId>mysql-connector-java</artifactId>
    23             <version>8.0.19</version>
    24         </dependency>
    25         <dependency>
    26             <groupId>c3p0</groupId>
    27             <artifactId>c3p0</artifactId>
    28             <version>0.9.1.2</version>
    29         </dependency>
    30         <dependency>
    31             <groupId>log4j</groupId>
    32             <artifactId>log4j</artifactId>
    33             <version>1.2.16</version>
    34         </dependency>
    35         <dependency>
    36             <groupId>junit</groupId>
    37             <artifactId>junit</artifactId>
    38             <version>4.12</version>
    39         </dependency>
    40         <dependency>
    41             <groupId>dom4j</groupId>
    42             <artifactId>dom4j</artifactId>
    43             <version>1.6.1</version>
    44         </dependency>
    45         <dependency>
    46             <groupId>jaxen</groupId>
    47             <artifactId>jaxen</artifactId>
    48             <version>1.1.6</version>
    49         </dependency>
    50     </dependencies>
    51 
    52 </project>

    下面,就可以开始正式的编码工作了。

    读取配置文件

    前面讲到了,第一步是要读取数据库配置的相关信息,以流的形式将其存放在内存中。那么首先我们就要在上图“io”包下创建一个Resources类,编写如下代码:

     1 package com.hardy.io;
     2 
     3 import java.io.InputStream;
     4 
     5 public class Resources {
     6 
     7     // 根据配置文件的路径,将配置文件加载成字节输入流,存储在内存中
     8     public static InputStream getResourceAsStream(String path) {
     9         InputStream resourceAsStream = Resources.class.getClassLoader().getResourceAsStream(path);
    10         return resourceAsStream;
    11     }
    12 }

    这个类的调用方法十分简单,直接传递配置文件的路径名作为参数即可。

    解析配置文件

    创建容器对象

    上面读取完配置文件的信息后,仅仅是将其以输入流的形式存放在内存中,而我们在项目开发过程中,需要调用到这些配置信息中的很多不同属性,如果每次都从内存中读取数据流,是很不方便的。

    这里我们将配置文件分为核心配置文件(提供存放数据库核心配置的信息)和映射配置文件(提供sql配置信息(包括sql语句、参数类型和返回类型))。因此,我们可以在“pojo”包下创建两个容器对象类,分别命名为Configuration(存放核心配置信息)和MappedStatement(存放映射配置信息),编写如下代码:

     1 package com.hardy.pojo;
     2 
     3 import javax.sql.DataSource;
     4 import java.util.HashMap;
     5 import java.util.Map;
     6 
     7 /*
     8     Configuration:
     9     核心配置类,存放数据库基本信息
    10     即sqlMapConfig.xml解析出来的内容
    11     */
    12 public class Configuration {
    13 
    14     private DataSource dataSource;
    15 
    16     /*
    17         key: statementId value: 封装好的mappedStatement对象
    18         */
    19     Map<String, MappedStatement> mappedStatementMap = new HashMap<>();
    20 
    21     public DataSource getDataSource() {
    22         return dataSource;
    23     }
    24 
    25     public void setDataSource(DataSource dataSource) {
    26         this.dataSource = dataSource;
    27     }
    28 
    29     public Map<String, MappedStatement> getMappedStatementMap() {
    30         return mappedStatementMap;
    31     }
    32 
    33     public void setMappedStatementMap(Map<String, MappedStatement> mappedStatementMap) {
    34         this.mappedStatementMap = mappedStatementMap;
    35     }
    36 
    37 }
     1 package com.hardy.pojo;
     2 
     3 // Mapper.xml文件中一个select标签对应一个MappedStatement对象
     4 
     5 /*
     6     映射配置类:
     7     存放sql语句、statement类型、输入参数java类型、输出参数java类型
     8     即Mapper.xml解析出来的内容
     9     */
    10 public class MappedStatement {
    11 
    12     // id标识
    13     private String id;
    14 
    15     // sql语句
    16     private String sql;
    17 
    18     // 输入参数值类型
    19     private String parameterType;
    20 
    21     // 返回结果集类型
    22     private String resultType;
    23 
    24     public String getId() {
    25         return id;
    26     }
    27 
    28     public void setId(String id) {
    29         this.id = id;
    30     }
    31 
    32     public String getSql() {
    33         return sql;
    34     }
    35 
    36     public void setSql(String sql) {
    37         this.sql = sql;
    38     }
    39 
    40     public String getParameterType() {
    41         return parameterType;
    42     }
    43 
    44     public void setParameterType(String parameterType) {
    45         this.parameterType = parameterType;
    46     }
    47 
    48     public String getResultType() {
    49         return resultType;
    50     }
    51 
    52     public void setResultType(String resultType) {
    53         this.resultType = resultType;
    54     }
    55 
    56 }

    创建配置文件解析类

    上面创建了存放配置文件信息的两个容器对象,但配置文件信息不会自动存放到容器对象中,因此我们还需要编写两个配置文件信息的解析类,可以在“config”包下分别创建XMLConfigBuilder和XMLMapperBuilder,编写以下代码:

     1 package com.hardy.config;
     2 
     3 import com.hardy.io.Resources;
     4 import com.hardy.pojo.Configuration;
     5 import com.mchange.v2.c3p0.ComboPooledDataSource;
     6 import org.dom4j.Document;
     7 import org.dom4j.DocumentException;
     8 import org.dom4j.Element;
     9 import org.dom4j.io.SAXReader;
    10 
    11 import java.beans.PropertyVetoException;
    12 import java.io.InputStream;
    13 import java.util.List;
    14 import java.util.Properties;
    15 
    16 public class XMLConfigBuilder {
    17 
    18     private Configuration configuration;
    19 
    20     public XMLConfigBuilder(Configuration configuration) {
    21         this.configuration = new Configuration();
    22     }
    23 
    24     /*
    25     该方法就是使用dom4j对配置文件进行解析,封装成Configuration
    26     */
    27     public Configuration parseConfiguration(InputStream inputStream) throws DocumentException, PropertyVetoException, ClassNotFoundException {
    28 
    29         // 1、解析sqlMapConfig.xml
    30         /*
    31         * 这里需要注意一下:Document和Element等类用的都是org.dom4j库中的类,而不是javax.swing的
    32         * 若编译器自动导入了javax.swing,需要手动删除,否则会报错
    33         * */
    34         Document document = new SAXReader().read(inputStream);
    35         //<configuation>
    36         Element rootElement = document.getRootElement();
    37         List<Element> propertyElements =
    38                 rootElement.selectNodes("//property");
    39         Properties properties = new Properties();
    40         for (Element propertyElement : propertyElements) {
    41             String name = propertyElement.attributeValue("name");
    42             String value = propertyElement.attributeValue("value");
    43             properties.setProperty(name,value);
    44         }
    45         // 连接池
    46         ComboPooledDataSource comboPooledDataSource = new
    47                 ComboPooledDataSource();
    48         comboPooledDataSource.setDriverClass(properties.getProperty("driverClass"));
    49         comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
    50         comboPooledDataSource.setUser(properties.getProperty("username"));
    51         comboPooledDataSource.setPassword(properties.getProperty("password"));
    52 
    53         // 填充configuration
    54         configuration.setDataSource(comboPooledDataSource);
    55 
    56         // 2、解析UserMapper.xml:拿到路径——获取字节输入流——使用dom4j进行解析
    57         List<Element> mapperElements = rootElement.selectNodes("//mapper");
    58         XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration);
    59         for (Element element : mapperElements) {
    60             String mapperPath = element.attributeValue("resource");
    61             InputStream resourceAsStream = Resources.getResourceAsStream(mapperPath);
    62             xmlMapperBuilder.parse(resourceAsStream);
    63         }
    64 
    65         return configuration;
    66     }
    67 }
     1 package com.hardy.config;
     2 
     3 import com.hardy.pojo.Configuration;
     4 import com.hardy.pojo.MappedStatement;
     5 import com.hardy.pojo.SqlOperationEnum;
     6 import org.dom4j.Document;
     7 import org.dom4j.DocumentException;
     8 import org.dom4j.Element;
     9 import org.dom4j.io.SAXReader;
    10 
    11 import java.io.InputStream;
    12 import java.util.List;
    13 
    14 public class XMLMapperBuilder {
    15 
    16     private Configuration configuration;
    17 
    18     public XMLMapperBuilder(Configuration configuration) {
    19         this.configuration = configuration;
    20     }
    21 
    22     // 解析mapper.xml文件
    23     public void parse(InputStream inputStream) throws DocumentException {
    24         Document document = new SAXReader().read(inputStream);
    25         Element rootElement = document.getRootElement();
    26 
    27         String namespace = rootElement.attributeValue("namespace");
    28 
    29         List<Element> elementList = rootElement.elements();
    30         for (Element element : elementList) {
    31             // id的值
    32             String id = element.attributeValue("id");
    33             // 输入参数类型
    34             String parameterType = element.attributeValue("parameterType");
    35             // 返回结果集类型
    36             String resultType = element.attributeValue("resultType");
    37             // sql语句
    38             String sqlText = element.getTextTrim();
    39 
    40             // 封装mappedStatement
    41             MappedStatement mappedStatement = new MappedStatement();
    42             mappedStatement.setId(id);
    43             mappedStatement.setParameterType(parameterType);
    44             mappedStatement.setResultType(resultType);
    45             mappedStatement.setSql(sqlText);
    46 
    47             // 获取sql操作名,并将其转换为大写
    48             String elementName = element.getName();
    49             mappedStatement.setSqlOperationEnum(SqlOperationEnum.valueOf(elementName.toUpperCase()));
    50 
    51             // statementId
    52             String key = namespace + "." + id;
    53 
    54             //填充configuration
    55             configuration.getMappedStatementMap().put(key, mappedStatement);
    56 
    57         }
    58     }
    59 
    60 }

    总结

    本篇文章中,我们创建了IPersistence项目,做了一些必要的准备工作,然后完成了读取数据库配置信息及解析数据库配置信息的编码工作。

    到这里,我们就可以调用我们自定义的工具来读取和解析数据库配置信息了,下一篇文章会讲解如何调用这些工具。

    作者:blayn
    出处:https://www.cnblogs.com/blayn/
    版权:本文版权归作者和博客园共有
    转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
  • 相关阅读:
    sqlite设置主键
    sqlite 分页
    Server.Transfer方法在页面间传值
    JS实现背景透明度可变,文字不透明的效果
    css hack 区分浏览器
    Asp.net(c#)实现多线程断点续传
    C# 中的委托和事件
    使用C#的HttpWebRequest访问网站
    相似图片搜索的原理
    asp.net内存溢出问题
  • 原文地址:https://www.cnblogs.com/blayn/p/12829872.html
Copyright © 2020-2023  润新知