THIS IS B3c0me

记录生活中的点点滴滴

0%

Javaweb

一、C/S架构和B/S架构

对于一个软件系统,用户是通过用户界面来完成与软件系统的交互的,根据软件不同的架构模式,软件系统界面设计的实现技术是不同的

1.1 C/S架构

client-server 基于客户端和服务器的架构模式

特点:

  • 想要使用软件的话需要下载软件客户端软件并安装
  • 需要连接互联网
  • 服务端需要正在运行

优点:

  • 提前下载并安装了客户端,响应速度块
  • 客户端功能比较丰富

缺点:

  • 客户端需要专门下载,如果是临时使用的话不太方便
  • 需要占用本地的磁盘空间

1.2 B/S架构

Browser-Server

优点:

  • 打开浏览器即可使用

缺点:

  • 界面存储在服务器上,需要通过网络传输到用户的浏览器显示,显示速度受网速限制

1.3 Java前端开发技术栈

1.3.1 C/S

java语言可以进行C/S架构开发,JDK提供的awt(abstract window toolkit)可以进行窗体开发

  • awt
  • swing

1.3.2 B/S

Java语言主要应用于web系统的开发,web系统就是基于B/S架构

  • HTML 决定网页结构
  • CSS 决定网页样式
  • javaScript 实现和用户的交互

1.3.3 移动应用

Java语言可以用于Android和鸿蒙系统的应用开发

  • AndroidUI xml及组件
  • HarmonyOSUI xml 及组件

二、HTML简介

2.1 什么是网页

通过网址请求的可以在网络中传输的,并且可以通过浏览器解析显示视图的页面

  • 存储在服务器上的页面文件中编写的是浏览器可以识别的代码
  • 当浏览器请求服务时,服务器将代码渲染成视图

2.2 HTML是什么

2.3 HTML书写规范

  • 网页文件后缀名为 html 或 htm
  • 网页文件有一个基本结构
2.3.1 HTML版本规范

前端规范—w3c

  • html 4
  • xhtml
  • html 5

2.4 前端开发工具

  • webStorm
  • vsCode
  • subline
  • Hbuilder

三、HTML 常用标签

3.1 显示标签

1
2
3
4
5
6
7
8
9
10
11
12
13
1.文本标签:
<font color="red" face="黑体" size='7'>显示文本1,不推荐使用</font>

<lable style="color:red;font-size:100px;font-family:楷体">显示文本2</lable>

2.图片标签:
<img src="图片路径,可以是网络地址也可以是本地地址" width="宽度" hight="高度" alt="文本代替"/>

3.声音和视频
<audio src="音频文件地址" controls autoplay >调用浏览器内置的播放器,默认隐藏。controls表示显示播放器.autoplay自动播放</audio>

<video src="视频文件地址" controls width="视频宽度" >视频播放器,controls表示显示进度条</video>

3.2 表单标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1.input标签
<input type="text" value="默认值" />文本输入框
<input type="password" />密码输入框
<input type="radio" name="选择类型" value="选择后提交的值" checked="" />单选按钮,多个name相同的单选按钮只能选择一个
<input type="checkbox" name="类型" value="值" checked="" />复选框,
<input type="button" value=" " />按钮
<input type="reset" />重置按钮,必须在表单中使用,用于重置表单中输入框的值
<input type="submit" />提交按钮,用在form表单中,用于提交表单中的数据
<input type="image" src=" 图片地址 " />图片按钮
<input type="file" />文件选择框
<input type="number" min="最小值"max="最大值" />数字输入框
<input type="date" />日期输入框
<input type="color" />颜色选择框
<input type="email" />邮箱输入框
<input type="tel" />电话输入框
<input type="search" />搜索输入框

2.select标签
<select multiple size="下拉列表中可见选项的数值">
<option value="提交的值" >选项</option>
</select>

3.textarea标签
<textarea rows="行数" cols="每行显示的字符个数">多行输入框,这里是文本域的默认值</textarea>

4.form标签
<form id="form1" action="所要提交到的url" method="post/get" enctype="编码方式">
<input type="text" placeholder="请输入账号" name="userName"/><br/>
<input type="password" placeholder="请输入密码" name="userPwd"/><br/>
<input type="submit" value="登录"/>
</form>
<input type="submit" value="login" form="form1" formaction="url" formmethod="get/post"/>H5可以在form表单外面提交

3.2.1 表单标签共有属性
  • id属性,表示此标签在当前网页文件中的唯一标识。在一个网页中标签的id要保持唯一性
  • name属性,用于将数据提交到后端时在后端读取数据
  • required属性,表示限制当前输入框必须输入数据
  • placeholder属性,设置输入框的提示信息
  • readonly属性,表示设置此输入视图只能显示数据,不能点击输入
  • disabled属性,限制输入,选择等行为
  • value属性,用于表示当前输入框的值

3.3布局标签

对网页中的视图组建进行排版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
1.标题
<h1>
标题1到标题6
</h1>

2.段落
<p>
这是一个段落,前后会自动留白,但没有缩进功能
</p>

3.列表
<ol type="指定序号类型">
<li>有序列表中的项,自动编序</li>
</ol>

<ul type="指定图标类型">图标类型有circle空心,disc实心圆,square方形实心
<li>无序列表中的项</li>
</ul>

<dl>
<dt>分组1</dt>
<dd>元素1</dd>
<dd>元素2</dd>
<dt>分组2</dt>
</dl>


4.表格
<table border="边框宽度同时设置单元格边框和外边框" cellspacing="单元格之间的空隙" cellpadding="单元格内边距" width="宽度" height="高度" align="当前表格在网页中的水平位置" bgcolor="背景颜色">

<tr height="行高度" bgcolor="背景颜色">第一行
<td width="列宽度" bgcolor="单元格背景" valign="单元格内容垂直位置" align="单元格内容水平位置" colspan="占用列数" rowspan="占用行数">第一个单元格</td>
<td>第二个单元格</td>
</tr>

<tr>第二行
<td>第一个单元格</td>
<td>第二个单元格</td>
</tr>

</table>

5.区块
<div style="width:300px;">
是一个层,也是一个容器
如果不设置宽度,则占据整个页面宽度
如果不设置高度,为其中存放的元素高度相同

</div>

<fieldset>
处于一个容器,默认有边框
可以认为是网页中的模块
<legend>
子标签,用于设置当前模块区域的标题(标题支持图标形式)
</legend>
</fieldset>

3.4 功能标签

1
2
3
4
1.from标签,见上文
2.a标签
<a href="链接地址">点击文本、图片跳转到链接</a>
<a href="#id">跳转到id位置</a>

3.5 框架标签

1
2
3
4
1.iframe标签
<iframe name="框架名,用于设置超链接" frameborder="框架边框宽度">
是一个页面容器
</iframe>

3.6 其他标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1.文本相关

<b>粗体显示文本</b>
<em>强调文本内容</em>
<i>斜体文本</i>
<strong>加重语气</strong>
<small>小号文本</small>
<sup>上标</sup>
<sub>下标</sub>
<u>下划线</u>

2.计算机输出相关

<code>代码块</code>
<kbd>键盘指示文字</kbd>
<var>程序变量标签</var>
<pre>预定义格式文本</pre>

3.引用相关
<address>地址信息引用</address>
<abbr title="全写">缩写</abbr>
<bdo dir="rtl反向">定义文字方向</bdo>
<blockquote>
块级引用
</blockquote>


四、HTML页面设计案例

  • 华为商城登录页面

使用HTML标签完成华为商城的登录页面的模仿设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<body>
<table width="100%" height="720" cellspacing="0" cellpadding="0" >
<tr height="35" bgcolor="#eeeeee">
<td width=20%""></td>
<td valign="middle">
<img src="Huaweiimg/1.jpg" height="30" alt="华为商标">
<label >|华为商城</label>
</td>
<td></td>
<td width="20%"></td>

</tr>
<tr height="135">
<td></td>
<td colspan="2" align="center">
<label style="font-size:15px;">华为账号登录</label>
</td>

<td></td>

</tr>
<tr height="350">
<td></td>
<td align="center" width="30%">
<img src="Huaweiimg/qrcode.jpg" alt="二维码">
<br/>
<br/>
<br/>
<label style="font-size:10px;color:grey">若您使用华为手机,前进入"设置">"华为账号"扫码登录</label>

</td>
<td width="30%" align="center">
<table cellspacing="0" cellpadding="0" height="350" width="100%">
<tr>
<td align="center"><input type="text" placeholder="请输入手机号/邮箱/账户名"></td>
</tr>
<tr>
<td align="center">
<input type="password" placeholder="密码"><br>
<label style="font-size:8px"><a href="#">使用短信验证登录</a></label>
</td>
</tr>
<tr>
<td align="center">
<input type="submit" value="登录">
</td>
</tr>
<tr>
<td align="center">
<a href="#">注册</a>
<a href="#">忘记密码</a>
<a href="#">遇到问题</a>

</td>
</tr>
<tr>
<td align="center">
<a><img src="Huaweiimg/qqimg.jpg" width="10%"></a>
<a><img src="Huaweiimg/weixin.jpg" width="10%"></a>
<a><img src="Huaweiimg/zhifubao.jpg" width="10%"></a>
</td>
</tr>
</table>
</td>
<td></td>
</tr>
<tr height="">
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr bgcolor="#eeeeee">
<td></td>
<td colspan="2" align="center">
<a href="">华为用户协议</a>|<a href="">华为技术支持</a>|<a href="">京东合作伙伴</a>
</td>
<td></td>
</tr>
</table>
</body>

五、CSS基础

对HTML的显示效果进行优化

5.1 style 属性

几乎所有的标签都可以添加一个style属性,在style属性中设置样式属性,来修改HTML标签的现实效果

在style属性值中可以添加多个样式属性

  • 标签属性:在HTML中添加的键值对
  • 样式属性:style属性值中的键值对

5.2 style标签

将多个标签的共有样式属性定义在style标签中

1
2
3
4
<style>
input{width:20px;height:30px}
img{height:30px;width:50px}
</style>

5.3 CSS层叠样式表

style标签中定义的可以供网页中HTML标签复用的属性表

层叠样式表:在style标签中定义的多个样式表可以叠加作用在同一个标签

5.3.1 基础语法
1
选择器{样式属性列表}
5.3.2 CSS选择器
  • id选择器#

    1
    #id{样式列表}
  • 标签选择器

    1
    标签名{样式列表}
  • class选择器

    1
    .class名{styleList}

5.4 CSS文件

  • 将多个HTML文件所需要的样式单独定义在css文件中
  • 通过link标签引用此样式文件即可
  • 在一个网页中可以引用多个css文件
1
<link rel="stylesheet" href="样式文件地址">

六、CSS常用样式设置

6.1 CSS盒子模型

基于HTML的嵌套关系,并列关系,用形象的盒子的嵌套和并列堆放关系来理解常见的css模型

6.2 尺寸样式

属性名 说明
width 设置宽度
height 设置高度

6.3 边框样式

可以设置整个边框,也可以上下左右边框单独设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
border-color:设置边框颜色 
色号:#******红绿蓝各两位
rgb(x,x,x)RGB函数
rgba(x,x,x,x)RGB和透明度

border-style:设置边框样式
solid:实线 dotted:点状虚线 dashed:段状虚线 double:双实线

border-width:设置边框宽度
单位是px,对于双边框宽度必须>=3px

!常用:
boder: 同时设置边框颜色、样式、宽度(顺序不变)


边框圆角及阴影

1
2
3
4
5
6
7
8
9
10
11
12
13
14
圆角:
border-radius:50px/20% 同时设置四个圆角
以50px边长正方形切边
以边框的20%边长切边

border-radius:0 50px; 第一个值表示左上角和右下角,第二表示左下右上

border-radius:x x x x : 四个值分别从左上角顺时针旋转

阴影:

box-shadow: red 0px 3px 4px; 分别表示阴影颜色,x轴偏移,y轴偏移,阴影渐变


6.4 背景样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
background-color:   背景颜色
background-image: url(imgs/.../.jpg) 设置背景图片,优先级高于背景颜色
background: url() 颜色; 同时设置背景图片和背景颜色

如果背景图片过大,可以对图片进行偏移设置:
background-position:-50px;同时设置图片在水平和垂直方向的偏移
background-position:x,y; 分别在x轴和y轴上的偏移

如果图片太小,可以设置图片的平铺方式:
background-repeat:no-repeat; 不进行平铺
background-repeat:repeat-x; 横向平铺
background-repeat:repeat-y;纵向平铺
background-repeat:repeat; 横向纵向都平铺

6.5 外边距样式

HTML标签与父容器边框的距离或与同级标签的边框距离

1
2
3
4
5
6
7
margin-left:100px;   左外边距
margin-top:100px; 上外边距
margin-right:
margin-bottom:
margin:x; 同时设置四个外边距
margin:x,y; 分别设置上下、左右
margin:x,y,z,t; 分别设置上、右、下、左;

6.6 内边距样式

  • width表示设置内容的宽度,内边距不会占据内容宽度
1
2
3
4
5
6
7
padding:x; 同时设置四个方向的内边距
padding:x,y; 设置上下和左右的内边距
padding:x,x,x,x; 分别设置上右下左边距
padding-left:
padding-right:
padding-bottom:
padding-top:

6.7 字体样式

1
2
3
4
5
6
7
8
9
10
11
font-size:字体大小
font-weight:字体粗细/bold设置字体加粗
color:颜色字号/颜色名称/RGB
font-family:设置字体家族(样式)
自定义字体样式:1.下载字体文件TTF、ttc/格式
2.创建字体目录,在目录中放进文件
3.根据字体文件自定义字体
@font-face{
font-family:自定义字体样式名;
src:url(字体文件地址)
}

6.8 文本样式

1
2
3
4
text-align:文本的水平对齐方式|right|left|center
text-decoration:underline | overline | line-through(删除线)
text-underline-color:
text-shadow:颜色 \ 偏移量

6.9 列表样式

1
2
3
list-style-type:列标签图标的样式 (none\)
list-style-position:列表图标的位置(outside/inside)
list-style-image:设置图标图片(url(图片地址))

6.10 分列显示(瀑布模型)

将一个容器下的多个数据分成多列显示

1
2
3
4
5
6
#container{
column-count:4;分成4列,先排列再排行
column-rule:blue 1px dashed;:; 分列显示后列与列之间的分割样式
column-gap:30px;每列的宽度,会占据宽度,如果超过容器宽度则减少列数
瀑布模型:每列的高度基本一致
}

6.11 超链接(伪类)

设置超链接在不同状态下的样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
text-decoration:none; 超链接样式
color:;设置超链接颜色
超链接的伪类:
a:link{
只设置超链接初始状态
color:;初始颜色
}
a:hover{
设置鼠标悬停的样式
color:blue;悬停的颜色
}
a:active{
被点击时的样式
}
a:visited{
超链接激活后的样式
}

6.12 CSS布局

DIV层是一个HTML的容器,课已将HTML标签放到容器中,通过css改变DIV的排列方式,即可实现对HTML元素的布局

  • 绝对布局
  • 相对布局
  • 浮动布局
6.12.1 绝对布局
  • 如果div标签直接写在body标签中,div的位置参考浏览器边框
  • 如果div写在一个div父容器中,设置绝对位置是div的位置不是参考div,而是参考浏览器
  • 如果父容器div增加一个position属性,里面的div就会参考父容器div
  • fixed属性设置在所有情况下以浏览器边框为参考设置绝对布局
1
2
3
position:absolute;
left:300px;
top:200px;
6.12.2 相对布局

相较于初始位置的偏移量

1
position:relative;
6.12.3 浮动布局

float

1
2
float:right|left;
clear:both;终止浮动布局

6.13 2D 与 3D

css3中提供了一些关于HTML标签的2D视图和3D视图的转换

1
2
3
4
5
6
7
8
9
10
11
display:inline;将块级元素转换为内联元素
用于对HTML标签进行2D和3D的转换,样式属性值为函数:
transform:translate(100px,10px);横向和纵向偏移量

transform:rotateZ(45deg);绕Z轴旋转
transform:rotateX(45deg);绕X轴旋转
transform:rotateY(45deg);绕Y轴旋转

transform:scale(0.5);按比例缩放

transform:skewX(30deg);从X轴拉伸

6.14 自定义动画

  • 过渡

    1
    transition:transform 5s ease|ease-in|ease-out|linear 2s;对transform样式5s过渡样式,延迟时间为2s
  • 动画

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    1.定义动画
    @keyframes name{
    from/0%{
    transform:rotate(0deg);
    }
    to/100%{
    transform:rotate(360deg);
    }
    }
    2.应用动画
    animation:name 完成动画的时间 动画效果(linear) 动画循环次数(整数或infinite)

七、用户界面设计

7.1 媒体查询

使用CSS设置网页根据不同的显示设备动态调整显示样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<style type="text/css">
*{
padding:0px;
magin:0px;
}
/* 当屏幕最小尺寸为1800px时显示如下样式 */
@media only screen and (min-width:1800px){
div{
width: 1800px;
height: 800px;
background: lightcyan;
border:1px solid #008B8B;
margin: 20px auto;
}
}
/* 当屏幕尺寸在1200px到1800px之间时使用该样式 */
@media only screen and (min-width:1200px) and (max-width:1800px){
div{
width: 1200px;
height: 800px;
background: lightyellow;
border:1px solid #008B8B;
margin: 20px auto;
}
}
/* 当屏幕尺寸在600-1200时使用该样式 */
@media only screen and (min-width:600px) and (max-width:1200px){
div{
width: 600px;
height: 800px;
background: lightpink;
border:1px solid #008B8B;
margin: 20px auto;
}
}
</style>

7.2 响应式布局

标签的尺寸随父容器的尺寸改变而改变

  • 使用浮动布局实现:float:left

  • 使用弹性盒

    • 父容器中的子标签不设置宽度、高度的具体值,只设置在父容器中占据的宽度、高度的比例
    1
    2
    3
    4
    5
    6
    7
    #div1{
    width:1500px;
    height:300px;
    display:flex;
    flex-direction:row;/* 设置弹性盒的主轴方向row(左-右) row-reverse(右-左) column(上-下) column-reverse(下-上) */
    }
    <div id="d1"></div>

八、JavaScript

8.1 JS介绍

8.1.1 JS简介

JS是一种基于对象的、事件驱动型的解释型的脚本语言

  • 基于对象:区别于面向对象,JS和Java语言一样通过对象调用方法(obj.fn())
  • 事件驱动:网页文档中的HTML标签事件触发JS代码执行
  • 解释型:边解释边执行(不会先对网页进行编译生成中间文件)
  • 脚本语言:JavaScript不会独立运行,依赖于网页文件(html)的存在

8.1.2 JS发展史

JS是一种嵌入在网页中的脚本语言,是网页通过浏览器加载并显示的,因此JS的执行是在浏览器中完成的,对于浏览器而言,它能够执行JS代码,在浏览器中内嵌了JS解释器(引擎)

  • 1995年由网景公司开发

===========

8.1.3 JS的作用

  • 动态改变html标签的属性
  • 动态改变html标签的样式
  • 对用户输入的数据进行合法性校验(格式检查)
  • 动态操作网页中的HTML标签
  • 实现页面数据的异步通信

不能

  • 不能操作用户的本地文件(安全)
  • 不能操作来自不同服务器的网页文档数据

8.2 第一个JS程序

8.2.1 JS程序写在哪里?
  • JS代码写作HTML文档的script标签中,script标签可以写在HTML文档的任何位置,通常声明在网页的最后。一个网页中可以有多个script标签
  • 写在单独的.js文件里面,在网页文件中通过script标签(必须为双标签)中的src属性引用js文件,用来引用的script标签不能在里面自定义JS代码
8.2.2 JS函数(方法)定义

将实现某个功能的JS代码定义在一个函数中

1
2
3
4
//1.函数的定义语法:
function <funcName> ([参数]){
//js代码
}
8.2.3 JS的函数的运行
  • 通过HTML文档中的事件触发
8.2.4 查看浏览器的控制台

f12—>console—>usermessage

8.3 JS基础语法

变量、数据类型

表达式、流程控制

8.3.1 变量和数据类型

JS是弱类型语言,变量以var进行变量的类型声明,一个变量可以被赋予不同类型的数据

1
2
3
4
5
6
7
8
9
10
var i = 5;
var s = "hello";
var b1 =true;
var arr = new Array(); arr[0]="aaa";
var arr1 = new Array("aaa","bbb");
var stu = {stuNum:"1001"};//新建学生对象并建立属性
stu.Stugender="man";//扩展对象属性
//undefined表示变量没有被赋值
//null用于清空变量的值

8.3.2 表达式

由变量和运算符组合成的代码

1
2
3
4
5
6
7
8
//算数运算符
+ - * / % ++ --
//赋值运算符
= += -+ *= /=
//字符串拼接
var s = i + j;i和j须是同一类型
//关系运算符
> < >= <= != == ===表示绝对等于(值和类型都相等)
8.3.3 逻辑运算符
1
&& || !
8.3.4 三目运算符
1
var i =条件?i:j;
8.3.5 流程控制
1
2
3
4
//if同Java语言
//switch:同Java
//for同Java
//while同Java

8.4 JS异常处理

1
2
3
4
5
6
7
8
9
try{
//可能出现异常的代码
} catch(e){
//出现异常后进入该块进行的代码
} finally{
//这里的代码总会执行
}

throw ;抛出语句,用于创建自定义错误

8.5 JS对象

8.5.1 创建JS对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1.直接通过{}创建对象
var obj = {属性名:"属性值",属性名:"属性值"...方法名:function([params]){方法实现}};
//通过对象.属性名可以调用对象属性
var s = obj.属性名;

//2.使用JS构造器创建对象
function Student(num,name){
this.stuNum=num;
this.stuGender=name;
this.method1 = function(){
//方法实现
}
}
var stu1 = new Student("1001","张三");

8.5.2 JS扩展属性

对对象的属性进行扩增

1
2
//如stu对象中没有stuAge属性,通过对象.新属性名="属性值"添加新属性,这样添加的新属性只有该对象具有
stu.stuAge = "男"

8.5.3 构造函数扩展属性

针对构造器方式创建JS对象,我们也可以扩展构造器的属性

1
2
//对Student对象进行属性扩展,通过输出对象看不到新添加的属性,但是可以通过对象调用新增属性
Student.prototype.StuGender="男";

8.6 JS内置对象

JS引擎预定义了一些对象构造器,通过这些构造器构造的对象就是内置对象

  • 常见内置构造器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    1.Array:数组
    2.String:字符串
    3.Date:日期
    4.Math:数学
    5.Number:对数值进行操作
    6.RegExp:正则表达式
    7.Boolean:布尔
    8.Object:通用对象
    9.Error:异常处理的错误对象
    10.Function:顶层对象,函数
    11.Events:事件对象
    • String对象:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      //1.创建String对象
      var str1 = "www.baidu.com";
      var str2 = new String("www.baidu.com");
      //2.属性
      var len = str1.length;//获取当前字符串的属性
      console.log(len);

      //3.构造器常用函数
      var c = str1.charAt(1);//获取str1中索引为1的字符
      var a = str1.indexOf("b");//获取第一次出现该字符(串)的位置
      var j = str2.lastIndexOf("w");//获取该字符最后出现的位置
      var arr = str1.split(".");//将str1依据"."进行分隔
      var s1 = str1.substring(4);//从该字符串索引为4的位置开始截取直到str1结束
      var s2 = str1.substring(4,7);//前闭后开截取字符串
      var s3 = str1.substr(4,5);//从第4个开始截取5个字符
      var s4 = str2.toUpperCase();//转换为大写
      var s5 = str2.toLowerCase();//转换为小写

      var str3 = "1550044023";
      var reg= "^1[3,5,7,8]\\d{9}$";//手机号的规则,正则表达式
      var b = str3.match(reg);//判断str3是否符合正则表达式reg,如果不匹配,返回值为null
      console.log(b);
    • RegExp对象:对字符串的格式进行规则的检查

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      var s1 = "13033003030";
      var reg = new RegExp("^1[3,5,7,8]\\d{9}$");//规定正则表达式
      var b =reg.test(s1);//测试s1是否符合正则表达式,返回值为布尔类型
      console.log(b);

      //正则表达式说明:
      1.特殊符号
      \d表示任意数字,相当于[0-9]
      \s表示空白字符
      \b单词边界
      \u????匹配unicode编码

      2.区间
      [0-9]表示从0-9的任意数字
      [13579]表示该集合中的任意一个数字
      [a-z]从a-z的任意一个小写字母
      [A-Z]从A-Z的任意一个大写字母
      [a-zA-Z]表示任意一个字母
      [0-9a-zA-Z]表示0-9任意数字和字母

      3.量词
      a+ 表示至少有一个a
      a* 表示0-n个a
      a? 表示01个a
      a[m] 表示m个a
      a{m,n} 表示m-n个a

    • math类:静态函数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      var e = Math.E;
      var pi = Math.PI;
      var random = Math.random()*10;//随机产生一个0-1的随机数
      var i = Math.round(random);//四舍五入得到一个整数
      var j = Math.floor(random);//只舍不入,获取比参数小的最大整数
      var k = Math.ceil(random);//只入不舍,获取不小于参数的最小整数
      var m = Math.abs(-5);//获取参数的绝对值
      var n = Math.sqrt(9);//获取参数的平方根
      var v = Math.sin(3.14);//sin函数
      console.log(pi);
    • Array对象:JS的数组中可以存放不同类型的数据

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      //创建数组
      var arr = new Array(5);
      arr[6]="hello";//会自动增加数组的长度
      var arr1 = new Array("你好","世界");
      //数组的操作
      arr[0]="hah";//添加元素
      var i = arr[0];//通过索引获取数组中的元素
      //遍历数组
      for(var i = 0; i<arr.length;i++){
      var v = arr[i];
      console.log(v);
      }
      //for in 获取的是数组元素的索引
      for(var i in arr2){
      var v = arr2[i];
      }
      console.log(arr2);
      //array中定义的函数

      var s1= arr.join("-");//把数组中的值用-拼接成一个字符串
      var arr3 = arr1.slice(2,4);//切片,前闭后开
      var arr4 = arr.reverse();//反转arr中的值
    • Date对象

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      //创建date对象
      var date = new Date();//表示系统的当前时间
      var year = date.getYear();//从当前日期中获取获取年份,相对于1900年的年份
      var month = date.getMonth();//获取月份,下标从0开始
      var d = date.getDay();

      //设置日期
      date.setDate();

      //构造一个时间字符串
      var timeStr = year+"年"+...;
    • function对象:全局对象

      在JS中,window作为顶层容器,在语法上可以通过window对象调用全局函数,例如window.eval();

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      通过全局对象可以访问JS中的所有全局函数,全局属性;
      //全局函数,通过functions调用全局函数,Functions没有对象名
      parseInt();//将字符串转换成整数数值
      parseFloat();//将字符串转换成浮点类型
      var url = "www.baidu.com/?wd=中国人民银行"
      var newUrl = encodeURI(url);//对网址的参数部分进行编码
      var url2 = decodeURIComponent(newUrl);//对编码后的网址进行解码
      var str1 = "my name is 张三";
      var str2 = escape(str1);//对字符进行编码
      var str3 = unescape(str2);//对编码后的字符进行解码
      //当一个字符串满足JS中对象的格式时,我们可以通过eval转换成对象格式
      var str4 = "{stuName:'1001',stuAge:'18'}";
      var stu = eval("("+str4+")");//注意需要用()括起

8.7 BOM

Browser Object Model,浏览器对象模型

JS编写在网页文档中,网页文档运行在浏览器窗口window中,document、 window这样的对象也称为JS的宿主对象

8.7.1 window对象

window对象是BOM容器中的顶层容器,表示打开的浏览器窗口

  • window对象属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //获取window对象
    console.log(window);

    //BOM对象属性
    var v = window.navigator;//获取浏览器对象
    var s = window.screen;//获取屏幕对象
    var m = window.location;//获取地址栏对象
    var n = window.history;//获取某一个对象的历史记录
    var d = window.document;//获取文档对象

    //浏览器窗口属性
    var name = window.name;//获取当前浏览器窗口的名字
    var status = window.status;//获取当前浏览器的状态栏
    var b = window.closed;//获取当前窗口是否关闭
    var w = window.innerWidth;//获取浏览器的内部宽度innerHeight
    var ow = window.outerWidth;//获取浏览器外部宽度

    //窗口对象属性
    var ws = window.self;//self就是当前窗口属性

    //parent
    var p = window.parent;//如果当前网页是现实在另一个网页的iframe中,表示获取当前窗口的上一级窗口
    var t = window.top;//获取当前窗口的顶层容器
  • window对象函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    //弹窗函数
    window.alert("attention!");//警告提示框,没有返回值。
    window.confirm("sure!");//消息确认框
    window.prompt("请输入你的生日","2022");//用户交互弹窗.提示信息和默认值

    //打开和关闭窗口的函数
    window.close();//关闭窗口
    //打开新窗口
    //URL:新打开窗口显示的网址,返回值表示打开的窗口对象
    //name:新打开窗口的名字
    //features:新打开窗口的属性,需要先定义features:var features="width:400,height:300,location:none;";
    //replace:是否替换当前窗口,默认值为false,设置为true表示打开的新窗口会替换当前窗口
    window.open();//参数(URL,name,features,replace)


    //窗口操作函数:对浏览器窗口进行尺寸设置,位置设置,滚动条操作等的函数
    var w = window.open("www.baidu.com","百度","width=400,height=300");//新建一个窗口

    //1.修改窗口尺寸
    w.resizeTo(800,600);//设置新的窗口的尺寸为800x600;
    w.resizeBy(800,600);//表示在原有的基础上窗口的宽度和高度的变化值

    //2.改变窗口的位置
    w.moveTo(100,200);// 将窗口移动到横向、纵向的相应位置
    w.moveBy(100,100);//在窗口原来位置的基础上相对移动的距离

    //3.滚动条
    w.scrollTo(100,200);//滚动条默认的位置
    w.scrollBy(100,100);//相对变化

    //4.延时和循环任务
    var task1;
    task1 = window.setTimeout("test1()",3000);//参数1:延迟调用的函数,参数2:延迟时间
    window.clearTimeout(task1);//清除未执行的延时任务

    var task2 = window.setInterval("test1()",10000);//参数1,循环执行的函数,参数2:循环间隔时间
    window.clearInterval(task2);//关闭正在进行的循环任务

8.7.2 screen对象

表示网页显示的硬件设备的屏幕

只读对象,包含了硬件屏幕的相关参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//获取屏幕的宽度和高度
var w = screen.width;
var h = screen.height;
//alert(w+"*"+h);

//获取屏幕可用的尺寸
var aw = screen.availWidth;
var ah = screen.availHeight;
//alert(aw+"*"+ah);

//获取屏幕1英寸的物理像素点
var xdpi = screen.deviceXDPI;
var ydpi = screen.deviceYDPI;
// alert(xdpi);

8.7.3 navigator对象

包含有关浏览器的属性信息

1
2
3
4
5
6
7
8
9
10
11
12
//返回浏览器的名称(Netscape)
var name = navigator.appName;
console.log(name);
//返回浏览器的代码名
var code = navigator.appCodeName;
//返回浏览器的版本信息
var version = navigator.appVersion;
//返回浏览器的语言环境
var lan = navigator.browserLanguage;
//查看浏览器cookie是否可用
var b = navigator.cookieEnabled;
console.log(b);

8.7.4 location对象

表示当前浏览器窗口的地址信息,可以获取和设置地址栏信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//获取地址栏完整的网址
var s1 = location.href;
console.log(s1);
//获取地址栏网址的协议
var s2 = location.protocol;
console.log(s2);
//获取网页端口
var s3 = location.port;
//获取主机名称
var s4 = location.hostname;
//获取路径
var s5 = location.pathname;
//修改地址栏完整的网址
location.href = "www.baidu.com";//可以实现网页的跳转
//刷新网页
location.reload();
//使用该链接替换当前网址
location.replace("http://www.baidu.com");

8.7.5 history对象

1
2
3
4
5
6
7
8
//返回到当前页面的上一页
history.back();
//到下一场页面
history.forward();
//回退到指定位置
history.go(-1);
//返回历史记录中网址的个数
var len = history.length;

8.8 DOM

Document Object Model,文档对象模型

对于一个网页文件来说,文档的结构可以用树模型来建立

所有的标签都可以理解为树的结点

8.8.1 document对象属性

document对象指代的就是一个网页文档,document对象提供属性、函数大多是获取网页文档中的元素

1.集合属性
1
2
3
4
5
//集合属性
var arr = document.all;//获取当前网页文档中的所有属性
var arr2 = document.images;//获取当前网页中所有的img标签
var arr3 = document.links;//获取当前网页中的所有链接
var arrr4 = document.forms;//获取所有的forms标签
2.其他属性
1
2
3
4
5
6
7
//其他属性
var body = document.body;//获取当前文档中的Body标签
var title = document.title;//获取当前网页文档的标题内容
title = "设置当前文档的标题";
var url = document.URL;//获取当前网页文档的url
var cookie = document.cookie;//获取cookie中缓存的内容
document.cookie = "key=cookie";//向cookie中添加数据!注意是添加!
8.8.2 document方法
1.流操作函数
1
2
3
4
var cs = document.write("从前有座山");//打开一个输出流,并通过输出流将数据显示到网页中(会覆盖原网页内容)
document.close();//如果这个流不关闭,则输出的内容会追加到网页中
var sc = document.write("这是第二次写入的内容");//因为上个语句已经关闭上一个流,此次写入会覆盖原有内容
document.open();//打开一个新的输出流,不论上个输出流是否关闭
2.获取网页元素的函数
1
2
3
4
5
//获取元素函数
document.getElementById("img2");//根据标签的ID属性获取元素
document.getElementsByName("name");//根据NAME属性获取元素
document.getElementsByClassName("classname");//根据class属性获取元素
document.getElementsByTagName("img");//根据标签名获取元素
3.对HTML标签的操作
  • 属性操作

    1
    2
    3
    4
    var img = document.getElementById("img1");
    //标签属性操作
    var s = img.src;//获取图片的属性
    img.src="imgs/qqimg.jpg";//设置属性值
  • 样式操作

    1
    2
    3
    4
    img.style.height="300";//设置样式属性,JS中操作要使用驼峰命名
    var s1 = img.style.height;//获取样式属性
    img.style.borderRadius="50px";//设置圆角,注意要驼峰命名borderRadius
    img.className="imgStyle";//设置标签对象的class属性

8.8.3 案例:表单数据校验

在网页中通过JS完成数据的合法性校验

校验规则:

  • 账号:不能为空,长度8-20之间,只能包含数字和字母
  • 密码:不能为空,长度8-16
  • 确认密码:与密码一致
  • 手机号:不能为空,满足手机号码格式
  • 邮箱:不为空,满足邮箱格式

案例实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//js代码
function doValidate(){
// console.log("dovalidate")
//1.校验账号
var userName = document.getElementById("userName").value;//获取账号输入框的值
var label1 = document.getElementById("userNameLable");
//判断不为空
if(userName==null || userName==""){
//通过innerHTM修改标签对象里面的值
label1.innerHTML="用户名不能为空!";
label1.style.color="red";
return false;
} else if(userName.length<8 || userName.length>20){
label1.innerHTML="用户名长度不符,请输入8-20位字符";
label1.style.color="red";
return false;
} else if(!new RegExp("^[0-9a-zA-Z]*$").test(userName)){
label1.innerHTML="用户名只能包含数字和字母";
label1.style.color="red";
return false;
} else {
label1.innerHTML="Bingo!";
label1.style.color="red";
}

//2.校验密码
var passwd = document.getElementById("passwd").value;
var label2 = document.getElementById("passLabel");
if(passwd==null || passwd==""){
label2.innerHTML="密码不能为空哦亲";
label2.style.color="red";
return false;
} else if(passwd.length<8 || passwd.length>16){
label2.innerHTML="密码长度应该在8-16哦";
label2.style.color="red";
return false;
} else {
label2.innerHTML="密码格式正确啦";
label2.style.color="green";
}
//3.校验确认密码
var repasswd = document.getElementById("repasswd").value;
var label3 = document.getElementById("repassLabel");
if(repasswd==null || repasswd=="" || repasswd!=passwd){
label3.innerHTML="两次输入密码不同哦亲,这样子是不可以滴";
label3.style.color="red";
return false;
} else {
label3.innerHTML="密码合法!";
label3.style.color="green";
}

//4.校验手机号
var phone= document.getElementById("phoneNum").value;
var label4 = document.getElementById("pheneLabel");
if(phone.length !=11 || !new RegExp("/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/").test(phone)){
label4.innerHTML="你TNN的连个手机号都输不对?";
label4.style.color="red";
return false;
}

//5.邮箱验证
var mail = document.getElementById("main").value;
var label5 = document.getElementById("mailLabel");
if(mail == null || mail=="" || !new RegExp("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$").test(maim)){
label5.innerHTML="连个邮箱都不会输吗!";
label5.style.color="red";
return false;
}
console.log(userName);
return false;
}

8.8.4 节点操作

网页中的元素、元素属性、文本都是节点

节点操作:使用JS完成节点创建,节点插入,修改节点,删除节点等

1.节点属性
1
2
3
4
5
6
7
//标签节点
nodeType:1 nodeName:标签名 nodeValue: null
//属性节点
nodeType:2 nodeName:属性名 nodeValue:属性值
//文本节点
nodeType:3 nodeName:#text nodeValueL:文本内容

对于HTML元素对象:

1
2
3
4
//获取标签属性
var arr1 = tag.attributes
//获取标签的子标签
var arr2 = tag.childNode;
2.创建新节点
1
2
3
4
5
6
7
8
//创建一个标签节点
document.createElement("img");
//获取标签名
img.outerHTML;
//创建文本节点
var textNode=document.createTextNode("hello");
//创建属性节点
var attrNode = document.createAtribute("name");
3.插入结点

将创建的新节点载入到网页文档中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var imgTag = document.createElement("img");//新建一个标签节点
var srcAttr = document.createAttribute("src");//新建一个属性节点
srcAtt.nodeValue="imgs/img1.png";//给属性节点赋值
imgTag.setAttributeNode(srcAttr);//把创建的属性节点添加到标签节点中

imgTag.setAttribute("src","imgs/img1.png");//给标签节点添加属性并设置属性值
imgTag.alt="图片";//设置属性
imgTag.removeAttribute("alt");//移除属性

//拼接子节点
var body = document.body;
body.appendChild(imgTag);//将新建的img标签拼接到Body标签(拼接子节点)
//插入结点
body.insertBefore(imgTag,bodyTag);//表示插入子节点到什么标签之前
4.修改节点
1
2
3
4
5
6
7
8
//节点修改
var img2 = document.createElement("img");
img2.src="imgs/img02.jpg";
var div1 = document.getElementById("div1");
var p1 = document.getElementById("p1");
div1.replaceChild(img2,p1);//替换子节点(用img2替换p1)
p1.replaceWith(img2);//用img2替换p1(部分浏览器不支持)
p1.replaceChild(img2);//如果使用网页中已存在的标签替换,该标签的位置会发生变化
5.删除节点
1
2
img2.remove();//删除当前节点
div1.removeChild(p1);//移除子节点

8.9 JS事件

JS事件,指的是网页文档中发生的行为。这个行为可以是网页文档加载过程产生的,也可以是用户人为操作的

8.9.1JS事件绑定

JS函数是通过网页事件驱动的,驱动的方式有标签内联绑定和外联绑定

  • 内联绑定:

    在标签上添加事件属性,绑定对应的JS函数

    1
    2
    3
    4
    <button onclick="test1()">测试按钮</button>
    function test1(){
    console.log("test1");
    }
  • 外联绑定:

    不在HTML标签上添加事件属性,而是通过JS获取HTML元素,调用事件函数绑定

    1
    2
    3
    4
    <button id="btn2">测试按钮2</button>
    document.getElementById("btn2").onclick=function(){
    console.log("test2");
    };
8.9.2 HTML常用事件
  • 鼠标事件:鼠标的点击、移动、悬浮触发的事件
  • 键盘事件、window事件、表单事件
  • 鼠标事件:

    用户的鼠标在HTML标签上产生点击、双击、移动、悬浮等事件

    1
    2
    3
    4
    5
    6
    7
    onmouseover="test()";//鼠标移动到目标时触发事件
    ondbclick="test1()";//鼠标双击触发事件
    onclick="test2()";//鼠标点击触发事件
    onmouseout="test4()";//鼠标移开时触发事件
    onmousemove="test5()";//鼠标在该目标上移动时触发事件
    onmousedown="test6()";//鼠标左键按下时触发事件
    onmouseup="test7()";//鼠标左键松开时触发事件
  • 键盘事件:

    针对于表单中的输入标签

    1
    2
    3
    onkeydown="test8()";//键盘按下时触发事件,如果按下去不放,则一直触发
    onkeyup="test9()";//键盘松开时触发事件
    onkeypress="teest10()";//键盘按下时触发事件,只支持字符键盘键入
  • window事件:

    window对象触发的事件,win对象并不是一个HTML标签,window对象的事务通常使用JS脚本绑定

    如果在head标签中通过JS绑定标签事件,要把函数window.onload中

    1
    2
    3
    4
    window.onload=function(){};//当网页中body标签内容加载完毕触发事件
    window.onunload=function(){};//当网页解体时触发事件,主要用于回收资源
    window.onscroll=function(){};//当网页滚动时触发事件
    window.onresize=function(){};//当改变窗口尺寸时触发事件
  • 表单事件:

    键盘事件通常是绑定在输入标签上的,但表单输入标签支持的事件不止键盘事件

    1
    2
    3
    4
    5
    6
    inputTag.onfocus=function(){};//获得焦点时触发事件
    inputTag.onblur=function(){};//失去焦点时触发事件
    inputTag.onchange=function(){};//当输入框内的值发生变化时触发事件
    inputTag.onselect=function(){};//当输入框中的内容被选中时触发事件
    document.forms[0].onsubmit=function(){};//当该表单被提交时触发事件
    document.forms[0].onreset=function(){};//当该表单被重置时触发事件
8.9.3 事件对象

JS将标签触发的动作抽象为事件

一个EVENT对象表示HTML标签与发生的动作的组合

1
2
3
window.event;//表示获取当前时间对象
window.event.srcElemen;//获取当前事件的标签
window.event.type;//获取事件的类型
8.9.4 阻止事件冒泡

事件冒泡:在子标签发生的事件触发了当前标签父标签绑定的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function(event){
event.cancelBubble = true;
or:
event.stopPropagation();
}
//多标签阻止冒泡:
var arr = div.childNodes;
for(var i = 0; i < arr.length; i++){
if(arr[i].nodeType==1){
arr[i].onclick=function(event){
event.cancelBubble = true;
}
}
}

8.10 JS综合案例:锅打灰太狼

源码见Hbuider;

2022.10.28完结

九、Servlet

9.1 web服务器

9.1.1 web服务器概述

web服务器就是web项目的容器,我们将开发好的web项目部署到web容器

  • 接受网络请求
  • 查找资源
  • 响应网络请求
9.1.2 静态资源和动态资源

web项目中的资源根据特性可以分为静态资源和动态资源两类

  • 静态资源:网页中的数据始终保持不变
  • 动态资源:网页中的数据是根据用户的请求意图动态生成的
9.1.3 常见的web服务器产品
  • Tomcat: Apache开源,主流的服务器之一,多应用与web项目开发
  • Jetty: 运行效率高
  • Web Logic: Oracle产品,收费
  • WebSpere
  • Nginx: web静态资源服务器
9.1.4 Tomcat

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

目录结构:
  • bin:存放可执行的二进制文件(sh,exe) startup.bat用于启动tomcat shutdown.bat用于启动tomcat
  • conf: 存放Tomcat的配置文件(server.xml可以配置Tomcat的端口)
  • lib: 存放服务器编译执行java代码的基础库
  • log:日志文件
  • temp:临时目录
  • webapps:存放项目目录,默认部署了几个项目
  • work:缓存动态生成的页面
启动和关闭
9.1.5 web项目部署

方式一:直接将web项目拷贝到Tomcat的webapps目录

方式二:将web项目的路径配置到tomcat

  • ​ 在conf目录>Catlina\localhost创建一个xml文件
  • xml配置:
9.1.6 浏览器访问web服务器

http://localhost:8080/demo1

9.1.7 Tomcat服务器请求响应流程
9.1.8 Tomcat端口配置

通过修改conf/server/xml配置文件修改端口

9.2 HTTP协议

浏览器与服务器之间的网络通信遵循HTTP协议

9.2.1 HTTP简介

网络中的通信协议:

TCP协议:基于连接的安全传输协议(客户端和服务器先建立连接,再通过连接发送出去)

UDP:基于广播分发的非安全传输协议(不会建立网络连接)

HTTP协议是基于TCP协议的基础之上,基于请求与响应模式,无状态的应用层协议

9.2.2 HTTP协议特点

  • 基于连接通信:当浏览器和服务器进行通信时,会首先建立网络连接,通过网络连接进行通信
    • 短连接:在HTTP协议1.0中,浏览器向服务器发送请求,建立连接,但是这个连接只作用于浏览器和服务器的一次请求响应,响应结束后断开连接
    • 长连接:浏览器与服务器建立连接之后等待几秒钟,在这几秒钟之内如果浏览器有新的请求,则直接使用该连接进行请求和数据响应,几秒钟之后断开
  • 请求与响应模式:由浏览器向服务器发送请求,服务器再对请求进行响应
  • 无状态:服务器不会感知同一个客户端的多次请求

9.2.3 HTTP协议通信规则

通信协议:客户端与服务器之间共同遵守的规则

1.通过自定义的HTTP服务器,接受浏览器请求并查看请求规则

  • 自定义服务器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package com.http.request;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;

    public class MyHttpServer {

    public static void main(String[] args) throws IOException {
    //创建一个网络服务,通过浏览器请求服务
    ServerSocket serverSocket = new ServerSocket(9999);
    //当浏览器请求这个服务器之后建立网络连接(socket对象)
    Socket socket = serverSocket.accept();
    //通过socket对象的输入流可以读取浏览器发送的HTTP请求
    InputStream inputStream = socket.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    //读取
    String content = null;
    while((content = reader.readLine()) != null){
    System.out.println(content);
    }
    //暂时未对浏览器请求进行响应
    }
    }

2.HTTP响应规则:

  • 自定义“浏览器”查看响应规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.http.response;

import java.io.*;
import java.net.Socket;

public class MyBrowser {

public static void main(String[] args) throws IOException {
//将上一个request中浏览器发送给Myserver的请求内容发送给百度


//向百度服务器发送链接请求
Socket socket = new Socket("www.baidu.com", 80);
//System.out.println(socket);
//通过连接中的输出流将HTTP请求内容发送给百度
OutputStream outputStream = socket.getOutputStream();
PrintWriter out = new PrintWriter(outputStream);
out.println("GET / HTTP/1.1");
out.println("Host: www.baidu.com:80");
out.println("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0");
out.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
out.println("Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
out.println("Accept-Encoding: gzip, deflate, br");
out.println("Connection: keep-alive");
out.println("Upgrade-Insecure-Requests: 1");
out.println("Sec-Fetch-Dest: document");
out.println("Sec-Fetch-Mode: navigate");
out.println("Sec-Fetch-Site: none");
out.println("Sec-Fetch-User: ?1");
out.println();
out.flush();

//通过输入流接受百度的响应数据
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String response = null;
while((response=reader.readLine())!=null){
System.out.println(response);
}
}
}

9.3 Servlet基础使用

9.3.1 Servlet简介

servlet是服务器端的Java程序,是能够接受HTTP请求,处理HTTP请求,并对HTTP请求进行响应的动态网页技术

Servlet是javaEE规范的一个重要组成部分

作用:

  • 接受浏览器的HTTP请求
  • 根据用户请求进行数据处理
  • 动态生成网页
  • 将生成的包含动态数据的网页响应给客户端
9.3.2 创建Java web工程
  • Java工程:只引入了JDK的标准库(JavaSE)
  • Javaweb工程:引入了Java企业级开发环境(JavaEE)
9.3.3 Servlet创建

Servlet是一个Java程序,是一个能够接受HTTP请求的Java类,因此需要去实现HTTP协议

在导入的javaee库中有HttpServlet实现了HTTP协议,我们创建的类只需要继承此类

1.创建一个类继承HttpServlet

2.继承HttpServlet的类就能够接受HTTP请求,一般类名后面加Servlet,如BookListServlet

3.在我们创建的类中重写doGet和doPost方法,用于处理用户不同的请求

9.3.4 Servlet配置URL

Servlet创建完成之后需要配置URL访问路径,然后将web项目运行在Tomcat之上,就能够通过配置的url访问Servlet类

支持两种配置方式:

  • 基于web.xml配置文件进行配置
  • 基于注解配置
1.基于web.xml配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!--配置BookListServlet类的访问路径-->
<!-- servlet标签:配置类路径-->
<servlet>
<!-- name用来匹配servlet和mapping-->
<!-- 只要用户请求book-list就能进入bookListServlet-->
<servlet-name>bookListServlet</servlet-name>
<!--servlet-class:servlet类路径-->
<servlet-class>com.example.demo.BookListServlet</servlet-class>
</servlet>
<!-- servlet-mapping标签:配置访问的URL-->

<servlet-mapping>
<servlet-name>bookListServlet</servlet-name>
<url-pattern>/book-list</url-pattern>
</servlet-mapping>

<!-- 配置BookQueryServlet类的访问路径-->
<servlet>
<servlet-name>bookQueryServlet</servlet-name>
<servlet-class>com.example.demo.BookQueryServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>bookQueryServlet</servlet-name>
<url-pattern>/book-query</url-pattern>
</servlet-mapping>
2.直接在servlet类中配置
1
2
//配置bookqueryservlet类
@WebServlet("/book-query")
9.3.5 IDEA部署web项目
9.3.8 Servlet 响应动态数据

案例:根据客户端请求的BookID动态查询图书数据响应给客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.example.demo3;

import com.example.demo3.dto.Book;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@WebServlet("/book-query")
public class BookqueryServlet extends HelloServlet {

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("querypost");
}

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("queryget");

//动态生成HTML

//1.接受到浏览器请求时发送的参数
String bid = request.getParameter("bookId");
// System.out.println(bid);
//2.根据参数查询数据库图书表(伪代码)
Map<String, Book> bookMap = new HashMap<>();
bookMap.put("1001",new Book("1001","java","tom",11.11,"img/img01"));
bookMap.put("1002",new Book("1002","c++","mike",22.22,"img/img02"));
bookMap.put("1003",new Book("1003","python","john",33.33,"img/img03"));

Book book = bookMap.get(bid);
//3.将查询到的结果生成网页

//设置响应头
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
//该writer对象就是用于用于响应浏览器的输出流,通过这个输出流写出什么数据,浏览器就可以接收到什么收据
PrintWriter writer = response.getWriter();
//动态网页
writer.print("<DCOTYPE html>");
writer.print("<html>");
writer.print("<head>");
writer.print("<meta charset='utf-8'>");
writer.print("<title>");
writer.print("图书信息查询");
writer.print("</title>");
writer.print("</head>");
writer.print("<body>");
writer.print("<table style='border:1px deepskyblue solid;width:1000px;' align='center'border='1' cellspacing='0' >");
writer.print("<tr><th>图书编号</th><th>图书名称</th><th>图书作者</th><th>图书价格</th><th>封面</th></tr>");
writer.print("<tr>");
writer.print("<td>" + book.getBookId() + "</td>");
writer.print("<td>" + book.getBookName() + "</td>");
writer.print("<td>" + book.getBookAuthor() + "</td>");
writer.print("<td>" + book.getBookPrice() + "</td>");
writer.print("<td>" + book.getBookImgPath() + "</td>");
writer.print("</tr>");
writer.print("</table>");
writer.print("</body>");
writer.print("</html>");
writer.flush();
writer.close();

}
}

9.4 Servlet原理解析

9.4.1 ServletAPI核心类与接口

9.4.2 servlet类处理用户请求的流程

9.4.3 servlet实例的生命周期

当客户端的请求到达tomcat,tomcat会创建一个线程来写接受、处理、响应客户端请求,客户端在请求某个servlet类是,线程需要通过着这个servlet类的实例来调用service方法,调用方法来处理和响应请求

生命周期值得是一个servlet类的实例从创建到销毁的过程

  • servlet实例是单实例多线程
    • 一个servlet类自始至终只会创建一个对象
    • 当用户第一次请求servlet时创建一个实例
    • 使用这个实例依次调用后续方法来处理用户请求
    • 当客户端请求再次到达时,将不会重新创建实例,直接使用第一次创建的实例
    • 当在web.xml中配置了<load-on-startup></load-on-startup>时,服务器启动时就创建实例,后面的操作都使用这个实例
  • 停止服务器时执行destroy方法,此时该实例被释放
  • 配置load-on-startup的两种方式
    • 在web.xml中配置<load-on-startup>序号</load-on-startup>,序号代表创建实例的顺序
    • 注解配置@WebServlet(loadOnStartup = 1)
9.4.4 线程安全问题

当多个客户端并发访问时,tomcat会创建多个线程,而多个线程使用同一个servlet实例可能会导致线程安全问题

解决方案:

  • 实现SingleThreadModel接口,让每个线程都创建servlet实例,避免了多线程使用同一个servlet实例的情况
    • 这种方式会导致对客户端的请求响应效率降低,增加了服务器因频繁创建和销毁实例的负载
    • 此种方式不建议使用,已经过时
  • 使用synchronize同步锁
    • synchronize(this){业务代码}
  • 在servlet实例中尽量不使用全局(成员)变量,让每个线程有自己的局部变量

9.5 Servlet开发技术

  • servlet如何接受客户端请求
  • servlet如何对请求进行响应

9.5.1 HttpServletRequest对象

servlet类中的方法通过request对象接受客户端的请求信息

客户端向服务器发送的请求信息都会被封装到request对象

1.接收请求行数据
1
2
3
4
5
6
7
8
//获取客户端的请求方式
String mathod = request.getMethod();
//获取请求url,只能得到url,不包含参数
String url = request.getRequestURL().toString();
//获取请求参数,根据key获取value
String key1 = request.getParameter("key1");
//获取请求协议
String protocol = request.getProtocol();
2.获取请求头数据
1
2
3
4
5
6
7
8
9
//获取请求头中的key 
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()){
//获取请求头类型
String key = headerNames.nextElement();
//获取请求头参数
String head = request.getHeader(key);
System.out.println(key + ":" + head);
}
3.获取请求正文
1
2
3
4
5
ServletInputStream inputStream = req.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
//读取请求正文
String s = bufferedReader.readLine();
System.out.println(s);

案例:request对象接受表单数据

图书添加操作:需要从图书添加页面提交数据

  • java代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.example.demo5;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

@WebServlet(name = "bookAdd", value="/bookAdd")
public class BookAddServlet extends HttpServlet {

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求正文
// ServletInputStream inputStream = req.getInputStream();
// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
// String s = bufferedReader.readLine();
// System.out.println(s);
//2.form表单Post方式提交的数据也可已通过reque对象的getparameter获取
//使用parameter之前不能打开输入流
String bookId = req.getParameter("bookId");
int book_id = Integer.parseInt(bookId);
String bookName = req.getParameter("bookName");
String bookAuthor = req.getParameter("bookAuthor");
String bookPrice = req.getParameter("bookPrice");
double book_price = Double.parseDouble(bookPrice);
System.out.println("book_id=" + book_id );
System.out.println("book_name=" + bookName);
System.out.println("book_author=" + bookAuthor );
System.out.println("book_price=" + book_price );
}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String bookId = req.getParameter("bookId");
int book_id = Integer.parseInt(bookId);
String bookName = req.getParameter("bookName");
String bookAuthor = req.getParameter("bookAuthor");
String bookPrice = req.getParameter("bookPrice");
double book_price = Double.parseDouble(bookPrice);
System.out.println("book_id=" + book_id );
System.out.println("book_name=" + bookName );
System.out.println("book_author=" + bookAuthor );
System.out.println("book_price=" + book_price );

}
}
  • HTML代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加图书</title>
</head>
<body>
<form action="http://localhost:8080/demo5/bookAdd" method="get">
<p>图书编号:<input type="text" name = "bookId"/></p>
<p>图书名称:<input type="text" name = "bookName"/></p>
<p>图书作者:<input type="text" name = "bookAuthor"/></p>
<p>图书价格:<input type="text" name = "bookPrice"/></p>
<input type="submit" value = "提交">
</form>
<form action="http://localhost:8080/demo5/bookAdd" method="post">
<p>图书编号:<input type="text" name = "bookId"/></p>
<p>图书名称:<input type="text" name = "bookName"/></p>
<p>图书作者:<input type="text" name = "bookAuthor"/></p>
<p>图书价格:<input type="text" name = "bookPrice"/></p>
<input type="submit" value = "提交">
</form>

</body>
</html>
  • 如果出现中文乱码问题
1
2
3
4
5
6
7
8
9
10
11
#为什么会出现乱码问题
*提交的数据数据会被编码压缩
*如果服务器和网页的编码方式不同将导致乱码问题
#get方法:
*get方法提交的请求参数是通过服务器处理的
*出现乱码:在Tomcat的conf/server/xml中配置
<Content> ... URLEncoding="utf-8"/>
#POST方式:
*请求正文会编码
*解决:在servlet类中接受数据之前通过request对象设置http请求数据的编码方式
request.setCharacterEncoding("utf-8");

9.5.2 HttpServletResponse对象

Servlet中的方法都有一个response对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//设置状态码
response.setStatus(200);
//设置响应头
response.setContentType();
...
//设置响应数据的编码
response.setCharacterEncoding("utf-8");
//设置响应正文
ServlertOutputStream out = response.getOutputStream();//获取字节流,响应文件数据给客户端
PrinterWriter writer = response.getWriter();//获取字符流,可以响应文本数据给客户端
//通过流输出的数据就会以响应正文的形式传输给客户端浏览器
writer.println("<html/>");//写出
writer.flush();
writer.close();

9.5.3 servlet动态案例:学生成绩查询

学生信息管理系统:

功能:学生登录 学生查询成绩

项目源码见demo6(IDEA)

1.项目分析:

2.项目环境搭建
  • 数据库环境准备

  • 创建一个java web工程

  • 搭建JDBC环境

    • 导入jdbc所需的驱动jar、 导入数据库连接池jar 、导入DBUtils jar
      • 在web-info中创建目录lib,拷贝jar包并添加为library
    • 配置连接池信息
      • 创建druid.properties配置连接池信息
      • 创建连接池的工具类

3.完成数据库操作

根据项目流程,完成需要的数据库操作

  • 学生登录实现:
    • 根据输入的学号和密码查询学生信息,如果查询到了说明学号和密码输入正确,登陆成功
    • 根据输入的学号查询学生,再比较输入的密码和查询到的密码是否一致,如果一致则登录成功
  • 查询成绩:
    • 根据学生的学号和课程号从成绩表中查询成绩

根据学号和密码查询学生

  • 创建学生实体类
  • 创建数据库学生查询类

根据学号、课程号查询成绩

  • 创建成绩实体类
  • 创建数据库成绩查询类
4.实现LoginPageServlet

为用户提供一个登录页面

要求:

  • form表单数据提交到check页面
  • 采用post方法
5.实现CheckServlet

检查学生登录信息

要求:

  • 接受学号和密码并查询数据库判断
6.业务与视图分离

上面步骤存在的问题:

  • 如果登录失败需要响应登录页面,登录页面已经存在,但是在check中又写了一遍(冗余)
  • check中业务代码和视图代码混合,不满足单一原则的编程规范

业务与视图分离表示:

  • checkServlet只负责学生登录校验的业务处理
  • 如果登录成功, 创建单独的页面来响应
  • 如果登陆失败,重复使用login页面响应
7.实现IndexPageServlet主页面

显示成绩查询的主页面,并且能够输入学号和课程号

8.从check页面跳转到其他页面

转发或重定向

  • 登录成功重定向到IndexPageServlet
  • 登录失败转发到LoginPageServlet
9.实现GradeQueryServlet

接受客户端的学号和课程号查询成绩

转发到GradePageServlet

10.实现GradePageServlet显示成绩

接收查询到的成绩

显示成绩

9.5.4 转发和重定向

当客户端请求到了某个Servlet类之后,servlet类进行处理,但并不使用这个servlet来响应客户端,而是调用其他servlet来响应

转发的特点:

  • 转发是在服务器端两个servlet之间的请求行为
  • 转发过程中浏览器只对服务器进行一次请求
  • 浏览器的地址不会改变
  • 转发过程中可以进行数据传递(request.setAttribute)

转发的代码实现:

1
2
//servletA中:
request.getRequestDispacher("servletB的URL").forward(request,response);

转发的数据传递:

1
2
3
4
5
6
//servletA中:value值是object对象
request.setAttribute("key","value");
request.setAttribute("stu",new Student(id,name,age));
//servletB中:
request.getAttribute("key");
Student student = request.getAttribute("stu");

重定向的特点:

  • 重定向是浏览器的行为

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

  • 浏览器地址栏会发生变化

  • 不能通过request对象将servletA中的数据传递给servletB

  • 如果servletA重定向到servletB的时候有数据要传递给servletB

    1
    //进行url传值

重定向的代码实现:

1
2
//ServletA中:
response.sendRedirect("servletB的访问URL");

重定向的数据传递:

1
2
3
4
//A中:
response.sendRedirect("servletB?key=value");
//B中:
request.getParameter("key");

9.5.5 状态管理实现

将浏览器和服务器之间的多次交互作为一个整体处理,通过服务器数据存储和浏览器数据存储结合实现状态管理

服务器状态管理:session技术

客户端状态管理:cookie技术

1.现有问题:
  • HTTP请求无状态,不能保存用户的访问和登录记录
  • 客户端发送一个新的请求到达服务器,服务器无法知道此客户端是否曾经有过请求,两次请求之间没有关系
  • 如果用户在访问系统的主页面时,需要访问之前请求的数据如何实现呢?
2.状态管理示意图

9.5.6 Cookie的使用

1.Cookie介绍
  • Cookie是浏览器访问web服务器上的某个资源时由web服务器在响应浏览器时通过响应头附带的传送给浏览器并存储在浏览器的一小段数据
  • 浏览器访问服务器的时候只会携带由当前服务器存储在客户端的Cookie
  • Cookie中缓存的数据以键值对形式存储,可以存储多个键值对
2.Cookie的使用
  • 创建一个新的工程
  • 创建两个servlet
  • 写cookie
1
2
3
4
5
6
7
//向浏览器存储一个cookie
//1.创建cookie
Cookie cookie = new Cookie("key1", "value1");
//设置cookie的生命周期
cookie.setMaxAge(24*60*60);//单位是秒,如果参数为0表示浏览器关闭即销毁cookie,参数=-1时表示内存存储
//2.把cookie写到客户端
response.addCookie(cookie);
  • 读cookie
1
2
3
4
5
6
7
8
Cookie[] cookies = request.getCookies();
for(Cookie cookie : cookies){
if("key1".equals(cookie.getName())){
String value = cookie.getValue();
System.out.println(value);

}
}
3.cookie的优点和局限性

优点:

  • 可以灵活配置过期规则
  • 简洁,存储的是最简单的键值对数据
  • 可以支持数据的持久性

局限性:

  • cookie存储数据的大小一般是4k或8k
  • 用户可以通过浏览器设置禁用cookie,因此限制了cookie的使用场景
  • cookie是存储在客户端浏览器中的,有被篡改的风险
  • 如果一定要使用cookie,可以检查浏览器cookie是否可用,如果不可用则提醒用户开启cookie

9.5.7 session

1.session概述

​ 当浏览器向服务器发送请求时,服务器就会为请求创建一个session对象用于记录用户状态

2.session特性
  • 服务器会为每个客户端连接分配一个session对象
  • 同一个浏览器向同一个服务器发送多次请求,同属于一次会话,共享一个session对象
3.session原理

借助cookie让浏览器多次请求共享同一个session

  • 当浏览器第一次请求服务器时,服务器为这个连接创建一个session对象,当服务器响应浏览器的请求的时候,自动通过response将sessionID写入到浏览器的cookie中
  • 服务器再次接收到浏览器的请求时,先读取cookie,判断cookie中的jsession的值是否在服务器中存在对应的session对象,如果能找到,则不会创建新的session对象,直接使用找到的session对象
4.获取session对象

当用户连接到服务器时,服务器会为这个用户连接创建一个session对象,在Servlet类中可以通过request调用getSession获取session

5.session对象数据操作
  • 向session对象存储数据

    1
    session.setAttrubute("key1","value1");
  • 获取session对象中的数据

    1
    session.getAttribute("key1");
  • 修改session对象中的数据

    1
    sessin.setAttribute("key1","newvalue");
  • 删除session中的对象

    1
    session.removeAttribute("key1");
6.session对象失效

一个客户端的多次请求正常情况下获取到的是同一个session对象,也正是因为多次请求获取到的是同一个session对象,才实现了session中可以共享数据;

导致session对象失效的原因:

  • 客户端清除cookie数据或者客户端禁用cookie

    • 解决方案:使用URL传递sessionID
  • session生命周期完结

    • 解决方案:根据系统的需求灵活设置session的生命周期或者手动销毁session对象
    1
    2
    3
    4
    //设置session的生命周期
    session.setMaxInactiveInterval(10);//单位是s
    //手动销毁session
    session.invalidate();
7.使用session实现用户登录验证
1
2
3
4
5
6
7
8
9
10
11
//登录成功则设置session
//重定向到index
HttpSession session = request.getSession();
session.setAttribute("stu",student);
response.sendRedirect("index");

//需要登录才能访问的页面添加验证
if (student == null) {
request.setAttribute("tips", "请先登录");
request.getRequestDispatcher("login").forward(request, response);
} else {//执行}
8.request和session的区别
  • request对象用于获取用户的请求数据,作用于浏览器和服务器的一次请求
  • session对象用于记录当前用户的状态,作用于一个客户端的多次请求
  • 转发行为连接的多个servlet之间共享一个request对象,重定向的servlet之间是不同的request对象

9.5.8 ServletContext对象

HttpServletRequest对象作用于一次用户请求,获取用户数据

HttpSession对象作用于一个用户的多次请求,实现数据共享

ServletContext对象作用于整个web项目,实现多个用户之间的数据共享

1.简介

ServletContext是Javaweb项目的全局对象,包含当前web项目在web服务器中的信息,同时它也是一个域对象,可以实现访问当前web项目的所有用户之间的数据共享

2.通过servletcontext对象获取web应用信息
1
2
3
4
5
6
7
8
//获取当前web应用在服务器上的信息
ServletContext servletContext = getServletContext();
//通过context对象获取web应用的上下文路径
//上下文路径就是当前web应用在web服务器上的访问路径
String contextPath = servletContext.getContextPath();
String contextPath1 = req.getContextPath();
//获取web项目中的目录在服务器上的绝对路径
String realPath = servletContext.getRealPath("/files");
3.通过servletContext对象实现全局数据共享
1
2
3
4
5
6
//通过servletContext设置全局对象
servletContext.setAttribute("key1","value1");
//通过servletContext获取全局对象
servlatContext.getAttribute("key1");
//从全局对象移除数据
ser4vletContext.removeAttribute("key1");
4.servletContext对象特性
  • 在服务器启动的时候创建,当服务器关闭或者将项目从项目移除的时候销毁对象
  • 可以实现在线人数统计等需要全局存储的场景
5.servletContext对象设置和获取全局参数
1
2
3
4
5
6
7
8
9
10
//web.xml中配置全局参数
<!-- 配置上下文参数-->
<context-param>
<param-name>key1</param-name>
<param-value>hello word!</param-value>
</context-param>
//获取web.xml中全局参数所有的key
servletContext.getInitParameterNames();
//获取全局参数中的值,根据key获取value
servletContext.getInitParameter("key");

9.5.9 servletConfig对象

servletconfig对象表示的是一个servlet在web项目中的配置信息

1
2
3
4
5
6
7
8
9
//1.获取servletConfig对象
getServletConfig();
//2.通过xml方式配置servlet的初始化参数
<init-param>
<param-name> </param-name>
<param-value></param-value>
</init-param>
//3.获取当前servlet的参数
servletConfig.getInitParam("key1");

9.6 过滤器

9.6.1 过滤器介绍

过滤器(filter)是处于客户端和服务器资源之间的一道过滤技术,可以在用户请求目标资源之前进行预处理业务

作用:

  • 执行多个servlet公共的代码,提高了代码的复用性(例如受限资源的登录验证)
9.6.2 过滤器的使用
1.创建过滤器

在dofilter方法中编写过滤业务规则,通过filterChain.doFilter(request,response)方法放行或者直接返回响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.demo9.filters;


import jakarta.servlet.*;

import java.io.IOException;

//创建一个类实现过滤器接口
//实现其中的init()/doFilter()/destroy()方法
public class MyFilter01 implements Filter {
//过滤器的初始化方法,用于获取初始化参数等
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//定义过滤器的业务

//放行
filterChain.doFilter(servletRequest,servletResponse);
}

@Override
public void destroy() {
Filter.super.destroy();
}
}

2.配置过滤器

配置过滤器拦截哪些资源

  • xml配置

    1
    2
    3
    4
    5
    6
    7
    8
    <filter>
    <filter-name>MyFilter01</filter-name>
    <filter-class>com.demo9.filters.MyFilter01</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>MyFilter01</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
  • 注解配置

    1
    @webFilter("/*");表示拦截所有请求
3.过滤器路径的配置规则
  • 精确过滤:拦截指定的serlvet

    1
    /firstServlet
  • 后缀过滤:拦截指定后缀文件的访问

    1
    2
    *.jpg
    *.html
  • 通配符配置:

    1
    2
    /*拦截所有请求
    /aa/bb/*拦截指定目录下的所有请求
9.6.3 过滤器的执行时机

根据过滤器在目标资源执行的时机,可以把过滤器分为三类:

  • 前置过滤器:过滤器在目标资源之前执行
  • 后置过滤器:在目标资源之后执行
  • 环绕过滤器:执行目标之前和执行之后都执行一次
1.设置前置、后置、环绕过滤器:

在过滤器的 doFilter()方法中写在放行代码(filterChain.doFilter()) 之前的代码会在目标资源执行之前执行,后面的会在目标资源执行之后执行

9.6.4 过滤器链

在同一个服务器资源上可以添加多个过滤器,当用户请求资源时,会依次执行每一个过滤器的前置过滤业务,然后再执行目标资源,最后通过过滤器的后置过滤业务响应请求

1.过滤器链介绍
2.过滤器优先级

在一个web项目中如果配置了多个过滤器,多个过滤器的先后执行顺序

  • 如果多个过滤器都是通过注解配置的,则通过过滤器类的名称字符串的字典顺序执行,如filter01->filter02
  • 如果是通过xml配置的过滤器,则按照在xml中的配置的先后顺序执行,与过滤器类名无关
  • 如果既有注解配置又有xml配置,则xml配置的优先级高于注解配置
  • 如果同一个过滤器既有xml配置,又有注解配置,则该过滤器会被当成两个过滤器执行多次
9.6.5 过滤器应用案例
1.编码过滤器
2.登录验证过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//此过滤器会拦截所有资源请求
//1.判断是否是访问受限资源
//将servletRequest对象转换成HttpServletrequest对象
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
//获取请求路径
String requestURI = httpServletRequest.getRequestURI();
//截取URI的最后一部分
String requestPath = requestURI.substring(requestURI.lastIndexOf("/"+1));

//2.如果请求资源是非受限资源则直接放行,如果是受限资源则验证
if("check".equals(requestPath)||"login".equals(requestPath)){
filterChain.doFilter(servletRequest,servletResponse);
} else {
HttpSession session = httpServletRequest.getSession();
Student stu = (Student) session.getAttribute("stu");
if(stu!=null){
filterChain.doFilter(servletRequest,servletResponse);
}else{
httpServletRequest.setAttribute("tips","请先登录");
httpServletRequest.getRequestDispatcher("login").forward(httpServletRequest,httpServletResponse);
}
}

}

@Override
public void destroy() {

}
}

9.7 servlet应用

9.7.1 文件上传

客户端提交文件到servlet类

1.文件上传案例流程

  • 创建新的web工程
  • 创建静态提交页面
  • 创建servlet
  • 创建dTO
  • 创建dao
2.文件上传实现
  • 前端提交文件:
1
2
3
4
5
6
form表单数据提交时,浏览器会对表单数据进行编码然后上传
当表单中存在文件的时候,要设置不编码传输
通过form表单的enctype属性设置表单数据的压缩方式
-application/x-www-form-urlencoded表示在发送前编码所有字符(默认操作)
-text/plain将表单数据空格转换成+,同时不对特殊字符进行编码
-multipart/form-data表示不对表单数据进行编码
  • servlet接收文件
1
2
3
4
5
6
//当网页设置了multipart/form-data之后不能直接使用getparamter接收文本数据
//需要在当前servlet类添加@MutipartConfig,用于处理非编码数据
//接受表单提交的文件,part对象即为接收到的文件
Part bookImg = request.getPart("bookImg");
//接受表单中所有文件并放在一个集合中
// Collection<Part> parts = request.getParts();
  • 保存接受到的文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //保存文件的目录如果不在web服务器的管理范畴,用户将无法访问
    //在files目录下要放一个任意的文件(空的目录在项目部署的时候不会被创建到web项目)
    //保存接受到的文件
    //1.获取files目录在web服务器上的路径
    ServletContext servletContext = getServletContext();
    String realPath = servletContext.getRealPath("/files");
    //System.out.println(realPath);
    //2.给上传的文件重命名
    String header = bookImg.getHeader("Content-Disposition");//获取文件头信息
    int begin = header.lastIndexOf(".");
    int end = header.lastIndexOf("\"");
    String ext = header.substring(begin, end);//截取文件后缀名
    //System.out.println(ext);
    //取名 可用时间毫秒数,UUID,雪花算法
    String fileName = UUID.randomUUID().toString()+ext;
    System.out.println(fileName);
    //3.存储文件到目录
    bookImg.write(realPath+"//"+fileName);
  • 将文件保存到数据库

    1
    2
    3
     //5.将图书信息保存到数据库,保存到数据库的是图片的访问路径,不是绝对路径
    Book book = new Book(bookId,bookName,"files/"+fileName);
    //将book对象保存到数据库-调用bookdao
9.7.2 文件下载
1
2
3
4
5
6
7
8
9
10
#在项目的files目录下添加几个待下载的图片
#创建文件列表的静态网页
<img src="files/img01.png"/><br/>
<a href="download?fileName=img01.png">下载</a><br/>

<img src="files/img02.png"/><br/>
<a href="download?fileName=img02.png">下载</a><br/>

<img src="files/img03.png"/><br/>
<a href="download?fileName=img03.png">下载</a><br/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//创建文件下载的servlet类FileDownloadServlet
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.接受客户端传递的文件名
String fileName = req.getParameter("fileName");
//2.获取存储文件的files目录路径
ServletContext servletContext = getServletContext();
String dir = servletContext.getRealPath("/files");
//拼接要下载的文件地址
String filePath = dir+"//"+fileName;
//3.设置响应头
resp.setContentType("application/image");//设置响应的类型如果浏览器无法识别则会提示另存为
resp.addHeader("Content-Disposition","attachment; fileName="+fileName);//设置文件头,设置了文件名

//4.通过IO流将文件数据响应给浏览器,由于文件是二进制数据,要通过字节流传输
ServletOutputStream outputStream = resp.getOutputStream();
FileInputStream fileInputStream = new FileInputStream(filePath);
byte[] bs = new byte[1024];
int len = -1;
while((len = fileInputStream.read(bs))!=-1){
outputStream.write(bs,0,len);
}
outputStream.close();
fileInputStream.close();
}
9.7.3 验证码
1.验证码简介

在用户登录或者用户注册的界面为了避免客户端通过暴力破解的形式获取用户的信息,使用验证码技术

提高用户信息的安全性

2.验证码实现流程

3.验证码生成实现
  • 提供登录页面
1
2
3
4
5
6
7
8
9
10

<form action="" method="post">
<p>账号:<input type="text" name="userName" placeholder="请输入账号"/></p>
<p>密码:<input type="password" name="userPwd" placeholder="请输入密码"/></p>
<p>
验证码:<input type="text" name="userCode" maxlength="4" placeholder="请输入验证码"/>
<img src="validateCode"height="30" width="100"/>
</p>
<p><input type="submit" value="登录"/></p>
</form>
  • 创建生成验证码的servlet类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@WebServlet(name="validateCodeServlet",value="/validateCode")
public class ValidateCodeServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收客户端请求生成一个验证码图片
//使用awt工具包
//1.创建一张图片
int width = 300;//验证码宽度
int height = 90;//验证码高度
BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.绘制图片 从图片对象中获取绘制图片的“笔”
Graphics2D graphics = bufferedImage.createGraphics();
//绘制背景
graphics.setColor(getRandomColor());
//绘制实心矩形
graphics.fillRect(0,0,width,height);
//绘制验证码字符串
int letterLen = 4;//验证码字符个数
int letterSpace = 20;//验证码图片上两个字母之间的空隙
int letterWidth = (width-(letterLen+1)*letterSpace)/letterLen;//计算每个字母占据的宽度
//绘制字母 每循环一次绘制一个字母
Random random = new Random();
for(int i = 0; i < letterLen; i++){
//随机生成一个小写字母
int ascii = random.nextInt(26)+97;
byte[] bs = new byte[1];
bs[0] = (byte)ascii;
String letter = new String(bs);
//绘制字母
//为了让图片不太容易被程序识别,可以设置干扰图形TODO
graphics.setColor(getRandomColor());
graphics.setFont(new Font("Gulim",Font.BOLD,70));
graphics.drawString(letter,(i+1)*letterSpace+i*letterWidth,height-letterSpace);
}

//3.图片绘制完成之后将图片通过response的输出流响应到客户端
ImageIO.write(bufferedImage,"png",response.getOutputStream());


}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
//产生一种随机颜色
private Color getRandomColor(){

// Random random = new Random();
// int r = random.nextInt(256);
// int g = random.nextInt(256);
// int b = random.nextInt(256);

int r = (int)Math.floor(Math.random() * 256);
int g = (int)Math.floor(Math.random() * 256);
int b = (int)Math.floor(Math.random() * 256);
Color color = new Color(r, g, b);
return color;
}
}
4.点击验证码图片切换验证码
1
2
3
4
5
6
<script type="text/javascript">
var img = document.getElementById("validateCodeImg");
img.onclick=function (){
img.src="validateCode?m="+Math.random();//为了避免浏览器缓存导致不能刷新地址
}
</script>
5.验证码的验证流程

6.验证流程实现
  • 在生成验证码的时候将验证码存到session
  • 创建验证用户登录的serlvet类
  • 在loginservlet中接受账户的账号密码验证码并进行验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.接受账号、密码、验证码
String userName = request.getParameter("userName");
String userPwd = request.getParameter("userPwd");
String userCode = request.getParameter("userCode");

//2.从session中取出生成验证码时存储的正确的验证码
HttpSession session = request.getSession();
Object validateCode = session.getAttribute("validateCode");

//3.将用户输入的验证码和session中的验证码进行比较
if(userCode.equals(validateCode)){
System.out.println("验证码正确");
//继续校验账号和密码
} else {
System.out.println("验证码错误");
//提示重新输入验证码
}
}

十、JSP

使用servlet的不足

  • 项目更新麻烦,servlet类中的代码发生改变需要重新编译运行Tomcat
  • 呈现页面复杂,动态页面需要写大量的输出流,需要进行HTML标签的拼接
  • 协同开发困难,UI负责页面美化,但是页面是由servlet类提供,因此UI需要掌握java代码

10.1 JSP简介

JSP(Java Server Page),运行在服务器之上,支持Java语言的动态网页技术

背景:简化了servlet的设计,采用在HTML标签中嵌套代码的形式进行动态网页的呈现

作用:替换显示页面部分的servlet(使用,jsp网页文件替换servlet.java的类)

10.2 JSP入门案例

  • 创建一个新的web项目

    • JSP必须依赖服务器运行,因此只能在web应用中使用JSP技术
  • 完成数据库操作的准备

  • 创建工具类,实体类,DAO类

  • 创建servlet类,接受用户请求

    • 调用bookDao查询图书信息,并将数据转发到book-list.jsp
  • 创建JSP页面(在web目录下)

    • 在JSp进行网页界面设计(HTML+CSS+JS)
  • 在JSP页面进行动态显示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    <%@ page import="com.jsp.dto.Book" %>
    <%@ page import="java.util.List" %><%--
    Created by IntelliJ IDEA.
    User: 赵
    Date: 2022/11/14
    Time: 15:49
    To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>Title</title>
    </head>
    <body>
    <%--jsp 中的注释这样写
    JSP文件中可以写Java代码但是要写在<%%>符号中
    --%>
    <%
    //1.通过Java代码接收到booklistServlet转发过来的数据
    List<Book> bookList = (List<Book>) request.getAttribute("bookList");
    %>
    <table width="80%" align="center" border="1" cellspacing="0">
    <tr>
    <th>图书ID</th>
    <th>图书名称</th>
    <th>图书库存</th>
    </tr>
    <%
    for(int i = 0; i < bookList.size(); i++){
    //book是Java中的变量
    Book book = bookList.get(i);
    %>
    <tr>
    <%-- 如果需要将JSP中Java代码的变量显示在HTML中,则需要使用<%=变量%>--%>
    <td><%=book.getBookId()%></td>
    <td><%=book.getBookName()%></td>
    <td><%=book.getBookStock()%></td>
    </tr>
    <%
    }
    %>
    </table>

    </body>
    </html>

10.3 JSP开发详解

10.3.1 JSP和Servlet

JSP和servlet一样可以接受客户端请求,并响应一个动态网页

JSP是对Servlet的一种高级封装,一个JSP文件底层就是一个Servlet类,JSP文件需要依赖服务器运行,当客户端请求一个JSP文件时,会将该JSP文件转换成java代码运行

使用JSP的必要性:

  • 开发动态网页更为便捷

10.3.2 JSP开发的语法规范

1.JSP文档规范
  • JSP文件不放在pacakge中
  • JSP文件以.jsp后缀名结尾
  • 一个JSP文档内容的结构:
    • 第一行需要通过<%@ page %>声明使用java语言
    • JSP文件的主题内容是一个HTML文档,要符合HTML文档规范
2.Java脚本

JSP页面可以嵌入Java代码,Java代码就是这个页面的脚本

  • Java代码:在JSP中的Java代码必须写在<%%>中

  • 变量输出:<%=变量%>

  • 声明变量和方法:

    1
    2
    3
    4
    5
    6
    声明变量:
    <%! int i = 5;%>
    声明方法:
    <%!
    public void method(){}
    %>
3.JSP注释:
  • HTML文档注释
  • JSP 注释

10.3.3 JSP编译指令

编译指令:在JSP文件转换成Java代码之后,编译成class文件的过程中执行的指令

<%@ page %>:声明当前JSP页面在web容器中的配置、引用。

<%@ include %>:在当前JSP中引用其他的资源(JSP、HTML等)作为当前JSP的一部分

<%@ tablib %>:引用第三方标签库扩展JSP文件中的标签

1.<% @page %>
1
2
3
4
5
6
7
8
9
10
11
12
contentType:声明当前JSP文档的MIME类型、字符集编码
#contentType="text/html;charset=UTF-8"
language:定义JSP中所用的脚本的语言类型(默认java)
#language="java"
import:导入要使用的Java的类
#import="java.util.List"
pageEncoding:声明JSP页面的解码格式
#pageEncoding="utf-8"
errorPage:指出当前JSP页面出错后跳转的页面
#errorPage="error.jsp"
isErrorPage:设置当前页面是否可以作为错误页面
#isErrorPage="true"
2.<%@ include %>

被引入的页面不会单独作为一个JSP编译,而是将引入的页面中的代码插入到当前JSP之后作为一个整体进行编译

1
file="header.jsp" 在当前页面引入header.jsp文件
3.<%@ taglib %>
1
refix="c" url="tag/core"

10.3.4 JSP动作指令

在JSP文件中,除了支持标准的html标签库和编译指令之外,JSP还支持JSP特有的动作指令(动作标签)

动作指令:在JSP中以jsp:开头的,在JSP页面运行期间执行的指令

1.JSP:include
1
2
表示动态引入JSP文件:被引入的JSP文件先单独进行编译,将编译结果引入到当前JSP页面
<jsp:include page="1.jsp">

静态引入和动态引入的区别:

  • 静态引入:使用<% @include file=”1.jsp” %>指令将文件引入到当前文件,被引入的页面先引入再编译
  • 动态引入:使用<jsp:include page=”1.jsp”> 将文件引入到当前文件,被引入的页面先编译再引用
2.JSP:useBean

在JSP页面中构造Java对象

1
2
//相当于book = new Book();
<jsp:useBean id="book" class="com.jsp.Book"></jsp:useBean>
3.JSP:setProperty
1
2
//相当于book.setBookId("1001")
<jsp:setProperty name="book" property="bookId" value="1001"></jsp:serProperty>
4.JSP:getProperty
1
2
//取到对象的属性
<jsp:getProperty name="book" property="bookId"/>
  • name属性表示对象的变量名
  • property表示对象的属性名
5.JSP:forward
1
2
3
4
//从当前JSP转发到另一个JSP并传递参数
<jsp:forward page="1.jsp">
<jsp:param name="sex" value="男"/>
</jsp:forward>
6.JSP:param

在转发过程中进行参数传递

10.3.5 JSP九大内置对象

JSP文件在服务器上是转换成servlet类编译执行的,在JSP中嵌入的Java代码都会转换到这个java文件的方法中,因此这个方法的参数和方法中定义的变量以及当前类继承的父类中定义的变量,我们的代码都可以使用

在JSP中编写java代码是可以不用创建,直接使用的对象我们称为JSP内置对象

对象名 说明
request 获取用户请求
response 响应对象,用于将JSP处理的数据响应给客户端
session session对象,表示当前客户端与服务器的会话对象
application ServletContext,表示当前web应用在服务器上的全局对象
config ServletConfig,表示当前servlet类的配置信息
pageContext 当前JSP的上下文,可以获取当前JSP的任何信息
out 指向当前JSP文档的输出流
exception 只有在指定了errorPage=true的页面才能使用
page 相当于当前JSP转换的Servlet实例

10.3.6 JSP四大域对象

可以用来存取数据的对象称为域对象

  • pageContext

    pageContext只作用于当前JSP文件

  • request

    • 作用于一次请求
  • session

    • session作用于一次连接
  • servleContext:application

    • 作用于一个应用的所有用户

10.3.7 JSP开发应用

  • JSP负责页面呈现
  • Servlet负责业务处理

10.4 EL

10.4.1 什么是EL

Expression Language 表达式语言,应用于JSP页面,可以更简单、便捷地获取page/request/session/application的值进行渲染

EL表达式就是替代以下代码的作用:

1
pageContext.getAttribute("key");

使用示例:

1
2
3
4
servlet:
<%request.getAttribute("key");%>
EL:
${key}

10.4.2 EL表达式的使用

serlvet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//1.传递数据
//简单类型
request.setAttribute("key1",123);
//字符串
request.setAttribute("key2","key2");
//对象
Book book = new Book("1001","JAVA","tom","19.99");
request.setAttribute("book",book);
//数组
String[] arr = {"aaa","bbb","ccc"};
request.setAttribute("arr",arr);
//集合
List<Book> bookList = new ArrayList<>();
bookList.add(new Book("1002","c++","mike","11.11"));
bookList.add(new Book("1003","c","mike","11.11"));
bookList.add(new Book("1004","mysql","mike","11.11"));
bookList.add(new Book("1005","python","mike","11.11"));
request.setAttribute("bookList",bookList);
//映射集合
Map<String,Book> bookMap = new HashMap<>();
bookMap.put("1002",new Book("1002","c++","mike","11.11"));
bookMap.put("1003",new Book("1003","c","mike","11.11"));
request.setAttribute("bookMap",bookMap);

//2.转发到jsp
request.getRequestDispatcher("test.jsp").forward(request,response);

JPS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   <%--使用EL表达式获取数据--%>
<%-- 接收简单对象可以直接使用${key}--%>
${key1+1}<br/>

${key2}<br/>

<%-- 接收对象数据:${获取到的是对象的tostring的返回值}--%>
${book}
<%-- 获取对象属性 通过反射调用类中属性的get方法获取属性值--%>
<%-- 因此通过EL表达式获取属性值的对象必须要提供get方法--%>
${book.bookId}<br/>

<%--接收数组--%>
${arr}<%--获取到的是对象路径--%>
${arr[0]}<br/><%--获取到索引位置的值--%>
<%--接收集合--%>
${bookList}<%--取到集合中的所有元素--%>
${bookList[0]}<%--取到指定索引指定的元素--%>
${bookList[0].bookName}<br/><%--取到指定的元素的属性值--%>
<%--接收map--%>
${bookMap}<%--取到map中的所有元素--%>
${bookMap["1002"]}<%--取到map中的指定键值元素--%>
${bookMap["1002"].bookName}<%--获取指定的对象的属性值--%>

10.4.3 EL访问域对象

如果在servlet分别使用request/session/application同时将JSP页面传递数据,并且key都相同,那么在JSP页面直接用${key}获取值,那么获取到的是那个域的对象?如何获取不同域中的对象?

1.${key}获取的数据
  • 四个域对象的范围从小到大依次是:pageContext、request、session、application
  • ${key}如果没有指定域对象,${key}默认获取最小域对象的数据
2.获取指定域对象的数据
  • 在EL表达式中,为4个域对象各自取了名
    • pageContext:pageScope
    • request:requestScope
    • session:sessionScope
    • application:applicationScope
1
2
如:
${sessionScope.key}获取session域对象的数据

10.4.4 EL的隐式对象

EL语法中提供的隐藏对象

除了四个域对象之外,还有七个隐式对象

隐式对象 说明
param 获取request对象的参数,返回的是String类型
paramValues 获取request对象的参数值,返回的是字符串集合
header 获取Http请求头,例如${header.contentPosition}
headerValues 获取http请求头中所有的值
initParam 获取上下文初始化参数
pageContext 获取当前页面的pageContext对象:${pageContext.request.contextPath}
cookie 获取cookie中的值:${cookie.JSESSIONID}

10.4.5 EL运算符

EL表达式不仅能够从域对象获取数据,还能对去除的数据进行算数、关系比较、逻辑运算等运算

1.算数运算:
1
${key+3}表示取到的值+3,同样的运算符有-   *   /or div   %
2.关系比较
1
>  <  >=  <=   ==(eq)  !=(ne)
3.逻辑运算
1
&&(and)    ||(or)    !(not)    
4.判空
1
empyt    ${empty key}判断keysh

10.5 JSTL

JSTL(JSP standard Tag Library),JSP标准标签库,可以扩展JSP中的标签,可以实现流程控制、类型转换等功能

在JSP中通常使用JSTL+EL表达式的组合来进行数据的提取和渲染

JSTL标签库提供了多类标签:

  • c ,核心标签库,提供流程控制
  • fmt,转换标签库,提供了日期、数值类型转换的标签
  • sql
  • fn
  • x

10.5.1JSTL的引入

需要在JSP中引用JSTL标签库之后,才可以使用JSTL提供的标签库

1.下载和导入jstl和standard架包

2.在需要使用JSTL标签的JSP文件中通过<%@taglib%>引入JSTL标签库(JSTL包含多种标签,每种标签需要单独引入)

1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

10.5.2 JSTL核心标签库

c标签,主要用于完成JSP页面中逻辑控制、流程控制

1.c:if
1
2
3
4
5
//如果test属性中的条件成立,则运行c:if标签中的代码
<c:if test="${score}>=60">
<label style="color:green">通过</label>

</c:if>
2.c:choose
1
2
3
4
5
6
7
8
9
10
11
12
<c:choose>
<c:when test="${score}>=60">
<label>及格</label>
</c:when>
<c:when test="${score}<60">
<label>不及格</label>
</c:when>
<c:otherwise>
<label>及格且不及格</label>
</c:otherwise>

</c:choose>
3.c:forEach
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<table align="center" border="1" cellspacing="0">
<tr>
<th>图书编号</th>
<th>图书名称</th>
<th>图书作者</th>
<th>图书价格</th>
</tr>

<c:forEach items="${bookList}" var="book" begin="1" end="3" step="2">----begin指定从集合中的第几个元素开始显示
<tr>
<td>${book.bookId}</td>
<td>${book.bookName}</td>
<td>${book.bookAuthor}</td>
<td>${book.bookPrice}</td>

</tr>

</c:forEach>
</table>

10.5.3 JSTL转换标签

提供了日期、数字等类型的格式转换标签

1
2
3
<fmt:formatNumber value="${num}" pattern="#.00"></fmt:formatNumber>显示两位小数
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd"></fmt:formatNumber>
<fmt:formatDate value="${date}" pattern="hh:mm:ss"></fmt:formatNumber>

十一、Servlet+JSP综合案例

图书信息管理系统:管理员登录,对图书信息进行管理

  • 管理员登录
  • 添加图书信息
  • 图书信息列表
  • 修改图书信息
  • 删除图书信息

11.1 图书信息管理系统业务流程

11.2项目的MVC分层架构

将项目中的实现不同业务的代码进行分离

  • JSP:负责客户端的界面呈现–VIEW
  • Servlet:负责接受用户请求,调用service进行处理,根据处理结果进行流程跳转–CONTROLLER
  • service/dao/dto对数据的业务处理—MODEL

11.3 数据库设计

1.根据项目业务功能抽象数据实体

  • 管理员
  • 图书

2.提取实体的数据项

  • 管理员:ID,登录名,登录密码,真实姓名,性别,电话,备注
  • 图书:编号,名称,作者,价格,封面图片,描述,库存,分类

3.使用三范式约束数据项

4.绘制ER图

5.数据库建模

6.建库建表

11.4 web项目环境搭建

  • 新建web项目
  • 添加jar包
  • 创建JDBC环境
    • 驱动
    • 连接池
    • DButils

11.5 数据库访问实现

1.管理员登录的数据库操作

根据登录名查询用户信息(根据用户名查询用户,将查询出来的密码和输入的密码进行对比)

  1. 创建实体类
  2. 创建DAO类
2.图书管理的数据库操作
  • 添加图书信息
  • 查询所有图书
  • 根据图书ID删除图书信息
  • 根据图书ID查询一个图书信息
  • 根据图书id修改一个图书信息
  1. 创建图书实体类
  2. 创建DAO类完成数据库操作

11.6 网页设计

11.7 业务层实现

1.管理员登录业务
2.图书管理业务实现

11.8 功能流程实现

1.创建JSP和servlet类
  • 在项目中创建所需的JSP文件,将设计好的HTML整合到jsp
  • 创建servlets包,在包中创建业务流程所需的servlet类
2.管理员登录
  • 在login.jsp界面添加name属性,添加表单
3.添加图书
  • 将用户接收到的信息封装成一个图书对象
  • 将图书对象保存到数据库中
  • 关键地方在于文件上传
  • 在prompt中显示添加结果
4.图书列表
5.删除图书
  • 显示图书列表时将图书ID和删除链接绑定
  • 获取图书ID, 删除图书,添加删除确认框
  • 在prompt中显示删除结果
6.修改图书信息
  • 当点击修改的时候将图书ID传递到queryservlet
  • 调用bookService通过Bookid查询到图书并显示到界面
  • Bookid和Bookimg暂不支持修改,所以使用隐藏域
7.分页功能实现

分页是web应用开发中一个重要的业务实现,数据库中的数据可能很多(成千上万),不能将这些数据全部查询出来显示到页面,一般我们需要为用户提供翻页功能

实现思路:

功能实现:

  • BookDAO:
    • 查询总记录数
    • 分页查询数据
8.PageHelper的封装

分页操作在service查询页面数据及总页码都属于同一个分页业务

十二、AJAX

12.1 AJAX简介

AJAX(Asynchronous JavaScript And XML)异步JS与XML,指的是在网页中使用JS脚本实现前端与服务器的异步交互技术。

即在不刷新前端网页的前提下实现和服务器的请求与响应。

AJAX不是一种编程语言,而是使用JS代码实现的前后端异步数据交互的技术。

  • 同步与异步:

    • 同步请求:前端提交数据到Servlet类时,浏览器会离开前端页面,发生了页面的跳转
    • 异步请求:在页面不刷新的情况下,通过JS代码向服务器发送请求,接收响应,显示结果

12.2 异步交互的使用场景

异步交互技术适用于网页中显示大量的数据,同时我们只想对一小部分数据进行更新

例如:

  • 首页登录(系统首页有大量的信息显示,用户需要登录可以使用异步交互完成,避免首页刷新导致重新加载页面中的所有数据。)
  • 省市区联动
  • 注册功能中检测用户名是否可用

12.3 AJAX实现

1.实现流程

2.代码实现

  • 创建web工程

  • 创建注册页面regist.jsp

  • 创建检测用户名的servlet类

  • 创建ajax请求对象

    • IE7+/firefox/O/Safari/Chrome

      1
      var ajaxReq = new XMLHttpRequest();
    • IE5/IE6/

      1
      var ajaxReq = new ActiveXObject("Microsoft.XMLHTTP")
      1
      2
      3
      4
      5
      6
      7
      //1.检测浏览器型号和版本信息
      window.XMLHttpRequest//如果返回true说明是新内核
      //2.创建ajax对象
      //新内核:
      var ajaxReq = new XMLHttpRequest();
      //旧版内核:
      var ajaxReq = new ActiveXObject("Microsoft.XMLHTTP")
  • 封装ajax的请求数据

    1
    2
    3
    4
    open(method,url,asyn);
    //method表示异步请求的请求方式(get或post)
    //url表示 异步请求的目标路径
    //asyn是否异步(true)
    • 封装参数:

      • get请求,通过url传参

        1
        ajaxReq.open("GET","checkUserName?userName="+userName,true);
      • post请求,可通过url或者ajaxReq请求正文传参

        1
        ajaxReq.open("POST","checkUserName?userName="+userName,true);
        1
        ajaxReq.send("key1=value1&key2=value2");
  • 指定ajax的回调函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //3.指定ajax请求的回调函数
    //ajax请求对象是有状态的,通过ajaxReq.readyState获取状态值
    //ajaxReq请求对象的不同状态表示异步交互的不同阶段
    /*
    ajaxReq.readyState == 0 表示ajax请求对象完成创建但并未初始化
    ajaxReq.readyState == 1 表示ajax请求对象完成初始化但并未发送请求
    ajaxReq.readyState == 2 表示ajax请求已经发送并到达服务器
    ajaxReq.readyState == 3 表示服务器正在处理ajax请求(通信中···)
    ajaxReq.readyState == 4 表示服务器处理完成,ajax请求对象已成功获取响应结果
    */

    //只要ajax请求对象状态发生变化,就会触发这个回调函数执行
    ajaxReq.onreadystatechange = callback;

    //指定回调函数
    function callback(){
    //结果在此处理
    if(ajaxReq.readyState == 4){
    //只在状态为4的时候处理

    }
  • 发送ajax请求

    1
    2
    3
    4
    //4.发送请求
    ajaxReq.send(null);
    //如果请求方式为get,为null
    //如果请求方式为post,为null或,"key1=value1,key2=value2"
  • servlet响应AJAX请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if(ajaxReq.readyState == 4 && ajaxReq.status == 200){
    //只在状态为4的时候处理
    //如果服务器响应的是文本数据,用responseText接受
    var result = ajaxReq.responseText;
    //将获取的结果显示到网页的标签中
    document.getElementById("tipsLabel" ).innerHTML = result;
    //console.log(result);
    //如果服务器响应的是XML文件,使用RESPONSEXML
    //var result = ajaxReq.responseXML;
    }

十三、JSON

Ajax是一种使用JavaScript在前端页面不刷新的情况下和服务器进行数据交互的技术

JSON简介

是一种在不同系统之间、前后端之间、不同语言之间进行数据交互所遵守的一种数据格式

不同表现形式

Java对象:
1
2
3
Book book = new Book("001","java","tom",33.33);

>json: {"bookId":"001","bookName":"java","bookAu":"tom","bookPrice":33.33}
Map:
1
2
3
4
5
6
HashMap map = new HashMap();
map.put("k1","aaa");
map.put("k2","bbb");
map.put("k3","ccc");

>json: {"k1":"aaa","k2":"bbb","k3":"ccc"}
数组:
1
2
3
String[] arr = {"AAA","BBB","CCC"}

>JSON:["AAA","BBB","CCC"]
集合:
1
2
3
4
5
6
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");

>JSON: ["aaa","bbb","ccc"]
嵌套
1
2
3
list.add(new Book("002","name","author","price"))//对象的集合

>json: [{对象1},{...},...]

JSON格式转换

前端JS对象与JSON格式的转换

  • JS对象转换成JSON格式字符串

    1
    2
    3
    4
    //1.将JS对象转换成JSON格式字符串
    var obj = {stuNum:"10001",stuName:"tonny"};
    obj.stuGender = "boy";
    var jsonStr = JSON.stringify(obj);
  • 将JSON格式字符串转换成js对象

    1
    2
    3
    //2.将JSON格式字符串转换成JS对象
    var obj2 = eval("("+jsonStr+")");
    console.log(obj2);

后端Java对象与JSON格式转换

FASTJson GSon JackSon

1.将json格式字符串转换成java对象

1
2
3
4
5
//将接受的字符串转换成java对象(student)
//要求:JSON格式中字符串的key要和目标Java对象的属性一致
Gson gson = new Gson();
Student student = gson.fromJson(str, Student.class);
System.out.println(student);

2.将java对象转换成json格式

1
2
Student stu2 = new Student("10002","TOM","girl");
String s = gson.toJson(stu2);

十四、JQuery

简介

JQuery是一个javascript的框架,简化了js的语法和操作,定义了HTML属性操作,样式操作、DOM操作及ajax异步请求等相关函数

JQuery就是一个提供了很多预定义函数的JS文件

入门使用

本地文件引入

下载JQuery函数库:

https://jquery.com

点击下载后ctrl+s保存即可

在网页文件中引入jquery文件:
  • 在HTML文件或者JSP文件,通过script标签引入jquery文件即可

    • 在项目的根目录下新建js目录
    • 将下载的jquery文件拷贝到该目录下
    1
    <script type="text/javascript" src="js/jquery-3.6.4.js"></script>

CDN引入

CDN内容分发网络,将jquery的js文件提前部署到一个服务器,可以通过jquery文件在服务器上的访问路径来引入此jqyery.js文件

官方CDN地址:http://code.jquery.com/jquey-3.6.4.js

JQuery入门示例

点击按钮隐藏图片

1
2
3
4
5
6
7
8
<img id="img01" src="imgs/h4.png" height="200"/><br/>
<button id="btn">测试</button>
<script type="text/javascript">
//点击按钮隐藏图片
$("#btn").click(function(){
$("#img01").hide();
});
</script>

JQueryAPI

https://www.jb51.net/shouce/jquery/cheatsheet.html

JQuery核心函数

  • jQuery()函数:用于获取HTML文档中的元素

    • jQuery([selector,[context]]),根据特定的规则从HTML文档中获取元素

      1
      2
      jQuery("#btn"); //获取当前文档中id=“btn"的元素--数组格式
      jQuery("..inputStyle"); //获取当前文档中calss="inputStyle"的元素--数组格式
    • jQuery(html,[ownerDocument]),创建一个新的HTML元素

      1
      jQuery("<textarea></textarea>").appendTo("body");
    • jQuery(callback)

1.常用函数

1
2
3
4
5
6
7
8
1.$(function(){}) = window.onload = function () {}
2.//$(HTML字符串),根据这个字符串创建元素结点对象
$("<div>" + "hello" + "<div").appendTo("body")将括号内字符串加入到body标签中
3.$("#id") 根据id查询对象
$("标签名") 根据标签名查询对象
$(".class属性值") 根据类名查询对象
4.$(dom对象) 将dom对象转换为JQuery 对象

2.区分DOM对象和JQuery 对象

  • JQuery对象是DOM对象的数组 + JQuery 提供的一系列功能函数
  • DOM对象和jQuery对象方法不通用
  • $(dom)将DOM对象转化为jQuery对象
  • jQuery[下标]即可取出DOM对象

3.jQuery基础选择器

1
2
3
4
5
6
7
1.ID查询
2.$("div,span,p.myClass") 组合选择器
3.css()方法可以设置和获取样式
4.$("*") 选择所有元素
5.$(label + input) 查找紧跟在label后面的input元素
6.$(form ~ input) 查找与form 同辈的input元素
7.$("form input") 查找form元素里面的input

4.过滤选择器

1.基本过滤选择器

1
2
3
4
5
6
1.$(":first") 获取匹配的第一个元素  // 也可是:last
2.$("not:(selector)") 查找未选中的元素
3.$("tr:even") 匹配索引值为偶数的元素 // odd 匹配索引值为奇数的元素
4.$("tr:eq(1)") 匹配指定索引值的元素
5.$("tr:gt(0)") 匹配索引值大于 0 的元素 // lt 小于
6.$(":head") 匹配标题元素

2.内容过滤器

1
2
3
4
1.$("div:contains("John")") 匹配包含指定文本的元素
2.$(":empty") 匹配所有不包含子元素或者文本的元素 //:parent 匹配非空元素
3.$(":has(selector)" ) 匹配含有选择器所匹配元素的元素

3.属性过滤器

1
2
3
4
5
6
1.$("div[id]") 查找含有id属性的div元素
2.$("div[id=1]") 查找含有Id=1 属性的元素
3.$("div [name=^'name']") 查找以name开头的name 属性的div标签
4.$("div[naem=$'name'] ") 结尾匹配
5.$("div[name*'name']") 包含元素查询
6.复合属性选择器 $("div [id][name=^'ni']")

4.表单过滤器

1
1.:text 匹配所有单行文本框

5.元素筛选

5.JQuery动画

1
2
3
4
5
show(时长,回调函数)
hide()
toggle()
fadeIn()
fadeOut()

6.JQUERY和JS加载顺序

1.页面加载完成之后先执行jQuery,再执行JS

2.原生JS的页面加载完成之后只执行最后一次的赋值函数,jQuery会依次执行所有的赋值函数

3.在子元素的事件函数内return false 可以组织事件

欢迎关注我的其它发布渠道