JAVAEE

这里写目录标题

1. 二阶段技术点:

客户端技术:

  1. HTML 网站页面内容 (HTML4 HTML5)
  2. CSS 网站页面样式(CSS2 CSS3)
  3. Javascript (AJAX)
  4. jQuery
  5. bootstrap / LayUI (前端样式框架,插件)
  6. 数据库 mysql
  7. JDBC (JAVA连接数据库)
  8. JAVAEE (Servlet + JSP) 请求-响应 MVC
  9. 综合项目

2. 客户端技术

2.1 HTML

2.1.1 概念

Hyper Text markup language ,超文本标记语言,HTTP(Hyper Text Transfer Protocol )超文本传输协议,HTML基于HTTP协议的网站开发语言。

2.1.2 版本

HTML4.01  10年
HTML5.0   智能手机,移动端优先

W3C 技术联盟组织

2.1.3 开发工具

txt文档  / Editplus / notepad
Hbuilder / sublime / VScode / webstorm ... Eclipse / idea 

2.1.4 调试运行

浏览器
调试: F12
浏览器历史:
		第一次大战   网景 nn  / 微软 IE 
		第二次大战	欧朋 Opera / 火狐 FireFox / 谷歌 Chrome / IE / 苹果 Safari 
双核:   360 / QQ / 2345 / 搜狗 / 搜狐 ....

2.1.5 语法规则

  1. 拓展名 .html .htm
  2. 不区分大小写 (小写) , 不区分单双引号(‘’ “” )
  3. 标记(标签) + 属性
<标记 属性="值"  属性= "值"  属性='值'>

		内容

</标记>
  1. 网页结构
<!-- 注释:网页的文档类型  ctrl+shift+/ -->
<!DOCTYPE html> 
<!-- 网页的开始   -->
<html>
    <!-- 网页的头   -->
	<head>
    	 <!-- 设置网页的编码方式   -->
		<meta charset="utf-8">
    	 <!-- 设置关键词   -->
    	<meta name="keywords" content="千锋教育" />
    	<!-- 网页的标题   -->
		<title></title>
	</head>
     <!-- 网页的主体   -->
	<body>
		
	</body>
<!-- 网页的开始   -->
</html>
  1. 标记(单标记 <标记/> 双标记 <标记> </标记>)

2.1.6 标记和属性

1.基本布局标记

标签含义属性
<h1></h1> ...<h6></h6>标题,双标记,独占一行,1最大 6最小align=“center”
<hr/>水平线,单标记color=“hotpink”
width=“80%”
size=“4”
align=“center”
<p></p>段落,双标记,大段文字
<br/>换行
<img />图像src=“img/1.png”
alt=“该图无法刷新”
width=“500px”
<b></b> <strong></strong>文字加粗
<s></s>删除线
<i></i>文字倾斜
<u></u>下划线
<sup></sup>上标
<sub></sub>下标
<div></div>块元素(容器)
<span></span>文本标记
<ul> <li></li> </ul>无序列表type=“” circle square disc
<ol> <li></li> </ol>有序列表type=“” 1 a A I i
<dl><dt></dt><dd></dd></dl>自定义列表
<a></a>超级链接href=“” 链接跳转路径
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			/* CSS代码 */
			h1{
				color: #333;
			}
			/* 居中 */
			p{
				width: 80%;
				/* 段落居中 */
				margin: auto;
			}
		</style>
	</head>
	<body>
		<!-- 标题 -->
		<h1 align="center" >
			世界杯结果: 日本对战德国(2:1)
		</h1>
		<!-- 水平线 -->
		<hr color="hotpink" width="80%" size="4" align="center">	
		<br><br><br>
		<!-- 段落 -->
		<p align="center">
			<!-- 图 -->
			<img src="img/1.png" alt="该图无法刷新">
		</p>
		<br>
		<p align="left">			
			<br>
			&nbsp;&nbsp;&nbsp;&nbsp;第31分钟,劳姆在禁区内被权田修一放倒。随后京多安主罚点球命中,德国队1-0领先。整个上半场,两队各有一次越位破门被判无效。
			<br>
			下半场比赛第74分钟,刚换上场的南野拓实扫射被诺伊尔扑出,随后跟进的堂安律补射破门,日本队1-1扳平场上比分。第83分钟,浅野拓磨右路突破,一脚爆射再次破门。日本2-1反超比分,并将比分保持至终场。
		</p>
		
	</body>
</html>	
<!-- 文字标记 -->
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			span{
				color: palevioletred;
				font-size: 30px;
				font-family: 楷体;
			}
			div{
				width: 80%;
				height: 200px;
				background-color: lightblue;
			}
		</style>
	</head>
	<body>
		<p>
			<b>下半场比赛</b>
			<u><i>第74分钟,刚换上场的</i></u>
			<br>
			原价: <s>¥999</s> , 优惠价: <strong>¥99</strong>
			<br>
			2 <sup>3</sup>	
			<br>
			H<sub>2</sub>O
			log<sub>2</sub>10
			<br>
			南野拓实扫射被诺伊尔扑出,随后跟进的堂安律补射破门,日本队1-1扳平场上比分。第83分钟,浅野拓磨右路突破,一脚爆射再次破门。日本2-1反超比分,并将比分保持至终场。
		</p>		
		<span>
			于老师今天心情还行~~~
		</span>		
		<div>			
		</div>
	</body>
</html>

链接:

1. 页外链接  <a href="其他页面/URL"></a>

2. 页内链接  (单页长,一个页面跳转; 锚链接)
   1. 定义锚点  <a name="锚点名" ></a>
   2. 找锚点 <a href="#锚点名"></a>
  <a href="#"></a> 回到顶端
  1. 表格标记

    用于显示批量数据。

标签含义属性
<table></table>表格border=“1” 边框
align=“center”
width=“600”
height=“400”
cellspacing=“0” 单元格间距
cellpadding=“10” 边框和内容间距
<tr></tr>height=“100”
align=“center”
valign=“top”
<td></td>行里列,单元格width=“100” align=“right” valign=“bottom”
rowspan=“数字 跨行合并”
colspan=“数字” 跨列合并
<table border="1" align="center" width="600" height="400" cellspacing="0">
			<!-- 第一行 -->
			<tr height="100" align="center" valign="top">
				<td width="100" align="r" valign="bottom" rowspan="2">
					跨行
				</td>
				<td colspan="2">跨列</td>
				
			</tr>
			<!-- 第二行 -->
			<tr>		
				<td>5</td>
				<td>6</td>
			</tr>
</table>
  1. 表单标记

表单用于在客户端收集客户信息,表单填写数据,提交到服务器端。

标记含义属性
<form></form>表单整体action=“” 表单提交的路径
method=“get” 表单提交方式 GET 明文 POST 密文
id=“” 唯一名,不要数字开头
name=“” 可以重

表单元素(内容):

​ 输入上传

标记含义属性
<input type="text" />文本框value=“” 表单的值
placeholder=“” 提示文字
maxlength=“6” 最大长度
id=“”
name=“”
readonly 只读 不能编辑
required 空校验
pattern=“[0-9]{6}” 正则校验
<input type="password" />密码框同上
<input type="file" />上传框
<input type="hidden">隐藏框,客户端向服务器传值
<textarea></textarea>文本域

选择框

标记含义属性
<input type="radio" >单选按钮name=“” 相同name
checked 默认选择
<label for="pass"></label>文本标记for=“某id”
<input type="checkbox" >复选框name=“” 相同name
checked 默认选择
<select><option></option><option></option>....<br /></select>下拉菜单select : value 最终选择值
option: seleted value 每个选项的值
<optgroup></optgroup>分组label=“辽宁省”

​ 按钮

标记含义属性
<input type="submit" >提交按钮,自动提交表单到对应URLvalue=“登录”
<button></button>提交,语义化标记
<input type="button" >普通按钮
<input type="image" src="" >图像按钮

2.1.7 常用问题

方位:
	水平方位  align :  left  center  right
	垂直方位  valign : top  middle  bottom

颜色: (文字,背景,边框)
	1. 颜色名  pink hotpink blue ...
	2. #FF00DD  十六进制  红绿蓝 混合 0-255 
	3. rgb()  rgba()  十进制 背景
	4. 渐变
尺寸:
	px 像素
	%  
空格: &nbsp;

内容居中:
	块: 容器(标题 段落 div ) 可以设置居中
    文字/图 : 借助容器内容居中
	<p align="center">
			<span>
				于老师今天心情还行~~~
			</span>
	</p>
	p{
		text-align: center;
	}
	容器本身:
	p{
				width: 80%;
				/* 段落居中 */
				margin: auto;
	}


路径:
	<img >   src
	<a></a>  href
	<form>   action
        
	</form>

2.1.8 HTML5的特性

1. <!DOCTYPE html> 头文件 : 文档类型(版本,语法严格HTML  XHTML  XML )
2. 废弃标记,属性(废弃和样式关系紧密的: 内容和样式分离)
	<font></font> 字体标记 
	align=""
	<center>
	...
3. 新增
	1. 语义化标签  <button>  <nav>  <footer>
	2. 表单: 标签: 
			 <!-- <input type="date" value="2022-11-25" />
            <input type="time" />
            <input type="range" />
            <input type="color" />
            <input type="email" />
            <input type="tel" />
            <input type="url" />
            <input type="number" min="1" value="1"> -->

            <input type="text" list="l1" />
            <datalist id="l1">
			
			<option value="大连" label="DL">大连</option>
			<option value="大同" label="DT">大同</option>
			<option value="深圳" label="SZ">深圳</option>
			<option value="上海" label="SH ">上海</option>
			</datalist>
			 属性: required pattern placeholder
    3. 拖拽
    4. 视频 音频 <video src=""></video>
    5. 画布 矢量图 
    ....

2.1.9 HTML中标记的分类

一 块元素(容器)

1. 元素宽度一定100%,独占整行
2. 每次重新另起一行
3. 可以设置宽度 高度 内外补白 边框 
  
<p></p>  <div></div>  <table></table>  <form></form> <hr> <ul/ol/dl></ul/ol/dl> <hn></hn> [n: 1-6]

二 内联元素(内容)

1. 元素宽度就是本身宽度
2. 元素都会紧挨着显示
3. 不可以设置宽度 高度,水平方向留白
    
<a></a> <span></span> <label></label> <i></i> <b></b> ...

三 内联块元素(内容但设置宽高)

1. 元素宽度就是本身宽度
2. 元素都会紧挨着显示
3. 可以设置宽度 高度,留白

<img/> <video></video> <input> <button></button>

2.2 CSS

2.2.1 概念

层叠样式表(cascading style sheet),用来修饰网站网页的语言。

2.2.2 作用

​ 1.美化HTML的元素,美化网页的效果

​ 2.实现内容和样式的分离,解耦,代码方便维护和调试

​ 3.一次定义可以反复使用

2.2.3 版本

CSS2.0	修饰网页基本样式
CSS3.0  动态样式

2.2.4 CSS的位置

1. 行内样式 (元素上添加style属性)
	<p style="color: pink;font-size: 20px;">
			横眉冷对千夫指,俯首甘为孺子牛
	</p>
2. 页内样式(head标记添加style标记) 【内嵌样式】
	<style>
			a{
				color: blue;
				font-size: 30px;
				/* 去掉下划线 */
				text-decoration: none;
			}
	</style>
3. 页外样式(需要在外部创建xx.css文件,页面引入外部css)【外部样式】
	<link rel="stylesheet" href="css/css-1.css">

总结:

对于同一个元素,三个位置同时设置,优先选择?

优先级: 就近原则,行内 > 页内 > 页外(参考导入顺序)

不同样式: 共同作用

<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<link rel="stylesheet" href="css/css-2.css">
		<style>
			span{
				color: green;
			}
		</style>		
	</head>
	<body>
		<span>
			测试文字
		</span>
	</body>
</html>
<!--
span{
	background-color: pink;
	font-size: 20px;
}

-->

2.2.5 CSS的语法规则

选择器:选取网页内容

样式属性: 修饰元素的

在这里插入图片描述

2.2.6 CSS的选择器

CSS2.0 10选择器, CSS3.0 10+ ,代码越精炼。

  1. 基本选择器(3个)
选择器用法示例选取
标记选择器p{ } img{ } a{ }选取所有该标记
id选择器#p1{} <p id="p1"></p>只选取一个元素
类选择器.c2{} <p class="c2">这是段落2</p>分类别选取元素
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			/* 标记选择器 */
			p{
				color: red;
			}
			h2{
				color:pink;
			}
			a{
				color: green;
			}
			/* id选择器 */
			#p1{
				color: hotpink;
				font-size: 25px;
			}
			/* 类选择器 */
			.c2{
				color: blue;
			}
			.c3{
				color: aqua;
			}
		</style>
	</head>
	<body>
		<h2>测试选择器</h2>
		<hr>
		<a href="">link1</a>
		<a href="" class="c2">link2</a>
		<p id="p1">这是段落1</p>
		<p class="c2">这是段落2</p>
		<p class="c3">这是段落3</p>
		<p class="c3">这是段落4</p>	
	</body>
</html>

优先级: 权值决定 : ID 100> 类 10> 标记 1

<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			#p{
				color: red;
			}
			p{
				color: pink;
			}
			
			.c1{
				color: blue;
			}
		</style>
	</head>
	<body>
        <!-- 红色 -->
		<p id="p" class="c1"> 		
			这是测试段
		</p>
	</body>
</html>

​ 2.层级选择器(选取有层级关系)

选择器用法示例选取
后代选择器祖先元素 后代元素{ }选取父元素中所有子元素(所有的后代)
子代选择器父元素 > 子元素{ }选取父元素中一层子元素
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			p{
				color: blue;
			}
			div>ul{
				/* color: deeppink; */
				border: 3px lawngreen solid;
			}
		</style>
	</head>
	<body>
		<p>nn</p>
		<p>nn</p>
		<div>
			<ul>
				<li>
					<ul>
						<li>888</li>
					</ul>
				</li>
				<li>
					2
				</li>
				<li>
					3
				</li>
			</ul>
		</div>
	</body>
</html>

​ 3.同级选择器

选择器用法示例选取
分组选择器元素1,元素2{ } p,a{}多个元素合并选取
相邻选择器元素1+元素2{} div+p{}元素1后面紧挨着的元素2
兄弟选择器元素1~元素2{} div~p{} 【css3】元素1后面所有的元素2
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			/* div,#p2{
				color: hotpink;
			} */
			
			div+p{
				color: deeppink;
			}
		</style>
	</head>
	<body>
		<div>1</div>
		<p class="cc">ppp1</p>
		<p id="p2">ppp2</p>
		<p>ppp3</p>		
		<div>2</div>
		<p class="cc">ppp3</p>
		<p >ppp4</p>
		<p>ppp3</p>		
		<div>3</div>
		<p class="cc">ppp3</p>
		<p>ppp4</p>
		<p>ppp3</p>	
		<div>4</div>
		<p class="cc">ppp3</p>
		<p >ppp4</p>
		<p>ppp3</p>
	</body>
</html>

​ 4.其他选择器

选择器用法示例选取
通设选择器*{ }将网页上全部元素选取,用于通设,如字体14px 微软雅黑,改变浏览器初始状态
属性选择器元素[属性=值]根据元素的属性值筛选元素
伪类选择器元素:动作{ }动作触发的时候显示元素样式,:hover{} :focus{} …

<style>
		  /*通设选择器*/
		  *{
				margin: 0;
				/* color: aliceblue; */
			}
		 /*属性选择器*/
			input[type=text]{
				width: 200px;
				height: 25px;
			}
			input[type=password]{
				width: 300px;
				height: 25px;
			}
 		  /*伪类选择器*/
			div {
				color: green;
			}

			div:hover {
				color: pink;
			}
</style>

5.选择器权值计算

		/*权值100*/
		#p1{
			color: red;
		}
		/*权值1*/
        p{
			
        }
		/*权值累加: 100 + 1 = 101 */
		#con p{
			color: pink;
		}
		/*权值累加: 100 + 100 = 200 */
		#con #p1{
				color: red;
			}
		/*red !important; 强行添加该样式,权值最高*/
		#p1{
				color: red !important;
			}

2.2.7 CSS的样式属性

1.字体样式

样式含义
color文字颜色颜色值 red ; 十六进制
font-size文字大小px / em 磅 ,默认16px = 1em
font-family文字字体微软雅黑 黑体 宋体
font-style倾斜italic
font-weight加粗100-900 bold bolder
text-decoration修饰none / underline 下划线
text-shadow【css3】阴影x轴 y轴 半径 颜色
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			body{
				background-color: lavenderblush;
			}
			div{
				width: 600px;
				/* 盒子在浏览器中间居中 */
				margin: auto;
				/* 内容居中 */
				text-align: center;
			}
			h2{
				color: palevioletred;
				font-style: italic;
				text-decoration: none;
			}
			p{
				color: aquamarine;
				font-size: 26px;
				font-family: 楷体;
				font-weight: bold;
				/* 文字阴影 */
				text-shadow: 5px 5px 5px pink;
			}
			a:hover{
				text-decoration: underline;
			}
		</style>
	</head>
	<body>
		<div>
			<h2>
				<a>《登高》【唐】杜甫</a>
			</h2>
			<hr>
			<p>
				风急天高猿啸哀,渚清沙白鸟飞回。 <br>
				无边落木萧萧下,不尽长江滚滚来。 <br>
				万里悲秋常作客,百年多病独登台。 <br>			
				艰难苦恨繁霜鬓,潦倒新亭浊酒杯。 <br>
			</p>
		</div>
		
	</body>
</html>

2.背景样式

样式含义
background-color背景颜色颜色值 ;十六进制 ; rgba() rgb()
background可渐变linear-gradient(to top right ,pink,lightblue); 线性渐变;射线渐变
background-image背景图url();
background-size大小100% 100%; px px; cover ; contain;
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>
			
		</title>
		<style>
			div{
				width: 500px;
				height: 300px;
				/* background-color: rgba(200, 50, 50, 0.7); */
				/* 居中 */
				margin: auto;
				/* 渐变 */
				/* background: linear-gradient(to top right ,pink,lightblue); */
				background-image: url(img/1.png);
				background-size: 100% 100%;
			}
		</style>
	</head>
	<body>
		<div>
			测试div
		</div>
	</body>
</html>

3.段落样式

样式含义
text-indent首行缩进em
text-align内容水平位置left right center justify【文字】
letter-spacing字间距px
verticle-align垂直方位【表格/】top middle bottom
line-height行高px
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			p{
				text-indent: 2em;
				/* 内容居中 */
				text-align: justify;
				width: 600px;
				margin: auto;
				/* letter-spacing: 5px; */
				line-height: 40px;
			}
			img{
				width: 200px;
				height: 200px;
			}
			div{
				text-align: center;
				width: 100%;
				height: 300px;
				background-color: pink;
				line-height: 300px;
			}
		</style>
	</head>
	<body>
		<div>
			<!-- haha -->
			<img src="img/1.png" alt="">
		</div>
		<p>
			长时间不外出活动,学习只能上网课,在这种生活状态下,部分儿童青少年出现焦虑、叛逆、情绪低落、兴趣减退等现象。儿童心理专家表示,在长时间居家的特殊时期,家长应该高度关注孩子的心理健康,用正确的方法及时疏导不良情绪。
			
			重庆医科大学附属儿童医院儿保科副主任医师魏华表示,作为一名儿童心理医生,也是一位母亲,她感触很深。因为她的孩子也居家学习,她面临着跟很多家长一样的挑战,比如孩子居家学习状态不稳定,上网课注意力不集中,自控能力差,情绪不稳定,抵触家长,生活没有规律,部分孩子还可能会沉迷于电子产品、网络游戏。
			
			为什么会出现这些问题呢?魏华表示,长时间居家,相对于常态的生活模式来说是一个改变,打乱了固有的生活状态和节奏。所以这种情况下,家长对于孩子的学习和生活状态是有很多的焦虑情绪的。而孩子除了学习以外,外出活动的时间减少,和同龄儿童互动的时间减少,往往会觉得无聊。因此无论是对于家长还是孩子来说,可能在这个阶段更容易产生一些焦虑、烦躁的情绪,亲子关系和家庭氛围会变得比较紧张。
			
			专家表示,长时间居家对全家人来说都是一个挑战,但也要看到其积极的一面:这是一段难得的亲子时光,家长可以借着朝夕相处的机会发现孩子内心的需求,找对方法就能让孩子愉快居家,还能拉近亲子距离。
		</p>
	</body>
</html>

4.边框样式

样式含义
border复合样式1px red solid; 不分顺序
border-width宽度px
border-color颜色red
border-style款式solid 实线 double 双实线 dashed 虚线 dotted 点状 none 无边框
border-radius圆角px
border-top…单方向设置边框
border-top-left-radius …单方向设置圆角
outline外边框1px red solid; 不分顺序
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			div{
				width: 500px;
				height: 500px;
				background-color: pink;
				margin: auto;
				border: 10px solid red;
				/* border-radius: 10px; */
				border-top: 10px solid blue;
				border-bottom: 10px solid blue;
				/* border-bottom: none; */
				/* border-top-left-radius: 20px;
				border-top-right-radius: 20px; */
				border-radius: 250px;
			}
		</style>
	</head>
	<body>
			
		<div>
		</div>
	</body>
</html>

外边框:

<style>
			input{			
				outline: none;
			}
			div{
				width: 800px;
				height: 400px;
				background-color: pink;
				margin: 100px auto;
				border:dashed 6px lightblue;
				outline:solid 10px pink;
			}
</style>

5.盒子样式(块元素,布局的)

样式含义
widthpx % vw[视口]
heightpx % vh[视口]
margin复合样式:外补白,以边框边界,向外距离;
上 右 下 左;
px auto [自动]
margin-top
margin-bottom
margin-left
margin-right
单方向设置px
padding同上,内补白,以边框边界,向内距离;影响宽高
padding-top
padding-bottom
padding-left
padding-right
单方向设置px
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			div{
				width: 800px;
				height: 400px;
				background-color: palevioletred;
				margin: 50px auto 20px auto;
				padding-left: 30px;
				padding-top: 30px;
			}
		</style>
	</head>
	<body>
		<div>
			C罗头球
		</div>
		<!-- <div>
			
		</div> -->
	</body>
</html>

6.盒子显示样式(布局的)

样式含义
display显示效果block; 块
inline-block ; 内联块
inline ; 内联
none; 消失,回收空间
verticle-align垂直方位,inline-block ; 内联块top middle bottom
visibility可见性 ,不回收空间hidden visible
opacity透明度,不回收空间(0 - 1)
	<style>
		#con{
			width: 950px;
			margin: auto;
		}
		#con div{
			width: 300px;
			height: 200px;
			background-color: pink;
			margin-top: 10px;
			display: inline-block;
			vertical-align: top;
		}
	</style>
</head>
<body>
	<div id="con">
		<div>1</div>
		<div></div>
		<div>3</div>
	</div>
</body>

显示和隐藏:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			div{
				width: 400px;
				height: 400px;
				background-color: pink;
			}
		</style>
	</head>
	<body>
		<div id="div1">
			
		</div>
		<button onclick="hide()">隐藏</button>
	</body>
</html>
<script>
	function hide(){
		//判断
		var div = document.getElementById("div1")
		//div.style.display = "none"
		//div.style.visibility = "hidden"
		div.style.opacity = 0
		//特效css3 过渡
		div.style.transition = "all 1s"
        //切换盒子的显示和隐藏
        
	}
</script>

盒子显示和隐藏的切换:

<body>
	<div id="div1"></div>
	<button onclick="hide()" id="btn1">隐藏</button>
</body>
function hide(){
		//判断
		var div = document.getElementById("div1");
		var btn = document.getElementById("btn1");
		if(div.style.display == "none"){
		div.style.display = "block";
			
        }else{
            div.style.display = "none";
        }
        btn.innerHTML = btn.innerHTML == '隐藏' ? '显示':"隐藏";
}

7.盒子布局方式(排版)

1. 流式布局 【盒子的显示: 从上往下,从左往右依次排版】 盒子: display verticle-align width margin height padding
2. 浮动布局 【将一组元素批量的向左或者向右设置漂浮】 : float : left ; float : right 
3. 定位布局 【用于元素定位显示在浏览器/父元素的某个位置】: position:fixed; absolute ; relative; 
												   left/right /top/bottom
												   z-index

流式布局案例:

<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Document</title>
		<style>
			#con {
				width: 900px;
				margin: auto;
				/* 去掉编辑器造成文本空格 */
				font-size: 0;
			}

			#con div {
				width: 300px;
				height: 200px;
				background-color: pink;
				margin-top: 10px;
				display: inline-block;
				vertical-align: top;
				font-size: 16px;
			}
		</style>
	</head>
	<body>
		<div id="con">
			<div>1</div>
			<div>2</div>
			<div>3</div>
		</div>
	</body>
</html>
样式含义
display流式block; 块
inline-block ; 内联块
inline ; 内联
none; 消失
float浮动布局left / right
clear浮动坍塌(浮动飘出文档空间)both ; left ; right

浮动布局案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			div{
				width: 300px;
				height: 300px;
				
				background-color: pink;
			}
			.left{
				float: left;
			}
			#right{
				float: right;
			}
		</style>
	</head>
	<body>
		<div class="left">1</div>
		<div class="left">3</div>
		<div id="right">2</div>
		<div style="clear:both;width: 0px;height: 0px;">
			
		</div>
		<p>
			2131223423423
		</p>
	</body>
</html>

浮动导航条:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			#top {
				width: 100%;
				height: 76px;
				background-color: #000000;
			}
			li{
				float: left;
				width: 100px;
				height: 76px;				
				line-height: 76px;
				text-align: center;
			}
			a{
				color: #cbcccc;
				font-size: 14px;
				text-decoration: none;
			}
			ul{
				margin-left: 200px;
			}
		</style>
	</head>
	<body>
		<div id="top">
			<ul>
				<li><a href="">关于我们</a></li>
				<li><a href="">关于我们</a></li>
				<li><a href="">关于我们</a></li>
				<li><a href="">关于我们</a></li>
				<li><a href="">关于我们</a></li>
			</ul>
		</div>
	</body>
</html>

定位布局(重叠)

样式含义
position定位fixed; 固定定位
absolute; 绝对定位
relative;相对定位
static 无定位;正常文档流;
left定位位置px
rightpx
toppx
bottompx
z-index定位层正数 ; 负数

三种定位:

定位含义参照物是否脱离文档是否重叠
fixed固定定位浏览器脱离重叠
absolute绝对定位针对于有过定位的父元素,否则针对于浏览器【子元素】脱离重叠
relative相对定位自己 【父元素】不脱离重叠

案例1: 固定定位

		#top {
				width: 100%;
				height: 76px;
				background-color: #000000;
				
				/* 固定定位 */
				position: fixed;
				top:0px;
				left: 0px;
				z-index: 1;
			}
		#footer{
				width: 40px;
				height: 60px;
				background-color: rgba(0, 0, 0, 0.2);				
				line-height: 60px;			
				text-align: center;
				/* 固定定位 */
				position: fixed;
				right: 150px;
				bottom: 180px;
				border-radius: 10px;
			}
		#footer a{
				color: white;
				text-decoration: none;
			}

案例2 : 绝对和相对定位(父元素相对,子元素绝对)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			#father{
				width: 600px;
				height: 300px;
				background-color: pink;
				margin: 30px auto;
				position: relative;
			}
			#son{
				width: 50px;
				height: 300px;
				background-color: lightblue;
				position: absolute;
				right: 0;
				top: 0;
			}
		</style>
	</head>
	<body>
		<div id="father">
			父元素
			<div id="son">
				子元素
			</div>
		</div>
		<p>
			hahaha 
		</p>
	</body>
</html>

2.3 Javascript

2.3.1 概述

JavaScript是应用在客户端的一门脚本语言,在浏览器上实现网页动态效果的技术。

2.3.2 版本和特点

Es5 常规版本
Es6 箭头函数

特点:
1.基于对象的  万物皆对象
2.弱类型	  不明确划分多种数据类型(有数据类型), var b = 10;
3.解释型语言	 靠浏览器引擎解析,解释一条,执行一条 
4.基于动作触发的 事件触发运行: 点击按钮  改变下拉菜单 刷新网页

2.3.3 JAVA和JS的区别

1. JAVA 编译型语言(解释);JS解释型语言
2. JAVA运行虚拟机;JS运行浏览器
3. JAVA面向对象;JS 基于对象
4. JAVA强类型语言;JS 弱类型语言
2.3.4 Javascript的位置

JS注释: // 单行注释 /* */ 多行注释

//1.行内脚本 button对象  οnclick=”" 点击事件
<button onclick="alert('点我做什么?')">点击试试</button>  

//2.页内脚本
//在网页中添加 <script></script> 任何位置 head里
<script>
	alert("欢迎学习JS")
</script>
<select name="" id="">
		<script>
				for(var i = 1; i <= 12;i ++){
					document.write("<option>"+ i  +"</option>")
				}
		</script>
</select>
//3.页外脚本,在外部提供xx.js 文件,页面引入
<script src="js/js2.js"></script>

//注意:引入的顺序 ,按照引入的顺序依次执行 脚本 > 页面 > 样式

2.3.5 基本语法规则

//和JAVA相似

1. 变量 ,常量就是直接的数值(10 "abc" 'abc' 10.52. 数据类型 ,数据类型转化
3. 运算符,表达式
4. 语句(顺序 分支 循环,循环退出 )
5. 数组
6. 函数
7. 对象(核心)		
        内置对象
        浏览器对象....DOM(事件)  BOM
        自定义对象,JSON 
		原型对象(类)
2.3.5.1 变量的定义
1. = 赋值
2. 区分大小写
3. 不区分单双引号 '' "" 
4. 每句话结束可以加; ,不加换行(一句话结束),必要时候使用,
			var a = 10
			var b = 10;

声明语法:

//1.声明一个
var 变量名 = 初始值 ;

//2.声明多个
var 变量名 [= 初始值 ] , 变量名2 [= 初始值 ]  ....

变量名: 同JAVA(字母 数字 _ $ 不是数字开头 , 不能是关键字, 小写;驼峰)

变量可以不断的重新赋值(不限制类型)

<script>
			var a = 10;
			var b = 10;
			var c = 20,d = 30;
			c = "abc";
			d = true;
			var sum = a + b;
			alert(c)			
		</script>
2.3.5.2 数据类型
1.基本数据类型
			数字类型: number (整数 小数)
			字符串类型: string (""  '')
			布尔类型: boolean  (true false)
2.特殊数据类型
			未定义 : undefined
            空值 : null

3.复杂数据类型
			函数 : function
            对象 : object

//测试函数: 测试变量属于哪种类型

typeof(变量)  true/false

案例:

<script>
			var num = 10;
			//弹出框
			//alert()
			
			/* 页面打印 */
			//document.write()
			num = 10.5
			num = 'abc'
			num = "welcome"
			num = false
			var num2 ;
			//数组
			var num3 = [];
			//控制台
			console.log(typeof(num))//number string boolean
			console.log(typeof(num2))//undefined
			console.log(typeof(num3))//object
</script>
2.3.5.3 数据类型转化
1. 浮点型取整(浮点型变成整数型)
	parseInt(小数);
2. 字符串转化为数字 string > number
	parseInt(字符串);  //转化为整数
	parseFloat(字符串);//转化为小数
<script>
			var n = 12.56
			console.log(parseInt(n))
						
			var s = "123.89"
			//alert(s + 10)
			//s = parseInt(s)
			s = parseFloat(s)
			alert(s + 10)
</script>

练习:定义一个浮点型变量,保留两位小数输出

var num = 12.57567567
num = parseInt(num * 100)
num = num / 100;
alert(num)

结合页面:

	<body>
		<input type="text" id="t1"> + <input type="text" name="" id="t2" />
		= ?
		<button onclick="js(t1.value,t2.value)">计算</button>
	</body>
	
	<script>
		function js(v1,v2){
			//取整
			v1 = parseInt(v1)
			v2 = parseInt(v2)
			alert(v1 + v2)
		}
	</script>
2.3.5.4 运算符
运算符符号注意事项
算术运算符+ - * / % ++ –+ 加法/拼接
/ 可小数运算 10.0 > 10
比较运算符== > >= < <= != === !==== 值是否相等 === 值和数据类型一致
逻辑运算符&& || !
条件运算符(三目)? :
赋值运算符= += -= …

注意:

运算的时候,JS中出现类型自动转化,因此快速字符串转化成数字 : “10” - 0 + 10 > 20 (*1 /1 )

算术运算符:

<script>
			var a = 10.0
			a = 10 / 4 
			alert(a)
			
			alert("10" - 8) // 2,不会出错,自动转化
			alert(2 * "5")//10
			
			//alert(10 % 3)
			var a = 1;
			alert(a++); // 1
</script>

比较:

			alert(1 == "1") // true
			alert(1 === "1") // false
			
			alert(undefined == null)// true
			alert(undefined === null)// false

练习:三个文本框,按钮,点击,弹出框获得三个数字最大数字(三目)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<input type="text" id="t1"> 
		<input type="text" id="t2" />
		<input type="text" id="t3" />
		
		<button onclick="js(t1.value,t2.value,t3.value)">获取最大值</button>
	</body>
	
	<script>
		function js(v1,v2,v3){
			//取整
			v1 = parseInt(v1)
			v2 = parseInt(v2)
			v3 = parseInt(v3)
			
			var max = v1 > v2 ? v1 : v2;
			max = v3 > max ? v3 : max
			alert(max)
			
		}
	</script>
</html>
2.3.5.5 分支语句

if-else结构

if(布尔类型条件真/0数字/非空字符串/null){

}else{

}

if(布尔类型条件真/0数字/非空字符串/null){

}else if(布尔类型条件真/0数字/非空字符串/null){

}...
else{

}

案例:

<script>
			var a = 2;
			if(a){
				alert("执行if") //执行if
			}else{
				alert("执行else")
			}
</script>

switch结构

switch(变量){
    case : 语句 ; break;
    case : 语句 ; break;
    case : 语句 ; break;
        
    default: 语句;
  }

注意:

没有类型要求

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		输入交通灯:
		<!-- <input type="text" id="light"> -->
		<select name="" id="light">
			<option value="红灯">红灯</option>
			<option value="绿灯">绿灯</option>
			<option value="黄灯">黄灯</option>
		</select>
		<button onclick="check(light.value)">检测</button>
	</body>
	
	<script>
		function check(v){
			switch(v){
				case "红灯" : alert("红灯停"); break;
				case "绿灯" : alert("绿灯行"); break;
				case "黄灯" : alert("缓行"); break;
				default : alert("灯错误")
			}
		}
	</script>
</html>
2.3.5.6 循环语句
for/while/do-while 语法规则同JAVA
//视力表  EEEE
for(var i = 1; i <= 6 ;i ++){
	document.write("<h"+ i + ">EEEE</h" + i + ">")
}

练习: 打印九九乘法表

<script>
			document.write("<table width='800' align='center'>")
			for(var i = 1;i <= 9; i ++){
				document.write("<tr>")
				for(var j = 1;j <= i ; j ++){
					document.write("<td>"+ j + "*" + i + "=" + j * i + "</td>")
				}
				document.write("</tr>")
			}

			document.write("</table>")
</script>
2.3.5.7 循环跳出
continue	跳过本次,执行下一个
break		跳出本层循环
return		跳出当前函数 function xx(){}
function js(v1,v2,v3){
			//判断
			if(v1 == '' || v2 == '' || v3 == ''){
				alert("不能为空");
				return ;
			}			
}

2.3.6 函数

函数概念: 封装实现了特定功能和任务的代码块。

2.3.6.1 函数的定义
function 函数名 ([参数变量名,参数变量名2 ...]){
	函数体;
	[return 返回值;]
}
<script>
		//声明
		function sum(a,b,c){
			return a + b + c;
		}
		
		//调用
		alert(sum(1,2,3))
</script>
2.3.6.2 函数的调用
function max(a,b){
	return a > b ? a : b;
			
}
//1.脚本中直接调用 : 有形参,传入实参 ; 有返回值,接收返回值
alert("最大值:" + max(2,5))
//2. 函数变量化:将匿名函数赋值给变量
var 变量名 = function(参数){
	
}
变量名(实参);
//3.页面实现事件触发函数调用
<button onclick="alert(max(2,3))">
			点击
</button>

2.3.7 数组

数组对象属于特殊的对象,存储多个元素的。比如多个按钮,多个整数,多个文本,多张图片…

前端的数组 [增删改查的]== 后端的集合

2.3.7.1 数组的声明
var 数组名  = [元素1,元素2 ....];
2.3.7.2 数组的使用
//1. 下标  0 ~ a.length - 1
//2. 元素 a[下标]
//3. 遍历数组

for (var i = 0; i < a.length; i++) {
		document.write(a[i] + "<br>")
}
//增强for i还是下标
for (var i in a) {
		document.write(a[i] + "<br>")
}
2.3.7.3 数组的应用
//求和
//平均值
//最值
//排序
//查找
//去重复
...

案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script>
			var a = [12,56,67,34,89,6,99]
			//alert(a[1])
			// for (var i = 0; i < a.length; i++) {
			// 	document.write(a[i] + "<br>")
			// }
			
			// for (var i in a) {
			// 	document.write(a[i] + "<br>")
			// }
			function find(tx){
				tx = parseInt(tx)
				
				for (var i = 0; i < a.length; i++) {
					if(a[i] == tx){
						alert("找到啦")
						return ;
					}
				}			
				alert("没有")
			}
		</script>
	</head>
	<body>
		请输入查询数字:
		<input type="text" id="tx">
		<button onclick="find(tx.value)">check</button>
	</body>
</html>

2.3.8 对象

一切皆为对象,【基于对象语言】。对象是根源。如: 一个变量,网页上一个按钮,浏览器都是对象…

对象分类:

1. 浏览器对象 window,document ,网页上的按钮.... 
2. 内置11个对象 【Math , String , Array ,Date ,RegExp ....】
3. 自定义对象 
		普通对象
		【JSON格式】
		原型对象【类】 Student Teacher 

自定义对象:

var 对象名 = {
	属性 :, 
    属性 : 值,
    方法名 : function(参数){
        
    }
}
<script>
			var obj = {
				"name" : "全儿",
				"age" : 20,
				"eat" : function(){
					alert(this.name + "吃铁锅炖")
				}
			}
			
			alert(obj.name + "," + obj.age)
			obj.eat()
</script>
2.3.8.1 内置对象

11个内置对象,JS已经定义好的对象,对象包含属性/方法,直接使用的。

内置对象【原型对象】含义
Math操作数学
String操作字母串
Date操作日期
Array操作数组
RegExp正则表达式
Number数字
Boolean布尔
Object对象
Function函数
Error错误
Global全局对象

1.全局对象Global

typeof(a); //判断变量是何种数据类型
isNaN(a); //判断变量是否不是数字
parseInt(a); //类型转换
parseFloat(a);

//获得串内的计算结果
eval();

var str = "2 + 3";
alert(eval(str)); // 5

2.Math / String 【同JAVA】

Math:
属性: Math.PI
方法:
random();
ceil();
floor();
round();
sqrt();



String:
var 变量 = "";
var 变量 = '';
var 变量 =  new String("");

属性:
字符串.length
方法:
String.fromCharCode(数字); 将数字按照Unicode转化字符
charAt(下标)
substring(0,5)
substr(下标,截取个数)

indexOf()
lastIndexOf()

split()

案例:

<script>
			document.write(Math.round(2.67) + "<br>")
			document.write(Math.ceil(2.67) + "<br>")
			document.write(Math.floor(2.67) + "<br>")
			document.write(Math.sqrt(25) + "<br>")
			document.write(Math.pow(2,4) + "<br>")
</script>


<body>
		<span id="span">????</span>
		<button onclick="code()">
			获取验证码
		</button>
</body>
	
	<script>
		function code(){
			//获得span
			var span = document.getElementById('span')
			//A -Z  65 -90
			var c1 = parseInt((90 - 65 + 1) * Math.random() + 65)
			var c2 = parseInt((90 - 65 + 1) * Math.random() + 65)
			var c3 = parseInt((90 - 65 + 1) * Math.random() + 65)
			var c4 = parseInt((90 - 65 + 1) * Math.random() + 65)
			
			//将数字转化为字母			
			span.innerHTML = String.fromCharCode(c1,c2,c3,c4)
			
		}
</script>

去重复:

<script>
		function code(){
			var arr = [];
			//获得span
			var span = document.getElementById('span')
			//A -Z  65 -90
			for (var i = 1; i <= 4; i++) {
				var c = parseInt((90 - 65 + 1) * Math.random() + 65);
				var f = true;
				//判断是否有重复的
				for(var j = 0 ;j < i;j ++){
					if(c == arr[j]){
						i --;
						f = false;
						break;
					}
				}
				if(f){
					//添加到数组
					arr.push(c)
				}								
			}
			//将数字转化为字母			
			span.innerHTML = String.fromCharCode(arr[0],arr[1],arr[2],arr[3])
			
		}
</script>

String 案例:

	function hide(v){
				//截取法
				//var index = v.lastIndexOf(".");
				//alert(v.substring(0,index) + ".*")
				
				//分割法
				var arr = v.split(".");
				arr[arr.length - 1] = "*"
				alert(arr.join("."));
	}

3.Date 日期

var 日期 = new Date(); // 系统当前时间

方法:
getXX(); // ....
setXX(); // ....

getTimes(); //获取时间差 毫秒单位
<script>
			var date = new Date();
			date.setFullYear(2001)
			date.setMonth(11)
			date.setDate(31)
			
			alert(date.toLocaleDateString())
</script>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		
	</head>
	<body>
		<input type="date" id="date">
	</body>
	
	<script>
		var date = new Date();
		//
		//alert(date.getFullYear() +"-" + (date.getMonth() + 1 ) + "-" + date.getDate())
		var d = document.getElementById('date');
		var m = "",day = ""
		if(date.getMonth() + 1 < 10){
			m = "0" + (date.getMonth() + 1)
		}else{
			m =  (date.getMonth() + 1)
		}
		
		if(date.getDate() < 10){
			day = "0" + (date.getDate())
		}else{
			day =  date.getDate()
		}
		d.value = date.getFullYear() +"-" + m + "-" + day
	</script>
</html>

4.数组Array

var 数组名 = [];  //字面量
var 数组名 = new Array(元素1,元素2...); //对象new 创建

方法:
//排序 翻转
reverse() 元素翻转
sort()  默认按照字符串字典顺序
sort(px); px 比较函数
function px(a,b){
		return a - b ;
}
join(连接符) 将数组元素链接成字符串

//数组操作: 增删
push(元素1,元素2....); 将元素添加到数组尾部
pop() 尾部删除一个元素

unshift(元素1,元素2....) 首端添加
shift()  首端移除

//中间位置【增加/删除/修改】
splice(起始下标,【删除个数】【,添加元素1,添加元素2...)

splice(起始下标,删除个数) 删除元素

splice(起始下标,0,添加元素) 插入元素

splice(起始下标,1,添加元素) 修改元素

案例:

<script>
			var a = [12,456,34,88,48,94];
			
			document.write(a + "<br>")
			//删除
			//a.splice(1,1)
			//增加
			a.splice(1,0,888,999,1000)
			//修改一个
			//a[1] = 999
			//修改多个
			//a.splice(1,1,999,888)
			document.write(a)
</script>

5.正则对象 RegExp

var 正则对象 = /^$/gi;
var 正则对象 = new RegExp("^$","gi")

g 全局匹配
i 忽略大小写

方法:
test(字符串) true/false 检测内容是否符合正则

案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		username:<input type="text" id="username"> <span>*用户名字母数字构成【6-10位】</span>
		<input type="button" value="提交" onclick="ck(username.value)" >
	</body>
	
	<script>
		function ck(name){
			//空
			if(name == ""){
				alert("用户名不能为空")
				return 
			}
			//正则
			var reg = /^[a-z0-9]{6,10}$/i;
			if(!reg.test(name)){
				alert("用户名格式错误")
				return 
			}
			
			alert("账户名可用");
		}
	</script>
</html>
2.3.8.2 浏览器对象

浏览器上任何元素都是对象,包括浏览器本身。

当打开浏览器的时候,JS自动构建对象 : window对象
window对象:
 			document对象
            history 对象
            location 对象
            screen 对象
            navigator对象 
            
注意: 这些对象都是自动创建

BOM 模型【Browser Object Model】 浏览器对象模型 【window对象】

在这里插入图片描述

DOM 模型【Document Object Model】 文档对象模型 【document对象】

在这里插入图片描述

document对象:文档对象

//创建  自动创建,window.省略的
//window.document.write("");
document.write("");


//属性
document.title  文档标题
document.bgColor 文档背景色
document.cookie  文档缓存
//...

//方法

//文档打印
window.document.write("");

案例:

省份:
		<select name="" id="">
			<option value="">请选择省份</option>
			<script>
				for(var i= 0; i< pro.length;i ++ ){
					document.write("<option>"+pro[i]+"</option>")
				}
			</script>
		</select>

document 获得网页上元素对象【重点】

方法含义返回值
getElementById(“元素的id属性”)通过元素的id属性获得一个元素一个对象
getElementsByTagName(“标签名”)通过标记名获得一组元素对象数组
getElementsByName(“name属性”)通过元素的name属性获得一组元素对象数组
getElementsByClassName(“class属性”)通过元素的class属性获得一组元素对象数组

案例:

<span id="s1">
			
</span>

window.onload = function(){
	var span = document.getElementById('s1')
	span.innerHTML = new Date().toLocaleTimeString()
}
<body>
		<button>btn1</button><button>btn2</button><button>btn3</button>
		<span>
			1
		</span>
	</body>
	
	<script>
		// var btns = document.getElementsByTagName('button');
		// for(var i = 0; i < btns.length ;i ++){
		// 	alert(btns[i].innerHTML)
		// }
		
		var span = document.getElementsByTagName('span');
		alert(span[0].innerText)
	</script>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<input type="text" id="t1">
		+
		<input type="text" id="t2">
		=
		<span>
			?
		</span>
		<button onclick="cal()">
			计算
		</button>
	</body>
	
	<script>
		function cal(){
			var t1 = document.getElementById('t1')
			var t2 = document.getElementById('t2')
			var span = document.getElementsByTagName("span")[0];
			if(t1.value == '' || t2.value == ''){
				alert("不能为空")
				return
			}
			if(isNaN(t1.value) || isNaN(t2.value)){
				alert("必须是数字")
				return
			}
			span.innerHTML = parseFloat(t1.value) + parseFloat(t2.value)
		}
		
	</script>
</html>

案例1:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<input type="radio" name="gender" value="帅哥" checked id="boy"><input type="radio" name='gender' value="美女" id="girl"><button onclick="ck()">
			check
		</button>
	</body>
	
	<script>
		function ck(){
			var genders = document.getElementsByName('gender')
			for (var i = 0; i < genders.length; i++) {
				if(genders[i].checked){
					alert("您好" + genders[i].value)
				}
			}
		}
	</script>
</html>

案例2:

<script>
		
		function guess(){
			var num = parseInt(10 * Math.random() + 1);
			var g = document.getElementsByName('g')
			
			for (var i = 0; i < g.length; i++) {
				if(g[i].checked){
					if(g[i].value == 'big' && (num >= 6 && num <= 10)){
						alert('猜中' + num)					
						return ;
					}
					else if(g[i].value == 'small' && (num >= 1 && num <= 5)){
						alert('猜中' + num)
						return ;
					}
				}			
			}
			
			alert('没猜中' + num)
			
		}
	</script>

共同作用:

	<body>
		<div id="d1">
			<p class="pp">1</p>
			<p>2</p>
			<p class="pp">3</p>
		</div>
		
		<p>4</p>
		<p class="pp">5</p>
	</body>
	
	<script>
		//var p = document.getElementById('d1').getElementsByTagName('p')
		//alert(p.length)
		
		var p = document.getElementsByClassName('pp');
		
	</script>

元素操作:

1. 操作元素的文本  innerHTML(识别标记)  innerText(文本)   【div / span / p / button 】
2. 操作表单
				 value 表单的值
				 checked 单选/复选
3.操作元素事件动作
				
4.操作元素样式	
				style.xxx

案例1:多选(全选)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h2>购物清单</h2>
		<hr>
		<input type="checkbox" id="all" onclick="al()"> 全选
		<input type="checkbox" name="kh"> YSL
		<input type="checkbox" name="kh"> DIOR
		<input type="checkbox" name="kh"> TF
		<input type="checkbox" name="kh"> MAC
		
		
	</body>
	
	<script>
		function al(){
			var all = document.getElementById('all')
			var kh = document.getElementsByName("kh")
			
			// if(all.checked){
			// 	for (var i = 0; i < kh.length; i++) {
			// 		kh[i].checked = true
			// 	}
			// }else{
			// 	for (var i = 0; i < kh.length; i++) {
			// 		kh[i].checked = false
			// 	}
			// }
			
			for (var i = 0; i < kh.length; i++) {
				kh[i].checked = all.checked
			}
			
		}
	</script>
</html>

案例2:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h2>购物清单</h2>
		<hr>
		<input type="checkbox" id="all" onclick="al()"> 全选
		<input type="checkbox" name="kh" onclick="ck()"> YSL
		<input type="checkbox" name="kh" onclick="ck()"> DIOR
		<input type="checkbox" name="kh" onclick="ck()"> TF
		<input type="checkbox" name="kh" onclick="ck()"> MAC
		
		
	</body>
	
	<script>
		var all = document.getElementById('all')
		var kh = document.getElementsByName("kh")
		function al(){

			// if(all.checked){
			// 	for (var i = 0; i < kh.length; i++) {
			// 		kh[i].checked = true
			// 	}
			// }else{
			// 	for (var i = 0; i < kh.length; i++) {
			// 		kh[i].checked = false
			// 	}
			// }
			
			for (var i = 0; i < kh.length; i++) {
				kh[i].checked = all.checked
			}
			
		}
		
		function ck(){
			//统计后面选择个数
			var count = 0;
			for (var i = 0; i < kh.length; i++) {
				if(kh[i].checked){
					count ++;
				}
			}
			if(count == kh.length){
				all.checked = true
			}else{
				all.checked = false
			}
		}
		
		
		
	</script>
</html>

案例3:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h2>购物清单</h2>
		<hr>
		<input type="checkbox" id="all""> 全选
		<input type="checkbox" name="kh" > YSL
		<input type="checkbox" name="kh" > DIOR
		<input type="checkbox" name="kh" > TF
		<input type="checkbox" name="kh"> MAC
		
		
	</body>
	
	<script>
		var all = document.getElementById('all')
		var kh = document.getElementsByName("kh")
		
		
		all.onclick = function(){
				for (var i = 0; i < kh.length; i++) {
					kh[i].checked = all.checked
				}
		}
		for (var i = 0; i < kh.length; i++) {
			kh[i].onclick = function(){
				// 	//统计后面选择个数
					var count = 0;
					for (var i = 0; i < kh.length; i++) {
						if(kh[i].checked){
							count ++;
						}
					}
					if(count == kh.length){
						all.checked = true
					}else{
						all.checked = false
					}
			}
			
		}
		
	</script>
</html>

事件操作:

1. 事件源  事件源头,事件绑定的元素,如点击按钮,按钮就是事件源
2. 绑定事件
		 <button onxxx="事件函数()" >   function 函数(){}
		
		事件源.onxxx = function(){
		 	//回调函数
		 }
3. 事件类型
		三类
        鼠标事件 
            点击 onclick  
            双击 ondblclick    
            移入 onmouseover
            移出 onmouseout
            滑动 onmousedown  onmousemove onmouseup
            拖拽 ondrag 【html5】
        键盘事件 
        	按下 onkeydown
            弹起 onkeyup
        状态事件 
        	加载 	 window.onload
            改变   window.onresize
            滚动   window.onscroll
            表单提交 	onsubmit  【表单】
            获得失去焦点 onfocus onblur  【输入框】
            表单改变    onchange 【下拉菜单,数字框】
        
        
4. 事件对象
		e 记录事件相关信息
        this 当前被触发的对象

单击:

var all = document.getElementById('all')
all.onclick = function(){
			for (var i = 0; i < kh.length; i++) {
				kh[i].checked = all.checked
			}
}

双击:

<script>
		var d = document.getElementById('d')
		d.ondblclick = function(){
			d.style.width = '400px'
			d.style.height = '400px'
			d.style.borderRadius = '200px'
		}
		
</script>

移入移出事件:

<script>
		var data = ["周杰伦何时出专辑","世界杯多次暴雷","今日股票大涨","汽车车展结束"];
		var main = document.getElementById('main')
		//事件源
		var lis = document.getElementsByTagName('li')
		for (var i = 0; i < lis.length; i++) {
			//事件回调
			lis[i].index = i;
			lis[i].onmouseover = function(){
				main.innerHTML = data[this.index]
			}
		}
</script>

键盘事件:

事件绑定: 绑定在document对象

键盘码 : console.log(e.keyCod

<script>
		
		// document.onkeydown = function(e){
		// 	//console.log("按下键盘")
		// 	//键盘码
		// 	console.log(e.keyCode)
		// }
		
		var tx = document.getElementById('tx')
		var span = document.getElementsByTagName('span')[0]
		tx.onkeyup = calc
		tx.onkeydown = calc
		
		function calc(){
			var len = 120 - tx.value.length
			span.innerHTML = len
		}	
</script>

浏览器状态事件:

事件绑定: 绑定在window对象

<script>
			//加载窗口事件
			window.onload = function(){
				var d1 = document.getElementById('d1')
				d1.innerHTML = "hello"
			}
			//窗口改变
			window.onresize = function(){
				console.log(window.innerHeight)
			}
			//滚动条事件(动态加载,随着滚动条滚动,动态请求后台数据)
			window.onscroll  = function(){
				console.log("滚动监听")
			}
</script>

表单状态事件【重点】

事件绑定: 表单或元素

<script>
			window.onload = function(){
				//获取表单
				var form = document.forms[0]
				var username = form.username
				var tel = form.tel
                // 表单提交事件 事件源是 提交按钮 事件绑定表单上
				form.onsubmit = function(){
					
					if(username.value == '' || tel.value == ''){
						alert('信息不能为空')
						return 
					}
					
				}
    			//输入框焦点事件
				username.onfocus = function(){
					username.style.backgroundColor = "pink"
				}
				//失去焦点
				username.onblur = function(){
					//异步校验 + ajax
					if(username.value == ''){
						alert('信息不能为空')
						return 
					}
					//格式
					
					//内容
					
					username.style.backgroundColor = "green"
				}
    			
			}
 			
</script>

<body>
		<form action="#">
			Username: <br>
			<input type="text" id="username" >
			
			<br><br>
			
			Tel :  <br>
			<input type="text" id="tel" value="" />
			
			<br><br>
			
			<input type="submit">
		</form>
</body>

状态改变事件: 下拉菜单 onchange

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<select name="" id="pro">
			
		</select>
		
		<select name="" id="city">
				
		</select>
	</body>
	
	<script>
		var pros = ["辽宁省","山东省","江苏省","黑龙江省"];
		var citys = [["大连","沈阳","本溪"],["日照","济南","青岛"],["南京","苏州"],["齐齐哈尔"]]
		
		var p = document.getElementById("pro")
		var c = document.getElementById("city")
		p.innerHTML = "<option value=''>请选择省份</option>"
		c.innerHTML = "<option value=''>请选择城市</option>"
		for (var i = 0; i < pros.length; i++) {
			p.innerHTML += "<option value=''>"+pros[i]+"</option>"
		}
		
		p.onchange = function(){
			c.innerHTML = "<option value=''>请选择城市</option>"
			//获得选中元素的下标
			var arr =citys[p.selectedIndex - 1]
			for (var i = 0; i < arr.length; i++) {
				c.innerHTML += "<option value=''>"+arr[i]+"</option>"
			}
			
		}
		
	</script>
</html>

history对象:历史记录对象

方法:
history.back(); //上一页 回退
history.forward(); //下一页 前进
history.go(num) num 任意指定
history.go(0) //刷新网页
history.go(-1) // 回退一页
history.go(1)//下一页 前进
history.go(-2) // 回退2页
history.go(2)//下2页 前进
<script>
		var span = document.getElementsByTagName('span')[0]
		var count = 5;
		window.setInterval(function(){
			if(count == 1){
				history.go(-2)
			}
			span.innerHTML = --count
		},1000)		
</script>

location 对象 : 地址信息对象

//属性,浏览器路径跳转
location.href = "url" // url 前端页面/后端路径

//方法
location.reload() //页面刷新

//url请求路径,路径跳转的同时,传参数
location.href = "success.html?key=value&key=value&key=value" 
<script>
		var form = document.forms[0]
		var username = form.username
		var tel = form.tel
		var button = form.button
		button.onclick = function(){
			
			if(username.value == ''){
				alert("用户名不能为空")
				return 
			}
			if(!/^\d{11}$/.test(tel.value)){
				alert("手机号不合法")
				return 
			}
			alert("注册成功")
			//正确的
			//location.href = "success.html?username=" + username.value
			//客户端缓存【会话缓存】
			sessionStorage.setItem("username",username.value)
			location.href = "success.html"
		}
		
</script>

<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		注册成功 ,欢迎你 <span id="s"></span>
		
	</body>
	
	<script>
		//var url = location.href
		//var index = url.indexOf("?")
		//var str = url.substring(index + 1)
		var span = document.getElementById('s')
		//span.innerHTML = (str.split("=")[1])
		span.innerHTML = sessionStorage.getItem("username")
	</script>
</html>

window对象,浏览器窗口对象

//属性
document , history , location

//方法
// 弹出对话框
window.alert("");//提示框
window.prompt(""); //接收框
window.confirm(""); //确认框 返回值布尔

// 定时器
//周期性定时器【每隔一定时间间隔,调用方法】
定时器 = window.setInterval(函数,毫秒时间间隔)//定时器
clearInterval(定时器) //取消定时器


//定时器应用
1. 动态时钟
2. 倒计时
3. 秒杀
4. 滚动文字
5. 滚屏阅读
6. 幻灯片,轮播
7. 定时关闭
8. 小游戏
.....


//一次性定时器
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<table width='800' align="center" border="1">
			<tr>
				<th>学号</th>
				<th>姓名</th>
				<th>操作</th>
			</tr>
			<tr>
				<td>1</td>
				<td>全额</td>
				<td>
					<button class="del">
						删除信息
					</button>
					<button>
						修改信息
					</button>
				</td>
			</tr>
			<tr>
				<td>2</td>
				<td>小盖</td>
				<td>
					<button class="del">
						删除信息
					</button>
					<button>
						修改信息
					</button>
				</td>
			</tr>
		</table>
		<script>
			var dels = document.getElementsByClassName('del')
			for (var i = 0; i < dels.length; i++) {
				dels[i].onclick = function(){
					//确认框
					if(window.confirm("是否确认删除?")){
						//提示框
						window.alert("删除成功")
					}
				}
			}
		</script>
	</body>
</html>

定时器应用:

	<body>
		<span id='s'>
			
		</span>
	</body>
	<script>
		// var count = 1;
		// function test(){
		// 	console.log(count ++)
		// }
		
		//定时器
		//window.setInterval(test,1000)
		
		var span = document.getElementById('s');
		var date = new Date();
		span.innerHTML = date.toLocaleTimeString()
		
		
		window.setInterval(function(){
			var date = new Date();
			span.innerHTML = date.toLocaleTimeString()
		},1000)
	</script>
2.3.8.3 JSON格式对象
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。JS中简易对象。

//更加轻巧和方便

//两种表现形式

1.JSON对象 【前端负责操作使用的对象】
{
    "key":value,
    "key":value
}

复杂的:
1. 属性是数组
{
	"name":"刘桂全",
	"age":21,
	"height":185,
	"nick":["全额","全儿","全全"]
}
2. JSON数组
[{
	"name":"刘桂全",
	"age":21,
	"height":185,
	"nick":["全额","全儿","全全"]
},

{
	"name":"小盖",
	"age":21,
	"height":180,
	"nick":["盖小盖","盖盖"]
}
]

2.JSON字符串【前后端数据传递】

案例:

{
	"name":"刘桂全",
	"age":21,
	"height":185,
	"nick":"全额"
}{
	"name":"刘桂全",
	"age":21,
	"height":185,
	"nick":"全额"
}

JSON 字符串和对象的转化

JSON.parse(JSON字符串)
JSON.stringify(JSON对象)

2.4 jQuery

jQuery是Javascript的代码函数库,目的写更少的代码,实现更多的功能(底层执行JS)。

jQuery目的: 简化Javascript的代码,更加简洁和灵活,方便。

jQuery理解为Javascript的简易框架【不能完全代替JS】,主要致力于【DOM操作】

Bootstrap/LayUI 主要致力于【CSS部分,美化页面】

Vue JS/Angular JS/React JS 主要致力于【数据绑定:对象,数组…】

API:
https://jquery.cuishifeng.cn/

官方下载:
https://jquery.com/download

2.4.1 jQuery的优势

1. DOM 操作元素获取元素 :  类似于CSS的选择器【更多】
2. DOM 元素操作方便 :
					操作表单值,操作属性,操作文本值...
					操作样式
					操作事件
3.DOM文档操作
4.DOM动画效果
5.AJAX
6.丰富插件
....

2.4.2 jQuery的版本

1.x  
2.x  特殊,不支持IE
3.x  


Download the compressed, production jQuery 3.6.1  // 压缩版,适合生产环境,去掉空格,换行注释,abc定义变量
//https://code.jquery.com/jquery-3.6.1.min.js

Download the uncompressed, development jQuery 3.6.1 //非压缩版,适合开发环境,注释,换行,适合程序调试
//https://code.jquery.com/jquery-3.6.1.js

在这里插入图片描述

2.4.3 jQuery的基本使用

需要在页面中引入jQuery库文件

<script src="js/jquery-3.6.1.min.js"></script>

2.4.4 jQuery的语法规则

$("选择器").函数().函数()......

总结:
链式操作,通过选择器将页面上的元素获取【选择器】,将元素进行一系列的操作【动作函数】。jQuery将js中的动作封装成一个个函数。

	$('#btn')
		.click(function(){
			alert("点我干点啥")
		})
		.css('background-color','pink')

加载页面:

//window.onload = function(){}

$(function(){
    //加载页面
    
    
})
//多次加载,简写,加载结果【内容不需要加载】

$符号

//$符号就是jQuery的等价替换
jQuery("选择器").函数();
$("选择器").函数();
1.jQuery 大小写关键,单词长
2.使用符号$等价替换

alert(jQuery == $) // true
alert(jQuery === $) // true


//冲突
jQuery.noConflict([ex])

2.4.5 jQuery的选择器

//1. 基本选择器
#id  .class  *  p  ,

//2. 层级选择器
// 后代 子代  兄弟 相邻

//3. 筛选选择器
	//1 按照位置筛选
	:first 第一个元素	
    :last
    :eq(下标)  筛选第几个
    :even	筛选偶数
	:odd	筛选奇数
    :gt(下标) 大于该下标
    :lt(下标) 小于该元素
    
    //2 按照内容筛选
    :contains(文本) 根据文本内容筛选
	:empty 筛选空元素
    :has(选择器) 筛选包含xx的元素
    //子元素下标
    :first-child  每个子元素第一个
    
//4. 属性选择器
    
    [attribute=value]  属性是xx值
	[attribute!=value] 不是xx值
	[attribute^=value] 以xx开头
    [attribute$=value] 以xx结尾
	[attribute*=value] 包含xx
    
//5. 表单和状态筛选
    :input
    :text
    :password
    :radio
    :checkbox
    :submit
    :image
    :reset
    :button
    :file
    
    //状态筛选
    :checked 选中的
//基本和层级
<script>
	//jQuery 对象数组
	$('li').click(function(){
		alert($(this).text())			
	})		
	$('#l1,a').css('color','red')		
</script>
//位置筛选
<script>
		
		//$('li:first').css('color','red')
		//$('li:last').css('color','blue')
		
		// $('li:even').css('color','red')
		// $('li:odd').css('color','blue')
		
		//$('li:eq(1)').css('color','red')
		
		$('li:gt(3)').css('color','red')
		
</script>
//内容筛选
<script>
		
		//$('div:contains(于老师)').css('color','hotpink')
		//$('div:empty').width(300).height(300).css('background-color','pink')
		
		$('div:has(a)').css('color','hotpink')
</script>


//first-child
<script>
		//$('li:first').css('color','hotpink')	
		$('ul li:first-child').css('color','hotpink')	
</script>


//属性
<script>
		//jpg图
		$('img[src$=jpg]').width(200).height(200)
		$('img[src$=png]').width(400).height(400).css('border-radius','200px')
		
		$('input[type=text]').width(400)
</script>

表单选择:

	<body>
		<input type="checkbox"> 全选
		<input type="checkbox"> YSL
		<input type="checkbox"> TF
		<input type="checkbox"> DIOR
		<input type="checkbox"> MAC
	</body>
	
	<script src="js/jquery-3.6.1.js"></script>
	<script>
		$(':checkbox:first').click(function(){
			$(':checkbox:gt(0)').prop('checked',$(':checkbox:first').prop('checked'))
		})
		
		$(':checkbox:gt(0)').click(function(){		
			//获得选中的个数
			var count = $(':checkbox:gt(0):checked').length
			var len = $(':checkbox:gt(0)').length
			if(count == len){
				$(':checkbox:first').prop('checked',true)
			}else{
				$(':checkbox:first').prop('checked',false)
			}
		})
		
	</script>

2.4.6 jQuery和JS互相转化

// jQuery对象不能把调用JS中属性, JS对象不能使用jQuery中函数

//1 JS对象转化为JQ
$(JS对象)

$(this) 
$(document)
$(window)

$(document).click(function(){
		alert("点击文档")
})

//2. JQ对象转化为JS对象

1- JQ对象 $(对象).get(0)

$(':checkbox:first').get(0).checked

2- JQ对象数组  $(对象).get(下标) 必须遍历

$('a').click(function(){
			for (var i = 1; i <= $(':checkbox:gt(0)').length; i++) {
				var ck = $(':checkbox:eq('+i+')').get(0)
				ck.checked = !ck.checked;
			}			
})

2.4.7 jQuery的函数库

1 操作属性

$(选择器).attr("属性","值")//修改属性的值
$(选择器).prop("属性","值") //修改属性的值

$(选择器).attr("属性")//获得属性的值
$(选择器).prop("属性") //获得属性的值
<body>
		<input type="checkbox"> 全选
		<input type="checkbox"> YSL
		<input type="checkbox"> TF
		<input type="checkbox"> DIOR
		<input type="checkbox"> MAC
	</body>
	
	<script src="js/jquery-3.6.1.js"></script>
	<script>
		$(':checkbox:first').click(function(){
			$(':checkbox:gt(0)').prop('checked',$(this).prop('checked'))
		})
		
	</script>
2 操作表单/文本值

html([val|fn])  操作文本的值   innerHTML 
text([val|fn])				 innerText
val([val|fn|arr])操作表单值	  value


html() text() val()  获取值
html() text() val()  设置文本值
html(函数) text(函数) val(函数) 
	<body>
		<input type="text">
		+
		<input type="text">
		=
		<span>?</span>
		<button>计算</button>
	</body>
	<script src="js/jquery-3.6.1.js"></script>
	<script>
		$('button').click(function(){
			$('span').text($(':text:first').val() - 0 + ($(':text:last').val() - 0))
		})
	</script>

案例2:

<script>
			$(function(){
				$('button:last').click(function(){
					//$(":text").val($(":text").val() - 0 + 1) 
					
					$(':text').val(function(i,v){
						return v - 0 + 1;
					})
					
					$('#total').text($('span:first').text()  * $(":text").val() )
				})
				
				$('button:first').click(function(){
					//$(":text").val($(":text").val() -  1) 
					
					$(':text').val(function(i,v){
						if(v == 1){
							alert("不能减少啦")
							return 1;
						}
						return v - 1;
					})
					
					$('#total').text($('span:first').text()  * $(":text").val() )
				})
			})
</script>
3.查找元素

children([expr]) 获得子元素
closest(e|o|e)1.7*
find(e|o|e)
next([expr])  获取当前元素后面的
nextAll([expr])
nextUntil([e|e][,f])
offsetParent()
parent([expr]) 获得父元素
parents([expr])
parentsUntil([e|e][,f])
prev([expr])  获得当前元素前面的
prevAll([expr])
prevUntil([e|e][,f])
siblings([expr]) 
4. 文档操作(DOM节点增加和删除)

//删除
父元素.empty();  //清空父元素中所有子元素
元素.remove(); //删除当前元素

//添加

1.内部插入
	父元素.append(子元素)  父元素内部尾部添加子元素
    父元素.prepend(子元素)  父元素内部首端添加子元素
    
    
2.外部插入
	A元素.after(B元素)  A元素后面添加B元素
    A元素.before(B元素)  A元素前面添加B元素
<script>
		var count = 0;
		$('button').click(function(){
			
			if(count == 5){
				alert("不能超过五人");
				return
			}else{
				$('div').append("<p>姓名: <input type='text'> 电话<input type='text'><a href='#'>删除</a></p>")
				count ++;				
			}
		})
		
		//事件委托: a后续添加到网页,委托a的父元素帮助注册事件
		//a如果后续添加到网页上
		$('div').on('click','a',function(){
			count --;
			$(this).parent().remove()	
		})
</script>
5.筛选函数【在选择器选出来进一步筛选】

eq(index|-index)
first()
last()
hasClass(class)
filter(expr|obj|ele|fn)
is(expr|obj|ele|fn)
map(callback)
has(expr|ele)
not(expr|ele|fn)
slice(start,[end]) 获得一部分

案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<ul>
			<li>这是li1</li>
			<li>这是li2</li>
			<li>这是li3</li>
			<li>这是li4</li>
			<li>这是li5</li>
			<li>这是li6</li>
			<li>这是li7</li>
			<li>这是li8</li>
			<li>这是li9</li>
			
		</ul>
		<a href="">商家1</a>
		<a href="" class="del">删除</a>
		<a href="" class="del">删除</a>
		<a href="" >商家2</a>
		<a href="" class="del">删除</a>
	</body>
	<script src="js/jquery-3.6.1.js"></script>
	<script>
		
		//$('li').first().css('color','red')
		//$('li').last().css('color','blue')
		//$('li').eq(2).css('color','deeppink')
		//$('li').slice(0,3).css('color','deeppink')
		$('a').click(function(){
			//判断
			if($(this).hasClass('del')){
				alert("删除按钮")
			}
		})
	</script>
</html>
6. 元素样式操作

	1.直接操作某个样式
	$().css(样式属性,值) //设置样式的值
	$().css(样式属性) //获取某个样式的值
	$().css({key:value,key:value}) //设置多个样式
	
	2.操作样式类
	.show{
		/*css任意定义*/
	}
	addClass(class|fn)
	removeClass([class|fn])
	toggleClass(class|fn[,sw])
	
	3. 直接操作元素宽高,元素的位置
	好处: 可直接数值
	height()
	width()
	
	4. 直接操作位置
	scrollTop() 滚动条上方间距

案例1:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			div{
				width: 200px;
				height: 200px;
				background-color: hotpink;
				/* 过渡 */
				transition:all 2s;
			}
			
		</style>
	</head>
	<body>
		<div>
			
		</div>
		<button>
			点击查看
		</button>
	</body>
	
	<script src="js/jquery-3.6.1.js"></script>
	<script>
		$('button').click(function(){
			
			//修改一个样式
			//$('div').css('background-color','lightblue')
			
			//修改多个
			$('div').css({
				"width":"300px",
				"height":"300px",
				"background-color":'lightblue'
			})
		})
	</script>
</html>

案例2:

<script>
		$('button').click(function(){
			// $('div').css('display','none')
			var div = $(this).next().next()
			// div.css('display','block')
			div.toggleClass('show')
		})
		
</script>

案例3:

<script>
		$('div').dblclick(function(){
			//$('div')
			// .css('width','300px')
			// .css('height','300px')
			
			//.css('background-color','pink')
			
			
			//.width(300)
			//.height(300)
			//$('div').width($('div').width() + 50)
			//$('div').height($('div').height() + 50)
			
			$('div').width("+=50")
			$('div').height("+=50")
		})
</script>

案例4:

<script>
		//滚动条事件
		$(window).scroll(function(){
			
			if($(window).height() + $(document).scrollTop() - 0 + 1>= $(document).height()){
				alert("到底了")
			}
		})
</script>
7.元素动画【显示和隐藏】

	1. 显示隐藏【过渡 display】
	show(速度) hide() toggle()
	2. 滑动特效【上下卷帘 height】
	slideUp() slideDown()  slideToggle()
	3. 渐入渐出【逐渐变化 opacity】
	fadeIn() fadeOut()...
8. 事件处理

	1.简单的事件注册【常用的事件被封装成事件函数】
	
	$(元素).事件函数(function(事件对象){
			//回调函数
	})
	
            事件过程:
            1. 事件源
            2. 事件类型 
                    鼠标 click()  dblclick()  mouseover()  mouseout()
                    键盘 keyup() keydown()
                    表单 change() focus() blur() submit()
                    窗口加载
                    $(document).ready(function(){

                    })
                    $(function(){

                    })
            3. 事件类型绑定到事件源【事件注册】
            4. 事件对象记录事件发生中数据
	2.事件委托【元素是后续增加DOM上,不能直接绑定事件函数】
	on() 的用法: 注册事件,实现委托,注册不存在事件函数的事件类型【右击,input 实时接收, drag 】
	one() 注册事件【只能一次】
	off() 取消事件注册
	
	//注册新型事件
	$(元素).on('事件类型',function(){
	
		
	})
	
	//委托
	$(父元素).on('事件类型',"委托人子元素",function(){
	
		
	})
	$(document).on('contextmenu',function(e){
			//取消默认行为
			e.preventDefault()
			alert("右击事件")
		})
	$('div').on('click','a',function(){
			
	})

案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
				list-style-type: none;
			}
			#con{
				width: 800px;
				margin: 30px auto;
			}
			li{
				float: left;
				width: 180px;
				height: 40px;
				background-color: pink;
				margin-right: 10px;
				text-align: center;
				line-height: 40px;
				color: aliceblue;
				border-radius: 5px;
			}
			#con #main{
				width: 700px;
				height: 450px;
				border: solid 2px lightblue ;
				margin: 20px;
			}
			.high{
				background-color: lightblue;
				color: pink;
			}
		</style>
	</head>
	<body>
		<div id="con">
			<ul>
				<li>音乐</li>
				<li>体育</li>
				<li>财经</li>
				<li>汽车</li>
			</ul>
			<div style="clear: both;"></div>
			<div id="main">
				
			</div>
		</div>
	</body>
	<script src="js/jquery-3.6.1.js"></script>
	<script>
		var data = ["周杰伦何时出专辑","世界杯多次暴雷","今日股票大涨","汽车车展结束"];
		$('li').mouseover(function(){
			$('#main').text(data[$(this).index()])
			//$("li").css('background-color','pink').css('color','white')
			//$(this).css('background-color','lightblue').css('color','pink')
			$('li').removeClass('high')
			$(this).addClass('high')
		})

	</script>
</html>
$(document).keydown(function(e){
		console.log(e.keyCode)
})
9.核心函数
length() 对象个数
index(选择器) 下标
	get(下标) jq对象转化js对象
    each(function(){
    
    }) jq循环遍历

//反选
		$('a').click(function(){
			// for (var i = 1; i <= $(':checkbox:gt(0)').length; i++) {
			// 	var ck = $(':checkbox:eq('+i+')').get(0)
			// 	ck.checked = !ck.checked;
			// }
			
			$(':checkbox:gt(0)').each(function(i,v){
				//v js对象
				v.checked = !v.checked
			})	
						
		})


10.AJAX【服务器】

2.5 Bootstrap

客户端的样式框架,致力于网页的样式效果。

Bootstrap中文网 (bootcss.com)

作用: 使得web开发更加简单,明了。

特点:

  1. 扁平化设计的样式框架【去除冗余、厚重和繁杂的装饰效果】
  2. 响应式前端框架 【自适应不同的设备,完成网页适应设备】
  3. 动态效果【插件】,调制好的组件,成型的样式...

2.5.1 Bootstrap版本

v2.0  旧版本【老的项目引用】

v3.0  

v4.0 设备更新

v5.0 新版

下载:

bootstrap-3.4.1-dist
	css		和样式有关的文件  
	fonts	字体图标,基于css里面文件
	js		bootstrap插件【动态特效】
	
	
bootstrap脚本都是使用jQuery实现的,使用脚本的前提条件,先引入jQuery。

在这里插入图片描述

2.5.2 Bootstrap样式

1.容器

	<div class="container"></div>  定宽,自适应,居中
	
	<div class="container-fluid"></div> 100%宽度
	
2.内容【响应式】
	
	<div class="row"></div> 行
	列: 栅格系统,将所有设备宽度等分  12列,分配
	.col-xs-手机	.col-sm-平板	.col-md- 小PC	.col-lg- 大PC
	
	.col-lg-num  num 1-12之间
	
	
	
3. 表格
	.table
	.table-bordered 边框
	.table-striped 条纹
	.table-hover
	
	色调: .active  .danger .info .success .warnning
	
4.表单
	<div class="form-group">
	<input type="text" placeholder="请输入学生姓名" class="form-control">
	<button type="button" class="btn btn-primary">(首选项)Primary</button>
	<form action="" class="form-inline"> 横向

2.5.3 Bootstrap组件

1.图标库
	<span class="glyphicon glyphicon-trash"></span>
2.下拉菜单
<div class="dropdown">
				  <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
				    城市
				    <span class="caret"></span>
				  </button>
				  <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
				    <li><a href="#">本溪</a></li>
				    <li><a href="#">大连</a></li>
				    <li><a href="#">沈阳</a></li>
				    <li role="separator" class="divider"></li>
				    <li><a href="#">江苏</a></li>
				  </ul>
				</div>

3.路径导航
<ol class="breadcrumb">
  <li><a href="#">Home</a></li>
  <li><a href="#">Library</a></li>
  <li class="active">Data</li>
</ol>

4. 分页器
<nav aria-label="Page navigation">
			  <ul class="pagination">
			    <li>
			      <a href="#" aria-label="Previous">
			        <span aria-hidden="true">&laquo;</span>
			      </a>
			    </li>
			    <li class="active"><a href="#">1</a></li>
			    <li><a href="#">2</a></li>
			    <li><a href="#">3</a></li>
			    <li><a href="#">4</a></li>
			    <li><a href="#">5</a></li>
			    <li>
			      <a href="#" aria-label="Next">
			        <span aria-hidden="true">&raquo;</span>
			      </a>
			    </li>
			  </ul>
</nav>

5. 进度条
<div class="container">
			<br><br><br><br>
			<div class="progress">
			  <div class="progress-bar progress-bar-success progress-bar-striped" style="width: 0%">
					0%
			  </div>
			</div>
</div>

2.5.4 Bootstrap插件

1. 模态框
2. 轮播
3. 提示框
4. 标签页

2.6 LayUI

Layui - 经典开源模块化前端 UI 框架 (winxapp.cn)

开源模块化前端 UI 框架

2.7 其他样式框架

ElementUI (饿了么团队)

Echart (客户端表格数据)

jQuery UI

3. 数据库开发

Database : 数据库,按照一定的数据结构,有组织的长期存储数据,管理数据的仓库。

好处:

1. 有数据分类
2. 共享性强
3. 数据量大

3.1 数据库的分类

1.关系型数据库【以二维表形式存储】
	Oracle , MySQL ,SqlServer , DB2
	
2.非关系型数据库 【以键值对,哈希表】
	Redis , MongoDB

关系型数据库区分:

数据库特点优点缺点
oracle甲骨文,非开源,大型网络数据库1.安全性高
2.跨平台
3.数据量大
4.并发性
1.成本
2.操作复杂,DBA操作复杂
mysql中小型数据库,开源,灵活,方便1.开源
2.灵活,方便
3.操作简单,数据方便移植
1.并发性弱
2.安全性弱
3.数据存储量弱
sqlsever微软产品,受限操作系统,不能跨平台1.数据量大
2.并发性强
1.不能跨平台
db2IBM,功能强大,细节不足数据操作强大,功能强,金融项目数据库细节不做处理

3.2 数据库相关概念

DB :  database  数据库
DBA : database administer  数据库管理员
DBMS : database Management System 操纵和管理数据库的大型软件
DBS :  database System数据库系统

在这里插入图片描述

3.3 关系型数据库数据存储

3.3.1 关系表基本概念

二维表: 【关系表 > JAVA中对象,一类事物的数据存储】 
	列: 属性 , 字段 ,分量
	行: 记录 , 元组 
	键: 主键【主属性】,最为关键的列,表的唯一标志
	域: 列的取值范围 
	数据类型: 数字  字符串  日期 ...

3.3.2 表的设计

数据表的设计: 数据建模【现实世界 > 概念世界 > 机器世界】

美团系统:

店家  地址 电话 编号 类型...
顾客  手机号 会员 余额 地址...
商品  编号 价格 商家编号 品种...
骑手  
平台

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5cjRSGFE-1672059110709)(pics\8.png)]

现实世界 > 概念世界体现:

E-R 实体关系模型图

实体: 矩形
属性: 椭圆
主属性: 下方横线
连接: 实线
关系: 菱形
	1:1
	1:n  
	m:n

举例: 学生选课

实体: 学生实体   课程实体   
学生属性 : 姓名 学号 班级 
课程属性: 编号  名称 学分

关系: 选课 [m:n]

在这里插入图片描述

概念世界 > 机器世界转化:

转化标准: 数据库设计范式

实体 > 表
关系 > 表
数据库范式:

	1NF: 表的属性不可分割的原子级别
	2NF: 满足1NF,所有的非主属性依赖于主属性
	3NF: 满足2NF,表中不能存在传递依赖

学生表

类型
学号【主键】 sno数字 int
姓名 sname字符串 varchar/char
生日 birth日期 date

课程:

类型
编号 cno整数 int
名称 cname字符串 varchar
学分credit小数 double

选课:

类型
学生编号 sno整数 int
课程编号 cnoint
选课时间日期

3.4 MySQl 数据库

最流行关系型数据库之一,原MySQL AB,被Oracle。

3.4.1 MySQl数据操作

SQL语言: 结构化的查询语言,完成对数据库数据的增删改查操作。

专业说法: 增删改查 CRUD (create read update delete)

建库,建表

1.建库:
在连接上 > 新建数据库  db

2.建表:
3.数据导出: 右键 转储sql文件
4.数据导入: 右键 运行sql文件

3.4.2 SQL语句

结构化的查询语言,完成对数据库数据的增删改查操作。  Structured Query language

分类:
	DQL   数据查询语言  查询
	DML	  数据操作语言  增删改
	DDL	  数据定义语言  建表
	DCL   数据控制语言  权限 
	

3.4.3 DQL

数据库查询语言: 查询表中数据 【查询全部 查单个列 表连接查询 分组查询 子查询】

3.4.3.1 基本查询
-- 这是注释,基本查询
SELECT  * | 列名,列名2... | 表达式 | DISTINCTFROM  表名 ;

示例:

select *
from emp;

注意:

  1. select 和from 两个关键字,推荐大写,表名列名小写
  2. *代表表中的所有列
  3. 空格是分隔符号,每句话结束 ;
  4. 建议每子句换一行

示例:只需姓名 薪资

select ename,sal
from emp;

示例:查询编号,姓名,年薪

select empno,ename,sal*12
from emp;

示例: 员工表几种部门

select distinct deptno
from emp;

为列添加别名(为查询内容提供名字)

SELECT  表达式 AS 别名 
FROM  表名 ;

SELECT  表达式  别名 
FROM  表名 ;

示例:

select empno,ename,sal*12 as 年薪
from emp;

空值问题: 包含空值的任何运算都是空值,空值需要处理的

处理函数: ifnull(空值列,替换值) ; 如果第一个参数是空的,取替换的值,否则取自己

select ename,sal,(sal +ifnull(comm,0)) * 12 年薪
from emp
select ifnull(1,2)
from dual;

-- 1 
-- 空值变成2 1 不是空值
3.4.3.2 条件查询
-- 条件筛选查询
SELECT  * | 列名,列名2... | 表达式 | DISTINCTFROM  表名 
-- 筛选当xx条件的数据
WHERE 条件+ ;

数据类型:

数据类型含义
int整数型
double浮点型
varchar可变字符串 varchar(20) ‘jack’
char定长字符串,char(20) 'jack ’
date/datetime日期

运算符:

运算符应用
算术运算符+ - * / %SELECT 后
WHERE 后
比较运算符> < >= <= = 等于 != <> 不等于WHERE 后
逻辑运算符NOT 非 AND 与 OR 或 【NOT > AND > OR】WHERE 后
特殊的比较运算符WHERE 后
between 值1 and 值2 【包含边界值】 ; not between … and
like ‘’ 【模糊查询,像…样 , _ 占位1个 % 0或多个】; not like
in(值1,值2…) 【只要满足其中一个值,集合】 not in()
is null ; is not null;

总结:

1. 查询数字类型,直接写
2. 字符串,日期使用 ''  ""

-- 查询员工薪资8000以上的员工信息
-- select *
-- from emp
-- where sal > 8000;


-- 查询2022-12-12后之后入职员工年薪(包含奖金)
select ename,hiredate,(sal+ifnull(comm,0)) * 12 年薪
from emp
where hiredate > "2022-12-12"


-- 查询小管的个人信息
select *
from emp
where ename = '小管'


-- 查询10部门员工信息
-- select *
-- from emp
-- where deptno=10;

-- 查询不是20部门的员工信息
-- select *
-- from emp
-- where deptno <> 20;

示例:

-- 查询10部门 且薪资10000以上员工信息

select *
from emp
where deptno=10 and  sal>=8000;


-- 查询10或40部门 且在2022-12-15之后员工信息

select *
from emp
where (deptno=10 or deptno=40 ) and hiredate > '2022-12-15'

between…and …示例:

-- 查询薪资8000-10000员工信息

-- select *
-- from emp
-- where sal between 8000 and 10000;


-- 查询2022-12月份上半月(15前)入职的员工信息
select *
from emp
where hiredate between '2022-12-1' and '2022-12-15';

like用法:

-- 查询名字中包含s字母的员工信息

select *
from emp
where ename like '%s%';


-- 查询名字中首字母是 y


select *
from emp
where ename like 'y%';


-- 查询名字的第二字 管

select *
from emp
where ename like '_管%';

练习:

-- 1. 查询10或40部门中,名字包含s 且薪资5000-10000之间


-- select *
-- from emp
-- where (deptno=10 or deptno=40) and ename like '%s%' and sal between 5000 and 10000;



-- 2. 查询姓 w ,且在2022-11月份入职的员工信息

-- select *
-- from emp
-- where ename like 'w%' and hiredate between '2022-11-1' and  '2022-11-30';

select *
from emp
where ename like 'w%' and hiredate like '2022-11-%';

in:

-- 1. 查询10或40部门中,名字包含s 且薪资5000-10000之间

select *
from emp
where deptno in(10,40) and ename like '%s%' and sal between 5000 and 10000;


-- 技术职员或财务职员员工信息
-- select *
-- from emp
-- where job in('技术职员','财务职员');


-- 查询名字中包含s或包含f的员工信息

select *
from emp
where ename like '%s%' or ename like '%f%'

is null:

-- 查询有奖金的员工信息

select *
from emp
where comm is not null;


-- 查询10或20部门没有员工的员工信息
select *
from emp
where deptno in(10,20) and comm is null;


-- 查询员工表中boss(领导编号是空的)
select *
from emp
where mgr is null;
3.4.3.3 排序
-- 排序
SELECT  * | 列名,列名2... | 表达式 | DISTINCTFROM  表名 
-- 筛选当xx条件的数据
WHERE 条件+ 
ORDER BY1 [DESC|ASC],2  [DESC|ASC]...

注意:

  1. 可以使用多个列排序,列1如果相同,参考第二个
  2. 默认升序【ASC】 , 降序【DESC】
  3. ORDER BY 最后一步
  4. 排序的时候,还可以使用别名排序
-- 查询20部门的员工信息,按照薪资降序排列
select *
from emp
where deptno=20
order by sal desc;

-- 查询名字中包含s的员工信息,按照入职时间升序,同一天入职,按照工资降序

select * 
from emp
where ename like '%s%' 
order by hiredate,sal desc;

-- 查询10或20部门中薪资5000-10000姓名,年薪(奖金),按照年薪降序排列
select ename,(sal+ifnull(comm,0) ) * 12 年薪
from emp
where deptno in(10,20) and sal between 5000 and 10000 
order by 年薪 desc;

3.4.3.4 查询中使用函数

函数: 能够实现一定功能的机制。 y = f(x); 多个x 对应一个y 。函数的参数可以是多个,结果只有一个。

函数的分类:

-- 1. 单行函数 对表中一行数据进行处理,返回一个结果。
	数字函数  round()  truncate() ceil() floor()
	字符串函数 length() substring() instr() 
	日期函数 now() sysdate() year() ...
	转化函数 date_format()  str_to_date()
	通用函数  ifnull() if()  case表达式
	
-- 2. 多行函数 对表中多行数据进行处理,返回一个结果。
	求和函数  sum()
	平均值函数 avg()
	计数函数 count()
	最大值函数 max()
	最小值函数 min()
	
  1. 数字函数 【Math】
函数名作用
round(数字)
round(数字,保留位数) 位数可正 负 0
四舍五入
truncate() 截断【不考虑进位和退位】
mod(a,b)余数 %
ceil() floor()向上向下取整
rand()随机数

示例:

select round(26.679765,-1)
from dual;

-- -3
select round(-2.5)
from dual;

select truncate(2.567,2)
from dual;

-- 1. 查询员工的日薪,按30天 四舍五入 2位

select ename,round(sal / 30,2) 日薪
from emp

​ 2.字符串函数 【String】

函数名作用
length(字符串)获取字符串字节长度
char_length(字符串)考虑字符编码
concat(字符串1,字符串2…)字符串拼接,mysql不可以使用+
substring(字符串,下标,截取长度)字符串截取,下标从1开始
instr(字符串,要查找的串)字符串中查询子串,返回第一次出现位置,不存在返回下标0
replace(字符串,原串,替换串)字符串替换
upper(字符串)大写
lower(字符串)小写
LPAD(字符串,总长度,填充内容)左填充
RPAD()右填充
trim(字符串)去掉左右两侧空格
trim(字符 from 字符串)从字符串的两端去掉某字符
ltrim(字符串)去掉左侧空格
rtrim(字符串)去掉右侧空格
-- 查询员工表名字长度为两个字符

-- select *
-- from emp
-- where length(ename) = 2 or char_length(ename) = 2;

-- select ename,length(ename)
-- from emp;


select concat('abc','ys','hhk')
from dual;
-- 查询员工表信息,查询格式如下: xxx earns ¥ xxx 

select concat(ename,' earns ¥',sal) 信息
from emp;

-- 1. 获得员工表中员工姓氏
-- select substring(ename,1,1) 姓氏,ename
-- from emp;
-- 
-- 2. 查询姓于的,且薪资8000-10000的员工信息

select *
from emp
where substring(ename,1,1) = '于' and sal between 8000 and 10000;

-- 3 查询名字中包含a或s的员工信息
-- select *
-- from emp
-- where ename like '%a%' or ename like '%s%';

select *
from emp
where instr(ename,'a') != 0 or instr(ename,'s') != 0

-- 查询员工表中ys员工信息,忽略大小写
select *
from emp
where upper(ename) = 'YS'


-- 查询员工姓名,右侧填充*[名字的长度]

select ename,rpad(ename,char_length(ename)*2,'*' )
from emp;


-- select concat('xxxx',trim('  wel come  '),'yyyy')
-- from dual;

-- select trim('a' from 'aaahekadsaaa')
-- from dual;

​ 3.日期函数 【Date】

函数名作用
now()获得系统当前时间
sysdate()获得系统当前时间
curdate()系统日期
curtime()系统时间
datediff(日期1,日期2)日期相差天数
year()
month()
day()
adddate(日期,天数)日期增加天数
last_day(日期)返回该日期的最后一条
TIMESTAMPDIFF(类型,开始时间,结束时间)类型: MONTH YEAR …
-- 查询 已经入职的员工来了多少周,不足一周向上取整

-- select ename,ceil(datediff(now(),hiredate) / 7) weeks
-- from emp
-- where hiredate < now()

-- 查询2月入职的员工
-- select *
-- from emp
-- where month(hiredate)=2;

-- 查询下半月入职的员工信息
select *
from emp
where day(hiredate) > 15;

-- 查询5天后入职的员工信息
select *
from emp
where hiredate = adddate(now(),3);


-- 查询每个月倒数第二天入职的员工信息
SELECT *
from emp 
where hiredate = LAST_DAY(hiredate) - 1;

​ 4.转化函数 【SimpleDateFormat】

函数名作用
DATE_FORMAT(date,format)将日期格式化处理
STR_TO_DATE(varchar,format)将字符串变成日期

format:

秒 %S、%s 两位数字形式的秒( 00,01, ..., 59)

分 %I、%i 两位数字形式的分( 00,01, ..., 59)

小时 %H 24小时制,两位数形式小时(00,01, ...,23)

%h 12小时制,两位数形式小时(00,01, ...,12)

%k 24小时制,数形式小时(0,1, ...,23)

%l 12小时制,数形式小时(0,1, ...,12)

%T 24小时制,时间形式(HH:mm:ss)

%r 12小时制,时间形式(hh:mm:ss AM 或 PM)

%p AM上午或PM下午

周 %W 一周中每一天的名称(Sunday,Monday, ...,Saturday)

%a 一周中每一天名称的缩写(Sun,Mon, ...,Sat)

%w 以数字形式标识周(0=Sunday,1=Monday, ...,6=Saturday)

%U 数字表示周数,星期天为周中第一天

%u 数字表示周数,星期一为周中第一天

天 %d 两位数字表示月中天数(01,02, ...,31)

%e 数字表示月中天数(1,2, ...,31)

%D 英文后缀表示月中天数(1st,2nd,3rd ...)

%j 以三位数字表示年中天数(001,002, ...,366)

月 %M 英文月名(January,February, ...,December)

%b 英文缩写月名(Jan,Feb, ...,Dec)

%m 两位数字表示月份(01,02, ...,12)

%c 数字表示月份(1,2, ...,12)

年 %Y 四位数字表示的年份(2015,2016...)

%y 两位数字表示的年份(15,16...)

文字输出 %文字 直接输出文字内容

-- 将系统当前时间显示为 xxxx-xx-xx 星期几 
select DATE_FORMAT(now(),'%Y-%m-%d %W')
from dual;


select DATE_FORMAT(now(),'%Y年%m月%d日 %h:%i:%s %W %p')
from dual;

-- 1949-10-1 距离今天有多少天?
-- select datediff(now(),STR_TO_DATE('1949-10-1','%Y-%m-%d'))
-- from dual;


--假如 12-25 是公司的年会,查询可以参加年会的员工
select *
from emp
where datediff(STR_TO_DATE('2022-12-25','%Y-%m-%d'),hiredate)>=0

5.通用函数【三种数据类型都可用】

函数名作用
ifnull(值1,值2)值1是否为空,值1空的,结果取值2,否则取值1,任意类型
if(布尔类型,值1,值2)判断布尔类型表达式,真取值1,否则值2
-- 1
select ifnull(1,2)
from dual;

-- 2
select ifnull(null,2)
from dual;

-- 1. 查询员工编号,上司编号,没有上司的,上司编号替换为8888
-- select empno,ifnull(mgr,8888)
-- from emp;

-- 2. 查询员工姓名,入职时间,没有入职时间的替换为2023-1-1

select ename,ifnull(hiredate,'2023-1-1')
from emp;

-- select if(3 > 5 , 3,5) result
-- from dual;


-- select ename,sal,if(sal > 6000 , '高薪资','低薪资') result
-- from emp;

-- 查询员工的入职时间,15之前 上半月/  15之后 下半月 
select ename,hiredate,if(day(hiredate) > 15, '下半月','上半月') 入职时间
from emp
where hiredate is not null;

​ case表达式:【分支判断】

-- 语法规则1
	casewhen1 then  结果1
        when2 then  结果2
        ...
        else 结果n
	end
	
-- 查询员工表信息 10 技术型人才  20 教育型人才 40 计算型人才
select ename, deptno, case deptno 
												when 10 then '技术型人才'
												when 20 then '教育型人才'
												when 40 then '计算型人才'
												else '其他人才'
											end 人才分类
from emp;	


-- 语法规则2
	case 
        when 条件1 then  结果1
        when 条件2 then  结果2
        ...
        else 结果n
	end
	
-- 查询员工姓名,薪资,5000-10000 A级别  10000-20000 B级别  20000-50000 C D

select ename,sal,case
									when sal between 5000 and 10000 then 'A'
									when sal between 10001 and 20000 then 'B'
									when sal between 20001 and 50000 then 'C'
									else 'D'
									end
from emp;

-- 查询员工入职时间: 月份1-3 一季度  4-6 二季度 7-9 三季度  10-12 四季度 入职

select ename,hiredate,case
									when month(hiredate) between 1 and 3 then '第一季度'
									when month(hiredate) between 4 and 6 then '第二季度'
									when month(hiredate) between 7 and 9 then '第三季度'
									when month(hiredate) between 10 and 12 then '第四季度'
									else '无此时间'
									end 入职区间
from emp;

多行函数【聚合函数,对多行数据处理,最终得到一个结果】

函数名作用
sum(列)求和函数,列数字类型的
avg(列)平均值函数,列数字类型的
min(列)最小值函数,列数字类型/日期类型
max(列)最大值函数,列数字类型/日期类型
count(*)统计总记录数
count(列)统计非空列
count(distinct 列)统计非空列,去重复

注意:所有的聚合函数,会忽略空值。

-- 1. 查询名字中包含s的员工的总薪资  
select sum(sal+ ifnull(comm,0))
from emp
where ename like '%s%';

-- 2. 查询10和40部门平均薪资
select avg(sal+ ifnull(comm,0))
from emp
where deptno in(10,40);

-- 查询公司最晚的入职时间

-- select max(hiredate)
-- from emp;

-- 查询10部门的最低薪资
-- select min(sal)
-- from emp;

-- 1. 查询薪资8000-20000之间,入职最早的入职时间
select min(hiredate)
from emp
where sal  between 8000 and 20000;

-- 2. 查询有奖金的员工中,最高薪资

select max(sal)
from emp
where comm is not null;


-- 查询员工表中员工个数
-- select count(*)
-- from emp;

-- 统计有奖金的员工个数
select count(comm)
from emp;

-- 统计员工表涉及到几个部门
-- select count(distinct deptno)
-- from emp

-- 1. 查询员工表没有奖金的员工个数
select count(*)
from emp
where comm is null;

-- 2. 查询10或20 部门涉及到几种职位(去重)
select count(distinct job)
from emp
where deptno in(10,20);
-- 3. 查询1号员工下属的人数
select count(empno)
from emp
where mgr = 1;
3.4.3.5 表的连接查询

将多张表的数据联合进行查询,表连接查询。

查询需求: 查询员工姓名,部门编号,部门位置

表的连接方式:

-- 1 笛卡尔集
-- 2 等值连接
-- 3 不等值连接
-- 4 自我连接
-- 5 外连接
  1. 笛卡尔集

将两张【多张表】在没有任何连接条件的基础上,做完全连接。

语法规则:

SELECT1.* | *
FROM1,2

注意: 将两张表数据完全交叉,即使条件不对等,连接上,表1 * 表2

​ 2.等值连接

将表通过等值的连接条件完成连接。

语法规则:

SELECT1.,2.FROM1,2
WHERE1.=2.AND 条件+;
select emp.ename,dept.deptno,dept.loc
from emp,dept
where emp.deptno=dept.deptno
order by emp.sal desc

总结:

  1. 查询的时候,两张表中出现的相同的列,必须指定表名,其他的列可以不用
select ename,emp.deptno,loc
from emp,dept
where emp.deptno=dept.deptno
order by sal desc

​ 2. 开发中,添加表.列 推荐,提高查询效率,一般需要为表取别名【推荐的写法】

select e.ename,e.deptno,d.loc
from emp e ,dept d
where e.deptno=d.deptno
order by e.sal desc
3. 一旦使用别名,不可以使用原表名,以下错误的
select e.ename,emp.deptno,d.loc
from emp e ,dept d
where e.deptno=d.deptno
order by e.sal desc

表连接推荐写法:

select e.ename,e.deptno,d.loc
from emp e ,dept d
where e.deptno=d.deptno
order by e.sal desc

练习:

-- 1 查询有奖金,且薪资高于8000的员工姓名,部门名称
select e.ename,e.sal,d.dname
from emp e,dept d
where e.deptno=d.deptno 
and e.comm is not null 
and e.sal>8000
order by e.sal desc
-- 2 查询名字中包含a或e的员工薪资,部门位置
select e.ename,e.sal,d.loc
from emp e,dept d
where e.deptno=d.deptno 
and (e.ename like '%a%' or e.ename like '%e%');

3.不等值连接

将表通过不等值的连接条件完成连接。

语法规则:

SELECT1.,2.FROM1,2
WHERE1.列 不等值 表2.AND 条件+;
-- 查询员工表姓名,薪资,薪资所处等级【等级表】
select e.ename,e.sal,s.grade
from emp e,sal s
where e.sal between s.losal and s.hisal;

注意: 表联查的时,N个表至少N-1连接条件。

练习:

-- 查询工资等级为3或4级员工的姓名,薪资和部门位置
select e.ename,e.sal,s.grade,d.loc
from emp e,sal s,dept d
where e.sal between s.losal and s.hisal 
and e.deptno=d.deptno 
and s.grade in(3,4);

4.自我连接

一张表,自己和自己做连接。

语法规则:

SELECT 别名1.列,别名2.FROM 表 别名1, 表  别名2
WHERE 别名1.= 别名2.AND 条件+;
-- 查询员工编号,姓名,领导编号,领导姓名
select e.empno,e.ename,e.mgr,m.ename
from emp e,emp m
where e.mgr = m.empno 

练习:

-- 查询员工姓名,薪资等级,领导姓名,薪资等级
select e.ename,s1.grade,m.ename,s2.grade
from emp e,emp m,sal s1,sal s2
where e.mgr = m.empno  
and e.sal between s1.losal and s1.hisal
and m.sal between s2.losal and s2.hisal


-- 查询下级比自己上司入职早的员工姓名和部门位置

select e.ename,d.loc,m.ename
from emp e,emp m ,dept d
where e.mgr =m.empno and e.deptno=d.deptno
and e.hiredate < m.hiredate

5.外连接

将等值连接时,不满足连接条件的数据也显示出来,叫做外连接。

左外连: 左侧表为主表,右侧表从表,左侧表数据完全显示

右外连: 右侧表为主表,左侧表从表,右侧表数据完全显示

满外连: 两侧数据都完全显示

内连接: 只显示满足连接条件数据。

语法规则:

SELECT1.,2.FROM1  LEFT JOIN |  RIGHT JOIN  | FULL JOIN2
ON(1.=2.)
-- 显示员工和对应领导【即使没有领导的员工也显示】
select e.empno,e.ename,e.mgr,m.ename
from emp e left join emp m
on(e.mgr = m.empno)

-- 查询员工编号,姓名,部门编号,部门位置【没有员工的部门也要显示】
select e.empno,e.ename,d.deptno,d.loc
from emp e right join dept d
on(e.deptno=d.deptno)
order by d.deptno

SQL1999语法规范:

SELECT ...
FROM1  CROSS JOIN | JOIN | LEFT JOIN | RIGHT JOIN | FULL JOIN2
USING(列名) -- 等值连接,连接的列名同名列
ON(连接条件) 
-- 笛卡尔集
select *
from emp cross join dept

--等值连接
select e.ename,d.dname
from emp e join dept d
using(deptno)
where ename like '%s%'

-- 自我连接
select *
from emp e join emp m
on(e.mgr=m.empno)
where e.sal > 8000

--外连接
select e.empno,e.ename,e.mgr,m.ename
from emp e left join emp m
on(e.mgr = m.empno)
3.4.3.6 分组查询

将表中的数据进行分组,按照每个组进行查询。如: 按性别分组,按部门分组,按职位…

语法规则:

SELECT ....
FROM ....
WHERE ....
GROUP BY 分组列
[HAVING 组函数条件]
ORDER BY ...
-- 按照部门分组,统计每个部门的人数
select deptno,count(*)
from emp
group by deptno

-- 按照部门位置分组,统计每个部门位置多少人【没有人的部门也显示】
select d.loc,count(e.empno)
from emp e right join dept d
on(e.deptno=d.deptno)
group by d.loc;

select d.deptno,count(e.empno)
from emp e right join dept d
using(deptno)
group by d.deptno

总结:

执行顺序:

WEHRE  分组之前筛选
GROUP BY  分组
HAVING   分组后限制条件

GROUP BY后面分组列,通常才会在SELECT后面查。

-- 按照部门编号分组,统计各个部门有奖金的员工的平均薪资,平均薪资在8000+

select deptno,avg(sal) a
from emp 
where comm is not null
group by deptno
having a>8000

-- 统计各个领导者手下员工,有奖金员工最高薪资,最高薪资在10000
select e.mgr,m.ename,max(e.sal) s
from emp e , emp m
where e.comm is not null  and e.mgr is not null and e.mgr = m.empno
group by e.mgr
having s > 10000
3.4.3.7 TOP-N查询

通用用于表中数据分页【查询1-n】,或者用于查询xx的第几名,前几名。

语法规则1 - 分页显示数据

SELECT ....
FROM ....
WHERE ....
[GROUP BY 分组列]
[HAVING 组函数条件]
LIMIT 起始位置,查询个数  -- 起始位置从0开始

语法规则2 - 查询前几名

SELECT ....
FROM ....
WHERE ....
[GROUP BY 分组列]
[HAVING 组函数条件]
ORDER BYLIMIT 起始位置,查询个数  -- 起始位置从0开始

案例:分页显示

-- 分三页显示 1页 3条  
-- 1 
select *
from emp
limit 0,3;

-- 2 
select *
from emp
limit 3,3;

-- 3 
select *
from emp
limit 6,3;


-- 查询员工表中最高薪资的员工信息
select *
from emp
order by sal desc
limit 0,1

练习:

-- 1. 查询没有奖金的员工中,最早入职的员工信息
-- select *
-- from emp
-- where comm is null and hiredate is not null
-- order by hiredate 
-- limit 0,1;


-- 2. 按照部门名称分组,统计各个部门的平均薪资,获得最高平均薪资的部门信息

select d.dname,avg(e.sal) a
from emp e,dept d
where e.deptno=d.deptno
group by d.dname
order by a desc
limit 0,1

3.4.3.8 子查询

经过一次内部子查询,查询结果给外部主查询使用,称之为子查询。

语法规则1:【WHERE型子查询】

SELECT ...
FROM ...
WHERE  列 比较 (子查询)

比较:

​ 单行子查询,子查询结果是一行, = > >= < <= !=

​ 多行子查询,子查询结果是多行, IN >ALL >ANY < ALL <ANY

--单行
-- 查询比小管工资高的员工信息
select *
from emp
where sal>(select sal from emp where ename='小管');

-- 查询和ys相同部门的员工姓名和雇用日期
-- select ename,hiredate
-- from emp
-- where deptno=(select deptno from emp where ename='ys') 
-- and ename !='ys';

-- 多行
-- 查询和姓名中包含字母c的员工在相同部门的员工的员工号和姓名
-- IN()
select empno,ename
from emp
where deptno in (select deptno
							from emp
							where ename like '%s%');
							
							
							
-- 查找出不在部门20,且比部门20中任何一个人工资都高的员工姓名、部门名称
-- select e.ename,d.dname
-- from emp e,dept d
-- where e.deptno=d.deptno 
-- and e.deptno!=20 
-- and sal > (select max(sal) from emp where deptno=20);
-- >ALL

select e.ename,d.dname
from emp e,dept d
where e.deptno=d.deptno 
and e.deptno!=20 
and sal >ALL (select sal from emp where deptno=20);

语法规则2:【FROM型子查询】

SELECT ...
FROM, (子查询)2
WHERE  表连接 AND  条件+;
-- 分部门得到平均工资等级为2级(等级表)的部门编号

select dd.deptno
from (select deptno,avg(sal) a
			from emp
			group by deptno) dd, sal s
where dd.a between s.losal and s.hisal and s.grade=4;

练习:

-- 1. 查询和wsj相同领导的员工的总薪资
select sum(sal)
from emp
where mgr = (select mgr from emp where ename='wsj');


-- 2. 查询不在10部门,但是比10号部门任何一个员工入职都早的员工信息

select *
from emp
where deptno!= 10 and hiredate <all (select hiredate from emp where deptno=10);


-- 3. 查询比自己所在部门平均薪资高的员工信息

select e.*
from emp e,(select deptno,avg(sal) a from emp group by deptno) m
where e.deptno=m.deptno and e.sal > m.a;

总结:

在这里插入图片描述

3.4.4 DML

数据操作语言,主要是对表中的数据进行增加,删除,修改操作。从而产生事务

3.4.4.1 增加数据

向表中添加数据。

语法规则:

INSERT INTO 表名[(1,列2)]
VALUES(1,2...);

注意:

1,每次只能向表中添加一条数据

2,表名(列) 可以省略的,省略的时候,向表里的所有列插入数据

3,值要和列相应: 个数,类型,插入时候,主键列必须要有,其他的列可以省略不写的,默认null

insert into dept
values(80,'防疫部','南京');


insert into emp(empno,ename,sal,job,hiredate,deptno)
values(9,'lyx',9000,'防疫经理',now(),80);

  1. 数据批量加入到表中
-- 复制一张表
-- create table emp2
-- as
-- select * from emp;


-- 批量增加
-- emp中20部门数据插入到emp2

-- insert into emp2
-- select * from emp where deptno=20
3.4.4.2 修改数据

修改表中数据。

语法规则:

UPDATE 表名
SET=,=WHERE 条件;

注意:

1.WHERE 不加任何条件,修改表中所有数据

2.修改多个信息使用,隔开

-- 员工表中薪资扣掉 500块
-- update emp
-- set sal = sal - 500;

-- 10部门员工薪资增加1000,奖金添加500
-- update emp
-- set sal =sal+1000,comm = ifnull(comm,0) + 500
-- where deptno=10;
3.4.4.3 删除数据

语法规则:

DELETE FROM 表名
[WHERE 条件];

注意:

没有条件时,将表中数据清空。

-- 删除名字为a的员工信息
delete from emp
where ename='a';
3.4.4.4 事务

事务是一连串的DML操作集合,是一个逻辑操作单元,一个事务会包含多个DML动作。

如: 转账500业务:【修改A账户余额-500】-> 【修改B账户余额+500】-> 查询A/B账户

事务存在的意义?

一个事务中的所有动作都是一个逻辑单元,保证多个操作协调,统一、一致的【要么都做,要么都不做】
保证数据的安全性

事务的特点:

ACID:
A 原子性 一个事务是一个整体,一起的
C 一致性 协调一致
I 隔离性  事务与事务的隔离操作
D 持久性 提交回滚之间永久改变数据

事务的开始和结束:

开始:
	发生第一个DML动作开始。【所有事务结束】

结束:
	提交  COMMIT ;  事务的所有动作全部执行
	回滚  ROLLBACK;  事务的所有动作全部不执行

事务的操作:

-- kf 的薪资 转给 quan 2000
-- 启动事务
-- start transaction;

-- update emp
-- set sal = sal - 2000
-- where ename = 'kf';
-- 
-- update emp
-- set sal = sal + 2000
-- where ename = 'quan';

-- rollback;

3.4.5 DDL

数据定义语言,用于定义表【创建表】,为表添加列,修改表,删除表,为表添加约束。

3.4.5.1 建表语法规则
1.具备建表的权限
2.具备存储空间
3.必须写表名,列名【类型 大小】

语法规则:

CREATE TABLE 表名(
	列名  数据类型(大小) [default 默认值] [约束],	
	列名  数据类型(大小) [default 默认值] [约束],   
    .....
    列名  数据类型(大小) [default 默认值] [约束],   
    表约束    
)

注意:

1.表名,列名 : 字母 数字 _ $ # 构成, 30字符内,字母开头

2.数据类型

在这里插入图片描述
3.默认值 不添加数据时,默认的值

-- 创建学生表 
create table stu(
	sno int(4) primary key,
	sname varchar(20),
	sex varchar(4) default '男',
	birth date

)
insert into stu
values(1,'quan','男','2001-12-31');
select * from stu;

-- 课程表 课程编号 名称 学分【浮点】,上课时间
CREATE TABLE course(
	cno INT(4) PRIMARY KEY,
	cname VARCHAR(20),
	credit DOUBLE(5,2),
	timi datetime
)


3.4.5.2 修改表

修改表: 新增列,删除列,修改列的数据类型或大小。

语法规则:

ALTER TABLE 表名
ADD(列 类型(大小));

ALTER TABLE 表名
DROP;

ALTER TABLE 表名
MODIFY 列 类型(大小)
-- 添加一个列 年龄
alter table stu
add(age int(3));

-- 修改表数据
alter table stu
modify sname varchar(40);

-- 删除age列

alter table stu
drop age;
3.4.5.3 删除表

语法规则:

DROP TABLE 表名; -- 全部删除,表数据,表结构,表空间全部回收,不能回滚

DELETE FROM 表名; -- 只删除表中数据,表结构还有空间不回收,可以回滚

TRUNCATE TABLE 表名; -- 截断表,表结构在,不可回滚
-- start transaction;
-- delete from stu;

-- rollback;

-- truncate table stu;
-- select * from stu;

drop table sksj;
3.4.5.4 约束

约束是给表添加限制条件。约束分为: 表级约束,列级约束。

约束分类:
	实体完整性约束
	域完整性约束
	参照完整性约束
约束类型:
	非空约束  NOT NULL 
	唯一约束  UNIQUE
	主键约束  PRIMARY KEY
	外键约束  FOREIGN KEY
	检查约束  CHECK

添加约束的时机:

​ 1.建表时【推荐】

​ 2.建表后

添加约束的位置:

CREATE TABLE 表名(
	列名  数据类型(大小)  列级约束 ,	
    表级约束,
    表级约束2
)
-- drop table stu;
-- create table stu(
-- 	sno int(4) primary key,
-- 	sname varchar(20) not null,
-- 	sex varchar(4) ,
-- 	birth date,
-- 	check sex in ('男','女')
-- )
-- 
-- insert into stu
-- values(1,'a','a','2022-1-1');

非空约束:NOT NULL

非空约束只能定义在列级,用于某列插入数据时,要求该列不能为空。

CREATE TABLE 表名(
	列  数据类型(大小) NOT NULL,
    ...
)

案例:

create table stu(
	sno int(4) primary key,
	sname varchar(20) not null
)
insert into stu
values(1,'jack');

select *
from stu;

唯一约束: UNIQUE

唯一约束可以列级,表级。某列插入数据时唯一的,不能重复。

CREATE TABLE 表名(
	列  数据类型(大小) UNIQUE,
    UNIQUE()
)
create table stu(
	sno int(4) primary key,
	sname varchar(20) not null,
	stel varchar(11) unique
)

主键约束 PRIMARY KEY

主键约束表的唯一标志,每个表必须要有个主键,可以是列级,表级。

一个表一个主键,主键不一定是一个列,多个列构成的主键【联合主键】,联合主键定义在表级。

CREATE TABLE 表名(
	列  数据类型(大小) PRIMARY KEY,
    PRIMARY KEY(1,列2)
)
-- 学生表
-- drop table stu;
-- create table stu(
-- 	sno int(4) primary key,
-- 	sname varchar(20) not null,
-- 	stel varchar(11) unique
-- )

-- 课程表
-- drop table course;
create table course(
	cno int(4) primary key,
	cname varchar(20) not null,
	cdate date
)

-- 选课
create table choose(
	sno int(4),
	cno int(4),
    -- 联合主键
	primary key(sno,cno)
)

注意: 主键 = 非空+唯一,一旦设置主键,不能空不能重复

外键约束 FOREIGN KEY

当前表A的某个列参照于另一张表B的主键,此时该列就是外键。

如: 选课表 学号【外键】 参考 学生的表 学号【主键】 , 选课表 课程号【外键】 参考 课程的表 课程编号【主键】。

CREATE TABLE 表名(
	列  数据类型(大小) PRIMARY KEY,
    FOREIGN KEY(外键列) REFERENCES 参考表(主键)
)
drop table choose;
create table choose(
	sno int(4),
	cno int(4),
	primary key(sno,cno),
	foreign key(sno) references stu(sno),
	foreign key(cno) references course(cno)
)

insert into choose
values(2,1);

注意: 父表和子表,选课表子表,参考学生表/课程表,父表

关于级联删除:

前提: 当子表调用了父表中的数据时,此时删除父表的数据,无法实现删除。

如果想要可以删除,删除父表数据时连带的删除子表数据【删除学生,学生相关的选课信息也被删除】,也就是级联删除。

CREATE TABLE 表名(
	列  数据类型(大小) PRIMARY KEY,
    FOREIGN KEY(外键列) REFERENCES 参考表(主键)  ON DELETE CASCADE
)
-- drop table choose;
-- create table choose(
-- 	sno int(4),
-- 	cno int(4),
-- 	primary key(sno,cno),
-- 	foreign key(sno) references stu(sno) on delete cascade,
-- 	foreign key(cno) references course(cno)on delete cascade
-- )

检查约束 CHECK

一般用检查类型是否合法,比如 年龄是不是>0 ,性别是否男女。

CREATE TABLE 表名(
	列  数据类型(大小) PRIMARY KEY,
   CHECK (age > 0)
)

总结:

约束分类:
	实体完整性约束   主键 / 唯一 
	域完整性约束	   非空 / 检查  【域: 列的取值范围】
	参照完整性约束   外键

3.4.6 视图

从原表中抽取逻辑相关的,需要的部分,即为视图。视图是虚拟表,更关注你需求的数据,作用和原表一样,当操作视图的时候,实质还是在操作原表。

视图的作用:

1. 将表逻辑相关的汇聚一起,逻辑划分
2. 简化用户对表的操作【增删改查】
3. 优化数据库的操作

创建视图语法:

CREATE VIEW 视图名
AS
查询表
-- 创建视图【员工编号,姓名,薪资,奖金】

create view emp_sal
as
select empno,ename,sal,comm
from emp

数据操作: DQL DML

-- insert into emp_sal values(7,'jack',5000,1000);
delete from emp_sal where empno=7;
update emp_sal set sal=6000 where ename='kf';

select * from emp_sal;
select * from emp;

修改视图语法:

CREATE OR REPLACE VIEW 视图名
AS
查询表

注意: 如果存在,修改视图,否则新建

create or replace view emp_sal
as
select  empno,ename,sal,comm
from emp
where deptno in(10,40);

删除视图:

drop view 视图名;

3.4.7 索引

数据库中一种对象,为数据库中表添加的数据查询导向,方便快速查询数据。【相当于书籍的目录】

作用:

1. 加快数据的查询效率,优化数据库性能
2. 减少数据库服务器磁盘IO

索引类型:

1. 自动索引   主键约束/唯一约束
2. 手动添加

何时适合索引:

1.列中数据值分布范围很广
2.列中包含大量空值
3.列经常在 WHERE 子句或连接条件中出现
4.表经常被访问而且数据量很大 ,访问的数据大概占数据总量的2%到4%

不适合索引:

1.表很小
2.列不经常作为连接条件或出现在WHERE子句中
3.查询的数据大于2%到4%
4.表经常更新
5.加索引的列包含在表达式中

语法规则:

CREATE INDEX 索引名
ON();

DROP INDEX  索引名;

案例:

create index index1
on emp(deptno);

3.4.8 自动增长列

能够自动提供主键【数字型】,不需要手动插入主键列,自动递增。

在这里插入图片描述

-- 自动递增主键
insert into stu(sname,stel)
values('jack','6666');

4. JDBC

java database connectivy ,JAVA连接数据库的一套统一的标准和规范。使用一套统一的JAVA API,在JAVA里操作数据库,完成数据库数据的CRUD。

java.sql.* 和数据库相关的API。

JDBC实现的原理: JAVA操作不同的数据库,采用一套API,接口和类相同,源于不同的数据库驱动。

在这里插入图片描述
MYSQL的驱动:

1. mysql-connector-java-5.x;  mysql5.0+
2. mysql-connector-java-8.x;  mysql8.0+

4.1 JDBC涉及的API

在这里插入图片描述

4.2 JDBC操作步骤【重点】

1. 加载驱动包
2. 建立数据库连接
3. JAVA发送SQL语句到数据库
4. 数据库返回结果
5. JAVA解析结果
6. 释放资源

4.2.1 注册加载驱动包【1】

1. 新建JAVA项目,引入驱动jar文件 
2. 驱动文件打开	项目 右键 > build path > libraries > add jars 
3. 通过反射载入驱动
   //载入驱动
  static {		
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

4.2.2 反射原理

JAVA源程序运行机制:半编译半解释

在这里插入图片描述

反射:反向编译和解析,在获得JAVA字节码对象的时候,反过来寻求JAVA的源文件中定义,解析这类的构成【属性,方法,构造】。

java.lang.Object 所有的JAVA类型的父类

java.lang.Class 运行时对象的类型父类

获得运行时对象的三种方式:

1.对象.getClass();
2..class
3.Class.forName("类型字符串");

案例:

package reflect;

public class Student extends Object{
	public int sno;
	public String sname;
	public Student() {
		
	}
	public Student(int sno, String sname) {
		super();
		this.sno = sno;
		this.sname = sname;
	}
	
	public void eat() {
		
	}
	public void sleep() {
		
	}
}


package reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestClass {
	public static void main(String[] args) {
		//第一种
		//Class c1 = new Student().getClass();
		
		//第二种
		//Class c2 = Student.class;
		
		//第三种
		try {
			Class c3 = Class.forName("reflect.Student");
			
			//反射
			//获得类所有属性
			Field[] f = c3.getFields();
			for (Field field : f) {
				System.out.println(field.getName());
			}
			System.out.println("--------------------");
			//获得类的方法
			Method[] m = c3.getDeclaredMethods();
			for (Method mm : m) {
				System.out.println(mm.getName());
			}
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
}

4.2.3 建立数据库连接【2】

连接接口: java.sql.Connection
    
三个信息: 
    		1.数据库连接路径    jdbc:mysql://ip地址:3306/数据库名
			localhost 本地ip
            3306 mysql端口
    	 	2.数据库名 root  
    		3.数据库密码 admin   
Connection c = DriverManager.getConnection(url,username,password);

public static Connection getConn() throws SQLException {
		
		Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2204", "root", "admin");
		return c;
}

4.2.4 执行SQL命令【3,4,5】

执行命令接口: java.sql.Statement
		//执行DML操作
		//获得执行命令接口
		Statement ste = conn.createStatement();
		
		//增加数据	
		String sql = "insert into dept values(50,'后勤部','上海')";
		//返回值 受到影响行数
		//执行DML
		int a = ste.executeUpdate(sql);
		
		//判断返回值结果
		if(a > 0) {
			System.out.println("增加成功");
		}else {
			System.out.println("增加失败");
		}

		
		//执行DQL
		//1.2 加载驱动 建立连接
		//连接接口
		Connection conn = null;
		//执行命令
		Statement ste = null;
		//结果集接口
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			//3. 执行命令接口
			ste = conn.createStatement();
			String sql = "select * from dept";
			//4. 执行查询语句 executeQuery()
			rs = ste.executeQuery(sql);
			//5. 解析结果
			//解析行
            rs.next();//每次解析一行
            //解析列
            rs.getXX(下标);
            rs.getXX("列名");
            //XX 数据类型  int  getInt()   double getDouble()  varchar getString()  date getDate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


封装:

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 1,2,6
 * @author 86136
 *
 */
public class DBUtil {
	/**
	 * 1.载入驱动
	 */
	static {
		
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 2. 建立数据库连接
	 * @throws SQLException 
	 */
	public static Connection getConn() throws SQLException {
		
		Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2204", "root", "admin");
		return c;
	}
	
	/**
	 * 6. 关闭
	 */
	public static void close(Connection c,Statement s,ResultSet r) {
		try {
			if(r != null && s != null && c != null) {
				r.close();
				s.close();
				c.close();
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
	
}

修改部门:

public class UpdateDept {
	
	public static void main(String[] args) {
		//1.载入驱动 获得连接
		Connection conn = null;
		Statement ste = null;
		try {
			conn = DBUtil.getConn();
		//3 执行命令
			String sql = "update dept set dname='保安部',loc='大连' where deptno=50";
			ste = conn.createStatement();
		//4 执行	
			int a = ste.executeUpdate(sql);
		//5 解析
			if(a > 0) {
				System.out.println("成功");
			}else {
				System.out.println("失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//6
			DBUtil.close(conn,ste,null);
		}
	}
	
}

部门数据封装:

public class Dept {
	private int deptno;
	private String dname;
	private String loc;
	//....
	
}

部门操作:

public interface IDeptDao {
	
	int addDept(Dept dept);
	
	int updateDept(Dept dept);
	
	int deleteDept(int deptno);
}

public class DeptDao implements IDeptDao {

	@Override
	public int addDept(Dept dept) {

		return 0;

	}

	@Override
	public int updateDept(Dept dept) {
		// 1.载入驱动 获得连接
		Connection conn = null;
		Statement ste = null;
		int a = 0;
		try {
			conn = DBUtil.getConn();
			// 3 执行命令
			String sql = "update dept set dname='"+dept.getDname()+"',loc='"+dept.getLoc()+"' where deptno=" + dept.getDeptno();
			ste = conn.createStatement();
			// 4 执行
			a = ste.executeUpdate(sql);
			// 5 解析
			if (a > 0) {
				System.out.println("成功");
			} else {
				System.out.println("失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			// 6
			DBUtil.close(conn, ste, null);
		}
		return a;
	}

	@Override
	public int deleteDept(int deptno) {
		// TODO Auto-generated method stub
		return 0;
	}

}

部门查询:

@Override
	public ArrayList<Dept> queryAll() {
		//1.2 加载驱动 建立连接
		//连接接口
		Connection conn = null;
		//执行命令
		Statement ste = null;
		//结果集接口
		ResultSet rs = null;
		ArrayList<Dept> list = new ArrayList<Dept>();
		try {
			conn = DBUtil.getConn();
			//3. 执行命令接口
			ste = conn.createStatement();
			String sql = "select * from dept";
			//4. 执行查询语句 executeQuery()
			rs = ste.executeQuery(sql);
			//5. 解析结果
			//解析行 next();
			//rs.next();
			while(rs.next()) {
				//解析列  getXX(下标/列名) XX类型
				list.add(new Dept(rs.getInt(1) , rs.getString("dname"), rs.getString(3)));
				
			}
		
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return list;
	}

4.2.5 释放连接【6】

	try{
		//....
	}
	catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	}finally {
			//6.关闭数据库连接
			ste.close();
			conn.close();
	}

总结:

Connection接口: 数据库连接接口

方法含义
createStatement()返回Statement对象
close()关闭连接
prepareStatement(sql);返回PreparedStatement对象

Statement接口: 执行命令接口

方法含义
executeUpdate()返回值int 执行DML
executeQuery()返回值ResultSet 对象,执行DQL
close()关闭对象

ResultSet接口: 结果集接口

方法含义
next()结果集获取行,返回值 boolean
getXX(下标)根据列下标获取列,下标从1开始
getXX(“列名”)根据列名获取列
close()关闭对象

4.3 预编译SQL

SQL注入: SQL语句编译的时候,传入了用户输入数据,编译语句同时,提取JAVA的参数,不方便不安全,避免SQL注入,提前预先编译好sql,动态传参。

String sql = "insert into dept values(" + dept.getDeptno() + ",'" + dept.getDname() + "','" + dept.getLoc()
					+ "')";

4.3.1 PreparedStatement 接口

可以实现提前预编译sql语句的接口,是Statement接口的子接口,性能更加优化。

好处:

1. 提前预先编译sql,后续JAVA参数动态传入,执行效率更高
2. JAVA代码和sql代码分离,解耦
3. 安全性更高,避免sql注入

4.3.2 使用步骤

//只代替3,4步 

1. sql语句中所有的java参数,使用?代替
    String sql = "insert into dept values(?,?,?)";
2. 创建PreparedStatement对象
    PreparedStatement ste = null;
	ste = conn.prepareStatement(sql);
3. 给?赋值,传参
	ste.setXX(?位置,);
4. 执行不带参数 a = ste.executeUpdate();

完整:

@Override
	public int addDept(Dept dept) {
		// 1.载入驱动 获得连接
		Connection conn = null;
		PreparedStatement ste = null;
		int a = 0;
		try {
			conn = DBUtil.getConn();
			// 3 执行命令
			String sql = "insert into dept values(?,?,?)";
			//预编译
			ste = conn.prepareStatement(sql);			
			//给?赋值
			ste.setInt(1, dept.getDeptno());
			ste.setString(2, dept.getDname());
			ste.setString(3, dept.getLoc());
			
			// 4 执行
			a = ste.executeUpdate();
			// 5 解析
			if (a > 0) {
				System.out.println("成功");
			} else {
				System.out.println("失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			// 6
			DBUtil.close(conn, ste, null);
		}
		return a;

	}

4.4 分层封装

4.4.1 实体封装pojo

pojo: 普通java对象

//实体封装:ORM
//ORM : Object Relationship Mapping   对象【java对象】关系【表】一一映射
public class Dept {
	private int deptno;
	private String dname;
	private String loc;
	
}

//对应数据表: 
    int  int
    varchar String
    date  Date
    ....

4.4.2 DAO层封装

DAO : data access object ,数据访问对象,数据层,和db直接交涉,完成对数据库的增删改查。

包含所有对表的增加,删除,修改,查询的方法。

// DAO封装,面向接口
// 对实体操作的方法声明
public interface IDeptDao {
	/**
	 * 增加方法
	 * @param dept
	 * @return
	 */
	int addDept(Dept dept);
	/**
	 * 修改部门
	 * @param dept
	 * @return
	 */
	int updateDept(Dept dept);
	/**
	 * 删除部门
	 * @param deptno
	 * @return
	 */
	int deleteDept(int deptno);
	
	/**
	 * 查询部门
	 */
	ArrayList<Dept> queryAll();
	
	/**
	 * 查询单个
	 */
	
	Dept queryByNo(int deptno);
	
}

// 实现类实现方法
public class DeptDao implements IDeptDao {

	@Override
	public int addDept(Dept dept) {
		// 1.载入驱动 获得连接
		Connection conn = null;
		PreparedStatement ste = null;
		int a = 0;
		try {
			conn = DBUtil.getConn();
			// 3 执行命令
			String sql = "insert into dept values(?,?,?)";
			//预编译
			ste = conn.prepareStatement(sql);			
			//给?赋值
			ste.setInt(1, dept.getDeptno());
			ste.setString(2, dept.getDname());
			ste.setString(3, dept.getLoc());
			
			// 4 执行
			a = ste.executeUpdate();
			// 5 解析
			if (a > 0) {
				System.out.println("成功");
			} else {
				System.out.println("失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			// 6
			DBUtil.close(conn, ste, null);
		}
		return a;

	}

	@Override
	public int updateDept(Dept dept) {
		// 1.载入驱动 获得连接
		Connection conn = null;
		Statement ste = null;
		int a = 0;
		try {
			conn = DBUtil.getConn();
			// 3 执行命令
			String sql = "update dept set dname='" + dept.getDname() + "',loc='" + dept.getLoc() + "' where deptno="
					+ dept.getDeptno();
			ste = conn.createStatement();
			// 4 执行
			a = ste.executeUpdate(sql);
			// 5 解析
			if (a > 0) {
				System.out.println("成功");
			} else {
				System.out.println("失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			// 6
			DBUtil.close(conn, ste, null);
		}
		return a;
	}

	@Override
	public int deleteDept(int deptno) {
		// 1.载入驱动 获得连接
		Connection conn = null;
		Statement ste = null;
		int a = 0;
		try {
			conn = DBUtil.getConn();
			// 3 执行命令
			String sql = "delete from dept where deptno=" + deptno;
			ste = conn.createStatement();
			// 4 执行
			a = ste.executeUpdate(sql);
			// 5 解析
			if (a > 0) {
				System.out.println("成功");
			} else {
				System.out.println("失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			// 6
			DBUtil.close(conn, ste, null);
		}
		return a;
	}

	@Override
	public ArrayList<Dept> queryAll() {
		// 1.2 加载驱动 建立连接
		// 连接接口
		Connection conn = null;
		// 执行命令
		Statement ste = null;
		// 结果集接口
		ResultSet rs = null;
		ArrayList<Dept> list = new ArrayList<Dept>();
		try {
			conn = DBUtil.getConn();
			// 3. 执行命令接口
			ste = conn.createStatement();
			String sql = "select * from dept";
			// 4. 执行查询语句 executeQuery()
			rs = ste.executeQuery(sql);
			// 5. 解析结果
			// 解析行 next();
			// rs.next();
			while (rs.next()) {
				// 解析列 getXX(下标/列名) XX类型
				list.add(new Dept(rs.getInt(1), rs.getString("dname"), rs.getString(3)));

			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			DBUtil.close(conn, ste, rs);
		}

		return list;
	}

	@Override
	public Dept queryByNo(int deptno) {
		// 1.2 加载驱动 建立连接
		// 连接接口
		Connection conn = null;
		// 执行命令
		Statement ste = null;
		// 结果集接口
		ResultSet rs = null;
		Dept dept = null;
		try {
			conn = DBUtil.getConn();
			// 3. 执行命令接口
			ste = conn.createStatement();
			String sql = "select * from dept where deptno=" + deptno;
			// 4. 执行查询语句 executeQuery()
			rs = ste.executeQuery(sql);
			// 5. 解析结果
			// 解析行 next();
			// rs.next();
			if (rs.next()) {
				// 解析列 getXX(下标/列名) XX类型
				dept = new Dept(rs.getInt(1), rs.getString("dname"), rs.getString(3));

			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			DBUtil.close(conn, ste, rs);
		}

		return dept;
	}

}

4.4.3 DAO的深层封装

/**
 * 实现对于DML的深层封装
 * 
 * @author 86136
 *
 */
public class BaseDao {

	/**
	 * 执行DML
	 */
	public static int executeDML(String sql, Object... params) {

		// 1.载入驱动 获得连接
		Connection conn = null;
		PreparedStatement ste = null;
		int a = 0;
		try {
			conn = DBUtil.getConn();
			ste = conn.prepareStatement(sql);
			// 给?赋值
			for (int i = 0; i < params.length; i++) {
				ste.setObject(i + 1, params[i]);
			}

			// 4 执行
			a = ste.executeUpdate();
			// 5 解析
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			// 6
			DBUtil.close(conn, ste, null);
		}
		return a;

	}
    
    
    public interface RowMapper<T> {
   		 public T getRow(ResultSet resultSet);
	}

    
    public List<T> commonsSelect(String sql, RowMapper<T> rowMapper, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<T> list = new ArrayList<>();

        try {
			connection = DBUtil.getConn();
		} catch (SQLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
        try {
            preparedStatement = connection.prepareStatement(sql);
            if(args != null) {
            	for (int i = 0; i < args.length; i++) {
                    preparedStatement.setObject(i + 1, args[i]);
               }
            }
            
            
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                
                //如何根据查询结果完成ORM,如何进行对象的创建及赋值
                T t = rowMapper.getRow(resultSet);//回调 -->调用者提供的一个封装方法ORM
                list.add(t);
            }
            return list;

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

        return null;

    }
    
    
    
}


public class DeptDao extends BaseDao implements IDeptDao {

	@Override
	public int addDept(Dept dept) {

		return executeDML("insert into dept values(?,?,?)", dept.getDeptno(), dept.getDname(), dept.getLoc());
	}

	@Override
	public int updateDept(Dept dept) {
		
		
		return executeDML("update dept set dname=?,loc=? where deptno=?", dept.getDname(), dept.getLoc(), dept.getDeptno());
		
	}
}

//查询实现类:
    @Override
	public List<Emp> queryAll() {
		
		String sql = "select empno,ename,sal,hiredate,deptno from emp";
		return commonsSelect(sql, new RowMapper<Emp>() {
			Emp emp = null;
			@Override
			public Emp getRow(ResultSet rs) {
				
				try {
					emp = new Emp(rs.getInt(1),rs.getString(2),rs.getDouble(3),rs.getDate(4),new Dept(rs.getInt(5)));
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return emp;
			}
		});	
	}

日期格式转化类:

public class DateFormatter {
	
	public static Date formatter(String str) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");	
		Date d = null;
		try {
			d  = new Date(sdf.parse(str).getTime());
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		return d;
	}
}	

4.4.4 常见的异常

在这里插入图片描述

4.4.5 Service业务层

业务层:service层,完成一个完整的业务功能,一个业务功能包含多个DAO的操作。

如:业务功能: 清空购物车【购物车数据删除 DELETE 】 -> 【新建一个订单数据 INSERT】

​ 转账业务 : 【A账户修改 减少余额】 -> 【B账户修改 增加余额】

​ 预定房间: 【预定订单:增加】 -> 【修改房间 : 修改】

业务层: 粗粒度,关注一个完整的业务功能【增 删 改】,业务层多次调用DAO层方法

数据层: 细粒度,关注一个数据库操作,要么增 删  改 查,一个方法只完成一个操作
service包  面向接口

public interface IDeptService {
	
	boolean add(Dept dept);
	
	boolean update(Dept dept);
	
	boolean delete(int deptno);
	
	/**
	 * 查询: 分页查询: 
	 */
	ArrayList<Dept> getAll(Pager pager);
}

public class DeptServiceImpl implements IDeptService{

}

分页信息:

// 一共多少页, 第几页 , 一页显示几条,  起始位置  
/**
 *  分页信息
 * @author 86136
 *
 */
public class Pager {
	private int pages; //一共多少页
	private int nums = 3;  //一页显示几个
	private int counts ; //获取有多少条数据
	//客户需求
	private int curr;//当前第几页
	
	//数据库
	private int start;//起始位置
	
	
	public Pager(int curr) {
		
		this.curr = curr; // 2
		//计算起始下标
		this.start = (curr - 1) * nums ;
	}

	public int getPages() {
		return pages;
	}

	public void setPages(int pages) {
		this.pages = pages;
	}

	public int getNums() {
		return nums;
	}

	public void setNums(int nums) {
		this.nums = nums;
	}

	public int getCounts() {
		return counts;
	}
	//设置记录总数
	public void setCounts(int counts) {
		this.counts = counts;//
		//页码数
		this.pages = counts % nums == 0 ?  counts / nums : counts / nums + 1;
	}

	public int getCurr() {
		return curr;
	}

	public void setCurr(int curr) {
		this.curr = curr;
	}

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
	}	
}

分页实现:

@Override
	public ArrayList<Dept> getAll(Pager pager) {
		//1. 先查询表中多少条数据
		int count = dao.getCounts();
		pager.setCounts(count);
		//2.根据页面查询	
		return dao.queryAll(pager);
}

测试分页:

public class TestDept {
	public static void main(String[] args) {
		IDeptService service = new DeptServiceImpl();
		Pager p = new Pager();
		p.setCurr(1);
		
		ArrayList<Dept> list = service.getAll(p);
		System.out.println("一共:" + p.getPages() + "页");
		System.out.println("当前第" + p.getCurr() + "页");
		for (Dept dept : list) {
			System.out.println(dept);
		}		
	}
}

登录注册业务:

public interface IAdminService {
	// 注册业务 【注册】 >  【增加】
	/**
	 * 注册业务
	 */
	
	boolean register(Admin admin);
    
    
	//登录业务 【登录】 >  【查询】
    /**
	 * 登录业务
	 */
	boolean login(String username,String password);
}


public class AdminServiceImpl implements IAdminService{
	
	private IAdminDao dao = new AdminDaoImpl();
	
	@Override
	public boolean register(Admin admin) {
		// TODO Auto-generated method stub
		return dao.addAdmin(admin) > 0;
	}

	@Override
	public boolean login(String username, String password) {
		//业务判断
		Admin admin = dao.queryByUsername(username);
		if(admin == null) {
			return false;
		}else {
			//判断密码
			if(admin.getPassword().equals(password)) {
				return true;
			}else {
				return false;
			}
		}
	}
}

事务操作:业务层多次调用DAO

事务通常用在业务层,业务逻辑包含多个动作,多个动作一个事务单元。
JDBC: 默认自动提交


//不自动提交【手动提交】
c.setAutoCommit(false);
///手动提交回滚
c.commit();
c.rollback();

4.4.6 总结三层架构

项目分层: 界面层  业务逻辑层  数据访问层
好处: 高内聚  低耦合 ,让代码打开耦合关系

在这里插入图片描述

public class HRUI {
	public HRUI() {
		//调用业务层
		IAdminService ser = new AdminServiceImpl();
		Scanner sc = new Scanner(System.in);
		//菜单程序
		while(true) {
			System.out.println("欢迎进入人事系统");
			System.out.println("1- 注册");
			System.out.println("2- 登录");
			System.out.println("3- 修改密码");
			System.out.println("请选择操作:");
			int opr1 = sc.nextInt();
			if(opr1 == 1) {
				//调用注册业务方法
				
			}else if(opr1 == 2) {
				//调用登录业务方法
				System.out.println("请输入用户名和密码:");
				if(ser.login(sc.next(), sc.next())) {
					System.out.println("登录成功");
					//进入二级菜单
					while(true) {
						System.out.println("功能模块");
						System.out.println("1- 部门模块");
						System.out.println("2- 员工模块");
						
						System.out.println("请选择操作:");
						int opr2 = sc.nextInt();
					}
				}else {
					System.out.println("账户或密码错误");
				}
			}
		}
	}
}

4.5 表连接查询

查询需求: 查询员工编号,姓名,薪资,部门名称

//实体
public class Emp {
	
	private int empno;
	private String ename;
	private double sal;
	private Date hiredate;
	//private int deptno;
	//一对一包含
	private Dept dept;
}
public Emp queryEmp_dept(int empno) {
		// 1.2 加载驱动 建立连接
		// 连接接口
		Connection conn = null;
		// 执行命令
		PreparedStatement ste = null;
		// 结果集接口
		ResultSet rs = null;
		Emp emp = null;
		try {
			conn = DBUtil.getConn();
			// 3. 执行命令接口
			//表连接
			StringBuilder sql = new StringBuilder()
					.append("select e.empno,e.ename,e.sal,d.deptno,d.dname ")
					.append("from emp e,dept d ")
					.append("where e.deptno=d.deptno and e.empno=? ");
			// 4. 执行查询语句 executeQuery()
			ste = conn.prepareStatement(sql.toString());
			ste.setInt(1, empno);
			rs = ste.executeQuery();
			// 5. 解析结果
			if (rs.next()) {
				// 解析列: 员工需要部门对象
				emp = new Emp(rs.getInt(1), rs.getString(2), rs.getDouble(3), new Dept(rs.getInt(4), rs.getString(5), null));

			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			DBUtil.close(conn, ste, rs);
		}

		return emp;
	}

5.0 web服务器

5.1.1 什么是服务器

将开发好的项目部署到一个容器中,服务器就是一个容器

5.1.2 什么是web服务器

web服务器就是web项目的容器,将开发好的web项目部署到web容器中,才能使网络中的用户通过浏览器进行访问

5.1.3 静态资源和动态资源

web项目中根据资源特性可以分为两类

  • 静态资源:网页中数据始终保持不变(HTML/CSS/JS/图片)
  • 动态资源:网页中的数据会根据用户的不同请求发生变化,网页中的数据会根据用户的意图进行变化

5.1.4 常见的服务器

  • Tomcat:apache开源,主流的服务器之一,多应用于javaweb项目开发
  • jetty:运行效率高于Tomcat
  • WebLogic:Oracle,收费

5.1.5 tomcat简介

Tomcat是Apache开源组织(apache.org)共享的Jakarta项目中的一个核心向,Tomcat开源免费、支持Java中的动态网页技术ServletJSP规范,因此Java开发者多使用Tomcat.

Tomcat目前最新版本是10.1(alpha),在企业主流使用8.5和9,我们的学习主要基于8.5.72版本;各个版本之间的最大区别就是对于JavaEE版本及Servlet规范的支持、依赖的JDK版本。Tomcat8.x全面支持Servlet3.x规范及JavaEE4规范。

Tomcat基于其先进的技术、稳定的性能深受Java开发者的青睐。

sun参与其中

Tomcat官网:https://tomcat.apache.org/

5.1.6 tomcat的下载和安装

在这里插入图片描述

选用压缩版,解压即用

解压时的注意事项

解压时目录层级不要多

解压时不要有中文路径

Tomcat目录结构(高危的面试问题)

  • bin 该目录存放的是可执行的二进制文件,例如:startup.bat用于启动tomcat服务器,shutdown.bat用于停止tomcat服务器
  • conf 存放tomcat的配置文件。server.xml可以配置tomcat的端口号,web.xml配置文件
  • lib 类库,存放web项目所运行时的基础类库
  • logs 存放tomcat的运行日志,记录服务器启动,运行异常及关闭等操作记录
  • temp 临时目录,存放tomcat运行时产生的临时文件
  • webapps 存放tomcat管理的web项目目录,此目录中默认部署了tomcat管理器等几个web项目
  • work tomcat可以运行动态网页,jsp生成的java代码

5.1.7启动和关闭Tomcat

双击 …\apache-tomcat-8.5.84\bin\startup.bat 关闭窗口,服务器默认就关闭了

建议使用双击 …\apache-tomcat-8.5.84\bin\stutdown.bat进行关闭

tomcat无法启动问题

tomcat是基于java语言的web服务器,它的运行依赖 jdk,因此在安装tomcat时需要保证计算机安装了jdk环境并正确环境变量,特别时JAVA_HOME一定要正确

tomcat控制台乱码问题处理

apache-tomcat-8.5.84\conf\logging.properties中的java.util.logging.ConsoleHandler.encoding = UTF-8

  • 将utf-8改为gbk
  • 将注释掉,添加#

5.1.8 web项目部署

部署 web项目到tomcat服务器下,当访问tomcat时,可以 访问到web服务器 下的资源响应给浏览器

访问的前提是服务器必须启动状态

访问路径:http://ip:端口号/项目/资源 (ip:localhost/本机的ip地址/127.0.0.1)

例如:http://localhost:8080

部署项目 :

​ 直接将 web项目拷贝到tomcat的webapps下即可

5.1.9 浏览器访问web服务器

项目部署完成后建议重启一个tomcat

静态重新加载,无需重启服务器

动态重现加载,需要重启服务器

浏览器输入网址:http://ip:端口/web-path/xxx.html

http:// web服务器的http传输协议

ip: 服务器所在计算机的ip的地址,例如:192.168.121.1 或者 127.0.0.1(回环地址) 或者 localhost(表示本机)

端口号:tomcat服务器占用的网络端口(默认8080,可以在conf/server.xml中修改端口)

web-path:tomcat中部署的web项目名的访问路径

xxx.html:页面路径

5.1.10 tomcat配置端口号

tomcat默认对的端口号为8080,可以在conf/server.xml中修改端口

端口号为1-65535中的数字,但2000以下的很多端口号都被一些系统绑定了,不建议使用

<!--conf/server.xml 69行-->
<Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

5.2 HTTP协议

web服务器可以接收 浏览器的请求(request),并将服务器中的web项目资源响应(response)给浏览器,浏览器与服务器之间进行网络通信遵循http协议

5.2.1 什么是http协议

http:超文本传输协议 (HypeText Transfer Protocol)

网络中的通讯协议

  • TCP协议:基于连接对的安全协议(浏览器与服务器之间建立连接,再通过连接发送数据)
  • UDP协议:基于广播/分发的非安全传输协议(不会建立连接)

HTTP超文本传输协议是运行在TCP协议基础之上的,基于请求与响应的模式,无状态的应用协议,是互联网中应用最广泛的一种网络协议

5.2.2 http协议的特点

基于连接通信:当 浏览器与服务器之间进行通信时,会优先建立网络 连接,通过网络连接进行通讯

短连接:在 http1.0中,浏览器向服务器发送请求建立连接,但该连接只作用于浏览器与 服务器之间的一次请求 与响应,这次请求与响应完成之后立刻断开连接

长连接:该连接不只作用于浏览器与 服务器之间的一次请求 与响应,如果过了几秒钟之后,没有新的请求,将断开连接

5.2.3HTTP协议通讯规则

通讯协议:浏览器与服务器之间需要共同遵守的规则

http协议请求:服务器对浏览器进行响应的同时,也需要遵守http响应规则

5.2.3.1 HTTP请求规则

说明:当浏览器发送请求时,浏览器已经实现了HTTP请求协议,基于协议发送请求的

浏览器查看请求步骤:

打开浏览器

F12打开调试窗口,点击network/网络

在浏览器输入网址进行访问

在network查看请求头信息(Request Headers)

url: 统一资源定位器 ,网址

在这里插入图片描述

5.2.3.2 HTTP响应规则

在这里插入图片描述

请求:浏览器访问服务器的过程 用户发送

响应:服务器给浏览器显示的内容 服务器发送

5.2.4 HTTP响应状态码

浏览器向服务器发送请求,服务器对浏览器进行响应时,会响应给浏览器一个状态码,不同的状态码表示 服务器 对请求的不同处理

状态码的分类

  • 1xx请求服务器 时,服务器未做出任何操作
  • 2xx表示服务器正常响应,并且响应成功
  • 3xx服务器只对浏览器进行了部分处理,通知浏览器进行下一步操作(缓存)
  • 4xx表示浏览器端错误:404 405
  • 5xx表示服务器端 错误

常见的响应状态码

  • 200响应成功
  • 302服务器临时重定向
  • 304服务器 没有任何变化
  • 400错误的请求数据
  • 404访问资源不存在
  • 405错误 的请求方式
  • 500访问的服务器端资源错误

5.3 Servlet简介

问题 :浏览器可以通过http协议请求web 服务器,访问服务器上的web资源,web资源可以分为静态资源和动态资源,静态资源可以直接存储在web服务器上提供给浏览器访问,动态资源该如何访问?

Servlet是放服务器端的java程序,能够接收http请求,处理http请求 ,并对http请求响应 动态页面的技术

该java类是运行在服务器下的,有服务器进行创建和管理

Servlet是javaEE(javaWEB)规范中的一个重要的组成部分

Servlet的作用:

  • 接收浏览器(客户端)端的http请求
  • 根据 用户的 请求进行 数据处理
  • 生成动态页面(网页中的数据是根据用户请求的动态 改变 )
  • 将生成 的 包含动态数据的网页 响应给客户端

5.4 Servlet的基本使用

Servlet是javaEE规范中的一部分,Servlet的开发需要依赖 javaEE环境,之前创建的纯java应用已经不能满足servlet的开发所需环境,我们需要创建JavaWEB工程

java工程:只引入 jdk标准类库(javase)

javaWEB工程 :引入 java企业级开发环境(javaee)

5.4.1 创建JavaEE工程

1.创建JavaWEB工程
在这里插入图片描述
2.配置 tomcat服务器

点击new按钮,选择tomcat server

配置tomcat服务器

在这里插入图片描述

3.选择web application项目 框架及版本
在这里插入图片描述

4.输入项目名
在这里插入图片描述

5.web项目的目录
在这里插入图片描述

5.4.2 创建Servlet

servlet是一个java程序,一个可以接收http请求的java类,因此需要实现http协议

在javaEE类库中有一个javax.servlet.http.HttpServlet实现了http协议

我们创建的类只需继承这个HttpServlet,同时就实现了HTTP协议,就能够接收http请求

1.创建一个类继承javax.servlet.http.HttpServlet

2.继承javax.servlet.http.HttpServlet类之后就可以接收http请求,我们把这样的类统一都称为servlet,类名以Servlet结尾(Servlet全称为servlet applet )

3.创建完成的Servlet类中,重写doPost/doGet用于处理用户的不同请求

5.4.3 配置Servlet的url

创建Servlet完成之后,需要配置url访问路径,然后将web项目运行在tomcat之上,就能够将配置的url在浏览器上访问到(通过url访问servlet)

自servlet3.0规则之后配置方式有两种

  • 基于web.xml配置文件进行配置
  • 基于注解
5.4.3.1 基于web.xml的方式配置servlet

打开java web工程,在web/WEB-INF/web.xml文件 配置如下

<!--配置HelloServlet的访问路径-->
    <!--配置对应的servlet类-->
    <servlet>
        <!--为需要配置的servlet起个名字-->
        <servlet-name>hello</servlet-name>
        <!--配置servlet的位置(全类名)-->
        <servlet-class>com.qf.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--配置url-->
    <servlet-mapping>
        <!--要求和servlet节点中的servlet-name一致-->
        <servlet-name>hello</servlet-name>
        <!--配置访问路径 要求以/开始 /表示的是项目的根据路径(http://localhost:8888/my/)-->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
5.4.3.2 基于注解

在创建Servlet类之上添加注解@WebServlet,在注解内配置url,url必须以 / 开头

注解可以和配置文件同时存在,url不可以重复(web.xml不可以重复,注解不可以重复,web.xml和注解不可以重复)

一个项目中的url是唯一的

@WebServlet("/my")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("get请求");
    }
    ...

5.4.4 IDEA部署web项目

同idea,将java web部署到tomcat下并执行tomcat

5.4.4.1 配置服务器

File/settings
在这里插入图片描述

5.4.4.2 部署web项目

将web项目 添加部署到tomcat

1.点击idea的左上角
在这里插入图片描述
2.进行项目部署
在这里插入图片描述
3.配置web项目的外部访问路径
在这里插入图片描述
4.启动tomcat
选择运行或者debug运行
在这里插入图片描述
5.浏览器访问测试

通过浏览器发送http请求,访问tomcat中的 web项目的servlet类

6.控制台乱码处理方式三,通过idea处理
在这里插入图片描述

5.4.5 post请求与get请求

servlet类中的
doGet和doPost是用来处理浏览的不同http请求的,在http协议中请求方式有多种(get/post/put/delete/option等),不同的请求方式传递数据是不同的

get请求:doGet方法

post请求:doPost方法

5.4.5.1 GET请求

使用get的方式进行请求服务器

参数是拼接在url之后的,以?开始的多个参数之间使用&进行连接,参数名和参数值使用=进行连接

例如:/hello?name=tom&password=123

发送get请求的方式

  • 超链接
<a href="hello">请求</a>

  • 浏览器地址栏
http://localhost:8081/demo01/hello
  • url重写的方式(拼接了参数)
<a href="hello?gender=男&hobby=学习">请求</a>
http://localhost:8081/demo01/hello?gender=1&hobby=study
  • form表单的默认提交方式,也就是method=get
<form action="hello" method="get">
    <input type="text" name="username"><br>
    <input type="password" name="password"><br>
    <input type="submit">
</form>

注意:

get方式是明文提交,提交的数据小,安全性较差

5.4.5.2 POST请求

使用post的 方式请求服务器,参数是在请求正文中的(request body中)

发送post请求方式

  • form表单method=post

注意:

post请求是密文传输,数据量几乎无限,安全性较高

5.5 Servlet原理解析

5.5.1 ServletAPI核心类和接口

Servlet接口,Servlet核心接口,包含声明等方法

ServletConfig接口,包含Servlet配置信息

GenericServlet抽象类,最普通的Servlet

HttpServlet抽象类,实现http协议的

ServletRequest封装所有请求信息

​ HttpServletRequest实现了http协议

ServletResponse封装所有响应信息

​ HttpServletResponse实现了http协议

5.5.2 Servlet类处理请求的流程

创建Servlet步骤

1.创建一个名为HelloServlet

2.继承javax.servlet.http.HttpServlet类

3.重写doGet/doPost

4.配置servlet的访问路径

在这里插入图片描述

5.5.3 Servlet生命周期

声明周期:从产生到消亡的过程

一个Servlet从创建到销毁的过程

1.构造方法,是由服务器调用的,只调用一次,由服务器创建对象的过程 单例的

2.init方法,初始化方法,只调用一次,可以servlet的信息进行初始化

3.service方法,每次发送http请求时都会调用一次(doGet/doPost是有service分化出来的,不是生命周期方法)

4.destory方法,销毁方法,服务器停止或者服务器销毁时调用,只调用一次

5.5.4 配置load-on-startup节点(在框架时会使用)

控制servlet的创建时间的

默认servlet是第一次调用时由服务器创建的

可以使用去修改创建时间,可以是服务器创建 的同时servlet立刻创建

大于0的数是服务器创建的同时创建,小于0默认 的情况

SpringMVC框架中适配器Servlet的基础

xml配置

<servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.qf.servlet.HelloServlet</servlet-class>
        <!--配置servlet的创建时间 该节点必须 是Servlet子节点中的最后一个节点-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

注解配置

@WebServlet(value="/MyServlet",loadOnStartup = 1)

5.5.5 Servlet的线程安全问题

因为 Servlet是单例的,当多个客户端并发的访问同一个Servlet实例时,tomcat会创建多个线程,多个线程会使用同一个Servlet实例,有可能导致线程安全问题

方案1:synchronized同步锁

@Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        synchronized (this){
            
        }
    }

方案2:实现SingleThreadMethod接口

我们可以让多有的Servlet类实现SingleThreadMethod接口,每个线程都会创建Servlet实例,这种方式会导致客户端请求效率变低,增加了服务器 频繁创建和销毁Servlet的开销,因此该方法不建议使用,已经过时

建议:在Servlet实例中尽量不要使用成员变量(属性)数据不安全的,数据不准确

5.5.6 Servlet核心对象

servlet是创建动态网页的,为服务器请求提供动态响应

servlet接收请求

servlet响应服务器端信息

5.5.6.1 HttpServletRequest

封装了http请求的所有信息

获取请求行信息

//请求行信息
//获取请求方式
String method = request.getMethod();
System.out.println(method);

//获取请求额url
String url = request.getRequestURL().toString();
System.out.println(url);

//获取请求参数中的值 http请求参数中的值,都是String类型
String username = request.getParameter("username");
System.out.println(username);
String stuno = request.getParameter("stuno");
System.out.println(Integer.parseInt(stuno));

//获取浏览器提交数据的协议及版本
String protocol = request.getProtocol();
System.out.println(protocol);

//请求字符串 ?后的内容
String queryString = request.getQueryString();
System.out.println(queryString);

获取请求头信息

//获取请求头中的所有数据
Enumeration<String> e = request.getHeaderNames();
while(e.hasMoreElements()){
    String key = e.nextElement();
    String value = request.getHeader(key);
    System.out.println(key+":"+value);
}

request对象处理中文乱码问题

浏览器向服务器 发送请求,包含中文,因为编码格式不统一,可能会出现中文 乱码
封装了http响应的所有信息

get请求在tomcat7之后,服务器默认处理完了

post请求提交的乱码处理

  • 设置请求的编码格式为 utf-8即可
  • request.setCharacterEncoding(“utf-8”);//在doGet/doPost的第一行
5.5.6.2 HttpServletResponse

封装了http响应的所有信息

//设置状态行
response.setStatus(200);

//设置响应头
response.setContentType("text/html; charset=utf-8");//以html的形式显示当前页面 响应页面的编码格式

//设置响应过程中的编码格式
response.setCharacterEncoding("utf-8");

//获取页面打印流
PrintWriter out = response.getWriter();
//进行动态页面的拼接
out.println("<html>");
out.println("<head>");
out.println("<meta charset='utf-8'>");
out.println("<title>这是响应的页面</title>");
out.println("</head>");
out.println("<body>");
out.println("hello 页面");
out.println(new Date());
out.println("</body>");
out.println("</html>");

5.6 连接JDBC

搭建JDBC环境

导入JDBC项目的jar包

1.在web/WEB-INF创建lib文件夹

2.将jar文件添加到lib中

3.选中jar文件右键—add as library

5.7 Servlet动态网页案例

员工管理系统

员工登录

员工注册

5.7.1 项目环境的搭建

JavaEE项目:jar文件需要添加到web/WEB-INF/lib 中

WEB-INF文件夹中,存在.class文件和相关的jar文件 真实部署在服务器下的文件夹

数据库表准备:Emp表

JDBC环境

​ 引入jdbc相关的jar包

​ 引入DBUtils项目的jar包

Junit环境

​ 引入单元测试环境

LomBok

​ 引入工具包

5.7.2 完成数据库操作

根据项目业务去完成对应的SQL编写

员工登录实现

根据员工名和员工编号进行登录,使用名字和编号进行sql的编写,若可以查询到输入则证明登录成功,否则登录失败

5.7.3 创建数据表对应的实体类

/**
 * 创建 EMP表对应的ORM映射实体Emp类
 * 属性和字段对应
 * 对象和记录对应
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class Emp {
    private Integer empno;
    private String ename;
    private Double sal;
    private Double comm;
    private Integer deptno;
}

5.7.4 编写LoginServlet

@WebServlet(name = "LoginServlet" ,value="/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");//处理post请求时的乱码
        response.setCharacterEncoding("utf-8");
        String empno = request.getParameter("empno");
        String ename = request.getParameter("ename");

        System.out.println(empno+":"+ename);
        //创建一个eno用于接收String转换的编号
        Integer eno = 1;
        try{
            eno = Integer.parseInt(empno);
        }catch (NumberFormatException e){
            e.printStackTrace();
        }

        //传入到jdbc
        //创建实现类对象
        EmpDaoImpl edi = new EmpDaoImpl();
        Emp loginEmp = edi.login(eno, ename);

        if(loginEmp!=null){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

5.8 重定向

可以进行页面跳转

response.sendRedirect("跳转的页面");

5.8.1 重定向跳转页面流程

浏览器请求AServlet,AServlet响应给客户端(浏览器)一个新的请求地址(servlet/jsp/html),让浏览器重新定向到新的地址

特点:

  • 重定向是浏览端行为

  • 浏览器向服务器发送两个请求

  • 重定向是由浏览器再次发送请求的,浏览器的地址栏会发生变化

  • 不能通过requset对象将AServlet中的数据内容发送到新的请求地址中

  • 使用重定向传递参数

  • 使用url重写的方式

5.9 请求转发

可以进行页面跳转

request.getRequestDispatcher("success.html")/*获取转发对象*/.forward(request,response)/*请求转发*/;

5.9.1 请求转发跳转页面的流程

浏览器请求AServlet,AServlet转发当前请求到另一个新的地址,服务器端进行的页面跳转

特点:

  • 转发是服务器行为
  • 浏览器只向服务器发送一个请求
  • 浏览器地址栏不会发生变化,停留在第一次请求的位置
  • 可以通过requset对象将AServlet中的数据内容发送到新的请求地址中

转发时是需要将数据带到另一Servlet或者JSP页面,转发的地址是Servlet/JSP

5.10Servlet版本

Servlet接口

内部有生命周期相关方法,和Servlet配置相关方法

GenericServlet抽象类

内部只有一个抽象方法(service)

HttpServlet抽象类

根据request.getMethod方法将不同的请求转换为doXxx方法

5.10.1 重定向跳转页面流程

5.10.2 Servlet的不足

1.开发方式麻烦:继承HttpServlet,重写doGet/doPost方法,Servlet配置等

2.项目更新麻烦:Servlet类中的代码若发生改变,需要重新编译重新启动服务器

3.网页呈现复杂:需要使用html进行页面拼接,同时配置页面打印流进行页面的打印

4.协同开发困难:UI负责对的页面美化,但的我们的页面是由Servlet提供的,不能保证UI懂java代码

5.11 JSP简介

JSP(java server page)基于Servlet的技术,运行在服务器之上,支持java语言的动态网页技术(就是在html上写java代码)

jsp是简化Servlet的设计 ,采用html嵌套java代码的形式进行动态网页的呈现,可以高效的进行动态web项目的设计

JSP的本质是一个Servlet

Jsp注释:<%–注释内容–%>

JSP指令:<%@ 内容%>

5.12 使用Eclipse配置tomcat

5.12.1 配置tomcat

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
若找不到servers,则可以在window–>show view–>Servers 若还是没有则window–>other–>server(Servers)

点击对应的连接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
确定—>finish 完成服务器的搭建

5.12.2Eclipse的tomcat的初始配置

1.双击服务器
在这里插入图片描述
2.修改基础配置
在这里插入图片描述

5.12.3 创建动态web项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.12.4 修改外部浏览器

在这里插入图片描述

在这里插入图片描述

5.12.5 修改jsp的默认编码格式

在这里插入图片描述

5.13 JSP详情

jsp和Servlet一样可以接收浏览器请求,并响应一个动态网页给浏览器

JSP是Servlet的一种高级封装,本质就是Servlet,可以在tomcat下的work文件夹中找到对应的Servlet代码(eclipse工具)jsp继承了HttpJspBase(HttpServlet的子类)

JSP文件需要依赖服务器运行,当浏览器请求一个JSP文件时,JSP会在服务器端自动转换为一个Servlet文件

使用JSP优点:在html中嵌入java代码,开发动态网页更加便捷

路径:path:\apache-tomcat-8.5.84\work\Catalina\localhost\projectpath\org\apache\jsp可以查看jsp对应的java代码

生成的代码
在这里插入图片描述

5.14 JSP开发的规则

jsp文件和html文件一样是视图,JSP创建在项目中的WebContent(eclipse)或者Web(idea)

jsp以.jsp为扩展名

jsp的文档内容

​ 在jsp的第一行需要通过<%@ page…%>声明为java语言

​ jsp文件的主体就是html代码,符合html的文档规范

5.14.1 jsp语法(java脚本语法)

jsp页面中可以编写java代码,编写的java代码就是页面的脚本

java代码必须写在**<% %>**中,可以写在jsp页面的任意位置

如下代码建议写在jsp的最上面,写在下面是可以运行的没有任何的影响,但可读性差

<%@page import="com.qf.pojo.Emp"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

若需要在页面中直接输出内容则使用**<%=变量 %>**

可以 使用脚本片段,**<% %>**可以分别的包裹不同java代码段

5.15 jsp注释

html文件注释:该注释可以显示在浏览器上 html注释中是无法注释掉jsp代码

html注释中的jsp代码仍然会被执行

<!--内容-->

jsp文档注释:会被转换为java代码中的注释

<%-- 内容 --%>

5.16 JSP编程指令

编译指令:在JSP文件转换成Java代码之后,编译成.class文件的过程中执行的指令

<%@ page %> : 声明当前JSP页面在web容器中的配置、引用

<%@ include %> : 在当前JSP中引用其他的资源(JSP、HTML)作为当前JSP的一部分

<%@ taglib %> : 引用第三方标签库、扩展JSP文件中的标签

5.16.1<%@ page %>指令

标签属性说明示例
language定义JSP中所用的脚本语言类型,默认javalanguage=“java”
contentType用于声明当前JSP文档的字符集编码contentType=“text/html;charset=UTF-8”
import声明当前JSP中的Java代码依赖的类import=“java.sql.Date”
pageEncoding声明当前JSP文档的解码格式pageEncoding=“UTF-8”
errorPage如果当前JSP出现异常则跳转到errorPage指向页面errorPage=“error.jsp”
isErrorPage定义当前页面是否可以作为错误页面isErrorPage=“true”

5.16.2 <%@ include %>指令

在当前的JSP中引用其他资源(JSP/HTML),作为当前JSP的一部分,被引入的页面不会单独的作为一个JSP编译而是作为一部分被引入到的JSP之后进行整体编译

引入的页面只需要一个HTML片段即可

静态引入:被引入的片段不会单独解析

5.16.3 <%@ taglib %>指令

引用第三方标签库、扩展JSP文件中的标签

5.17 JSP动作指令

jsp文件中除了支持标签的html标签库和编译指令以外,还可以编写jsp特有的动作指令(动作标签)

动作指令:在jsp页面中以jsp:开头,在jsp页面执行的过程中进行编译

5.17.1 jsp:include

动态引入资源(html/jsp),被引入的jsp先单独的进行编译

被引入的资源,会先编译一次

使用和静态引入是一样的,效果也是相同的

<!-- 动态引入 必须是闭合标签 -->
<jsp:include page="head.jsp"/>

5.17.2 jsp:useBean

<!-- 
	id是对象的变量名
	class是类的全限定名
 -->
<%Emp emp1 = new Emp(); %>
<!--等价代码-->
<jsp:useBean id="emp2" class="com.qf.pojo.Emp"></jsp:useBean>在jsp页面中创建java对象

5.17.3jsp:setProperty/jsp:getProperty

<!-- 
	property对应java对象的属性
	name为哪一个变量赋值
 -->
<jsp:setProperty property="empno" name="emp2" value="2"/>
<jsp:setProperty property="ename" name="emp2" value="jack"/>
<!-- 
	取值,是直接输出到页面上的
 -->
<jsp:getProperty property="empno" name="emp2"/>

5.17.4 jsp:forward

jsp页面的请求转发,请求大多使用servlet完成

<jsp:forward page="test7.jsp"></jsp:forward>

5.17.5 jsp:param

页面转发的同时携带参数

<jsp:forward page="test7.jsp">
	<jsp:param value="tom" name="name"/>
	<jsp:param value="17" name="age"/>
</jsp:forward>

5.18 JSP九大内置对象

可以在jsp页面中直接使用的对象

一个jsp文件在服务器上转换为java文件(Servlet类),在我们的jsp文件中嵌入的java代码会在_jspService中查看到,该方法内部可以找到jsp的内置对象

对象名类型说明
requestjavax.servlet.http.HttpServletRequest表示浏览器端请求对象,封装所有http请求信息
responsejavax.servlet.http.HttpServletResponse封装所有响应信息
pageContextjavax.servlet.jsp.PageContext表示当前jsp的上下文,可以获取当前jsp中的任何信息
sessionjavax.servlet.http.HttpSession表示当前浏览器与服务器之间的一次会话
applicationjavax.servlet.ServletContext当前web应用在服务器上的全局对象
configjavax.servlet.ServletConfig当前servlet的配置信息
outjavax.servlet.jsp.JspWriter向当前的jsp页面中打印内容,被<%=%>所代替
pagejava.lang.Object表示当前jsp对象,等价于this
exceptionjava.lang.Throwable需要当前jsp设置<%page isErrorPage=“true”%>,才可以在jsp页面中使用

5.19 四大作用域

JSP中有四个域对象,可以用来存储数据

pageContext 只能域范围是当前的jsp页面(存储数据只能在当前页面中使用)

​ servlet中是没有的

request 域范围为一次请求(请求转发就是一次请求)

​ servlet中是可以直接使用的额

session 一次会话,一次连接的多次请求,只要浏览器打开就是同一次session

​ servlet使用request.getSession())获取,再使用

application 作用于一个web的所有用户

​ serlet中this.getServletContext()获取再使用

方法:

域.setAttribute(String key,Object value);存值方法

域.getAttribute(String key);取值方法,返回值类型为Object

域.removeAttribute(String key);移除/删除存储的数据

JSP域对象中的request/session/application又被称为Servlet三大作用域

pageContext补充

<%
	//只能作用于当前页面,可以获取其他三个域的
	//就是为EL做辅助的 EL中的域对象是requestScope,sessionScope,applicationScope 而并不是request、session、application
	//从而导致,无法直接调用三个域的原有方法
	pageContext.getRequest();//获取request
	pageContext.getSession();//获取session
	pageContext.getServletContext();//获取application
	
	request.getContextPath();//获取项目名
	
	
%>

${pageContext.request.contextPath}
${param.name }

5.19.1 作用域传值

在某个Servlet/JSP中存储一个值,在另一个Servlet/JSP中获取到

//存值
//request域
request.setAttribute("name", "tom");
//session域 获取使用request.getSession();
HttpSession session = request.getSession();
session.setAttribute("age", 19);
//application域 获取this.getServletContext();
ServletContext application = this.getServletContext();
application.setAttribute("gender", "男");
//请求转发和重定向不能同时使用
//response.sendRedirect("test3.jsp");
request.getRequestDispatcher("test3.jsp").forward(request, response);

5.20 EL表达式(处理单个值)

5.20.1 EL域对象

表达式语音,Expression Language,应用于JSP页面的,可以更简单的便捷的获取域中的内容,进行页面渲染(代替<%%>的语法)

EL表达式语法${}

EL是默认忽略null的

el中的域对象对应jsp写法
pageScopepageContext
requestScoperequest
sessionScopesession
applicationScopeapplication

${requestScope.name}等价于<%=request.getAttribute(“name”) %>

el中域对象是可以省略的 默认是从pageScope–>requestScope–>sessionScope–>applicationScope

若使用省略写法,有域中重复的key值,则会优先使用最小域中的值

EL中自带类型转换

EL中是自动忽略空值的

5.20.2 EL隐式对象

处理四个域还有七个隐式对象,可以直接使用

对象不是可以省略

隐式对象说明
param获取request对象参数,${param.key}等价于<%=request.getParam(“key”)%>
paramValues获取的数据为数组,例如复选按钮
header获取HTTP请求头${header.contentPosition}
headerValue获取HTTP请求头的所有值
initParam获取上下文中的初始化参数
pageContext获取当前页面的pageContext(jsp最小的域)对象,${pageContext.request.contextPath}当前web应用在服务器上的访问路径,可以通过改隐式对象获取其他的域对象
cookie获取cookie中的值${cookie.username}

${requestScope.contextPath}认为是在request域中获取key为contentPath的value值

使用EL获取原本的request对象${pageContext.request.contextPath}获取项目名

5.20.3 EL运算符

数学运算符

运算符描述
+加法
-减法
*
/ or div
% or mod取余

逻辑运算符

运算符描述
== or eq等于判断
!= or ne不等
> or gt大于
< or lt小于
>= or ge大于等于
<= or le小于等于

逻辑运算符

运算符描述
&& or and
|| or or
! or not

判空

运算符描述
empty${empty key}若key为空值,则返回true

5.21 JSTL

jsp的标准标签库,用于jsp的标签,能够为jsp页面提供流程控制,类型转换等功能

作用:EL+JSTL进行jsp页面的渲染

EL处理单个数据的,数据量不确定时需要配置JSTL来使用

JSTL标签库提供了很多的类型的标签

  • c:核心标签库,提供流程控制等标签
  • fmt:转换标签库,提供了日期数值类型转换的额标签
  • sql,fn,x等

5.21.1JSTL的使用步骤

1.下载JSTL标签库的依赖jar https://mvnrepository.com/

2.将jar文件引入到web项目中

3.需要在jsp页面中引入jstl标签,通过<% taglib %>引入(jstl中包含了多种标签,每个库都需要独立的去引入)

5.21.2JSTL的使用

引入c库

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

c:out

<c:out value="a"></c:out>

c:if

<%
	request.setAttribute("score", 88);
%>
<%-- ${}等价的 --%>
<c:out value="a"></c:out>
<%-- if结构 --%>
<!-- if(true/false){

} -->
<c:if test="${score >= 90 }">
	<span>优秀</span>
</c:if>
<c:if test="${score < 90 }">
	<div>不优秀</div>
</c:if>

c:choose

<%-- c:choose多分支结构 可以包含c:when和一个c:otherwise --%>
<%request.setAttribute("score", 59); %>
<c:choose>
	<c:when test="${score >= 90 }">
		<span style="color:red;">优秀</span>
	</c:when>
	<c:when test="${score >= 80 }">
		<span style="color:green;">良好</span>
	</c:when>
	<c:when test="${score >= 70 }">
		<span style="color:blue;">中等</span>
	</c:when>
	<c:when test="${score >= 60 }">
		<span style="color:#0cc;">及格</span>
	</c:when>
	<c:otherwise>
		<span style="color:yellowgreen;">不及格</span>
	</c:otherwise>
</c:choose>

c:forEach

<%-- c:foreach:基本遍历 遍历集合/数组 --%>
<!-- 
	for(int i = 1;i<=100;i+=2){
		sout(i);
	}
 -->
<c:forEach begin="1" end="100" var="i" step="20">
	${i }<br>
</c:forEach>
<%
	List<Emp> list = new ArrayList<>();
	list.add(new Emp(1,"tom",8999.0,200.0,1,1));
	list.add(new Emp(2,"jack",8999.0,200.0,1,1));
	list.add(new Emp(3,"rose",8999.0,200.0,1,1));
	request.setAttribute("list", list);
%>
<!-- for(Emp emp:list){} -->
<c:forEach items="${list }" var="emp">
	${emp.empno }---${emp.ename }---${emp.deptno }<br>
</c:forEach>

5.21.3JSTL转换标签

引入转换标签库

<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:formatDate value="${date }" pattern="yyyy-MM-dd hh:mm:ss"/><br>
<fmt:formatDate value="${date }" pattern="hh:mm:ss"/>

<fmt:formatNumber value="99999" pattern="$000,000.00"/>

5.22 Servlet映射细节

关于servlet-mapping>url-pattern

同一个servlet可以被映射到多个url,即可以使用多个额节点,只要保证是同一个,并且不重复即可

<!--一个Servlet的多个去请求路径url-->
<servlet>
  	<servlet-name>login</servlet-name>
  	<servlet-class>com.qf.servlet.LoginServlet</servlet-class>
  </servlet>

  <servlet-mapping>
  	<servlet-name>login</servlet-name>
	<url-pattern>/login</url-pattern>  	
  </servlet-mapping>
  <servlet-mapping>
  	<servlet-name>login</servlet-name>
	<url-pattern>/a</url-pattern>  	
  </servlet-mapping>
  <servlet-mapping>
  	<servlet-name>login</servlet-name>
	<url-pattern>/b</url-pattern>  	
  </servlet-mapping>
<!--通过匹配多个url-->
<servlet-mapping>
  	<servlet-name>login</servlet-name>
  	<url-pattern>/c</url-pattern>
  	<url-pattern>/d</url-pattern>
  	<url-pattern>/e</url-pattern>
  	<url-pattern>/f</url-pattern>
  </servlet-mapping>
//注解写法
@WebServlet(value= {"/LoginServlet","/g","/h","/j"})
//或者使用
@WebServlet(urlPatterns = {"/LoginServlet","/g","/h","/j"})

5.22.1 Servlet映射的四种匹配方式

1.精确匹配

2.路径匹配 匹配规则:以/开头 ,以**/***结尾 (/*匹配项目下的所有资源)

@WebServlet("/vip/*")

可以匹配 发送请求时的路径中带有vip的

<a href="${pageContext.request.contextPath }/vip/a">123</a>

可以匹配到指定文件夹
在这里插入图片描述
3.后缀名匹配 以* . 开头 非法写法:/api/*.jsp

@WebServlet("*.jsp")

4.缺省匹配:固定值/ 匹配所有的servlet,不包含jsp

DispatcherServlet,Spring中的核心类,配置路径为/

@WebServlet("/")

5.23 ServletConfig接口

是Servlet中init方法参数,可以获取servlet的初始配置

使用web.xml的形式

<servlet>
  	<servlet-name>d</servlet-name>
  	<servlet-class>com.qf.servlet.DServlet</servlet-class>
  	<!-- servlet初始化参数 -->
  	<init-param>
  		<param-name>charset</param-name>
  		<param-value>utf-8</param-value>
  	</init-param>
    <!--初始化参数可以有多个-->
  </servlet>

使用注解的形式 :访问web.xml中的url获取web.xml的init; 直接访问注解的url获取注解中的init

@WebServlet(value = "DServlet" , initParams = {
    @WebInitParam(name = "username", value = "tom"),
	@WebInitParam(name = "password",value="123456")
})

5.24 ServletContext接口

(如何在request中获取application的操作)

application的数据类型

四种获取方式

//获取ServletContext的四种方式
ServletContext application1 = this.getServletContext();//推荐
ServletContext application2 = this.getServletConfig().getServletContext();
ServletContext application3 = request.getServletContext();//推荐
ServletContext application4 = request.getSession().getServletContext();

配置全局默认参数

<!-- 全局默认参数:是所有web应用共享的 -->
  <context-param>
  	<param-name>username</param-name>
  	<param-value>tom</param-value>
  </context-param>

5.25 配置页面

配置欢迎页面

<!-- 欢迎页面,该节点是可以省略,启动服务器的首页 默认是按照下面的六个页面的查询,可以修改自行替换 -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>

错误页面和异常页面的配置

<!-- 配置全局的错误页面,错误页面的配置都转发的形式 -->
  <error-page>
  	<error-code>404</error-code>
  	<location>/404.jsp</location>
  </error-page>
  <error-page>
  	<error-code>500</error-code>
  	<location>/500.jsp</location>
  </error-page>

5.26 Cookie的使用(浏览器行为)

会话跟踪机制:cookie,session

5.26.1 什么是cookie?

浏览器访问web服务器上的某个资源,由服务器的响应传递给浏览器,并存储在浏览器端的一小段数据

一旦web浏览器保存了来自服务器的cookie,那么再次访问(请求)时,就会通过请求将cookie传给web服务器

5.26.2 写cookie到浏览器(以键值对的形式存在的)

1.创建cookie :Cookie cookie = new Cookie(“username”,“tom”);

2.设置cookie: cookie.setMaxAge(60*60);//设置生命周期,以秒为单位

3.写cookie: respose.addCookie(cookie);//将cookie添加浏览器

//1.创建Cookie
Cookie cookie = new Cookie("username","tom");

//2.设置Cookie的生命周期
//若>0表示的cookie的时效(单位是s) 若=0浏览器关闭即销毁 若<0表示内存存储
cookie.setMaxAge(-100);

//3.将cookie添加到HTTP响应头中
response.addCookie(cookie);

5.26.3 服务器读取cookie

1.通过request对象获取所有的额cookie: Cookie[] cookies = request.getCookies();

2.获取cookie对象的key:String key = cookie.getName();

3.获取cookie对象的value: String value = cookie.getValue();

//读取cookie:当浏览器再请求时,通过request将cookie传到服务器
Cookie[] cookies = request.getCookies();
//做非空和长度限定
if(cookies != null && cookies.length>0) {
    for (Cookie cookie : cookies) {
        String key = cookie.getName();
        String value = cookie.getValue();
        System.out.println(key+"对应的值为:"+value);
    }
}

5.26.4 cookie的优点和限制

优点:

可以灵活的配置过期的规则

简洁,cookie中存储的是最简单的键值对格式的文本数据

数据的持久性,保存到浏览器中,在cookie过期之前都是持久保存的

限制:

数据存储的大小有限,大多数浏览器支持4k,8k的数据存储

用户可以设置禁用cookie,因此就限制了cookie的使用(如果一定要使用cookie,可以检查浏览器cookie是否可以是否,并提示用户开启cookie)

cookie是存在浏览器端的,有被篡改的风险,有潜在的安全隐患

5.27 HttpSession(服务器行为)

session:该对象就是浏览器打开到关闭的过程,这个过程被称为一次会话(浏览器访问服务器时建立一次连接)

session的特点

​ 服务器会为每一个浏览器/客户端分配一个session,session存储在服务器上的

​ 同一个浏览器发送的多次请求,同属于一次会话,共享一个Session对象

session的原理

1.当浏览器端第一次请求时,服务器会为当前的浏览器创建一个session对象,同时将sessionID存储到cookie中(服务器完成的)并发送到浏览器,存储到浏览器上

2.当浏览器再次访问服务器时,会在请求头中携带存储着sessionID的cookie返回到服务器端

5.27.1 获取session对象

jsp的内置对象,servlet获取方式request.getSession

<%=
	session.getId()

%>
${pageContext.session.id }
//获取session
HttpSession session = request.getSession();
//获取sessionId
System.out.println(session.getId());

5.27.2 session失效

session有自己生命周期,默认的生命时间为30min,服务器会将之间的session自动销毁,创建一个新的session对象

浏览器端的cookie被禁用了,对应的JSessioID也就无法查到了

seession失效的解决方案

服务器端可以设置session的生命周期

//设置生命周期 时间到就会更换新的session对象
session.setMaxInactiveInterval(10);
//销毁session方法
session.invalidate();

可以使用web.xml设置生命周期

<!-- session配置 以分钟为单位 -->
<session-config>
    <session-timeout>1</session-timeout>
</session-config>

cookie被禁用可以使用url重写的方式,将jsessionid拼接在url之后,明文拼接,不安全不推荐使用

5.28 过滤器Filter

过滤器是位于浏览器与服务器之间的一道过滤技术,可以在浏览器与客户端进行预处理业务

作用

执行多个Servlet的公共代码,解决了代码的冗余问题,提供代码的复用性(例如:中文乱码问题)

Filter也有类似于Servlet的生命周期doFilter可以理解为service

5.28.1 过滤器的使用

创建过滤器

实现Filter接口,并重写内部的方法,在doFilter中去编写业务,若向继续访问则需要调用chain.doFilter(request, response);方法

若不想允许通行,则请求转发或重定向到浏览器到

package com.qf.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

/**

 * url-pattern的配置方式和servlet是一样的

 * servlet值精准访问,filter是进行过滤
   */
   @WebFilter("/*")
   public class CharacterFilter implements Filter {

   /**

    * Default constructor. 
      */
      public CharacterFilter() {
      // TODO Auto-generated constructor stub
      }

   /**

    * @see Filter#destroy()
      */
      public void destroy() {
      // TODO Auto-generated method stub
      }

   /**

    * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
      */
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      System.out.println("过滤之前....");

      //过滤器链,访问当前的filter去查找下一个filter,若没有filter了则正常请求
      //放行操作,只有调用该方法,才能继续下次访问
      //chain.doFilter(request, response);

      System.out.println("过滤之后...");
      }

   /**

    * @see Filter#init(FilterConfig)
      */
      public void init(FilterConfig fConfig) throws ServletException {
      // TODO Auto-generated method stub
      }

}

配置过滤器 目的:可以拦截/过滤哪些资源

过滤的优先级

​ 若使用web.xml在上面的配置优先于下面的配置

​ 若使用注解,优先级是按照类名的字母顺序进行过滤的

注解的形式:

<!-- 配置filter -->
  <filter>
  	<filter-name>character</filter-name>
  	<filter-class>com.qf.filter.CharacterFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>character</filter-name>
	<url-pattern>/*</url-pattern>  	
  </filter-mapping>

配置文件的形式:

@WebFilter("/*")

url规则和servlet的url规则是一致的UI想爱你改

6. AJAX

$(function(){
    $('#name').blur(function(){
        /**
					 * 默认就是get请求
					 * 参数1 url(请求的url)
					 * 参数2 param(请求参数)
					 * 参数3 fn(回调函数)
					 * 参数4 typ(回调函数的参数类型)
					 */
        var param = {
            name:$('#name').val()
        }
        $.post('CheckNameServlet',param,function(res){
            if(res == 0){
                $('#check').html('用户名以存在').css('color','red');
            }else{
                $('#check').html('*').css('color','red');
            }
        },'text');
    });
});

在不刷新网页的前提下,与服务器进行交互,可以完成局部的刷新

典型案例:用户名重复验证

ajax不是一种编程语言,而使用javascript代码完成实现前后端的异步交互的技术

ajax的js核心对象 XMLHttpRequest(javascript对象)

6.1 servlet准备

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//模拟查询数据库中ename
		List<String> names = new ArrayList<>();
		names.add("王班长");
		names.add("王世君");
		names.add("王状状");
		names.add("刘桂全");
		names.add("盖家斌");
		
		//接收用户的输入
		String name = request.getParameter("name");
		//设置响应页面的编码格式
		response.setContentType("text/html; charset=utf-8");
		
		//使用ajax时接收数据时,不用跳转页面,交给前端完成
		if(names.contains(name)/*若存在于数据库*/) {
			response.getWriter().append("0");
		}else {
			response.getWriter().append("1");
		}
	}

6.2 前端代码准备

<body>
<!-- 使用ajax:不是非必须使用name属性 -->
<input type="text" id="name">
<span id="check"></span>
<script type="text/javascript">
	window.onload = function(){
		//获取两个标签对象
		var name = document.querySelector("#name");
		var check = document.querySelector("#check");
		name.onblur = function(){
			//前端验证
			
			//后端验证
			//1.获ajax核心的对象 兼容ie浏览器
			var xhr = new XMLHttpRequest() || new ActiveXObject("Micsoft.XMLHTTP");
			
			//2.设置请求方式和url
			xhr.open('POST','CheckNameServlet?name='+name.value);
			
			//3.发送请求
			xhr.send();
			
			//4.请求成功之后的回调函数
			xhr.onreadystatechange = function(){
				//判断成功状态
				if(xhr.readyState == 4){
					if(xhr.status == 200){
						//5.接收响应的数据
						var result = xhr.responseText;
						// console.log(result);
						// check.innerHTML = result;
						if(result == 0){
							check.innerHTML = "用户名不可用";
							check.style.color = 'red';
						}else{
							check.innerHTML = "*";
							check.style.color = 'red';
						}
					}
				}
			}
		}
	}
</script>
</body>

6.3 jqAjax

ajax技术被很多前端框架所封装

<input type="text" id="name">
		<span id="check"></span>
		<script src="./js/jq.js" type="text/javascript" charset="utf-8"></script>
		<script type="text/javascript">
			$(function(){
				$('#name').blur(function(){
					//jq中封装的ajax函数 参数是{}字面量对象
					$.ajax({
						url:'CheckNameServlet',//请求的url 可以使用?&的形式进行数据的拼接
						data:{//data中是请求参数的数据  以键值对的形式存在的
							name:$('#name').val()
							// password:$().val()
						},
						type:"get",
						//成功后的回调函数,参数为服务器端响应的数据
						success:function(res){
							if(res == 0){
								$('#check').html('用户名以存在').css('color','red');
							}else{
								$('#check').html('*').css('color','red');
							}
						},
						//es6语法
						error(){
							//服务器端异常时调用的回调函数
							console.log("呀,服务器异常了啊");
						}
					});
				});
			})
		</script>

6.4 jqAjax简化写法

$(function(){
    $('#name').blur(function(){
        /**
					 * 默认就是get请求 
					 * get可以处理json数据,封装好的java对象改为的json对象
					 * 参数1 url(请求的url)
					 * 参数2 param(请求参数)
					 * 参数3 fn(回调函数)
					 * 参数4 typ(回调函数的参数类型)
					 */
        var param = {
            name:$('#name').val()
        }
        $.get('CheckNameServlet',param,function(res){
            if(res == 0){
                $('#check').html('用户名以存在').css('color','red');
            }else{
                $('#check').html('*').css('color','red');
            }
        },'text');
    });
});
$(function(){
    $('#name').blur(function(){
        /**
					 * 默认就是get请求 
					 * get可以处理json数据,封装好的java对象改为的json对象
					 * 参数1 url(请求的url)
					 * 参数2 param(请求参数)
					 * 参数3 fn(回调函数)
					 * 参数4 typ(回调函数的参数类型)
					 */
        var param = {
            name:$('#name').val()
        }
        $.get('CheckNameServlet',param,function(res){
            if(res == 0){
                $('#check').html('用户名以存在').css('color','red');
            }else{
                $('#check').html('*').css('color','red');
            }
        },'text');
    });
});

7. JSON

一种数据格式,用于前后端分离式项目的数据交换,也有技术使用json做配置文件(微信小程序)

数据格式

最基本的json数据:{“key”:“value”,“key”:“value”…} javapojo可以封装

json数组:[{json对象},{json},{jso},{j}…] javalist集合额可以封装

复杂的json数据:{“key”:{json},“key”:{json}} javamap集合可以封装

//最简单的json数据
var json = {
    "empno":"1",
    "ename":"王世君",
    "sal":20000.0,
    "comm":800.0,
    "deptno":1
}
//json数组
var arr = [
{
"empno":"1",
"ename":"王世君1",
"sal":20000.0,
"comm":800.0,
"deptno":1
},
{
"empno":"2",
"ename":"王世君2",
"sal":20000.0,
"comm":800.0,
"deptno":1,
},
{
"empno":"3",
"ename":"王世君3",
"sal":20000.0,
"comm":800.0,
"deptno":1,
},
]
var json = {
//分页的数据
"pager":{
"start":1,
"end":10,
"currPage":1,
"count":200,
"limit":10
},
//查询到的数据
"emps":[
{
"empno":"1",
"ename":"王世君1",
"sal":20000.0,
"comm":800.0,
"deptno":1
},
{
"empno":"2",
"ename":"王世君2",
"sal":20000.0,
"comm":800.0,
"deptno":1,
},
{
"empno":"3",
"ename":"王世君3",
"sal":20000.0,
"comm":800.0,
"deptno":1,
},
]
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值