黑马程序员——mysql——day06——XML、Dom4j、综合案例

目录:

  1. 反射
  2. 注解
  3. 动态代理
  4. XML
    1. XML概述
      1. 目标
      2. 什么是XML
      3. XML作用
      4. 小结
    2. 编写第1个XML文件
      1. 需求
      2. 效果
      3. 步骤
      4. 小结:
    3. XML的组成:声明和元素
      1. 目标
      2. XML组成
      3. 文档声明
      4. 元素(标签、标记)
      5. 小结
    4. XML的组成:属性、注释和转义字符
      1. 属性的语法
      2. 注释
      3. 转义字符[实体字符]
      4. 小结
    5. XML的组成:字符区(了解)
    6. XML约束:DTD约束
      1. 目标
      2. XML约束
      3. 约束示例
      4. DTD学习要求
      5. 小结:
    7. XML约束:Schema约束
      1. 目标
      2. 概念
      3. 约束示例
      4. 实现步骤
      5. 名称空间
      6. schema学习要求
      7. 小结:
  5. Dom4j
    1. XML解析
      1. 解析方式和解析器
      2. 小结
    2. Dom4j的基本使用
      1. DOM解析原理及结构模型
        1. 解析原理
        2. 结构模型
        3. 引入dom4j的jar包
        4. 小结
      2. 常用的方法
        1. SAXReader对象
        2. Document对象
        3. Element对象
        4. 小结
        5. 方法演示
    3. Dom4J结合XPath解析XML(了解)
      1. 介绍
      2. XPath使用步骤
      3. XPath语法(了解)
      4. 绝对路径表达式(了解)
      5. 相对路径表达式(了解)
      6. 全文搜索路径表达式(了解)
      7. 谓语(条件筛选了解)
      8. 小结
  6. 综合案例
    1. 学习目标:
    2. 需求
    3. 案例效果
    4. 案例分析
    5. 自定义JDBC框架-代码实现
    6. Configuration
    7. 注解
    8. 映射类:Mapper
    9. SqlSession类
    10. 自定JDBC框架的使用
      1. 数据表
      2. 创建实体类
      3. UserMapper接口
      4. 配置文件:config.xml
      5. 测试类

1.反射

概念:反射技术就是对类进行解剖,解剖出"构造器"、"成员变量"、"成员方法"

  • 构造器: 可以实例化对象
  • 成员变量:可以赋值、取值
  • 成员方法:调用方法
  • 大白话:不使用new关键字,可以实例化对象,可以访问对象中的成员

反射技术,通常应用于:框架

反射技术的程序书写步骤:

  1. 获取Class对象
  2. 获取构造器
  3. 获取成员(成员方法、成员变量)
  4. 实例化对象 | 调用方法 | 给成员变量赋值取值

使用反射技术:

  • 核心点:Class类
    • Class类是什么呢?
      • JVM中只能执行.class字节码文件(Java程序中会存在大量的.class文件)
      • .class文件是通过类加载器读取到内存中,并基于这个.class文件创建出:Class对象
        • Class对象,就是指一个.class文件
    • Class类的作用
      • 通过Class对象,获取"构造器"、"成员方法"、"成员变量"

步骤:

1、获取Class对象

Class  cls = 类名.class;
Class  cls = 对象名.getClass(); 
Class  cls = Class.forName("类的全限定名");

//回顾:同步方法(线程), 非静态方法默认有一个同步锁:this   
//                     静态方法的同步锁:类名.class

2、基于Class对象,可以获取:构造器、成员方法、成员变量

  • 构造器:Constructor类
Constructor c = Class对象.getConstructor();//无参构造器
Constructor c = Class对象.getConstructor(String.class);//有参构造器
  •  成员方法:Method类

Method m = Class对象.getMethod("方法名");//获取指定方法名的无参方法
Method m = Class对象.getMethod("方法名",int.class);
  •  成员变量:Field类
Field f = Class对象.getDeclaredField("属性名");

//针对私有成员:成员变量、成员方法、构造器,需要取消权限检查
f.setAccessible(true);//true就表示关闭本次权限检查

3、使用构造器,调用newInstance(...)方法,来实例化对象

4、使用成员方法,调用invoke(...)方法,来调用方法入栈执行

5、使用成员变量,调用set(...)方法、get(...)方法,对变量进行赋值、取值

2.注解

认知:

  • 注解单独使用,没有任何意义。
  • 通常注解会配合反射技术一起使用,常用于框架技术

注解的定义:

public @interface 注解名{
    数据类型 属性名();
    数据类型 属性名() default 默认值;
    数据类型[] 属性名();
}

注解中的数据类型可以有哪些:
    1. 8种基本数据类型
    2. 枚举
    3. String
    4. Class
    5. 注解
    6. 以上所有类型的一维数组形式

 注解的使用:

@注解名
public class 类{
    
    @注解名(属性名=值)
    private String 成员变量;
    
    @注解名    //@Test
    public void 成员方法(int 参数){
        
    }   
}

元注解:

  • 作用:限定注解的使用位置、注解的生命周期
  • @Target //指定注解的使用位置
  • @Retention //设定注解的生命周期
    • SOURCE : 只能在源码中使用 。 例:@Override
    • CLASS :可以用于源码中、字节码文件中 【默认】
    • RUNTIME : 可以用于源码、字节码文件、程序运行 例:@Test

注解解析(注解存在的意义)

注解解析的步骤:
1、获取一个对象(构造器Constructor、成员变量Field、成员方法Method)
2、判断对象上是否有指定的注解
   有: 获取对象上的注解对象
        对象上有注解后,获取注解对象中的属性值    



//API:
//判断某个对象(类、接口、成员变量、构造器、成员方法)上是否有使用注解
boolean flag = isAnnotationPresent(注解.class)
    
//获取某个对象上的注解对象
注解名  对象 =   getAnnotation(注解.class)   
    
    
数据类型 变量 = 注解对象.属性;    

 示例:

//前置铺垫:
一张数据表   对应    类
一行记录     对应    对象    
一个字段     对应    成员变量
    
create table t_student
(
   sname varchar(20),
   sage  int
);

//类
class Student{
    private String name;
    private int age;
}
    

//JDBC程序: (程序员自己编写)
连接数据库
创建数据库操作对象
发送sql语句: select ...
处理结果集
     while(rs.next()){
         
        age = rs.getInt("sage");
        name =rs.getString("sname");
         
         Student stu = new Student();
         stu.setName( name );
         stu.setAge( age );     
     }


//框架技术: 反射+注解   (别人已经完成的)
//1、自定义一些注解
public @interface Entity{  //实体
    String table();  //表名
}   
public @interface property{ //属性
    String name();
}
//2、解析@Entity、@Property注解
 扫描某些包下的的类,发现这些类上有@Entity、@Property注解,就会利用反射
 利用反射技术: 获取 Student.class 对象 (Class对象)
              解析 类上的@Entity注解
 利用反射技术: 获取所有的成员变量 : 
              解析所有成员变量上的@Property注解
              

     

//JDBC程序中使用框架技术中注解 ( 程序员自己编写 )

@Entiry(table="t_student")  //表示当前的Student类和数据表t_student关联
class Student{
    
    @Property(name="sname") //表示当前的成员变量name和字段sname关联
    private String name;
    
    @Property(name="sage") //表示当前的成员变量age和字段sage关联
    private int age;
}

3.动态代理

  • 动态代理,提供了一个代理的对象,有了代理对象后,当访问某个方法时,会被代理对象拦截(拦截后可以对方法进行前增强、后增强【代理对象不会破坏原有方法的代码】)
  • 动态代理的特点:
    • 动态的创建.class文件(创建一个和被代理类实现相同父接口的子类[代理类])
    • 动态的加载.class文件到内存中(创建Class对象)
      • Proxy类需要一个"类加载器"
    • 对程序员来讲,不需要书写代理类
  • 动态代理的代码实现:
代理对象 = Proxy.newProxyInstance(类加载器 , 父接口 , 处理器)
类加载器: 动态的加载.class文件

父接口 : 代理类和被代理类需要拥有共同的父接口
    
处理器: 代理对象拦截了方法后,对方法进行前增强、后增强,是由处理器来书写逻辑    
代理对象  = Proxy.newProxyInstance(
             类.class.getClassLoader(), //类加载器
             被代理类.class.getInterfaces(), //父接口
             
             new InvocationHandler(){
                 public Object invoke(
                                       Object 代理对象, 
                                       Method 被拦截的方法对象 ,
                                       Object[] 方法中的实参
                                      ){
                     
                     
                     //业务逻辑
                 }
                    
             }
           )

动态代理:

  • 代理程序中的某个类中的功能,为该功能进行增强

动态代理实现的关键步骤:

  1. 被代理类(例:UserServiceImpl),必须有实现接口

  2. 创建被代理类对象(例: new UserServiceImpl() ),交给代理对象使用

动态代理的实现:

  • JDK已经提供了现成的代理对象的生成

    • Proxy类

      • 静态方法:newProxyInstance(类加载器 , 接口数组 , 处理器)

    • Proxy创建一个子类

      • 子类: 必须和被代理类实现相同的父接口

      • 子类编译后是一个.class文件, 需要使用类加载器,加载.class文件到内存中

4.XML

1.XML概述
目标
  • 什么是XML
什么是XML
  1. 英文:eXtensible Markup Language 可扩展的标记语言,由各种标记(标签,元素)组成。

  2. 可扩展:所有的标签都是自定义的,可以随意扩展的。如:<abc/>,<姓名>

  3. 标记语言:整个文档由各种标签组成。清晰,数据结构化!

  4. XML是通用格式标准,全球所有的技术人员都知道这个东西,都会按照XML的规范存储数据,交互数据!!

XML作用

作用:总体上来说,就是为了存储维护数据的。

  • 数据交换:不同的计算机语言之间,不同的操作系统之间,不同的数据库之间,进行数据交换。

  • 配置文件:在后期我们主要用于各种框架的配置文件基本天天见。

  • 比如 连接池:c3p0-config.xml 日志:logback.xml

小结

xml是什么?

  • 可扩展的标记语言
    • 标记:标签。例: <abc> </abc>
  • xml文件是由N多个标签组成的

主要有哪两个作用?

  • 存储数据
  • 配置文件(主流)
2.编写第1个XML文件
需求

编写xml文档,用于描述人员信息,person代表一个人员,id是人员的属性代表人员编号。人员信息包括age年龄、name姓名、sex性别信息。

使用Java类去描述:

class Person{
  String id;
  int age;
  String name;
  String sex;
}
Person p = new Person("1","张三",18,"男");
效果

步骤
  • 选择当前项目鼠标右键新建
  • 新建一个File命名时,以 .xml结尾。这个文件就是xml文件

  • 编写person.xml文件  
<?xml version="1.0" encoding="UTF-8" ?>
<peopel>
    <person>
        <id>1</id>
        <name>张三</name>
        <age>18</age>
        <sex>男</sex>
    </person>
    
    <person>
        <id>2</id>
        <name>李四</name>
        <age>20</age>
        <sex>女</sex>
    </person>

</peopel>
  •  通过浏览器解析XML的内容

  • 注:XML以后通过Java来进行解析,很少直接在浏览器上显示。

小结:
  • xml文件,通常以.xml作为后缀名

  • xml文件中的首行必须书写: <?xml version="1.0" encoding="UTF-8" ?> (固定写法)

  • xml文件通常是由成对标签(开始标签、结束标签)组成

3.XML的组成:声明和元素
目标
  1. XML文档中的声明

  2. XML文档中的元素

XML组成
  1. 声明

  2. 元素(标签)

  3. 属性

  4. 注释

  5. 转义字符【实体字符】

  6. CDATA 字符区

文档声明
<?xml version="1.0" encoding="utf-8" ?>    固定格式
  1. IDEA会自动提示。
  2. 文档声明必须为<?xml开头,以?>结束
  3. 文档声明必须从文档的1行1列位置开始,==必须在xml文档中的首行首列==
  4. 文档声明中常见的两个属性:
  5. version:指定XML文档版本。必须属性,这里一般选择1.0;
  6. encoding:指定当前文档的编码,可选属性,默认值是utf-8;
元素(标签、标记)
格式1:  <person> 标签体 </person>   有标签体的标签    (双标签)
格式2:  <person/>  没有标签体的标签 (空标签)         (单标签)
  • 元素是XML文档中最重要的组成部分;
  • 普通元素的结构由开始标签、元素体、结束标签组成。【格式1】
  • 元素体:元素体可以是元素,也可以是文本,例如:
<person> 
  标签中可以包含另一个标签  
  <name>张三</name>  
</person>
  •  空元素:空元素只有标签,而没有结束标签,但元素必须自己闭合,例如:
<sex/>
  • 元素命名
    • 可以保持与Java命名标识符一样的规则
    • 区分大小写
    • 不能使用空格,不能使用冒号
    • 不建议以XML、xml、Xml开头
    • 标签名不能数字开头,可以有数字
    • 可以使用下划线
  • 格式化良好的XML文档,有且仅有一个根元素。
    • 错误演示:
    • 元素没有结束

元素大写小写不一致

xml中多个根

小结
  1. 声明有哪两个常用的属性?

    • version

    • encoding

  2. 一个XML有几个根元素?

    • 有且只能有一个根元素

  3. XML标签命名不能有什么符号?

    • 不能使用关键字xml、XML

    • 不能有空格、不能有冒号

    • 不能以数字作为开头

4.XML的组成:属性、注释和转义字符
属性的语法
<person id="110" id2="11">
  • 属性是元素的一部分,它必须出现在元素的开始标签中

  • 属性的定义格式:属性名=“属性值”,其中属性值必须使用单引或双引号括起来

  • 一个元素可以有0~N个属性,但一个元素中不能出现同名属性

  • 属性名不能使用空格 , 建议不要使用冒号等特殊字符,且必须以字母开头建议以Java的标识符定义规则做参考

<person id="123">
	<name>张三</name>
</person>
注释
<!-- 注释内容 -->

<!-- 
注释内容 1
注释内容 2
-->

XML的注释与HTML相同,既以<!--开始,-->结束。不能嵌套。

Java中注释:

// 单行
/* */ 多行注释
/** */ 文档注释

XML注释:

<!-- 注释内容 -->
<!--<person>注释</person>-->  <!-- 快捷键:Ctrl+/ :可以将整行进行注释-->
<person>三生三世</person> <!-- 快捷键:Ctrl+Shift+/:局部注释-->
转义字符[实体字符]

XML中的实体字符与HTML一样。因为很多符号已经被文档结构所使用,所以在元素体或属性值中想使用这些符号就必须使用实体字符

字符预定义的转义字符说明
<&lt;小于(less than)
>&gt;大于(greater than)
"&quot;双引号(quotation)
'&apos;单引号(apostrophe)
&&amp;和号(ampersand )

注意:严格地讲,在 XML 中仅有字符 "<"和"&" 是非法的。省略号、引号和大于号是合法的,但是把它们替换为实体引用是个好的习惯。

转义字符应用示例:

假如您在 XML 文档中放置了一个类似 "<" 字符,那么这个文档会产生一个错误,这是因为解析器会把它解释为新元素的开始。因此你不能这样写:

<message>if salary < 1000 then </message>

 为了避免此类错误,需要把字符 "<" 替换为实体引用,就像这样:

<message>if salary &lt; 1000 then</message>
小结
  • 属性必须出现在标签哪个位置?
    •  和开始标签绑定在一起,书写在开始标签元素的后面
  • <person id="属性值">
    </person>
  • 同一个标签是否可以有同名的属性?
    • 不可能。
    • 允许有多个属性,属性之间使用空格分隔,但不能出现相同名称的属性
  • 为什么要有转义字符(实体字符)?
    • 在xml文件中,一些特定的符号已经被xml使用了。例:> & 等
    • 希望在xml文档中,使用特定的符号,需要用:转义字符
      • < => &lt;
      • & => &amp;
  • 注释的快捷?
    • ctrl + /
5.XML的组成:字符区(了解)

当大量的转义字符出现在xml文档中时,会使XML文档的可读性大幅度降低。这时如果使用CDATA段就会好一些。

CDATA (Character Data)字符数据区,格式如下:

<![CDATA[
	文本数据   < >  & ; " "
]]>
  1. CDATA 指的是不应由 XML 解析器进行解析的文本数据(Unparsed Character Data)

  2. CDATA 部分由 <![CDATA[开始,由 ]]> 结束;

例如:

<![CDATA[
    if salary < 1000 then
]]

快捷模板:CD 回车

注意:

CDATA 部分不能包含字符串 "]]>"。也不允许嵌套的 CDATA 部分。

标记 CDATA 部分结尾的 "]]>" 不能包含空格或折行。

小结:

  • 字符区的特点:

    • 原样显示(书写的内容不会被xml解析器解析)

6.XML约束:DTD约束
目标
  1. XML有哪两种约束

  2. 了解DTD约束

XML约束

在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束。

常见的xml约束:DTD、Schema

注意:我们对于约束的要求是能通过已写好的约束文件编写xml文档.

约束示例

效果说明:当编写xml文档时不符合指定dtd约束时,进行提示xml编写错误,如下图:

体验步骤:

步骤1:复制bookshelf.dtd文件

步骤2:bookshelf.dtd文件内容如下

<!ELEMENT 书架 (书+)> <!-- 声明了根元素,并指定了根元素下必须有的一个子元素 -->

<!-- 声明子元素 书 -->
<!ELEMENT 书 (书名,作者,售价)><!--约束元素书的子元素必须为书名、作者、售价-->
                           <!-- , 表示必须按照元素的顺序出现  -->

<!ELEMENT 书名 (#PCDATA)> <!-- #PCDATA  : 表示文本内容 -->
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>

步骤三:新建books.xml,代码如下

引用 <!DOCTYPE 根元素 SYSTEM "dtd约束文件的路径"> 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 书架 SYSTEM "bookshelf.dtd"><!--指定使用bookshelf.dtd文件约束当前xml文档-->
<书架>
    <书>
        <书名>JavaWeb开发教程</书名>
        <作者>张孝祥</作者>
        <售价>100.00元</售价>
    </书>
    <书>
        <书名>三国演义</书名>
        <作者>罗贯中</作者>
        <售价>100.00元</售价>
        <测试>hello</测试><!--不符合约束,书的子元素必须为书名、作者、售价-->
    </书>
</书架>

步骤四:idea开发工具books.xml的dtd约束验证不通过的效果如下

DTD学习要求

在企业实际开发中,我们很少自己编写DTD约束文档,通常情况下通过框架提供的DTD约束文档编写对应的XML文档。所以这一知识点的要求是可以根据DTD约束文档内容编写XML文档。

小结:

在xml文件中引入DTD约束文件

<!DOCTYPE 根元素 SYSTEM "约束文件的路径">
7.XML约束:Schema约束
目标
  • 了解Schema约束
概念
  • Schema 语言也也叫做 XSD(XML Schema Definition)。
  • 其本身也是XML格式文档,但Schema文档扩展名为xsd,而不是xml。
  • Schema 功能更强大,数据类型约束更完善。 比DTD强大,是DTD代替者。
约束示例

体验效果说明:体验schema约束XML文档中对元素体数据类型的约束。

效果如下:

DTD约束无法对具体数据类型进行约束,所以开发工具没有任何错误提示,如下效果:

实现步骤

步骤1:复制schema约束文件bookshelf.xsd,其中已对售价约束了数据类型,代码如下

<?xml version="1.0" encoding="UTF-8" ?>

<!--
	传智播客schema教学实例文档.将注释中的以下内容复制到要编写的xml的声明下面
	复制内容如下:
	<书架 xmlns="http://www.itcast.cn"
		  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		  xsi:schemaLocation="http://www.itcast.cn bookshelf.xsd"
    >
 -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.itcast.cn"
           elementFormDefault="qualified">
        <xs:element name='书架' >
        <!--  complexType : 复杂元素 
              xml文档中的某个标签,有子标签或有属性,该标签就为:复杂元素
              例: <书架>   <书>
              
              简单元素: 
                 没有子标签、没有属性。   例:书名、作者、售价
        -->
                <xs:complexType>
                        <xs:sequence maxOccurs='unbounded' >
                                <xs:element name='书' >
                                        <xs:complexType>
                                                <xs:sequence>
                                                     <xs:element name='书名' type='xs:string' />
                                                     <xs:element name='作者' type='xs:string' />
                                                     <xs:element name='售价' type='xs:double' />
                                                </xs:sequence>
                                        </xs:complexType>
                                </xs:element>
                        </xs:sequence>
                </xs:complexType>
        </xs:element>
</xs:schema>

步骤2:新建books2.xml使用schema约束文件bookshelf.xsd,代码如下

<?xml version="1.0" encoding="UTF-8"?>
<书架
xmlns="http://www.itcast.cn"    
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.itcast.cn bookshelf.xsd"
><!--指定schema文档约束当前XML文档-->
    <书>
        <书名>JavaScript网页开发</书名>
        <作者>张孝祥</作者>
        <售价>abc</售价>
    </书>
</书架>

步骤3:开发工具提示效果

名称空间

一个XML文档最多可以使用一个DTD文件,但一个XML文档中使用多个Schema文件,若这些Schema文件中定义了相同名称的元素时,使用的时候就会出现名字冲突。这就像一个Java文件中使用了`import java.util.*`和`import java.sql.*`时,在使用Date类时,那么就不明确Date是哪个包下的Date了。

同理 , 在XML文档中就需要通过名称空间(namespace)来区分元素和属性是来源于哪个约束中的。

名称空间就在在根元素后面的内容 , 使用xmlns到引入约束 。

当一个XML文档中需要使用多个Schema文件的时候 , 有且仅有一个使用缺省的 , 其他的名称空间都需要起别名 。

参考资料中的 applicationContext.xml文件(spring框架的配置文件)

 xmlns="http://www.itcast.cn"    
 	<!-- 缺省的名称空间.使用此约束中的元素的时候只需要写元素名即可 例如:<书></书> -->
 
 xmlns:aa="http://java.sun.com"
 	<!-- aa就是此约束的别名,使用此约束中的元素的时候就需要加上别名 例如:<aa:书></aa:书> -->

总之名称空间就是用来处理元素和属性的名称冲突问题,与Java中的包是同一用途。如果每个元素和属性都有自己的名称空间,那么就不会出现名字冲突问题,就像是每个类都有自己所在的包一样,那么类名就不会出现冲突。

schema学习要求

虽然schema功能比dtd强大,但是编写要比DTD复杂,同样以后我们在企业开发中也很少会自己编写schema文件。

xml编写与约束内容已经完成了,根据xml的作用我们了解到,无论是xml作为配置文件还是数据传输,我们的程序都要获取xml文档中的数据以便我们进行具体的业务操作,接下来我们就要学习XML解析技术Dom4j。

小结:

怎么引入xsd 文档

<?xml version="1.0" encoding="UTF-8" ?>
<根元素 xmlns="命名空间"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="命名空间 文件路径"
>
    
   
</根元素>
  • schemaLocation:指定命名空间所在的文件
  • 命名空间在约束文件的:targetNamespace中

5.Dom4j

1.XML解析

解析概述

  • ​当将数据存储在XML后,我们就希望通过程序获取XML的内容。我们使用Java基础所学的IO知识是可以完成的,不过需要非常繁琐的操作才可以完成,且开发中会遇到不同问题(只读、读写)。
  • 人们为不同问题提供不同的解析方式,使用不同的解析器进行解析,方便开发人员操作XML。
解析方式和解析器

开发中比较常见的解析方式有三种,如下:

1. DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象

   a)优点:元素与元素之间保留结构关系,故可以进行增删改查操作。

   b)缺点:XML文档过大,可能出现内存溢出

2. SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都触发对应的事件。

   a)优点:处理速度快,可以处理大文件

   b)缺点:只能读,逐行后将释放资源,解析操作繁琐。

3. PULL:Android内置的XML解析方式,类似SAX。(了解)

解析器,就是根据不同的解析方式提供具体实现。有的解析器操作过于繁琐,为了方便开发人员,有提供易于操作的解析开发包

常见的解析器

小结

xml的常用解析方式:

1. DOM
2. SAX
3. PULL

基于解析方式,常用的解析工具包: Dom4j

2.Dom4j的基本使用
DOM解析原理及结构模型
解析原理

将整个XML文档加载到内存,生成一个DOM树,并获得一个Document对象,通过Document对象就可以对DOM树进行操作。以下面books.xml文档为例。

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="0001"> 
        <name>JavaWeb开发教程</name>
        <author>张孝祥</author>
        <sale>100.00元</sale>
    </book>
    <book id="0002">
        <name>三国演义</name>
        <author>罗贯中</author>
        <sale>100.00元</sale>
    </book>
</books>
结构模型

DOM中的核心概念就是节点,在XML文档中的元素、属性、文本,在DOM中都是节点!所有的节点都封装到了Document对象中。

结论:使用Document对象,就可以去访问DOM树中的每一个节点  

引入dom4j的jar包

去官网下载 zip 包。http://www.dom4j.org/

通常我们会在项目中创建lib文件夹,将需要依赖的库放在这里。

库导入方式:

  1. 在IDEA中,选择项目鼠标右键--->弹出菜单-->open Module settings”-->Dependencies-->+-->JARs or directories... 找到dom4j-1.6.1.jar,成功添加之后点击"OK" 即可。

  2. 直接右键选择:Add as Library

小结

dom4j的解析思想,先把xml文档加载到内存中,从而得到一个DOM树,并创建一个Document对象去维护dom树。利用Document对象,就可以去解析DOM树(解析XML文件)

常用的方法

dom4j 必须使用核心类SaxReader加载xml文档获得Document,通过Document对象获得文档的根元素,然后就可以操作了。

SAXReader对象
方法作用
SAXReader sr = new SAXReader();构造器
Document read(String url)加载执行xml文档
Document对象
方法作用
Element getRootElement()获得根元素
Element对象
方法作用
List<Element> elements(String ele )获得指定名称的所有子元素。可以不指定名称
Element element(String ele)获得指定名称第一个子元素。
String getName()获得当前元素的元素名
String attributeValue(String attrName)获得指定属性名的属性值
String elementText(Sting ele)获得指定名称子元素的文本值
String getText()获得当前元素的文本内容
小结

解析xml的步骤:

  1. 创建SaxReader对象,调用read方法关联xml文件,得到一个Document对象

  2. 通过Document对象,获取根元素

  3. 获取根元素之后,就可以层层深剥,运用Element相关的API进行解析其子元素

方法演示

复制资料下的常用xml中"books.xml",内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="0001">
        <name>JavaWeb开发教程</name>
        <author>张孝祥</author>
        <sale>100.00元</sale>
    </book>
    <book id="0002">
        <name>三国演义</name>
        <author>罗贯中</author>
        <sale>100.00元</sale>
    </book>
</books>

注意:为了便于解析,此xml中没有添加约束

解析此文件,获取每本书的id值,以及书本名称,作者名称和价格.

步骤分析:

  1. 创建一个SaxReader对象,调用read方法加载一个xml文件获得文档对象

  2. 通过文档对象,获取根元素

  3. 通过根元素一层一层的进行解析子元素。

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.List;

public class Demo01 {
    public static void main(String[] args) throws DocumentException {
        //1. 创建一个SaxReader对象,调用read方法加载一个xml文件获得文档对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/book.xml");

        //2. 通过文档对象,获取根元素
        Element rootElement = doc.getRootElement();

        //3. 通过根元素一层一层的进行解析子元素。
        //获取所有的子元素
        List<Element> bookElements = rootElement.elements("book");

        for (Element bookElement : bookElements) {
            //System.out.println(bookElement);
            //解析属性
            String id = bookElement.attributeValue("id");
            System.out.println("id = " + id);
            //获取子元素文本
            String name = bookElement.elementText("name");
            String author = bookElement.elementText("author");
            String sale = bookElement.elementText("sale");
            System.out.println("name = " + name);
            System.out.println("author = " + author);
            System.out.println("sale = " + sale);



            System.out.println("----------------------");
        }
        
    }
}

需求二:

将xml中文件数据解析成为java对象,每个book解析为一个book类型的对象。然后将book对象放到一个集合中存储。

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="0001">
        <name>JavaWeb开发教程</name>
        <author>张孝祥</author>
        <sale>100.00元</sale>
    </book>
    <book id="0002">
        <name>三国演义</name>
        <author>罗贯中</author>
        <sale>100.00元</sale>
    </book>
</books>

步骤分析:

  1. 先创建一个Book类对应book元素

  2. 创建一个ArrayList集合用来存储解析后的book对象

  3. 创建SaxReader对象,调用read方法加载xml文件,得到文档对象

  4. 通过文档对象获取根元素,然后层层解析

代码实现:

public class Demo02 {
    public static void main(String[] args) throws DocumentException {
        //定义一个集合用来存储解析的Book对象
        ArrayList<Book> books = new ArrayList<>();



        //1. 创建一个SaxReader对象,调用read方法加载一个xml文件获得文档对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/book.xml");

        //2. 通过文档对象,获取根元素
        Element rootElement = doc.getRootElement();

        //3. 通过根元素一层一层的进行解析子元素。
        //获取所有的子元素
        List<Element> bookElements = rootElement.elements("book");

        for (Element bookElement : bookElements) {
            //System.out.println(bookElement);
            //解析属性
            String id = bookElement.attributeValue("id");
            System.out.println("id = " + id);
            //获取子元素文本
            String name = bookElement.elementText("name");
            String author = bookElement.elementText("author");
            String sale = bookElement.elementText("sale");

            //将解析的字符串封装成为对象,放到集合
            Book book = new Book(id,name,author,sale);
            books.add(book);

        }


        //将集合遍历,打印book对象
        for (Book book : books) {
            System.out.println("book = " + book);
        }

    }
}

class Book{
    private String id;
    private String name;
    private String author;
    private String sale;

    public Book() {
    }

    public Book(String id, String name, String author, String sale) {
        this.id = id;
        this.name = name;
        this.author = author;
        this.sale = sale;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getSale() {
        return sale;
    }

    public void setSale(String sale) {
        this.sale = sale;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", sale='" + sale + '\'' +
                '}';
    }
}
Dom4J结合XPath解析XML(了解)
介绍

XPath使用路径表达式来选取XML/HTML 文档中的元素节点或属性节点。节点是通过沿着路径 (path) 来选取的。XPath在解析XML/HTML文档方面提供了一独树一帜的路径思想。

XPath使用步骤

步骤1:导入jar包(dom4j和jaxen-1.1-beta-6.jar)

步骤2:通过dom4j的SaxReader获取Document对象

步骤3: 利用Xpath提供的api,结合xpath的语法完成选取XML文档元素节点进行解析操作。

Node接口中存在以下方法:

方法作用
List<Element> selectNodes("路径表达式")获取符合表达式的元素集合
Element selectSingleNode("路径表达式")获取符合表达式的唯一元素

我们熟知的Document,Element等都是Node的子类型,因此也能使用上述selectNode的方法。如下图

XPath语法(了解)

XPath也是一种解析XML或者HTML的方式。

  • XPath表达式,就是用于选取XML文档中节点的表达式字符串。获取XML文档节点元素一共有如下4种XPath语法方式:

    1. 绝对路径表达式方式 例如: /元素/子元素/子子元素...

    2. 相对路径表达式方式 例如: 子元素/子子元素.. 或者 ./子元素/子子元素..

    3. 全文搜索路径表达式方式 例如: //子元素//子子元素

    4. 谓语(条件筛选)方式 例如: //元素[@attr]

在xml解析得到的一个文档对象中,Document,Element,Attribute,Text ,都是接口Node的子类型。

Node中存在两个方法,可以结合xpath使用查询节点:

List<Node>  selecteNodes(路径) :将所有满足路径的节点给获取出来
Node  selecteSingleNode(路径) :获取单个满足路径的节点

xpath使用步骤:

  1. 创建SAXReader对象,调用read方法,关联xml文件。得到Document对象

  2. 就可以使用Document对象来调用方法传入xpath路径

绝对路径表达式(了解)

格式:  

String xpath="/根元素/子元素/子子元素...";

绝对路径是以“/”开头,一级一级描述标签的层级路径就是绝对路径,这里注意不可以跨层级

演示需求(将素材中的Contact.xml拷贝到项目中)

采用绝对路径获取从根节点开始逐层的查找name节点列表并打印信息
String path="/contactList/contact/name";

实现步骤:

  1. 先创建SAXReader对象,调用read方法,将Contact.xml关联,得到Document对象

  2. 定义绝对路径

  3. 调用selectedNodes

public class Demo01 {
    public static void main(String[] args) throws DocumentException {
        //采用绝对路径获取从根节点开始逐层的查找name节点列表并打印信息

        //1. 先创建SAXReader对象,调用read方法,将Contact.xml关联,得到Document对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/Contact.xml");
        //2. 定义绝对路径
        String xpath = "/contactList/contact/name";
        //3. 调用selectedNodes
        List<Node> nameNodes = doc.selectNodes(xpath);

        for (Node nameNode : nameNodes) {
            String text = nameNode.getText();
            System.out.println("text = " + text);
        }
        
    }
}

text = 潘金莲
text = 武松
text = 武大狼

相对路径表达式(了解)

相对路径介绍

格式:

String xpath2="./子元素/子子元素";		// "./"代表当前元素路径位置

需求: 先采用绝对路径获取 contact 节点 再采用相对路径获取下一级name子节点并打印信息。

public class Demo01 {
    public static void main(String[] args) throws DocumentException {
        //先采用绝对路径获取 contact  节点 再采用相对路径获取下一级name子节点并打印信息。
        //1. 先创建SAXReader对象,调用read方法,将Contact.xml关联,得到Document对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/Contact.xml");

        //先使用绝对路径,获取contact
        List<Node> contactNodes = doc.selectNodes("/contactList/contact");
        for (Node contactNode : contactNodes) {
            //使用相对路径获取name,并获取文本打印

            Node node = contactNode.selectSingleNode("./name");
            System.out.println("node.getText() = " + node.getText());

        }

    }
}


node.getText() = 潘金莲
node.getText() = 武松
node.getText() = 武大狼
全文搜索路径表达式(了解)
  • 全文搜索路径介绍

    格式:

String xpath1="//子元素//子子元素";

“/”符号,代表逐级写路径

“//”符号,不用逐级写路径,可以直接选取到对应的节点,是全文搜索匹配的不需要按照逐层级

举例说明
//contact找contact元素,无论元素在哪里
//contact/name找contact,无论在哪一级,但name一定是contact的子节点
//contact//namecontact无论在哪一种,name只要是contact的子孙元素都可以找到
//name

需求:直接全文搜索所有的 name元素并打印

public class Demo01 {
    public static void main(String[] args) throws DocumentException {
        //需求:直接全文搜索所有的 name元素并打印
        //1. 先创建SAXReader对象,调用read方法,将Contact.xml关联,得到Document对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/Contact.xml");

        List<Node> nodes = doc.selectNodes("//name");
        for (Node node : nodes) {
            System.out.println("node.getText() = " + node.getText());
        }

    }
}

 结论:

  • / 表示根节点 (不能跨层级)
  • // 表示全文任意节点 (可以跨层级)
谓语(条件筛选 了解)

介绍

谓语,又称为条件筛选方式,就是根据条件过滤判断进行选取节点

格式:

String xpath1="//元素[@属性名]";//查找元素对象,全文中只要含有该属性名的元素
String xpath2="//元素[@属性名=value]";//查找元素对象,全文中只要含有该属性,并指定的值

 需求:查找含有id属性的contact元素

public class Demo01 {
    public static void main(String[] args) throws DocumentException {
        //查找含有id属性的contact元素
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/Contact.xml");

        //List<Node> nodes = doc.selectNodes("//contact[@id]");//获取含有属性id的元素
        List<Node> nodes = doc.selectNodes("//contact[@id=1]");//获取含有属性并且值为1的元素
        for (Node node : nodes) {
            //将节点,先转换Element
            Element contact = (Element) node;
            System.out.println("contact.elementText(\"name\") = " + contact.elementText("name"));
        }

    }
}
小结

在xpath解析xml方式中,最核心的就是使用了"路径表达式"

  • xpath是利用"路径表达式"实现对xml文件的解析

路径表达式的语法:

  • 绝对路径表达式
/根元素/子元素/子子元素/....   (一层一层查找)
  •  相对路径表达式

./子元素/子子元素/.....
  •  全文搜索路径表达式
//元素     (会跨层级进行全文查找)
  •  条件筛选表达式
//元素[@属性名]
//元素[@属性名=属性值]

 6.综合案例

学习目标:
  • 理解所谓的框架是如何实现的,如何使用框架

需求
  • 需求:自定义dao层jdbc框架
  • 为了方便程序员操作数据库,让程序员更关注于sql代码层面和业务层面
案例效果

 

使用到的技术:

  • 反射

  • 注解

  • 动态代理

  • xml解析:xpath

案例分析

自定义jdbc框架开发步骤:

1、通过软配置方式,和数据库连接

  • 解析xml配置文件,获得:driver、url、username、password

  • C3P0连接池

    • 根据配置文件中的参数,创建连接池对象

2、创建@Select注解

  • 解析@Select注解中value值:select查询语句

3、创建映射接口Mapper

  • 把从@Select注解中解析出来的select查询语句,赋值给Mapper中的sql成员变量

4、创建SqlSession类

  • 提供getMapper()方法,用来获取代理对象

    • 说明:程序员在获取到代理对象后,利用代理对象调用某个方法时,会被代理对象拦截处理

自定义JDBC框架-代码实现
Configuration
  • 作用:读取配置文件

    • 配置文件名称被固定了:config.xml

/*配置类
  1. 解析XML文件
  2. 创建C3P0连接池
*/
public class Configuration {
    /* 定义数据库连接对象相关属性 */
    private String driver;//驱动
    private String url;//连接地址
    private String username;//登录名
    private String password;//密码

    /* Mapper接口的全名称 */
    private String interName;

    /* 数据库连接池对象 */
    private DataSource dataSource;

    /* 映射类对象 */
    private Mapper mapper = new Mapper();


    //无参构造方法
    public Configuration() {
        try {
            //解析"config.xml"文件
            SAXReader reader = new SAXReader();
            InputStream is = Configuration.class.getClassLoader().getResourceAsStream("config.xml");
            Document doc = reader.read(is);
            
            //调用自定义方法: 将核心配置文件中的数据封装到Configuration类的属性中
            loadConfigXml(doc);

            //调用自定义方法: 初始化数据库连接池对象
            createDataSource();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //初始化数据库连接池对象
    private void createDataSource() throws Exception {
        //创建c3p0核心类对象
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        
        //使用对象调用方法将四大连接参数给数据库连接池
        cpds.setDriverClass(driver);
        cpds.setJdbcUrl(url);
        cpds.setUser(username);
        cpds.setPassword(password);

        //将cpds赋值给成员变量ds
        this.dataSource = cpds;//数据库连接池对象
    }


    //将核心配置文件中的数据封装到Configuration类属性中
    private void loadConfigXml(Document doc) {
        /*
        //使用document对象调用方法获取property标签:
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.01:3306/itheima"/>
        <property name="username" value="root"/>
        <property name="password" value="itheima"/>
        */
        List<Node> list = doc.selectNodes("//property");

        //遍历List集合
        for (Node node : list) {
            //强制转换
            Element e = (Element) node;
            //获取property标签的name属性值
            String name = e.attributeValue("name");//双引号中的name是property标签的name属性 driver
            //获取property标签的value属性值
            String value = e.attributeValue("value");//双引号中的value是property标签的value属性 com.mysql.jdbc.Driver
           
            //将value的值赋值给成员变量
            switch (name) {
                case "driver":
                    this.driver = value;//数据库驱动
                    break;
                case "url":
                    this.url = value;//连接url
                    break;
                case "username":
                    this.username = value;//登录名
                    break;
                case "password":
                    this.password = value;//密码
                    break;
            }
        }

        //<package name="xxx.xxx.UserMapper"></package>
        Node node = doc.selectSingleNode("//package");
        Element e = (Element) node;
        //Mapper接口的全名称
        this.interName = e.attributeValue("name");//"xxx.xxx.UserMapper"
    }


    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getInterName() {
        return interName;
    }

    public void setInterName(String interName) {
        this.interName = interName;
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Mapper getMapper() {
        return mapper;
    }

    public void setMapper(Mapper mapper) {
        this.mapper = mapper;
    }
}
注解

@Select

//查询时使用的注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
    String[] value();
}

@ResultType

//查询结果的封装类型
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResultType {
    String value();
}
映射类:Mapper
  • 作用:把通过解析@Select注解中的属性值(sql语句),存储到Mapper对象中

public class Mapper {
    private String sql;//存储sql语句

    public Mapper() {
    }

    public Mapper(String sql) {
        this.sql = sql;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }
}
SqlSession类
  • 作用:

    1. 解析@Select、@ResultType注解

    2. 和数据库交互

    3. 把数据结果封装到指定的对象中

@SuppressWarnings("all")
public class SqlSession {
    /**
     * 动态代理
     */                     //clazz = UserMapper.class
                            //clazz = StudentMapper.class
    public <T> T getMapper( Class<T> clazz ) {
        
        //类加载器: 负责加载代理类到内存中
        ClassLoader classLoader = SqlSession.class.getClassLoader();

        //父接口
        Class[] interfaces = {clazz};


        T mapperProxy = (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {

            //在调用方法时,代理对象执行invoke方法,返回List
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //创建核心配置类对象
                Configuration config = new Configuration();


                /******** 解析 @Select、@ResultType *******/
                //config.getInterName() 获取接口的全路径名称  例:com.itheima.UserMapper
                Class clazz = Class.forName(config.getInterName());

                Method[] methods = clazz.getMethods();//获取到接口中所有的方法
                
                //遍历数组
                for (Method m : methods) {
                    //判断是否有注解
                    boolean boo = m.isAnnotationPresent(Select.class);

                    boolean boo2 = m.isAnnotationPresent(ResultType.class);

                    if (boo && boo2) {
                        //获取@Select注解对象
                        Select select = m.getAnnotation(Select.class);
                        
                        //获取属性值
                        String[] value = select.value();//{"select * from user"}
                        String sql = value[0];//select * from user
                        //给Mapper对象中的sql成员变量赋值
                        config.getMapper().setSql(sql);

                        //获取@ResultType注解对象
                        ResultType resultType = m.getAnnotation(ResultType.class);
                        String type = resultType.value();//获取属性值
                        config.getMapper().setResultType(type);
                    }
                }
                /*******************************/


                //获取映射对象
                Mapper mapper = config.getMapper();
                //利用映射对象,获取sql语句
                String sql = mapper.getSql();

                //利用映射对象,获取类型
                String resultType = mapper.getResultType();
                
                //通用型JDBC框架:考虑查询的结果类型是不同
                //为了保障结果类型统一, 把所有的结果类型当作Class对象
                Class cl = Class.forName(resultType);


                //获取数据库连接池对象
                DataSource ds = config.getDataSource();
                
                //利用连接池对象,获取Connection对象
                Connection conn = ds.getConnection();

                //调用自定义方法: 执行sql查询语句
                //参数1:Connection对象     
                //参数2:要执行的sql语句(select.....)
                //参数3:select查询语句的结果要封装到指定的类型对象中
                List list = queryForList(conn, sql, cl);

                return list;
            }
        });

        //代理对象返回给getMapper的调用者     UserMapper mapper = sqlSession.getMapper(UserMapper.class);//mapperProxy
        return mapperProxy;
    }
    
    
    
   public List queryForList(Connection conn, String sql, Class clazz) throws SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        List userList = new ArrayList();

        //通过连接对象得到预编译的语句对象
        PreparedStatement ps = conn.prepareStatement(sql);

        //执行SQL语句,得到结果集
        ResultSet rs = ps.executeQuery();

        while (rs.next()) {
            //获取构造方法对象,并实例化
            Object user = clazz.getConstructor().newInstance();

            //获取所有的成员变量(包含私有成员变量)
            Field[] fields = clazz.getDeclaredFields();
            
            for (Field field : fields) { //field可以是:id name passwd age gender ...
                //得到成员变量的名字
                String name = field.getName();

                //暴力破解: 取消权限检查
                field.setAccessible(true);

                //rs.getObject(name) 表示根据数据表的列名取出数据表中的列值 因为User类中的成员变量名必须和数据表列名一致
                //例如: name 的值是birthday 那么这里 rs.getObject(name)---》rs.getObject("age")获取数据表的年龄20
                Object table_value = rs.getObject(name);

                //void set(Object obj, Object value)给成员变量赋值,参数1:对象名 参数2:要赋的值
                field.set(user, table_value);

            }
            //user对象添加到集合中
            userList.add(user);
        }

        //释放资源
        rs.close();
        ps.close();
        conn.close();

        //返回集合
        return userList;
    }
}   

 

自定JDBC框架的使用
数据表
CREATE TABLE user (
  id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name varchar(30) DEFAULT NULL,
  passwd varchar(20) DEFAULT NULL,
  age int(3) DEFAULT NULL,
  gender varchar(2) DEFAULT NULL,
  adddate date DEFAULT NULL
);

# 测试数据
INSERT INTO user VALUES (null, 'itcast', '123123', '10', '男', '2020-12-11');
创建实体类
public class User {
    private int id;
    private String name;
    private String passwd;
    private int age;
    private String gender;
    private Date adddate;

    public User() {
    }

    public User(int id, String name, String passwd, int age, String gender, Date adddate) {
        this.id = id;
        this.name = name;
        this.passwd = passwd;
        this.age = age;
        this.gender = gender;
        this.adddate = adddate;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Date getAdddate() {
        return adddate;
    }

    public void setAdddate(Date adddate) {
        this.adddate = adddate;
    }


    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", passwd='" + passwd + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", adddate=" + adddate +
                '}';
    }
}
UserMapper接口
public interface UserMapper {
    //编写SQL语句
    
    //查询所有用户
    @Select("select * from user")
    @ResultType("com.itcast.pojo.User")
    public abstract List queryAllUser();

}
配置文件:config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>

    <!--数据源-->
    <dataSource>
        <!--驱动-->
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <!--地址-->
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/itheima"/>
        <!--用户名-->
        <property name="username" value="root"/>
        <!--密码-->
        <property name="password" value="itheima"/>
    </dataSource>

    <!--加载映射接口-->
    <mappers>
        <package name="com.itcast.mapper.UserMapper"></package>
    </mappers>

</configuration>
测试类
public class Test1 {
    @Test
    public void testSelect() {
        //使用jdbc框架中提供的API
        
        //实例化
        SqlSession sqlSession = new SqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> users = mapper.queryAllUser();

        for (User u : users) {
            System.out.println(u);
        }
    }
}

 

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿瞒有我良计15

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值