视频来自:尚硅谷JavaWeb课程
核心技术点有:Servlet程序、Filter过滤器、Listener监听器、jsp页面、EL表达式、JSTL标签库、jQuery框架、Cookie技术、Session会话、JSON使用、Ajax请求
1.HTML和CSS
java文件是需要预先编译,再由java虚拟机跑起来。但HTML文件它不需要编译,直接由浏览器进行解析执行。
网页的组成部分:
- 内容(结构):使用html技术展示
- 表现:指的是这些内容在页面上的展示形式,比如布局、颜色、大小等等。一般使用CSS技术展示
- 行为:指的是页面中元素与输入设备交互的响应。一般使用javascript技术实现
1.1 HTML
通过标签来标记要显示的网页中的各个部分
1.1.1书写规范
<!DOCTYPE html> <!--约束,声明-->
<html lang="zh_CN"> <!--html语言的开始-->
<head> <!--表示头部信息,一般包含三部分内容,title标签,css样式,js代码-->
<meta charset="UTF-8"> <!--表示当前页面所用字符集-->
<title>标题</title> <!--表示标题-->
</head>
<body>
hello <!--body标签表示html的主体内容-->
</body>
</html> <!--表示整个html页面的结束-->
1.1.2HTML标签
-
标签的格式:
<标签名>封装的数据</标签名>
-
标签名大小写不敏感
-
标签拥有自己的属性
- 基本属性: 可以修改简单的样式效果
- 事件属性: 可以直接设置事件响应后的代码
-
标签可以分为单标签和双标签
- 单标签: <标签名 /> 换行 br 水平线hr
- 双标签: <标签名>封装的数据</标签名>
-
常用标签文档:w3cschool.CHM
1.1.3常用标签介绍
1.font字体标签
在网页上显示 我是字体标签 , 并修改字体为 宋体, 颜色为红色
<body>
<!-- 字体标签
需求 1: 在网页上显示 我是字体标签 , 并修改字体为 宋体, 颜色为红色。
font 标签是字体标签,它可以用来修改文本的字体,颜色,大小(尺寸)
color 属性修改颜色
face 属性修改字体
size 属性修改文本大小
-->
<font color="red" face="宋体" size="7">我是字体标签</font>
</body>
2.特殊字符
把 < br>换行标签 变成文本 转换成字符显示在页面上
<body>
<br>换行 <br/> fu kd
</body>
3.标题标签
标题标签是h1-h6,align为对齐属性
<body>
<!-- 标题标签
需求 1: 演示标题 1 到 标题 6 的
h1 - h6 都是标题标签
align 属性是对齐属性
left 左对齐(默认)
center 剧中
right 右对齐
-->
<h1 align="left">标题 1</h1>
<h2 align="center">标题 2</h2>
<h3 align="right">标题 3</h3>
<h4>标题 4</h4>
<h5>标题 5</h5>
<h6>标题 6</h6>
<h7>标题 7</h7>
</body>
4.普通的超链接
在网页中所有点击之后可以跳转的内容都是超连接
<body>
<!-- a 标签是 超链接
href 属性设置连接的地址
target 属性设置哪个目标进行跳转
_self 表示当前页面(默认值)
_blank 表示打开新页面来进行跳转
-->
<a href="https://www.baidu.com" target="_blank">百度</a><br/>
<a href="https://www.google.com" target="_self">谷歌</a>
</body>
5.列表标签
无序列表、有序列表
需求 1: 使用无序, 列表方式, 把东北 F4, 赵四, 刘能, 小沈阳, 宋小宝, 展示出来
<body>
<!--需求 1: 使用无序, 列表方式, 把东北 F4, 赵四, 刘能, 小沈阳, 宋小宝, 展示出来
ul 是无序列表 ol是有序列表
type 属性可以修改列表项前面的符号
li 是列表项
-->
<ul type="none">
<li>赵四</li>
<li>刘能</li>
<li>小沈阳</li>
<li>宋小宝</li>
</ul>
</body>
6.Img标签
使用 img 标签显示一张美女的照片。 并修改宽高, 和边框属性
<body>
<!--需求 1: 使用 img 标签显示一张美女的照片。 并修改宽高, 和边框属性
img 标签是图片标签,用来显示图片
src 属性可以设置图片的路径
width 属性设置图片的宽度
height 属性设置图片的高度
border 属性设置图片边框大小
alt 属性设置当指定路径找不到图片时,用来代替显示的文本内容
在 JavaSE 中路径也分为相对路径和绝对路径.
相对路径:从工程名开始算
绝对路径:盘符:/目录/文件名
在 web 中路径分为相对路径和绝对路径两种
相对路径:
. 表示当前文件所在的目录
.. 表示当前文件所在的上一级目录
文件名 表示当前文件所在目录的文件,相当于 ./文件名 ./ 可以省略
绝对路径:
正确格式是: http://ip:port/工程名/资源路径
错误格式是: 盘符:/目录/文件名
-->
<img src="1.jpg" width="200" height="260" border="1" alt="美女找不到"/>
<img src="../2.jpg" width="200" height="260" />
<img src="../imgs/3.jpg" width="200" height="260" />
<img src="../imgs/4.jpg" width="200" height="260" />
<img src="../imgs/5.jpg" width="200" height="260" />
<img src="../imgs/6.jpg" width="200" height="260" />
</body>
7.表格标签
需求 1: 做一个 带表头的 , 三行, 三列的表格, 并显示边框
需求 2: 修改表格的宽度, 高度, 表格的对齐方式, 单元格间距。
<body>
<!--
需求 1: 做一个 带表头的 , 三行, 三列的表格, 并显示边框
需求 2: 修改表格的宽度, 高度, 表格的对齐方式, 单元格间距。
table 标签是表格标签
border 设置表格标签
width 设置表格宽度
height 设置表格高度
align 设置表格相对于页面的对齐方式cellspacing 设置单元格间距
tr 是行标签
th 是表头标签
td 是单元格标签
align 设置单元格文本对齐方式
b 是加粗标签
-->
<table align="center" border="1" width="300" height="300" cellspacing="0">
<tr>
<th>1.1</th>
<th>1.2</th>
<th>1.3</th>
</tr>
<tr>
<td>2.1</td>
<td>2.2</td>
<td>2.3</td>
</tr>
<tr>
<td>3.1</td>
<td>3.2</td>
<td>3.3</td>
</tr>
</table>
</body>
8.跨行跨列表格
新建一个五行, 五列的表格, 第一行, 第一列的单元格要跨两列, 第二行第一列的单元格跨两行, 第四行第四列的单元格跨两行两列
<body>
<!-- 需求 1:
新建一个五行, 五列的表格,第一行, 第一列的单元格要跨两列,第二行第一列的单元格跨两行,第四行第四列的单元格跨两行两列。
colspan 属性设置跨列
rowspan 属性设置跨行
-->
<table width="500" height="500" cellspacing="0" border="1">
<tr>
<td colspan="2">1.1</td>
<td>1.3</td>
<td>1.4</td>
<td>1.5</td>
</tr>
<tr>
<td rowspan="2">2.1</td>
<td>2.2</td>
<td>2.3</td>
<td>2.4</td>
<td>2.5</td>
</tr>
<tr>
<td>3.2</td>
<td>3.3</td>
<td>3.4</td>
<td>3.5</td>
</tr>
<tr>
<td>4.1</td>
<td>4.2</td>
<td>4.3</td>
<td colspan="2" rowspan="2">4.4</td>
</tr>
<tr>
<td>5.1</td>
<td>5.2</td>
<td>5.3</td>
</tr>
</table>
</body>
9.iframe框架标签
ifarme 标签它可以在一个 html 页面上,打开一个小窗口,去加载一个单独的页面.
<body>
我是一个单独的完整的页面<br/><br/>
<!--ifarme 标签可以在页面上开辟一个小区域显示一个单独的页面
ifarme 和 a 标签组合使用的步骤:
1 在 iframe 标签中使用 name 属性定义一个名称
2 在 a 标签的 target 属性上设置 iframe 的 name 的属性值
-->
<iframe src="3.标题标签.html" width="500" height="400" name="abc"></iframe>
<br/>
<ul>
<li><a href="0-标签语法.html" target="abc">0-标签语法.html</a></li>
<li><a href="1.font 标签.html" target="abc">1.font 标签.html</a></li>
<li><a href="2.特殊字符.html" target="abc">2.特殊字符.html</a></li>
</ul>
</body>
10.表单标签
- 表单就是 html 页面中,用来收集用户信息的所有元素集合.然后把这些信息发送给服务器.
需求 1:创建一个个人信息注册的表单界面。 包含用户名, 密码, 确认密码。 性别(单选) , 兴趣爱好(多选) , 国籍(下拉列表) 。隐藏域, 自我评价(多行文本域) 。 重置, 提交。
- form表单的显示:
1.input type=text 是文件输入框 value 设置默认显示内容
2.input type=password 是密码输入框 value 设置默认显示内容
3.input type=radio 是单选框 name 相同属性可以进行分组 checked="checked"表示默认选中
4.input type=checkbox 是复选框 checked="checked"表示默认选中
5.input type=reset 是重置按钮 value 属性修改按钮上的文本
6.input type=submit 是提交按钮 value 属性修改按钮上的文本
7.input type=button 是按钮 value 属性修改按钮上的文本
8.input type=file 是文件上传域
9.input type=hidden 是隐藏域 当我们要发送某些信息, 而这些信息, 不需要用户参与, 就可以使用隐藏域(提交的时候同时发送给服务器)
10.select 标签是下拉列表框 option 标签是下拉列表框中的选项 selected="selected"设置默认选中
11.textarea 表示多行文本输入框 (起始标签和结束标签中的内容是默认值)
rows 属性设置可以显示几行的高度
cols 属性设置每行可以显示几个字符宽度
- 表单提交细节,form中的属性
form 标签是表单标签
action 属性设置提交的服务器地址
method 属性设置提交的方式 GET(默认值)或 POST
表单提交的时候, 数据没有发送给服务器的三种情况:
1、 表单项没有 name 属性值
2、 单选、 复选(下拉列表中的 option 标签) 都需要添加 value 属性, 以便发送给服务器
3、 表单项不在提交的 form 标签中
GET 请求的特点是:
1、 浏览器地址栏中的地址是: action 属性[+?+请求参数]
请求参数的格式是: name=value&name=value
2、 不安全
3、 它有数据长度的限制
POST 请求的特点是:
1、 浏览器地址栏中只有 action 属性值
2、 相对于 GET 请求要安全
3、 理论上没有数据长度的限制
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="https://www.baidu.com" method="get">
<input type="hidden" name="action" value="login">
<h1 align="center">用户注册</h1>
<table align="center">
<tr>
<td>用户名称:</td>
<td>
<input type="text" name="user"/>
</td>
</tr>
<tr>
<td>用户密码:</td>
<td>
<input type="password" />
</td>
</tr>
<tr>
<td>确认密码:</td>
<td>
<input type="password" name="password" />
</td>
</tr>
<tr>
<td>性别:</td>
<td>
<input type="radio" name="sex" checked = "checked" value="boy">男
<input type="radio" name="sex" value="girl">女
</td>
</tr>
<tr>
<td>兴趣爱好:</td>
<td>
<input type="checkbox" name="hobby" value = "篮球" checked = "checked">篮球
<input type="checkbox" name="hobby" value = "足球">足球
<input type="checkbox" name="hobby" value = "游泳">游泳
<input type="checkbox" name="hobby" value = "跑步">跑步
</td>
</tr>
<tr>
<td>国籍:</td>
<td>
<select name="country">
<option value="none">--请选择国籍--</option>
<option value="cn">中国</option>
<option value="us">美国</option>
<option value="rs">俄罗斯</option>
<option value="uk">英国</option>
</select>
</td>
</tr>
<tr>
<td>自我评价:</td>
<td>
<textarea name="desc"cols="30" rows="10">请输入自我评价:</textarea>
</td>
</tr>
<tr>
<td><input type="reset"></td>
<td align="center"><input type="submit"></td>
</tr>
</table>
</form>
</body>
</html>
11.其他标签:
需求 1: div、 span、 p 标签的演示
<body>
<!--需求 1: div、 span、 p 标签的演示
div 标签 默认独占一行
span 标签 它的长度是封装数据的长度
p 段落标签 默认会在段落的上方或下方各空出一行来(如果已有就不再空)
-->
<div>div 标签 1</div>
<div>div 标签 2</div>
<span>span 标签 1</span>
<span>span 标签 2</span>
<p>p 段落标签 1</p>
<p>p 段落标签 2</p>
</body>
1.2 CSS
CSS是层叠样式表单,是用于(增强)控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。
1.2.1语法规则
选择器{
属性:值;
}
/*注释的内容*/
1.2.2CSS和HTML结合方式
- 第一种:直接在标签的style属性上设置"key: value value;", 修改标签样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--需求 1: 分别定义两个 div、 span 标签, 分别修改每个 div 标签的样式为: 边框 1 个像素, 实线, 红色。 -->
<div style="border: 1px solid red;">div 标签 1</div>
<div style="border: 1px solid red;">div 标签 2</div>
<span style="border: 1px solid red;">span 标签 1</span>
<span style="border: 1px solid red;">span 标签 2</span>
</body>
</html>
问题:这种方式的缺点?
1.如果标签多了,样式多了,代码量非常庞大
2.可读性非常差
3.CSS代码没什么复用性可言
- 第二种:在head标签中,使用style标签来定义各种自己需要的css样式
格式:xxx{Key : value value}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--style 标签专门用来定义 css 样式代码-->
<style type="text/css">
/* 需求 1: 分别定义两个 div、 span 标签, 分别修改每个 div 标签的样式为: 边框 1 个像素, 实线, 红色。 */
div{
border: 1px solid red;
}
span{
border: 1px solid red;
}
</style>
</head>
<body>
<div>div 标签 1</div>
<div>div 标签 2</div>
<span>span 标签 1</span>
<span>span 标签 2</span>
</body>
</html>
问题:
1.只能在同一页面内复用代码,不能在多个页面中复用css代码
2.维护起来不方便,实际项目中有成千上万的页面,每个页面修改,太麻烦
- 第三种:把 css 样式写成一个单独的css 文件,再通过link标签引入即可复用
使用html的 标签导入css样式文件
css文件:
span{
border: 1px red solid;
}
div{
border: 1px blue solid;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS基本语法</title>
<!-- -link标签专门用来引入css样式代码->
<link rel="stylesheet" type="text/css" href="1.css">
</head>
<body>
<div>落霞与孤鹜齐飞,秋水共长天一色</div>
</body>
</html>
1.2.3CSS选择器
- 标签名选择器
标签名选择器的格式是:
标签名{
属性:值;
}
标签名选择器,可以决定哪些标签被动的使用这个样式
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS选择器</title>
<style type="text/css">
div{
color: blue;
font-size: 30px;
border: 1px yellow solid;
}
span{
color: yellow;
font-size: 20px;
border: 5px blue dashed;
}
</style>
</head>
<body>
<!--
需求1:在所有div标签上修改字体颜色为蓝色,字体大小30个像素。边框为1像素黄色实线。
并且修改所有span 标签的字体颜色为黄色,字体大小20个像素。边框为5像素蓝色虚线。
-->
<div>div标签1</div>
<div>div标签2</div>
<span>span标签1</span>
<span>span标签2</span>
</body>
</html>
- id选择器:
id选择器的格式是:
#id 属性值{
属性:值;
}
id选择器,可以让我们通过id属性值有选择性的去使用这个样式
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ID 选择器</title>
<style type="text/css">
#id001{
color: blue;
font-size: 30px;
border: 1px yellow solid;
}
#id002{
color: red;
font-size: 20px;
border: 5px blue dotted ;
}
</style>
</head>
<body>
<!--需求 1: 分别定义两个 div 标签,第一个 div 标签定义 id 为 id001 , 然后根据 id 属性定义 css 样式修改字体颜色为蓝色,字体大小 30 个像素。 边框为 1 像素黄色实线。
第二个 div 标签定义 id 为 id002 , 然后根据 id 属性定义 css 样式 修改的字体颜色为红色, 字体大小 20 个像素。边框为 5 像素蓝色点线。-->
<div id="id002">div 标签 1</div>
<div id="id001">div 标签 2</div>
</body>
</html>
- 类选择器
class类选择器的的格式是:
.class属性值{
属性:值;
}
class 类型选择器, 可以通过 class 属性有效的选择性地去使用这个样式。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>class 类型选择器</title>
<style type="text/css">
.class01{
color: blue;
font-size: 30px;
border: 1px solid yellow;
}
.class02{
color: grey;
font-size: 26px;
border: 1px solid red;
}
</style>
</head>
<body>
<!--需求 1: 修改 class 属性值为 class01 的 span 或 div 标签, 字体颜色为蓝色, 字体大小 30 个像素。 边框为 1 像素黄色实线。
需求 2: 修改 class 属性值为 class02 的 div 标签, 字体颜色为灰色, 字体大小 26 个像素。 边框为 1 像素红色实线。-->
<div class="class02">div 标签 class01</div>
<div class="class02">div 标签</div>
<span class="class02">span 标签 class01</span>
<span>span 标签 2</span>
</body>
</html>
- 组合选择器
组合选择器的格式是:
选择器1,选择器2,选择器n{
属性:值;
}
组合选择器可以让多个选择器公用一个css样式代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>class 类型选择器</title>
<style type="text/css">
.class01 , #id01{
color: blue;
font-size: 20px;
border: 1px yellow solid;
}
</style>
</head>
<body>
<!--需求 1: 修改 class="class01" 的 div 标签 和 id="id01" 所有的 span 标签,
字体颜色为蓝色, 字体大小 20 个像素。 边框为 1 像素黄色实线。-->
<div id="id01">div 标签 class01</div> <br />
<span >span 标签</span> <br />
<div>div 标签</div> <br />
<div>div 标签 id01</div> <br />
</body>
</html>
1.2.4CSS常用样式
1.字体样式:
color:red;字体颜色
font-size:20px;字体大小
2.宽度
width:19px;
3.高度
height:20px;
4.背景颜色
backgroud-color:red;
5.边框
border:1px solid red;
6.DIV居中
margin-left:auto;
margin-right:auto;
7.文本居中
text-align:center;
8.超链接去下划线
text-decoration:none;
9.表格细线
table{
bordr:1px solid black;设置边框
border-collapse:collapse;将边框合并
}
td,th{
border:1px solid black;
}
10.列表去除修饰
ul{
list-style:none;
}
2.JavaScript
JS是弱类型语言,Java是强类型语言。
- 交互性(它可以做的就是信息的动态交互)
- 安全性(不允许直接访问本地磁盘)
- 跨平台性(只要是可以解释JS的浏览器都可以执行,和平台无关
网页调试:FN+F12
var 变量名 = []; 数组 var 变量名 = {}; 对象
2.1 JavaScript和html代码结合
- 第一种方式:
只需要在head或者body标签中,使用script标签来书写js
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
// alert是JavaScript语言提供的一个警告框函数。
// 它可以接收任意类型的参数,这个参数就是警告框的提示信息
alert("hello world!")
</script>
</head>
- 第二种方式:
使用script标签引入单独的javascript代码文件
1.js
alert("hello world");
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--
现在需要使用script引入外部的js文件来执行
src 属性专门用来引入js文件路径(可以是相对路径,也可以是绝对路径)
script标签可以用来定义js代码,也可以用来引入js文件
但是,两个功能二选一使用。不能同时使用两个功能
-->
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript">
alert("国哥现在可以帅了");
</script>
</head>
2.2 变量
- JavaScript的变量类型:
- 数值类型: number
- 字符串类型:string
- 对象类型:object
- 布尔类型:boolean
- 函数类型:function
- JavaScript里的特殊值:
- undefined:未定义,所有js变量未赋初值时,默认值
- null:空值
- NaN:not a Number 非数值 var a = 1 ; var b = “abc”; alert(a*b)// NaN
- JS中定义变量的格式:
- var 变量名;
- var 变量名 = 值;
1.关系(比较运算)
-
等于: == 等于是简单的做字面值的比较
-
全等于: === 除了做字面值的比较外,还会比较两个变量的数据类型
var a = "12";
var b = 12;
alert(a == b); //true
alert(a === b); //false
2.逻辑运算
与运算:&& 或运算:|| 非运算:!
-
在js语言中,所有变量都可以作为boolean变量去使用,0 、 null、 undefined、 ””(空串) 都认为是 false;
-
&& 且运算 :
- 第一种: 当表达式全为真的时候。 返回最后一个表达式的值。
- 第二种: 当表达式中, 有一个为假的时候。 返回第一个为假的表达式的值
-
||或运算:
- 第一种情况: 当表达式全为假时, 返回最后一个表达式的值
- 第二种情况: 只要有一个表达式为真。 就会把回第一个为真的表达式的值
-
并且 && 与运算 和 ||或运算 有短路。短路就是说, 当这个&&或||运算有结果了之后 。 后面的表达式不再执行 。
var d = "";
if (d) {
alert("空串为真");
} else {
alert("空串为假");
}
2.3 数组
格式:
var 数组名 = [];//空数组
var 数组名 = [1, ‘abc’, true];// 定义数组同时赋值元素(可以不同类型)
- js 中的数组, 只要我们通过数组下标赋值, 那么最大的下标值, 就会自动的给数组做扩容操作,数组长度为最大下标
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
var arr = [true, 1]; // 定义一个空数组
// alert( arr.length ); // 0
// javaScript语言中的数组,只要我们通过数组下标赋值,那么最大的下标值,就会自动的给数组做扩容操作。
arr[2] = "abc";
alert(arr.length); //3
// alert(arr[1]);// undefined
// 数组的遍历
for (var i = 0; i < arr.length; i++) {
alert(arr[i]);
}
</script>
</head>
2.4 函数
- 第一种定义:
function 函数名(形参列表){
函数体;
(return xx;)
}
function sum(num1, num2){
var result = num1 + num2;
return result;
}
alert(sum(1,2));
- 第二种定义:
var 函数名 = function(形参列表){
函数体;
(return xx;)
}
var sum = function(num1, num2){
return num1 + num2;
}
-
JS中函数的重载会直接覆盖掉上一次的定义
-
函数的arguments隐形参数(只在function函数中),类似于java中的可变长参数public void fun(Object …args);操作类似于数组
// 需求:要求 编写 一个函数。用于计算所有参数相加的和并返回
function sum(num1,num2) {
var result = 0;
for (var i = 0; i < arguments.length; i++) {
if (typeof(arguments[i]) == "number") {
result += arguments[i];
}
}
return result;
}
//arguments是可变长参数数组
alert( sum(1,2,3,4,"abc",5,6,7,8,9) );
2.5 js中的自定义对象
- Object形式的自定义对象
对象的定义:
var 变量名 = new Object();//对象实例化,空对象
变量名.属性名 = 值; //定义一个属性
变量名.函数名 = function(){}//定义一个函数
对象的访问:
对象名.属性/函数名();
var obj = new Object();
obj.name = "fkd";
obj.age = 22;
obj.fun = function(){
alert("姓名:"+this.name+",年龄:"+this,age);
}
obj.fun()
- {}花括号形式的自定义对象
对象的定义:
var 变量名 = { //空对象
属性值:值; //定义一个属性
属性值:值; //定义一个属性
函数名: function(){} //定义一个函数
};
对象的访问:
变量名.属性 / 函数名();
var obj = {
name:fkd,
age:18,
fun:function(){
alert("姓名:"+this.name+",年龄:"+this.age);
}
}
alert(obj.name);
obj.fun();
2.6 js中的事件
事件是电脑输入设备与页面进行交互的响应
1. 常用的事件
- **onload加载完成事件: ** 页面加载完成后,常用于js代码初始化
- **onclick单击事件:**常用于按钮的点击响应操作
- **onblur失去焦点事件:**常用于输入框失去焦点后验证其输入内容是否合法
- **onchange内容发生改变事件:**常用于下拉列表和输入框内容发生改变后的操作
- **onsubmit表单提交事件:**常用于表单提交前,验证所有表单项是否合法
2.事件注册
事件注册就是告诉浏览器,当事件响应后要执行哪些操作代码。
-
静态注册事件: 通过 html 标签的事件属性直接赋于事件响应后的代码
-
动态事件注册:通过js代码得到标签的dom对象,再通过dom对象.事件名 = function(){} 这种形式赋于事件响应后的代码。动态注册的基本步骤:
1.获取标签对象
2.标签对象.事件名 = function(){}
3.js事件
onload加载完成事件
- 静态事件:
<body onload = "alert('静态注册事件')">
</body>
在head中定义函数:
<script type="text/javascript">
// onload事件的方法
function onloadFun() {
alert('静态注册onload事件,所有代码');
}
</script>
<body onload = "onloadFun();">
</body>
- 动态注册事件:
// onload事件动态注册。是固定写法
<script type="text/javascript">
window.onload = function () {
alert("动态注册的onload事件");
}
</Script>
onclick事件
<script type="text/javascript">
function onclickFun(){
alert("静态注册onclick事件");
}
//动态注册 onclick 事件
window.onload = function(){
// 1 获取标签对象
/*
* document 是JavaScript语言提供的一个对象(文档)<br/>
* get 获取
* Element 元素(就是标签)
* By 通过。。 由。。经。。。
* Id id属性
* getElementById通过id属性获取标签对象
**/
var btnObj = document.getElementById("12345");
// 2 通过标签对象.事件名 = function(){}
btnObj.onclick = function(){
alert("动态这侧onclick事件");
}
}
</script>
<body>
<!--静态注册onClick事件-->
<button onclick = "onclickFun()">按钮1</button>
<!--动态注册onClick事件-->
<button id = "12345">按钮2</button>
</body>
onblur事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
// 静态注册失去焦点事件
function onblurFun() {
// console是控制台对象,是由JavaScript语言提供,专门用来向浏览器的控制器打印输出, 用于测试使用FN+F12
// log() 是打印的方法
console.log("静态注册失去焦点事件");
}
// 动态注册 onblur事件
window.onload = function () {
//1 获取标签对象
var passwordObj = document.getElementById("password");
//2 通过标签对象.事件名 = function(){};
passwordObj.onblur = function () {
console.log("动态注册失去焦点事件");
}
}
</script>
</head>
<body>
用户名:<input type="text" onblur="onblurFun();"><br/>
密码:<input id="password" type="text" ><br/>
</body>
</html>
onchange事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//静态注册事件
function onchangeFunc(){
alert("选项已经改变了")
}
//动态注册事件
window.onload = function (){
//1.获取标签对象
var onchangeObj = document.getElementById("123");
//2.对象名.事件名调用事件
onchangeObj.onchange = function (){
alert("选项已经改变了");
}
}
</script>
</head>
<body>
<div><select name="option" onchange="onchangeFunc()">
<option>选项1</option>
<option>选项2</option>
<option>选项3</option>
<option>选项4</option>
</select>
</div>
<div>
<select name="option" id="123">
<option>选项1</option>
<option>选项2</option>
<option>选项3</option>
<option>选项4</option>
</select>
</div>
</body>
</html>
onsubmit事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" >
// 静态注册表单提交事务
function onsubmitFun(){
// 要验证所有表单项是否合法,如果,有一个不合法就阻止表单提交
alert("静态注册表单提交事件----发现不合法");
//js返回值靠return
return flase;
}
window.onload = function () {
//1 获取标签对象
var formObj = document.getElementById("form01");
//2 通过标签对象.事件名 = function(){}
formObj.onsubmit = function () {
// 要验证所有表单项是否合法,如果,有一个不合法就阻止表单提交
alert("动态注册表单提交事件----发现不合法");
return false;
}
}
</script>
</head>
<body>
<!--return false 可以阻止 表单提交 -->
<form action="http://localhost:8080" method="get" onsubmit="return onsubmitFun();">
<input type="submit" value="静态注册"/>
</form>
<form action="http://localhost:8080" id="form01">
<input type="submit" value="动态注册"/>
</form>
</body>
</html>
2.7 DOM模型
DOM(Document Object Model)文档对象模型,就是把文档中的标签,属性,文本,转换成为对象来管理。
Document对象:
Document 对象的理解:
- 第一点: Document 它管理了所有的 HTML 文档内容。
- 第二点: document 它是一种树结构的文档。有层级关系。
- 第三点: 它让我们把所有的标签都对象化。
- 第四点: 我们可以通过 document 访问所有的标签对象。
html标签对象化
正则表达式:
表示要求字符串中,是否包含字母e
var patt = new RegExp("e");
var patt = /e/; // 也是正则表达式对象
表示要求字符串中,是否包含字母a或b或c
var patt = /[abc]/;
表示要求字符串,是否包含小写字母
var patt = /[a-z]/;
表示要求字符串,是否包含任意大写字母
var patt = /[A-Z]/;
表示要求字符串,是否包含任意数字
var patt = /[0-9]/;
表示要求字符串,是否包含字母,数字,下划线
var patt = /\w/;
表示要求 字符串中是否包含至少一个a
var patt = /a+/;
表示要求 字符串中是否 *包含* 零个 或 多个a
var patt = /a*/;
表示要求 字符串是否包含一个或零个a
var patt = /a?/;
表示要求 字符串是否包含连续三个a
var patt = /a{3}/;
表示要求 字符串是否包 至少3个连续的a,最多5个连续的a
var patt = /a{3,5}/;
表示要求 字符串是否包 至少3个连续的a,
var patt = /a{3,}/;
表示要求 字符串必须以a结尾
var patt = /a$/;
表示要求 字符串必须以a打头
var patt = /^a/;
^:从头开始 $:到结束
要求字符串中是否*包含* 至少3个连续的a
var patt = /a{3,5}/;
要求字符串,从头到尾都必须完全匹配
var patt = /^a{3,5}$/;
2.7.1.Document对象中方法
- document.getElementById(elementId)
通过标签的 id 属性查找标签 dom 对象, elementId 是标签的 id 属性值
- document.getElementsByName(elementName)
通过标签的 name 属性查找标签 dom 对象, elementName 标签的 name 属性值
- document.getElementsByTagName(tagname)
通过标签名查找标签 dom 对象。 tagname 是标签名
- document.createElement( tagName)
方法, 通过给定的标签名, 创建一个标签对象。 tagName 是要创建的标签名
getElementByID方法:返回指定id的第一个对象
/*
* 需求:当用户点击了较验按钮,要获取输出框中的内容。然后验证其是否合法。<br/>
* 验证的规则是:必须由字母,数字。下划线组成。并且长度是5到12位。
* */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<script type="text/javascript">
function clickFun(){
//当要操纵一个标签时,首先要获取标签对象
//获取输入框标签对象
var userObj = document.getElementById("username");
//提示框标签对象
var spanObj = document.getElementById("userspan")
//正则表达式:验证的规则是:必须由字母,数字。下划线组成。并且长度是5到12位
var patt = /^\w{5,12}$/;
//获取输入框的值
var usertext = userObj.value;
if(patt.test(usertext)){
// innerHTML 表示起始标签和结束标签中的内容
// innerHTML 这个属性可读,可写
// 匹配图像地址可在外部写完后粘贴进取,自动匹配
spanObj.innerHTML = "<img src=\"right.png\" width=\"18\" height=\"18\">";
}else{
spanObj.innerHTML = "<img src=\"wrong.png\" width=\"18\" height=\"18\">";
}
}
</script>
</head>
<body>
用户名:<input type="text" id="username">
<span id="userspan" style="color: red ">
</span>
<button id="button1" onclick="clickFun()">验证</button>
</body>
</html>
getElementsByName:返回带有指定名称的对象集合
/*
* 需求:多选框,具有全选,全部选,反选的功能
* */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
// 全选
function checkAll() {
// 让所有复选框都选中
// document.getElementsByName();是根据 指定的name属性查询返回多个标签对象集合
// 这个集合的操作跟数组 一样
// 集合中每个元素都是dom对象
// 这个集合中的元素顺序是他们在html页面中从上到下的顺序
var hobbies = document.getElementsByName("hobby");
// checked表示复选框的选中状态。如果选中是true,不选中是false
// checked 这个属性可读,可写
for (var i = 0; i < hobbies.length; i++){
hobbies[i].checked = true;
}
}
//全不选
function checkNo() {
var hobbies = document.getElementsByName("hobby");
// checked表示复选框的选中状态。如果选中是true,不选中是false
// checked 这个属性可读,可写
for (var i = 0; i < hobbies.length; i++){
hobbies[i].checked = false;
}
}
// 反选
function checkReverse() {
var hobbies = document.getElementsByName("hobby");
for (var i = 0; i < hobbies.length; i++) {
hobbies[i].checked = !hobbies[i].checked;
}
}
</script>
</head>
<body>
兴趣爱好:
<input type="checkbox" name="hobby" value="cpp" checked="checked">C++
<input type="checkbox" name="hobby" value="java">Java
<input type="checkbox" name="hobby" value="js">JavaScript
<br/>
<button onclick="checkAll()">全选</button>
<button onclick="checkNo()">全不选</button>
<button onclick="checkReverse()">反选</button>
</body>
</html>
getElementsByTagName:返回带有指定标签名称的对象集合
// 全选
function checkAll() {
alert( document.getElementById("btn01") );
// document.getElementsByTagName("input");
// 是按照指定标签名来进行查询并返回集合
// 这个集合的操作跟数组 一样
// 集合中都是dom对象
// 集合中元素顺序 是他们在html页面中从上到下的顺序。
var inputs = document.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++){
inputs[i].checked = true;
}
}
注:
- document 对象的三个查询方法, 如果有 id 属性, 优先使用 **getElementById **方法来进行查询
- 如果没有 id 属性, 则优先使用getElementsByName 方法来进行查询
- 如果 id 属性和 name 属性都没有最后再按标签名查 getElementsByTagName
- 以上三个方法, 一定要在页面加载(从上至下执行完页面)完成(windows.onload = function{内部是加载完页面执行})之后执行, 才能查询到标签对象。
createElement
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
window.onload = function () {
// 现在需要我们使用js代码来创建html标签,并显示在页面上
// 标签的内容就是:<div>国哥,我爱你</div>
var divObj = document.createElement("div"); // 在内存中 <div></div>
// divObj.innerHTML = "国哥,我爱你"; // <div>国哥,我爱你</div>,但,还只是在内存中
//创建文本对象方式添加内容
var textNodeObj = document.createTextNode("国哥,我爱你"); // 有一个文本节点对象 #国哥,我爱你
divObj.appendChild(textNodeObj); // <div>国哥,我爱你</div>
// 添加子元素
document.body.appendChild(divObj);
}
</script>
</head>
<body>
</body>
</html>
2.7.2节点的常用属性和方法
节点就是标签对象
1.方法:
- 通过具体的元素节点调用,**getElementsByTagName()**方法, 获取当前节点的指定标签名孩子节点
- appendChild( oChildNode )
可以添加一个子节点, oChildNode 是要添加的孩子节点
2.属性:
- childNodes
属性, 获取当前节点的所有子节点 - firstChild
属性, 获取当前节点的第一个子节点 - lastChild
属性, 获取当前节点的最后一个子节点 - parentNode
属性, 获取当前节点的父节点 - nextSibling
属性, 获取当前节点的下一个节点 - previousSibling
属性, 获取当前节点的上一个节点 - className
用于获取或设置标签的 class 属性值 - innerHTML
属性, 表示获取/设置起始标签和结束标签中的内容(包含标签、属性、内容) - innerText
属性, 表示获取/设置起始标签和结束标签中的文本(只取所有文本)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>dom查询</title>
<link rel="stylesheet" type="text/css" href="style/css.css" />
<script type="text/javascript">
window.onload = function(){
//1.查找#bj节点
//获取要操作的按钮对象
var btn01Ele = document.getElementById("btn01");
btn01Ele.onclick = function () {
var bjObj = document.getElementById("bj");
alert(bjObj.innerHTML);
}
//2.查找所有li节点
var btn02Ele = document.getElementById("btn02");
btn02Ele.onclick = function(){
var lis = document.getElementsByTagName("li");
alert(lis.length);
};
//3.查找name=gender的所有节点
var btn03Ele = document.getElementById("btn03");
btn03Ele.onclick = function(){
var genders = document.getElementsByName("gender");
alert(genders.length)
};
//4.查找#city下所有li节点
//能连续调用,因为还是DoM对象
var btn04Ele = document.getElementById("btn04");
btn04Ele.onclick = function(){
//1 获取id为city的节点
//2 通过city节点.getElementsByTagName按标签名查子节点
var lis = document.getElementById("city").getElementsByTagName("li");
alert(lis.length)
};
//5.返回#city的所有子节点
var btn05Ele = document.getElementById("btn05");
btn05Ele.onclick = function(){
//1 获取id为city的节点
//2 通过city获取所有子节点
alert(document.getElementById("city").childNodes.length);
};
//6.返回#phone的第一个子节点
var btn06Ele = document.getElementById("btn06");
btn06Ele.onclick = function(){
// 查询id为phone的节点
alert( document.getElementById("phone").firstChild.innerHTML );
};
//7.返回#bj的父节点
var btn07Ele = document.getElementById("btn07");
btn07Ele.onclick = function(){
//1 查询id为bj的节点
var bjObj = document.getElementById("bj");
//2 bj节点获取父节点
alert( bjObj.parentNode.innerHTML );
};
//8.返回#android的前一个兄弟节点
var btn08Ele = document.getElementById("btn08");
btn08Ele.onclick = function(){
// 获取id为android的节点
// 通过android节点获取前面兄弟节点
alert( document.getElementById("android").previousSibling.innerHTML );
};
//9.读取#username的value属性值
var btn09Ele = document.getElementById("btn09");
btn09Ele.onclick = function(){
alert(document.getElementById("username").value);
};
//10.设置#username的value属性值
var btn10Ele = document.getElementById("btn10");
btn10Ele.onclick = function(){
document.getElementById("username").value = "国哥你真牛逼";
};
//11.返回#bj的文本值
var btn11Ele = document.getElementById("btn11");
btn11Ele.onclick = function(){
alert(document.getElementById("city").innerHTML);
// alert(document.getElementById("city").innerText);
};
};
</script>
</head>
<body>
<div id="total">
<div class="inner">
<p>
你喜欢哪个城市?
</p>
<ul id="city">
<li id="bj">北京</li>
<li>上海</li>
<li>东京</li>
<li>首尔</li>
</ul>
<br>
<br>
<p>
你喜欢哪款单机游戏?
</p>
<ul id="game">
<li id="rl">红警</li>
<li>实况</li>
<li>极品飞车</li>
<li>魔兽</li>
</ul>
<br />
<br />
<p>
你手机的操作系统是?
</p>
<ul id="phone"><li>IOS</li><li id="android">Android</li><li>Windows Phone</li></ul>
</div>
<div class="inner">
gender:
<input type="radio" name="gender" value="male"/>
Male
<input type="radio" name="gender" value="female"/>
Female
<br>
<br>
name:
<input type="text" name="name" id="username" value="abcde"/>
</div>
</div>
<div id="btnList">
<div><button id="btn01">查找#bj节点</button></div>
<div><button id="btn02">查找所有li节点</button></div>
<div><button id="btn03">查找name=gender的所有节点</button></div>
<div><button id="btn04">查找#city下所有li节点</button></div>
<div><button id="btn05">返回#city的所有子节点</button></div>
<div><button id="btn06">返回#phone的第一个子节点</button></div>
<div><button id="btn07">返回#bj的父节点</button></div>
<div><button id="btn08">返回#android的前一个兄弟节点</button></div>
<div><button id="btn09">返回#username的value属性值</button></div>
<div><button id="btn10">设置#username的value属性值</button></div>
<div><button id="btn11">返回#bj的文本值</button></div>
</div>
</body>
</html>
3. jQuery
JQuery就是JavaScript和Query,它是辅助javascript开发的js类库
- 使用jQuery一定要引入jQuery库
<script type="text/javascript" src="../script/jquery-1.7.2.js"></script>
-
jQuery中的$是核心函数
- 传入的参数是[函数]时,表示页面加载之后,相当于window.onload = function(){}
$(funtion(){ }); 等价于: $(document).ready(function(){ });
- 传入的参数是[HTML字符串]时,会对我们创建这个html标签对象
$("<button id=\"btnId\">SayHello</button>").appendTo("body");
- 传入参数是[选择器字符]
$("#id属性值"); id选择器,根据id查询标签对象 $("标签名"); 标签名选择器,根据指定的标签名查询标签对象 $(".class属性值"); 类型选择器,可以根据class属性值查询标签对象
- 传入参数为[DOM对象时],会把dom对象转化为jQuery对象
var $btnObj = $("#btnId"); $($btnObj);
-
为按钮添加响应函数的步骤
- 使用jQuery查询到标签对象
var $btnObj = $("#btnId");
- 使用标签对象.click(function(){})
$btnId.click(function(){ alert(""); })3.1 jQuery对象与dom对象
-
jQuery函数的一般传入参数是设置,不传参数是获取
3.1 jQuery对象与Dom对象
-
Dom对象([object HTML 标签名 Element] )
- 通过 getElementById()查询出来的标签对象是 Dom 对象
- 通过 getElementsByName()查询出来的标签对象是 Dom 对象
- 通过 getElementsByTagName()查询出来的标签对象是 Dom 对象
- 通过 createElement() 方法创建的对象, 是 Dom 对象
-
jQuery对象 [object Object]
- 通过 JQuery 提供的 API 创建的对象, 是 JQuery 对象
$("<button id=\"btnId\">SayHello</button>");
- 通过 JQuery 包装的 Dom 对象, 也是 JQuery 对象
//Dom对象 var btnObj = document.getElementById("dom2dom"); //jQuery对象 $(btnObj);
- 通过 JQuery 提供的 API 查询到的对象, 是 JQuery 对象
$("#buttonObj");
-
jQuery对象的本质:
是dom对象的数组+jQuery提供的一系列功能函数
$btnObj = init(4) [button#dom2dom, button#dom2jQuery, button#jQuery2jQuery, button#jQuery2dom]
-
jQuery对象和Dom对象使用区别
- jQuery对象不能使用Dom对象的属性和方法
- Dom对象也不能使用jQuery对象的属性和方法
-
Dom对象和jQuery对象的转换
- dom对象 => jQuery对象
var $obj = $(dom对象);
- jQuery对象 => dom对象
var dom = $obj[下标];
3.2 jQuery选择器
1.基本选择器
# ID选择器 | 根据id查找标签对象 | $("#button01") |
---|---|---|
.class选择器 | 根据class查找标签对象 | $(".myclass") |
element 选择器: | 根据标签名查找标签对象 | $(“button”) |
*** 选择器:** | 表示任意的, 所有的元素 | $("*") |
selector1, selector2 组合选择器: | 合并选择器 1, 选择器 2 的结果并返回 | $(“div,span.Myclass”) |
数组中的顺序是标签在页面中的顺序。span.Myclass为同时满足标签名为span以及class属性是Myclass的对象。
<script type="text/javascript">
//页面加载完之后
$(function (){
//1.选择 id 为 one 的元素 "background-color","#bbffaa"
$("#btn1").click(function (){
//设置css样式
$("#one").css("background-color", "#bbffaa");
});
//2.选择 class 为 mini 的所有元素
$("#btn2").click(function (){
$(".mini").css("background-color", "#bbffaa");
});
//3.选择 元素名是 div 的所有元素
$("#btn3").click(function (){
$("div").css("background-color", "#bbffaa");
});
//4.选择所有的元素
$("#btn4").click(function (){
$("*").css("background-color", "#bbffaa");
});
//5.选择所有的 span 元素和id为two的元素
$("#btn5").click(function (){
$("span, #two").css("background-color", "#bbffaa");
});
});
</script>
2.层级选择器:
ancestor descendant | 后代选择器 :在给定的祖先元素下匹配所有的后代元素 | $(“form input”) |
---|---|---|
parent > child | 子元素选择器:在给定的父元素下匹配所有紧挨的子元素,孙子元素不算 | $(“form > div”) |
prev + next | 相邻元素选择器: 匹配所有紧接在 prev 元素后的 next 元素(与prev同级) | $(“form + input”) |
prev ~ sibings | 之后的兄弟元素选择器: 匹配 prev 元素之后的所有 siblings 元素(与prev同级) | $(“form ~ input”) |
3.过滤选择器:
- 基本过滤器
根据标签位置
:first | 获取第一个元素 | $(“div:first”) |
---|---|---|
:last | 获取最后一个元素 | $(“li:last”) |
:not(selector) | 去除所有与给定选择器匹配的元素 | $(input:not(:checked)) |
:even | 匹配所有索引值为偶数的元素, 从 0 开始计数 (第一、三行) | $(“tr:even”) |
:odd | 匹配所有索引值为奇数的元素, 从 0 开始计数 (第二、四行) | $(“tr:even”) |
**:eq(index) ** | 匹配一个给定索引值的元素 | $(“tr:eq(0)”) |
:gt(index) | 匹配所有大于给定索引值的元素 | $(“tr:gt(1)”) |
:lt(index) | 匹配所有小于给定索引值的元素 | $(“tr:lt(1)”) |
:header | 匹配如 h1, h2, h3 之类的标题元素 | $(":header").css(“background”,“red”) |
:animated | 匹配所有正在执行动画效果的元素 | $(":animated") |
索引从0开始计数,可以一次筛选
//选出没有执行动画的最后一个div
$(div:not(:animated):last)
//选择class不为 one 的所有 div 元素
$("div:not(.one)")
- 内容过滤器:
根据标签内容
:contains(text) | 匹配包含给定文本的元素 | $(“div:contains(‘John’)”) |
---|---|---|
:empty | 匹配所有不包含子元素或者文本的空元素 | $(“td:empty”) |
:parent | 匹配含有子元素或者文本的元素 (非空) | $(“td:parent”) |
:has(selector) | 匹配含有选择器所匹配的元素的元素 | $(“div:has§”) |
//选择含有class为mini元素的div元素
$(div:has(.mini))
- 属性过滤器
根据标签属性
[attribute] | 匹配包含给定属性的元素 | $(“div[id]”) |
---|---|---|
**[attribute=value] ** | 匹配给定的属性是某个特定值的元素 | $(“div[name = ‘newsletter’]”) |
[attribute!=value] | 匹配所有不含有指定的属性, 或者属性不等于特定值的元素。 | $(“div[name != ‘bewsletter’]”) |
[attribute^=value] | 匹配给定的属性是以某些值开始的元素 | $(“input[name ^= ‘news’ ]”) |
[attribute$=value] | 匹配给定的属性是以某些值结尾的元素 | $(“input[name $= ‘letter’ ]”) |
[attribute*=value] | 匹配给定的属性是以包含某些值的元素 | $(“input[name *= ‘man’ ]”) |
[selector1] [selector2] [selector3] | 复合属性选择器, 需要同时满足多个条件时使用 | $(input[id] [name = ‘man’]) |
//选取属性值含有title但是不等于test的元素
$(div[title][title != 'test'])
- 表单过滤器
筛选具有指定type类型的标签
:input | 匹配所有 input, textarea, select 和 button 元素 | $(":input") |
---|---|---|
**:text ** | 匹配所有 文本输入框 | $(":text") |
**:password ** | 匹配所有的密码输入框 | $(":password") |
:radio | 匹配所有的单选框 | $(":radio") |
:checkbox | 匹配所有的复选框 | $(":checkbox") |
:submit | 匹配所有提交按钮 | $(":submit") |
:image | 匹配所有 img 标签 | $(":image") |
:reset | 匹配所有重置按钮 | $(":reset") |
:button | 匹配所有 input type=button 按钮 | $(":button") |
:file | 匹配所有 input type=file 文件上传 | $(":file") |
:hidden | 匹配所有不可见元素 display:none 或 input type=hidden | $(“input : hidden”) |
- 表单对象属性过滤器
//单选框复选框选中checked = “checked”
<input type = "radio" checked = “checked”/>
//多选框选中 selected = "selected"
:enabled | 匹配所有可用元素 | $(“input:enabled”) |
---|---|---|
:disabled | 匹配所有不可用元素 | $(“input:disabled”) |
:checked | 匹配所有选中的单选, 复选, 和下拉列表中选中的 option 标签对象 | $("input:checked) |
:selected | 匹配所有选中的 option | $(“select option:selected”) |
//1.对表单内 可用input 赋值操作
$("#btn1").click(function(){
//jQuery对象有.val("")方法修改值
$(":text:enabled").val("New Value");
});
//2.对表单内 不可用input 赋值操作
$("#btn2").click(function(){
$(":text:disabled").val("New Value Too");
});
//3.获取多选框选中的个数 使用size()方法获取选取到的元素集合的元素个数
$("#btn3").click(function(){
alert($(":checkbox:checked").size());
});
//4.获取多选框,每个选中的value值
$("#btn4").click(function(){
var $eles = $(":checkbox");
//each方法是jQuery对象提供的用来遍历的方法,
// 在遍历function函数中有一个this对象,就是当前遍历到的dom对象
$eles.each(function (){
alert(this.value);
});
});
//5.获取下拉框选中的内容
$("#btn5").click(function(){
//获取option标签对象
var $options = $("select option:checked");
//获取option标签文本内容
$options.each(function (){
alert(this.innerHTML);
})
});
- jQuery元素筛选
jQuery对象的方法
eq() | 获取给定索引的元素 | $(“div”).eq(3) |
---|---|---|
first() | 获取第一个元素 | $(“div”).first() |
last() | 获取最后一个元素 | $(“div”).last() |
filter(exp) | 留下匹配的元素 | $(“div”).firter(“even”) |
is(exp) | 判断是否匹配给定的选择器, 只要有一个匹配就返回, true | $("#one").is(":empty") |
has(exp) | 返回包含有匹配选择器的元素的元素 | $(“div”).has(".mini") |
not(exp) | 删除匹配选择器的元素 | $(“div”).not(".one") |
children(exp) | 返回匹配给定选择器的子元素 | $(“body”).children(“div.one”) |
find(exp) | 返回匹配给定选择器的后代元素 | $(“body”).find(“div.mini”) |
next() | 返回当前元素的下一个兄弟元素 | $("#one").next(“div”) |
nextAll() | 返回当前元素后面所有的兄弟元素 | $("#one").nextAll(“span”) |
nextUntil() | 返回当前元素到指定匹配的元素为止的后面元素 | $("#one").nextUtil(“span”) |
parent() | 返回父元素 | $(".mini").parent() |
prev(exp) | 返回当前元素的上一个兄弟元素 | $("#two").prev(“div”) |
prevAll() | 返回当前元素前面所有的兄弟元素 | $(“span”).prevAll(“div”) |
prevUnit(exp) | 返回当前元素到指定匹配的元素为止的前面元素 | $(“span”).prevAll(“div”) |
siblings(exp) | 返回所有兄弟元素 | $("#two").siblings(“div”) |
add() | 把 add 匹配的选择器的元素添加到当前 jquery 对象中 | $(“span”).add("#two") |
js中不区分单引号与双引号
3.3 jQuery的属性操作
1.HTML代码/文本/值
html() | 它可以设置和获取起始标签和结束标签中的内容(包括标签) | 跟 dom 属性 innerHTML 一样 (不传参数是获取,传递参数是设置(可以传标签)) |
---|---|---|
text() | 它可以设置和获取起始标签和结束标签中的文本。 | 跟 dom 属性 innerText 一样。 |
val() | 它可以设置和获取表单项的 value 属性值 | 跟 dom 属性 value 一样 |
alert($("username").val());//获取
$("username").val("lalala");//设置
- val 方法同时设置多个表单项的选中状态: val([value属性值])
// 批量操作单选
$(":radio").val(["radio2"]);
// 批量操作筛选框的选中状态
$(":checkbox").val(["checkbox3","checkbox2"]);
// 批量操作多选的下拉框选中状态
$("#multiple").val(["mul2","mul3","mul4"]);
// 操作单选的下拉框选中状态
$("#single").val(["sin2"]);
$("#multiple,#single,:radio,:checkbox").val(["radio2","checkbox1","checkbox3","mul1","mul4","sin3"]);
2.属性
attr() | 可以设置和获取属性的值, 不推荐操作 checked、 readOnly、 selected、 disabled 等等 。attr 方法还可以操作非标准的属性。 比如自定义属性。 |
---|---|
prop() | 可以设置和获取属性的值,只推荐操作 checked、 readOnly、 selected、 disabled 等等 |
//attr()
$(":checkbox:first").attr("name");//设置一个参数是获取
$(":checkbox:first").attr("name","abc");//设置一个参数是获取
//prop()
$(":checkbox").attr("checked","false"); //返回true或者false
//设置自定义属性
$(":checkbox:first").attr("abc", "abcValue");
3.练习
全选、全部选、反选
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="../../script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function(){
//绑定全选单击事件
$("#checkedAllBtn").click(function (){
$(":checkbox").prop("checked", true);
});
//绑定全不选单击事件
$("#checkedNoBtn").click(function (){
$(":checkbox").prop("checked", false);
});
//绑定反选按钮
$("#checkedRevBtn").click(function (){
//获取运动候选框对象遍历
$(":checkbox[name = 'items']").each(function (){
//在每一个function函数中this都表示当前的dom对象
this.checked = !this.checked;
});
//读取运动候选框选中个数
var countChecked = $(":checkbox[name = 'items']:checked").size();
$("#checkedAllBox").prop("checked", countChecked == 4);
});
//绑定提交按钮
$("#sendBtn").click(function (){
$(":checkbox[name = 'items']:checked").each(function (){
//遍历的是dom对象,val()是jQuery对象的方法
alert(this.value);
});
});
//绑定全选/全部选单选框
$("#checkedAllBox").click(function (){
$(":checkbox[name = 'items']").prop("checked",this.checked);
});
//给所有运动候选框绑定单击事件
$(":checkbox[name = 'items']").click(function (){
//读取候选框选中个数
var countChecked = $(":checkbox[name = 'items']:checked").size();
$("#checkedAllBox").prop("checked", countChecked == 4);
});
});
</script>
</head>
<body>
<form method="post" action="">
你爱好的运动是?<input type="checkbox" id="checkedAllBox" />全选/全不选
<br />
<input type="checkbox" name="items" value="足球" />足球
<input type="checkbox" name="items" value="篮球" />篮球
<input type="checkbox" name="items" value="羽毛球" />羽毛球
<input type="checkbox" name="items" value="乒乓球" />乒乓球
<br />
<input type="button" id="checkedAllBtn" value="全 选" />
<input type="button" id="checkedNoBtn" value="全不选" />
<input type="button" id="checkedRevBtn" value="反 选" />
<input type="button" id="sendBtn" value="提 交" />
</form>
</body>
</html>
3.4 DOM的增删改
- **内部插入:**子元素
appendTo() | a.appendTo(b) | 把 a 插入到 b 子元素末尾, 成为最后一个子元素 ( " < h 1 > 标 题 < / h 1 > " ) . a p p e n d T o ( ("<h1>标题</h1>").appendTo( ("<h1>标题</h1>").appendTo((“div”)) |
---|---|---|
prependTo() | a.prependTo(b) | 把 a 插到 b 所有子元素前面, 成为第一个子元素 |
a与b可以是选择器,筛选出的标签对象
- **外部插入:**同级
insertAfter() | a.insertAfter(b) | 得到 ba |
---|---|---|
insertBefore() | a.insertBefore(b) | 得到 ab |
- 替换:
replaceWith() | a.replaceWith(b) | 用 b 替换掉 a(所有a换成一个b) |
---|---|---|
replaceAll() | a.replaceAll(b) | 用 a 替换掉所有 b |
- 删除:
remove() | a.remove(); | 删除 a 标签 |
---|---|---|
empty() | a.empty(); | 清空 a 标签里的内容 |
1. 从左到右,从右到左练习:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">
select {
width: 100px;
height: 140px;
}
div {
width: 130px;
float: left;
text-align: center;
}
</style>
<script type="text/javascript" src="script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function (){
//给第一个按钮绑定单击事件
$("button:eq(0)").click(function (){
//将左边复选框的option添加到右边复选框
$("select[name = 'sel01'] option:selected").appendTo($("select[name = sel02]"));
});
//给全部添加到右边绑定单击事件
$("button:eq(1)").click(function (){
$("select:eq(0) option").appendTo($("select:eq(1)"));
});
//给选中删除到左边绑定单击事件
$("button:eq(2)").click(function (){
$("select[name = 'sel02'] option:selected").appendTo($("select[name = 'sel01']"));
});
//选中全部删除到右边
$("button:eq(3)").click(function (){
$("select[name = 'sel02'] option").appendTo($("select[name = 'sel01']"));
});
});
</script>
</head>
<body>
<div id="left">
<select multiple="multiple" name="sel01">
<option value="opt01">选项1</option>
<option value="opt02">选项2</option>
<option value="opt03">选项3</option>
<option value="opt04">选项4</option>
<option value="opt05">选项5</option>
<option value="opt06">选项6</option>
<option value="opt07">选项7</option>
<option value="opt08">选项8</option>
</select>
<button>选中添加到右边</button>
<button>全部添加到右边</button>
</div>
<div id="rigth">
<select multiple="multiple" name="sel02">
</select>
<button>选中删除到左边</button>
<button>全部删除到左边</button>
</div>
</body>
</html>
2.动态添加和删除表格的行记录
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>提交删除功能验证</title>
<link rel="stylesheet" type="text/css" href="styleB/css.css" />
<script type="text/javascript" src="../../script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function (){
//在事件响应的function函数中,只有一个this对象,这个this对象是正在响应事件的dom对象
//定义删除函数
var delFunc = function (){
//读取该行记录
var row = $(this).parent().parent();
var name = row.find("td:first").val();
//comfirm是js提供的一个确认提示框按钮,当点击确认返回true,否则false
if(confirm("确认删除["+name+"]这条记录吗?")){
row.remove();
}
//return false 可以阻止元素的默认行为
return false;
}
//添加员工信息
$("#addEmpButton").click(function (){
var name = $("#empName").val();
var email = $("#email").val();
var sal = $("#salary").val();
//读取输入数据创建一个行标签对象
var $rowObj= $("<tr>\n" +
"\t\t\t<td>"+name+"</td>\n" +
"\t\t\t<td>"+email+"</td>\n" +
"\t\t\t<td>"+sal+"</td>\n" +
"\t\t\t<td><a href=\"deleteEmp?\">Delete</a></td>\n" +
"\t\t</tr>");
$rowObj.appendTo($("#employeeTable"));
//给新添加的记录中的删除标签绑定单击事件
$rowObj.find("a").click(delFunc);
});
/*删除员工信息:
函数delFunc与delFunc()的区别:加括号会调用整个函数,返回函数的返回值
不加括号是直接添加函数的完整体*/
$("a").click(delFunc);
//jQuery 给所有匹配的元素附加一个事件处理函数live(),即使这个元素是以后再添加进来的也有效
//即新添加的a标签页绑定click单击触发事件
//$("a").live("click" , delFunc);
});
</script>
</head>
<body>
.....
</body>
</html>
3.5 CSS样式操作
addClass() | 添加样式 |
---|---|
removeClass() | 删除样式 |
toggleClass() | 有就删除, 没有就添加样式 |
offset() | 获取和设置元素的坐标 |
css样式:
//标签名(限定当前样式的使用范围)+类型选择器
div.whiteborder{
border: 2px white solid;
}
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">
div{
width:100px;
height:260px;
}
div.whiteborder{
border: 2px white solid;
}
div.redDiv{
background-color: red;
}
div.blueBorder{
border: 5px blue solid;
}
</style>
<script type="text/javascript" src="script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function(){
var $divEle = $('div:first');
$('#btn01').click(function(){
//addClass() - 向被选元素添加一个或多个类
$divEle.addClass("redDiv blueBorder");
});
$('#btn02').click(function(){
//removeClass() - 从被选元素删除一个或多个类
$divEle.removeClass("redDiv");
});
$('#btn03').click(function(){
//toggleClass() - 对被选元素进行添加/删除类的切换操作
$divEle.toggleClass("redDiv");
});
$('#btn04').click(function(){
//offset() - 返回区域左上角相对于文档的左上角位置
//注意通过offset获取到的是一个对象,这个对象有两个属性top表示顶边距,left表示左边距
console.log($divEle.offset({
top:5, //设置顶边距
left:500 //设置左边距
}));
});
})
</script>
</head>
3.6 jQuery 动画
- 基本动画:
show() | 将隐藏的元素显示 | $("#div1").show(1000,function(){alert(“hhh”)}); |
---|---|---|
hide() | 将可见的元素隐藏 | $("#div1").hide(1000); |
toggle() | 可见就隐藏, 不可见就显示 | $("#div1").toggle(1000); |
- 淡入淡出动画:
fadeIn() | 淡入(慢慢可见) | $("#div1").fadeIn(1000) |
---|---|---|
fadeOut() | 淡出(慢慢消失) | $("#div1").fadeOut(1000); |
fadeToggle() | 淡入/淡出 切换将隐藏的元素显示 | $("#div1").fadeToggle(1000); |
fadeTo() | 在指定时长内慢慢的将透明度修改到指定的值。 0 透明, 1 完成可见, 0.5 半透明 | $("#div1").fadeTo(1000,0.5) |
以上动画方法都可以添加参数。
1、 第一个参数是动画 执行的时长, 以毫秒为单位
2、 第二个参数是动画的回调函数 (动画完成后自动调用的函数)
1.品牌展示:
css样式:
//属性是showmore 后代有a和后代span的样式
.showmore a span {
padding-left: 15px;
background: url(img/down.gif) no-repeat 0 0;
}
.showless a span {
padding-left: 15px;
background: url(img/up.gif) no-repeat 0 0;
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>品牌展示练习</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
font-size: 12px;
text-align: center;
}
a {
color: #04D;
text-decoration: none;
}
a:hover {
color: #F50;
text-decoration: underline;
}
.SubCategoryBox {
width: 600px;
margin: 0 auto;
text-align: center;
margin-top: 40px;
}
.SubCategoryBox ul {
list-style: none;
}
.SubCategoryBox ul li {
display: block;
float: left;
width: 200px;
line-height: 20px;
}
.showmore , .showless{
clear: both;
text-align: center;
padding-top: 10px;
}
.showmore a , .showless a{
display: block;
width: 120px;
margin: 0 auto;
line-height: 24px;
border: 1px solid #AAA;
}
.showmore a span {
padding-left: 15px;
background: url(img/down.gif) no-repeat 0 0;
}
.showless a span {
padding-left: 15px;
background: url(img/up.gif) no-repeat 0 0;
}
.promoted a {
color: #F50;
}
</style>
<script type="text/javascript" src="script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function() {
//绑定显示单击事件
$("div div a").click(function (){
$("div ul li:gt(5):not(:last)").toggle();
//判断是否被隐藏,两个状态
if ($("div ul li:gt(5):not(:last)").is(":hidden")){
//精简品牌
$("div div a span").text("显示全部品牌");
$("div div").removeClass("showless");
$("div div").addClass("showmore");
//增加高亮样式
$("li:contains('佳能')").addClass("promoted");
}else{
//显示全部品牌
//精简品牌
$("div div a span").text("显示精简品牌");
$("div div").removeClass("showmore");
$("div div").addClass("showless");
$("li:contains('佳能')").removeClass("promoted");
}
return false;
});
});
</script>
</head>
<body>
<div class="SubCategoryBox">
<ul>
<li><a href="#">佳能</a><i>(30440) </i></li>
<li><a href="#">索尼</a><i>(27220) </i></li>
<li><a href="#">三星</a><i>(20808) </i></li>
<li><a href="#">尼康</a><i>(17821) </i></li>
<li><a href="#">松下</a><i>(12289) </i></li>
<li><a href="#">卡西欧</a><i>(8242) </i></li>
<li><a href="#">富士</a><i>(14894) </i></li>
<li><a href="#">柯达</a><i>(9520) </i></li>
<li><a href="#">宾得</a><i>(2195) </i></li>
<li><a href="#">理光</a><i>(4114) </i></li>
<li><a href="#">奥林巴斯</a><i>(12205) </i></li>
<li><a href="#">明基</a><i>(1466) </i></li>
<li><a href="#">爱国者</a><i>(3091) </i></li>
<li><a href="#">其它品牌相机</a><i>(7275) </i></li>
</ul>
<div class="showmore">
<a href="more.html"><span>显示全部品牌</span></a>
</div>
</div>
</body>
</html>
3.7 jQuery事件操作
$( function(){} );和window.onload = function(){}的区别?
- 触发时间?
- jQuery 的页面加载完成之后是浏览器的内核解析完页面的标签创建好 DOM 对象之后就会马上执行
- 原生 js 的页面加载完成之后, 除了要等浏览器内核解析完标签创建好 DOM 对象, 还要等标签显示时需要的内容加载完成
- 触发顺序?
- 先 jQuery 页面加载
- 后 js 的页面加载
- 执行次数?
- 原生 js 的页面加载完成之后, 只会执行最后一次的赋值函数
- jQuery 的页面加载完成之后是将注册的全部 function 函数依次顺序执行
1. jQuery中其他事件的处理方法
click() | 它可以绑定单击事件, 以及触发单击事件 |
---|---|
mouseover() | 鼠标移入事件 |
mouseout() | 鼠标移出事件 |
bind() | 可以给元素一次性绑定一个或多个事件。 |
one() | 使用上跟 bind 一样。 但是 one 方法绑定的事件只会响应一次。 |
unbind() | 跟 bind 方法相反的操作, 解除事件的绑定 |
live() | 也是用来绑定事件。 它可以用来绑定选择器匹配的所有元素的事件。 哪怕这个元素是后面动态创建出 来的也有效 |
//触发单击事件
$("h5").click(function(){//传function是绑定事件
alert("h5单击绑定事件");
});
$("button").click(function(){
//点击按钮触发h5绑定的单击事件
$("h5").click();
});
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Untitled Document</title>
<link href="css/style.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="../../script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function(){
//*1.通常绑定事件的方式
//给元素绑定事件
//jquery对象.事件方法(回调函数(){ 触发事件执行的代码 }).事件方法(回调函数(){ 触发事件执行的代码 }).事件方法(回调函数(){ 触发事件执行的代码 })
//绑定事件可以链式操作
$(".head").click(function(){
$(".content").toggle();
}).mouseover(function(){
$(".content").toggle();
});
//*2.jQuery提供的绑定方式:bind(type,[data],fn)函数把元素和事件绑定起来
//type表示要绑定的事件 [data]表示传入的数据 fn表示事件的处理方法
//bind(事件字符串,回调函数),后来添加的元素不会绑定事件
//使用bind()绑定多个事件 type可以接受多个事件类型,使用空格分割多个事件
$(".head").bind("click mouseover",function(){
$(".content").toggle();
});
//3.one()只绑定一次,绑定的事件只会发生一次one(type,[data],fn)函数把元素和事件绑定起来
//type表示要绑定的事件 [data]表示传入的数据 fn表示事件的处理方法
$(".head").one("click mouseover",function(){
$(".content").toggle();
});
//4.live方法会为现在及以后添加的元素都绑定上相应的事件
$(".head").live("click",function(){
$(".content").toggle();
});
$("#panel").before("<h5 class='head'>什么是jQuery?</h5>");
});
</script>
</head>
<body>
<div id="panel">
<h5 class="head">什么是jQuery?</h5>
<div class="content">
jQuery是继Prototype之后又一个优秀的JavaScript库,它是一个由 John Resig 创建于2006年1月的开源项目。jQuery凭借简洁的语法和跨平台的兼容性,极大地简化了JavaScript开发人员遍历HTML文档、操作DOM、处理事件、执行动画和开发Ajax。它独特而又优雅的代码风格改变了JavaScript程序员的设计思路和编写程序的方式。
</div>
</div>
</body>
</html>
2. 事件的冒泡:
事件的冒泡是指, 父子元素同时绑定监听同一个事件。 当触发子元素的事件的时候, 同一个事件也被传递到了父元素的事件里去响应。
- 如何阻止事件的冒泡?
在子元素事件函数体内, return false; 可以阻止事件的冒泡传递。
$(function(){
//冒泡就是事件的向上传导,子元素的事件被触发,父元素的响应事件也会触发
//解决冒泡问题:return false;
//给span绑定一个单击响应函数
$("span").click(function(){
alert("我是span的单击响应函数");
return false;
});
//给id为content的div绑定一个单击响应函数
$("#content").click(function(){
alert("我是div的单击响应函数");
return false;
});
//给body绑定一个单击响应函数
$("body").click(function(){
//alert("我是body的单击响应函数");
});
//取消默认行为
/* $("a").click(function(){
return false;
}) */
})
3.javaScript事件对象
事件对象, 是封装有触发的事件信息的一个 javascript 对象
- 如何获取呢 javascript 事件对象呢?
在给元素绑定事件的时候, 在事件的 function( event ) 参数列表中添加一个参数, 这个参数名, 我们习惯取名为 event。这个 event 就是 javascript 传递参事件处理函数的事件对象
- 原生 javascript获取事件对象:
window.onload = function () {
document.getElementById("areaDiv").onclick = function (event) {
console.log(event);
}
}
- jQuery 代码获取事件对象:
$(function () {
$("#areaDiv").click(function (event) {
console.log(event);
});
});
- 使用 bind 同时对多个事件绑定同一个函数。 怎么获取当前操作是什么事件
$("#areaDiv").bind("mouseover mouseout",function (event) {
if (event.type == "mouseover") {
console.log("鼠标移入");
} else if (event.type == "mouseout") {
console.log("鼠标移出");
}
});
4. 图片跟随:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">
body {
text-align: center;
}
#small {
margin-top: 150px;
}
#showBig {
position: absolute;
display: none;
}
</style>
<script type="text/javascript" src="script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function(){
//绑定鼠标移入,鼠标移除,滑动事件
$("#small").bind("mouseover mouseout mousemove", function (event){
if(event.type == "mouseover"){
$("#showBig").show();
}else if(event.type == "mouseout"){
$("#showBig").hide();
}else if(event.type == "mousemove"){
$("#showBig").offset({
left:event.pageX + 5, //左边距
top: event.pageY + 5 //顶间距
})
}
});
});
</script>
</head>
<body>
<img id="small" src="img/small.jpg" />
<div id="showBig">
<img src="img/big.jpg">
</div>
</body>
</html>
4.XML
xml是可拓展的标记性语言,主要作用有:
- 用来保存数据(程序类等,之后可通过解析), 而且这些数据具有自我描述性
- 它还可以做为项目或者模块的配置文件
- 还可以做为网络传输数据的格式(现在 JSON 为主)
4.1 XML语法
<?xml version="1.0" encoding="utf-8" ?>
<!-- xml声明 version是版本的意思 encoding是编码 -->
<books> <!-- 这是xml注释 -->
<book id="SN123123413241"> <!-- book标签描述一本图书 id属性描述 的是图书 的编号 -->
<name>java编程思想</name> <!-- name标签描述 的是图书 的信息 -->
<author>华仔</author> <!-- author单词是作者的意思 ,描述图书作者 -->
<price>9.9</price> <!-- price单词是价格,描述的是图书 的价格 -->
</book>
<book id="SN12341235123"> <!-- book标签描述一本图书 id属性描述 的是图书 的编号 -->
<name>葵花宝典</name> <!-- name标签描述 的是图书 的信息 -->
<author>班长</author> <!-- author单词是作者的意思 ,描述图书作者 -->
<price>5.5</price> <!-- price单词是价格,描述的是图书 的价格 -->
</book>
</books>
- xml元素指的是从开始标签到结束标签的内容
<title>java 编程思想</title>
- xml元素名称不能以数字或者标点开始,不能包含空格
- xml中的元素(标签)也分为单标签和双标签:
单标签:
<标签名 属性=”值” 属性=”值” ...... />
双标签:
< 标签名 属性=”值” 属性=”值” ......>文本数据或子标签</标签名>
-
xml 的标签属性和 html 的标签属性是非常类似的,属性可以提供元素的额外信息。每个属性的值必须使用引号引起来。
-
xml中标签必须闭合、对大小写敏感、必须有根元素(没有父标签的顶级元素)
-
xml的文本区域:CDATA语法可以告诉xml解析器,保存的是纯文本,不需要进行语法解析
CDATA 格式:
<![CDATA[ 这里可以把你输入的字符原样显示, 不会解析 xml ]]>
4.2 xml解析技术
早期JDK为我们提供了两种xml解析技术:DOM和Sax
- DOM解析是基于创建dom对象
- Sax解析以类似事件机制通过回调告诉用户当前正在解析的内容,它是一行一行的读取 xml 文件进行解析的。 不会创建大量的 dom 对象。所以它在解析 xml 的时候, 在内存的使用上。和性能上。 都优于 Dom 解析。
4.3 dom4j解析技术
Dom4j 它是第三方的解析技术。我们需要使用第三方给我们提供好的类库才可以解析 xml 文件
- 首先创建lib目录,添加dom4j-1.6.1.jar包,添加到类路径
dom4j编程步骤:
- 第一步: 先加载 xml 文件创建 Document 对象
- 第二步: 通过 Document 对象拿到根元素对象
- 第三步: 通过根元素.elelemts(标签名); 可以返回一个集合, 这个集合里放着。 所有你指定的标签名的元素对象
- 第四步: 找到你想要修改、 删除的子元素, 进行相应在的操作
- 第五步, 保存到硬盘上
package com.zju;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.util.List;
public class Dom4jTest {
@Test
public void test() throws DocumentException {
//第一步:通过创建SAXReader对象,来读取xml文件,获取Document对象
SAXReader reader = new SAXReader();
Document document = reader.read("src/books.xml");
//第二步:通过Document对象,拿到xml的根元素对象
Element root = document.getRootElement();
//Element.asXML()它将当前元素转换成为String对象
//Element.elements(标签名)可以拿到当前元素下的指定元素的集合
//第三步:通过根元素对象,获取所有的book标签对象
List<Element> books = root.elements();
//第四步:遍历每一个book对象,然后获取到每一个元素
for (Element book:books){
//获取属性值Element.attributeValue()
String sn = book.attributeValue("sn");
Element nameElement = book.element("name");
String name = nameElement.getText();
String price = book.elementText("price");
String author = book.elementText("author");
System.out.println(new Book(sn, name, Double.parseDouble(price), author));
}
}
}
5.Tomcat服务器
5.1 Javaweb
1.Javaweb概念:
- JavaWeb是指所有通过Java语言编写的可以通过浏览器访问的程序的总称,
JavaWeb是基于请求和响应来开发的 - 请求(Request):指客户端给服务器发送数据
- 响应(Response):指服务器给客户端回传数据
2.web资源分类:
静态资源:html,css,js,txt,mp4,jpg等
动态资源:jsp页面,servlet程序
Tomcat是一种轻量级的javaweb容器(服务器),提供对jsp和Servlet的支持
5.2 Tomcat使用
1.Tomcat解压之后的目录介绍:
bin:存放Tomcat服务器的可执行程序
conf:存放Tomcat服务器的配置文件
lib:存放Tomcat服务器的jar包
logs:存放Tomcat服务器运行时输出的日志信息
temp:存放Tomcat服务器运行时产生的临时数据
webapps:存放部署的Web工程
work:存放Tomcat运行时jsp翻译为Servlet的源码和Session钝化(序列化)的目录
2.配置JAVA_HOME环境变量
3.启动Tomcat服务器
①找到Tomcat目录下的bin目录下的startup.bat文件,双击即可启动Tomcat服务器
测试:
②打开命令行;cd到Tomcat安装目录下的bin目录下;敲入启动命令:catalina run
4.Tomcat服务器的停止
以下方式三选一:
① 点击已经启动Tomcat服务器的命令行窗口的x关闭按钮
② 把Tomcat服务器窗口设置为当前窗口,然后按快捷键ctrl + c
③ 双击Tomcat安装目录下的bin目录下的shutdown.bat文件
5.修改Tomcat的端口号
Tomcat的默认端口号是8080,修改方法如下:
①找到Tomcat目录下的conf目录,打开server.xml配置文件
②找到Connector标签,修改port属性值为想要的端口号
③修改完端口号需重启Tomcat服务器方可生效
http协议默认端口号是80
6.部署web工程到Tomcat
- 方法一:只需要把 web 工程的目录拷贝到 Tomcat 的 webapps 目录下即可
访问方式:http://ip:port/工程名(访问index.html)
http://port/工程名/文件目录/文件名
- 方法二:找到 Tomcat 下的 conf 目录\Catalina\localhost\ 下,创建配置文件bookstore.xml
<!-- Context 表示一个工程上下文
path 表示工程的访问路径,即:/此文件名
docBase 表示你的工程目录在哪里(项目可以放在外面)
-->
<Context path="/bookstore" docBase="D:\IDEA_workspace\JavaWeb\_bookstore" />
访问方式:http://localhost:8080/bookstore
7.用手把html页面拖到浏览器和在浏览器中输入 http://ip:端口号/工程名/访问的区别?
8.ROOT 的工程的访问,以及默认 index.html 页面的访问
-
http://ip:port/ ===>>>> 没有工程名的时候,默认访问的是ROOT工程。
-
http://ip:port/工程名/ ===>>>> 没有资源名,默认访问index.html页面
9.IDEA整合Tomcat服务器
-
操作的菜单如下:File | Settings | Build, Execution, Deployment | Application Servers。
-
最后,在新创建module中查看是否配置成功
5.3 IDEA中动态web工程的操作
1.IDEA中创建动态web工程
-
新建普通java项目---->add framesupport —>JavaEE Application 和 web Application----->选择 Edit Configuration -> 左上角加号 -> Tomcat Server->Local
-
选择第二个选项卡Deployment->选择Artifacts,Application context表示工程路径,可以对项目的访问地址进行修改,web war exploded–>Apply;
-
给javaEE模块添加Tomcat依赖
-
勾选Source Roots
2.web工程目录介绍
- **src:**存放自己编写的java源代码
- web:目录专门用来存放web工程的资源文件,比如html,css,js文件等
- WEB-INF目录是一个受服务器保护的目录,浏览器无法直接访问此目录的内容
- lib目录用来存放第三方的jar包
- web.xml是整个动态web工程的配置部署描述文件,可以在这里配置很多web工程的组件,比如:Servlet程序、Fileter过滤器、Listener监听器、Session超时等
3.给动态web工程添加额外的jar包
方法一:将jar包拷贝到lib目录下,右键添加到该模块
方法二:
- 打开Project Structrue菜单操作界面, 添加一个自己的类库libraries;
- 添加你你类库需要的 jar 包文件
- 选择你添加的类库, 给哪个模块使用
- 选择 Artifacts 选项, 将类库, 添加到打包部署中fix:
4.在IDEA中部署工程到Tomcat上运行(整个web工程)
- 为防止多个web工程的Tomcat实例混淆,修改web工程对应的Tomcat运行实例名称
- 确认Tomcat实例中有要部署运行的web工程
- 配置资源热部署
6.Servlet
- Servlet是JavaEE规范(接口)之一
- Servlet是JavaWeb三大组件之一,三大组件分别是Servlet程序、Filter过滤器、Listener监听器
- Servlet是运行在服务器上的一个Java程序,可以接收客户端发来的请求,并响应数据给客户端
6.1 Servlet技术
1.手动实现servlet程序(了解)
- 编写一个类实现Servlet接口,并覆写service方法处理请求、响应数据
- 在WEB-INF文件夹中的web.xml文件中配置Servlet程序的访问地址
在src下创建一个HelloServlet类
public class HelloServlet implements Servlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Servlet被访问了!");
}
}
在web.xml中配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<!--servlet-name标签是给Servlet程序起的一个别名-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class标签是Servlet程序的全类名-->
<servlet-class>com.zju.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<!--此时servlet-name标签要和上一个标签别名相同-->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern标签配置访问地址:
/:在服务器解析时表示为Tomcat的工程路径(在Edit Configurations中修改),
/hello:代表默认路径/hello,即http://localhost:8080/HelloServlet/hello,
也就是说在浏览器的地址栏中输入上述路径访问到的是HelloServlet类
//注意起别名,用这个名字访问指定类-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
点击绿色按钮开启Tomcat服务器之后,会自动打开默认的地址http://localhost:8080/servlet。servlet为工程路径
在地址栏继续输入/hello,会执行指定类的service方法,控制台输出:Servlet被访问了!
约定大于配置,起别名要有一定的对应关系
常见的错误:
- url-pattern 中配置的路径没有以斜杠打头
- servlet-name 配置的值不存在
- servlet-class 标签的全类名配置错误
2.url地址到Servlet程序的访问:
3.Servlet的生命周期
Servlet程序被访问以后按以下顺序执行:
- 执行Servlet程序的构造方法
- 执行init方法
- 执行service方法
- 执行destroy方法
其中1和2是在初次访问并创建Servlet程序时会执行(每次启动服务只执行一次),第3步每次刷新 (访问)都会执行,第4步点击停止时会执行一次
4.GET和POST请求的不同处理
在src目录下创建此类:
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//转换的原因:HttpServletRequest有getMethod方法,可以得到请求的类型
//向下转型
HttpServletRequest httpServletRequest =(HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod();
//method的值为GET或者POST
if(method.equals("GET")){
doGet();
}else if(method.equals("POST")){
doPost();
}
}
//POST请求方式要执行的操作
private void doPost() {
System.out.println("POST方式请求");
}
//Get请求要执行的操作
private void doGet() {
System.out.println("GET方式请求");
}
在web目录下创建Test.html页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<form action="http://localhost:8080/servlet/hello" method="post">
<input type="submit"/>
</form>
</body>
</html>
运行结果:服务器启动之后,在浏览器的地址栏中的后缀加上Test.html,即可访问此页面,点击提交标签,即可跳转到http://localhost:8080/servlet/hello,执行service方法,控制台输出:POST请求方式
5.继承HttpServlet类实现Servlet程序
在实际的项目开发中,都是使用继承HttpServlet类实现Servlet程序的方式,步骤如下:
- 编写一个类继承HttpServlet类
- 根据需求重写doGet或doPost方法,由service方法根据表单的method属性值调用二者之一
- 到web.xml中配置Servlet程序的访问地址
在src目录下创建此类:
public class HelloServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("POST方法执行");
}
}
//HttpServlet的service方法会根据method方式调用二者之一
在web.xml中继续写配置:
<servlet>
<servlet-name>HelloServlet2</servlet-name>
<servlet-class>com.zju.HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
在web创建html页面调用
<body>
<form action="http://localhost:8080/servlet/hello2" method="post">
<input type="submit"/>
</form>
</body>
运行结果:服务器启动之后,在浏览器的地址栏中的后缀加上test.html,即可访问此页面,点击提交标签, 即可跳转到http://localhost:8080/servlet/hello2,执行service方法,进而执行doPost方法
6.IDEA创建Servlet程序(重要)
创建之后,会在包下创建此类(类名为全类名中的类名),此类继承于HttpServlet类,其中有doGet和doPost方法(无函数体),并自动的在web.xml 文件中补充新的标签
但访问地址还没有配置,需自己补充。
7.Servlet的类继承体系结构
6.2 ServletConfig类
1.此接口是Servlet的配置信息:
- Servlet程序和ServletConfig对象都是由Tomcat负责创建,编程人员负责使用
- Servlet程序默认是第一次访问时创建,每个Servlet程序创建时对应的创建ServletConfig对 象,二者相互对应,某个Servlet程序只可以获得他对应的ServletConfig对象,无法获得别的 Servlet程序的ServletConfig对象
2.ServletConfig接口的三大作用:
- 可以获取Servlet程序的别名(即web.xml的的内容)(config.getServletName())
- 可以获取web.xml的初始化参数的值(config.getInitParameter())
- 可以获取ServletContext对象(config.getServletContext())
示例:
1.在web.xml中补充初始配置
<servlet>
<servlet-name>HelloServlet2</servlet-name>
<servlet-class>com.zju.HelloServlet2</servlet-class>
<!--<init-param>是初始化参数,每个servlet标签中都可以有,一个servlet标签中可以有多个-->
<init-param>
<!--参数名-->
<param-name>username</param-name>
<!--参数值-->
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
2.在自定义类中继承HttpServlet并覆写init()方法
public class HelloServlet2 extends HttpServlet {
@Override
//使用init方法的原因:1.一定会执行 2.参数中有ServletConfig对象
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println(config.getServletName());
System.out.println("username是:"+config.getInitParameter("username"));
System.out.println("url是:"+config.getInitParameter("url"));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Get方法执行");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("POST方法执行");
}
}
/*运行结果(浏览器地址栏输入http://localhost:8080/servlet/hello2):
此程序的别名是:HelloServlet2
username的值是:root
url的值是:jdbc:mysql:localhost:3306/test
org.apache.catalina.core.ApplicationContextFacade@64d62c61 */
注意覆写init方法时,必须要在函数体内写:super.init(config);
原因:父类GenericServlet中的init方法将参数config保存起来,子类若不调用则无法保存config
6.3 ServletContext接口
1、 ServletContext 是一个接口, 它表示 Servlet 上下文对象
ServletContext servletContext = getServletContext();
2、 一个 web 工程, 只有一个 ServletContext 对象实例。
3、 ServletContext 对象是一个域对象。
4、 ServletContext 是在 web 工程部署启动的时候创建。 在 web 工程停止的时候销毁。
域对象:像Map一样存取数据的对象称为域对象,域指的是存取数据的操作范围,
ServletContext的域是整个web工程
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
ServletContext接口的四个作用:
(1) 获取web.xml中配置的上下文参数标签中的值
servletContext.getInitParameter("username");
(2) 获取当前工程的路径,
servletContext.getContextPath();
格式:/工程路径
也就是Edit Configurations中Deployment中的 Application context的内容(即地址中8080之后,具体的打开的页面之前的内容)
(3) 获取工程部署后在硬盘上的绝对路径
servletContext.getRealPath();
D:\IDEA_workspace\Javaweb\out\artifacts\servlet_war_exploded\
(4) 像Map一样存取数据
注意:一个web工程只会创建一个ServletContext对象实例,一旦给此对象赋值,换其他类输出servletContext得到的结果相同,只有当restart整个web工程会被销毁。
示例:1. 在web.xml中继续写配置(在标签中)
<!--<context-param>标签中是上下文参数,属于整个web工程-->
<!--可以有多个,写在第一个<servlet>标签之外(之上)-->
<context-param>
<param-name>username</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123</param-value>
</context-param>
<!--并写出下方的类对应的<servlet标签>-->
- 在src目录下创建此类
package com.zju; /**
* @Autor:godfu
* @Date:2022/3/8-14:43
*/
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "ServletContext", value = "/ServletContext")
public class myServletContext extends HttpServlet {
/**
* 默认执行doGet方法,故只重写doGet方法
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//GenericServlet类中有public ServletConfig getServletConfig()方法,返回this.config
ServletContext servletContext = getServletConfig().getServletContext();
//1.获取web.xml中配置的上下文参数<context-param>标签中的值
String username = servletContext.getInitParameter("username");
System.out.println("context-param参数的username值是" + username);
/* 运行结果:context-param参数的username值是root */
System.out.println("context-param参数的password值是" + servletContext.getInitParameter("password"));
/* 运行结果:context-param参数的password值是root */
//2.获取当前工程的路径
System.out.println("当前工程路径:" + servletContext.getContextPath());
/* 运行结果:当前工程路径(自己取得别名):/servlet */
//3.获取工程部署后在硬盘上的绝对路径
/* /斜杠被服务器解析地址为:http://ip:port/工程名/对应IDEA中整合的Tomcat文件下的配置工程路径
* 即/斜杠对应IDEA代码的web目录 */
System.out.println("工程部署的路径是:" + servletContext.getRealPath("/"));
/* 运行结果:D:\IDEA_workspace\Javaweb\out\artifacts\servlet_war_exploded\ */
//在web目录下创建一个css文件夹
System.out.println("工程下css目录的绝对路径是:" + servletContext.getRealPath("/css"));
/* 运行结果:D:\IDEA_workspace\Javaweb\out\artifacts\servlet_war_exploded\css */
//在web目录下创建一个img文件夹,里面放1.gif文件
System.out.println("工程下img目录1.gif的绝对路径是:" + servletContext.getRealPath("/img/1.gif"));
/* 输出:D:\IDEA_workspace\Javaweb\out\artifacts\servlet_war_exploded\img\1.gif */
}
//记得要在浏览器的地址栏输入http://localhost:8080/servlet/ServletContext才可访问到此类
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
6.4 HTTP协议
HTTP协议指的是客户端(浏览器)和服务器之间通信时,发送的数据需要遵守的规则,HTTP协议中的数据又称为报文
1.请求的HTTP协议格式:
- GET请求:
- 请求行:包括请求的方式、请求的资源路径、请求的协议的版本号
- 请求头:由不同的键值对构成,具有不同含义key:value
- POST请求:POST请求:由请求行、请求头、空行、请求体组成
- 请求体就是发给服务器的数据
区分GET请求和POST请求:
-
GET请求有:
1、 form 标签 method=get
2、 a 标签
3、 link 标签引入 css
4、 Script 标签引入 js 文件
5、 img 标签引入图片
6、 iframe 引入 html 页面
7、 在浏览器地址栏中输入地址后敲回车 -
POST请求有:
8、 form 标签 method=post
2.响应的HTTP协议格式:
响应一般由响应行、响应头、空行和响应体(回传给客户端的数据)组成。
常见的响应码:
- 200 表示请求成功
- 302 表示请求重定向
- 404 表示服务器收到请求,但是请求的数据不存在(请求地址错误)
- 500 表示服务器收到请求,但是服务器内部错误(代码错误)
MIME类型说明:
MIME是HTTP协议中的数据类型,格式是:大类型/小类型,并与某一种文件的扩展名相对应:
谷歌浏览器查看HTTP协议:
FN+F12
6.5 HttpServletRequest类
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求发来的HTTP协议信息解析好封装到Request对象中,然后传递到service方法中(调用doGet或doPost方法)供编程人员使用,编程人员通过HttpServletRequest对象,可以获取到请求的所有信息。
常用API方法 | 描述 |
---|---|
getRequestURI() | 获取请求的资源路径 |
getRequestURL() | 获取请求的绝对路径 |
getRemoteHost() | 获取客户端的ip地址 |
getHeader() | 获取请求头 |
getParameter() | 获取请求的参数 |
getParameterValues() | 获取请求的参数(多个值时使用) |
getMethod() | 获取请求的方式(GET或POST) |
setAttribute(key, value): | 设置域数据 |
getAttribute(key): | 获取域数据 |
getRequestDispatcher(): | 获取请求转发对象 |
package zju.edu; /**
* @Autor:godfu
* @Date:2022/3/9-14:35
*/
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class RequestAPI extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求的资源路径
System.out.println(request.getRequestURI());
//2.获取请求的绝对路径
System.out.println(request.getRequestURL());
//3.获取客户端的ip地址
System.out.println(request.getRemoteHost());
//4.获取请求头
System.out.println(request.getHeader("User-Agent"));
//5.获取请求的方式
System.out.println(request.getMethod());
//输出
/*在IDEA中,使用localhost访问时得到的客户端ip地址是127.0.0.1
使用真实ip访问时,得到的客户端地址是真实的客户端ip地址 */
/**
* /servlet_2/requestAPI
* http://localhost:8080/servlet_2/requestAPI
* Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
* GET
* 127.0.0.1
*/
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
2.获取请求参数:
在web目录下创建form.html页面(不可在WEB-INF中创建,无法访问到):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>form</title>
</head>
<body>
<form action="http://localhost:8080/servlet_2/requestAPI" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
<input type="checkbox" name="hobby" value="Java">Java
<input type="checkbox" name="hobby" value="Go">Go
<input type="submit">
</form>
</body>
</html>
在src下创建此类
public class RequestAPI2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//doPost方法会出现中文请求乱码问题
//需要在获取任何参数之前修改字符编码集,而不仅仅获取中文参数时才修改:
request.setCharacterEncoding("UTF-8");
//获取请求的参数(此方法参数中放name属性值,得到value属性值)
String username = request.getParameter("username");
String password = request.getParameter("password");
//获取请求的参数的多个值
String[] hobbies = request.getParameterValues("hobby");
//输出
System.out.println("用户名:" + username);
System.out.println("密码:" + password);
//将数组转换为集合输出
System.out.println("兴趣爱好:" + Arrays.asList(hobbies));
}
}
请求的中文乱码问题:
- doPost乱码
//doPost方法会出现中文请求乱码问题
//需要在获取任何参数之前修改字符编码集,而不仅仅获取中文参数时才修改:
request.setCharacterEncoding("UTF-8");
- doGet乱码
// 获取请求参数
String username = req.getParameter("username");
//1 先以 iso8859-1 进行编码
//2 再以 utf-8 进行解码
username = new String(username.getBytes("iso-8859-1"), "UTF-8");
3.请求转发:
请求转发指的是服务器收到请求之后,从一个资源跳转到工程下另一个资源(可以是html、servlet等)的操作,如图所示:
在src下创建此类,并在web.xml中配置相应的数据
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的参数(查看办事的材料)
String username = request.getParameter("username");
System.out.println("在Servlet1(柜台1)中查看参数(材料):" + username);
//给材料盖章
request.setAttribute("key1","柜台1的章");
//获得通向Servlet2的路径(请求转发对象)
//参数必须以斜杠打头,斜杠代表http://localhost:8080/工程名/,对应IDEA代码的web目录
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Servlet2");
//可以转发到WEB-INF目录下:request.getRequestDispatcher("/WEB-INF/xxx");
//通过得到的路径走向Servlet2(柜台2)
//forward方法将当前资源的request和response转发到该requestDispatcher指定的资源
requestDispatcher.forward(request, response);
//使得Servlet2中的request和response与Servlet1一致
}
}
servlet2类
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的参数(查看办事的材料)
String username = request.getParameter("username");
System.out.println("在Servlet2(柜台2)中查看参数(材料):" + username);
//查看是否有柜台1的章
Object key1 = request.getAttribute("key1");
System.out.println("柜台1的章为:" + key1);
//出处理自己的业务
System.out.println("Servlet2处理业务");
}
}
运行结果:
(在浏览器的地址栏中输入:http://localhost:8080/servlet_2/Servlet1?username=jaychou)
可以得出地址栏的内容不发生变化,但页面自动跳转(访问)到了请求转发对象Servlet2中,即显示http://localhost:8080/servlet_2/Servlet2的页面
4.base标签的作用:对相对路径设置了参考跳转路径
1.在web目录下创建a文件夹下创建b文件夹下创建c.html(设置了相对路径)
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
这是a下的b下的c.html<br/>
<a href="../../index.html">跳到web下的index.html</a>
</body>
2.在src下创建此类,并在web.xml中配置
public class Forward extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("a/b/c.html").forward(request,response);
}
}
- 在web目录下创建index.html
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
这是web下的index.html页面<br/>
<a href= http://localhost:8080/MyTest/Forward>请求转发:a/b/c.html</a>
</body>
问题:在地址栏输入http://localhost:63342/FirstWeb/MyTest/web/index.html,点击后成功跳转到 http://localhost:8080/MyTest/Forward,此时的页面是:
点击之后无法跳转,根据以上原因,要跳转的地址是http://localhost:8080/MyTest/Forward…/…/index.html,抵消之后为http://localhost:8080/index.html,这是错误的路径,因此跳转失败。
解决方案:base标签可以设置当前页面中所有相对路径跳转时参照指定的路径来进行跳转,在href属性中设置指定路径
修改c.html
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--base标签写在<title>标签之后-->
<base href="http://localhost:8080/MyTest/a/b/">
</head>
<body>
这是a下的b下的c.html<br/>
<a href="../../index.html">跳到web下的index.html</a>
</body>
5.Web中的相对路径和绝对路径:
绝对路径 | http://ip:port/工程路径/资源路径 |
---|---|
相对路径:. | 表示当前目录 |
相对路径:… | 表示上一级目录 |
相对路径:资源名 | 表示当前目录/资源名 |
在实际开发中, 路径都使用绝对路径, 而不简单的使用相对路径。
6.web中/的不同意义
在web中/也是一种绝对路径。
-
/ 如果被浏览器解析,得到的地址是:http://ip:port/
-
<a href="/"></a>
-
-
/ 如果被服务器解析,得到的地址是:http://ip:port/工程路径
-
<url-pattern>/servlet1</url-pattern>
-
servletContext.getRealPath(“/”);
-
request.getRequestDispatcher(“/”)
-
-
特殊情况: response.sendRediect(“/”); 把斜杠发送给浏览器解析得到http://ip:port/
6.6 HttpServletResponse类
1.作用:
每次只要有请求进入Tomcat服务器,Tomcat服务器就会创建一个Response对象传递给Servlet程序。
HttpServletResponse表示所有响应的信息(HttpServletRequest表示请求发来的信息),
可以通过HttpServletResponse对象设置返回给客户端的信息。
2.两个输出流的说明:
- 字节流 getOutputStream(); 常用于下载(传递)二进制数据
- 字符流 getWriter(); 常用于回传字符串
- 注:同一个HttpServletResponse对象两个流不可同时使用,只可二选一。
3.从服务器往客户端(浏览器)回传字符串数据:
解决中文乱码:
public class ResponseIO extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//防止中文乱码问题,在获取流对象之前调用此方法:
//同时设置服务器和客户端都使用UTF-8字符集
response.setContentType("text/html; charset=UTF-8");
//获取流对象
PrintWriter writer = response.getWriter();
writer.write("I Love China!");
}
}
//解决请求中文乱码问题,一定要在请求参数之前调用才有效
request.setCharacterEncoding("UTF-8");
//解决响应中文乱码问题
response.setContentType("text/html;charset=UTF-8");
4. 请求重定向
请求重定向指的是客户端给服务器发送请求,然后服务器通知客户端去访问自己的新地址(之前的地址可能被废弃)叫请求重定向
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//请求重定向
response.sendRedirect(“http://localhost:8080/MyTest/Response2”);
}
}
请求重定向的特定:
- 浏览器地址会直接发生变化
- 两次请求
- 不共享Request域中的数据
- 不能访问WEB-INF下的资源
- 可以访问工程外的资源
7. jsp
- JSP的全称是Java Server Pages,即Java的服务器页面
- JSP的主要作用是代替Servlet程序回传HTML页面的数据
- web目录(或其他)右击 --> new --> JSP/JSPX --> 输入文件名 --> 选择JSP file创建
Servlet是在java里面写html,jsp是在html里面写java代码
JSP的本质:
JSP本质上是一个Servlet程序:第一次访问JSP页面时(运行Tomcat服务器后在浏览器地址栏输入路径),Tomcat服务器会将此JSP页面翻译成为一个Java源文件,并对其进行编译成为.class字节码文件(一个.java,一个.class)。JSP翻译出来的Java类间接继承于HttpServlet类。
其底层实现也是通过输出流把页面回传给客户端。
注意:
查看翻译后的Java源文件的方法:启动Tomcat服务器访问到JSP页面之后在控制台输出的信息的前端找到Using CATALINA_BASE中的路径,在硬盘中打开此目录,点击work --> Catalina --> localhost,找到对应的工程文件夹寻找即可
访问JSP页面其实是在执行对应的翻译后的Java代码的jspService方法:翻译后的Java类中没有service方法,而是重写了父类的jspService方法,这个方法会被父类的service方法调用
7.1 JSP的语法:
1.jsp头部的page指令
JSP头部的page指令可以修改JSP页面中的一些重要属性或行为
(以下属性均写在page指令中,默认page指令中没有出现的属性都采用默认值):
(1) contentType属性:表示JSP返回的数据类型是什么,即response.setContentType()的参数值
(2) language属性:表示JSP翻译之后是什么语言文件(目前只支持Java)
(3)pageEncoding属性:表示当前JSP文件本身的字符集(可在IDEA右下角看到)
(4) import属性:表示导包(导类),与Java一致
(5) autoFlush属性:设置当out输出流缓冲区满了之后是否自动刷新缓冲区,默认值是true
(6) buffer属性:设置out缓冲区的大小,默认是8kb
注意:out缓冲区满了之后不能自动刷新的话会报错
(7) errorPage属性:设置当JSP页面运行出错时自动跳转到的页面(错误信息页面)的路径,这个 路径一般都是以斜杠打头,表示请求的地址是http://ip:port/工程路径/,对应代码web目录
(8) isErrorPage属性:设置当前JSP页面是否是错误信息页面,默认是false,如果是true可以 获取错误信息
(9) session属性:设置访问当前JSP页面时是否会创建HttpSession对象,默认值是true
(10) extends属性:设置JSP页面翻译出来的Java类默认继承谁
注意:以上默认值除非有特殊需要,否则不建议修改
2.声明脚本(极少用)
- 格式:<%! 声明Java代码 %>
- 作用:可以给JSP翻译出来的Java类定义属性、方法、静态代码块、内部类等
- 特点:不会在浏览器的页面上显示出来,仅存在于翻译后的Java类中
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--1.声明类属性--%>
<%!
private String name;
private static Map<String, Object> map;
%>
<%--2.声明类方法--%>
<%!
public int sum() {
return 12;
}
%>
<%--3.声明静态代码块--%>
<%!
static {
map = new HashMap<String, Object>();
map.put("key1", "value1");
}
%>
</body>
</html>
翻译后得到的java源文件:
3.表达式脚本:
格式:<%=表达式 %>
作用:在浏览器的JSP页面上输出数据(只有此脚本可以在浏览器的页面上输出数据)
特点:
(1) 所有的表达式脚本都会被翻译到对应的Java类的jspservice()方法中,故表达式脚本可以直接使用jspService()方法参数中的对象(九大内置对象)
(2) 表达式脚本都会被编译后的Java类中的out.print()方法输出到浏览器页面上
(3) 表达式脚本中的表达式不能以分号结束
<%=22 %> <br/>
<%="可以输出字符串" %> <br/>
<%=map %> <br/>
<%--使用_jspService方法中的对象--%>
<%=request.getParameter("username") %>
4.代码脚本:
格式:<% Java语句 %>
作用:在JSP页面中的jspService()方法中可以编写添加需要的Java代码
特点:
(1) 代码脚本翻译后都在_jspService方法中,故代码脚本可以直接使用此方法参数中的对象
(2) 可以由多个代码脚本块组合完成一个完整的Java语句
(3) 代码脚本还可以和表达式脚本一起组合使用,在JSP页面上输出数据
<%--1.if语句--%>
<%
int i = 1;
if (i == 1) {
System.out.println("我爱祖国!");
} else {
System.out.println("我很爱祖国!");
}
%> <br/>
<%--2.for循环语句--%>
<%
for (int j = 0 ; j < 3; j++) {
System.out.println("第" + j + "次循环");
}
%> <br/>
<%--3.使用_jspService方法参数中的对象--%>
<%
String username = request.getParameter("username");
System.out.println("username对应的值为:" + username);
%>
5. jsp的三种注释
- HTML注释:
HTML注释会被翻译到JSP文件对应的Java类的_jspService方法中,以out.write()输出到客户端,
write方法会自动识别标签,执行标签对应的功能,不会在浏览器的页面上输出注释
- Java注释:
(1) //单行注释 (2) /*多行注释*/
Java注释要写在声明脚本和代码脚本中才被认为是Java注释,会被翻译到JSP文件对应的Java类的_jspService方法中,在对应的Java类中也是注释
-
JSP注释:<%- -这是JSP注释- -%>
JSP注释中的内容不会在JSP文件翻译后的Java类中出现,即注释中的内容没有任何功能
7.2 九大内置对象与四大域对象
1. 九大内置对象
JSP的内置对象指的是Tomcat服务器将JSP页面翻译为Java类之后内部提供的九大对象:
- request:请求对象
- response:响应对象
- pageContext:JSP的上下文对象
- session:会话对象
- application:ServletContext对象
- config:ServletConfig对象
- out:JSP输出流对象
- page:指向当前JSP的对象
- exception:异常对象
2. 四大域对象
域对象是指可以像Map一样存取数据的对象,四个域对象功能一样,只是对数据的存取范围不同
- pageContext:当前页面,请求转发会失效
- request:一次请求,换一个请求地址会失效
- session:个会话,浏览器关闭会失效
- application:整个web工程范围,服务器没重启都有效
注意:若四个域对象在使用时范围都可满足要求,则使用的优先顺序是(范围从小到大):
pageContext --> request --> session --> application(原因:随时释放内存,减轻服务器压力)
3. JSP的out输出和response.getWriter输出的异同
- 相同点:response表示响应,用于给客户端(浏览器)返回内容
out同样也是用于给客户端(浏览器)输出内容 - 不同点:
注意:由于官方的代码中翻译后的Java代码底层都是使用out进行输出,故一般都使用out进行 输出,out又分为write方法和print方法:
(1) out.print():会将任何内容转换成字符串后调用write()方法输出
(2) out.write():输出字符串没有问题,但输出int型时会将int转换成char输出,导致输出的并非是想要的数字而是数字对应的ASCII码
结论:JSP页面的代码脚本中任何要输出在浏览器的内容均使用out.print()方法
7.3 JSP的常用标签
1. 静态包含:
使用场景:加入我们,友情连接、联系我们、版权归属…等作为一个单独的jsp页面引入主页面中,只需要维护一份
(2)使用方法:
<%@include file=""%>
其中file属性设置要包含的JSP页面,以/打头,代表http://ip:port/工程路径/,对应web目录
代码演示1:在web目录下创建body.jsp
<body>
头部信息 <br>
主体信息 <br>
<%@include file="/foot.jsp"%>
</body>
代码演示2:在web目录下创建foot.jsp
<body>
页脚信息 <br>
</body>
(3)静态包含的特点:
①静态包含不会将被包含的JSP页面翻译成.java.class文件
②静态包含是把被包含的页面的代码拷贝到body.jsp对应的Java文件的对应位置执行输出
2.动态包含:
(1)使用方法:
<jsp:include page=””></jsp:include>
其中page属性设置要包含的JSP页面,与静态包含一致
(2)动态包含的特点:
①动态包含将被包含的JSP页面翻译成.java.class文件
②动态包含还可以传递参数
③动态包含底层使用如下代码调用被包含的JSP页面执行输出:
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, “/foot.jsp”, out, false);
代码演示1:在web目录下创建body.jsp
<body>
头部信息 <br>
主体信息 <br>
<jsp:include page="/foot.jsp">
<jsp:param name="username" value="Jaychou"/>
<jsp:param name="password" value="root"/>
</jsp:include>
</body>
代码演示2:在web目录下创建foot.jsp
<body>
页脚信息 <br>
<%=request.getParameter("username")%>
</body>
3.请求转发:
<jsp:forward page="/scope2.jsp"></jsp:forward>
7.4 监听器
(1) Listener监听器是JavaWeb的三大组件之一
(2) Listener监听器是JavaEE的规范(接口)
(3) Listener监听器的作用是监听某件事物的变化,然后通过回调函数反馈给程序做一些处理
- ServletContextListener监听器
ServletContextListener监听器可以监听ServletContext对象的创建和销毁
web工程启动时创建,停止时销毁,监听到创建和销毁之后都会调用ServletContextListener监听器的方法进行反馈:
public interface ServletContextListener extends EventListener {
//在ServletContext对象创建之后调用
public void contextInitialized(ServletContextEvent sce);
//在ServletContext对象销毁之后调用
public void contextDestroyed(ServletContextEvent sce);
}
- ServletContextListener监听器的使用步骤
(1) 编写一个类实现ServletContextListener接口
(2) 重写两个方法
(3) 在web.xml文件中配置监听器
代码演示1:创建一个类
public class ListenerTest implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象创建");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象销毁");
}
}
代码演示2:在web.xml中配置
<listener>
<!-- <listener-class>标签中写上述程序的全类名 -->
<listener-class>com.zju.servlet.ListenerTest</listener-class>
</listener>
8. EL表达式 & JSTL标签库
8.1 EL表达式简介
-
EL表达式全称:Expression Language,即表达式语言,代替JSP页面中的表达式脚本输出
-
EL表达式的格式是:${表达式} ,注:EL表达式写在jsp页面中,表达式一般是域对象的key
-
EL表达式搜索域中数据顺序:按照四个域对象的范围从小到大进行搜索,找到就输出
1. EL表达式获取java类的属性
EL表达式中对象名.属性名不找属性的值,而是找名字对应的getXxx方法,没有此方法会报错
public class Person {
//输出Person类中普通属性,数组属性,list集合属性和map集合属性
private String name;
private String[] phones;
private List<String> cities;
private Map<String, Object> map;
//注意:没有声明age属性
public int getAge() {
return 18;
}
//以及全参、空参构造器,各属性的getter/setter方法
}
<body>
<%
Person person = new Person();
person.setName("JayChou");
person.setPhones(new String[]{"123","456","789"});
//给cities属性赋值
List<String> cities = new ArrayList<String>();
cities.add("北京");
cities.add("上海");
cities.add("深圳");
person.setCities(cities);
//给map属性赋值
Map<String,Object> map = new HashMap<>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
person.setMap(map);
pageContext.setAttribute("p", person);
%>
<%--EL表达式中对象名.属性名不找属性的值,而是找名字对应的getXxx方法,没有此方法会报错--%>
输出Person:${ p }<br/>
输出Person的name属性:${p.name} <br>
输出Person的phones数组地址值:${p.phones} <br>
输出Person的phones数组属性值:${p.phones[2]} <br>
输出Person的cities集合中的元素值:${p.cities} <br>
输出Person的List集合中个别元素值:${p.cities[2]} <br>
输出Person的Map集合: ${p.map} <br>
输出Person的Map集合中某个key的值: ${p.map.key1} <br>
<%-- 注意,即使没有age属性,但因为有getAge方法,也可得出结果 --%>
输出Person的age值:${p.age} <br>
</body>
8.2 EL表达式运算
语法:$(运算表达式)
-
关系运算:$(5!=5) —> true
-
逻辑运算:$(12 == 12 && 12!= 11) ----> true
-
算术运算:$(144 % 10) ---->4
-
empty运算:可以判断一个数据是否为空,语法:$(empty key1)
若为空,输出true,不为空,输出false
- 值为null、空串
- 值为Object类型的数组且长度为0 (注:其他类型的长度为0的数组值为非空)
- List、Map集合元素个数为0
<%
List<String> list = new ArrayList<>();
request.setAttribute("emptynull", list);
%>
$(empty emptynull); ---->true
- 三元运算:$(表达式 1?表达式 2:表达式 3)
表达式1为真返回表达式2的值,表达式1为假返回表达式3的值
$(12==12 ? "相等" : "不相等");
- ".“点运算和”[]"中括号运算
- 点运算可以输出某个对象的某个属性的值(getXxx或map中key value)
- 中括号运算可以输出有序集合中某个元素的值
- 注:中括号运算可以输出Map集合中key里含有特殊字符的key的值
<body>
<%
Map<String,Object> map = new HashMap<String, Object>();
map.put("a.a.a", "aaaValue");
map.put("b+b+b", "bbbValue");
map.put("c-c-c", "cccValue");
request.setAttribute("map", map);
%>
<%--特殊的key需要去掉最开始的"."并使用中括号和单引号(双引号)包起来--%>
${ map['a.a.a'] } <br> <%--如果不加中括号则相当于三个.运算--%> //错误的是 ${map.a.a.a}
${ map["b+b+b"] } <br> <%--如果不加中括号则相当于三个+运算--%>
${ map['c-c-c'] } <br> <%--如果不加中括号则相当于三个-运算--%>
</body>
8.3 EL表达式的11个隐含对象
1.pageScope、requestScope、sessionScope、applicationScope对象的使用
<body>
<%
//jsp四大域对象
pageContext.setAttribute("key1", "pageContext1");
pageContext.setAttribute("key2", "pageContext2");
request.setAttribute("key2", "request");
session.setAttribute("key2", "session");
application.setAttribute("key2", "application");
%>
<%-- 获取特定域中的属性 --%>
${ pageScope.key1 } <br>
${ applicationScope.key2 }
<%-- 若直接获取key1或key2依然按照之前范围从小到大检索,无法获取指定域 --%>
</body>
2.pageContext对象的使用
作用:1.协议 2.服务器ip: 3.服务器端口:
4.获取工程路径 5.获取请求方式 6.获取客户端ip地址 7.获取会话的id编号
大多数是request对象的属性值
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- 先通过pageContext对象获取request、session对象,再获取以下内容 --%>
<%--
获取请求的协议:request.getScheme()
获取请求的服务器ip或域名:request.getServerName()
获取请求的服务器端口号:request.getServerPort()
获取当前工程路径:request.getContextPath()
获取请求的方式:request.getMethod()
获取客户端的ip地址:request.getRemoteHost()
获取会话的唯一标识:session.getId()
--%>
1.协议: ${ pageContext.request.scheme }<br>
2.服务器ip:${ pageContext.request.serverName }<br>
3.服务器端口:${ pageContext.request.serverPort }<br>
4.获取工程路径:${ pageContext.request.contextPath }<br>
5.获取请求方法:${ pageContext.request.method }<br>
6.获取客户端ip地址:${ pageContext.request.remoteHost }<br>
7.获取会话的id编号:${ pageContext.session.id}<br>
</body>
</html>
3.param、paramValues对象的使用
<body>
获取请求参数username的值:${ param.username } <br>
获取请求参数password的值:${ param.password } <br>
获取请求参数中第一个hobby的值:${ paramValues.hobby[0] } <br>
获取请求参数中第二个hobby的值:${ paramValues.hobby[1] } <br>
<%-- 有多个同名的key时使用paramValues的索引值决定获取哪一个,使用param只可获取第一个 --%>
使用param获取hobby的值:${ param.hobby } <br>
</body>
地址栏输入:http://localhost:8080/MyTest/Test.jsp?username=Jaychou&password=123&hobby=sing&hobby=play
4.header, headerValues对象的使用
<body>
输出请求头[user-Agent]的值:${ header["User-Agent"] }<br>
输出请求头中第一个[user-Agent]的值:${ headerValues["User-Agent"][0] }<br>
</body>
5.cookie对象的使用
<body>
获取Cookie的名称:${ cookie.JSESSIONID.name } <br>
获取Cookie的值:${ cookie.JSESSIONID.value } <br>
</body>
6.InitParam对象的使用
读取context-param初始化参数
在web.xml中修改参数
<context-param>
<param-name>username</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql:///test</param-value>
</context-param>
在web目录下创建test.jsp
<body>
输出<Context-param>username的值:${ initParam.username } <br>
输出<Context-param>url的值:${ initParam.url } <br>
</body>
8.4 JSTL标签库简介
EL表达式主要是为了替换JSP中的表达式脚本,JSTL(JSP Standard Tag Library)标签库是为了替换代码脚本
使用步骤:
- 导入jar包(taglibs-standard-impl)
- 在jsp页面中使用taglib指令引入标签库(可自动导包)
CORE 标签库
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
8.5 JSTL核心库core使用
1.<c:set/>标签,作用:可以往域中保存数据, var属性表示key, value属性表示值
scope属性设置保存到哪个域:page,request,session,application
<c:set scope = "page" var = "username" value = "fkd"/>
2.<c:if/>标签,作用:做if判断。test属性设置判断的条件,属性值使用EL表达式。
<c:if test="${ 1 == 1 }">
true
</c:if>
3.<c:choose>、<c:when>、<c:otherwise>标签,作用:多路判断,类似switch-case-default结构
注意:
(1) 使用三种标签时标签里不能使用html注释,要使用jsp注释
(2) when标签的父标签一定是choose标签
(3) when标签是从上向下依次判断的,一旦有满足的就不会再判断剩余when标签
<c:choose>
<c:when test="${requestScope.grade > 90}">
优秀
</c:when>
<c:when test="${requestScope.grade > 80}">
良好
</c:when>
<c:when test="${requestScope.grade > 60}">
及格
</c:when>
<c:otherwise>
不及格
</c:otherwise>
</c:choose>
4.<c:forEach/>标签,作用:遍历输出(与foreach循环一样,自动的遍历到下一个数据)
- 遍历1-10
<body>
<%--
begin属性设置开始的索引
end属性设置结束的索引
var属性表示循环的变量(当前正在遍历到的数据),可任意取名
循环的是foreach起始和结束标签中的内容
--%>
<c:forEach begin="1" end="10" var="i">
第${i}行
</c:forEach>
</body>
- 遍历数组
<body>
<%--
items表示遍历的数据源
var表示当前遍历到的数据,可任意取名
--%>
<%
request.setAttribute("arr", new String[]{"周杰伦","昆凌","方文山"});
%>
<c:forEach items="${ requestScope.arr }" var="item">
${ item } <br>
</c:forEach>
</body>
- 遍历Map集合
<body>
<%
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
request.setAttribute("map", map);
%>
<c:forEach items="${ requestScope.map }" var="entry">
${entry.key} 等于 ${entry.value} <br>
<%-- ${entry}会将所有数据以 key=value 格式输出 --%>
</c:forEach>
</body>
- 遍历List集合,集合中存放Student类
<body>
<%
List<Student> studentList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
studentList.add(new Student(i,"username"+i ,"pass"+i,18+i,"phone"+i));
}
request.setAttribute("stus", studentList);
%>
<%--
items 表示遍历的数据源
var 表示遍历到的数据
begin表示遍历的开始索引值(起始为0),不写begin代表从第一个开始
end 表示结束的索引值,不写end代表遍历到最后一个
step 属性表示遍历的步长值,默认是1
varStatus 属性表示当前遍历到的数据的状态
--%>
<c:forEach items="${requestScope.stus}" var="stu" begin="2"
end="7" step="2" varStatus="status">
${stu.id} <br>
${stu.username} <br>
${stu.password} <br>
${stu.age} <br>
${stu.phone} <br>
${status.step} <br> <%--还可获取更多状态,见下图--%>
</c:forEach>
<%--运行结果:从3输出到8,每隔两个输出,即只有3、5、7--%>
</body>
varStatus属性可以获得的状态:读方法:isXxx()或者getXxx()
9.文件的上传与下载
9.1 文件上传
1.要有一个form标签,method = post请求方式,原因:文件的长度一般都会超过get请求的限制
2.form标签的encType属性值必须为multipart/form-data
3.在form标签中使用input标签,type = file添加上传的文件;在form标签中使用input标签,type = submit提交到服务器
5.编写Servlet程序接收、处理上传的文件
注意:encType = multipart/form-data表示提交的数据以多段(每一个表单项表示一个数据段)的形式 进行拼接,然后以二进制流的形式发送给服务器
- 文件上传的Http协议:
- 服务器对上传的数据进行解析:
首先需要导入两个第三方的jar包,commons-fileupload-1.2.1.jar与commons-io-1.4.jar
(1) ServletFileUpload类,用于解析上传的数据
①public static final boolean isMultipartContent(HttpServletRequest request)
如果上传的数据是多段的形式,返回true,只有多段的数据才是文件上传的
②public ServletFileUpload()
空参构造器
③public ServletFileUpload(FileItemFactory fileItemFactory)
参数为工厂实现类的构造器
④public List parseRequest(HttpServletRequest request)
解析上传的数据,返回包含每一个表单项的List集合
(2) FileItem类,表示每一个表单项
①public boolean isFormField()
如果当前表单项是普通表单项,返回true,文件类型返回false
②public String getFieldName()
获取当前表单项的name属性值
③public String getString()
获取当前表单项的value属性值,参数为”UTF-8”可解决乱码问题
④public String getName()
获取上传的文件名
⑤public void write(File file)
将上传的文件写到参数File所指向的硬盘位置
(1):在web目录下创建Upload.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8080/servlet_2/uploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br>
头像:<input type="file" name="photo"><br>
<input type="submit" value="上传">
</form>
</body>
</html>
(2):创建Servlet程序upLoadServlet.java
package zju.edu; /**
* @author godfu
* @Date:2022/3/14-23:36
*/
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
@WebServlet(name = "UploadServlet", value = "/uploadServlet")
public class UploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.先判断上传的数据是否是多段数据
if(ServletFileUpload.isMultipartContent(request)){
//2.创建用于解析上传数据的工具类ServletFileUpload
FileItemFactory fileItemFactory = new DiskFileItemFactory();
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
//3.解析上传数据,得到每一个表单项
List<FileItem> list = servletFileUpload.parseRequest(request);
//遍历每一个表单项
for (FileItem fileItem:list){
//普通表单项
if (fileItem.isFormField()){
System.out.println("普通表单项的name属性值:"+fileItem.getFieldName());
System.out.println("普通表单项的value属性值:"+fileItem.getString("UTF-8"));
}else{
//上传的是文件类型
System.out.println("表单项的name属性值:"+fileItem.getFieldName());
System.out.println("上传的文件名"+fileItem.getName());
//将文件写入磁盘位置
fileItem.write(new File("E:\\"+fileItem.getName()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
9.2 文件的下载
- 获取要下载的文件名
使用String定义要下载的文件名
- 获取要下载的文件类型,告诉客户端
通过ServletContext的getMimeType(); 参数是要下载的文件所在路径,返回值是String类型
通过HttpServletResponse的setContentType(); 参数是第二步的结果,无返回值
- 告诉客户端收到的数据用于下载使用
通过HttpServletResponse的setHeader();
参数是"Content-Disposition", “attachment; fileName=xxx.xxx”
注意:Content-Disposition响应头表示客户端收到的数据如何处理
attachment表示附件,用于下载
filename表示下载的文件名,可以与原文件名不同
此方法无返回值
- 获取要下载的文件并回传给客户端
回传给客户端通过导入的io包的IOUtils类的copy(InputStream input, OutputStream output);
其中:
①通过ServletContext的getResourceAsStream(); 参数是要下载的文件路径,得到输入流
②通过HttpServletResponse的getOutputStream(); 得到响应的输出流
package zju.edu; /**
* @author godfu
* @Date:2022/3/15-10:51
*/
import org.apache.commons.io.IOUtils;
import sun.nio.ch.IOUtil;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@WebServlet(name = "DownloadServlet", value = "/downloadServlet")
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取要下载的文件名
String downloadFileName = "a.jpg";
ServletContext servletContext = getServletContext();
//2.获取要下载的文件类型,告诉客户端
String mimeType = servletContext.getMimeType("/File/" + downloadFileName);
response.setContentType(mimeType);
//3.告诉客户端收到的数据用于下载使用,Content-Disposition响应头表示收到数据怎么处理
//attachment表示附件,表示下载使用
response.setHeader("Content-Disposition","attachment;filename=狗.jpg");
//4.获取要下载的文件并回传给客户端
InputStream inputStream = servletContext.getResourceAsStream("/File/" + downloadFileName);
OutputStream outputStream = response.getOutputStream();
IOUtils.copy(inputStream,outputStream);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
-
中文名下载文件乱码问题
-
原因:
response.setHeader(“Content-Disposition”, “attachment; fileName=中文名.jpg”);
如果下载的文件是中文名,会发现下载的文件无法正常显示汉字,原因是响应头中不能有汉字 -
解决:
需要使用URLEncoder类先对中文名进行UTF-8编码,因为IE浏览器和谷歌浏览器收到含有 编码的字符串后会以UTF-8字符集进行解码显示
response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("狗狗.jpg","UTF-8"));
10.MVC
MVC 全称: Model 模型、 View 视图、 Controller 控制器。MVC 是一种思想,MVC 的理念是将软件代码拆分成为组件, 单独开发, 组合使用(目的还是为了降低耦合度)
- View 视图: 只负责数据和界面的显示, 不接受任何与显示数据无关的代码, 便于程序员和美工的分工合作
JSP/HTML。 - Controller 控制器: 只负责接收请求, 调用业务层的代码处理请求, 然后派发页面, 是一个“调度者”的角色——Servlet。转到某个页面。 或者是重定向到某个页面。
- Model 模型: 将与业务逻辑相关的数据封装为具体的 JavaBean 类, 其中不掺杂任何与数据处理相关的代码——JavaBean/domain/entity/pojo。
11.Cookie和Session
11.1 Cookie
1.概念:将数据保存到客户端,客户端有了Cookie之后,每次请求都会发送给服务器
作用:
(1) Cookie一般用于存储少量的安全性较低的数据
(2) 在不登陆的情况下,完成服务器对客户端的身份识别,如没有登录百度账号的前提下打开百 度,设置搜索引擎搜索时不提示,以后打开浏览器访问百度时,不会再出现搜索提示框,原 理:百度服务器将设置的Cookie信息保存到浏览器,下次访问百度时,百度服务器获取浏览 器的Cookie,根据Cookie的值决定要不要显示提示框
特点:
(1) 在Tomcat 8之后Cookie可以存中文,但特殊中文字符仍不支持,建议使用URL编码格式
(2) 浏览器对单个Cookie有大小限制(4KB),对同一个域名下的总cookie数量也有限制(20个)
2.使用步骤:
-
(1) 创建Cookie对象,参数中绑定数据(键值对)
new Cookie(String name, String value); -
(2) 客户端向服务器发送请求后,服务器向客户端发送Cookie对象,客户端保存cookie
response.addCookie(Cookie cookie);
- (3) 客户端收到Cookie后,再次发送请求时,服务器获取从客户端发来的Cookie对象
request.getCookies(); Cookie[]
- (4) 服务器得到Cookie对象后,使用getName与getValue方法得到Cookie对象的数据
3.Cookie值的修改:
- 方案一:创建一个同名的新cookie,调用 response.addCookie( Cookie ) 修改
- 方案二:获取cookie对象,通过setValue()方法修改
4.浏览器查看cookie
5.Cookie在浏览器中的保存时间
(1) 默认情况下,当浏览器关闭后,Cookie数据被销毁
(2) 持久化存储:
使用Cookie对象的setMaxAge(int seconds)方法:
a. 正数:将Cookie数据写到硬盘中存储,参数指定存活的秒数,时间到后,数据失效。采用格林时间。
b. 负数:默认情况
c. 零:删除cookie信息
6.Cookie 有效路径 Path 的设置
Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。 哪些不发。path 属性是通过请求的地址来进行有效的过滤。
CookieA | path=/工程路径 |
---|---|
CookieB | path=/工程路径/abc |
- http://ip:port/工程路径/a.html
CookieA 发送;CookieB 不发送 - http://ip:port/工程路径/abc/a.html
CookieA 发送;CookieB 发送
11.2 免用户名登录
11.3 Session
Session 就一个接口(HttpSession)
(1) Session用于存储一次会话的多次请求数据,存在服务器端,一次会话只有一个session对象
(2) Session可以存储任意类型,任意大小的数据。
(3) Session 会话中,我们经常用来保存用户登录之后的信息。
1. 快速入门
(1) 获取HttpSession对象
HttpSession session = request.getSession();
注:①第一次调用表示创建Session会话
②之后调用都是获取前面创建好的Session会话对象
(2) 使用HttpSession对象的方法
void setAttribute(String name, Object value);
Object getAttribute(String name);
void removeAttribute(String name);
2. Session 生命周期控制
- public void setMaxInactiveInterval(int interval) 设置session超时时间,超过指定时长就会被销毁。默认30分钟。
- public void invalidate() 让当前 Session 会话马上超时无效。
- Session的超时:指的是客户端两次请求的最大间隔时长
3.Session与Cookie的区别:
(1) Session存储数据在服务器端,Cookie在客户端
(2) Session没有数据大小的限制,Cookie有(4KB)
(3) Session数据安全,Cookie相对不安全
4.Session底层技术细节:(浏览器和Session关联)
Session 技术, 底层其实是基于 Cookie 技术来实现的。
5.Session被销毁的方式
(1)客户端关闭,Cookie消失,其中的Session自然也消失
(2)Session对象调用invalidate()
(3)Session默认失效时间:30分钟,可以到web.xml中修改配置文件修改默认失效时间
11.4 验证码解决表单重复提交
表单重复提交有三种常见的情况:
一: 提交完表单。 服务器使用请求转来进行页面跳转。 这个时候, 用户按下功能键 F5, 就会发起最后一次的请求。造成表单重复提交问题。 解决方法: 使用重定向来进行跳转
二: 用户正常提交服务器, 但是由于网络延迟等原因, 迟迟未收到服务器的响应, 这个时候, 用户以为提交失败,就会着急, 然后多点了几次提交操作, 也会造成表单重复提交。
三: 用户正常提交服务器。 服务器也没有延迟, 但是提交完成后, 用户回退浏览器。 重新提交。 也会造成表单重复提交。
- 导入谷歌验证码的 jar 包
- 在 web.xml 中去配置用于生成验证码的 Servlet 程序
- 在表单中使用 img 标签去显示验证码图片并使用它
- 在服务器获取谷歌生成的验证码和客户端发送过来的验证码比较使用。
12. Filter
- Filter过滤器是JavaWeb三大组件之一,其余组件是:Servlet程序、Listener监听器
- Filter过滤器是JavaEE规范,也就是一个接口
- Filter过滤器的作用是:拦截请求、过滤响应
12.1 Filter过滤器的使用步骤
用户访问拦截路径时会自动触发doFilter()方法:
1.编写一个类取实现Filter接口(导入的包为:javax.servlet.Filter))
2.实现过滤方法doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain
filterChain)
- filterChain.doFilter(servletRequest,servletResponse)只有执行此方法,才可以访问拦截路径中的资源,若未执行此方法则代表拦截
3.到web.xml配置filter拦截路径
- Filter过滤器也支持注解,在首行加@WebFilter(“拦截路径”),则无需web.xml文件
- 浏览器不能直接访问实现Filter接口的类,只需访问拦截路径,就会自动的触发doFilter方法
示例:
Fileter代码
public class AdminFilter implements Filter {
/**
* doFilter 方法, 专门用于拦截请求。 可以做权限检查
*/
@Override
public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpSession session = httpServletRequest.getSession();
Object user = session.getAttribute("user");
// 如果等于 null, 说明还没有登录
if (user == null) {
servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
return;
} else {
// 让程序继续往下访问用户的目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
web.xml编写配置
<!-- Filter标签用于配置一个Filter过滤器,用法与Servlet标签一致 -->
<filter>
<filter-name>LoginServlet</filter-name>
<filter-class>com.qizegao.Filter.LoginServlet</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginServlet</filter-name>
<!-- url标签用于配置拦截路径,也就是访问哪些资源需要被拦截 -->
<!-- /表示工程路径,映射到web目录 -->
<!-- /*代表指定目录下的所有文件 -->
<url-pattern>/Admin/*</url-pattern>
</filter-mapping>
12.2 Filter生命周期,FilterConfig类,FilterChain过滤器链
1.Filter生命周期:
- 1.构造器方法
- 2.init初始化方法
- 3.doFilter方法 (其中有chain.doFilter方法)
- 4.destroy方法
其中:① 1和2在web工程启动的时候执行(即在创建Filter过滤器)
② 第三步,符合拦截路径的请求发送到服务器的时候,自动的执行,若请求不属于拦截路径,则不会执行
③ 第四步,停止web工程的时候执行(停止web工程,也会销毁Filter过滤器)
2.FilterConfig类
FilterConfig类是Filter过滤器的配置文件类,每次创建Filter的时候,Tomcat也会创建一个FilterConfig类,其中包含了Filter配置文件的配置信息。FilterConfig类的作用是获取Filter过滤器的配置文件内容。
- 获取Filter的名称,即web.xml文件中标签的值:filterConfig.getFilterName();
- 获取在 Filter 中配置的 init-param 初始化参数:filterConfig.getInitParameter(“username”);
- 获取 ServletContext 对象:filterConfig.getServletContext()
3.FilterChain过滤器链
作用:解决多个过滤器一起工作
- 根据不同的自愿拦截路径,会执行不同的Filter过滤器的方法,FilterChain.doFilter方法的作用是:如果有下一个Filter则执行;如果没有,则执行目标资源
- 所有filter和目标资源默认是在同一个线程中,他们共享Request对象中的数据
12.3 Filter拦截路径
1.精确匹配:
<url-pattern>/target.jsp</url-pattern>
表示请求的地址必须为http://ip:port/工程路径/target.jsp,才可以触发doFilter方法
2.目录匹配:
<url-pattern>/admin/*</url-pattern>
表示请求的地址必须为http://ip:port/工程路径/admin/目录下所有的文件,才可以触发doFilter方法
3.后缀名匹配:
<url-pattern>*.jsp</url-pattern>
表示请求地址必须以.jsp结尾才可以触发doFilter方法
注意:Filter过滤器只关心请求的地址是否符合拦截路径,不会关心请求的资源是否存在
13. ThreadLocal
ThreadLocal的作用,它可以解决多线程的数据安全问题.只给当前线程中用。
ThreadLocal可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组或者集合)
- 1.每个 ThreadLocal 对象实例定义的时候, 一般都是 static 类型
//泛型相当于value,key是当前线程
public static ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();
- 2.每一个 ThreadLocal 对象, 只能为当前线程关联一个数据, 如果要为当前线程关联多个数据, 就需要使用多个ThreadLocal 对象实例。
- 3.ThreadLocal 可以为当前线程关联一个数据。 (它可以像 Map 一样存取数据, key 为当前线程)
Integer i = new Random().nextInt(1000);
//存数据
threadLocal.set(i);
//取数据
Object o = threadLocal.get(i);
- 4.ThreadLocal 中保存数据, 在线程销毁后。 会由 JVM 虚拟自动释放
13.1使用 Filter 和 ThreadLocal 组合管理事务
之前版本由于采用了连接池,多次dao是多个不同的连接
Tomcat一次请求就是一个相同线程,可以使用 ThreadLocal 来确保所有 dao 操作都在同一个 Connection 连接对象中完成。
使用 Filter 过滤器统一给所有的 Service 方法都加上 try-catch。 来进行实现的管理。
14. Json和Ajax
14.1 Json的介绍
JSON是一种轻量级(相较于xml)的数据交换格式(客户端(js)和服务器(java)之间数据的传递格式)。
JSON采用完全独立于语言的文本格式,很多语言都提供了 对JSON的支持(C、JAVA、JavaScript等),这就使得JSON成为理想的数据交换格式。
14.2 Json在JavaScript中的使用
1.定义:
JSON是由键值对组成,并且由大括号包围,每个键由引号引起(不使用引号也可以),键和值之间 使用冒号进行分割,多组键值对之间由逗号进行分割 (最后一组不加逗号)
<script type="text/javascript">
var jsonObj = {
"key1":12,
"key2":"abc",
"key3":true,
"key4":[11,"arr",false],
//JSON中套JSON
"key5":{
"key5_1":551,
"key5_2":"key5_2"
},
//数组中放JSON
"key6":[{
"key6_1_1":611,
"key6_1_2":621
},{
"key6_2_1":621,
"key6_2_2":622
}]
};
</script>
2.Json的访问
JSON本身是一个对象,JSON中的key可以理解为是对象中的一个属性,JSON中的key的访问与访问对象的属性一致:JSON对象.key。
alert(typeof (jsonObj)); //Object
alert(jsonObj.key1); //12
alert(jsonObj.key4); //11,arr,false
//JSON中数组值的遍历
for (var i = 0; i < jsonObj.key4.length; i++) {
alert(jsonObj.key4[i]);
}
//访问JSON中定义的JSON
alert(jsonObj.key5.key5_1); //551
alert(jsonObj.key6); //[object Object],[object Object]
//取出来的每一个元素都是JSON对象
var key6Element = jsonObj.key6[0];
alert(key6Element.key6_1_1); //611
alert(key6Element.key6_1_2); //621
3.JSON的两个常用方法
-
JSON的存在有两种形式:
(1) 对象的形式存在,称为JSON对象
此形式常用于操作JSON中的数据
(2) 字符串的形式存在,称为JSON字符串
此形式常用于在客户端和服务器之间进行数据的交换 -
JSON的两个方法
(1) JSON.stringify(JSON对象):把JSON对象转换成为JSON字符串(类似JAVA中的toString方法)
(2) JSON.parse(字符串):把JSON字符串转换成为JSON对象
var stringify = JSON.stringify(jsonObj);
alert(stringify); //JSON对象中的所有内容全部转换为字符串
var jsonObj2 = JSON.parse(stringify);
alert(jsonObj2.key1); //12
alert(jsonObj2.key2); //abc
14.3 Json在Java中的使用
-
首先导入jar包:gson-2.2.4.jar
-
创建Gson实例,调用 (1) toJson()方法:将参数转换成JSON字符串
(2) fromJson()方法:将参数JSON字符串还原
1.JavaBean和Json转换:
@Test
public void test1(){
//Person类中有id和name属性
Person person = new Person(12, "jay");
//创建Gson对象实例
Gson gson = new Gson();
//toString方法将java对象转换成JSON字符串
String toJson = gson.toJson(person);
System.out.println(toJson); //{"id":12,"name":"jay"}
//fromJson方法将JSON字符串转换成Java对象
//第一个参数是需要转换的JSON字符串
//第二个参数是转换回去的Java对象类型
Person person1 = gson.fromJson(toJson, Person.class);
System.out.println(person1); //Person{id=12, name='jay'}
}
2.List和Json转换:
@Test
public void test2(){
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person(1,"Tom"));
personList.add(new Person(2,"Jerry"));
//创建Gson对象
Gson gson = new Gson();
//把List集合转换成为JSON字符串
String s = gson.toJson(personList);
System.out.println(s); //[{"id":1,"name":"Tom"},{"id":2,"name":"Jerry"}]
/*将JSON字符串还原,如果还原的是集合,第二个参数是Type类型
首先创建一个类(PersonListType),此类继承TypeToken<T>,
T泛型是要转换回去的类型,T是List<Person>或ArrayList<Person>
则此类为PersonListType extends TypeToken<ArrayList<Person>>
此类什么都不做,类体是空的 */
List<Person> list = gson.fromJson(s, new PersonListType().getType());
System.out.println(list); //[Person{id=1, name='Tom'}, Person{id=2, name='Jerry'}]
}
3.map和json转换:
@Test
public void test3(){
Map<Integer,Person> personMap = new HashMap<>();
personMap.put(1, new Person(1, "Dog"));
personMap.put(2, new Person(2, "Cat"));
Gson gson = new Gson();
String JsonString = gson.toJson(personMap);
System.out.println(JsonString); //{"1":{"id":1,"name":"Dog"},"2":{"id":2,"name":"Cat"}}
//将JSON字符串转换为集合时,还有一种简便方式:接口的匿名实现类的匿名对象
Map<Integer,Person> personMap2 =
gson.fromJson(JsonString, new TypeToken<HashMap<Integer,Person>>(){}.getType());
System.out.println(personMap2); //{1=Person{id=1, name='Dog'}, 2=Person{id=2, name='Cat'}}
}
14.4 AJAX的介绍及使用
AJAX的概念:异步的JavaScript和XML,通过在后台与服务器 进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。传统的网页(不使用Ajax)如果需要更新内容,必须重载整个网页页面。
- Ajax 请求的局部更新, 浏览器地址栏不会发生变化
- 局部更新不会舍弃原来页面的内容
-
同步就是客户端的所有请求都返回数据后,一起相应。(串行)
-
异步就是客户端其他部分不用等待服务器局部相应,先执行;AJAX请求等服务器响应后单独执行。(类似并发)
1.jQuery中的AJAX请求:
$.ajax({键对值})
url | 表示请求的地址 |
---|---|
type | 表示请求的类型GET或POST请求 |
data | 表示发送给服务器的数据{key:value}(相当于?key=value&key=value) |
success | 请求成功,相应的回调函数(参数为返回的参数) |
dataType | 响应(返回)的数据类型:text(纯文本)、xml(xml数据)、json(json对象) |
$("#ajaxBtn").click(function(){
$.ajax({
url:"http://localhost:8080/16_json_ajax_i18n/ajaxServlet",
// data:"action=jQueryAjax",
data:{action:"jQueryAjax"},
type:"GET",
success:function (data) {
// alert("服务器返回的数据是: " + data);
// 传递回来是字符串,需要转成json类型才能取出数据
// var jsonObj = JSON.parse(data);
$("#msg").html("编号: " + data.id + " , 姓名: " + data.name);
},
dataType : "json"
});
});
protected void jqueryAjax(HttpServletRequest request, HttpServletResponse response){
Person person = new Person(1,"fkd");
//json格式字符串
Gson gson = new Gson();
String personJsonString = gson.toJson(person);
response.getwriter().write(personJsonString);
}
. g e t 方 法 和 .get方法和 .get方法和.post方法(对以上的封装)
url | 请求的url地址 |
---|---|
data | 发送的数据 |
callback | 成功的回调函数 |
type | 返回的数据类型 |
$.getJSON(url,data,callback)通过http的get请求返回JSON数据
url | 请求的url地址 |
---|---|
data | 发送的数据 |
callback | 成功的回调函数 |
表单序列化 serialize():
serialize()可以把表单中所有表单项的内容都获取到, 并以 name=value&name=value 的形式进行拼接。