JavaWeb

JavaWeb

所有通过Java语言编写可以通过浏览器访问的程序的总称

基于请求和响应来开发:

  • 请求:指客户端给服务器发送数据,Request

  • 响应:服务器给客户端回传数据,Response

  • 请求和响应是成对出现的,有请求就有响应

资源分类:

  • 静态资源:html/css/js/txt/mp4视频/jpg图片

  • 动态资源:jsp页面/Servlet程序

HTML

Hyper Text Markup Language

超文本标记语言

一种文本文件

通过标签标记显示网页中的各个部分

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>:约束声明
<html lang=“zh_CN”>:html开始
<head>:头部信息
<meta charset=“UTF-8”>:当前页面的字符集
<title></title>
<css></css>
<js></js>
</head>
<body>:整个html页面显示的主题内容
</body>
</html>
<!---—>:注释

字符实体

character entities

若希望显示预留字符,须在HTML源代码中使用字符实体

空格: 

大于号:>

小于号:<

……

标签

单标签:<标签名 />

双标签:<标签名> 数据 </标签名>

大小写不敏感

拥有自己的属性:

  • 基本属性:

    • 可修改简单的样式效果:bgcolor=”red”
  • 事件属性:

    • 可直接设置事件响应后的代码:onClick=”alert(“hello”);”
  • 属性必须有值,且值必须要加引号

注释不能嵌套

标题:h1到h6,h1最大/h6最小

超链接:网页中所有点击之后可以跳转的内容都是超链接

列表:

  • 无序列表(常用)

  • 有序列表

  • 定义列表(不常用)

img:用来显示图片

src:设置图片的路径

  • 相对路径:

    • .:当前文件所在的目录
    • ..:当前文件所在的上一级目录
    • 文件名:当前文件所载目录的文件,相当于./文件名,./可省略
  • 绝对路径:http://IP:port/工程名/资源路径

表格:

  • tr:行标签

  • th:表头标签

  • td:单元格标签

框架iframe:

  • 可在一个html页面中加载一个单独的页面

  • 可用name为iframe添加名称,使超链接的target指向它

表单form:

  • html页面中收集用户信息的所有元素集合,然后把这些信息发送给服务器

  • 可通过name分组

  • action属性设置提交的服务器地址

  • Method属性设置提交的方式:

  • GET请求:

    • 默认值
    • 浏览器地址栏中的地址:action属性[+?+请求参数]
    • 请求参数的格式:name=value&name=value
    • 不安全
    • 有数据长度的限制
  • POST请求:

    • 浏览器地址栏中只有action属性值
    • 相对于GET请求要安全
    • 理论上没有数据长度的限制
  • 表单提交时数据没有发送给服务器的情况:

    • 表单项没有name属性值
    • 表单项不在提交的form标签中
    • 单选/复选/下拉列表中的option标签都需要添加value属性

div标签:默认独占一行

span标签:它的长度是封装数据的长度

p段落标签:默认会在段落的上方或下方各空出一行来(如果已有就不再空)

CSS

层叠样式表单

用于(增强)控制网页样式并允许将样式信息与网页内容分离的一种标记性语言

选择器:浏览器根据“选择器”决定受CSS样式影响的HTML元素(标签)

属性property:

  • 所要改变的样式名

  • 每个属性都有一个值

  • 属性和值被冒号分开,由花括号包围,组成了一个完整的样式声明(declaration)

1
p {color: blue} 
  • 多个声明:
    • 若要定义不止一个声明则需要用分号将每个声明分开

    • 最后一条声明的最后可不加分号(但尽量在每条声明的末尾都加上分号)

1
2
3
4
5
6
<style type="text/css">
p {
color:red;
font-size:30px;
}
</style>

CSS注释:/注释内容/

CSS/HTML结合方式

方式1:在标签的style属性上设置”key:value value;”,修改标签样式

  • 代码量大
  • 可读性差
  • 代码没有复用性

方式2:在head标签中使用style标签来定义各种自己需要的css样式

1
2
3
4
5
6
<style type="text/css">
p {
color:red;
font-size:30px;
}
</style>
  • 不能在多个页面中复用css代码
  • 维护工作量大

方式3:把css样式写成一个单独的css文件,再通过link标签引入

  • 使用html的一下标签 导入css样式文件
1
<link rel="stylesheet" type="text/css" href="./styles.css" />

CSS选择器

标签名选择器:可以决定哪些标签被动的使用这个样式

1
2
3
标签名 {
属性:值;
}

Id选择器:可通过id属性选择性的去使用这个样式

1
2
3
#id 属性值 {
属性:值;
}
  • 不可复用

Class选择器(类选择器):可通过class属性有选择性地去使用这个样式

1
2
3
.class 属性值 {
属性:值;
}

组合选择器:可让多个选择器共用同一个css样式代码

1
2
3
选择器 1,选择器 2,选择器 n { 
属性:值;
}

常用样式

字体颜色:

1
color:red; 
  • 可以写颜色名:black,blue,red,green等
  • 可以写rgb值/十六进制表示值:rgb(255,0,0),#00F6DE
  • 如果写十六进制值必须加#

宽度:

1
width:19px;
  • 可以写像素值:19px;
  • 可以写百分比值:20%;

高度:

1
height:20px; 
  • 可以写像素值:19px;
  • 可以写百分比值:20%;

背景颜色:

1
background-color:#0F2D4C 

字体样式:

1
color:#FF0000;

字体颜色红色:

1
font-size:20px;

字体大小5/红色/1像素实线边框:

1
border:1px solid red;

DIV居中:

1
2
margin-left:auto;
margin-right:auto;

文本居中:

1
text-align:center;

超连接去下划线:

1
text-decoration:none; 

表格细线:

1
2
3
4
5
6
7
8
9
10
<style type="text/css">
table {
border: 1px solid black; /*设置边框*/
border-collapse: collapse; /*将边框合并*/
}

td, th {
border: 1px solid black; /*设置边框*/
}
</style>

列表去除修饰:

1
2
3
4
5
<style type="text/css">
ul {
list-style: none;
}
</style>

JavaScript

语言诞生主要是完成页面的数据验证

运行在客户端,需要运行浏览器来解析执行JavaScript代码

JS是弱类型,Java是强类型

特点

交互性:它可以做的就是信息的动态交互

安全性:不允许直接访问本地硬盘

跨平台性:只要是可以解释JS的浏览器都可以执行,和平台无关

JS/html结合方式

方式1:在head/body标签中使用script标签书写JavaScript代码

1
2
3
4
5
<script type="text/javascript">
// alert 是 JavaScript 语言提供的一个警告框函数
// 它可以接收任意类型的参数,这个参数就是警告框的提示信息
alert("helloJavaScript!");
</script>

方式2:使用script标签引入单独的JavaScript代码文件

  • 一个标签不能同时使用两个方式

变量

可以存放某些值的内存的命名

变量类型

数值类型:number

字符串类型:string

对象类型:object

布尔类型:boolean

函数类型:function

特殊值

undefined:未定义

  • 所有js变量未赋于初始值的时默认值都为undefined

null

NaN:Not a Number

  • 非数字/非数值

变量格式

var 变量名;

var 变量名 = 值;

关系/比较符运算

==:等于

  • 简单的做字面值的比较

===:全等于

  • 除了做字面值的比较之外,还会比较两个变量的数据类型

逻辑运算

且运算:&&

  • 全为真:返回最后一个表达式的值

  • 有一个为假:返回第一个为假的表达式的值

或运算:||

  • 全为假:返回最后一个表达式的值

  • 只要有一个表达式为真:返回第一个为真的表达式的值

&&和||运算存在短路:

  • 当&&/||有结果后后面的表达式不在被执行

取反运算:!

  • 所有的变量都可以做为一个boolean类型的变量去使用
  • 0/null/undefined/“”(空串)都认为是false

数组

只要通过数组下标赋值,最大的下标值就会自动给数组扩容

var 数组名 = []; // 空数组

var 数组名 = [1 , ’abc’ , true]; // 定义数组同时赋值元素

函数

若定义带有返回值的函数,只需要在函数体内直接使用return语句返回值

没有重载,会被覆盖

定义方式1:使用function关键字定义函数

1
2
3
function 函数名(形参列表) {
函数体
}

定义方式2:

1
var 函数名 = function(形参列表) { 函数体 }

arguments隐形参数

只在function函数内

函数中不需要定义却可以直接用来获取所有参数的变量

类似于Java的可变长参数,可变长参数其他是一个数组

自定义对象

Object形式的自定义对象:

  • 定义:
1
2
3
var 变量名 = new Object(); // 对象实例(空对象)
变量名.属性名 = 值; // 定义一个属性
变量名.函数名 = function(){} //定义一个函数
  • 访问:

    变量名.属性/函数名();

{}花括号形式的自定义对象:

  • 定义:
1
2
3
4
var 变量名 = { // 空对象
属性名: 值, // 定义一个属性
函数名: function () {} //定义一个函数
};
  • 访问:

    变量名.属性/函数名();

事件

电脑输入设备与页面进行交互的响应

常用事件

onload:加载完成事件

  • 页面加载完成之后,常用于做页面js代码初始化操作

onclick:单击事件

  • 常用于按钮的点击响应操作

onblur:失去焦点事件

  • 常用用于输入框失去焦点后验证其输入内容是否合法

onchange:内容发生改变事件

  • 常用于下拉列表和输入框内容发生改变后操作

onsubmit:表单提交事件

  • 常用于表单提交前,验证所有表单项是否合法

注册/绑定

告诉浏览器,当事件响应后要执行哪些操作代码

静态注册:通过html标签的事件属性直接赋于事件响应后的代码

动态注册:

  • 先通过js代码得到标签的dom对象

  • 再通过dom对象.事件名 = function(){}赋于事件

  • 基本步骤:

    获取标签对象

    标签对象.事件名 = function(){}

    window.onload在页面加载完后才运行

DOM模型

Document Object Model 文档对象模型

将文档中的标签/属性/文本转换成为对象来管理

Document对象

管理了所有的HTML文档内容

是一种树结构的文档,有层级关系

它让我们把所有的标签都对象化

我们可通过document访问所有的标签对象

方法

document.getElementById(elementId):通过标签的id属性查找标签dom对象

document.getElementByName(elementName):通过标签的name属性查找标签dom对象

  • 返回多个标签对象集合
  • 和数组操作一样
  • 集合中每个元素都是dom对象

document.getElementByTagName(tagName):通过标签名查找标签dom对象

优先级:id > name > tagName

以上三个方法一定要在页面加载完成之后执行才能查询到标签对象

document.createElement(tagName):通过给定的标签名创建一个标签对象

节点常用属性方法

节点:标签对象

属性

childNodes:获取当前节点的所有子节点

firstChild:获取当前节点的第一个子节点

lastChild:获取当前节点的最后一个子节点

parentNode:获取当前节点的父节点

nextSibling:获取当前节点的下一个节点

previousSibling:获取当前节点的上一个节点

className:获取或设置标签的class属性值

innerHTML:获取/设置起始标签和结束标签中的内容

innerText:获取/设置起始标签和结束标签中的文本

方法

.getElementsByTagName():获取当前节点的指定标签名孩子节点

.appendChild(oChildNode):添加一个子节点

oChildNode是要添加的孩子节点

jQuery

JavaScript和查询(Query),辅助JavaScript开发的js类库

jQuery对象是dom对象的数组 + jQuery提供的一系列功能函数

实现了很多浏览器的兼容问题

使用jQuery要引入jQuery库:

1
<script type="text/javascript" src="../script/jquery-1.7.2.js"></script>

使用$()代替window.onload:

1
2
3
4
5
$(function () {
$("#btnId").click(function () {
alert('Hello');
});
});

$:jQuery的核心函数,能完成jQuery的很多功能,$()就是调用$这个函数

  • 传入参数为[函数]时:表示页面加载完成之后,相当于 window.onload = function(){}
  • 传入参数为[HTML字符串]时:会对我们创建这个html标签对象
  • 传入参数为[选择器字符串]时:

$(“#id 属性值”);:id选择器,根据id查询标签对象

$(“标签名”);:标签名选择器,根据指定的标签名查询标签对象

$(“.class 属性值”);:类型选择器,可以根据class属性查询标签对象

传入参数为[DOM对象]时:会把这个dom对象转换为jQuery对象

对象区分

Dom对象:

  • getElementById()查询出来的标签对象
  • getElementsByName()查询出来的标签对象
  • getElementsByTagName()查询出来的标签对象
  • createElement() 方法创建的对象
  • DOM对象alert出来的效果是[object HTML 标签名 Element]

jQuery对象:

  • jQuery提供的API创建的对象是
  • jQuery包装的Dom对象
  • jQuery提供的API查询到的对象
  • jQuery对象alert出来的效果是[object Object]
  • jQuery对象不能使用DOM对象的属性和方法
  • DOM对象也不能使用jQuery对象的属性和方法

对象互转

dom对象 → jQuery对象:

  1. 先有DOM对象
  2. $(DOM对象)

jQuery对象 → dom对象:

  1. 先有jQuery对象
  2. jQuery对象[下标]取出相应的DOM对象

选择器

基本选择器

#ID选择器:根据id查找标签对象

.class选择器:根据class查找标签对象

Element选择器:根据标签名查找标签对象

*选择器:表示任意的,所有的元素

selector1,selector2组合选择器:合并选择器1,选择器2的结果并返回

层级选择器

ancestor descendant:后代选择器

在给定的祖先元素下匹配所有的后代元素

parent > child:子元素选择器

在给定的父元素下匹配所有的子元素

prev + next:相邻元素选择器

匹配所有紧接在prev元素后的next元素

prev ~ sibings:之后的兄弟元素选择器

匹配prev元素之后的所有siblings元素

过滤选择器

基本过滤器

:first:获取第一个元素

:last:获取最后个元素

:eq(index):匹配一个给定索引值的元素

:not(selector):去除所有与给定选择器匹配的元素

:even:匹配所有索引值为偶数的元素,从0开始计数

:odd:匹配所有索引值为奇数的元素,从0开始计数

:eq(index):匹配一个给定索引值的元素

:gt(index):匹配所有大于给定索引值的元素

:lt(index):匹配所有小于给定索引值的元素

:header:匹配如h1/h2/h3之类的标题元素

:animated:匹配所有正在执行动画效果的元素

内容过滤器

:contains(text):匹配包含给定文本的元素

:empty:匹配所有不包含子元素或者文本的空元素

:parent:匹配含有子元素或者文本的元素

:has(selector):匹配含有选择器所匹配的元素的元素

属性过滤器

[attribute]:匹配包含给定属性的元素

[attribute = value]:匹配给定属性是某个特定值的元素

[attribute!=value]:匹配所有不含有指定的属性,或者属性不等于特定值的元素

[attribute^=value]:匹配给定的属性是以某些值开始的元素

[attribute$=value]:匹配给定的属性是以某些值结尾的元素

[attribute*=value]:匹配给定的属性是以包含某些值的元素

[attrSel1][attrSel2][attrSelN]:复合属性选择器,需要同时满足多个条件时使用

表单过滤器

:input:匹配所有input/textarea/select/button元素

:text:匹配所有文本框输入框

:password:匹配所有密码输入框

:radio:匹配所有单选框

:checkbox:匹配所有复选框

:submit:匹配所有提交按钮

:image:匹配所有img标签

:reset:匹配所有重置按钮

:button:匹配所有input type = button<>按钮

:file:匹配所有inputtype=file文件上传

:hidden:匹配所有不可见元素display:none或input type=hidden

表单对象属性过滤器

:enabled:匹配所有可用元素

:disabled:匹配所有不可用元素

:checked:匹配所有选中的单选/复选/下拉列表中选中的option标签对象

:select:匹配所有选中的option

元素筛选

eq():获取给定索引的元素

  • 功能跟:eq()一样

first():获取第一个元素

  • 功能跟:first一样

last():获取最后一个元素

  • 功能跟:last一样

filter(exp):留下匹配的元素

is(exp):判断是否匹配给定的选择器,只要有一个匹配就返回true

has(exp):返回包含有匹配选择器的元素的元素

  • 功能跟:has一样

not(exp): 删除匹配选择器的元素

  • 功能跟:not一样

children(exp):返回匹配给定选择器的子元素

  • 功能跟parent > child一样

find(exp): 返回匹配给定选择器的后代元素

  • 功能跟ancestor descendant一样

next():返回当前元素的下一个兄弟元素

  • 功能跟prev + next一样

nextAll():返回当前元素后面所有的兄弟元素

  • 功能跟prev ~ siblings一样

nextUntil():返回当前元素到指定匹配的元素为止的后面元素

parent():返回父元素

prev(exp):返回当前元素的上一个兄弟元素

prevAll():返回当前元素前面所有的兄弟元素

prevUnit(exp):返回当前元素到指定匹配的元素为止的前面元素

siblings(exp):返回所有兄弟元素

add():把add匹配的选择器的元素添加到当前jquery对象中

属性操作

html():设置/获取起始标签和结束标签中的内容

  • 和dom属性innerHTML一样

text():设置/获取起始标签和结束标签中的文本

  • 和dom属性innerText一样

val():设置/获取表单项的value属性值

  • 和dom属性value一样

attr():设置/获取属性的值

  • 不推荐操作:checked/readOnly/selected/disabled等

  • Attr还可以操作非标准的属性。比如自定义属性:abc/bbj

prop():设置/获取属性的值

  • 只推荐操作:checked/readOnly/selected/disabled等

DOM的增删改

内部插入:

  • A.appendTo(b):把a插入到b子元素末尾,成为最后一个子元素
  • A.prependTo(b):把a插到b所有子元素前面,成为第一个子元素

外部插入:

  • a.insertAfter(b): 得到ba
  • a.insertBefore(b):得到ab

替换:

  • a.replaceWith(b):用b替换掉a
  • a.replaceAll(b): 得到ba得到ab

删除:

  • a.remove():用a替换掉所有b
  • a.empty():删除a标签清空a标签里的内容

CSS样式操作

addClass():添加样式

removeClass():删除样式

toggleClass():有就删除,没有就添加样式

offset():获取/设置元素的坐标

jQuery动画

基本动画:

  • show():将隐藏的元素显示
  • hide():将可见的元素隐藏
  • toggle():可见就隐藏,不可见就显示

淡入淡出动画:

  • fadeIn():淡入(慢慢可见)

  • fadeOut():淡出(慢慢消失)

  • fadeTo():在指定时长内慢慢的将透明度修改到指定的值

    0:透明

    1:完全可见

    0.5:半透明

  • fadeToggle():淡入/淡出切换

以上动画方法都可以添加参数:

  1. 参数是动画执行的时长,以毫秒为单位
  2. 参数是动画的回调函数(动画完成后自动调用的函数)

事件操作

$(function(){});/window.onload = function(){}区别

触发时间:

  • Query:
    1. 页面加载完成
    2. 浏览器的内核解析完页面的标签,创建好DOM对象
    3. 马上执行
  • JS:
    1. 页面加载完成
    2. 等浏览器内核解析完标签,创建好DOM对象
    3. 等标签显示时需要的内容加载完成

触发顺序:

  • jQuery:页面加载完成之后先执行
  • JS:页面加载完成之后

执行次数:

  • Js:页面加载完成之后只会执行最后一次的赋值函数
  • jQuery:页面加载完成之后依次顺序全部执行注册的function函数

其他事件处理方法

click():可以绑定单击事件/触发单击事件

mouseover():鼠标移入事件

mouseout():鼠标移出事件

bind():可以给元素一次性绑定一个/多个事件

one():使用上跟bind一样,one方法绑定的事件只会响应一次

unbind():跟bind方法相反的操作,解除事件的绑定

live():可以用来绑定选择器匹配的所有元素的事件,这个元素是后面动态创建出来的也有效

事件冒泡

父子元素同时监听同一个事件,当触发子元素的事件的时,同一个事件也被传递到了父元素的事件里去响应

阻止方法:在子元素事件函数体内return false;

事件对象

封装有触发的事件信息的一个javascript对象

获取:给元素绑定事件的时,在事件的function(event)参数列表中添加一个参数

这个event就是avascript传递参事件处理函数的事件对象

XML

可扩展的标记性语言

用来保存数据,而且这些数据具有自我描述性

做为项目或者模块的配置文件

做为网络传输数据的格式(现在JSON为主)

可以使用w3c组织制定的dom技术来解析(过时)

命名规则:

  • 名称可以含字母/数字/其他字符
  • 不能以数字或者标点符号开始
  • 不能包含空格

语法

文档声明

version:版本号

encoding:xml文件编码

standalone=“yes/no”:是否是独立的xml文件

元素(标签)

单标签:<标签名 属性=”值” 属性=”值” …… />

双标签:< 标签名 属性=”值” 属性=”值” ……>文本数据或子标签</标签名>

所有XML元素都须有关闭标签

对大小写敏感

必须正确地嵌套

文档必须有根元素:

根元素是没有父标签的顶级元素,且唯一

xml属性

属性可以提供元素的额外信息

每个属性的值必须使用引号引起来

文本区域(CDATA 区)

告诉xml解析器,CDATA里的文本内容只是纯文本不需要xml语法解析

CDATA格式:

1
<![CDATA[这里可以把你输入的字符原样显示不会解析xml]]> 

dom4j解析

第三方的解析技术

步骤:

  1. 加载xml文件创建Document对象

  2. 通过Document对象拿到根元素对象:

  3. 通过根元素.elelemts(标签名); 返回一个集合

    这个集合里放着所有指定的标签名的元素对象

  4. 找到要修改/删除的子元素,进行相应在的操作

  5. 保存到硬盘上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//读取.xml文件
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src/books.xml");
//通过Document对象获取根元素
Element rootElement = document.getRootElement();
//通过根元素获取root标签对象
//element()和elements()都是通过标签名查找子元素
List<Element> books = rootElement.elements("book");
//遍历处理每个book标签转换为Book类
for (Element book : books) {
//asXML():把标签对象转换为标签字符串
String sn = book.attributeValue("sn");
//直接获取指定标签名的文本内容
String name = book.elementText("name");
String author = book.elementText("author");
BigDecimal price = BigDecimal.valueOf(Double.parseDouble(book.elementText("price")));
Book b = new Book(sn, name, price, author);
System.out.println(b);
}

Tomcat

部暑:

1
2
3
4
5
6
- <!-- Context:一个工程上下文
- path:工程的访问路径:/abc
- docBase:工程目录
- -->
- <Context path="/abc" docBase="E:\book" />
- 访问http://ip:port/abc/ 就表示访问E:\book目录

src:存放Java源代码

Web:存放web工程资源文件(html/css/js)

WEB-INF:受服务器保护的目录,浏览器无法直接访问此目录的内容

  • lib:存放第三方的jar包

  • Web.xml:整个动态web工程的配置部署描述文件

    可配置很多web工程组件(Servlet/Filter/Listener)

Servlet

JavaEE规范之一(规范就是接口)

JavaWeb三大组件之一(Servlet程序、Filter过滤器、Listener监听器)

运行在服务器上的一个java小程序,可以接收客户端发送过来的请求,并响应数据给客户端

绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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">

<!--为Tomcat配置Servlet程序-->
<servlet>
<!--为Servlet程序起别(一般是类名)-->
<servlet-name>HelloServlet</servlet-name>
<!--为Servlet程序的全类名-->
<servlet-class>cc.mousse.servlet.HelloServlet</servlet-class>
</servlet>

<!--给servlet程序配置访问地址-->
<servlet-mapping>
<!--告诉服务器当前配置的地址给哪个servlet程序使用-->
<servlet-name>HelloServlet</servlet-name>
<!--配置访问地址:http://localhost:8080/JavaWeb/hello-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>

生命周期

  1. 执行Servlet构造器方法

  2. 执行init初始化方法

    (第一/二步在第一次访问时创建Servlet程序会调用)

  3. 执行service方法(每次访问都会调用)

  4. 执行destroy销毁方法(web工程停止的时候调用)

实现Servlet程序

继承Servlet实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class HelloServlet implements Servlet {
/**
* 专用于处理请求和响应的
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//类型转换(它有getMethod方法)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
//获取请求方式
String method = httpServletRequest.getMethod();
if ("GET".equals(method)) {
doGet();
} else if ("POST".equals(method)) {
doPost();
}
System.out.println("HelloServlet被访问");
}
}

继承HttpServlet实现

一般在实际项目开发中都使用继承HttpServlet类的方式去实现

  1. 编写一个类去继承HttpServlet类
  2. 根据业务需要重写doGet/doPost方法
  3. 到web.xml中的配置Servlet程序的访问地址
  4. 重写init()方法时一定要调用super.init(config);方法

继承体系

Interface Servlet:只负责定义Servlet程序的访问规范

​ ↑实现

Class GenericServlet:有很多空实现,有一个ServletConfig类的引用并对其的使用做了一些方法

​ ↑继承

Class HttpServlet:实现了service()方法,实现请求的分发处理

  • String method = req.getMethod()

​ ↑继承

自定义Servlet程序:只需要根据自己的业务重写doGet()/doPost()方法

ServletConfig

Servlet程序的配置信息类

Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用

Servlet程序默认是第一次访问的时候创建

ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象

作用:

  • 获取Servlet程序的别名servlet-name的值
  • 获取初始化参数init-param
  • 获取ServletContext对象

ServletContext

ServletContext是一个接口,它表示Servlet上下文对象

一个web工程只有一个ServletContext对象实例

ServletContext对象是一个域对象:

  • 这里的域指的是存取数据的操作范围:为整个web工程
  • 域对象:可以像Map一样存取数据的对象
    • 存数据:setAttribute()
    • 取数据:getAttribute()
    • 删除数据:removeAttribute()

ServletContext在web工程部署启动的时候创建,在web工程停止的时候销毁

作用:

  • 获取web.xml中配置的上下文参数context-param
  • 获取当前的工程路径,格式:/工程路径
  • 获取工程部署后在服务器硬盘上的绝对路径
  • 像Map一样存取数据

HTTP协议

客户端给服务器发送数据叫请求

服务器给客户端回传数据叫响应

请求

GET请求

请求行:

  • 请求的方式:GET
  • 请求资源路径:[+?+请求参数]
  • 请求的协议的版本号:HTTP/1.1

请求头:key : value组成不同的键值对,表示不同的含义

常用请求:

  • form标签method=get
  • a标签
  • link标签引入css
  • Script标签引入js文件
  • img标签引入图片
  • iframe引入html页面
  • 在浏览器地址栏中输入地址后敲回车
POST请求

请求行:

  • 请求的方式:POST
  • 请求资源路径:[+?+请求参数]
  • 请求的协议版本号:HTTP/1.1

请求头:key : value不同的请求头有不同的含义

空行

请求体:发送给服务器的数据

常用请求:

  • form标签method=post

常用的请求头:

  • Accept:表示客户端可以接收的数据类型
  • Accpet-Languege:表示客户端可以接收的语言类型
  • User-Agent:表示客户端浏览器的信息
  • Host:表示请求时的服务器ip和端口号

响应

响应行:

  • 响应的协议和版本号
  • 响应状态码
  • 响应状态描述符
  • 响应头:key : value:不同的响应头有其不同含义

空行

响应体:回传给客户端的数据

常用响应码:

  • 200:请求成功
  • 302:请求重定向
  • 404:请求服务器已经收到了,但是所要的数据不存在(请求地址错误)
  • 500:服务器已经收到请求,但是服务器内部错误(代码错误)

MIME

“Multipurpose Internet Mail Extensions” 多功能Internet邮件扩充服务

格式:“大类型/小类型”,与某一种文件的扩展名相对应

常见MIME类型:

文件 MIME 类型
超文本标记语言文本 .html , .htm text/html
普通文本 .txt text/plain
RTF 文本 .rtf application/rtf
GIF 图形 .gif image/gif
JPEG 图形 .jpeg,.jpg image/jpeg
au 声音文件 .au audio/basic
MIDI 音乐文件 mid,.midi audio/midi,audio/x-midi
RealAudio 音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG 文件 .mpg,.mpeg video/mpeg
AVI 文件 .avi video/x-msvideo
GZIP 文件 .gz application/x-gzip
TAR文件 .tar application/x-tar

HttpServletRequest

每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中。然后传递到service方法(doGet和doPost)中给我们使用

我们可以通过HttpServletRequest对象,获取到所有请求的信息

常用方法

getRequestURI():获取请求的资源路径

getRequestURL():获取请求的统一资源定位符(绝对路径)

getRemoteHost():获取客户端的IP地址

getHeader():获取请求头

getParameter():获取请求的参数

getParameterValues():获取请求的参数(多个值的时候使用)

getMethod():获取请求的方式GET或POST

setAttribute(key, value):设置域数据

getAttribute(key):获取域数据

getRequestDispatcher():获取请求转发对象

setCharacterEncoding(“UTF-8”):解决post请求中文乱码问题

需要在获取请求参数之前设置才有效

请求转发

服务器收到请求后,从一次资源跳转到另一个资源的操作

浏览器地址栏没有变化

一次请求

共享Request域中的数据

可以转发到WEB—INFO目录下

不可访问工程外的资源

过程:

  1. 浏览器:http://ip:port/工程名/servlet1
  2. Servlet1程序:
    1. 查看是否有带请求的参数
    2. 处理完业务加盖个章
    3. 问路,Servlet2怎么走
    4. 走到Servlet2
  3. Servlet2程序:
    1. 获取请求参数(查看材料)
    2. 检查有没有Servlet1的章
    3. 处理自己的业务
    4. 响应给客户端
  • Servlet1和Servlet2可以共同完成一个完整的业务功能
  • 从Servlet1到Servlet2的操作叫做请求转发
1
req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req, resp);

base标签

可以设置当前页面中所有相对路径工作室参照哪个路径进行跳转:

base标签:设置页面相对路径工作时参照的地址

href属性:是参数的地址值

1
<base href=“http://localhost:8080/JavaWeb/a/b/">

相对/绝对路径

相对路径:

  • .:表示当前目录
  • ..:表示上一级目录
  • 资源名:表示当前目录/资源名

绝对路径:http://ip:port/工程路径/资源路径

在实际开发中路径都使用绝对路径而不简单的使用相对路径:

  • 绝对路径

  • base+相对

斜杠意义

在web中/斜杠是一种绝对路径

被浏览器解析:http://ip:port/

1
<a href="/"></a>

被服务器解析:http://ip:port/工程路径

1
<url-pattern>/servlet</url-pattern>
1
servletContext.getRealPath("/")

例外:

1
response.sendRediect("/")

HttpServletResponse

和HttpServletRequest类一样,每次请求进来Tomcat服务器都会创建一个Response对象传递给Servlet程序使用

HttpServletRequest表示请求过来的信息

HttpServletResponse表示所有响应的信息

若需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置

输出流

字节流getOutputStream():常用于下载(传递二进制数据)

字符流getWriter():常用于回传字符串(常用)

两个流同时只能使用一个

乱码解决

方式1:

1
2
3
4
//设置服务器字符集为UTF-8:
response.setCharacterEncoding("UTF-8");
//通过响应头设置浏览器也使用UTF-8字符集:
response.setHeader("Content-Type", "text/html; charset=UTF-8");

方式2:

1
2
3
//响应头和服务器同时设置UTF-8字符集(一定要在获取流对象之前才有效)
response.setContentType("text/html; charset=UTF-8");
response.getWriter().write("Response的内容");

重定向

客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问(之前的地址可能已经被废弃)

浏览器地址会发生变化

两次请求

不共享Request域中的数据

不能访问WEB-INF下的资源

可以访问工程外的资源

过程:

  1. 客户端:http://ip:port/工程路径/response1
  2. Response1程序:
    1. 返回给客户端响应状态码:302
    2. 告知新地址:响应头Loaction
  3. 客户端:解析Response1的结果,发起新地址的请求到Response2程序

方法1:

1
2
3
4
//设置响应状态码
response.setStatus(302);
//设置响应头
response.setHeader("Location", "http://localhost:8080/JavaWeb/response2");

方法2:推荐

1
response.sendRedirect("http://localhost:8080/JavaWeb/response2");

JavaEE三层架构

Web层/视图展现层:

  1. 获取请求参数封装称为Bean对象
  2. 调用Service层处理业务
  3. 响应数据给客户端请求转发/重定向

Service业务层:

  1. 处理业务逻辑
  2. 调用持久层保存到数据库

Dao持久层:

  1. 只负责与数据库交互(CRUD操作)

分层的目的是为了解耦:降低代码的耦合度,方便项目后期的维护和升级

web层:

  • cc.mousse.web/servlet/controller

service层:

  • cc.mousse.service:Service接口包
  • cc.mousse.service.impl:Service接口实现类

Dao持久层:

  • cc.mousse.dao:DAO接口包
  • cc.mousse.dao.impl:DAO接口实现类

实体bean对象:

  • cc.mousse.pojo/entity/domain/bean:JavaBean类

测试包:

  • cc.mousse.test/junit

工具类:

  • cc.mousse.utils

JSP

java server pages,Java的服务器页面

代替Servlet程序回传html页面的数据:

  • Servlet程序回传html页面数据是一件非常繁锁的事情,开发成本和维护成本都极高

Jsp页面和html页面一样,都存放在web目录下,访问也和html页面一样

Jsp页面本质上是一个Servlet程序:

  • 第一次访问jsp页面的时,Tomcat服务器会把jsp页面翻译成为一个java源文件,并对它进行编译成为.class字节码程序
  • 它继承了HttpJspBase类,HttpJspBase类继承了HttpServlet类

语法

Page指令

修改jsp页面中一些重要的属性/行为

language:jsp翻译后是什么语言文件(暂时只支持java)

contentType:jsp返回的数据类型是什么(也是源码中response.setContentType()参数值)

pageEncoding:当前jsp页面文件本身的字符集

import:导包/类

errorPage:设置当jsp页面运行时出错,自动跳转去的错误页面路径

isErrorPage:设置当前jsp页面是否为错误信息页面,默认为false

  • 若为true可获取异常信息

session:设置访问当前jsp页面是否创建HttpSession,默认为true

extends:设置jsp翻译出的Java的直接父类

out输出流使用:

  • autoFlush:当out输出流缓冲区满了之后是否自动刷新冲级区,默认为true
  • buffer:设置out缓冲区大小,默认为8kb
  • 若缓冲区满了后不能自动刷新,则会报错

常用脚本

声明脚本:

1
<%!声明java代码%>
  • 极少使用
  • 可以给jsp翻译出来的Java类定义属性/方法/静态代码块/内部类等

表达式脚本:

1
<%=表达式%>
  • 常用

  • 在jsp页面上输出数据

  • 特点:

    • 所有的表达式脚本都会被翻译到_jspService()方法中
    • 表达式脚本都会被翻译成为out.print()输出到页面上
    • 由于翻译的内容都在_jspService()方法中,所以_jspService()方法中的对象都可以直接使用
    • 表达式脚本中的表达式不能以分号结束

代码脚本:

1
2
3
<%
java 语句
%>
  • 在jsp页面中编写我们自己需要的功能(Java语句)
  • 特点:
    • 翻译之后都在_jspService方法中
    • 由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用
    • 可以由多个代码脚本块组合完成一个完整的Java语句
    • 可以和表达式脚本一起组合使用在jsp页面上输出数据

注释

html注释:会被翻译到java源代码中,在_jspService方法里以out.writer输出到客户端

java注释:会被翻译到java源代码中

Jsp注释:可以注掉jsp页面中所有代码

内置对象

request:请求对象

response:响应对象

pageContext:JSP上下文对象

session:会话对象

application:ServletContext对象

config:ServletConfig对象

out:JSP输出流对象

page:指向当前JSP的对象

exception:异常对象(isErrorPage为true时)

域对象

pageContext:PageContextImpl类,当前jsp页面范围内有效

request:HttpServletRequest类,一次请求内有效

session:HttpSession类,一个会话范围内有效(打开浏览器访问服务器直到关闭浏览器)

application:ServletContext类,整个web工程范围内都有效(web工程不停止数据就在)

优先级:从小到大

输出

response/out:

  • response表示响应,经常用于设置返回给客户端的内容(输出)
  • out也是给用户做输出使用的
  • JSP页面所有代码执行完成的操作:
    1. out.write()的容会加载到out缓冲区
    2. response.getWriter().writer()的容会加载到response缓冲区
    3. 执行out.flush()操作,把out缓冲区的数据追加写到response缓冲区末尾
    4. 执行response刷新操作,把全部数据写给客户端
  • 由于jsp翻译之后底层源代码都使用out来进行输出,所以一般情况下统一使用out进行输出避免打乱页面输出内容的顺序

write()/print():

  • out.write():只适合输出字符串
  • out.print():可输出任意数据
    • print()方法会把数据都转换成为字符串后调用write()输出
  • 在jsp页面中可以统一使用out.print()进行输出

常用标签

静态包含:

1
<%@include file=""%>
  • 常用
  • file:指定所要包含的jsp页面的路径
  • 地址中第一个斜杠/表示为http://ip:port/工程路径/
  • 映射到代码的web目录
  • 静态包含不会翻译被包含的jsp页面
  • 静态包含把被包含的jsp页面的代码拷贝到包含的位置执行输出

动态包含:

1
<jsp:include page=“”></jsp:include>
  • page:功能与静态包含的file一样
  • 动态包含会把包含的jsp页面也翻译成为Java代码
  • 动态包含底层代码使用如下代码去调用被包含的JSP页面执行输出:
1
JspRuntimeLibrary.include(request, response, "/include/footer.jsp", out, false);
  • 动态包含可以传递参数:

    1. main.jsp会把自己的request/response/out对象传递给footer.jsp
    2. main.jsp和footer.jsp共用一个out缓冲区
    3. main.jsp先向out缓冲区写入数据
    4. 当调用被包含的JSP页面后,footer.jsp也向out缓冲区写入数据

请求转发:

1
<jsp:forward page=""></jsp:forward>

常用做法:

  1. Sevrlet程序:
    1. 获取请求参数
    2. 发SQL语句到数据库查询
    3. 保存结果到request域中
    4. 请求转发
  2. JSP页面:
    1. 从request域中获取数据
    2. 展示给客户端

Listenter监听器

JavaWeb的三大组件之一

JavaEE的规范(接口)

监听某种事物的变化,通过回调函数反馈给客户(程序)去做一些相应的处理

ServletContextListener

可以监听ServletContext对象的创建和销毁:

  • ServletContext对象在web工程启动的时候创建,在web工程停止的时候销毁

监听到创建和销毁之后都会分别调用ServletContextListener监听器的方法反馈:

  • contextInitialized(ServletContextEvent sce):在ServletContext对象创建之后马上调用,做初始化
  • contextDestroyed(ServletContextEvent sce):在ServletContext对象销毁之后调用

EL表达式

Expression Language

表达式语言

主要代替jsp页面中的表达式脚本在jsp页面中进行数据的输出(比JSP简洁)

格式:${表达式}

EL表达式输出null值:输出的是空串

JSP表达式输出null值:null字符串

主要是输出域对象中的数据:

  • 当四个域中都有相同的key的数据的时候,EL表达式会按照四个域的从小到大的顺序去进行搜索,找到就输出

输出属性

会搜寻属性对应的getXxx/isXxx方法

输出Person:${ p }

输出Person的name属性:${p.name}

输出Person的phones数组属性值:${p.phones[2]}

输出Person的cities集合中的元素值:${p.cities}

输出Person的List集合中个别元素值:${p.cities[2]}

输出Person的Map集合:${p.map}

输出Person的Map集合中某个key的值:${p.map.key3}

输出Person的age属性:${p.age}

运算

关系运算:

  • ==或eq
  • !=或ne
  • <或lt
  • >或gt
  • <=或le
  • >=或ge

逻辑运算:

  • &&或and
  • ||或or
  • !或not

算数运算:

  • -
  • /或div
  • %或mod

empty运算:

  • 判断一个数据是否为空:

    • 为空:输出true
    • 不为空:输出false
  • 为空的情况:

    • 值为null值
    • 值为空串
    • 值是Object类型数组,长度为零
    • List集合,元素个数为零
    • Map集合,元素个数为零

三元运算:

  • 表达式1 ? 表达式2 : 表达式3
  • 若表达式1的值为真,返回表达式2的值
  • 若表达式1的值为假,返回表达式3的值

点运算:

  • .点运算,可以输出Bean对象中某个属性的值

中括号运算:

  • []中括号运算,可以输出有序集合中某个元素的值
  • 可以输出map集合中key里含有特殊字符的key的值
  • map.put(“a.a.a”, “aaaValue”);
  • map.put(“b+b+b”, “bbbValue”);
  • map.put(“c-c-c”, “cccValue”);
  • ${ map[‘a.a.a’] }
  • ${ map[“b+b+b”] }
  • ${ map[‘c-c-c’] }

隐含对象

pageContext:PageContextImpl,获取JSP中的九大内置对象

1
<%=request.getScheme()%>
1
2
3
4
5
6
7
协议:${req.scheme}
服务器ip:${pageContext.request.serverName}
服务器端口:${pageContext.request.serverPort}
获取工程路径:${pageContext.request.contextPath}
获取请求方法:${pageContext.request.method}
获取客户端ip地址:${pageContext.request.remoteHost}
获取会话的id编号:${pageContext.session.id}

pageScope:Map<String,Object>,获取pageContext域中的数据

requestScope:Map<String,Object>,获取Request域中的数据

sessionScope:Map<String,Object>,获取Session域中的数据

applicationScope:Map<String,Object>,获取ServletContext域中的数据

1
${ applicationScope.key2 } 

param:Map<String,String>,获取请求参数的值

paramValues:Map<String,String[]>,获取请求参数的值(获取多值)

1
2
输出请求参数username的值:${param.username}
输出请求参数username的值:${paramValues.username[0]}

header:Map<String,String>,获取请求头的信息

headerValues:Map<String,String[]>,获取请求头的信息(获取多值)

1
2
3
输出请求头【User-Agent】的值:${header['User-Agent']}
输出请求头【Connection】的值:${header.Connection}
输出请求头【User-Agent】的值:${headerValues['User-Agent'][0]}

cookie:Map<String,Cookie> ,获取当前请求的Cookie信息

1
2
获取Cookie的名称:${cookie.JSESSIONID.name}
获取Cookie的值:${cookie.JSESSIONID.value}

initParam Map<String,String> 它可以获取在web.xml中配置的上下文参数

1
2
输出<Context-param>username的值:${initParam.username}
输出<Context-param>url的值:${initParam.url}

JSTL标签库

JSP Standard Tag Library,JSP标准标签库

一个不断完善的开放源代码的JSP标签库

EL表达式替换jsp中的表达式脚本

标签库替换代码脚本

由五个不同功能的标签库组成:

功能范围 URI 前缀
核心标签库–重点 http://java.sun.com/jsp/jstl/core c
格式化 http://java.sun.com/jsp/jstl/fmt fmt
函数 http://java.sun.com/jsp/jstl/functions fn
数据库(不使用) http://java.sun.com/jsp/jstl/sql sql
XML(不使用) http://java.sun.com/jsp/jstl/xml x

在jsp标签库中使用taglib指令引入标签库:

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

core核心库

<c:set />:往域中保存数据(使用很少)

1
<c:set scope=“session” value="abcValue"/> 
  • 同:域对象.setAttribute(key, value);

  • Scope:设置保存到哪个域

    • page:PageContext域(默认)
    • request:Request域
    • session:Session域
    • application:ServletContext域
  • var:设置key

  • value:设置值

<c:if />:if判断

  • Test:表示判断的条件(使用EL表达式输出)
1
2
3
<c:if test="${ 12 == 12 }">
<h1>12 等于 12</h1>
</c:if>

<c:choose> <c:when> <c:otherwise>:多路判断

  • 类似于switch … case break…. default

  • 只能使用使用jsp注释

  • When标签的父标签一定要是choose标签

  • <c:choose>
        <c:when test="${ requestScope.height > 190 }">
            <h2>小巨人</h2>
        </c:when>
        <c:when test="${ requestScope.height > 180 }">
            <h2>很高</h2>
        </c:when>
        <c:otherwise>
            <c:choose>
                <c:when test="${requestScope.height > 160}">
                    <h3>大于160</h3>
                </c:when>
                <c:when test="${requestScope.height > 150}">
                    <h3>大于150</h3>
                </c:when>
                <c:otherwise>
                    其他小于140
                </c:otherwise>
            </c:choose>
        </c:otherwise>
    </c:choose>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    <c:forEach />:遍历输出

    - begin:设置开始的索引

    - end:设置结束的索引

    - var:表示循环的变量(也是当前正在遍历到的数据)

    - Step:表示遍历的步长值

    - ```java
    for(var i = 1; i < 10; i+=2)
  • varStatus:表示当前遍历到的数据的状态

  • 遍历Object数组:

    • 类似于:for (Object item: arr)
    • items:遍历的数据源(遍历的集合/arr)
    • var:表示当前遍历到的数据(item)
1
2
3
4
<%request.setAttribute("arr", new String[]{"18610541354","18688886666","18699998888"});%>
<c:forEach items="${ requestScope.arr }" var="item">
${ item }<br>
</c >

文件上传/下载

上传

form标签:

  • method = post
    • get有请求长度
  • encType = multipart/form-data:
    • 表示提交的数据以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
  • input type = file

boundary:

  • 表示每段数据的分隔符
  • 由浏览器随机生成
  • 分隔符–:数据结束标记

commons-fileupload.jar

需要依赖commons-io.jar

ServletFileUpload:用于解析上传的数据

FileItem:表示每一个表单项

boolean ServletFileUpload.isMultipartContent(HttpServletRequest request): 判断当前上传的数据格式是否是多段的格式

public List parseRequest(HttpServletRequest request):解析上传的数据

boolean FileItem.isFormField():判断当前这个表单项是普通的表单项还是上传的文件类型

  • True:普通类型的表单项
  • False:上传的文件类型

String FileItem.getFieldName():获取表单项的name属性值

String FileItem.getString():获取当前表单项的值

String FileItem.getName():获取上传的文件名

void FileItem.write( file ):将上传的文件写到参数file所指向抽硬盘位置

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
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//判断上传数据是否为多段数据
if (ServletFileUpload.isMultipartContent(req)) {
//创建FileItemFactory工厂实现类
FileItemFactory fif = new DiskFileItemFactory();
//创建用于解析上传数据的ServletFileUpload工具类
ServletFileUpload sfu = new ServletFileUpload(fif);
//解析上传的数据得到每一个表单项fileItem
List<FileItem> fileItems = sfu.parseRequest(req);
for (FileItem fileItem : fileItems) {
//判断是否为普通表单项
if (fileItem.isFormField()) {
//普通表单项
System.out.println("表单项name属性值:" + fileItem.getFieldName());
//UTF-8解决乱码问题
System.out.println("表单项value属性值:" + fileItem.getString("UTF-8"));
} else {
//文件
System.out.println("表单项name属性值:" + fileItem.getFieldName());
System.out.println("上传文件的文件名:" + fileItem.getName());
fileItem.write(new File("/users/mousse/IdeaProjects/JavaEE/JavaWeb/" + fileItem.getName()));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取要下载的文件名
String downloadFileName = "GirlPlayingACello_LillaCabotPerry.jpg";
//通过ServletContext对象获取要下载的内容
ServletContext servletContext = getServletContext();
InputStream inputStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
//获取要下载的文件类型
String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
//通过响应头告诉客户端返回的数据类型
resp.setContentType(mimeType);
//通过响应头告诉客户端收到的数据用于下载使用(不然会直接显示在页面上)
//Content-Disposition:表示收到的数据如何处理
//attachment:附件
//filename:表示指定下载的文件名
resp.setHeader("Content-Disposition", "attachment; filename=" + downloadFileName);
//获取响应的输出流
OutputStream outputStream = resp.getOutputStream();
//把下载的文件内容回传给客户端
//把输入流的内容复制给输出流
IOUtils.copy(inputStream, outputStream);
}

中文乱码解决

URLEncoder:解决IE/Chrome

1
2
//URLEncoder.encode:为中文编码为%xx%xx的格式,适用于Chrome和IE,
resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("壁纸.jpg", StandardCharsets.UTF_8));

BASE64编解码:解决Firefox

1
2
3
4
5
6
7
8
9
10
11
String content = "内容";
//创建Base64编码器
Base64.Encoder encoder = Base64.getEncoder();
//编码操作
byte[] encoderBytes = encoder.encode(content.getBytes(StandardCharsets.UTF_8));
System.out.println(new String(encoderBytes, StandardCharsets.UTF_8));
//创建Base64解码器
Base64.Decoder decoder = Base64.getDecoder();
//解码操作
byte[] decoderBytes = decoder.decode(encoderBytes);
System.out.println(new String(decoderBytes, StandardCharsets.UTF_8));
  • 需要把请求头Content-Disposition: attachment; filename=中文名
    编码成为:Content-Disposition: attachment; filename==?charset?B?xxxxx?=

    • =?:表示编码内容的开始
    • charset:字符集
    • B:Base64编码
    • xxxxx:文件名Base64编码后的内容
    • ?=:表示编码内容的结束
1
resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" + Base64.getEncoder().encode("壁纸.jpg".getBytes(StandardCharsets.UTF_8)) + "?=");

使用User-Agent动态切换编码:

1
2
3
4
5
6
7
if (req.getHeader("User-Agent").contains("Firefox")) {
//Base64:适用于Firefox
resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" + Base64.getEncoder().encode("壁纸.jpg".getBytes(StandardCharsets.UTF_8)) + "?=");
} else {
//URLEncoder.encode:为中文编码为%xx%xx的格式,适用于Chrome和IE,
resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("壁纸.jpg", StandardCharsets.UTF_8));
}

一种服务器通知客户端保存键值对的技术

客户端有了Cookie后每次请求都发送给服务器

每个Cookie的大小不能超过4kb

增改查

创建:

  1. 服务器:
    1. 创建Cookie对象
    2. 通知客户端保存Cookie
  2. 客户端:
    1. 收到响应后发现有set-cookie响应头后查看自己有没有此cookie,没有就添加,有修改
1
2
3
4
5
6
7
protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建Cookie对象
Cookie cookie = new Cookie("key1", "value1");
//通知客户端保存Cookie
resp.addCookie(cookie);
resp.getWriter().write("Cookie创建成功");
}

服务器获取Cookie:Cookie[ ] req.getCookies( )

1
2
3
4
5
6
7
8
protected void getCookies(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies = req.getCookies();
for (Cookie cookie : cookies) {
//getName:返回Cookie的key
//getValue:返回Cookie的value
resp.getWriter().write("Cookie[name=" + cookie.getName() + ", value=" + cookie.getValue() + "]<br/>");
}
}

修改:

  • 方案一:
    1. 创建一个与目标Cookie的同名的Cookie对象
    2. 在构造器同时赋予新的Cookie值
    3. 调用response.addCookie( )
  • 方案二:
    1. 查找到需要修改的Cookie对象
    2. 调用setValue( )方法赋予新的Cookie值
    3. 调用response.addCookie( )

生命控制

如何管理Cookie什么时候被销毁

方法:setMaxAge( )

  • 正数:指定的秒数后过期
  • 负数:浏览器关闭后被清除,默认
  • 零:立马删除Cookie

有效路径

Cookie的path属性可以有效过滤哪些Cookie可以发送给服务器,哪些不发

通过请求的地址进行有效的过滤

例:

Session会话

Session是一个接口(HttpSession),用来维护一个客户端和服务器之间关联的一种技术

每个客户端都有自己的一个Session会话,此会话经常被用来保存用户登录之后的信息

保存在服务器端

每个会话都有一个唯一的ID值

底层基于Cookie实现

创建/获取

request.getSession( ):

  • 第一次调用:创建Session会话
  • 之后调用:获取Session会话对象

isNew( ):判断是否是刚创建出来的

getId( ):获取会话ID值

Session域数据的存取

1
2
3
4
5
6
7
8
protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().setAttribute("key1", "value1");
resp.getWriter().write("Session数据添加成功");
}
protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object key1 = req.getSession().getAttribute("key1");
resp.getWriter().write("Session获取的数据:" + key1);
}

生命控制

Session超时为客户端两次请求的最大间隔时长

在Tomcat服务器的配置文件web.xml中用来设置默认超时时长,工程中的web.xml做此配置可覆盖Tomcat的默认超时时长

1
2
3
<session-config>
<session-timeout>30</session-timeout>
</session-config>

setMaxInactiveInterval(int interval):

  • 正数:设定Session超时时长,默认30分钟
  • 负数:永不超时,极少使用

getMaxInactiveInterval( ):获取Session超时时间

invalidate( ):使当前会话立即超时无效

浏览器与Session关联技术

  • 服务器:
    1. 接收到没有Cookie的浏览器发送的请求
    2. req.getSession( )创建会话对象并存入内存中
    3. 服务器每次创建Session会话对象时都会创建一个Cookie对象,该对象的key为JSESSIONID,value为Seesion的ID值
    4. 通过响应把心创建的Session的ID值返回给客户端
  • 浏览器:
    1. 解析收到数据后创建Cookie对象
    2. 有了Cookie之后,每次请求都会把Session的ID值以Cookie的形式发给服务器
  • 服务器:
    1. req.getSession( )通过Cookie中的ID值找到之前创建好的Session对象并返回

缓存由最后的资源名和参数组成

Filter过滤器

JavaWeb三大组件之一(三大组件:Servlet程序,Listener监听器,Filter过滤器)

是JavaEE的规范(接口)

作用:拦截请求(权限检查,日记操作,事务管理),过滤响应

生命周期包含的方法

  1. 构造器方法,在web工程启动的时候执行(Filter已经创建)
  2. init初始化方法,在web工程启动的时候执行(Filter已经创建)
  3. doFilter过滤方法,每次拦截时就会执行
  4. destory销毁,停止web工程时就会执行(停止web工程也会销毁Filter过滤器)

FilterConfig类

Filter过滤器的配置文件类

Tomcat每次创建Filter时也会同时创建一个FilterConfig类,这里包含了Filter配置文件的配置信息

作用是获取filter过滤器的配置内容:

  • 获取Filter的名称filter-name的内容
  • 获取在xml中配置的init-param初始化参数
  • 获取ServletContext对象

FilterChain

过滤器链

多个Filter过滤器执行顺序由web.xml中的顺序决定

doFliter( )方法:

  • 如果有Filter:执行下一个Filter过滤器
  • 如果没Filter:执行目标资源

多过滤器执行特点:

  • 所有过滤器和目标资源默认都执行在同一个线程中
  • 多个过滤器共同执行时都使用同一个Request对象

拦截路径

1
<url-pattern>/target.jsp</url-pattern>
1
<url-pattern>/target/*</url-pattern>
  • 后缀匹配:请求地址必须以.xxx结尾才会拦截到
1
<url-pattern>*html</url-pattern>

Filter过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在

ThreadLocal

可以解决多线程的数据安全问题

可以给当前线程关联一个数据(可以是普通变量/对象/数组/集合)

ThreadLocal操作都使用同一个Connection连接对象的前提是所有操作必须在同一个线程中完成

特点:

  • 可以为当前线程关联一个数据(可以像Map一样存取数据,key为当前线程)
  • 每个ThreadLocal对象只能为当前线程关联一个数据,如果要为当前线程关联多个数据就需要使用多个ThreadLocal对象实例
  • 每个ThreadLocal对象实例定义的时候一般都是static类型
  • ThreadLocal中保存数据在线程销毁后会由JVM虚拟自动释放
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
public class JdbcUtils {
private static DruidDataSource dataSource;
private static ThreadLocal<Connection> connection = new ThreadLocal<>();

static {
try {
Properties properties = new Properties();
properties.load(JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//创建数据库连接池
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}

public static Connection getConnection() throws SQLException {
Connection conn = connection.get();
if (conn == null) {
try {
//从数据库连接池中获取连接
conn = dataSource.getConnection();
//保存到LocalThread对象中,供后面的JDBC操作使用
connection.set(conn);
//设置为手动提交
conn.setAutoCommit(false);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return conn;
}

/**
* 提交事务并关闭连接
*/
public static void commitAndClose() {
Connection conn = connection.get();
if (conn != null) {
//之前使用过连接操作数据库
try {
//提交事务
conn.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
//关闭连接释放资源
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
//一定要执行remove操作,否则会出错
//Tomcat服务器底层使用线程池技术
connection.remove();
}

/**
* 回滚事务并关闭连接
*/
public static void rollBackAndClose() {
Connection conn = connection.get();
if (conn != null) {
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
connection.remove();
}

JSON

JavaScript Object Notation,一种轻量级(与XML比较)的数据交换格式,易于人阅读和编写/机器解析和生成

采用完全独立于语言的文本格式,很多语言都提供了对 json 的支持(包括 C, C++, C#, Java, JavaScript, Perl, Python) 使JSON成为理想的数据交换格式

定义

由键值对组成,且由花括号(大括号)包围

每个键由引号引起来,键和值之间使用冒号进行分隔

多组键值对之间进行逗号进行分隔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var jsonObj = {
"key1": 123,
"key2": "abc",
"key3": true,
"key4": [1, "a", true],
"key5": {
"key5_1": 123,
"key5_2": "value5_2",
},
"key6": [
{
"key6_1_1": "value6_1_1",
"key6_1_2": "value6_1_2"
},
{
"key6_2_1": "value6_2_1",
"key6_2_2": "value6_2_2"
}
]
}

访问

JSON本身是一个对象,其中的key可理解为是对象中的一个属性,访问JSON与访问对象的属性一样:json对象.key

1
2
3
4
5
6
7
8
9
10
11
12
13
alert(typeof (jsonObj));//object json就是一个对象 alert(jsonObj.key1); //12
alert(jsonObj.key2); // abc
alert(jsonObj.key3); // true alert(jsonObj.key4);// 得到数组[11,"arr",false]
// json 中 数组值的遍历
for (var i = 0; i < jsonObj.key4.length; i++) {
alert(jsonObj.key4[i]);
}
alert(jsonObj.key5.key5_1);
alert(jsonObj.key5.key5_2);//key5_2_value alert( jsonObj.key6 );// 得到 json 数组
// 取出来每一个元素都是 json 对象
var jsonItem = jsonObj.key6[0];
// alert( jsonItem.key6_1_1 );
alert(jsonItem.key6_1_2); //key6_1_2_value

常用方法

  1. 对象的形式存在:
    • 称为JSON对象
    • 操作JSON中数据时使用
    • JSON.parse( ):JSON字符串 → JSON对象
  2. 字符串的形式存在:
    • 我们叫它JSON字符串
    • 在客户端和服务器之间进行数据交换的时使用
    • JSON.stringify( ):JSON对象 → JSON字符串
1
2
3
4
5
6
// 把 json 对象转换成为 json 字符串
var jsonObjString = JSON.stringify(jsonObj); // 特别像 Java 中对象的 toString alert(jsonObjString)
// 把 json 字符串。转换成为 json 对象
var jsonObj2 = JSON.parse(jsonObjString);
alert(jsonObj2.key1);// 12
alert(jsonObj2.key2);// abc

Java中的使用

JavaBean与JSON

1
2
3
4
5
6
7
8
9
Person personBean = new Person(1, "PZ");
//创建Gson实例
Gson gson = new Gson();
//使用toJson方法把Java对象转为JSON字符串
String personJsonString = gson.toJson(personBean);
System.out.println(personJsonString);
//fromJson方法把JSON字符串转为Java对象
Person person = gson.fromJson(personJsonString, Person.class);
System.out.println(person);

List与JSON

1
2
3
4
5
6
7
8
9
10
11
List<Person> personList = new ArrayList<>();
personList.add(new Person(1, "AB"));
personList.add(new Person(2, "CD"));
//创建Gson实例
Gson gson = new Gson();
//使用toJson方法把List集合转为JSON字符串
String personListJsonString = gson.toJson(personList);
System.out.println(personListJsonString);
//fromJson方法把JSON字符串转为List集合
List<Person> person = gson.fromJson(personListJsonString, new TypeToken<List<Person>>(){}.getType());
System.out.println(person);

Map与JSON

1
2
3
4
5
6
7
8
9
10
Map<Integer, Person> personMap = new HashMap<>();
personMap.put(1, new Person(1, "AB"));
personMap.put(2, new Person(2, "CD"));
//创建Gson实例
Gson gson = new Gson();
//使用toJson方法把Java对象转为Map集合
String personMapJsonString = gson.toJson(personMap);
System.out.println(personMapJsonString);
//fromJson方法把JSON字符串转为Map集合
HashMap<Integer, Person> person = gson.fromJson(personMapJsonString, new TypeToken<Map<Integer, Person>>(){}.getType());

AJAX

Asynchronous Javascript And XML(异步JavaScript和XML)

是指一种创建交互式网页应用的网页开发技术

是一种浏览器通过JS异步发起请求,局部更新页面的技术

AJAX请求的局部更新,浏览器地址栏不会发生变化局部更新不会舍弃原来页面的内容

jQuery与AJAX

常用方法:

$.ajax:

  • url:表示请求的地址
  • type:表示请求的类型 GET 或 POST 请求
  • data:表示发送给服务器的数据,两种格式
    1. name=value&name=value
    2. {key:value}
  • success:请求成功,响应的回调函数
  • dataType:响应的数据类型,常用的数据类型
    • text:纯文本
    • xml:XML数据
    • json:JSON对象
1
2
3
4
5
6
7
8
9
10
11
$("#ajaxBtn").click(function () {
$.ajax({
url: "http://localhost:8080/java_web/ajaxServlet",
data: "action=jQueryAjax",
type: "GET",
success: function (data) {
alert("服务器返回的数据:" + data);
},
dataType: "text"
});
});
  • $.get/$.post:
    • url:请求的url地址
    • data:发送的数据
    • callback:成功的回调函数
    • type:返回的数据类型
1
2
3
$.get("http://localhost:8080/java_web/ajaxServlet", "action=jQueryGet", function (data) {
$("#msg").html("Get\t\t编号:" + data.id + "\t姓名:" + data.name);
}, "json");
  • $.getJSON:
    • url:请求的url地址
    • data:发送的数据
    • callback:成功的回调函数
1
2
3
$.getJSON("http://localhost:8080/java_web/ajaxServlet", "action=getJson", function (data) {
$("#msg").html("getJson\t\t编号:" + data.id + "\t姓名:" + data.name);
});
  • 表单序列化:serialize( )
    • 可以把表单中所有表单项的内容都获取到,并以name=value&name=value的形式进行拼接

i18n

Internationalization(以I开头,以N结尾,中间是18个字母)

同一个网站可以支持多种不同的语言,以方便不同国家,不同语种的用户访问

三要素:

  1. RescourceBundle资源包:

    • RescourceBundle.getBundle( ):根据给定的baseName和Locale读取相应的配置文件得到文字信息

    • RescourceBundle.getString(key):得到不同国家的语言信息

  2. Locale对象:表示不同时区,位置,语言

    • zh_CN:中国,中文
    • en_US:英文,美国
  3. Properties属性配置文件:

    • 国际化配置文件命名规则:baseName_locale.properties

MVC

将软件代码拆封成组件单独开发,组合使用(未为了解耦)

Model模型:将与业务逻辑相关的数据封装为具体的JavaBean类,其中不参杂任何关于数据处理相关代码

  • JavaBean/domian/entity/pojo

View视图:只负责数据和界面显示,不接受任何与显示无关的代码

  • JSP/HTML

Controller控制器:只负责接收请求,调用业务层的代码处理请求后派发一个页面,是调度者的角色

  • Servlet转到/重定向到某个页面

JavaWeb
http://docs.mousse.cc/JavaWeb/
作者
Mocha Mousse
发布于
2025年5月26日
许可协议