JavaScript 基础语法
一、面向对象编程
1.1 什么是面向对象
JavaScript 、Java、c#、、、、面向对象:JavaScript有区别!
- 类:模板 原型对象
- 对象:具体的实例
在JavaScript中这个需要大家换一下思维
var xiaoming={
name:'xiaoming'
}
var bird={
fly:function () {
console.log(this.name+"fly....");
}
}
//小明的原型是user
xiaoming.__proto__=bird;
Class继承
- Class 关键字,在ES6引入的
- 定义一个类,属性,方法
//定义一个全新得类
class Student{
constructor(name){
this.name=name;
}
hello(){
alert('hello')
}
}
var xiaoming= new Student("xiaoming");
var xiaohong= new Student("xiaohong");
xiaoming.hello()
- 继承
class XiaoStudent extends Student{
constructor(name,grade){
super(name);
this.grade=grade;
}
myGrade(){
alert('我是一名小学生')
}
}
var xiaoming= new Student("xiaoming");
var xiaohong= new XiaoStudent("xiaohong",1);
- 本质:查看对象原型
XiaoStudent {name: "xiaohong", grade: 1}
grade: 1
name: "xiaohong"
__proto__: Student
constructor: class XiaoStudent
myGrade: ƒ myGrade()
__proto__: Object
原型链
proto:
二、 操作BOM对象(重点)
浏览器介绍
- JavaScript和浏览器的关系?
- JavaScript诞生就是为了能够让他在浏览器中运行
BOM:浏览器对象模型
- IE 6-11
- Chrome
- Sarfari
- FireFox Linux
- Opera
三方浏览器
- QQ浏览器
- 360浏览器
window 代表 浏览器窗口
window.innerHeight
360
window.innerWidth
986
window.outerHeight
882
Navigator
- 封装了浏览器信息
window.navigator.appName
"Netscape"
navigator.platform
"Win32"
navigator.userAgent
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36"
- 大多数时候我们不会使用navigator对象,因为会被人修改,不建议使用这些属性来判断和编写代码
screen
//代表屏幕尺寸
screen.width
1536
screen.height
864
location(重要)
location代表当前页面的URL信息
- 主机:host: “www.baidu.com”
- href: “https://www.baidu.com/”
- 协议:protocol: “https:”
- 刷新网页: reload: ƒ reload()
- 设置新的地址:location.assign(‘http://blog.kuangstudy.com/’)
document
- document代表当前的页面,HTML DOM文档树
- 获取具体的文档树结点
<dl id="app">
<dt>Java</dt>
<dd>JavaSE</dd>
<dd>JavaEE</dd>
</dl>
<script>
var dl=document.getElementById('app');
</script>
- 获取cookie
document.cookie
- 劫持cookie原理
<script src="aa.js"></script>
<!-- 恶意人员:获取你的cookie上传到他的服务器-->
- 服务器端可以设置cookie: httpOnly
history(不建议使用)
- history代表浏览器的历史记录
三、操作对象DOM对象(重点)
- DOM:文档对象模型
核心
- 浏览器网页就是一个Dom树形结构
- 更新:更新Dom节点
- 遍历Dom节点:得到Dom节点
- 添加:添加一个Dom节点
- 要操作一个Dom节点。就必须要先获得这个Dom节点
获得Dom节点
var h1=document.getElementsByTagName('h1');
var h1=document.getElementById('p1');
var h1=document.getElementsByClassName('p2');
var father=document.getElementById('father');
var childerns=father.children;//获取父节点下的所有子节点
//father.firstChild;
- 这是原生代码,之后用jQuery
更新节点
<div id="id1">
</div>
<script>
var id1=document.getElementById('id1');
操作文本
- id.innertText='456' 修改文本的值
- id.innerHTML='<strong>123</strong>' 可以解析html
操作css
id1.style.color='red'
"red"
id1.style.fontSize='20px'
"20px"
id1.style.fontSize='200px'
"200px"
删除节点
- 删除节点的步骤
- 先获取父节点,在删除自己
<div id="father">
<h1>标题一</h1>
<p id="p1">p1</p>
<p class="p2">p2</p>
</div>
<script>
var self=document.getElementById('p1');
var father=p1.parentElement;
father.removeChild(self)
</script>
- 注意:删除多个节点的时候,children属性是时刻变化的,删除节点的时候一定要注意
插入节点
- 我们获得了某个节点,假设这个dom节点是空的,我们通过innerHtml就可以增加一个元素了,但这个Dom节点已近存在元素了,我们就不能着呢干!会产生覆盖
追加:
<p id="js">JavaScript</p>
<div id="list">
<p id="se">JavaSE</p>
<p id="ee">JavaSE</p>
<p id="me">JavaME</p>
</div>
<script>
var js= document.getElementById('js');
var list=document.getElementById('list');
list.appendChild(js);
</script>
创建一个新标签
var js= document.getElementById('js');
var list=document.getElementById('list');
//通过js创建一个新的节点
var newP =document.createElement('p');//创建一个p标签
newP.id='newP';
newP.innerText='Hello,zxh';
list.appendChild(newP);
四、操作表单(验证)
表是什么 form DOM树
- 文本框: text
- 下拉框:
- 单选框: radio
- 多选框: checkbox
- 隐藏框: hidden
- 密码框: password
表单的目的:提交信息
<form action="post">
<p>
<span>用户名:</span><input type="text"id="username">
</p>
<p>
<span>性别:</span>
<input type="radio" name="sex" value="man" id="boy">男
<input type="radio" name="sex" value="woman" id="girl">女
</p>
</form>
<script>
var input_text= document.getElementById('username');
var boy_radio= document.getElementById('boy');
var girl_radio= document.getElementById('girl');
//对于单选框,多选框等等固定的值,boy_radio.value只能收到当前的值
//girl_radio.checked;查看返回值的结果,是否为true,如果为true,则被选中
//girl_radio.checked=true;赋值
//得到输入框的代码
//修改输入框代码
input_text='123'
</script>
提交表单 MD5加密 及代码优化
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
</head>
<body>
<!--表单绑定提交事件
onsubmit=绑定的一个提交函数,true false
将这个结果返回给表单,使用onsubmit接收!
onsubmit="return aaa{}-->
<form action="https://hao.360.com" method="post" onsubmit="return aaa()">
<p>
<span>用户名:</span><input type="text" id="username" name="username">
</p>
<p>
<span>密码:</span><input type="password" id="input-password">
</p>
<input type="hidden" id="md5-password" name="password">
<!--绑定一些事件-->
<button type="submit" >提交</button>
</form>
<script>
function aaa() {
alert(1);
var uname=document.getElementById('username');
var pwd=document.getElementById('input-password');
var md5pwd=document.getElementById('md5-password');
/* console.log(uname.value);
console.log(pwd.value);
//MDS算法
pwd.value=md5(pwd.value);
console.log(pwd.value);*/
md5pwd.value=md5(pwd.value);
//可以校验判断表单内容,true就是通过验证,false:阻止提交
return true;
}
五、jQuery
- JavaScript
- jQuery 库,里面存在着大量的JavaScript函数
获取jQuery
<script src="jquery-3.2.1.js"></script>
选择器
<script>
//原生的js,选择器少,麻烦不好记
//标签
document.getElementsByTagName();
//id
document.getElementById();
//类
document.getElementsByClassName();
//jQuery
$('p').click();//标签选择器
$('#id1').click();//id选择器or
$('.class').click();//类选择器
</script>
事件
操作DOM
- 节点文本操作
$('#test-ul li[name=python]').text();//获得值
"python"
$('#test-ul li[name=python]').text('12323');//设置值
jQuery.fn.init [li, prevObject: jQuery.fn.init(1)]
- css 操作
$('#test-ul li[name=python]').css("color","red");
- 元素的显示和隐藏
- $(’#test-ul li[name=python]’).hide();
Ajax
数据库
一、数据库介绍
数据库是按照一定的数据结构来组织、存储管理数据的仓库
数据库的发展史
- 从早期的数据库到数据库管理系统DBMS的应运而生
数据库管理系统DBMS:
- 是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,简称DBMS
- 它是数据库进行统一的管理机制,以保证数据库的安全和完整性
- 数据库管理系统是数据库系统的核心,是管理数据库的软件
- 我们一般说的数据库就是指数据库管理系统
常见的数据库
- Oracle
- DB2
- MySQL
- SQL Server
二、专业术语
- 表:具有固定的列数和任意行数
- 列:一个数据项的字段
- 行:一条记录
- 数据库:一些关联表得集合
- 主键:主键是唯一的,一个数据表中只能包含一个主键,你可以使用主键来查询数据
- 外键:用于关联两各表
- 索引:
三、关系型数据库
MySQL是一个关系型数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有的数据放在大仓库中,这样就增加了速度并提高了灵活性
- MySQL可以
- 端口号:3306
字符集
- ASSCLL码:一套文字符号及其编码比较规则的集合。美国标准化组织ANSI发布了第一个字符集,ASSCLL,后来进一步成了国际化标准。
- unicode:为了统一字符编码,国际化标准组织制定,后来被IOS收编
- utf-16:任何字符对应的数字都用两个字节来保存,但很显然如果都用两个字节来表示会浪费资源。
- utf-8:用utf-8表示时一个字符是可变的,有可能用一个字节来表示一个字符,也可以是两三个,根据字符对应的数字大小来确定
-汉字的一些常用字符集:GBK、GB2312
MySQL存储引擎
- 什么是存储引擎:
- MySQL中的数据用各种不同的技术存储在文件(或内存)中,这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得意外的熟读或者功能,从而改变应用的整体功能。
- 不同的存储引擎性能是不一样的
- 存储引擎分类:
-
- MYISAM:它不支持事物,也不支持外键,尤其是访问速度快,对事物完整性没有要求或者以select、insert、为主的应用基本都可以使用这个引擎创建。在磁盘上存在三个文件,其中文件名和表明都相同,但扩展名分别为(.frm(存储定义)、.MYD(MYData,存储数据)、MY(MYINDEX,存储索引))
-
- INNODB:innoDB存储引擎提供了具有提交、回滚、和崩溃恢复能力的事务安全,但是对比MYSAM的存储引擎,innoDB的写入效率差一些并且会占用更多的磁盘空间以保留数据和索引
-
- MEMORY:memory使用内存中的内容来创建表,每个MEMORY表实际对应一个磁盘文件,格式是.frm;MEMORY类型的表访问非常快,因为它到数据是放在内存中的,但一旦服务器关闭,表中数据就会丢失,但表还会继续存在。
什么是SQL?
- SQL是Structured Query Lanuage(结构化查询语言)的缩写。
- SQL是专门为数据库而建立的操作命令集,是一种功能齐全的数据库语言。
- 在使用他时,只需要发出操作命令即可
SQL的功能分类:
- DDL:数据定义语言—用来定义数据库对象:创建库、表、列等
- DML:数据操作语言—用来操作数据库中的记录
- DQL:数据查询语言—用来查询数据
- DCL:数据控制语言—用来定义访问权限和安全级别
SQL数据类型
- MySQL支持所有标准SQL数值的数据类型
- MySQL支持多种类型,大致可以分为三类:
-
- 数值类型
-
- 字符串类型
-
- 日期和时间类型
- 常用的数据类型:
-
- double:浮点型,例如double(5,2)表示最多5为,其中必须有两位小数,即最大值为999.99
-
- char:固定长度字符串类型:char(10) 'abc ’
-
- varchar:可变字符串类型:varchar(10)‘abc’
-
- text:字符串类型
-
- blob:二进制类型
-
- date:日期类型:格式为:yyy-MM-dd;
-
- time:时间类型,格式为:hh:mm:ss
-
- datetime:日期时间类型:yyy-MM-dd hh:mm:ss
- 在mysql中字符串类型和日期类型都需要用单引号引起来
四、数据库操作
DDL
- 创建数据库
create database 数据库名 charcter set utf8;
- 修改数据库
alert database 数据库名 character set gbk;
- 创建学生表
CREATE TABLE student(
id bigint,
stu_name varchar(50),
stu_age int
);
- 添加一列
ALTER TABLE 表名 ADD 列名 数据库类型
- 修改一个表的字段类型
alter TABLE student modify stu_name varchar(30);
- 修改表名:
rename table student to newstu;
- 修改表的字符集为gbk:
alert table 表名 character set 字符集名称
- 修改表的列名:
alert table 表名 change 原始列名 新列名 数据类型
alter table student change stu_name s_name varchar(30);
- 查看表的字段信息:
DESC 表名;
- 删除一列
alter table student drop stu_gender;
- 查看表的创建细节
show create table 表名
- 删除表
drop table 表名
DML
- 查询表中所有数据—Select * from 表名
-DML是对表中的数据进行增删改查的操作 - 插入操作
- INSERT INTO 表名(列名1,列名2…) VALUE (列值1,列值2)
insert into student (id,stu_name,stu_age) value(3,'wangwu',22); insert into student value (6 ,'lx',10);
- 注意事项:
- 列名与列值得类型个数,顺序等要一致
- 值不要超出列定义得长度
- 插入的日期和字符一样,都使用引号括起来
- 批量插入:
insert into student (id,stu_name,stu_age) values(4,'wangwu',22),(5,'zxh',23);
- 更新操作
- UPDATE 表名 SET 列名1==值列值1,列名2=列值2… where 列名
- 把所有学生的成绩改为90;
- update student set stu_score =90;
- 把zhangsan的成绩改为60;
- UPDATE student set stu_score =60 where stu_name=‘zhangsan’;
- 把姓名为lisi的年龄改为20分数改为70
- update student set stu_age=20 ,stu_score=70 where stu_name =‘lisi’;
- 把zxh年龄在原来基础上加1岁
- update student set stu_age=stu_age+1 where stu_name=‘zxh’;
- 修改是数据库密码
- mysql8
-ALERT USER ‘root’@'localhost’IDENTIFIED BY ‘123456’;
- mysql8
- 删除操作
- DELETE FROM 表名{where 列名=值}
- delete from student where id=6;
- TRUNCATE TABLE 表名;
- truncate table student;//删除多有数据 不能删除指定数据
- DELETE与TRUNCATE的区别:
- delete删除表中的数据,表结构还在;
- truncate 删除是把表直接Drop掉,然后再创建一个同样的新表,执行速度比delete快
DQL
- 查询所有列:select *from 表名
- 结果集:
- 数据库执行DQL语句不会对数据进行改变,而是让数据库发送结果集给客户端。
- 查询返回的是一张虚拟的结果表。
- 虚拟结果集存放在内存中
- 查询指定的列
- select stu_name,stu_age from student;
- 条件查询
- 条件查询就是时给出where 子句,在where子句中可以使用一些运算符及关键字;
- 条件查询运行符及关键字:
- = > < != <>(不等于)
- BETWEEN …AND :值在什么范围:
- IN(set):查询固定范围内的值
- IS null:(为空) is notNull(不为空) 等查询
- and :与
- or:或
- NOT:非
- 使用:
- 查询性别为男,并且年龄为20的学生记录
- SELECT *from student where stu_gender=‘男’ and stu_age=20;
- 查询序号为3或4名为 wangwu的记录
- SELECT *from student where id=3 or stu_name=‘wangwu’;
- 查询编号为 1、2、3的记录
- SELECT *from student where id=3 or id=1 or id=2;
- SELECT *from student where id in(1,2,3,4);
- 查询表中年龄为空的记录
- SELECT *from student where stu_name is null;
- 查询性别为非男的记录
- SELECT *from student where stu_gender !=‘男’;
- 查询性别不为null的学生记录
- SELECT *from student where stu_gender is not null;
- 年龄在21到23 的记录
- SELECT *from student where stu_age >=20 and stu_age<=23;
- SELECT *from student where stu_age between 20 and 23 ;
- 查询性别为男,并且年龄为20的学生记录
- 模糊查询:
- 根据指定的关键字查询
- 使用link关键字后的通配符
- 通配符
- _:任意一个字符
- %:任意0-n个字符
- 使用
- 查询姓名由三个字母构成的记录
- select stu_name from student where stu_name like ‘___’;
- 查询姓名由3个字母组成,并且第三个字母为‘h’的记录
- select stu_name from student where stu_name like ‘__h’;
- 查询以‘z’开头的记录
- select * from student where stu_name like ‘z%’;
- 查询姓名中第二个字母为’a’的记录
- select * from student where stu_name like ‘_a%’;
- 查询姓名中包含‘s’的记录
- select * from student where stu_name like ‘%s%’;
- select * from student where stu_name like ‘%张%’;
- 字段控制查询
- 去除重复记录
- select DISTINCT stu_name from student;
- 把查询字段的结果进行运算,必须是数据型
- select *,stu_age+stu_score from student;
- 年龄和分数为null时把他们变为0 相加
- select *,IFNULL(stu_age,0)+ IFNULL(stu_score,0) from student;
- 对查询结果起别名
- select *,IFNULL(stu_age,0)+ IFNULL(stu_score,0) as total from student;
- 去除重复记录
- 排序
- 使用关键字升序 (默认)
- SELECT *from student order by stu_score asc;
- 降序:
SELECT *from student order by stu_score desc; - 一个条件相同时 选取另一个条件
SELECT *from student order by stu_score desc,stu_age desc;
- 使用关键字升序 (默认)
- 聚合函数
- 对查询结果进行统计运算
- 常用的聚合函数
- COUNT():统计指定列不为空的记录行数
- SELECT COUNT(*) from student; 为空着不同记
- MAX():计算指定列最大值,如果是字符串类型,则使用字符串排序运算;
- MIN():计算指定最小值,如果是字符串类型,则使用字符串排序运算;
- SUM():计算指定列数值和,如果指定类型不是数值类型,那么结果计算为0 ;
- AVG():计算指定列平均值,如果指定类型不是数值类型,那么结果计算为0
- COUNT():统计指定列不为空的记录行数
- 使用
- 统计不为空的列数
- SELECT COUNT(stu_score) from student;
- 统计成绩大于60的
- SELECT COUNT(*)from student where stu_score>60;
- 统计年龄和分数和大于110的记录
- SELECT COUNT(*)from student where IFNULL(stu_score,0)+IFNULL(stu_age,0)>110;
- 同时统计有分数和年龄的人数
- SELECT COUNT(stu_age),COUNT(stu_score)from student ;
- 查询所有人成绩的总和
- SELECT SUM(stu_score) from student ;
- 查询成绩和分数的和
- SELECT SUM(stu_score+stu_age) from student ;
- 平均值
- SELECT AVG(stu_age) from student ;
- 最大值 最小值:
- SELECT max(stu_age),MIN(stu_age) from student ;
- 统计不为空的列数
SQL进阶部分1
- 分组查询
- 将查询的结果按照一个或多个字段进行分组,字段相同的为一组
- 分组使用:
- SELECT * from student GROUP BY stu_gender;
- 根据gender字段来分组,gnder字段的全部值只有两个(男和女)所以分为了两组,当groupby单独使用时,只能显示出每组的第一条记录,所以group by 实际意义不大
- 分组事项:在使用分组时,select后面直接跟字段以般都出现在group by 后
- SELECT stu_name,stu_gender from student GROUP BY stu_gender,stu_name ;
- group by + group_concat():
- group_concat(字段名)可以作为一个输出字段
- 表示分组之后,根据分组结果,使用group_concat()来放置一组某字段的值的集合
- SELECT stu_gender,GROUP_CONCAT(stu_name) from student GROUP BY stu_gender;
- 分组聚合函数
- SELECT stu_gender,GROUP_CONCAT(stu_score) ,SUM(stu_score)from student GROUP BY stu_gender;
- group+having:
- 用来分组查询后指定一些条件输出查询结果
- having作用和where一样,但having只能用于group by
- SELECT stu_gender,GROUP_CONCAT(stu_score),SUM(stu_score) from student GROUP BY stu_gender HAVING SUM(stu_score)>160;
- having和where的区别:
- having在分组后对数据进行过滤
- where是在分组前对数据进行过滤
- having后面可以使用分组函数
- where后面不可以使用
- where是对分组前记录的条件进行条件约束,如果某行记录没有满足where子句条件,那么这行记录不会参加分组,而having是对分组的数据约束
- 查询分数大于70的,分数综合大于160的学生的性别以及分数和。
- SELECT stu_gender ,GROUP_CONCAT(stu_score),SUM(stu_score),COUNT(*)from student where stu_score >=70 GROUP BY stu_gender HAVING SUM(stu_score)>160;
- 分页查询 LIMIT
- 从哪一行开始查,总共查几行
- limit 参数1,参数2 :
- 参数1:从哪行开始
- 参数2:一共查几行
- 角标是从0开始
- 格式:select * from student LIMIT 0,3 ;
- 分页思路:
- int curPage=1;—当前页
- int pageSize=3;—每页多少条数据
- 当前页为1 第一页从0开始 (1-1)*3=0;
- 当前页为2 第二页从3开始 (2-1)*3=3
- 当前页为3 第三页从6开始 (3-1)*3=6
- select * from student limit (curPage-1)*pageSize,pageSize
- 数据完整性:
- 保证用户输入的数据保存到数据库中是正确的。
- 在创建表的时候给表中数据添加约束
- 完整性分类
- 实体完整性:
- 什么是实体完整性:表中的一行(一条记录)代表一个实体(entity)
- 实体完整性的作用:标识每一行数据不重复,行级约束
- 约束类型:
- 主键约束:
- 特点:
- 每个表中要有一个主键
- 数据唯一,且不能为null
- 添加方式:
- CREATE TABLE person (ID BIGINT PRIMARY KEY, NAME VARCHAR(50));
- CREATE TABLE person (ID BIGINT , NAME VARCHAR(50),PRIMARY KEY(ID));
- 联合主键:两个字段数据同时相同,才违反联合主键约束
- CREATE TABLE stu (ID BIGINT , snum BIGINT, sname VARCHAR(50),PRIMARY KEY(ID,snum));
- 添加主键约束:
- ALTER TABLE student ADD CONSTRAINT PRIMARY KEY(id);
- 特点:
- 唯一约束:
- 特点:指定列的数据不能重复,但可以为空值
- 格式:CREATE TABLE stu (id int PRIMARY KEY,name VARCHAR(50) UNIQUE);
- 自动增长列:
- 特点:指定列的数据自动增长,即使数据删除,还是从删除的数据继续往下
- 格式:
- CREATE TABLE stu (
id int PRIMARY KEY auto_increament,
name VARCHAR(20) UNIQUE
);
- 主键约束:
- 域完整性:
- 使用:
- 限制此单元格的数据正确,不对照此列的其他单元格比较
- 域代表当前单元格
- 域完整性约束:
- 数据类型:数值类型、日期类型、字符串类型
- 非空约束:(not null)
- 默认值约束:(default)
- gender CHAR(1) DEFAULT ‘男’
- 使用:
- 参照完整性:
- 定义:
- 表与表之间一一对应关系
- 通常情况下可以通过设置两表的主键、外键关系或者编写两表的触发器来实现
- 有对应参照完整性的两张表格,在对他们进行数据插入、更新、删除的过程中系统都会将被修改的表格与另一张表格进行对照,从而阻止一些不正确的数据的操作
- 数据库的主键和外键的类型一定要一致
- 两个表必须是InnoDB操作引擎
- 完整性的添加:
- CONSTRAINT sc_st_fk FOREIGN KEY (sid) REFERENCES stu1(id)
- 定义:
- 实体完整性:
SQL进阶2
- 表之间的关系:
- 一对一
- 一对多
- 多对多
- 一个老师有多个学生,一个学生也可以有多个老师
- 创建老师表
- 创建学生表
- 创建学生与老师关系表
- 添加外键
CREATE TABLE teacher( tid int PRIMARY KEY ,name VARCHAR(50) ); CREATE TABLE stu( sid int PRIMARY KEY,name VARCHAR(50) ); CREATE TABLE tea_stu_rel( tid int,sid int ) ALTER TABLE tea_stu_rel ADD CONSTRAINT FOREIGN KEY(tid) REFERENCES teacher (tid); ALTER TABLE tea_stu_rel ADD CONSTRAINT FOREIGN KEY(sid) REFERENCES stu(sid);
- 拆分表:
- 避免大量冗余信息
- 多表查询:
- 合并结果集
- 合并结果集就是把两个select语句的查询结果语句合并到一起
- 合并结果集的两种方式:
- union:合并时结果去除重复记录
SELECT * FROM A UNION SELECT * FROM B; - union all:合并时不去除重复记录
SELECT * FROM A UNION all SELECT * FROM B;
- union:合并时结果去除重复记录
- 格式:
- 示列:
- 注意:别合并的表列数和列类型必须相同
- 连接查询
- 也可以叫跨表查询,需要关联多个进行查询
- 笛卡尔集:
- 假设A={a,b} B={0,1,2}
- 则集合的笛卡尔集为(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)
- 同时查询两个表,出现的就是笛卡尔集的结果
- 查询时起别名:
- 多表联查,如何保证数据正确:
- 在查询时要把主键和外键保持一致 SELECT * FROM stu ,score where stu.sid=score.sid;
- 主表当中的数据参照子表当中的数据
- 原理:
- 根据连接方式分类:
- 内连接
- 等值连接:两个表同时出现的id值才显示
- SELECT * FROM stu st INNER JOIN score sc ON where st.sid = sc.sid;
- 与多表连接约束主外键一样,只是写法改变了
- 如果有条件直接在后面加where
- 多表连接:
- 建立学生,分数,科目表
- SELECT st.
name
,sc.score,c.NAME
FROM stu1 st,score sc,course c where st.id=sc.sid and sc.cid=c.cid;
- 非等值连接
- 后面条件不一定必须时=是等于号,只要满座条件即可
- 等值连接:两个表同时出现的id值才显示
- 外连接:
- 左连接:把左边的数据全部查出来,右边只查满足条件的数据
-SELECT * FROM stu1 st LEFT JOIN score sc ON where st.id = sc.sid; - 右连接:
- SELECT * FROM stu1 st RIGHT JOIN score sc ON where st.id = sc.sid;
- 左连接:把左边的数据全部查出来,右边只查满足条件的数据
- 自然连接:
- 连接查询时会产生笛卡尔集,我们通常使用主外键来去去除它,而自然连接无需你去给出主外键等式,他会自动找到这一等式,也就是说不用写条件
- 条件:
- 两张连接的表中的列名称和类型完全一致时才会去除相同的列。
- 内连接
- 子查询:
- 一个select语句中包含另一个完整的select语句 或两个以上Select语句就是子查询语句了
- 子查询出现的位置:
- where后,把select查询处的结果当作另一个select的条件值
- 查询与1号同学选择同一课程的同学:
SELECT sid ,cid FROM score WHERE cid=(SELECT cid FROM score WHERE sid='1');
- from后:把查询出的结果当作一个新表
- 查询选2号课程成绩大于80的学生
SELECT sid ,cid, score FROM (SELECT sid, cid ,score FROM score where cid='2') s WHERE s.score>80;
- where后,把select查询处的结果当作另一个select的条件值
- 示列表:
- 使用:
- 多表查询
- – 多表查询 查询员工编号为2的学生的选修课程以及成绩
SELECT * FROM stu1 s,score c,course o WHERE s.id=c.sid AND o.cid=c.cid AND s.id=2;
- – 多表查询 查询员工编号为2的学生的选修课程以及成绩
- 自连接:
- 自己连接自己 ,起别名
- 合并结果集
SQL进阶部分3
-
常用函数:
- 有对象调用的称为方法
- 没有对象调用的称为函数
- 函数介绍:
- 事先提供好的一些功能可以直接使用
- 函数可以用在select语句及其子句
- 也可以用在UPDATE ,DELEETE语句当中
- 函数分类:
- 字符串函数:
- concat(s1,s2,…sn):将传入的字符连接成一个字符串,任何字符串与null连接的结果都是null SELECT CONCAT(‘aaa’,‘bbb’,null);
- insert(strert,3,2,‘ee’):把字符串从第三个位置开始,2个字符长的字符串替换为指定字符SELECT INSERT(‘aaa’,2,1,‘b’);
- LOWER(Str)和UPPER(Str):将字符转成大写或小写
- LEFT(Str,x)和RIGHT(Str,x):分别返回字符串最左边的x个字符和最右边的x个字符
- LPAD(Str,n,pad)和RPAD(Str,n,pad):用字符串pad对Str最左边和最右边进行填充,直接到长度为n个字符长度 SELECT LPAD(‘my’,6,1234);
- LTRIM(Str)和RTRIM(str):去掉字符串当中最左侧和最右侧的空格
- TRIM(Str):去掉字符串左右的空格
- REPEAT(Str,x):返回str重复x次的结果
- REPLACE(str,a,b):用字符串b替换str中所有出现的字符串a --SELECT REPLACE( ‘abcdefg’,‘c’,’**’);
- SUBSTRING(str,x,y):截取字符串,从x位置起截取到y位置的字符串
- 数值函数
- ABS(X) :返回x的绝对值
- CEIL(X):小数不为0部分上取整,即向上取最近整数 SELECT CEIL(2.3);
- FLOOR(X):小数向下取,也就是舍弃小数部分
- MOD(X,Y):返回X/Y的模(余数)
- RAND():返回0-1内容的随机值 SELECT FLOOR(RAND()*10) ;
- 日期和时间函数
- CURDATE():返回当前日期,只包含年月日
- CURETIME():返回当前时间,只含时分秒
- NOW():包含当前时间 年月日 时分秒
- UNIX_TIMESTAMP():返回当前日期的时间戳
- FROM_UNIXTIME(UNIXTIME):将以一个时间戳转换为日期
- WEEK(DATE):返回当前第几周
- YEAR(DATE):返回当前日期是那年
- HOUR(TIME):返回当前时间的小时
- MINUTE(TIME):返回当前时间的分钟
- DATE_FORMAT(date,fmt):对日期进行格式化
- DATE_ADD(date,interval expr type):计算日期
- DATEDIFF(date1,date2):date1到date2隔了多少天
- 流程函数
- IF(VALUE,t,f):如果value是真,返回t否则返回f
- IFNULL(VALUE1,VALUE2):如果value不为空,返回value1值否则返回2
- CASE WHEN THEN END:
- 其它函数
- DATABASE():返回当前数据库名
- VERSION():返回数据库版本
- USER():返回当前登录用户名
- PASSWORD(STR):对str进行加密
- MD5():返回str的MD5值
- 字符串函数:
-
事务:
- 概念:
- 1、可分割的操作,假设该操作有ABCD四个步骤组成:若ABCD四个步骤都成功完成,则认为事务成功,若四个步骤其中任何一个失败,则认为事物失败
- 2、每条sql语句都是一个事物
- 3、事务只对DMl操作有效,对DQL无效
- 事务的ACID:
- 原子性(Atomicity):原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚
- 一致性(Consistency):让数据保证一定的合理性,一个商品出库时,对应用户的购物车中的商品加1
- 隔离性(lsolation):
- 持久性(Durability):
- 事务的使用:
- 开启事务: start transaction:
- 回滚事务:rollback: 回到事务开始前
- 提交事务:commit: 所有事务全部执行完毕,没有发生异常,提交事务,更新到数据库当中
- 事务的并发问题:
- 脏读:用户看到的结果和真实达到的数据不同,后台管理者再提交事务时数据进行回滚。
- 解决办法:Read committed! 读提交,能解决脏读问题。
- 不可重复读:一个事务范围内两个相同的查询却返回了不同数据,这就时不可重复读
- 重复读:事务开启时不允许其他事务执行修改操作
- 幻读:
- 对应关系:
- 脏读:用户看到的结果和真实达到的数据不同,后台管理者再提交事务时数据进行回滚。
- 事务隔离级别:
- Read uncommitted:就是一个事务可以读数据另一个未提交事务的数据
- Read committed:一个事务要等另一个事务提交后才能读取数据
- Repeatable read:重复读
- Serializable:
- 概念:
-
权限操作:
- 限制一个用户能够作什么事情,再MySQL中,可以设置全局权限,指定数据库权限,指定表权限,指定字段权限
- 创建用户:CREATE user ‘zxh’@‘localhost’ IDENTIFIED by ‘123456’;
- 删除用户:drop user ‘zxh’
- 分配权限:
- 给自己创建的用户分配管理员权限:GRANT ALL PRIVILEGES on . TO zxh@localhost
IDENTIFIED by ‘123456’
with GRANT OPTION;
- 给自己创建的用户分配管理员权限:GRANT ALL PRIVILEGES on . TO zxh@localhost
- 查看权限:show grants;
-
索引:
- 概念:
- 索引用于快速找出在某个列中有一特定的行
- 不使用索引,MySQL必须从第一条记录开始扫扫描整个表,直到找出相关行
- 表越大,查询数据花费的时间就越多
- 如果表查询的列中有一个索引,MySQL能够快速到达一个位置去搜素文件,而不必查看所有的数据省下了很多时间。
- 索引的优势与劣势:
- 优势:
- 提高了检索效率,降低了数据库的io成本
- 通过索引对数据进行排序,降低数据排序的成本,降低了CPU的消耗的消耗
- 劣势:
- 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表记录,所以索引也是要占空间的
- 虽然索引大大提高了查询速度,同时却会降低更新表得速度。
- 索引的分类
- 胆单值索引
- 唯一索引
- 复合索引
- 全文索引
- 空间索引
- 索引操作:
- 创建索引:create index 索引名称 on table
- 删除索引:drop index 索引名称 on 表名
- 查看索引:show index from 表名
- 自动创建索引:
- 在表上定义了一个主键时,会自动创建一个对应的索引
- 在表上定义一个外键时,会自动创建一个普通索引
- 解析查询语句:
- explain select * from emp where id=101\G;
- 索引结构
- btree索引: B+树
- hash索引:一次性到位,经过算法算出位置
- 索引的创建和选择:
- 创建索引:
- 主键自动建立唯一索引
- 频繁作为查询条件的字段作为索引
- 查询中与其他表关联二得字段,外键关系建立索引
- 提高查询速率
- 不需要创建索引:
- 表太少
- 经常进行增删改
- 创建索引:
- 优势:
- 概念:
-
视图:
- 概念:
- 视图就是一个虚拟表,其内容由查询定义
- 同真实表一样,视图包含一系列带有名称的行和列数据。
- 行和列数据来自定义视图的查询所引起的表,并且在引用视图时动态生成
- 简单的说视图由select结果组成
- 视图的特性:
- 视图是对若干张基本表的引用,一张虚表,查询语句执行的结果,
- 不存储具体数据(基本表数据发生了改变,视图也会跟着改变)
- 可以跟基本表一样,进行增删改操作有条件的权限
- 视图的作用:
- 安全性:创建一个视图,定义好该视图所操作数据,之后将用户权限与视图绑定
,这样的方式使用到了一个特性:grant 语句可以针对视图进行授予权限 - 查询性提高
- 提高了数据的独立性
- 安全性:创建一个视图,定义好该视图所操作数据,之后将用户权限与视图绑定
- 视图创建、修改、删除
- CREATE VIEW stu_score_view AS (SELECT * FROM score where score>47);
- 视图机制:
- 替换式:操作试图时,视图名直接被视图定义给替换掉
- 具化式:mysql先得到了视图执行结果,该结果形成一个中间结果暂时存在内存中,外面的select语句就调用了这个中间结果。(临时表)
- 两者区别:
- 替换式:将视图公式替换后,当成一个整体sql进行处理了
- 具体化方式:先处理视图结果,后处理外面的查询需求
- 视图不可更新部分:
- 只要视图当中的数据不来源于基表,是不能直接修改的
- 概念:
-
存储过程:
- 定义
- 一组编程语言, 是为了完成特定的mysql语句集
- 存储过程就是具有名字的一断代码,用来完成一个特定的功能
- 创建存储过程保存在数据库的数据字典中,
- 为什么要有存储过程?
- 将重复性很高的一些操作,封装到一个过程中,简化了对这些SQL的调用
- 批量处理
- 统一接口,确保数据安全
- 相对于oracle数据库来说,MySQL的存储过程使用较少
- 存储过程的创建和调用
- delimiter
:
它
与
存
储
过
程
语
法
无
关
,
d
e
l
i
m
i
t
e
r
语
句
标
准
分
割
符
−
−
分
号
改
为
: 它与存储过程语法无关,delimiter语句标准分割符--分号改为
:它与存储过程语法无关,delimiter语句标准分割符−−分号改为,
因为我们想将存储过程作为整体传递给服务器
delimiter $$ CREATE PROCEDURE show_stu1() BEGIN SELECT * FROM stu1; END$$ delimiter ; CALL show_stu1();
- 查看存储过程:
show PROCEDURE STATUS WHERE db=‘zxh’; - 删除:
drop procedure show_stu1;
- delimiter
:
它
与
存
储
过
程
语
法
无
关
,
d
e
l
i
m
i
t
e
r
语
句
标
准
分
割
符
−
−
分
号
改
为
: 它与存储过程语法无关,delimiter语句标准分割符--分号改为
:它与存储过程语法无关,delimiter语句标准分割符−−分号改为,
- 定义
-
自定义函数
随机生成一个指定个数字符串 delimiter $$ CREATE FUNCTION rand_str(n int ) returns VARCHAR(255) BEGIN -- -声明一个str 个字母 DECLARE str VARCHAR (100) DEFAULT 'abcdefghijklmnopqrstuvwxyz'; -- 记录当前是第几个 DECLARE i int DEFAULT 0; -- 生成结果 declare res_str VARCHAR(255) DEFAULT ''; while i<n do -- 随机生成一个指定个数字符串 -- 1+RAND()*26 FLOOR(1+RAND()*26) -- substr(str,FLOOR(1+RAND()*26,1); -- 拼接字符串 set res_str=CONCAT(res_str,substr(str,floor(1+RAND()*26),1)); set i=i+1; end while; return res_str; END$$ delimiter ; SELECT rand_str(5);
JDBC
一、JDBC概述
- 什么时JDBC?
- 是一种用于执行SQL语句的JAVA API
- 它由Java语言编写的类和接口组成
- JDBC提供了一种操作数据标准
- JDBC的目标是使Java程序员使用JDBC可以连接任何提供JDBC驱动程序的数据库系统
- 通过驱动连接
- JAVA程序 通过JDBC(包含了数据库操作规范、类、接口、方法自己并没有提供实现) 连接数据库
- jdbc的API
- Java.sql 包装的就是API
- 各大数据库厂商就会对JDBC的API提供实现类 驱动包
- 注意不要引错包,不用引用这个com.mysql.xxx l类
二、连接MySQL
- 添加驱动:
- 导入jar包
- build pash
- 创建连接
- 1、加载驱动
// 把com.mysql.jdbc.Driver这份字节码加载进JVM // 当一份字节码被 加载进JVM时,就会执行该字节码中的静态代码块 Class.forName("com.mysql.jdbc.Driver");
- 2、获取连接对象
// 2、获取连接对象 //url 数据库地址 String url="jdbc:mysql://localhost:3306/zxh"; //user 用户名 String user="root"; // password: 密码 String password ="123456"; Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn);
- 1、加载驱动
- 操作MySQL创建表
- 创建要执行行的Sql语句:
- Statement接口:用来执行SQL语句对象
- 把SQL语句发送到数据库中去执行,并返回执行结果
- 对于DQl返回查询结果集
- 对于DML返回受影响的行数
- 对于DDL返回0
- executeUpdate(String):执行DDL、和DML
- 执行SQL
- 释放数据资源
- 为什么释放资源:
- connection 连接就相当于Java和到mysql之间建立管道
- 连接只连接到数据,Statement就相当于从数据库又接了一个管道连接MySQL的执行程序
- 把管道撤掉
- 为什么释放资源:
- 实例
// 1、加载驱动 // 把com.mysql.jdbc.Driver这份字节码加载进JVM // 当一份字节码被 加载进JVM时,就会执行该字节码中的静态代码块 Class.forName("com.mysql.jdbc.Driver"); // 2、获取连接对象 // url 数据库地址 String url = "jdbc:mysql://localhost:3306/zxh"; // user 用户名 String user = "root"; // password: 密码 String password = "123456"; Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); //3、编写SQl语句 String sql="create table student(id int,name varchar(50),age int)"; //创建接口 获取连接对象 Statement st=conn.createStatement(); //4、执行sql int row=st.executeUpdate(sql); //5、释放资源 st.close(); conn.close();
- 创建要执行行的Sql语句:
- 异常处理
三、执行DML操作
- 执行DML操作和DDL操作是一样,只是sql语句发生了变换
四、查询操作DQL
- 结果集:ResubltSet:表示数据库查询的结果的集合,在查询语句时就会得到这样一个结果
- 常用方法:
- boolean next():是否有下一行数据
- 执行sql:
String url = "jdbc:mysql://localhost:3306/zxh"; String user = "root"; String password = "123456"; // 1、加载驱动 Class.forName("com.mysql.jdbc.Driver"); // 2、数据库连接 Connection conn = DriverManager.getConnection(url, user, password); // 3、编写sql String sql = "SELECT COUNT(*) FROM emp"; // 创建连接接口 Statement st = conn.createStatement(); // 4、执行sql 得到一个结果集 ResultSet res = st.executeQuery(sql); // 取出列一个数据 if (res.next()) { // int count = res.getInt(1); int count = res.getInt("COUNT(*)"); System.out.println(count); } // 5、释放资源断开连接 st.close(); conn.close();
五、DAO设计
- 没有DAO时存在的问题:
- 多个地方都要同时做CRUD操作时,重复代码会很多
- 什么是DAO
- Data Access Object (数据存储对象)
- 位于业务逻辑层(test层)和持久层(数据库)之间
- 实现对数据持久化的访问
- ORM
- ORM-- 对象关系映射
- 将关系型数据库中的记录映射成为对象,以对象的形式展现
- 因此ORM的目的是为了方便开发人员以面向对象的思想来实现数据库的操作
- 对应关系:
- 类—》表
- 对象—》一行记录
- 属性—》字段
- 示意图:
- ORM-- 对象关系映射
- domain
- 什么是domain
- 就是一个类,符合JavaBeand的规范,一个类当中有字段和该字段的setter和getter方法
- 作用:用户与数据库的核心中转站
- 示例
- 创建一个domain类
- 先创建一个domain中转
- 保存数据
- 获取数据
- 创建一个domain类
- 什么是domain
- DAO设计规范
- 编写DAO组件
- 1、定义dao接口
- 2、编写dao实现类
- 定义接口的原因
- 接口只给函数声明,但是没有函数体类,函数体在实现类中给出
- 面向接口编程:
- 根据客户提出的需求,定义接口,业务具体实现通过实现类完成
- 当客户提出新的需求时,只需要编写业务逻辑的实现类
- 好处:
- 业务逻辑更加清晰
- 增强代码的扩展性,可维护性
- 接口和实现组分类,适合团队协作开发
- 降低耦合度,便于以后升级扩展
- 举例:
- 包名的规范:
- 整体规范:域名倒写.模块名称.组件名称
- DAO包名规范:
- domain包:存储所有的domain
- dao包:存储所有的dao接口
- dao.impl:存储的所有Dao接口的实现类
- test包:存储测试类
- 类名规范:
- domain类:存在domain包中,用于描述一个对象,是一个JavaBean,写时要见名知意
- dao接口:存储在dao包中,用于表示某一个对象的CRUD声明 起名规范:iDomainimpl包中 - 接口.domain.dao
- dao实现类:存储在dao.impl包中,用于表示DAO接口的实现类,要实现DAO接口 - DomainDAOimpl
- 编写DAO组件
- DAO开发步骤
- 1、创建表
- 2、建立domain包和domain类
- 3、建立dao包和dao接口
- 4、建立dao.impl包和dao实现类
- 5、根据dao接口创建dao测试类
- 6、编写一个dao方法,进行测试功能是否正确
- 7、创建包
- 8、内部结构
- 9、编写实现类方法体:
- 保存方法
- 删除方法
- 修改方法
- 获取一个学生
- 获取所有学生
- DAO代码重构:
- 1、每一个DAO中都会写驱动名称、url、用户名密码
- 2、每个DAO中都会有共同的代码模
- 3、每个dao方法中每次操作只需要connection对象,但每次不要注册驱动 将驱动注册封装为静态代码块
- 把创建的connection代码抽取到jdbcutil中
- 并提供一个getConnection就能获得连接对象
- 4、每个DAO方法需要关闭资源
- 5、DAO中拼接SQL太忙烦
- 使用预编译语句
- Statement接口
- 接口:
- 作用:用于进行java程序和数据库之间的传输
- 具体类有3个实现:
- Statement:用于对数据库进行通用访问,使用的是静态sql
- PreparedStatement:用于预编译模板SQL语句,在运行时直接输入参数
- CallabStatement:
- 预编译语句:
- 没有预编译语句时,所有的sql都是进行拼接的
- 有了预编译语句,在性能和代码的灵活性上有显著提高
- PreparedStatement:对象使用?作为占位符,即参与标记
- 使用setXXX(index,value)方法将值绑定在参数中
- PreparedStatement 对象执行sql语句
- executeQuery();
- executeUpdate();
- 编译语句去连接池中查询,在设置参数
- 更安全 能防止SQL注入
- 什么是SQL注入:
- 就是通过把sql命令插入到web表单提交或输入域名或页面请求的查询字符,最终达到欺骗服务器执行sql命令。
- 为什么预编译语句能防止sql注入?
- 它能把单引号转义,变成’;
- 这样一来,就无法截断sql语句基本上没有办法注入了
- 调用存储过程
- 1、在数据库中定义一个存储过程
- 2、JDBC调用一个参数的存储过程
- 3、编写输入参数和输出参数的存储过程
- 4、JDBC调用第二个参数的储存过程
六、事务处理
- 事务的使用
- 事务问题:
- 处理事务:
- 默认情况下,事务是自动提交的,
- 要设置为手动提交
- 处理事务过程:
- 关闭自动提交: conn.setAutoCommit(false);
- 没有问题时提交事务:conn.commit();
- 出现异常时进行回滚操作:conn.rollback():
- 回滚之后,没有提交,释放资源
- 出现异常,没有提交,也不会更新数据库,但是会占用资源
- 所以在出现异常时,进行事务回滚操作
- 只有增删改才需要事务,查询不需要事务
- 以后发现自己写的代码是正确的,
- InnoDB才支持外键和事务,MylSAM不支持外键和事务
- 出现异常:一个钱少了,一个没加钱,
- 事务的隔离级别:
七、批处理
- 什么时批处理
- 一次性执行多条sql语句,允许多条语句一次性提交给数据库批量处理
- 比单独处理效率高
- 批处理方法
- addBatch(String):添加需要批处理的sql语句
- exexcuteBatch():执行批处理
- 支持情况
- mysql默认情况下不支持批处理
- 在后面添加一个参数
- 示例
八、储存图片
- 数据库中的BLOB
- 存储图片、音频、视频等多媒体信息
- 以二进制的形式
- 真正开发当中
- 不会把二进制的文件存放到数据库当中
- 把文件存储的路径存储到数据库中,以后再取出路径,到该路径下读取信息
- BLOB类型:
- mediumBlob 16M
- 操作:
- 往表中添加一个字段,设置类型为blob类型
- 通过代码存入一张图片到数据库中
九、获取自动生成的主键
十、连接池
- 没有连接池情况
- 每次crud 操作都要使用数据库时,都要创建一个数据库连接对象
- 普通的jdbc数据库连接使用DriverManager来获取
- 每次向数据库连接时都需要将connection加载到内存中
- 每次CRUD操作就向数据库要一个连接执行完成后再断开连接,这样的方式将会消耗很多资源和时间。
- 数据库连接池:
- 池:保存对象的容器
- 连接池:保存数据库连接对象的容器
- 作用:
- 初始化时创建一定数量的对象,需要时直接从池中取出一个空闲对象
- 用完后并不选择直接释放对象,而是再放入对象池中以防便下一次对象请求时直接使用
- 池技术的优势是,可以消除对象创建所带来的延迟,从而提高性能
- 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”
- 预先再缓冲池中放入一定的数量的连接,当需要建立数据库连接时
- 只需从“缓冲池”中取出一个,使用完毕后再放回去
- 我们可以通过设定连接池最大连接来防止系统无尽的与数据库连接
- 可以通过连接池的管理机制监视数据库的连接数量,使用情况,为系统开发,测试及性能提供依据
- 示意图:
- 连接池属性
- 连接池的使用:
- 连接池是使用javax.sql.DataSouce接口来表示连接池
- DataSource 和jdbc连接池一样他在lib目录中
- 常用连接池;
- Druid:阿里
- C3P0:
- DBCP:
- 使用连接池与不使用连接池的区别:
- 1、获取方式
- 2、释放资源的方式
- 连接池操作
- 主要是学如何创建DataSource对象,再从DataSource对象中获取Connection对象
- 这些都是第三方提供的
- 创建DataSource:
- 使用DBCP:1、导入相关jar包 2、再项目中使用连接池来获取连接 3、实列R
- 配置文件
- 资源文件,是以properties作为扩展名的文件
- 再上面使用的数据库过程当中,我们把库的连接地址,用户名,密码都写再代码当中
- 不便于后期维护
- 配置文件的书写
- db.properties
- DAO代码重构
- 重构原则
- 同一类中:
- 同一个类中有多个方法当中有太多的代码相同
- 不同地方当作参数传进去
- 把他们抽到方法中
- 不同类中:
- 不同类中有共同的代码抽取到一个类中
- 共享类中内容
- DML抽取:
- 1、设计一个方法
- 2、要求传入两个参数
- 一个sql语句
- 一个参数:可变参数
- 3、返回值
- 返回值为int 受影响行数
- 封装处理结果集:
- 每一个都封装成了student对象,写死了
- 解决方法
- 把处理结果交给每个DAO
- 为了规范每个DAO的处理结果集,大家都叫同样的名字,这样在模板中就可以调用同一个名称
- 定义一个处理结果集的接口
- 代码实现:
- 1、定义一个接口
- 2、在具体DAO中实现接口
- 3、创建一个接口实现对象传给查询方法
- 4、在查询方法当中调用处理结果集的方法
- 结果集处理器:
- 存在的问题:
- 该类只能将结果集中的一行数据封装程一个Student对象
- 我们如果有多个domain,就得提供多个结果集处理器
- 想法:
- 自动的把一行行数据封装成对象,自动设置属性,结果集处理器
- 处理不同表时,干的事都一样:1、给我一个要封装的类2、自动设置属性
- 存在的问题:
- 内省
- Class类型:
- 字节码类型
- 通过字节码创建对象
- 内省:
- 用于查看和操作JavaBean的属性
- 类:introspector
- Class类型:
- DBUtils:
- 1、什么是DBUtis:
- DBUtils是Apach公司编写的数据库操作实用工具,小巧,简单,实用
- 封装了对JDBC的操作,简化了JDBC的操作
- 2、QueryRunner:
- QueryRunner(DataSource ds):提供数据源连接池,会自动为你创建连接
- Update(String sql, Object…obj):执行更新数据
- query(String sql,ResultSetHandler rsh,object…param):执行查询
- 3、ResultHandler:
- 1、什么是DBUtis:
WEB 服务器开发
一、客户端与服务器
C/S与B/S:软件使用上的两种方式的划分
- C/S:客户端/服务器架构
- 特点:在服务器当中有一个主要数据库,把所有的业务逻辑以及页面都交给客户端完成
- 优点:较为安全、用户界面丰富、用户体验好
- 缺点:每次升级多要重新安装,针对于其他操作系统的开发,可移值性差
- B/S:浏览器/服务器架构
- 特点:基于浏览器访问的应用,把业务层交给服务器来完成,客户端仅仅作页面的渲染来和数据交换。
- 优点:只开发服务器端,可以跨平台,移植性高
- 缺点:安全性比较低,用户体验差
Web资源
- web:WEB网页,它用于表示网络主机上供外界访问的资源
- Web资源分类:
- 静态web资源:用web页面中提供人们浏览的数据资源始终不变
- 动态web资源:用web页面中供人们浏览的数据是由程序产生的,不同的时间点访问web页面看到的内容不同。
- web资源存在哪里:
- 所有web资源都存放在一个web服务器中
- web服务器是可以供外界访问web资源的一个软件
- web资源放到指定目录当中,就可以通过对应的端口在浏览器当中访问
- URL地址:
- 协议://主机地址:端口号/资源地址
- http://www.zxh.com:80/index.html
- f访问协议 服务器的一个域名 、端口号、服务器上的目录或文件
资源访问流程
- 客户端:浏览器、Android程序、iOS程序、微信小程序
- 服务器:pah服务器、tomcat服务器、
- 当我们在浏览器中访问一个一个网址时,为什么就能看到一个页面?
- 1、 一个网址对应的其实就是一个IP地址
- 一个IP地址对应一个一台电脑
- 通过IP地址找到对应的电脑
- 电脑当中安装的有web服务器,通过端口号就能找到服务器
- 2、找到对应的服务器,服务器页面返回给你
- 3、这样的一个过程就是http请求过程
- 1、 一个网址对应的其实就是一个IP地址
- BS结构流程图:
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9JOHfOHd-1598243947085)(E:/dream_work/p2.png)]
- 请求与响应
- 请求:把客户请求发送给服务器
- 响应:服务器把你的数据发送给客户端
- 请求与响应都要一定格式
- 约定好客户以什么格式访问服务器
- 约定好服务器以什么的格式把数据给客户端
- 这个约定使用的就是http协议
Http协议
- 协议:约束双方的一个准则
- Http协议:
- http超文本传输协议是互联网上应用最为广泛的一种网络协议
- 所有的www文件都必须是这个标准
- 设计HTTP最初的目的是为了提供一种发布和接受html页面的方法
- 约束请求与响应的规则
- http组成部分:
- 请求:
- 响应:
- 请求与响应是成对出现的
- 请求的发送方式
- 1、通过浏览器地址栏
- 2、通过html当中的form表单
- 3、通过a链接的href
- 4、src属性
- Http请求
- 请求行:
- 请求方式:Post 、get
- 请求资源:/蚂蚁商城项目/html/login.html/?username=zxh&password=123
- 协议版本:HTTP/1.0
HTTP/1.1
- 请求头:
- 请求头是客户端发送给服务器的的以些信息
- 使用键值对表示Key:value
- 常见请求头:
- Referer:浏览器通知服务器,当前的请求来自何处,如果是直接访问就不会有这个头,常用于:放到链
- Cookie:用于存放浏览器缓冲的cookie信息
- User_Agent:浏览器通知服务器,客户端浏览器与操作系统的相关信息
- 请求体:
- 当请求方式是post,请求体会有请求的参数
- 如果请求方式为get,那么请求参数不会出现在请求体中,会拼接在url地址后
- 示意图:
- 请求行:
- HTTP响应:
- 响应行
- Http协议:
- 状态码:
- 200:请求成功
- 302:请求重定向
- 304:请求资源没有改变,访问本地缓存
- 404: 请求资源不存在,通常是用户路径编写错误,也可能是服务器资源以删除
- 500:服务器内部错误,通常程序异常。
- 其他状态码:
- 2 开始一般请求成功
- 3 开头代表重定向
- 4 代表资源不存在
- 5 代表资源内部有错误
- 响应头
- 服务器端将信息以键值对的形式返回给客户端
- 常见请求头
- 响应体
- 图示
- 响应行
- 请求方式
- 8种请求类型:
- 1、OPTIONS
- 2、HEAD:请求页面信息,返回头部信息
- 3、GET: 请求指定页面信息,并返回实体主体
- 4、POST:向指定的资源提交数据进行处理请求
- 5、PUT:
- 6、DELETE:
- 7、TRACE
- 8、CONNECT:
- 常见的两种请求:
- GET:GET方法向页面请求发送参数
- 地址和参数信息中间用?字符分隔:https://www.taobao.com/?username=zxh&password=123
- 查询字符串会显示在地址栏的URL中,不安全,一般不是用get提交数据
- GET方法有大小限制:请求字符串中最多只能有1024个字符
- GET请求能够被缓存
- GET请求会保存在浏览器的浏览记录中
- 可以添加书签
- 编码类型为
- GET只允许传输ASCll字符类型,不能用二进制
- 点击刷新时GET请求没反应
- GET请求主要用于获取数据
- POST: 向页面请求发送参数
- 使用POST方法,查询字符串在POST信息中单独存在,和HTTP请求一起发送到服务器
- 在传二进制流的时候一般使用post
- 没有历史记录
- 参数类型没有限制,可以是字符串也可以是二进制流
- 数据不会再地址栏中显示,也不会缓存下来,或保存在浏览记录中,所以有POST请求比GET安全,但也不是最安全的方式,如需要传送敏感数据,则使用加密传输
- 查询字符串不会显示在地址栏中
- POST传输分数据量大,可以达到2M,
- POST主要是为了将数据传送到服务器的,而get主要为了从服务器中取出数据
- GET:GET方法向页面请求发送参数
- 8种请求类型:
Tomcat服务器
- Java分类:
- JavaSE:Java的标准版,一般都用来开发桌面应用程序,但在开发桌面应用程序上相对于VB、Delphl、VC++并没有什么优势
- JavaEE:Java企业版,开发javaweb应用程序,初级的一般使用jsp+servlet+JavaBean来开发的,大型网站一般用框架来开发的,Struts、spring、Mybatis
- JavaME :Java的微型版,手机应用的开发
- JavaEE的规范:13个技术规范,Sun公司定义了13个标准,其他公司的人可以根据规范来开发JavaEE程序
- 常用的JavaWeb应用服务器:Tomcat(Apache开源组织开发免费应用)、weblogic、websphere
- 下载与安装Tomcat
- 启动tomcat:
- 1、进入到解压目录
- 2、找到bin目录
- 3、找到startup.bat双击启动脚本
- 4、通过浏览器访问:
- 5、shutdown.bat停止脚本:
- web应用目录结构
- webName:
- html、jsp、js文件
- WEB-INF:
- class目录:Java类字节码文件
- lib目录:Java类运行时需要的jar包
- web.xml文件:当前整个web应用的核心配置文件,可以从ROOT中复制一个
- WEB-INF目录下当前的页面的资源不能直接通过浏览器访问,是保护的,外界不能直接访问
- webName:
- 使用Eclipse发布项目
- 发布工程:
- 右键项目,run Server:1、将未发布的工程、发布到webapps下面 2、启动tomcat
- 说明:
- 在发布时
- 会在tomcat的webapps目录下创建一个名称为myprocject的目录
- 并且把webcontent当中的所有内容放到webapps目录下,myproject当中
- 不会把写的java代码给放到webapps当中,运行时只要字节码
- 发布工程:
- 发布程序详解:
- Context:docBase:web应用的文件路径
- path:URL入口
- reloadable:reloadable:字节码变化服务器是否重新加载web应用
- tomcat服务器体系结构
- Server整个Servlet容器组合,可以包含一个或多个
- service:它由一个或者多个Connector组成,以及一个Engine,负责处理所有Connection所获得的客户请求
- connector:客户端与程序交互组件:负责�������收请求以及向客户端返回响应
- Engine:处理接收到的请求
- Host:虚拟主机
- Context:一个Context对应于一个Web Application
- 虚拟主机:
- 1、输入网址时,就会先到host文档中查找有对应的IP地址,如果有及直接访问该IP地址
- 2、如果没有,就会到外网去找DNS服务器进行域名与IP地址的解析,查找
- 3、多个域名可以访问同一个IP
- 4、一个IP对应一台电脑
Servlet与Servlet服务器
- 什么是Servlet?
- Servlet运行在服务器端的Java小程序,是sun公司提供的一套规范(接口)
- 用来处理客户端请求、响应给浏览器的动态资源
- Servlet的实质就是Java代码,通过Java的API动态向客户端输出内容
- 以后程序就不在本地执行了,而是编译成字节码,放到服务器上去执行
- 编写程序时,不需要有main函数,因为写完后,就把编写的程序编译成了字节码,放到服务器上面。当前发送一个请求的时候,服务器就会按照一定的规则编写代码。
- servlet 快速入门
- 1、创建一个Web项目
- 2、在JavaResource中src下创建一个包名称为com.zxh.servlet
- 3、在创建的servlet包当中创建一个class文件起名为FirstServlet
- 4、进入该class实现一个Servlet接口,实现它为实现的方法
- 重点看service方法
- 在该方法当中写入一句话进行输出
- 5、在web.xml当中进行配置
反射
- 类的加载时机:
- 当程序要使用某个类时,如果该类还未被加载到内存中
- 系统会通过加载,连接,初始化三部来实现对这个类进行初始化
- 加载:就是指将class文件读入内存,并为之创建一个Class对象,任何类使用时系统都会建立一个Class对象
- 连接:
- 验证是否有正确的内部结构,并和其他类协商一致
- 准备负责为类的静态成员分配内存,并设置默认的初始化值
- 初始化:初始化变量
- 加载时机:
- 创建类的实例
- 访问类的静态变量,或者为静态变量赋值
- 调用类的静态方法
- 初始化某类的子类
- 使用反射的方式来强制创建某个类或接口对应的java.lang.Class对象
- 类加载器
- 什么是类加载器classLoader:
- 负责将.Class文件加载到内存中,并为之生成对应的Class对象
- 虽然不需要关心类加载机制,但是了解这个加载程序我们就能更好的理解程序的运行
- 类加载器分类:
- 根类加载器:
- 也被称为引导类加载器,负责Java核心类加载
- 比如System,String等,在JDK中JRE的lib目录下的rt.jar文件中
- 扩展类加载器:
- 负责JRE的扩展目录中jar包加载
- 在JDK中JRE的lib目录下ext目录
- 系统类加载器:
- 负责在JVM启动时加载来自Java命令的class文件
- 以及classpath环境变量所指定的jar包和类路径
- 根类加载器:
- 什么是类加载器classLoader:
- 什么是反射
- 创建一个对象的三个阶段:1、源文件阶段.java的文件2、字节码阶段.class 3、创建对象阶段 new 对象名称
- 内省:在运行时能够获取JavaBean当中的属性名和get和set方法
- 反射:
- Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
- 这种动态获取的信息以及动态调用的对象的方法的功能称为Java语言的反射机制
- 想要使用反射,就必须得要获取字节码文件
- 获取字节码文件:
- object类的getClass()方法
- 静态属性class
- Class类中静态方法forName()
- 示例:
- 通过字节码创建对象
- 获取字段:
- 获取公共字段
- 获取私有字段
- 获取方法:
- 通过数组越过集合泛型检测
Servlet访问流程
- 生命周期
- Servlet什么时候创建
- init
- service
- destory
- load-on-staetup
- Servlet配置信息
- :
- 名称
- 值
- config参数:
- 该servlet的配置信息
- 获得web.xml当中参数
- 初始化参数
- 获取servletContext对象
- url-patten:
- 1、完全匹配
- 2、目录匹配
- 3、扩展名匹配
- 缺省Servlet
- 欢迎页面
httpServlet
-
使用注解创建servlet
- 注解就相当于在代码上添加了一个小插件,贴上这个注解,会在内部自动帮你去做
- 注意点:在web.xml中要有一个配置 metadata-complete=“false”,是否扫描类当中定义的注解。true代表不扫描
-
直接new 的Servlet它是一个httpServlet
-
他是GenericeServlet的子类
-
HttpServlet方法
-
方法:
- service:每一次发送请求时候会调用,当写了service就不会在调用get和post
- doGet:当发送get请求时间调用
- dopost:当发送post请求的时候调用
-
内部方法调用过程
- 当接收到一个请求时,tomact就会找对应的service方法
- 如果当中的service当中没有存在service方法,就会到它的父类当中去找
- 在父类当中找到service是参数为ServletRequest,在会内部把参数转为httpServlet
- 转还完毕后会在继续调用参数为httpServletRequest的service方法
- 在此方法当中会获取参数类型,根据不同的参数类型再去调用不同方法
-
驱动案例:
- 用户输入用户的密码到数据库连接数据库,验证登录是否正确
- 步骤:
- 1、到数据库中建立一个用户表:id、name、password、email
- 2、书写html登录界面
- 3、创建loginServlet
- 4、接收到请求时+
上下文对象–请求对象-响应对象
ServletContext
- ServletContext:
- 定义:ServletContext代表是一个web应用的上下文对象(web应用对象) 、里面封装的都是web应用信息、一个Servlet对应一个应用
- servletContext的生命周期:在服务器一启动时就会创建、在服务器关闭时销毁
- 如何获得上下文:
- 1、通过init方法当中一个参数ServletConfig获取
- 2、直接在HttpServlet当中获取
- 获取全局的初始化参数:
- 获取web应用中某一个资源的绝对路径:
- context.getRealPath(“文件”)
- 相对的是web应用目录
- ServletContext是一个域对象
- 什么是域:能够存储数据
- 域对象:能够存取数据的对象
- ServletContext域对象的作用范围(整个web应用、所有的web资源都可以进行存取数据、数据是可以共享的)
- 获取完ServletContext之后向里面写数据Context.setAttribute (String name,Object value);
- 获取完ServletContext之后,通过name取出存放数据、context.getAttribute(String name);
- 删除指定名的值:Context.removeAttribute(String name);
- 只要是一个域对象,就有这几个方法
Response
- response响应过程
- 1、在去发送一个请求时,会找到tomcat引擎
- 2、引擎会找到对应的web应用,并且会创建response和request对象
- 3、找到应用后,会执行应用的web.xml再去根据url-pattern的内容创建Servlet对象
- 4、并且会调用servlet对象的service方法,并且把创建的request对象和response对象传入到方法中
- 5、拿到response对象后自己可以往响应中写入一些自己给客户的内容
- 6、写的内容是存到response的缓冲区当中
- 7、当方法执行结束之后,tomcat从response缓冲区中取出数据
- 学习响应
- 通过response设置响应行,响应头,响应体
- 设置响应行
- 设置状态码:response。setStatus(Code)
- 设置响应头:
- add(添加):add代表添加额外的信息
- set(设置):修改响应头信息
- 重定向:
- 什么是重定向:
- 到服务器中去找servlet1,
- servlet1当中有这个资源,告诉你去找servlet2
- 再发送一个请求到servlet2
- 状态码:302
- 特点:
- 要访问两次服务器:第一次人为的去访问,第二次自动访问,
- 浏览器地址栏发生变化。
- 什么是重定向:
- 设置重定向;
- 设置响应码
response.setStatus(302); - 设置响应头
response.setHeader(“location”,)
- 设置响应码
- 封装的重定向
- 每次都要写状态码,和location比较麻烦,就封装了一个方法,
- response.sendRedirect("/26_Servlet/LocationServlet");
- 定时刷新重定向
- 设置响应体:
- 1、通过write的方法来写
- 默认情况下写中文内容会乱码
- 把写的内容存到缓冲区中使用的是ISO8859
- ISO8859不支持中文,所以会乱码
- 在存之前设置
- 默认情况下写中文内容会乱码
- 2、通过OutPutStream来写
- FileinputStream:
- FileOutputStream:
- response注意点:getWrite()和OutputStream不可同时使用
- 1、通过write的方法来写
- 下载功能
- 使用a标签去下载:有些内容会自动解析,浏览器不能解析的文件才会被下载
- 通过发送Servlet请求来下载:
- 通过发送一个Servlet请求,把文件名发送给服务器
- 发送给服务器后,接收到文件名参数,获取文件的绝对地址
- 通过流的形式写到浏览器
- 还得要告诉文件是什么类型
- 设置响应头告诉浏览器不要去解析是以附件的形式打开
- 步骤
- 示例代码
- 解决中文名称的乱码问题
- 获取中文参数报错问题
- 1、把获取的字符串参数的字节码获取,再重新使用utf-8编码
- 2、在设置以前以附件的形式打开时,不同的浏览器会对默认的名字进行解码
- 所以根据不同的浏览器,要对名称进行编码之后,在放入文件名
- 对文件名进行解码
- 步骤
- 注册验证码功能
- 为什么要有验证码?
- 防止黑客恶意注册
- 1、把浏览器写好的验证码Servlet拿到程序当中
- 2、编写静态页面
- 3、编写判断验证码是否正确的servlet
- 为什么要有验证码?
Request
- 获取请求行
- 获取请求方法
- 获取请求资源:String getRequestURL() String getRequestURI()
- 获取应用名称: String getContextPath()
- 获取get查询参数:String getQueryString()
- 获取请求头
- 获取请求体
- 请求转发
- 客户端地址与服务器地址
n",)
- 封装的重定向
- 每次都要写状态码,和location比较麻烦,就封装了一个方法,
- response.sendRedirect("/26_Servlet/LocationServlet");
- 定时刷新重定向
- 设置响应体:
- 1、通过write的方法来写
- 默认情况下写中文内容会乱码
- 把写的内容存到缓冲区中使用的是ISO8859
- ISO8859不支持中文,所以会乱码
- 在存之前设置
- 2、通过OutPutStream来写
- FileinputStream:
- FileOutputStream:
- response注意点:getWrite()和OutputStream不可同时使用
- 下载功能
- 使用a标签去下载:有些内容会自动解析,浏览器不能解析的文件才会被下载
- 通过发送Servlet请求来下载:
- 通过发送一个Servlet请求,把文件名发送给服务器
- 发送给服务器后,接收到文件名参数,获取文件的绝对地址
- 通过流的形式写到浏览器
- 还得要告诉文件是什么类型
- 设置响应头告诉浏览器不要去解析是以附件的形式打开
- 步骤
- 示例代码
- 解决中文名称的乱码问题
- 获取中文参数报错问题
- 1、把获取的字符串参数的字节码获取,再重新使用utf-8编码
- 2、在设置以前以附件的形式打开时,不同的浏览器会对默认的名字进行解码
- 所以根据不同的浏览器,要对名称进行编码之后,在放入文件名
- 对文件名进行解码
- 步骤
- 注册验证码功能
- 为什么要有验证码?
- 防止黑客恶意注册
- 1、把浏览器写好的验证码Servlet拿到程序当中
- 2、编写静态页面
- 3、编写判断验证码是否正确的servlet
Request
- 获取请求行
- 获取请求方法
- 获取请求资源:String getRequestURL() String getRequestURI()
- 获取应用名称: String getContextPath()
- 获取get查询参数:String getQueryString()
- 获取请求头
- 获取请求体
- 请求转发
- 客户端地址与服务器地址