DOM

1. DOM简单学习

  • 功能:获取html文档内容

  • 代码:获取页面标签(元素)对象 Element

    • document.getElementById(id值)
  • 操作Element对象

    1. 修改属性值
      • 明确获取的对象是哪一个
      • 查看API文档,查找其中可以设置的属性
    2. 修改标签体内容
      • 属性:innerHTML
        1. 获取元素对象
        2. 使用innerHTML属性修改标签体内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <body>
    <img src="../img/off.gif" alt="开灯" id="light">
    <h1 id="on">关灯</h1>
    <script>
    var light = document.getElementById("light");
    alert("换图片");
    light.src = "../img/on.gif";
    var h1 = document.getElementById("on");
    h1.innerHTML="关灯";
    </script>
    </body>

2. DOM概念

  • Document Object Model文档对象模型

  • 将标记语言文档的各个组成部分,封装为对象。可以使用这些对象,对标记语言文档进行CRUD的动态操作。

  • W3C DOM 标准被分为 3 个不同的部分:

    • 核心 DOM - 针对任何结构化文档的标准模型

      • Document:文档对象

      • Element:元素对象

      • Attribute:属性对象

      • Text:文本对象

      • Comment:注释对象

      • Node:节点对象,其他5个的父对象

    • XML DOM - 针对 XML 文档的标准模型

    • HTML DOM - 针对 HTML 文档的标准模型

3.Document对象

  1. 创建:在html dom模型中可以使用window对象获取
  2. 方法
    • 获取Element对象
      • getElementById(): 根据id属性值获取元素对象。id属性值一般唯一
      • getElementsByTagName():根据元素名称获取元素对象们。返回值是一个数组
      • getElementsByClassName():根据Class属性值获取元素对象们。返回值是一个数组
      • getElementsByName(): 根据name属性值获取元素对象们。返回值是一个数组
    • 创建其他DOM对象:
      • createAttribute(name)
      • createComment()
      • createElement()
      • createTextNode()

4.Element

  1. 获取/创建:通过document来获取和创建

  2. 方法:

    • removeAttribute():删除属性

    • setAttribute():设置属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<a>链接</a>
<input type="button"id="btn_set"value="设置属性">
<input type="button"id="btn_del"value="删除属性">
<script>
var btn = document.getElementById("btn_set");
var tagName_a = document.getElementsByTagName("a")[0];
btn.onclick = function () {
tagName_a.setAttribute("href","https://www.baidu.com");
}
var btndel = document.getElementById("btn_del");
btndel.onclick = function () {
tagName_a.removeAttribute("href");
}
</script>

5.Node

  1. 特点:所有dom对象都可以被认为是一个节点

  2. 方法:

    CRUD dom树:

    • appendChild():向节点的子节点列表的结尾添加新的子节点。
    • removeChild() :删除(并返回)当前节点的指定子节点。
    • replaceChild():用新节点替换一个子节点。
  3. 属性

    parentNode:返回当前节点的父节点

6.HTML DOM

  1. 标签体的设置和获取:innerHTML
  2. 使用html元素对象的饿属性
  3. 控制样式
    • 使用元素的style属性来设置
    • 提前定义类选择器的样式,通过元素的className属性来设置其class属性值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTMLDOM</title>
<style>
.d1{
border: 1px solid blue;
}
</style>
</head>
<body>
<div id="div">
div
</div>
<div id="div1">
div
</div>
<script>
var div = document.getElementById("div");
div.onclick = function () {
div.style.border = "1px red solid";
//font-size---->fontSize
div.style.fontSize="50px";
}
var div1 = document.getElementById("div1");
div1.onclick = function () {
div1.className="d1";
}
var innerHTML = div.innerHTML;
//div中替换一个文本输入框
//div.innerHTML = "<input type='text'>";
//在div中追加一个文本输入框
div.innerHTML += "<input type='text'>";
</script>
</body>
</html>

JavaScript

1. 概念

  • 一门客户端脚本语言
    • 运行在客户端浏览器中,每一个浏览器都有一个JavaScript的解析引擎
    • 脚本语言:不需要编译,直接就可以被浏览器解析执行
  • 功能
    • 可以来增强用户和html页面的交互过程,可以来控制html元素,让页面有一些动态的效果,增强用户的体验

2. 基本语法

  1. 与html结合方式

    • 内部JS

      定义script标签.标签体内容就是JS代码

    • 外部JS

      定义script标签,通过src属性引入外部的JS文件

    • 注意:

      1. script可以定义多个,可以定义在html页面的任意地方.但是定义的位置会影响执行顺序
  2. 注释

    • 单行注释 //
    • 多行注释 /* */
  3. 数据类型

    • 原始数据类型:
      • number:数字。整数 / 小数 / NAN
      • string:字符串
      • boolean:true / false
      • null:对象为空的占位符
      • undefined:未定义。如果一个变量没有给初始化值,则默认赋值undefined
    • 引用数据类型:对象
  4. 变量

    • 一小块存储数据的内存空间
    • Java是强类型语言,JavaScript是弱类型语言
      • 强类型:在开辟变量存储空间时,定义了空间将来存储的数据的数据类型。只能存储固定类型的数据
      • 弱类型:在开辟变量存储空间时,不定义将来的存储数据类型,可以存放任意类型的数据
    • 语法:var 变量名 = 初试化值
  5. 运算符

    • 一元运算符

    • 算数/比较运算符

      • 全等于===:类型也必须相同
    • 逻辑运算符

      && || !

      • 其他类型装boolean
        1. number:0或者NAN为假,其他为真
        2. string:除恶空字符串。其他都是true
        3. null和undefined:false
        4. 对象:所有对象都是true
    • 三元运算符 ? :

  6. 流程控制语句

    • if…..else….
    • switch
      • 在Java中可以接收的数据类型:byte、int、short、char、枚举、String
      • 在JS中,可以接收任意类型的数据
    • while
    • do……while
    • for
  7. 特殊语法

    • 变量的定义使用var关键字,也可以不用

      使用var:定义的是局部变量

      不使用var:定义的是全局变量

3. 基本对象

  1. Array

    • 创建
      • var arr = new Array(元素列表);
      • var arr = new Array(默认长度);
      • var arr = [元素列表];
    • 特点
      • 在JS中,数组元素是可变的
      • JS中,数组长度也是可变的
    • 方法
      • join(参数):将数组中的元素按照指定的分隔符拼接为字符串
      • push():向数组的末尾添加一个或更多元素,并返回新的长度
  2. Boolean

  3. Date

    • 创建
      • var date = new Date();
    • 方法
      • toLocalString():返回当前date对象对应的时间本地字符串格式
      • getTime():返回当前时间对象描述时间到1970年1月1号的毫秒值差
  4. Math

    • 创建
      • Math对象不用创建,直接使用 Math.方法名
    • 方法
      • random():返回0~1之间的随机数。[0,1)
      • cell(x):对数字进行向上舍入
      • floor(x):向下舍入
      • round(x):把数四舍五入为最接近的整数
    • 属性
      • PI
  5. Number

  6. String

  7. RegExp:正则表达式对象

    • 正则表达式:定义字符串的组成规则

      • 定义单个字符:[],如 [a],[ab],[azAZ0~9]

      • \d :单个数字字符

      • \w:单个单词字符

      • 量词符号:

        *表示出现0次或多次

        ?表示出现0次或1次

        +表示出现1次或多次

        {m,n} m<=数量<=n,m如果缺省表示最多n次;n如果缺省表示最少m次

        \w{6,12}

      • 开始结束符号:开始^ 结束$

    • 正则对象

      • 创建
        1. var reg = new RegExp(“正则表达式”);
        2. var reg = /正则表达式/ ;
      • 方法
        1. test(字符串):验证字符串是否符合规范
  8. Global

    • 特点:全局对象,封装的方法不需要对象可以直接调用。 方法名()

    • 方法

      • encodeURI(str):URL编码

        decodeURI(str):URL解码

      • encodeURIComponent(str):URL编码

        decodeURIComponent(str):URL解码

      • parseInt():将字符串转换为数字,逐一判断每一个字符是否是数字,知道不是数字为止,将数字部分转为number

      • isNAN():判断是否是NAN

        如: var a = NAN; a == NAN; //false

        ​ isNAN(a);//true

      • eval():将JavaScript字符串转换为脚本代码来执行

    • URL编码:

  9. Function:函数对象

    • 创建
      • var fun = new Function(形式参数列表,方法体)
      • function 方法名称(形式参数列表) { 方法体 }
      • var 方法名 = function() { 方法体 }
    • 属性
      • length:形参的个数
    • 特点
      • 方法定义时形参的类型不用写,返回值类型也不写
      • 方法是一个对象,如果定义名称相同的方法,会覆盖
      • 在JS中,方法的调用只与方法名称有关,和参数列表无关
      • 在方法声明中有一个隐藏的内置对象(数组),arguments,封装所有的实际参数
    • 调用
      • 方法名称(实际参数列表)

CSS

1. 概念

  • 层叠样式表。页面美化和布局控制
  • 层叠:多个样式可以作用在同一个html的元素山,同时生效
  • 好处
    • 将内容展示和样式控制分离,降低耦合度

2. CSS使用

  • CSS和html结合使用

    1. 内联样式

      在标签内使用style属性指定css代码

      1
      <div style="color: antiquewhite">你好</div>
    2. 内部样式

      在head标签内,定义style标签,style标签体的内容就是css代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      <head>
      <style>
      div{
      color: brown;
      }
      </style>
      </head>
      <body>
      <!--内部样式-->
      <div>你好</div>
      </body>
    3. 外部样式

      1. 定义CSS资源文件
      2. 在head标签内,定义link标签引入外部资源文件
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      <head>
      <link rel="stylesheet" href="../CSS/a.css">
      或者
      <style>
      @import "../CSS/a.css";
      </style>
      </head>
      a.css文件
      div{
      color: green;
      }
  • css语法

    • 格式

      选择器{

      ​ 属性名1:属性值1;

      ​ 属性名2:属性值2

      ​ …….

      }

    • 选择器:筛选具有相似特征的元素

      每一对属性需要使用;隔开,最后一对属性可以不需要

3. 选择器

3.1 基本选择器

  1. id选择器:选择具体的id属性值的元素。#id属性值{}
  2. 元素选择器:选择具有相同标签名称的元素
  3. 类选择器:选择具有相同的class属性值的元素 .class属性值{}

3.2 扩展选择器

  • 选择所有元素 *{}

  • 并集选择器:选择器1,选择器2{}

  • 后代元素选择器:选择指定父元素的指定的子元素,父元素>子元素{}

  • 子元素选择器:选择指定元素内的指定后代元素,祖先元素 子元素{}

  • 属性选择器:选择元素名称,属性名=属性值的元素,元素名称[属性名="属性值"]

  • 伪类选择器:选择一些元素具有的状态,元素:状态{}

    如:<a>的状态

    ​ link:初始化的状态

    ​ visited:被访问过的状态

    ​ active:正在访问状态

    ​ hover:鼠标悬浮状态

4. CSS属性

  1. 字体、文本

    • font_size:字体大小

    • color:文本颜色

    • text_align:对齐方式

    • line_height:行高

  2. 背景

    • background
    1
    2
    3
    4
    5
    div{
    border: 1px solid red;
    height: 296px;
    background: url("../HTML/示意图.PNG") repeat center;
    }
  3. 边框

    • border:边框 border:1px solid red;
  4. 尺寸

    • width:宽度
    • height:高度
  5. 盒子模型:控制布局

    • margin:外边距

    • padding:内边距。默认情况下内边距会影响到整个盒子的大小。

      box-sizing: border-box;设置盒子的属性,让width和height就是最终盒子的大小

    • float:浮动

      • right
      • left

HTML标签

1. 概念

  • Hyper Text Markup Language,超文本标记语言
  • 超文本:是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本
  • 标记语言:由标签构成的语言。<标签名称>

2. 语法

  • html文档后缀名:html或htm

  • 标签分为

    围堵标签:由开始标签和结束标签。如< html> < /html>

    自闭和标签:开始标签和结束标签在一起。如< br/>

  • 标签可以嵌套

  • 在开始标签中可以定义属性。属性由键值对构成,值需要用引号引起来

  • 不区分大小写

3. 标签

3.1文件标签

  • html:标识html文档的根标签

  • head:头标签。用于指定html文档的一些属性。引入外部的资源

  • title:标题标签

  • body:体标签

  • < !DOCTYPE html>

3.2 文本标签

  • 注释:<!--注释内容-->

  • <h1> </h1> to <h6> </h6> :标题标签,字号从h1到h6变小,且自动换行

  • <p> </p> :段落标签

  • <br> :换行标签

  • <hr>:显示一条水平线。参数:color(颜色),width(线条宽度) size(线条高度) align(对齐方式)

  • <b> </b> :字体加粗

  • <i> </i>:字体斜体

  • <center> </center> :文本居中

  • <font> </font> :字体标签

  • 属性定义

    • color
      1. 英文单词:red、green
      2. rgb(值1,值2,值3):值的范围0~255,如rgb(0,0,255)
      3. #值1值2值3:值的范围:00~FF之间。如 #FF00FF
    • width
      1. 数值:width=”20”,单位默认是像素px
      2. 数值%:占比,相对与父元素的比例

3.3 图片标签

  • img:展示图片

    • 属性

      src:指定图片的位置

      alt:当图片加载不出来时所显示的文字

  • src路径

    • 绝对路径

    • 相对路径

      ./ :代表当前目录

      ../ :代表上一级目录

3.4 列表标签

  • 有序列表
    • ol :定义一个有序列表
    • li :有序列表项
  • 无序列表
    • ul :定义一个无序列表
    • li :无序列表项

3.5 链接标签

  • a :定义一个超链接

    • href:指定访问资源的URL

    • target:指定打开资源的方式

      _self:默认值,在当前页面打开

      _blank:在空白页面打开

1
2
3
<a href="https://hxx-98.github.io/"  target="_blank">hxx</a>
<a href="https://hxx-98.github.io/" target="_self">hxx</a>
<a href="https://hxx-98.github.io/"> <img src="示意图.PNG"> </a>

3.6 div和span

  • span:文本信息在一行展示,行内标签/内联标签
  • div:每一个div占满一行,块级标签
    • id

3.7 语义化标签

提高程序可读性

  • header
  • footer

3.7 表格标签

  • table:表

    width、border(边框)、bgcolor(背景色)、align

    cellpadding:定义内容和单元格之间的距离

    cellspacing:定义单元格之间的距离,若指定为0,则单元格的线会合为一条

  • tr:行

    • bgcolor(背景色)
    • align
  • td:单元格

    • bgcolor(背景色)
    • align
    • colspan:合并列
    • rowspan:合并行
  • th:表头单元格

  • caption:表格标题

  • thead:表示表格的头部分

  • tbody:表示表格的体部分

  • tfoot:表示表格的脚部分

3.8 表单标签

  • 表单:用于采集用户输入数据。用于和服务器进行交互。

  • 标签:form

    action:指定提交数据的URL

    method:指定提交方式

    • get
      1. 请求参数会在地址栏中显示,会封装在请求体中
      2. 请求参数长度有限制
      3. 不太安全
    • post
      1. 请求参数不会在地址栏中显示,会封装在请求体中
      2. 请求参数长度没有限制
  • 表单项中的数据要想被提交,必须指定其name属性

  • 表单项标签

    input:可以通过type属性值,改变元素展示的样式

    • label:指定输入项的文字描述信息。其for属性和input中的id属性对应,若对应,则点击label区域会在input输入框获取焦点

    • type

      • text:文本输入框

        placeholder:指定输入框的提示信息

      • password:密码输入框

      • radio:单选框

        注意

        1. 要想让多个单选框实现单选的效果,则多个单选框的name属性值必须一样

        2. 一般会给每一个单选框提供value属性,指定其被选中后提交的值

        3. checked=”checked”:代表默认被选中

      • checkbox:复选框

      • file:文件选择框

      • hidden:隐藏域

      • 按钮

        1. submit:提交
        2. button:按钮
        3. image:图片提交按钮,src属性指定图片的路径
      • color:取色器

      • date:日期,年月日

      • datetime-local:年月日时分

    • select:下拉列表

      • 子元素option指定列表项,其中可加入selected表示默认选择
    • textarea:文本域

      • cols:指定列数,每一行由多少个字符
      • rows:默认行数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<form action="#" method="get">
<label for="username">用户名</label>
<input id="username" type="text" name="username"placeholder="请输入用户名"><br>
<!--for和id对应起来-->
<label for="password">密码</label>
<input id="password" type="password"name="password"placeholder="请输入密码"><br>
<!--name值要一样-->
性别<input id="male"type="radio" name="gender"value="male"checked="checked"> <label for="male"></label>
<input id="female"type="radio" name="gender"value="female"> <label for="female"></label><br>
爱好
<input id="shopping"type="checkbox"name="hobby" value="shopping"> <label for="shopping">逛街</label>
<input id="sing"type="checkbox"name="hobby"value="sing"> <label for="sing">唱歌</label><br>
图片<input type="file"name="file"><br>
隐藏域 <input type="hidden"name="id"value="aaaa"><br>
取色器<input type="color"><br>
生日<input type="date"><br>
生日<input type="datetime-local"><br>
邮箱<input type="email"name="email"><br>
年龄<input type="number"name="age"><br>
省份
<select name="province">
<option value="null"selected>请选择</option>
<option value="陕西">陕西</option>
<option value="山西">山西</option>
<option value="北京">北京</option>
</select><br>
自我描述<textarea name="describe" id="des" cols="30" rows="10"></textarea><br>
<!--input type="image"src="移动运营商网间信令互通示意图.PNG"-->
<input type="submit" value="登录">
</form>

静态资源和动态资源

静态资源

  • 使用静态网页开发技术发布的资源
  • 特点:
    • 所有用户访问,得到的结果是一样的
    • 如:文本、图片、视频、音频、HTML、CSS、JavaScript
    • 如果用户请求的是静态资源,那么服务器会直接将静态资源发送给浏览器。浏览器中内置了静态资源的解析引擎,可以展示静态资源
  • HTML:用于搭建基础网页,展示页面的内容
  • CSS:用于美化页面,布局页面
  • JavaScript:控制页面元素,让页面有动态效果

动态资源

  • 使用动态网页技术发布的资源
  • 特点
    • 所有用户访问,得到的结果可能不一样
    • 如:JSP/servlet、PHP、asp
    • 如果用户请求的是动态资源,那么服务器会执行动态资源,转换为静态资源,再发送给浏览器

数据库连接池和Spring JDBC

数据库连接池

  • 概念:本质上是一个容器,存放数据库连接的容器

    当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器

  • 数据库厂商实现

    cp30:数据库连接池技术

    Druid:数据库连接池实现技术(阿里巴巴)

C3P0

  • 下载c3p0压缩包:https://sourceforge.net/projects/c3p0/files/latest/download?source=files

  • 导入jar包:c3p0-0.9.5.5.jar和mchange-commons-java-0.2.19.jar

  • 定义配置文件:

    • 名称:c3p0.propertiesorc3p0-config.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <c3p0-config>
    <!--使用默认的配置读取连接池对象 -->
    <default-config>
    <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
    <!--jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=GMT%2B8-->
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/test?&amp;useSSL=false&amp;serverTimezone=GMT%2B8</property>
    <property name="user">root</property>
    <property name="password">123456</property>

    <!--连接池对象 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">10</property>
    <property name="checkoutTimeout">3000</property>
    </default-config>

    <name-config name="otherc3p0">
    <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
    <property name="user">root</property>
    <property name="password">123456</property>

    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">10</property>
    <property name="checkoutTimeout">3000</property>
    </name-config>>
    </c3p0-config>
    • 路径:直接将文件放在src目录下即可
  • 创建数据库连接对象 ComboPooledDataSource

  • 获取连接:getConnection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class c3p0demo2 {
    public static void main(String[] args) throws SQLException {
    DataSource ds = new ComboPooledDataSource();
    //DataSource ds = new ComboPooledDataSource("otherc3p0");
    //验证最大连接数量参数
    for (int i = 0; i < 10; i++) {
    ds.getConnection();
    System.out.println(i+":"+ds);
    }
    }
    }

Druid

  • 导入jar包,下载地址:https://repo1.maven.org/maven2/com/alibaba/druid/

  • 定义配置文件properties

    1
    2
    3
    4
    5
    6
    7
    driverClassname=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=GMT%2B8
    username=root
    password=123456
    initialSize=5
    maxActive=10
    maxWait=3000
  • 获取数据库连接池对象:通过工厂类来获取 DruidDataSourceFactory

  • 获取数据库连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class druiddemo {
    public static void main(String[] args) throws Exception {
    Properties pro = new Properties();
    //加载配置文件
    InputStream is = druiddemo.class.getClassLoader().getResourceAsStream("druid.properties");
    pro.load(is);
    //参数是配置文件Properties对象
    DataSource ds = DruidDataSourceFactory.createDataSource(pro);
    Connection conn = ds.getConnection();
    System.out.println(conn);
    }
    }

Druid工具类实现

  • 定义一个工具类JDBCutils

    提供静态代码块加载配置文件,初始化连接池对象

    提供方法

    • 获取数据库连接方法:通过数据库连接池对象获取连接
    • 释放资源
    • 获取连接池的方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    public class JDBCutils {
    //定义数据库连接池对象
    private static DataSource ds;

    //静态代码块
    static{
    try {
    //加载配置文件
    Properties pro = new Properties();
    pro.load(JDBCutils.class.getClassLoader().getResourceAsStream("druid.properties"));
    //获取DataSource
    ds = DruidDataSourceFactory.createDataSource(pro);
    } catch (IOException e) {
    e.printStackTrace();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    //获取数据库连接方法
    public static Connection getConnection() throws SQLException {
    return ds.getConnection();
    }
    //释放连接
    public static void close(ResultSet rs,Statement stmt, Connection conn){
    if(rs != null){
    try {
    rs.close();
    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }
    }
    if(stmt != null){
    try {
    stmt.close();
    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }
    }
    if(conn != null){
    try {
    conn.close(); //归还连接
    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }
    }
    }
    public static void close(Statement stmt, Connection conn){
    close(null,stmt,conn);
    }
    //返回数据库连接池
    public static DataSource getDataSource(){
    return ds;
    }
    }
  • 工具类测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class druiddemo2 {
    public static void main(String[] args) {
    Connection connection = null;
    PreparedStatement pstmt = null;
    //获取数据库连接
    try {
    connection = JDBCutils.getConnection();
    String sql = "insert into user values(?,?)";
    pstmt = connection.prepareStatement(sql);
    //给问号赋值
    pstmt.setString(1,"hxxx");
    pstmt.setString(2,"123");
    //执行sql
    int count = pstmt.executeUpdate();
    System.out.println(count);

    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }finally {
    //释放连接
    JDBCutils.close(pstmt,connection);
    }
    }
    }

Spring JDBC

  • Spring框架对JDBC简单封装,提供了一个JDBCTemplate对象简化JDBC的开发

  • 步骤

    1. 导入jar包:下载链接: https://jar-download.com/artifacts/org.springframework/spring-jdbc
    2. 创建JDBCTemplate对象。依赖于数据源DataSource
    3. 调用JdbcTemplate的方法来完成CRUD的操作
      • update():执行DML语句。增删改
      • queryForMap():将查询结果集封装为Map集合,将列名作为key,将值作为value,将这条记录封装为一个Map集合。这个方法查询结果集长度只能是1.
      • queryForList():将查询结果集封装为Lisit集合,每一条记录封装为一个Map集合,再对Map集合装载到List集合中
      • query():查询结果,将结果封装为JavaBean对象
      • queryForObject():将结果封装为对象
  • 案例

    • 需求(表emp,字段id,name,age,dep_id)

      1. 添加一条记录

      2. 删除一条记录

      3. 查询id为1的记录,将其封装为Map集合

      4. 查询所有记录,将其封装为List集合

      5. 查询所有记录,将其封装为user对象的List集合

      6. 查询总记录数

    • 封装user类

      1
      2
      3
      4
      5
      6
      7
      public class user {
      private String name;
      private Integer id;
      private Integer age;
      private Integer dep_id;
      //省略get,set,toString
      }
    • 使用Junit进行测试

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      public class JdbcTemplateTest {
      private JdbcTemplate template = new JdbcTemplate(JDBCutils.getDataSource());
      // 添加一条记录
      @Test
      public void test1(){
      String sql = "insert into emp values(?,?,?,?)";
      int count = template.update(sql, 6, "老王", 21, null);
      System.out.println(count);
      }

      //删除一条记录
      @Test
      public void test2(){
      String sql = "delete from emp where id = ?";
      int count = template.update(sql, 6);
      System.out.println(count);
      }
      //查询id为1的记录,将其封装为Map集合
      @Test
      public void test3(){
      String sql = "select *from emp where id = ?";
      Map<String, Object> stringObjectMap = template.queryForMap(sql, 1);
      System.out.println(stringObjectMap);
      }
      //查询所有记录,将其封装为List集合
      @Test
      public void test4(){
      String sql = "select *from emp";
      List<Map<String, Object>> mapList = template.queryForList(sql);
      for (Map<String, Object> stringObjectMap : mapList) {
      System.out.println(stringObjectMap);
      }
      }
      //查询所有记录,将其封装为user对象的List集合
      @Test
      public void test5(){
      String sql = "select *from emp";
      List<user> list = template.query(sql, new BeanPropertyRowMapper<user>(user.class));
      for (user user : list) {
      System.out.println(user);
      }
      }
      //查询所有记录,将其封装为user对象的List集合
      @Test
      public void test6(){
      String sql = "select *from emp";
      List<user> list = template.query(sql, new RowMapper<user>() {
      @Override
      public user mapRow(ResultSet resultSet, int i) throws SQLException {
      user use = new user();
      String name = resultSet.getString("name");
      Integer id = resultSet.getInt("id");
      Integer age = resultSet.getInt("age");
      Integer dep_id = resultSet.getInt("dep_id");
      use.setAge(age);
      use.setDep_id(dep_id);
      use.setId(id);
      use.setName(name);
      return use;
      }
      });
      for (user user : list) {
      System.out.println(user);
      }
      }
      //查询记录总数
      @Test
      public void test7(){
      String sql = "select count(id) from emp";
      Long aLong = template.queryForObject(sql, Long.class);
      System.out.println(aLong);
      }
      }

JDBC管理事务

JDBC控制事务

  • 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失效

  • 使用Connection对象来管理事务:

    开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务

    提交事务:commit()

    回滚事务:roolback()

  • setAutoCommit(boolean autoCommit):true:开启自动提交;false关闭自动提交

    ​ 将此连接的自动提交模式设置为给定状态。如果连接处于自动提交模式下,则它的所有SQL语句将被执行并作为单个事务提交。否则直到调用commit方法或rollback方法为止。

    提交发生在语句完成时,完成时间取决于SQL语句的类型:

    • 对于DML语句(比如insert、update、delete)和DDL语句,语句在执行完毕时完成
    • 对于select语句,语句在关联结果集关闭时完成
    • 对于CallableStatement对象或者返回多个结果的语句,语句在所有关联结果集关闭并且已经获得所有更新计数和输出参数时完成。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
try {
conn = JDBCutils.getConnection();
//开启事务,在执行sql前开启
conn.setAutoCommit(false);
String sql1 = "update stu set account = account - 500 where id = 2";
stmt1 = conn.prepareStatement(sql1);
stmt1.executeUpdate();
String sql2 = "update stu set account = account + 500 where id = 1";
stmt2 = conn.prepareStatement(sql2);
stmt2.executeUpdate();
//手动添加一个异常
int a = 1 / 0;
//所有sql都执行完提交事务
conn.commit();
} catch (Exception e) {
//不管出现什么异常在catch中都需要回滚
try {
if(conn!=null)
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}

JDBC连接数据库占位符和prepareStatement解决sql注入

1. 输入用户名和密码判断是否登陆成功

  • 分别使用StatementprepareStatement执行对象来执行sql查询用户和密码,进而根据执行结果判断是否登陆成功。
  • 下面是编写的静态登录方法login 和 plogin
  • JDBCutils是自己抽取的工具类,用于获取数据库连接对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public class jdbcdemo3 {
public static boolean login(String username, String userpassword) {
if (username.equals("") || username.equals("")) {
return false;
}
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//连接数据库判断是否登陆成功
try {
//获取数据库连接
conn = JDBCutils.getConnection();
//获取sql执行对象
stmt = conn.createStatement();
//定义sql语句
String sql = "select * from user where username = '"+ username +"' and userpassword = '"+userpassword+"'";
System.out.println(sql);
//sql = "select * from user where username = 'hxx' and userpassword = '123'";
rs = stmt.executeQuery(sql);
return rs.next();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCutils.close(stmt, conn, rs);
}
return true;
}
public static boolean plogin(String username, String userpassword) {
if (username.equals("") || username.equals("")) {
return false;
}
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
//连接数据库判断是否登陆成功
try {
//获取数据库连接
conn = JDBCutils.getConnection();
//定义sql语句
String sql = "select * from user where username = ? and userpassword = ?";
//获取sql执行对象
stmt = conn.prepareStatement(sql);
stmt.setString(1,username);
stmt.setString(2,userpassword);
rs = stmt.executeQuery();
return rs.next();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCutils.close(stmt, conn, rs);
}
return true;
}
public static void main(String[] args) {
//键盘输入用户名和密码
String user;
String password;
Scanner scanner = new Scanner(System.in);
user = scanner.nextLine();
password = scanner.nextLine();
boolean plogin = plogin(user, password);
if (plogin == true) {
System.out.println("登陆成功!");
} else {
System.out.println("登陆失败!");
}
}
}
  • 代码运行结果
    • user表中的信息有 hxx 123 和 qzy 123
    • 使用login方法时和plogin方法的运行结果
1
2
3
4
5
6
7
8
// 执行login 方法判断登录
asd
a' or 'a' = 'a
登陆成功!
//执行plogin 方法判断登录
asd
a' or 'a' = 'a
登陆失败!
  • 结果分析

    在login方法中的sql语句中会出现sql注入的状况,将a’ or ‘a’ = ‘a输入后的sql实际上是下面的语句,是一个恒等式,也就意味之这条sql中where返回true,select将会返回user表中所有的数据,sql语句执行结果不为空则登录成功。

1
2
String sql = "select * from user where username = '"+ username +"' and userpassword = '"+userpassword+"'";
String sql = "select * from user where username = 'asd' and userpassword = 'a' or 'a' = 'a';

​ 为避免这种情况,我们使用占位符和prepareStatement。sql语句中需要的参数位置使用 ? 号代替。然后将sql传递给prepareStatement对象,并且使用该对象中的成员方法setXxxx()对?号所代表的变量赋值。

1
2
3
4
String sql = "select * from user where username = ? and userpassword = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1,username); //第一个参数代表第几个?号
stmt.setString(2,userpassword);

2. sql语句中单双引号’”+ username +”‘ and userpassword = ‘“+userpassword+”‘“的问题

  • 首先上面的sql是一个字符串,对这个字符串应该做出如下拆分来理解。
1
"select * from user where username = '"+ username +"' and userpassword = '"+userpassword+"'"

1:"select * from user where username = '"

​ 这里的双引号相当于定义了一个字符串select * from user where username = '

2:+ username +

​ 这里是用+号连接了username这个字符串变量

3:"' and userpassword = '"

​ 这里的双引号相当于定义了一个字符串' and userpassword = '

4:+userpassword+

​ 这里是用+号连接了userpassword这个字符串变量

5:'

​ 单独的单引号

6: 整体看单引号的用处,是因为user表中username和userpassword字段是字符串类型,那么等于号后面的内容要用单引号括起来。注意:下面单引号和双引号之间不可以有空格!就相当于在本身传递的username上加了一个空格

JDBC工具类

抽取JDBC工具类

  • 目的:简化书写
  • 分析:使用JDBC连接数据库,查询表中的所有数据。
  1. 注册驱动
  2. 抽取一个方法获取连接对象
  3. 抽取一个方法释放资源

配置文件

  • 为获取数据库对应url、user、password,可以将其写入配置文件,在类中的静态代码块中读取字段值
1
2
3
4
url=jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=GMT%2B8
user=root
password=123456
driver=com.mysql.cj.jdbc.Driver

定义jdbcutils类

  • 本类中包含两个静态方法,获取数据库连接对象和释放资源。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
* JDBC工具类
* 抽取一个方法获取连接对象
* 抽取一个方法释放资源
* */
public class JDBCutils {
private static String url;//定义静态变量
private static String user;
private static String password;
private static String driver;
static{
try {
//创建Properties对象
Properties pro = new Properties();
ClassLoader cls = JDBCutils.class.getClassLoader();
InputStream is = cls.getResourceAsStream("jdbc.properties");
pro.load(is);
//pro.load(new FileReader("E:\\JAVA\\jdbc01\\jdbcday1\\src\\jdbc.properties"));
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
} catch (IOException e) {
e.printStackTrace();
}
//注册驱动
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/*
* 获取数据库连接对象
* @return Connection
* */
public static Connection getConnection() throws Exception {
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
/*
* 释放资源
* 执行增删改语句时需要释放statement(sql执行对象)和Connection(数据库连接对象)
* 执行查询语句需要另外释放Resultset(数据库返回结果集)
* */
public static void close(Statement stmt,Connection conn){
if(stmt!=null){
try {
stmt.close();
System.out.println("数据库语句执行对像statement已关闭");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//关闭数据库连接
if(conn!=null){
try {
conn.close();
System.out.println("数据库连接connection已关闭");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close(Statement stmt, Connection conn, ResultSet rs){
if(stmt!=null){
try {
stmt.close();
System.out.println("数据库语句执行对像statement已关闭");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//关闭数据库连接
if(conn!=null){
try {
conn.close();
System.out.println("数据库连接connection已关闭");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(rs!=null){
try {
rs.close();
System.out.println("Resultset资源已关闭");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}

编写demo使用jdbcutil类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class jdbcdemo2 {
public static void main(String[] args) {
//获取数据库连接
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = JDBCutils.getConnection();
String sql = "select *from stu";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
while (rs.next()) {
Integer id = rs.getInt("id");
String stu_name = rs.getString("stu_name");
String stu_phone = rs.getString("stu_phone");
System.out.println("id:" + id + " stu_name:" + stu_name + " stu_phone:" + stu_phone);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.close(stmt,conn,rs);
}
}
}

JDBC连接MySQL数据库

1.JDBC连接MySQL数据库

  • 注册驱动
  • 获取数据库连接对象Connection
  • 定义sql语句
  • 获取sql执行对象
  • 执行sql
  • 处理结果
  • 释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class jdbcdemo1 {
public static void main(String[] args) {
//定义连接、用户名、密码
String url = "jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=GMT%2B8";
String user = "root";
String password = "123456";
// 先定义为null,这样在finally中才可以关闭
Connection conn = null;
Statement statement = null;
try {
//注册驱动
//北京时间东八区 serverTimezone=GMT%2B8
//全球标准时间:serverTimezone=UTC
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("注册驱动成功");
//获取数据库连接对象
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println("数据库连接成功");
//定义sql语句
String sql = "select * from stu";//stu表字段 id(Int) stu_name(String) stu_phone(String)
//获取sql执行对象
Statement statement = conn.createStatement();
//执行sql
ResultSet sql1 = statement.executeQuery(sql);
//处理结果
while (sql1.next()) {
Integer id = sql1.getInt("id");
String stu_name = sql1.getString("stu_name");
String stu_phone = sql1.getString("stu_phone");
System.out.println("id:" + id + " stu_name:" + stu_name + " stu_phone:" + stu_phone);
}
//关闭资源
statement.close();
//关闭数据库连接
conn.close();
} catch (ClassNotFoundException e) {
System.out.println("数据库驱动没有安装");
} catch (SQLException e) {
System.out.println("数据库连接失败");
}finally {
//关闭资源
// 避免空指针,添加判断
if(statement!=null){
try {
statement.close();
System.out.println("sql执行对象已关闭");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//关闭数据库连接
if(conn!=null){
try {
conn.close();
System.out.println("数据库连接已关闭");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}

2.详解各个对象

2.1 DriverManager

  • 驱动管理对象

    1. 注册驱动

      • DriverManager类中有一个静态成员方法:static void registerDriver(Driver driver):注册给定的驱动程序DriverManager

      • Class.forName(“com.mysql.cj.jdbc.Driver”); 这行代码会将com.mysql.cj.jdbc.Driver在源代码阶段加载进内存,自动执行其中包含的静态代码块,其核心就是执行DriverManager.registerDriver(new Driver());注册驱动。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      // com.mysql.cj.jdbc.Driver
      public class Driver extends NonRegisteringDriver implements java.sql.Driver {
      public Driver() throws SQLException {
      }
      // 静态代码块
      static {
      try {
      DriverManager.registerDriver(new Driver());
      } catch (SQLException var1) {
      throw new RuntimeException("Can't register driver!");
      }
      }
      }
      • 在jdbc驱动包下有一个文件java.sql.Driver,里面写入了com.mysql.cj.jdbc.Driver,程序会自动注册驱动,所以不执行Class.forName(“com.mysql.cj.jdbc.Driver”); 也可以。
    2. DriverManager类中有一个获取数据库连接对象的方法:getConnection,是静态方法,可以通过类名直接调用。

      static Connection getConnection(String url,Sptring user,String password);

      • url:指定连接的路径

        jdbc:mysql://ip地址(域名):端口号/数据库名称?&useSSL=false&serverTimezone=GMT%2B8

2.2 Connection

  • 获取执行sql语句的对象

    • Statement createStatement ()
    • PreparedStatement createStatement (String sql)
  • 管理事务

    开启事务:setAutoCommit(boolean autoCommit),设置参数为false,即为提交事务

    提交事务:rollback

    回滚事务:commit

2.3 statement

  • 执行sql的对象

    • boolean execute(String sql)

    • int executeUpdate(String sql):执行DML(insert、update、delete)、DDL(create、drop、alter),返回值为影响的行数

    • ResultSet executeQuery(String sql):执行DQL(select)语句,返回一个结果集对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    public static void main(String[] args) {
    .............
    /*
    * 练习executeUpdate、executeQuery
    * stu表字段 id(Int) stu_name(String) stu_phone(String)
    * 添加一条记录
    * 修改一条记录
    * 删除一条记录
    * 查询表中记录
    * */

    String sql = "insert into stu values(3,'qzy','456')";
    int count = statement.executeUpdate(sql);
    if(count>0){
    System.out.println("添加成功");
    }else{
    System.out.println("添加失败");
    }

    sql = "update stu set stu_phone = '123' where id = 2";
    count = statement.executeUpdate(sql);
    if(count>0){
    System.out.println("修改成功");
    }else{
    System.out.println("修改失败");
    }

    sql = "delete from stu where id = 3";
    count = statement.executeUpdate(sql);
    if(count>0){
    System.out.println("删除成功");
    }else{
    System.out.println("删除失败");
    }
    ..........
    }

2.4 ResultSet

  • 结果集对象,封装查询结果

2.5 PreparedStatement

  • 执行sql的对象
  • execute:能执行CRUD中的任意一种语句。它的返回值是一个boolean类型,表示是否有结果集。有结果集为true,没有结果集为false
  • executeUpdate:只能执行CUD,查询语句无法执行,返回值影响数据库记录的行数
  • executeQuery:只能执行select语句,无法执行增删改,执行结果封装的结果集ResultSet对象