1. XML文档的作用和解析
1. XML的基本概述:
XML的主要是用来存储一对多的数据,另外还可以用来当做配置文件存储数据。XML的表头如下:
<?xml version='1.0' encoding='UTF-8' ?>
使用代码获取此项目在电脑中的绝对路径方法如下所示:
URL path = 类名.class.getResource("/");
使用此方法能获取此项目的scr目录在电脑中的绝对地址。
2. XML约束的注意事项:
后缀名为.xsd的约束文档中的关键内容
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
//标准的名称空间
targetNamespace='http://www.itheima.com'
//将该schema文档绑定到http://www.itheima.com名称空间>
后缀名为.xml的XML文档中的关键内容
<itheima:书架 xmlns:itheima="http://www.itheima.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.itheima.com book.xsd">
如上加粗所示,为在XML文档中引用约束文档中的约束,使用名称空间引用。
3. 解析XML文件
XML中有两种常用的解析方式,分别是DOM解析和SAX解析,由于DOM解析功能强大,所以一般使用DOM下的DOM4J来解析XML文档。DOM解析是将整棵树一口气全部加载到内存当中, 我们可以非常方便的操作任意的标签和属性.但是, 如果整棵树特别大的时候, 会出现内存溢出的问题。
DOM4J的解析步骤如下:
//1.创建XML解析器
SAXReader saxReader = new SAXReader();
//2.使用解析器加载XML文档数据,并获取Document对象
Document document = saxReader.read(new File("person.xml"));
//3.根据document对象获取xml文档根节点
Element rootElt = document.getRootElement();
//输出根节点对象
System.out.println(rootElt);
DOM4J解析中的常用方法如下:
element.elmennts(),获取父标签所有的子元素对象列表
element.element(标签名),根据指定的标签名获取元素标签的直接子元素对象
element.elements(标签名),父标签根据指定标签名获取子元素标签列表对象
element.elementText(标签名),父标签根据指定标签名直接获取子标签文本
Element.attributes(),后期标签所有属性对象列表
Element.attribute(属性名),获取指定的属性对象
Element.attributeValue(属性名),直接获取指定的属性的值
4. 使用代码创建XML文件
创建XML中需注意如下问题:
//紧凑型格式,建议在企业工作开发中使用
OutputFormat format1 = OutputFormat.createCompactFormat();
//漂亮的格式,建议学习测试的时候使用
OutputFormat format2 = OutputFormat.createPrettyPrint();
使用代码创建XML文档有2种方式,一种是读取一个XML文件获取document对象,再使用这个document对象进行XML的创建,还有一种是构建一个全新的document对象,再进行写出,第二种的实现代码如下所示。
//1.创建Document对象 Document document = DocumentHelper.createDocument(); //1.1.设置文档的编码 document.setXMLEncoding("UTF-8"); //2.构建Document对象数据 //2.1.构建根节点 Element rootElt = document.addElement("books");//addElement方法返回添加的标签节点对象 //2.2.构建子节点book Element bookElt =rootElt.addElement("book"); //2.2.创建子节点属性id bookElt.addAttribute("id", "001"); //2.3.构建子子节点数据 bookElt.addElement("title").setText("《java开发实战》"); bookElt.addElement("price").setText("88"); bookElt.addElement("pubDate").setText("2016年12月27日"); //3.创建文件输出流 FileOutputStream out = new FileOutputStream(new File("books.xml")); //4.创建XML文件写出器 //4.1.创建格式化器 OutputFormat format1 = OutputFormat.createCompactFormat();//紧凑型格式,建议在企业工作开发中使用 OutputFormat format2 = OutputFormat.createPrettyPrint(); //漂亮的格式,建议学习测试的时候使用 XMLWriter writer = new XMLWriter(out,format2); //5.xml文件写出 writer.write(document); //6.关闭流资源 writer.close(); System.out.println("books.xml生成成功"); |
2. HTML的基本标签
1. <meta charset="utf-8" /> 指定网页的字符集
2. <meta name="keywords" content="Java培训,Android培训,安卓培训"> 告诉搜索引擎,当前网页的搜索关键字
3. <meta name="Description" content="描述信息..."/> 用于对整个网页信息概要描述的
4. <h1></h1> 标题标签 h1~h6,数字越小,字越大。如h1代表1级标题。
align属性:标题对齐的方式。left,向左对齐,默认;right,向右对齐;center,居中对齐。
5. <hr size="7" width="400" color="red" align="center"/> 水平线标签,可以设置大小,宽度,颜色和对其方式。
6. <font color="blue" size="30" face="楷体">内容</font> 用于设置字体、大小、颜色。HTML5中这个标签已经淘汰
7. <strong></strong> <b></b> 这两个标签的功能完全相同,都是用于字体的加粗
8. <i></i> 用于将字体设置为斜体
9. <br/> 换行,没有主体的标签
10. <p title="段落"> 段落内容 </p> 用来表示一个段落,段落之间有段间距,段前没有首行缩进。
title属性:当鼠标移到段落上面的时候,会显示提示文字。
11. 2<sup>3</sup> H<sub>2</sub>O sup和sub 上标和下标标签
12. <pre>内容</pre> 在网页上原样输出一段纯文本,例:在网页中原样输出一段Java代码。
13. 有序标签
<ol type="A"> <li>早餐</li> </ol> |
<ol></ol>: 有序列表的容器,会自动产生编号。orderly-label <li></li>: 列表中的每一项 type属性:默认取值为数字编号,可以取字母编号和罗马数字编号。 |
14. 无序标签
<ul type="disc"> <li>早餐</li> </ul> |
<ul></ul>:无序列表的容器,会根据type的值产生样式。unorderly-label type属性:(disc:实心圆)(circle:空心圆)(square:实心正方形) |
15. 项目列表,后期主要用于网页的布局
<dl> <dt>游戏列表</dt> <dd>扫雷</dd> <dd>空中接龙</dd> </dl> |
dl: 列表容器 dt: 列表标题 dd:列表描述 describe |
16. <span>内容</span> 行内标签(内联标签),只是在逻辑上将一段文字分成不同的部分。一般用于对部分文字的操作。
17. <div>内容</div> 块标签,在逻辑上将网页分成不同的部分。每个div会单独占一行。
18. 网页上显示的特殊字符:(<:<)(>:>)(版权符号:©)(人民币符号:¥)(空格: )
19. <a href="http://www.itcast.cn" target="_self">传智播客</a>
(1) 用于在网页上创建一个链接,点击某个文字跳转到其它页面去。
href为指定网页的地址;target取值:_self 在当前网页中打开地址,默认值,_blank:在新的页面中打开地址。
(2) 打开发送邮件的客户端,给指定的邮件发邮件。如:FoxMail。
例:<a href="mailto: newboy@itcast.cn">给我发邮件</a>
(3) 作为锚点使用,当一个网页特别长时,或者想要跳转到网页中不同的位置时(包括其他网页),可以使用锚点
定义锚点:<a name=”名字”>文字</a>
跳转时href的写法:<a href=”#名字”>文字</a>
20. <img src="img/girl1.jpg"/> 图像标签:用于在网页上显示图片
src:指定图片的地址 width:指定图片宽 height:指定图片高,可以只指定一个,另一个属性按等比缩放
alt:如果图片丢失,用于替代图片的文字 title:当鼠标移到图片上面的时候,出现的信息提示
21. 表格标签
<table border="1px" style="border-collapse: collapse;text-align: center;" width="25%" align="center"> <caption>学生成绩表</caption> <thead> <tr> <th>编号</th> <th>姓名</th> <th>性别</th> <th>成绩</th> </tr> </thead> <tr> <td>1</td> <td>潘金莲</td> <td>女</td> <td>89</td> </tr> <tr> <td>总成绩</td> <td colspan="3">788</td> </tr> </table> |
表格的结构:
常用的表格属性:
|
22. <frameset rows="30%,50%,*"><frameset> <frame src="main.html" name="main" />
框架标签可以将一个页面划分成N个组成部分,每个组成部分都是一个独立html网页。框架标签主要用于将多个网页组合成一个网页显示,这种功能叫栏式布局,(一个页面可以分成多个栏)。上述前段代码将整个页面分成了3个部分,上面一部分占百分之30,中间一部分占百分之50,剩余的是下面部分。
上述后段代码为将前段代码分成的3部分的具体显示,frameset中不仅可以放frame,还可以放frameset。
注意:frameset框架标签所在的页面不能有body标签,必须将body删除掉。
属性名 |
作用 |
rows |
每一行占多高,*星号表示占用剩下所有的空间。可以用百分比或者px像素点表示。 |
cols |
每列占多宽,规则同上。 |
src |
当前框架显示的网页地址 |
name |
当前框架的名字 |
23. 表单标签,如果浏览器端要将数据发送给服务器,使用表单标签封装所有的数据发送给服务器
<form action="https://www.baidu.com" method="post"> </form>
action属性:要提交给服务器的地址URL。 method:提交的方法,取值:get和post。
(1)get和post方法的区别:
|
GET方法 |
POST方法 |
服务器得到数据的方式 |
以请求头的方式发送数据 |
以请求体的方式发送数据 |
地址栏 |
在地址栏上显示发送的数据 |
在地址栏上看不到数据的 |
大小 |
限制为1K的大小 |
在理论上没有限制,如文件上传 |
安全性 |
相对比较差 |
相对比较高 |
(2)使用表单标签的注意事项:
A.表单元素数据能提交给服务器端的前提:第一个是必须有action(服务器地址),第二个是要有submit(进 行提交的触发),第三个是需要提交的每个表单元素数据必须有name属性,服务器根据name识别表单元 素数据,编写时要给每个表单元素设置name属性。
B.提交数据要注意的表单元素:
表单元素提交的数据就是表单元素value属性,所有的表单默认都有value,只有如下两个没有:
单选框,必须要设置value属性;多选框,必须要设置value属性。
C. 表单标签中需注意的属性:
placeholder="请输入用户名"属性:会在text或者password类型的标签中插入提示信息。
style="60%":表单元素中也可以在样式中设置宽度。
(3)表单标签中的元素:
表单项 |
代码 |
属性 |
说明 |
文本框 |
<input type=”text”/> |
name: 文本框的名字 value: 文本框的默认值 readonly: 文本框只读 disabled: 不可用 |
用户可以输入单行文本的表单元素 |
密码框 |
<input type="password"/> |
输入的文本不可见 |
|
单选框 |
<input type=”radio”/> |
checked:默认选中 |
同一组单选框名字要相同 |
复选框 |
<input type="checkbox"/> |
checked:默认选中 |
同一组复选框名字要相同,在服务器上可以通过名字得到一组值 |
下拉列表 |
<select> <option>一项</option> </select> |
option:表示其中一项 multiple:多选,按ctrl或shift可以多选 value: 其中一项的值 |
|
隐藏表单域 |
<input type=”hidden”/> |
在表单上不可见,可以将数据提交给服务器。 |
|
单行文本域 |
<input type=”file”/> |
上传文件给服务器 |
|
多行文本域 |
<textarea rows="5" cols="50"></textarea> |
rows: 行数 cols: 列数 |
主体部分是文本的内容 |
提交按钮 |
<input type=”submit”/> |
value: 指定按钮的文本 |
提交表单 |
重置按钮 |
<input type=”reset”/> |
重置表单的数据 |
|
普通按钮 |
<input type=”button”/> <button> |
普通按钮 |
|
图片按钮 |
<input type=”image”/> |
src: 指定图片的地址 x和y,表示点击图片的位置 |
功能与submit一样,用于提交表单,外观是一张图片 |
3. CSS
1. CSS的概述:
层叠样式表(英文全称:Cascading Style Sheets),也是一遍代码言语,是专门用于操作html元素进行效果展现的。html控制样式通过添加标签逐个控制非常麻烦,然而css不需要添加任何标签就可以灵活简洁的控制样式。
CSS的功能更加强大,可以实现HTML中一些标签不能实现的功能,CSS专门用来进行装饰,HTML专门用来创建结构,通常我们会将CSS做成一个单独的文件存在,降低耦合度。
2. CSS的编写方式(三种):
编写方式 |
格式 |
特点 |
内部方式 |
<style type="text/css"> a{color: red;} </style> |
使用<style></style>标签括起来,一个网页内可以有多个style标签;type="text/css",以文本代码方式存在的css代码,这个可以不写,但是建议写上,为了各个浏览器兼容性 |
内嵌方式 |
<a href="#" style="color: green;">新闻标题2</a><br /> |
直接将css代码写在html标签里面,以style属性方式存在 |
外部方式(推荐) |
特点:css代码写在外部的文件中,文件的扩展名.css。 实现步骤:在外部创建一个css文件,编写样式代码;再在当前网页引用外部的css文件。 格式:<link rel="stylesheet" type="text/css" href="外部样式文件路径"/>。 优点:代码分离,html代码与css代码分离;复用性强。 |
3. CSS的使用:
在HTML中使用CSS的优先级:使用CSS时,均是按照就近原则使用,哪个离调用的HTML标签进就使用哪个。
CSS的注释:/*注释内容*/,CSS中的注释与java中的多行注释一模一样。
CSS的学习方式:分为2步进行,第一步为选择出要进行样式控制的html元素---css选择器;第二步为对html元 素进行样式操作---css样式(常用样式与高级样式)。
4. CSS选择器
(1) 基本选择器
具体选择器名 |
格式 |
代码 |
标签选择器 就是根据标签名称选择要操作的html元素 |
标签名{ 样式属性1:样式属性值1; 样式属性2:样式属性值2; …… } |
a{color:red;} /*操作所有a标签的字体颜色为红色*/ p{color:yellow;} /*操作所有p标签的字体颜色为黄色*/ |
类选择器 可以对html元素进行分类控制样式,给每种类型定义一个类选择器,之后html元素通过class=”类型名字”使用 |
.类型名字{ 样式属性1:样式属性值1; 样式属性2:样式属性值2; …… } |
.one{ font-size: 30px; color: green; /*在类选择器里面设置的字体颜色*/ } |
ID选择器 对页面上指定一个元素操作样式。html标签都有一个id属性,这个id属性值必须唯一,用于区别同名标签。 |
#ID值 { 样式属性1:样式属性值1; 样式属性2:样式属性值2; …… } |
#new5{ color:yellow; } <a href="" id="new5">新闻标题5</a><br> |
基本选择器总结:ID>类>标签,还是使用就近原则来使用选择器。
(2) 扩展选择器(复合选择器)
扩展选择器就是将多个基本选择器进行组合之后就是复合选择器,一个复合选择器是由多个基本选取组成的。扩展选择器中包括(并集),(交集),(层级),(属性),(伪类)选择器。
作用 |
格式 |
代码 |
并集选择器 同时操作多个选择器拥有一样的样式,html元素只要符合其中一个选择器就可以应用到样式。选择器中以逗号隔开。 |
选择器名称1, 选择器名称2…{ 样式属性1:样式属性值1; 样式属性2:样式属性值2; …… } |
/*同时设置a标签,p标签的字体大小为30px*/ a,p{ font-size: 30px; } |
交集选择器 选择的html元素需要同时具有多个选择器才会应用到样式。选择器之间没有任何分隔符。 |
选择器名称选择器名称{ 样式属性1:样式属性值1; 样式属性2:样式属性值2; …… } |
/*设置span标签并且类样式是oushuA的html元素的字体大小为30px*/ span.oushuA{ font-size: 30px; } |
层级选择器 操作指定层级结构的html元素样式。选择器名称之间使用“ ”空格隔开。 |
选择器名称 选择器名称……{ 样式属性1:样式属性值1; 样式属性2:样式属性值2; …… } |
/*操作div里面span标签的字体颜色为蓝色样式*/ div span{ color:blue; } |
属性选择器 根据html元素属性选择html元素设置样式。属性使用"[]"括起来。 |
选择器名称[属性名=“属性值”]{ 样式属性1:样式属性值1; 样式属性2:样式属性值2; …… } |
/*设置input标签属性type="text"的html元素背景颜色为红色*/ input[type="text"]{ background: red; } |
(3) 伪类选择器(操作html元素不同状态下样式效果)
任何html元素都有如下状态:未访问过状态;已访问过状态;鼠标悬浮状态;鼠标按下状态。
格式 |
代码 |
选择器名称:状态行为{ 样式属性1:样式属性值1; 样式属性2:样式属性值2; …… } 状态行为示例格式如下: a:link {color: yellow}/* 未访问的链接 */ a:visited {color:blue} /* 已访问的链接 */ a:hover {color: red}/* 鼠标移动到链接上 */ a:active {color: black} /* 选定的链接 */ |
/*未访问状态:显示红色*/ a:link { color:red; } /*已访问状态:显示灰色*/ a:visited{ color: gray; } /*鼠标悬浮状态:显示蓝色*/ a:hover{ color: blue; } /*激活状态:显示绿色*/ a:active{ color: green; } |
注意:在 CSS 定义中,a:hover 必须被置于 a:link 和 a:visited 之后,才是有效的; a:active 必须被置于 a:hover 之后,才是有效的。
5. 常用样式:
(1) 边框:
属性 |
描述 |
简写属性,用于把针对四个边的属性设置在一个声明。 |
|
用于设置元素所有边框的样式,或者单独地为各边设置边框样式。 |
|
简写属性,用于为元素的所有边框设置宽度,或者单独地为各边边框设置宽度。 |
|
简写属性,设置元素的所有边框中可见部分的颜色,或为 4 个边分别设置颜色。 |
注意:必须把单边属性放在简写属性之后。因为如果把单边属性放在 border-style 之前,简写属性的值就会覆盖单边值 none。
style中的常用属性有:solid(实线), dotted(点线), dashed(虚线), double(双线)。
width一般使用px,color可以直接使用英语单词描述。
(2) 背景:
属性 |
描述 |
属性 |
简写属性,作用是将背景属性设置在一个声明中。 |
|
|
背景图像是否固定或者随着页面的其余部分滚动。 |
默认值是 scroll,会滚动,fixed属性是不滚动的。 |
|
设置元素的背景颜色。 |
直接使用英语单词表示 |
|
把图像设置为背景。 |
需统计url值 |
|
设置背景图像的起始位置。 |
10px,center,百分比均可 |
|
设置背景图像的平铺方式。 |
repeat-x,repeat-y,no-repeat |
(3) 文本
属性 |
描述 |
设置文本颜色 |
|
设置文本方向。 |
|
设置行高。 |
|
设置字符间距。 |
|
对齐元素中的文本。 |
|
向文本添加修饰。 |
|
缩进元素中文本的首行。 |
|
text-shadow |
设置文本阴影。CSS2 包含该属性,但是 CSS2.1 没有保留该属性。 |
控制元素中的字母。 |
(4) 字体
属性 |
描述 |
简写属性。作用是把所有针对字体的属性设置在一个声明中。 |
|
设置字体系列。 |
|
设置字体的尺寸。 |
|
设置字体风格。 |
|
以小型大写字体或者正常字体显示文本。 |
|
设置字体的粗细。 |
(5) 列表
属性 |
描述 |
简写属性。用于把所有用于列表的属性设置于一个声明中。 |
|
将图象设置为列表项标志。 |
|
设置列表中列表项标志的位置。 |
|
设置列表项标志的类型。 |
6. 高级样式:
(1) 浮动属性:
设置浮动属性 |
清除浮动属性 |
Div { /*设置左浮动属性*/ float: left; } |
div { /*清除左侧浮动*/ clear: left; } |
left:左浮动;right:右浮动;none:没有,默认。 |
left:清除左浮动;right:清除右浮动;both:左右浮动都清除; |
当将一个或几个div设置成浮动后,再在下方取消浮动,再设置大量文字,会发现文字会环绕上面的div,形成文字环绕的效果。
(2) 盒子模型:
介绍:css认为html的标签每个标签都是盒子,标签的嵌套,css认为就是盒子嵌套。所以css认为标签之间 关系可以使用盒子模型来解决。
作用:盒子模型就是用于解决html标签与标签里面文本距离和标签与直接相邻标签距离的。
内边距:用于设置标签与标签里面内容的距离,内边距会改变当前标签的大小。
外边距:用于设置标签与直接相邻标签的距离。
外边距四边 |
属性名 |
内边距四边 |
属性名 |
margin-top |
顶部外边距 |
padding-left |
左内边距 |
margin-bottom |
底部外边距 |
padding-right |
右内边距 |
margin-left |
左边外边距 |
padding-top |
顶部内边距 |
margin-right |
右边外边距 |
padding-bottom |
底部内边距 |
div1{ |
4. JavaScript基础
1. JavaScript基本概述
(1) JavaScript和Java的不同
Java |
JavaScript |
|
出品公司 |
Sun |
网景 |
面向对象 |
完全面向对象(封装、继承、多态) |
基于对象,不完全面向对象 |
运行方式 |
编译型 ,生成中间文件,字节码,运行字节码 |
解释型语言,不会生成中间文件,解释一行就运行一行。 |
数据类型 |
强类型语言,数据类型必须一样 int num=”abc”; 错误 |
弱类型语言,不同的数据类型之间可以赋值 var num=5; var num=”abc”; 正确 |
(2) JavaScript三大组成部分:
ECMA Script:一种脚本语言规范,构成了JS的核心语法基础。
BOM:Browser Object Model 浏览器对象模型,用来操作浏览器上的各种对象。
DOM:Document Object Model 文档对象模型,用来操作网页中的各种元素。
(3) JavaScript的引入方式:
内部方式:写在HTML的内部,所有的JS代码要写在script标签中。建议写在html的末尾。
内嵌方式:写在html标签的属性里面写js代码
外部方式:写在HTML的外部,以JS文件的方式存在。通过script标签导入,以后比较常用。同上。
2. JavaScript中的数据类型和函数:
(1) 数据类型:
数据类型 |
关键字 |
typeof操作符 |
数值类型 |
number (包含整数和小数) |
作用:判断一个变量的数据类型; 写法:typeof(变量名) 或 typeof 变量名; 返回值:这个变量的数据类型的字符串形式; null与undefined的区别:null是一个值为空的对类型,undefined是一个未定义的类型。 |
字符串类型 |
string(包含了字符和字符串) |
|
布尔类型 |
boolean (true/false) |
|
对象类型 |
object 代表一个对象 |
|
未定义类型 |
undefined 变量没有初始化 |
(2) 全局函数:
parseInt():将字符串类型转成整形;
parseFloat():将字符串类型转成浮动型;
3. JavaScript中的流程控制语句:
(1) JS中的调试(JS是在浏览器中进行调试),调试步骤如下:
a.打开浏览器,打开开发者工具(F12),任何浏览器都有开发者工具 b.开发者工具中点击“source”并点击你要调试的页面 c.单击代码左侧边框位置设置断点,刷新网页(重新运行网页),就会程序运行到断点位置 d.逐行调试,观察变量运行的结果,观察发现c变量是undefined未定义,所以结果错误了 e.如果想观察某个表达式的值,可以在右侧watch里面点击“+”复制表达式到里面,观察结果 f.调试完成,点击跳过断点 |
(2) JS中的判断(JS中的判断可以不为boolean类型):
数据类型 |
为真 |
为假 |
数据类型 |
为真 |
为假 |
number |
非0 |
0 |
undefined |
为假 |
|
string |
非空字符串 |
空字符串 |
object |
非null |
null |
(3) JS中使用switch函数时,case后面可以写常量,也可以写变量,还可以写表达式,但是在case后面使用表达式时,前提switch后面要写成switch(true)。
(4) Java中的while,do-while,for,增强for在JS中都能使用,但增强for使用变化如下:
for( var 数组索引或对象的属性名 in 数组或对象){ /*循环体*/ }
JS中访问对象的属性名有2中方式:js对象.属性和js对象["属性名"]。
4. JavaScript中的函数:
(1) 函数的种类:
- 命名式函数:function 函数名(形成) { //函数体代码 }
- 匿名式函数:var 变量 = function(形参){ //函数体代码 };
调用函数时,直接调用函数名或者变量名传入实参即可。例:函数名/变量函数名(实参);
(2) 注意:
函数不需要定义返回值,有返回值在函数体内直接使用return返回即可.
js函数中不存在方法重载,在js里面同名方法都是下面覆盖上面的
js调用函数传递实参的原理是会将实参数据封装到一个arguments数组里,再由数组按照次序给每个形参赋值
5. BOM对象(常用windos,location,history这三个对象):
(1) Windos(浏览器窗口)对象中的常用方法:
方法名 |
作用 |
alert() |
弹出一个信息框,只有一个确认按钮。 |
string prompt(“提示信息”, “默认值”) |
弹出一个输入框,返回用户输入的字符串。如果点取消,得到一个null。 |
boolean confirm("提示信息") |
弹出一个信息框,有确认和取消2个按钮,点确认返回true,点取消false |
eval("") |
直接执行括号中字符串中的JS代码 |
parseInt() |
把字符串转成整数,如果是小数会取整 |
parseFloat() |
把字符串转成小数,如果不能转换。返回NaN=Not a Number |
isNaN() |
判断是否非数字,非数字返回true,数字返回false |
window.setTimeout(“函数名”, 时间) |
函数名:要调用的函数 |
var 计时器= window.setInterval(“函数名”, 时间) |
函数名:要调用的函数 |
clearInterval(计时器) |
清除Interval的计时器 |
clearTimeout(计时器) |
清除Timeout的计时器 |
(2) location(地址栏对象)中的方法
location.href:可以得到浏览器访问的地址(右边)或者给浏览器地址赋新的值,相当于页面的跳转(左边)
reload()方法:重新加载当前的页面,相当于刷新当前的网页。
(3) history(历史记录对象)中的方法
方法 |
作用 |
forward() |
相当于浏览器上的前进按钮 -> |
back() |
相当于浏览器上后退按钮 <- |
go(正整数/负整数) |
正数相当于前进,负数相当于后退。如:-2,相当于后退2个页面 |
6. DOM对象
(1) DOM中的常用方法如下:
方法名 |
作用 |
document.getElementById("id") 方法 |
通过元素的id得到元素对象 |
innerHTML属性 |
获取/设置元素的HTML内容 |
innerText 属性 |
获取/设置元素的纯文本内容 |
(2) DOM中还常用Date对象,Date date = new Date(); 可以获取当前的系统时间。
getFullYear():获取年份; getMonth():获取月份(0-11); getDate():得到日期;
getHours():得到小时(0-23); getMinutes():得到分(0-59); getSeconds():得到秒; getMilliseconds():得到毫秒; getTime():得到1970-1-1到现在之间的毫秒数;
toLocaleString():将日期转成当地格式的日期; getDay():得到一周中的第几天,0-6,0表示周日,1周一;
5. JavaScript提高
1. JS中事件的处理
事件名 |
作用 |
事件名 |
作用 |
onclick |
鼠标单击事件 |
onmouseover |
鼠标移上 |
ondblclick |
鼠标双击事件 |
onmouseout |
鼠标移出 |
onchange |
改变事件 |
onmouseup |
鼠标松开 |
onload |
在页面加载完毕激活的事件 |
onmousedown |
鼠标按下 |
onfocus |
得到焦点 |
onkeyup |
键盘按键松开 |
onblur |
失去焦点 |
onkeydown |
键盘按键按下 |
onsubmit |
表单提交数据之前执行的事件 |
|
2. JS中的正则表达式
(1) 正则表达式的基本语法:
创建正则表达式的语法:var reg = /正则表达式/匹配模式;
正则表达式的匹配模式:i,忽略大小写匹配(需掌握); g,全局匹配(了解); m,多行匹配(没用)。
正则表达式中的方法:正则表达式对象.test(“字符串”),如果匹配则返回true,如果不匹配则返回false。
示例代码:
reg=/abc/i; //定义一个正则表达式忽略大小写匹配含有abc
var str ="ABC123"; //创建目标字符串str
if(reg.test(str)){ //验证字符串str是否含有abc或者ABC
document.write("str含有忽略大小写abc<br/>");
}else{
document.write("str不含有忽略大小写abc<br/>");
}
(2) 正则表达式的常用符号:
符号 |
作用 |
符号 |
作用2 |
常用正则表达式:
|
{n} |
匹配n个 |
d |
数字 |
|
{n,} |
匹配大于等于n |
D |
非数字 |
|
{n,m} |
匹配在n和m之间,包头包尾 |
w |
单词字符:大小写字母,数字,下划线[0-9a-zA-Z_] |
|
+ |
1~n次 |
W |
非单词字符(上面w取反) |
|
* |
0~n次 |
s |
空白字符:空格,制表符Tab,换行,分页符 |
|
? |
0~1次 |
S |
非空白 |
|
^ |
匹配开头 |
. |
任意字符,注:如果要使用点号,转义. |
|
$ |
匹配结尾 |
|
|
3. JS中的数字对象Array:
(1) 数组的概述和创建方式:
//1. 创建一个长度为0的数组 var arr = new Array();
//2. 创建指定长度的数组 var arr = new Array(5);
//3. 指定数组中的每个元素创建 var arr = new Array(5,10,20,12);
//4. 使用中括号创建数组 var arr = [3,10,2,6,9];
因为JS是一种弱类型的语言,所以在JS的数组中,每个元素的类型都可以不同;
在JS中,数组的长度可以变化,如果将长度设置为0,相当于清空数组
(2) 数组中的常用方法如下:
concat():用于数组的拼接,将多个数组或元素拼接成一个数组 array=array1.concat(array2);
reverse(): 将数组的元素逆转
join(separator):将一个数组按指定的分隔符,拼成一个字符串。与split(分隔符)的功能相反。
sort():用于数组的排序,在JS的数组中,排序比的是ASCII码值,如果想按照其他标准进行排序,就需要提供比较 函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b, 其返回值如下:
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
若 a 等于 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。
例://如果n>m,则返回正整数,如果n<m返回负整数,如果n==m则返回0,此时会将arr数组安装从小到大排序
arr.sort(function (n, m) {
return n-m;
});
4. JS中的DOM编程:
(1) DOM的概念:Document Object Model,文档对象模型。就是浏览器加载数据会在内存中构建DOM树;浏览器会从上往下一次性加载数据,每遇到一个标签就会在内存中创建一个节点对象,直到所有的标签对象创建完成。(如果遇到其他因素,如网络问题等导致图片等内容加载不出来,也会先将所有的节点封装到内存的document对象中)
(2) 通过document对象获取Dom对象的方法:
获取元素的方法 |
作用 |
document.getElementById(“id”) |
通过id得到唯一的元素,如果有相同的id,则得到第1个。 |
document.getElementsByName(“name”) |
通过name属性得到一组元素,返回一个数组 |
document.getElementsByTagName (“input”) |
通过标签名,得到一组元素 |
document.getElementsByClassName(className) |
根据标签类样式属性名字获取一组节点对象 |
(3) DOM修改CSS样式:
方法一:直接修改每一个样式; 例:pNode.style.fontSize="30px";
方法二:直接使用类样式的名字; 例:pNode.className="first";//与在标签上加class="first"效果一样
(4) DOM修改标签元素操作的方法:
元素操作的方法 |
作用 |
document.createElement("标签名") |
创建一个元素 input |
element.setAttribute("属性名", "属性值") |
给元素添加属性 type=”text” |
document.createTextNode("文本节点") |
创建文本节点 如:<h1>文本</h1> |
parent.appendChild(child) |
将child元素追加成parent的最后一个子元素 |
parent.insertBefore(new,old) |
将new元素插入到old元素的前面 |
parent.removeChild(child) |
将parent中的子元素child删除 |
(5) event.keyCode:获取当前键盘中当前当前按下键的键码值。
6.JQuery基础
1. JQuery框架概述:
使用简单,容易上手,体积小,占用资源少;jquery的宗旨是write less do more。jquery插件网:https://www.jq22.com/。
2. JS和JQuery的区别和转换:
区别:JS 的页面加载完毕:window.onload = function(){ ... ... }
JQuery 的页面加载完毕:$(document).ready(function(){ ... ... }),一般简写: $( function(){ ... ... } )
转换:JS对象转换成 jQuery 对象,语法:$(js 对象)
JQuery对象转换成js对象,语法:jQuery 对象[索引]或 jQuery 对象.get(索引);JQuery本质上是数组对象
3. JQuery中的选择器:
(1) 基本选择器:
标签选择器(元素选择器):$("html标签名"); 例:$("div").css("background","red");
id选择器:$("#id的属性值"); 例:$("#one").css("background","red");
类选择器:$(".class的属性值"); 例:$(".mini").css("background","red");
(2) 层级选择器:
获得 A 元素内部的所有的 B 元素:$("A B");子,孙 例:$("body div").css("background","red");
获得 A 元素下面的所有 B 子元素:$("A > B");只是子 例:$("body>div").css("background","red");
获得 A 元素同级,下一个 B 元素:$("A + B"); 例:$("#one+div").css("background","red");
获得 A 元素同级,所有后面 B 元素:$("A ~ B"); 例:$("#two~div").css("background","red");
(3) 属性选择器:
1) 获得有属性名的元素:$("A[属性名]")
含有属性 title 的 div 元素背景色为红色:$("div[title]").css("backgroundColor","red");
2) 获得属性名 等于 值 元素:$("A[属性名=值]")
属性 title 值等于 test 的 div 元素背景色为红色:$("div[title='test']").css("backgroundColor","red");
3) 获得属性名 不等于 值 元素:$("A[属性名!=值]")
属性 title 值不等于 test 的 div 元素(没有 title 属性的也将被选中)背景色为红色:
$("div[title!='test']").css("backgroundColor","red");
4) 获得属性名 以 值 开头 元素:$("A[属性名^=值]")
属性 title 值 以 te 开始 的 div 元素背景色为红色:
$("div[title^='te']").css("backgroundColor","red");
5) 获得属性名 以 值 结尾 元素:$("A[属性名$=值]")
属性 title 值 以 est 结束 的 div 元素背景色为红色:
$("div[title$='est']").css("backgroundColor","red");
6) 获得属性名 含有 值 元素:$("A[属性名*=值]")
属性 title 值 含有 es 的 div 元素背景色为红色:
$("div[title*='es']").css("backgroundColor","red");
7) 复合属性选择器,多个属性同时过滤:$("A[属性名=值][属性名=值][属性名=值]")
选取有属性 id 的 div 元素,然后在结果中选取属性 title 值含有“es”的 div 元素背景色为红色:
$("div[id][title*='es']").css("backgroundColor","red");
(4) 基本过滤选择器
1) 获得选择元素中的第一个元素: :first
改变第一个 div 元素的背景色为 红色: $("div:first").css("background","red");
2) 获得选择的元素中的最后一个元素: :last
3) 不包括指定内容的元素例如: :not(selecter)
改变 class 不为 one 的所有 div 元素的背景色为 红色:$("div:not(.one)").css("background","red");
4) 偶数,从 0 开始计数, :even
改变索引值为偶数的 div 元素的背景色为 红色:$("div:even").css("background","red");
5) 奇数,从 0 开始计数, :odd
6) 大于第 n 个,不含第 index 个: :gt(index)
改变索引值为大于 3 的 div 元素的背景色为 红色: $("div:gt(3)").css("background","red");
7) 小于第 n 个,不含第 index 个: :lt(index) 等于第n个:div:eq(3)
8) 获得标题所有标题元素 (<h1> /<h2> ....) :header
改变所有的标题元素的背景色为 红色: $(":header").css("background","red");
(5) 表单属性过滤选择器
可用: :enabled 例:$("input[type='text']:enabled").val("黑马程序员");
不可用: :disabled 例:$("input[type='text']:disabled").val("黑马程序员");
选中(单选 radio ,多选 checkbox):checked 例:var items = $("input[name='items']:checked");
选择(下列列表 <select>中的<option>): :selected 例:$("select option:selected").text()
4. JQuery中的方法:
(1) DOM操作方法:
html() 相当于 innerHTML; text() 相当于 innerText; val() 相当于 value; ()中没有值为获取,有值为赋值。
(2) HTML属性操作方法:
attr(name),获取属性name的值 |
prop(name),获取属性name的值 |
attr与prop的区别: 相同点:都是获取设置属性的方法 不同点: attr设置一般属性都可以 prop用于设置选中状态的属性 prop专门用于设置属性值为boolean类型的属性 |
attr(name,value),设置属性name的值为value |
prop(name,value),设置属性name的值为value |
|
removeAttr(name);删除指定的name属性 |
removeProp(name),删除指定的name属性 |
(3) HTML的class属性操作(相当于对 className 的操作) :
addClass(类样式名) 添加类样式
removeClass(类样式名) 删除类样式
toggleClass(类样式名) 如果存在类样式名就删除,如果不存在样式名就添加。切换类样式
(4) html的样式的操作 css():
获取:$("#one").css("background-color") 和 $("#one").css("backgroundColor") :2种方式均可。
设置:$("#one").css("background-color","green");和$("#one").css("backgroundColor","green"); :2种方式均可
(5) html的内部插入:
append(): 相当于 appendChild(),添加元素为当前元素的最后一个子元素。与当前元素是父子关系。
prepend():添加元素为当前元素的第一个子元素。与当前元素是父子关系
before():在当前元素的前面插入一个元素,与当前的元素是兄弟关系。
after(): 在当前元素的后面插入一个元素,与当前的元素是兄弟关系。
例:$("#city").append($("#fk"));
补充:$("#fk").clone() 克隆,复制一个一模一样的对象;$("#tj").after($("#fk").clone());将复制的fk插入tj后面
(6) html元素的删除操作:
remove(): 删除本身 例:$("#bj").remove();
empty():删除所有的子节点,本身还是存在 例:$("#city").empty();
5. JQuery的动画效果:
方法 |
作用 |
方法 |
作用 |
方法 |
作用 |
show(speed ,fn) |
显示 |
slideDown(speed,fn) |
下滑显示 |
fadeIn(speed ,fn) |
淡入显示 |
hide(speed ,fn) |
隐藏 |
slideUp(speed ,fn) |
上滑隐藏 |
fadeOut(speed ,fn) |
淡出隐藏 |
toggle(speed ,fn) |
切换 |
slideToggle(speed ,fn) |
切换 |
fadeToggle(speed ,fn) |
切换 |
Speed:设置速度,单位毫秒,可以指定常量:fast,normal,slow; fn:回调函数,动画执行后运行的函数。
6. JQuery的循环遍历:
(1) 原始方式:var $lis = $("#city li"); 再使用for循环遍历$lis;
(2) jquery对象each方法方式(推荐):jq对象.each(function(index,element){ //代码 }); element:js对象
例:$("#city li").each(function (i,item) { alert($(item).text()); });
(3) jquery全局each方法方式:$.each(jq对象,function(index,element){ //代码 });
7. HTTP和Tomcat
1. HTTP协议基本概述:
Hyper Text Transfer Protocol 超文本传输协议;用于规定浏览器与服务器传输数据的格式与内容。因为浏览器与服务器交互的时候都遵循http协议所以浏览器可以认识服务器响应过来的数据,服务器端也认识客户端浏览器的请求数据,最后得以交互识别。
2. 查看http协议数据方法:
(1) 浏览器开发者工具查看:可以通过浏览器“开发者工具”——“network网络”——提交请求——观察network下面请求url并点击——观察network的右边就是http协议数据(请求与响应);
(2) 专业Fiddler抓包工具软件查看:选择抓取到的数据->点击Inspection->点击Raw;
3. HTTP基础讲述:
(1) 网络的三要素:协议、IP地址、端口号; http协议默认端口号为80;
(2) HTTP请求组成:
请求消息行:请求方法 + url?get提交数据 + http协议版本
请求消息头:key:value格式
请求正文:用于传送post方法请求数据
(3) HTTP响应组成:
响应消息行:HTTP协议版本 + HTTP通信状态码 + 状态码翻译 (HTTP/1.1 200 OK)
响应消息头:key:value格式
响应正文:传输用户看的网页数据
4. URL组成:
Uniform Resource Locator 统一资源定位符(就是定位哪台服务器上具体资源)
http://www.itcast.cn:8080/news/index.jsp?boardid=5&id=24618&page=1
组成部分 |
功能 |
http |
访问的协议 |
www.itcast.cn |
服务器域名或IP地址。http://119.75.216.20/ 访问百度 |
8080 |
端口号,默认浏览器http协议端口号是:80,https默认端口443 |
news |
服务器上的一个项目访问地址(资源目录) |
index.jsp |
web资源,可以是HTML、JSP、图片 |
? |
分隔符,前面是URL访问地址,后面是参数 |
boardid=5&id=24618&page=1 |
客户端提交参数数据,多个参数之间使用&分隔 |
本地的hosts文件或者运营商的DNS可以对域名进行解析,将域名转为对应的IP地址。
5. Web服务器基本概述:
(1) 常用的Web服务器:Weblogic,Oracle公司的一款服务器;WebSphere,IBM公司;Tomcat:常用服务器;
(2) 服务器有能力将本地的web资源提供给外界用户使用浏览器去访问。
当浏览器请求静态资源,服务器会使用io流读取本地静态资源文件响应给浏览器;
当浏览器请求动态资源,服务器会调用java程序,java程序获取动态资源数据响应给浏览器;
6. Tomcat使用( http://tomcat.apache.org/ ) :
(1) Tomcat目录结构:
目录名 |
作用 |
bin |
命令目录,启动和关闭的可执行文件; 启动:startup.bat; 关闭:shutdown.bat; |
conf |
config配置文件夹,配置文件在这个目录下,如:server.xml,修改端口号等信息 |
logs |
服务器启动或出现异常的一些日志记录文件 |
webapps |
我们项目部署和发布资源的文件夹 如:/webapps/hello/1.html 访问:http://localhost:8080/hello/1.html 注意:所有发布的资源文件必须放在资源目录里面 如果放到指定的资源目录,访问的时候就要“资源目录/资源文件”,如果放到了ROOT目录下面,可以直接访问“/资源文件”。ROOT是资源根目录,放在这里的资源可以直接访问。 |
(2) Tomcat的启动常见的问题:
启动界面一闪而过现象:需配置好JAVA_HOME(JVM环境遍历)或者CATALINA_HOME(服务器环境遍历);
端口被占用问题:可以启动DOS,输入netstat -aov目录,找到8080端口号的进程,在进行清除;
或者将服务器的端口号进行修改。
7. 使用IDEA开发Web应用程序:
(1) idea使用初始化设置工作:、
统一idea码表:File->Setting->File Encodings->修改码表为UTF-8
找到idea安装目录,打开idea64.exe.vmoptions文件,在最后一行添加:-Dfile.encoding=UTF-8
点击edit config进入部署项目设置,在其中的VM options中添加:-Dfile.encoding=UTF-8
(2) idea绑定Tomcat
点击edit config进入部署项目设置,向下拖拽找到Tomcat Server中的Local选项点击,点击右上角config配置tomcat的路径,点击OK配置完成。
(3) 修改项目部署位置:
当我们运行项目时,会发现项目部署到C:Users用户.IntelliJIdea2017.3system目录下去了,此时需更改位置:
- 鼠标右击模块名->点击Open Modulel Setting->点击Artifacts->选中项目->右上角修改为Archive->点击OK;
- 点击edit config进入部署项目设置->选中当前Tomcat->点击Deployment->选中当前项目->修改右方/;
(原来只有/.修改为/项目名字,这样会将整个项目加载到服务器webapps中,如果不改会将当前项目下的 所有文件部署到ROOT里面)。
8. Web项目结构
8. Servlet
1. Servlet概述:
全称server applet,是sun公司提供开发动态资源的技术。Servlet类技术,与普通java类是有区别的,servlet具有处理请求与响应的能力。普通java类必须有程序的入口main方法才可以运行,而servlet类是web服务器调用运行的,用户访问的服务器,请求交给服务器,服务器调用servlet程序处理,servlet处理响应完成交给服务器,服务器交给浏览器。
在javaee中,存在Servlet接口和ServletConfig接口,作为Servlet功能最原始的接口,然后GenericServlet抽象类实现了这2个接口,HttpServlet抽象类又继承了GenericServlet抽象类。所以我们使用Servlet功能时可以创建类继承GenericServlet抽象类,可以可以继承HttpServlet抽象类;我们一般是继承Http抽象类(子类的功能更多)。
2. 使用Servlet功能的三种方式:
(1) 手动开发Servlet程序和配置web.xml方式(配置web.xml的2中方式):
方式一:右击模块名->点击Open Module Settings->点击左侧facets->点击右侧+生成web.xml文件
方式二:点击File->New->Module->选中Java Enterprise->选中JavaEE5和WebApplication->点击创建会自动生成
在web.xml配置文件中有<servlet>标签和<servlet-mapping>标签,需创建完成。
(2) 创建一个类,该类继承自HttpServlet抽象类,在该类名上方手动加上注解:
@WebServlet(name = "Hello2Servlet", urlPatterns = "/Hello2"); name为类名, urlPatterns为url值;
此时通过urlPatterns就可以访问该Servlet了。
(3) 使用IDEA的模板自动创建Servlet并生成注解:
鼠标右键->new->Servlet就可以自动生成Servlet,并在类上方自动生成以本类名为url的注解。
3. Servlet的运行原理:
服务器实例化了Servlet对象;并调用了service方法处理请求(HttpServlet抽象类在service内部对请求方式进行了分类,不同的请求调用不同的方法进行处理);将客户端的所有的请求的数据封装在request对象中;所有要响应给客户端的数据封装在response对象中。
4. Servlet的生命周期:
(1) servlet对象的从创建到销毁的过程,概念类似于对象作用域。Servlet中的主要方法如下:
方法 |
作用 |
运行次数 |
void init(ServletConfig config) |
初始化的方法 |
1次 |
void service(ServletRequest req, ServletResponse res) |
服务的方法 |
每次请求都会执行 |
void destroy() |
销毁的方法,Web容器关闭或重启的时候执行 |
1次 |
(2) Servlet中每个方法的具体生命周期:
a. 默认情况如下:
当第一个用户访问该Servlet时服务器会创建这个Servlet对象,此时会调用init方法,然后会调用此次访问的service方法,以后每次访问都会调用一次service方法,当服务器关闭或者重启时会调用destroy方法。
b. 当在web.xml配置文件中对应的<Servlet>标签中加上<load-on-startup>1</load-on-startup>子标签时如下:
该标签中间的取值是正整数(大于0),值越小就越先加载。如果配置成负数或0,则与不写这个参数是一样的。当该值是一个小于等于0或者没有指定时,则指示容器在该servlet第一次被访问时才加载创建对象。
当服务器启动时就会创建Servlet这个对象,并在此时调用了init方法,以后每次有浏览器访问这个Servlet时都会调用service方法,当服务器关闭或者重启时会调用destroy方法,此时这个Servlet也会被GC回收。
5. Servlet中的配置文件对象ServletConfig:
此对象可以读取web.xml中对当前servlet配置的参数数据。web.xml中的参数形态如下所示:
<init-param>
<param-name>param1</param-name> <param-value>123456</param-value>
</init-param>
ServletConfig对象中的方法如下:
String getInitParamter(String name):得到web.xml中有关Servlet的配置参数,通过参数名得到参数值
getInitParameterNames():会得到web.xml中有关这个Servlet的所有的配置参数的名字,返回一个枚举类
6. Servlet映射路径配置:
(1) 可以配置多个url-pattern:
<servlet-mapping>
<servlet-name>Demo1Servlet</servlet-name>
<url-pattern>/demo1</url-pattern>
<!-- 可以配置多个url-pattern -->
<url-pattern>/hello</url-pattern>
<url-pattern>/hello.html</url-pattern>
</servlet-mapping>
(2) 可以配置多个servlet-mapping:
同一个servlet可以配置多个访问映射servlet-mapping标签配置;
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.itheima.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
(3) Servlet映射路径匹配方式(精确匹配和模糊匹配):
- 精确匹配:要配置的url与用户访问的url要一模一样才可以访问到对应的servlet。
- 模糊匹配:模糊匹配使用一个通配符“*”号,只有这一个通配符。
前缀匹配,必须以“/”开头,以“*”结尾(*前面必须有/)
例:/abc/*,只要用户访问时/abc/开头都可以匹配到;
后缀匹配,必须以“*”开头,以“.”扩展名方式结束使用
例:*.do,只要用户访问时以.do结尾都可以匹配到;
注意:/abc/*/abc,既不属于前缀也不属于后缀,属于精确匹配;匹配模式一样的时候,匹配相似度越高优先级 越高;精确匹配优先于模糊匹配;模糊匹配中,前缀匹配优先于后缀匹配。
(4) 缺省路径:
“/”和“/*”就是缺省路径,缺省路径可以匹配一切资源,该映射路径已经被全局tomcat/conf/web.xml使用了,其中DefaultServlet配置了缺省路径。DefaultServlet是用于处理静态资源响应的。建议开发者不要使用这个配置url-pattern,如果开发人员使用了这个配置,就覆盖了缺省路径,就会导致所有的静态资源无法访问了。(访问路径时会先访问这个项目内部的web.xml中的局部路径,再访问服务器中的公有路径)
- 7. Web开发中的路径问题:
(1) 相对路径:url=直接写资源路径名字
如: <form class="form-horizontal" action="LoginServlet" method="post">
这个路径直接写LoginServlet的意思是:访问当前资源目录loginSys下的LoginServlet
(2) 绝对路径:url=/工程名字/资源路径名字
如: <form class="form-horizontal" action="/loginSys/LoginServlet " method="post">
这里路径中”/”代表的是tomcat/webapps,所以访问资源要使用资源目录loginSys
9. Request
1. Request中的方法介绍:
(1) 获取Request中请求行的方法:
String getMethod(): 得到请求的方法:GET或POST
String getRequestURI(): 得到请求的URI(统一资源标识符)
StringBuffer getRequestURL(): 得到请求的URL(统一资源定位符,可以直接访问),比较长
String getProtocol(): 得到协议和版本
String getQueryString(): 得到查询字符串,GET的参数使用查询字符串,?号后面的数据
String getContextPath(): 得到项目的访问地址
String getRemoteAddr(): 得到客户端的ip地址(0:0:0:0:0:0:0:1为ipv6,127.0.0.1为ipv4)
String getServerName(): 得到服务器的名字
int getServerPort(): 得到服务器的端口号
String getSchema(): 得到访问协议
(2) 获取Request中请求头的方法:
getHeader(String headName) :根据指定的请求头名字得到对应value
Enumeration<String> getHeaderNames() :得到所有的请求头名字,返回枚举类型
常见请求头 |
描述 |
referer |
得到上一个请求的访问地址,如果没有上一个页面,返回null |
If-Modified-Since |
浏览器缓存的时间 |
Cookie |
用来保存服务器上的一些文本信息 |
User-Agent |
得到浏览器的类型 |
(3) 获取Request中请求体的方法(请求体作用,用于客户端提交post提交的数据):
request.getParameter(name); //获取客户端指定的表单元素名称的一个值,返回string
request.getParameterValues(name); //获取客户端指定的表单元素名称的一组值,返回string[]
request.getParameterMap(); //获取所有表单元素的key-value的Map集合
2. 处理中文请求的乱码问题:
(1) 处理post提交中文乱码问题:
Tomcat服务器的解码方式默认为“ISO8859-1”,而浏览器的提交方式为“UTF-8”,所以可以设置服务器的解码为“UTF-8”,设置方式为: request.setCharacterEncoding("utf-8");
(2) 处理get提交中文乱码问题:
get方式提交时可以直接在Tomcat的配置文件server.xml中添加:<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8" />
3. 四大域对象之一:Request域对象
(1) 什么是域对象:用于在不同的Servlet之间共享数据的存储空间;
(2) Request域对象中的方法:
Object getAttribute("键"): 从请求域中取出一个值
void setAttribute("键",Object值): 向请求域中添加1个键和Object的值
removeAttribute("名字"): 从请求域中删除一个键和值
(3) ServeltContext对象和Request对象的区别:
a.生命周期不一样,servletContext是服务器启动就创建了对象,服务器关闭的时候销毁,作用域是整个应用程序
b.request对象是一次请求开始的时候创建,一次响应结束的时候就销毁。作用域是一次请求内。
(4) Request对象获取当前工程的名字:
代码:request.getContextPath()==》获取当前工程名字;
作用:应用于重定向页面跳转路径为绝对路径时替代路径中写死项目名称;
优点:如果工程名字写死代码,不利于以后修改工程名字;
10. Response
1. 响应消息行(HTTP/1.1 200 OK):
响应消息行由协议版本+http状态码+状态码含义组成;
在http中状态码与对应的含义如下所示:
100~199 :表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程;
200~299 :表示成功接收请求并已完成整个处理过程,常用200表示;
300~399 :为完成请求,客户需进一步细化请求。例如,请求的资源已移动一个新地址,常用302,307和304;
400~499 :客户端的请求有错误,常用404;
500~599 :服务端出现错误,常用500,503;
需重点掌握的状态码如下所示:
状态码 |
含义 |
200 |
通信正常 |
304 |
通知浏览器使用缓存(浏览器本地有缓存文件,不请求服务器了) |
404 |
服务器上没有找到对应的资源。用户的错误,用户输错了url导致的。 |
405 |
提交的请求方式服务器上没有相应的方法处理,比如,用户提交了post请求,servlet里面没有doPost()方法就会报错. |
500 |
服务器发生错误了,错误是由开发人员代码逻辑不完全导致的。99%是开发人员的错误。 |
302 |
通知浏览器进行页面跳转的动作执行 |
2. 响应消息头:
(1) 响应消息头的介绍:
响应头的数据是响应给浏览器,一般我们不用读取,但是我们可以设置响应头的数据,让浏览器按照我们指定的设置进行执行响应的功能。设置响应消息头的方法如下所示:
response.setHeader(name,value): 响应消息头是以key-value格式组成,所以设置时也是设置这2个;
(2) 响应消息头一(Location):
响应头location的作用是通知浏览器要进行页面跳转的目标地址。http状态码302的作用是通知浏览器进行页面跳转的动作执行,所以响应头location和http状态码302配合起来才可以完成页面跳转。代码如下所示:
response.setHeader("location", "/day37/count"); //设置响应消息头,跳转到该页面
response.setStatus(302); //设置http状态码为302
其实这2句代码和起来就是执行Response对象的重定向功能,所以我们如果要跳转页面,一般使用重定向,如下:
response.sendRedirect(getServletContext().getContextPath()+"/count");//一般使用域对象获取工程名
(3) 响应消息头二(Content-Encoding):
一般向客户端浏览器输出大量数据时,为了提供网络传输数据需要对数据进行压缩之后在响应给浏览器,但是浏览器接收的是一个压缩文件,所以需要服务器设置响应头content-encoding通知浏览器解压文件后再显示数据。目前浏览器只支持解压gzip格式的压缩文件。实现代码如下所示:
//设置响应头content-Encoding,通知浏览器解压数据后再显示
response.setHeader("content-encoding", "gzip");
//GZIPOutputStream 数据压缩类,这个类只有压缩功能,没有输出功能,所以要借助response输出流将数据输出给浏览器
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(response.getOutputStream());
//进行压缩(需要将传出的字符数据转成字节数组)
gzipOutputStream.write(stringBuilder.toString().getBytes());
//gzipOutputStream压缩好的在内存中,如果想将压缩好的数据输出给浏览器,必须将内存中数据给到输出流,如下方法
gzipOutputStream.finish();
//总结,如果服务器端客户端输出大量的数据要进行数据压缩
(4) 响应消息头三(Content-Type):
格式:Content-Type: text/html; charset=GB2312 设置响应正文类型,并通知浏览器以什么码表解码数据;
由于服务器响应数据默认采用iso8859-1码表,然而中国大陆浏览器默认采用GBK码表,所以通过设置响应头content-type来统一码表,解决响应中文数据乱码问题。
当需要输出中文时建议执行如下操作:
//修改服务器默认编码码表为utf-8 response.setCharacterEncoding("utf-8"); //通知浏览器以utf-8解码数据显示 response.setHeader("content-type", "text/html;charset=utf-8"); //对字符串进行输出 response.getWriter().write("hello world 传智"); //思考,字符流输出中文默认乱码,字节流输出默认不乱码,为什么呢? //.getBytes()如果无参,默认是GBK编码,浏览器有默认以gbk解码,所以不乱码了,使用字节流不安全,因为只有中国浏览器默认以GBK解码。所以,输出中文,建议字符流,明确设置服务器码表与浏览器码表一样就安全了。 |
(5) 响应消息头四(refresh):
格式:Refresh: 1;url=http://www.it315.org 描述:1秒以后页面跳转到http://www.it315.org
在项目中的实际运用如下:
需求:第一次跳转到倒计时页面wait.html,第二次跳转3秒以后跳转到index.html
response.setHeader("refresh", "3;url="+getServletContext().getContextPath()+"/index.html");
request.getRequestDispatcher("/wait.html").forward(request, response);
第一句代码作用为给响应对象设置一个延迟功能,3秒后会跳转到index.html界面,第二行代码作用为转发到wait.html
总结:上述为在后端设置延迟功能(几秒后跳转到指定页面),此功能也可以在前端使用JS代码实现;
(6) 响应消息头五(Content-Disposition):
通知浏览器不要直接显示数据,以附件形式下载数据。默认浏览器查看数据是直接显示数据,有的资源下载网站需要下载资源数据而不是直接显示,所以需要设置响应头content-disposition来通知浏览器以附件下载数据。
格式:Content-Disposition: attachment; filename=aaa.zip --下载
attachment,通知浏览器不要显示数据要以附件形式下载 filename=aaa.zip,下载的文件名字
实现代码如下所示:
//网页中a标签设置如下: <a href="down?filename=file.zip">压缩文件</a><br/> //后端代码如下: // 1) 通过request对象中的方法从链接上得到文件名 String file = request.getParameter("filename"); // 2) 通过servletcontext对象的方法得到文件的MIME类型 String type = getServletContext().getMimeType("/download/" + file); System.out.println(type); // 3) 设置content-type头为MIME类型 response.setHeader("content-type", type); // 4) 设置content-disposition,以附件方式下载文件filename后是文件名,防止中文乱码,文件名使用url编码格式 response.setHeader("content-disposition", "attachment; filename=" + URLEncoder.encode(file, "utf-8")); // 5) 得到文件的输入流 InputStream in = getServletContext().getResourceAsStream("/download/" + file); // 6) 得到response的输出流 OutputStream out = response.getOutputStream(); // 7) 写出到浏览器端 int len = 0; byte[] buf = new byte[1024]; while((len=in.read(buf))!=-1) { out.write(buf,0,len); } in.close(); out.close(); |
3. 响应正文:
就是服务器输出数据给用户看,浏览器直接要显示给用户,就是服务器输出数据;
可以输出字符数据、字节数据;可以输出资源文件数据(资源图片);可以输出缓存(内存中)图片(资源没有对应的物理资源)--验证码。
11. Request和Response之间的区别
1. 页面跳转的区别:
(1) Request中的页面跳转(转发):
- 转发的方法为:request.getRequestDispatcher("/转发的地址").forward(request, response);
- 由于用户只发送了一次请求,所以在转发过程中,url保持不变;
- 因为转发动作发生在服务器内部,所以只能跳转到当前项目内的资源,无法访问外部资源;
- 页面跳转前Servlet和页面跳转后的资源共用一个Request和Response(一次请求一个Request和Response);
- Request是服务器处理请求时创建,服务器响应结束后销毁(不管中间转发了多少次);
(2) Response中的页面跳转(重定向):
a. 重定向的方法为:response.sendRedirect(request.getContextPath() + "/two");
b. 用户发出2次请求,所以url改变了,一个url对应一次请求;
c. 在重定向中,页面跳转这个动作是浏览器发起的,所以可以跳转到任何地方的资源;
d. 页面跳转后2个资源不共享Request和Response,一次请求对应一个Request和Response;
e. 由于重定向浏览器发出了2次请求,所以跳转速度没有请求转发快;
(3) 转发和重定向的区别:
区别 |
转发forward |
重定向sendRedirect |
根目录 |
当前工程目录内 |
webapps这一级 |
地址栏 |
不会发生变化 |
会,显示第2个 |
跳转者 |
由服务器跳转 |
浏览器跳转 |
请求域 |
Request对象数据不会丢失 |
会丢失,不是同一次请求 |
代码执行 |
转发或重定向后续的代码的后续代码都会执行 |
2. 解决中文乱码的区别:
一般情况下,服务器的默认编码和解码方式均为”ISO8859-1”,而浏览器的提交或者解码方式为”UTF-8”,此时如果浏览器和服务器之间传输中文的话就会产生乱码问题,所以我们在编写代码的过程中需解决该问题,解决方案如下:
第一步:进入服务器的配置文件server.xml文件中,修改服务器的编码方式为UTF-8: URIEncoding=”utf-8”; 第二步:设置request请求对象和response响应对象的码表为utf-8: request.setCharacterEncoding(“utf-8”); response.setCharacterEncoding(“utf-8”); 第三步:通知浏览器以utf-8的格式解码: response.setHeader(“content-type”, “text/html;charset=utf-8”); |
12. ServletContext
1. ServletContext概述:
ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
在Servlet对象中,之间执行getServletContext方法就可以获得ServletContext对象,如下代码所示:
ServletContext servletContext = getServletContext();
2. ServletContext作用一(ServletContext是一个域对象):
域对象是服务器在内存上创建的存储空间,用于在不同动态资源(servlet)之间传递与共享数据 。
凡是域对象,都有如下三个方法:
setAttribute(name,value); name是String类型,value是Object类型; 往域对象里面添加数据 getAttribute(name); 根据指定的key读取域对象里面的数据
removeAttribute(name); 根据指定的key从域对象里面删除数据
servletContext存储数据特点,
全局共享,里面的数据所有动态资源都可以写入和获取;
服务器启动的时候创建,服务器关闭的时候销毁,因为这是全局应用程序对象,全局共享对象。
3. ServletContext作用二(可以读取全局配置参数):
在web.xml中配置全局参数如下代码所示:
<context-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</context-param>
servletContext读取全局参数核心方法如下所示:
getServletContext().getInitParameter(name); //根据指定的参数名获取参数值
getServletContext().getInitParameterNames(); //获取所有参数名称列表
4. ServletContext作用三(可以搜索当前工程目录下面的资源文件):
ServletContext搜索当前工程目录下的资源的主要方法如下:
getServletContext().getRealPath(path): 根据相对路径获取服务器上资源的绝对路径
getServletContext().getResourceAsStream(path):根据相对路径获取服务器上资源的输入字节流
示例代码如下:
String realPath = getServletContext().getRealPath("img/2.jpg"); 根据相对路径获取绝对路径
InputStream fileInputStream = getServletContext().getResourceAsStream("img/2.jpg"); 获取资源文件输入流
5. ServletContext作用四(可以获取当前工程名字):
核心方法如下:
getServletContext().getContextPath();
13. JavaEE项目中的架构
1. 三层架构:
在项目开发中,为了进行明确分工,将整个项目分成了三层,分别是表示层,业务逻辑层和数据访问层,具体如下:
表示层:是一个用户交互的层面,主要是执行Servlet的功能,用来获取用户的请求(request)和处理用户的响应(response)
业务逻辑层:service层,主要用来处理各种业务(将表示层的数据接收,进行业务处理,如果需要服务数据库,就将 需要处理的数据传入下一层)
数据访问层:dao层,用于操作数据库的层面,主要进行编写sql语句,和执行sql语句并返回结果;
dao(d:data数据 a:ask 访问 o:object 对象):数据访问对象。
2. MVC+三层架构:
M:model,模型,负责封装数据与业务处理,数据库操作(业务逻辑层和数据访问层)
V:view,视图,显示数据(JSP和前端的html显示数据)
C:controller,控制器,调度数据(servlet表示层,将用户输入的指令和数据传递给业务模型)
14. Cookie(客户端会话)
1. Cookie的概述:
Cookie 就是浏览器写在你本地计算机上的一个文本文件,大小不超过 4K;可以执行保存密码,下次自动登录功能。
2. Cookie的常见操作:
(1) Cookie中的常用方法:
public Cookie(String name,String value):构造方法,用来创建一个名字和值的 Cookie 对象;
setValue()/getValue(): 修改 Cookie 的值,得到 Cookie 中指定的值
getName(): 得到 Cookie 的名字
setMaxAge()/getMaxAge(): 设置 Cookie 过期的时间,单位是秒
setPath()/getPath(): 用来设置 Cookie 的路径,cookie的默认有效路径是当前工程名字,所以浏览器只要 访问当前服务器和当前的工程名字都会携带cookie到服务器
Response.addCookie(): 把 Cookie 对象写到浏览器。添加了一个叫"Set-Cookie"的响应头信息
Request.getCookies(): 得到浏览器发送回来的 Cookie 数组,返回值为一个Cookie数组
(2) Cookie中的注意事项:
A. 必须设置cookie有效期,否则不会产生文本文件,cookie只会在浏览器内存中,当浏览器关闭时会清空;
B. 当向浏览器中设置Cookie之后,以后每次访问浏览器都会自动携带cookie数据给到服务器端;
C. Cookie在浏览器和服务器之间的传递是通过响应消息头和请求消息头来传递的;
D. 浏览器每次请求都会携带cookie,会带来流量资源的销毁,这时可以通过setPath()方法来设置Cookie的路径,如将 路径设置为/工程名字/abc资源路径 时,这时只有访问abc这个资源时才会携带Cookie;
(3) Cookie的中文乱码问题:
因为Cookie传递数据是使用消息头就行传送的,所以如果使用Cookie传递中文时需进行url编码和解码。
Url编码方法:String str2 = URLEncoder.encode(str1,"utf-8"); 会将字符串str1编写成utf-8格式的url码str2。
Url解码方法:String str2 = URLDecoder.decode(cookie.getValue(),"utf-8"); 会将utf-8格式的url进行解码。
请注意:以后编程中,不管编码还是解码,一般使用utf-8;能支持所有语言;
3. Cookie总结:
默认生命周期:服务器创建输出给浏览器,浏览器关闭后cookie失效;设置的生命周期:通过setMaxAge设置有效期。
服务器端生成cookie数据,通过响应头传递给浏览器,在浏览器端存储的文本文件。
浏览器每次请求都会携带与cookie有效路径一样的cookie数据通过请求头带到服务器端。
cookie存储在客户端,数据是不安全的,对于敏感数据要进行加密后在存储,cookie文件大小有限制4KB。
cookie中存储是键值对,并且一个cookie中只能存储一个键值对。
4. Cookie和Session的总结:
会话对象一共有2个,cookie是客户端会话,session是服务器端会话
cookie只能存储字符串数据,session可以存储object类型数据
cookie默认有效期是浏览器关闭,session默认有效期30分钟并且是一次会话内
session存储数据是在服务器端,安全性比cookie高。
15. Session(服务器会话)
1. Session的概述:
从用户打开浏览器开始访问网站到关闭浏览器窗口,我们认为浏览器与服务器进行了一次会话。会话提供了一种方法,它让服务器可以识别多次请求或访问服务器的同一个用户,并服务器存储有关该用户的信息。会话在指定的时间段内有效。
2. Session的特点:
1) 运行在服务器端,由服务器为每个浏览器创建单独的存储空间对象,称为会话对象。
2) 每个用户都有自己的会话对象,不同的浏览器代表不同的用户。
3) 会话对象也是一个域对象,主要用于存储每个用户自己的数据,不同的用户之间数据不能共享。
3. Session的使用:
session 也是一个域对象,用来保存不同用户的数据。
域范围大小:request(一次请求) < session(一次会话内) < servletContext(整个应用程序范围内)。
使用过程:由服务器创建,在第一次用户访问的时候会创建一个会话。不同的浏览器得到的会话对象是不同的。 注:同一个浏览器不同的标签页,是同一个会话。可以通过request.getSession();方法获得这个会话。
HttpSession类(作用域)中的方法:
void setAttribute(String name, Object value) : 向会话中保存数据
void removeAttribute(String name): 从会话中删除指定的数据
Object getAttribute(String name) : 从会话中得到指定的数据
String getId() : 得到会话的 ID,一个 32 位的十六进制数,在服务上唯一。
4. Session的运行原理:
总结:session技术是依赖或基于cookie技术的;用户第一次访问没有cookie,所以服务器就创建session同时将sessionid写入cookie,用户第二次访问携带cookie,服务器就可以获取cookie-jsessionid,就返回对应已有session对象。
5. session有效期:
session的有效期是一次会话内,关闭了浏览器session就没用了,但是session对象依然存储在服务器内存中,session对象并没有销毁。默认的会话时间是 30 分钟(服务器创建一个session对象,30分钟后会销毁这个对象。超过30分钟浏览器没有关闭,浏览器访问服务器,服务器会产生一个新的session对象。)
6. 改变session的销毁时间:
方式一:通过web.xml文件设置(<session-config> <session-timeout>1</session-timeout> </session-config>)
值设置为1证明1分钟后该session会销毁,如果设置为0或者负值,那这个session就不会自动销毁。
方式二:session.invalidate();
当执行这个方法时,该session会立刻失效,可以应用于注销登录等场景。
16. JSP (基本概述)
1. JSP概述(Java Server Pages):
运行在服务器上的页面。结合了HTML和Servlet的优点,既可以方便的编写html、CSS和JS代码,又可以在网页上编写Java代码处理动态的内容。jsp在访问的时候,会被服务器翻译成.java文件,再被编译成.class文件,所以jsp可以写java代码。Jsp文件被编译后,其中的html代码是通过out.write直接输出,而java代码是原样输出。JSP其实本质上就是一个Servlet,只是服务器把其中的html代码通过out.write直接进行输出了。
2. JSP的运行原理:
用户访问jsp的时候,服务器每次都会检查jsp页面是否修改过,如果修改过服务器会将jsp翻译成.java文件,并编译成.class文件;如果服务器检查jsp没有修改过,会直接运行.class文件。运行.class的servlet,最后走servlet的生命周期。
3. JSP页面的七个组成部分:
组成部分 |
功能 |
语法 |
HTML |
制作静态内容 |
|
JSP脚本(重点) |
Java代码 |
符合Java语法 <% Java代码; %> 有分号 |
JSP表达式(重点) |
可以直接输出的表达式 |
<%=表达式%> 没有分号 |
JSP声明 |
只能声明全局变量和方法 |
<%! 声明 %> |
JSP指令 |
页面上的辅助功能 |
<%@指令名 属性名=属性值%> |
JSP动作 |
代替部分Java代码的功能 |
<jsp:动作名 属性名=属性值/> |
JSP注释(重点) |
用来注释JSP代码 |
<%-- 注释内容 --%> |
(1) JSP注释:在JSP中一共存在三种注释
第一种:<!-- 注释 --> 该只能注释静态内容,如html,css等,如果注释中有java代码时,还是会执行。
第二种:<%-- JSP注释--%>,被这个注释注释的内容,是完全不会运行的,不过前端还是后端。
第三种:/ , // , /**/,因为JSP中包含Java代码,所以Java中的注释在JSP中能正常使用。
(2) JSP脚本:
语法:<% Java代码; %>
作用:在JSP上直接编写Java代码
(3) JSP表达式:
语法:<%=表达式%>;前面有等于号,后面没有分号。
作用:用于输出表达式的值,类似于out.print(表达式),翻译成Servlet以后其实就是一句:out.print()
(4) JSP声明:
语法:<%! 声明方法或全局变量 %>
例:<%! private String string = "name"; %>
(5) JSP指令:请见如下详细讲解
(6) JSP动作(JSP的内置标签):
作用:jsp内置标签是sun公司开发的,用于封装了具有一定功能的脚本代码。(使用时不需要导包)
格式:<jsp:标签名字></jsp:标签名字>
标签一:include标签 <jsp:include page="设置包含页面地址的"></jsp:include> 会动态包含另一个JSP页面
动态包含:服务器会将包含的2个页面分别翻译成2个java文件,是在运行当前页面时动态将2个页 面合在一起;2个页面不共享成员变量或局部变量。(所以我们一般使用include指令进行静态包含)
标签二:forward标签 <jsp:forward page="转发地址"></jsp:forward> 用于请求转发
标签三:param标签 <jsp:param name="username" value="admin"></jsp:param> 用于转发中传递参数数据
<jsp:forward page="index.jsp">
<jsp:param name="username" value="admin"></jsp:param>
</jsp:forward>
4. JSP九个内置对象:
什么是内置对象:由JSP翻译成Servlet之后自动生成的对象,我们可以直接在JSP上使用这些内置对象。
对象名 |
对应的类型 |
功能描述 |
request |
HttpServletRequest |
代表请求对象 |
response |
HttpServletResponse |
代表响应对象 |
out |
JspWriter |
有缓存的打印流 |
session |
HttpSession |
会话对象 |
application |
ServletContext |
上下文对象 |
config |
ServletConfig |
配置对象 |
exception |
Throwable |
异常对象 |
page |
This===》Servlet |
JSP翻译以后的Servlet对象 |
pageContext |
PageContext |
页面上下文 |
pageContext内置对象详解(页面上下文对象):
(1) 可以获取所有内置对象: pageContext.getSession(); 可以通过 . 的方式获取其他的所有内置对象
(2) 是一个域对象:此域对象范围(一个servlet内,一个jsp页面内,相当于当前类内部的全局成员变量)
(3) 可以获取或设置其他域数据:
pageContext.setAttribute(String,Object,int); String:数据名字;Object:数据;int:枚举类型,代表具体域
pageContext.getAttribute(String,int); 从指定域对象里面获取数据
(4) 可以依次搜索所有域对象里面的数据:
pageContext.findAttribute(name) 会依次从pageContext/request/session/application中查找数据,找到为止.
5. JSP页面四大域对象:
作用域对象名 |
对应的接口名 |
对象名 |
作用范围 |
页面域 |
PageContext |
pageContext |
当前页面 |
请求域 |
HttpServletRequest |
request |
一次请求内,同一个请求到达的多个页面 |
会话域 |
HttpSession |
session |
一次会话内,同一个用户到达的多个页面 |
上下文域 |
ServletContext |
application |
整个应用程序,所有用户到达的所有页面 |
页面域pageContext < 请求域request < 会话域session < 上下文域servletContext
6. JSP和Servlet在以后开发中的使用选择:
jsp:编写html布局代码方便,所以主要负责显示布局动态资源数据
servlet:写的代码全部是java代码,所主要主要负责产生动态资源数据
jsp与servlet配合使用,用户请求servlet负责从数据库获取数据,存储到域对象里面,之后跳转到jsp页面显示布 局动态资源数据。
7. 解决JSP界面混乱问题:
(1) JSP界面只用了显示布局的动态资源数据,不用了进行业务逻辑等的处理;(请参考下方MVC+三层架构)
(2) <%= %> 在JSP界面不写这个标签,使用el表达式代替这个进行内容的输出;(请参考下方EL表达式)
(3) <% %> java代码不写在这个标签中了,使用jstl代替这个技术;(请参考下方JSTL标签库)
17. JSP (三大指令)
1. JSP中指令的概述:
指令的作用:用于在JSP页面上实现一些辅助的功能,并不会在JSP上生成Java代码。
指令的格式和分类:<%@指令名 属性名=属性值 %>; JSP中分为page、include、taglib三大指令。
2. page指令:
(1) 作用:用于告诉tomcat如何将一个JSP页面翻译成Servlet,指定翻译时的一些参数。
(2) 位置:page指令可以放在网页的任意的地方,根据开发习惯,建议放在网页的最前面。
(3) 格式:格式:<%@ page contentType="text/html;charset=UTF-8" language="java" %>。
(4) 属性一:contentType="text/html;charset=UTF-8",设置输出类型与码表的,相当于response.setContentType方法。
(5) 属性二:pageEncoding="utf-8" 指定页面编码,有三个作用:
作用一:与contentType="text/html; charset=utf-8"属性的功能相同
作用二:用于设置当前JSP页面文本保存的字符集
作用三:用于指定JSP翻译成Servlet的编码
所以:以后只需要设置pageEncoding属性就可以解决JSP编码的问题
(6) 属性三:language="java",告诉tomcat将jsp翻译java文件。
(7) 属性四:import,导入java类所需要的类
格式一:一个page指令导入一个类<%@ page import="java.util.List" %>
格式二:一个page指令导入多个类<%@ page import="java.util.ArrayList,java.text.SimpleDateFormat" %>
(8) 属性五:buffer="8kb",用于设置out字符流输出对象的缓存大小,该属性默认为8kb
缓存:没有缓存立即输出,有缓存输出的数据满足指定的大小之后才能输出;
buffer="8kb",out字符流输出对象缓存数据输出的前提条件
条件一:页面out字符流对象输出数据大小够8kb才会向浏览器输出数据
条件二:如果页面所有输出数据不够8kb,等待页面没有缓存的数据全部输出完后再输出缓存数据
PrinterWriter response.getWriter() ,这个打印字符流就没有缓存功能
out对象的类型JspWriter,这是PrinterWriter升级版,具有缓存功能
(9) 属性六:isErrorPage="false"
用于设置错误友好页面接收传递过来的exception对象,默认不接收,设置为true才接收
我们可以在错误友好界面将接收过来的exception对象进行控制台打印或者日志输出,可以看到异常输出
这个属性需配合errorPage="500.jsp"这个属性使用,当当前页面发生异常时跳转到500.jsp界面,但在工作开发中我们一般不用这个属性,我们会在web.xml文件中配置<error-page> <error-code>500</error-code>
<location>/500.jsp</location> </error-page>这个配置文件,这样当页面出现500异常时全部会跳转500.jsp页面。
3. taglib指令:
(1) 作用:导入JSP的标签库;(标签库:是具有特定功能的java代码,使用标签方式展现)
(2) 格式:<%@taglib uri="设置导入标签的地址" prefix="设置标签的前缀"%>
4. include指令:
(1) 作用:用来包含另一个JSP或者HTML页面;
(2) 格式:<%@include file="设置要包含的页面" %>;
(3) 特点:include指令的包含称作为静态包含,服务器会将当前页面和包含的页面2个jsp页面翻译成一个.java文件,这样就叫做静态包含;静态包含时2个页面共享成员或局部变量。
18. JSP(EL表达式)
1. EL表达式之概述:
我们在写JSP代码时,应该尽可能少的在jsp页面上使用Java代码,因为JSP是一个页面,页面上应该使用标签。所以我们这个时候就可以使用EL(Expression Language 表达式语言)表达式了,EL表达式是sun公司自己开发,在jsp页面上可以直接使用用。格式:${域对象里面的key },用于输出域对象里面的数据。请注意:JSP中使用的变量是脚本变量,而EL中的变量都是使用域变量,要操作的变量都在使用域中。
2. EL表达式之获取四大域里面的数据:
(1) 从指定域里面读取数据, ${指定域.key}:
${pageScope.name} ${requestScope.name}
${sessionScope.name} ${applicationScope.name}
(2) 依次从四大域对象里面获取数据,找到为止(从小到大) ${key}:
<p>${name}</p>
请注意:从域中通过EL表达式获取到数据后可以直接输出。
3. EL表达式之获取域里面不同数据类型的数据:
(1) 获取对象类型的数据:
语法:${域里面的key.对象属性} el会自动调用该属性的get封装方法获取值
例: <p>user对象里面的age属性值:${user.age}</p>
(2) 获取Map集合的数据:
语法:${域里面的key.map里面的key}
例: <p>获取map里面key为one的user对象里面的age属性值:${map.one.age}</p>
(3) 获取List集合的数据:
语法:${域里面的key[index]},index从0开始
例: <p>获取list里面第一个元素的user对象里面的age属性值:${userList[0].age}</p>
(4) 获取数组类型的数据:
语法:${域里面的key[index]},index从0开始
例: <p>获取数组里面第一个元素的user对象里面的age属性值:${users[0].age}</p>
4. EL表达式中的隐式对象:
(1) EL表达式中有11中常用的隐式对象,其中标红的6个需重点掌握:
pageContext: 代表页面上下文对象,可以在页面上调用get方法
pageScope: 代表页面域pageContext中的Map对象
requestScope: 代表请求域中request的Map对象
sessionScope: 代表会话域session中的Map对象
applicationScope: 代表上下文域servletContext中的Map对象
Param: 得到表单提交参数,功能与:request.getParameter()相同
paramValues: 得到表单提交参数,功能与:String[] request.getParameterValues()相同
Header: 得到请求头的数据 request.getHeader(“名字”)
headerValues: 得到请求头的数据 request.getHeaders(“名字”)
Cookie: 得到请求的Cookie信息
initParam: 相当于config.getInitParamter()得到web.xml中配置的参数
(2) pageContext和pageScope的区别:
这2个EL中的对象是由JSP中的一个对象pageContext变化而来,其作用分别如下所示:
pageScope,可以获取jsp域对象pageContext里面域数据
pageContext,可以获取jsp域对象pageContext对象的相关get方法的数据
跟JSP中的使用区别如下(以获取访问者IP为例):
脚本代码: <%= request.getRemoteAddr() %>
使用el代替: ${pageContext.request.remoteAddr}
(3) Cookie对象Cookie cookie = new Cookie("name","value"); :
${cookie.cookie存储的key.name}//获取cookie里面指定key的name 其中key值即为name值
${cookie.cookie存储的key.value}//获取cookie里面指定key的value
5. EL表达式中的运算符:
算术表达式:
|
比较表达式:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
判空表达式: 判断变量名是否为空或空串,如果是,则返回true,不是返回false: 1) 判断一个变量是否为null 2) 判断一个字符串是否是空串 3) 判断一个集合是否没有元素 <p>空字符串:${empty ""}</p> <p>可以取反:${not empty list}</p> |
逻辑表达式:
|
6. EL表达式的启用和禁用:
(1) page指令设置页面禁用EL(isELIgnored="true"):当在page中设置此指令时,会忽略EL表达式,所有EL表达式都不起作用。
(2) EL的转义: ${5 div 3 },当在EL表达式前面加上后,这个EL就不会起作用,表示这个表达式不起作用。
7. EL表达式中[]和.的区别:
在EL中,一共有2中写法:${ header["host"] } 和 ${header.host }
如果一个变量名中有特殊的字符,则应用使用[“名字”];
如:${header["user-agent"]},该属性名中含有特殊字符-,所以此时只能使用[ ]的写法。
19. JSP(JSTL标签库)
1. JSTL标签库概述:
Jsp Standard Tag Library ,Jsp标准标签库,一组由apache公司已经制作好的扩展标签库,可以在JSP页面直接使用。每个标签都有它自己的功能。可以替换JSP页面上的Java脚本代码。
我们使用JSTL标签库主要是使用其中的核心标签库,其前缀为c,url为http://java.sun.com/jsp/jstl/core,主要作用是一组常用的核心标签库,就是操作java逻辑控制语句的标签库,代替页面jsp脚本代码。
2. JSTL标签库使用步骤:
(1) 导包jstl.jar库到web下的lib目录;
(2) 2.在JSP页面上使用taglib指令:<%@taglib prefix=”c” uri=” http://java.sun.com/jsp/jstl/core” %>;
(3) 使用标签库;
3. JSTL标签库之set标签:
作用:往域里面设置数据
格式:<c:set var="域里面key" value="域里的值" scope="指定域"></c:set>
指定域的值page/request/session/application
例:<c:set var="username" value="admin" scope="session"></c:set>
4. JSTL标签库之out标签:
作用:用于输出el表达式数据,可以对特殊数据进行转义
格式:<c:out value="${requestScope.name }"></c:out>
注意:如果是大量数据不要直接给浏览器显示,需要使用out标签转义后再输出
例:<c:out value="${sessionScope.username}"></c:out>
5. JSTL标签库之if标签:
作用:相当于if条件句,用于分支判断
格式: <c:if test="el条件表达式"> //条件为true运行的代码 </c:if>
例:<c:set var="username" value="" scope="session"></c:set>
<c:if test="${not empty username}">
<p>你好,${username}</p>
</c:if>
6. JSTL标签库之choose标签:
作用:相当于if-else条件句,用于多分支判断
格式: <c:choose> <c:when test="${not empty username}"> when相当于if <p>你好,${username}</p> </c:when> <c:when test="${not empty username}"> when相当于else if <p>你好,${username}</p> </c:when> <c:otherwise> otherwise相当于else <p>请登录</p> </c:otherwise> </c:choose> |
例: <c:set var="username" value="" scope="session"></c:set> <c:choose> <c:when test="${not empty username}"> <p>你好,${username}</p> </c:when> <c:otherwise> <p>请登录</p> </c:otherwise> </c:choose>
|
7. JSTL标签库之forEach标签:
作用:用于循环,相当于for循环
常用属性:
begin:开始循环变量值
end:结束循环变量值
step:循环递增值,默认1
items:需要遍历的集合,使用el获取域里面的集合数据
var="user":循环变量,也是遍历集合中的每个元素,标签内部会将其放入域中
在循环过程中会执行这样操作pageContext.setAttribute("user",object);
varStatus="i":循环过程信息对象
forEach在循环过程中会产生很多循环的信息(循环的索引index,序号count),将这些封装给VarStatus对象
VarStatus varStatus = new VarStatus(index,count);
封装后会将对象存储到域中
pageContext.setAttribute("i",varStatus);
所以获取如下信息: ${i.index}获取循环索引 ${i.count}获取循环序号
格式:
普通根据次数循环格式: <c:forEach begin="1" end="5" step="1"> <p>hello world</p> </c:forEach> |
遍历集合的循环格式: <c:forEach items="${userList}" var="user"> <p>${user.age},${user.name}</p> </c:forEach> |
遍历数组: <c:forEach items="${arr}" var="num"> arr为一个数组对象 ${num} <br/> </c:forEach> |
遍历Map集合: <c:forEach items="${map}" var="entry"> map为一个Map集合 ${entry.key } -> ${entry.value} <br/> </c:forEach> |
类似于Java中for循环的用法(遍历从1到100): <c:forEach begin="1" end="100" var="i" step="2"> ${i} <br/> </c:forEach> |
20. ServletContextListener监听器
1. ServletContextListener监听器的概念:
监听器是JavaWeb三大组件(servlet,监听器,过滤器)之一,能够在web程序运行的过程中监听一些事件,对这些事件做出响应,通过编写代码对这些事件进行操作。
2. ServletContextListener的作用:
监听Servlet中ServletContext域对象,监听此作用域的创建和销毁。服务器利用“监听者(监听器)”监听“事件源对象”的变化,可以让开发人员在“事件源对象”变化发生时进行对应的控制实现。
3. ServletContextListener监听机制的组成
1)事件源:事件的发出者,ServletContext
2)事件:触发的一种行为。域对象的创建和销毁
3)监听者(服务器):接口,我们的程序实现这个接口,并且实现其中的方法。
4. ServletContextListener监听器中的方法:
接口中的方法 |
功能 |
void contextDestroyed(ServletContextEvent sce) |
web程序销毁的时候执行 |
void contextInitialized(ServletContextEvent sce) |
web程序创建的时候执行 |
5. ServletContextListener监听器的应用场景:
在服务器启动时加载配置文件,以后会学习spring框架,到时讲解加载spring的配置文件就是使用ServletContextListener监听器加载的,到时会具体讲解。
21. Filter(过滤器)
1. Filter的概述:
过滤器用来过滤用户的请求和响应,修改用户的请求和响应的数据,对请求进行拦截。如果某个功能是很多Web资源都需要执行,我们就可以在过滤器中集中进行处理。例如可以对汉字乱码进行集中的解决。
2. Filter的编写步骤:
步骤一:编写一个类,实现javax.serlvet.Filter接口
步骤二:重写接口中doFilter的方法,所有的过滤都是通过doFilter方法来过滤的;chain.doFilter(request, response);
步骤三:在web.xml中配置过滤器,配置需要过滤哪些用户访问的资源(详细配置请看下方配置映射路径和过滤类型)
3. Filter的执行流程和生命周期:
(1) 单一过滤器的执行流程:
当前端浏览器发送请求时,该请求会先来到过滤器中的doFilter方法,对请求进行过滤,然后通过该方法中的chain.doFilter(request, response);步骤进行放行,执行相应的servlet资源,当执行完毕后又会返回到此过滤器中,对响应进行过滤,最后才会将响应的数据发送给前端。
(2) 过滤器链的执行流程:
过滤器链就是多个过滤器同时过滤一个资源,这些过滤器就形成过滤器链。
当用户发送请求后,第一个过滤器会对用户的请求进行过滤,再将该请求传送给第二个过滤器,当第二个过滤器过滤完后才会执行对应的servlet,servlet返回的响应会先返回第二个过滤器,过滤完后再该响应会传送到第一个过滤器里,再次进行过滤后才会在浏览器上显示出来。
(3) 过滤器的生命周期:
因为过滤器是对浏览器的请求进行过滤的,所以创建的时间是很早的,当服务器进行加载时就已经创建好这个过滤器了,然后每次浏览器发送请求时,都会执行一次过滤器的doFilter方法,对数据进行过滤,当服务器关闭或者重启时,过滤器也会相应的进行销毁操作。
4. Filter配置映射路径:
(1) web.xml中的配置信息如下(以解决全局乱码为例) :
<filter>
<filter-name>CharacterFilter</filter-name>
<filter-class>com.itheima.filter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterFilter</filter-name>
<url-pattern>/*</url-pattern>
<servlet-name> </servlet-name>
<dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher>
</filter-mapping>
(2) Filter与Servlet中<url-pattern>的区别:
Servlet中的url-pattern是它的访问地址, Filter中url-pattern是过滤地址。
浏览器访问目标资源的路径,如果不存在,过滤器也会执行,只要匹配访问的url-pattern就会执行过滤器。
(3) 在Filter中URL的过滤方式:
Filter中的URL过滤方式和Servlet中的过滤方式基本相同。
但Servlet不允许使用缺省路径(/或/*),会导致静态资源无法访问,Filter可以使用缺省路径,表示全局过滤。
(4) 过滤器中匹配的要点:
a. 一个filter-mapping中写多个url-pattern,这会过滤所有的url-pattern对应的web资源。
b. 一个filter对应多个filter-mapping,这也会过滤所有filter-mapping中url-pattern对应的web资源。
c. 过滤Servlet的写法:在filter-mapping中,还可以写入<servlet-name> </servlet-name>,表示要过滤指定servlet
5. Filter的过滤类型:
没有配置过滤器类型采用默认的request,如果配置了过滤器就按照配置的类型执行过滤。
以后request和forward常用,所以一般这两都配置上。
REQUEST : 来自于用户的请求才经过过滤器(包括重定向),默认值
FORWARD: 来自于页面的转发才经过过滤器
INCLUDE: 来自于页面的动态包含才经过过滤器
ERROR: 来自于错误页面的跳转才经过过滤器
6. 装饰者模式:
(1) 概念:本来有一个类,对这个类中的某个方法的功能进行增强,不能修改这个方法的源代码。使用装饰者设计模式可以达到对以实现功能进行持续增强。
(2) 步骤:a.编写一个类,继承于具体对象。b.在装饰类中有一个抽象对象的成员变量,通过构造方法传递进来。
c.重写具体对象的方法,对这个方法进行功能的增强。
7. 解决全局乱码问题:
(1) 将传入的请求和响应对象分别转成子类的对象(HttpServletRequest和HttpServletResponse)
(2) 对请求添加的方法进行判断,如果是Post提交进行Post解决,如果是Get提交进行Get解决
① 解决请求中post方法的乱码问题(request.setCharacterEncoding("utf-8");)
② 解决请求中get方法的乱码问题(使用装饰模式对请求中的方法getParameter()进行重写)
(3) 解决响应中的乱码问题(response.setContentType("text/html; charset = utf-8 ");)
(4) 调用方法,进行放行(chain.doFilter(req, resp);)
8. 自动登录功能实现:
22. AJAX
1. AJAX介绍:
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML)可以使网页实现异步更新,就是不重新加载整个网页的情况下,对网页的某部分进行更新(局部刷新)。传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。
AJAX = 异步 JavaScript和XML,是一种新的思想,整合之前的多种技术,用于创建快速交互式网页应用的网页开发技术。
2. 同步与异步的区别:
同步概念:客户端发送请求到服务端,当服务端返回响应之前,客户端都处于等待卡死状态。
异步概念:客户端发送请求到服务端,无论服务端是否返回响应,客户端都可以在该页面中随意做其他事情,不 会被卡死,提高了用户的体验。
3. AJAX原理分析:
4. Jquery的AJAX使用:
jQuery.post(url, [data], [callback], [type]); 以post请求方式发送ajax
jQuery.get(url, [data], [callback], [type]); 以get请求方式发送ajax
参数1:url,请求路径
参数2:data,请求参数,可以分为普通格式和json对象格式
普通格式:key1=value1&key2=value2...; json对象格式(就是js对象格式),{key1:value1,key2:value2....}
参数3:callback,回调函数,function(result){…},这里的参数result是服务器响应的数据
参数4:type,返回内容格式,xml, html, script, json, text, _default,一般使用json格式
5. JSON数据:
(1) 什么是JSON数据:JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON采用完全独立于语言的文本格式,就是说不同的编程语言JSON数据是一致的。
(2) JSON格式:
JSON对象格式
{"key":"value","key":"value",....}
键和值使用冒号分隔。
标准规范要求key必须使用双引号,value如果没有使用双引号表示变量。
JSON数组
[ obj , obj , obj , ....]
表示一组值,多个值使用逗号分隔
(3) JSON-LIB工具( 就是一个json的jar包,现在一般使用gson的jar包 )
使用JSONObject对象将user对象转换为json对象格式:JSONObject.fromObject(user).toString();
使用JSONArray对象将userList转换为json数组格式:JSONArray.fromObject(userList).toString();
23. Redis(NOSQL数据库)
1. NOSQL概述:
(1) 什么是NOSQL:Not Only SQL,意即“不仅仅是SQL”,是一项全新的数据库理念,泛指非关系型的数据库。
(2) 为什么需要NOSQL数据库( NOSQL可以对如下三高问题解决 ):
High performance - 对数据库高并发读写的需求
Huge Storage - 对海量数据的高效率存储和访问的需求
High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求
(3) NOSQL的特点:易扩展;大数据量,高性能;灵活的数据模型;高可用。
2. Redis概述:
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,目前为止Redis支持的键值数据类型如下:
字符串类型 string, 散列类型 hash, 列表类型 list, 集合类型 set, 有序集合类型 sortedset
我们一般使用字符串类型。
3. Redis的下载、安装和使用:
(1) 下载Redis:
官方提供了Linux版的Redis,但Windows版的只能从GitHub中下载,具体链接地址如下:
官网下载地址:http://redis.io/download
github下载地址:https://github.com/MSOpenTech/redis/tags
(2) window版Redis的安装和使用( 本地安装 ):
window版的安装及其简单,解压Redis压缩包完成即安装完毕,其具体目录结构如下:
redis-benchmark: 性能测试工具
redis-check-aof AOF: 文件修复工具
redis-check-dump: RDB文件检查工具(快照持久化文件)
redis-cli: 命令行客户端
redis-server: redis服务器启动命令
redis.windows.conf: redis核心配置文件
双击Redis目录中redis-server.exe可以启动redis服务,Redis服务占用的端口是6379,关闭Redis的控制台窗 口就可以关闭Redis服务;双击Redis目录中redis-cli.exe可以启动redis客户端。
(3) Linux版Redis的安装( 本地安装 ):
步骤一:redis是C语言开发,安装redis需要对源码进行编译,编译依赖gcc环境。 yum install gcc-c++
步骤二:上传"redis-3.0.0.tar.gz"到linux系统/soft目录下
步骤三:进入soft目录,将"redis-3.0.0.tar.gz"解压到/usr/local目录下 tar -zxvf redis-3.0.0.tar.gz -C /usr/local
步骤四:进入redis-3.0.0目录 使用make命令编译redis,如下信息代表编译成功 ‘make test’ ; )
步骤五:在redis-3.0.0目录中 使用 make PREFIX=/usr/local/redis install 命令安装redis到/usr/local/redis中
(4) Linux版Redis的服务端启动( 一般不使用前端模式启动,这里介绍后端模式启动 ):
步骤一:将 /usr/local/redis-3.0.0/redis.conf 复制到 /usr/local/redis/bin/。 cp redis.conf /usr/local/redis/bin/
步骤二:修改redis.conf配置文件, daemonize yes 以后端模式启动。vim /usr/local/redis/bin/redis.conf
步骤三:启动时,指定配置文件 cd /usr/local/redis/bin ./redis-server redis.conf
(5) Linux版Redis的其他操作:
Redis默认端口6379,可以通过当前服务进行查看:ps -ef | grep -i redis
启动客户端命令:进入redis/bin目录,启动"redis-cli" ./redis-cli
redis停止:强制停止, kill -9 31475 #pid需要通过“ps -ef|grep redis”进行查询
正常关闭, 向Redis发送SHUTDOWN命令 cd /usr/local/redis ./bin/redis-cli shutdown
远程连接:如需远程连接redis,需配置redis端口6379在linux防火墙中开发
#开放6379端口 /sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
#开放的端口永久保存到防火墙 firewall-cmd --zone=public --add-port=6379/tcp --permanent
4. Redis的数据类型( 比较常用字符串类型 ):
(1) 字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型存入和获取的数据相同。在Redis中字符串类型的Value最多可以容纳的数据长度是512M。
(2) 字符串类型string常用命令:
set key value: 设定key持有指定的字符串value,如果该key存在则进行覆盖操作。总是返回”OK”
例:set company "itcast"
get key:获取key的value。如果与该key关联的value不是String类型,redis将返回错误信息,因为get命令 只能用于获取String value;如果该key不存在,返回(nil)。 例:set name "itcast"
del key:删除指定key 例:del name
5. Redis中keys的通用操作( 所谓通用操作是指,不管value是五种类型中的哪一种类型,都可以用的操作 ):
(1) keys pattern : 获取所有与pattern匹配的key,*表示任意0个或多个字符,?表示任意一个字符
例:keys * 查找出所有的key值
(2) del key key key : 删除指定的key
例:del username password gender 删除key为username,password,gender的键值对
(3) exists key:判断该key是否存在,1表示存在,0表示不存在
例:exists username 如果username存在返回1,不存在返回0
(4) rename key newkey : 将当前key重命名为newkey
例:rename username newusername 将username重命名为newusername
(5) type key :获取指定key的类型,以字符串形式返回,返回值为:string/hash等,如果key不存在,返回none
例:type username 返回username的类型
(6) select:一个Redis服务器可以包括多个数据库,客户端可以指连接Redis中的哪个数据库,例:select 1
(7) move : 移key到其他数据库 例:move key 1 : 将当前数据库中的key移到1号数据库中
6. Redis的持久化:
(1) 持久化概述:Redis的高性能是由于其将所有数据都存储在了内存中,为了使Redis在重启之后仍能保证数据不丢失,需要将数据从内存中同步到硬盘中,这一过程就是持久化。Redis支持两种方式的持久化,一种是RDB方式,一种是AOF方式。可以单独使用其中一种或将二者结合使用。
(2) RDB持久化( 默认支持,无需配置,在指定的时间间隔内将内存中的数据集快照写入磁盘 ):
优点:采用该方式,那么你的整个Redis数据库将只包含一个文件,可以非常容易的进行恢复;此方式是由子 线程进行IO写入,做到了性能最大化。
缺点:由于是在一段时间后才会执行持久化,所以如果在这段时间内发生宕机现象,数据不会保存;因为是 通过子线程进行持久化操作的,所以如果数据过大时执行持久化有几百毫秒的卡顿现象。
(3) AOF持久化( 该持久化需手动开启 ):
优点:该机制可以带来更高的数据安全性,即数据持久性;该机制写入数据时执行的是append模式,所以就 算发生宕机现象,也比较安全;如果日志过大,Redis可以自动启用rewrite机制,更能保证数据安全。
缺点:对于相同数量的数据集而言,AOF文件通常要大于RDB文件;根据同步策略的不同,AOF在运行效 率上往往会慢于RDB。
7. Jedis的基本使用:
(1) Jedis的基本基本操作和常用方法:
a. Jedis介绍:
Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java、C、等。 在官方网站里列一些Java的客户端,有Jedis、Redisson、Jredis、JDBC-Redis、 等其中官方推荐使用Jedis和Redisson。 在企业中用的最多的就是Jedis,Jedis同样也是托管在github上,地址:https://github.com/xetorthio/jedis。
b. 常用方法如下:
new Jedis(host, port): 创建jedis对象,参数host是redis服务器地址,参数port是redis服务端口
set(key,value): 设置字符串类型的数据
get(key): 获得字符串类型的数据
hset(key,field,value): 设置哈希类型的数据
hget(key,field) : 获得哈希类型的数据
lpush(key,values): 设置列表类型的数据
del(key): 删除指定的key
c. jedis的基本操作:
//1 设置ip地址和端口
Jedis jedis = new Jedis("localhost", 6379);
//2 设置数据
jedis.set("name", "itheima");
//3 获得数据
String name = jedis.get("name");
System.out.println(name);
//4 释放资源
jedis.close();
(2) Jdeis连接池的使用:
- 连接池的基本概念:
jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的池化技术,jedisPool在创建时初始化一些连接资源存储到连接池中,使用jedis连接资源时不需要创建,而是从连接池中获取一个资源进行redis的操作,使用完毕后,不需要销毁该jedis连接资源,而是将该资源归还给连接池,供其他请求使用。
- jedisPool的基本使用
public void testJedisPool(){
//1 获得连接池配置对象,设置配置项
JedisPoolConfig config = new JedisPoolConfig();
// 1.1 最大连接数
config.setMaxTotal(30);
// 1.2 最大空闲连接数
config.setMaxIdle(10);
//2 获得连接池
JedisPool jedisPool = new JedisPool(config, "localhost", 6379);
//3 获得核心对象
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//4 设置数据
jedis.set("name", "itcast");
//5 获得数据
String name = jedis.get("name");
System.out.println(name);
} catch (Exception e) {
e.printStackTrace();
} finally{
if(jedis != null){
jedis.close();
}
// 虚拟机关闭时,释放pool资源
if(jedisPool != null){
jedisPool.close();
}
}
}
24. Maven基础
1. Maven的概念:
Maven是项目进行模型抽象,充分运用的面向对象的思想,Maven可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。
2. Maven的作用:
maven对项目的第三方构件(jar包)进行统一管理。向工程中加入jar包不要手工从其它地方拷贝,通过maven定义jar包的坐标,自动从maven仓库中去下载到工程中。maven提供一套对项目生命周期管理的标准,开发人员、和测试人员统一使用maven进行项目构建。项目生命周期管理:编译、测试、打包、部署、运行。
3. Maven的概念模型:
项目对象模型 (Project Object Model)。POM对象模型,每个maven工程中都有一个pom.xml文件,定义工程所依赖的jar包、本工程的坐标、打包运行方式。
4. Maven的仓库:
本地仓库:相当于缓存,工程第一次会从远程仓库(互联网)去下载jar 包,将jar包存在本地仓库。
中央仓库:就是远程仓库,仓库中jar由专业团队(maven团队)统一维护。
远程仓库:在公司内部架设一台私服,其它公司架设一台仓库,对外公开。
5. Maven的坐标:
Maven的一个核心的作用就是管理项目的依赖,引入我们所需的各种jar包等。为了能自动化的解析所有Java构件,Maven将这些Jar包或者其他资源进行唯一标识,这是管理项目的依赖的基础,也就是我们要说的坐标。
坐标中的属性: groupId:定义当前Maven项目名称 artifactId:定义项目模块 version:定义当前项目的当前版本 |
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> |
6. Maven的安装和配置:
(1) 下载Maven:可以取Maven官方网站上下载Maven
(2) 安装Maven:将下载的压缩包解压即可,跟Tomcat服务器类似
(3) 配置环境变量:给Maven配置一个环境变量,配置方式跟JDK的环境变量配置方式类似
(4) 配置本地仓库:将Maven里的配置文件Settring.xml中的localRepository属性配置成本地仓库的地址即可
(5) 测试Maven安装成功:打开cmd本地控制台,输入mvn -version,显示Maven版本即配置成功
7. IDEA绑定Maven配置:
(1) 将Maven加载到IDEA中:
File -> Setting -> Build,Execution,Deployment -> Build Tools -> Maven :进行下图所示配置
(2) 设置使用本地仓库:
File -> Setting -> Build,Execution,Deployment -> Build Tools -> Maven -> Runner:
VMoptions:-DarchetypeCatalog=internal ( 设置这个参数会先从本地获取jar包,如果没有才去网上获取 )
(3) idea使用maven项目生命周期管理命令时,会输出中文乱码,解决方案:
File -> Setting -> Build,Execution,Deployment -> Build Tools -> Maven -> Runner:
VMoptions: -Dfile.encoding=GB2312
8. 使用Maven骨架创建JavaWeb工程:
(1) 点击File,新建Module,选择Maven骨架中的webapp创建项目;
(2) 将关联的module和父项目选为none,填写详细坐标信息( 可以填写当前的工程名和模块名[跟install有关] );
(3) 选择本机的Maven信息;
(4) 指定模块名称,工程名称和存储位置,点击Finish完成创建;
(5) 在main目录下创建java源代码目录和resources目录,在src下创建test目录,在test下创建java测试目录;
9. Java工程和Web工程的Maven目录结构:
(1) Java工程的Maven目录结构: |
(2) Web工程的Maven目录结构: |
10. Maven的常用命令:
(1) clean:清除编译产生的target文件夹内容,可以配合相应命令一起使用,如mvn clean package, mvn clean test
(2) complie:该命令可以对src/main/java目录的下的代码进行编译
(3) package:mvn package,打包项目,打包后的项目会在target目录下找到
(4) install:mvn install,打包后将其安装在本地仓库,安装完毕后,在本地仓库中可以找到该项目的信息
11. Maven的插件导入:
Maven是一个核心引擎,提供了基本的项目处理能力和建设过程的管理,以及一系列的插件是用来执行实际建设任务。maven插件可以完成一些特定的功能。例如,集成jdk插件可以方便的修改项目的编译环境;集成tomcat插件后,无需安装tomcat服务器就可以运行tomcat进行项目的发布与测试。在pom.xml中通过plugin标签引入maven的功能插件。
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
12. Maven的依赖管理:
(1) 导入依赖:
导入依赖坐标,无需手动导入jar包就可以引入jar。在pom.xml中使用<dependency>标签引入依赖。
导入servlet的依赖:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
如果本地仓库没有,可以去网络地址查:https://mvnrepository.com/
(2) 依赖范围:
根据<scope>test</scope>标签来设置依赖范围
依赖范围 |
对于编译classpath有效 |
对于测试classpath有效 |
对于运行时classpath有效 |
例子 |
compile |
Y |
Y |
Y |
spring-core |
test |
- |
Y |
- |
Junit |
provided |
Y |
Y |
- |
servlet-api |
runtime |
- |
Y |
Y |
JDBC驱动 |
system |
Y |
Y |
- |
本地的,Maven仓库之外的类库 |
按照依赖强度,由强到弱来排序:compile> provided> runtime> test |
25. Maven高级
1. 在Maven项目中需注意的事项:
(1) 常见的命令:
Compile:编译; Test:测试; Package:打包;
Install:安装(安装到本地仓库); Deploy:部署(部署到私服等); Clean:清空,将打包好的包删除;
(2) 坐标的书写规范:
groupId: 公司或组织域名的倒序
artifactId: 项目名或模块名
Version: 版本号
(3) 依赖范围:
compile:编译依赖范围,在编译,测试,运行时都需要。
test:测试依赖范围,测试时需要。编译和运行不需要。如 Junit
runtime:运行时依赖范围,测试和运行时需要。编译不需要。如 JDBC 驱动包
provided:已提供依赖范围,编译和测试时需要。运行时不需要。如 servlet-api
2. Maven构建 SSM工程中的知识点:
(1) 依赖传递:
- 什么是依赖传递:A依赖B,B依赖C 相当于 A传递依赖C;
- 依赖冲突解决( 当B和C都依赖了同一jar包,但版本不同时,会发生依赖冲突 ):
方法一:声明优先,在同路径(从依赖到具体的包的路径)下;会使用在前面声明的坐标;
方法二:路径近者优先,如果依赖坐标对应的路径比较短则优先使用该坐标对应的依赖;
方法三:排除传递依赖;在坐标里面设置配置的坐标信息;配置之后则不会再传递相关的依赖;
例: <exclusions> <exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion> </exclusions>
(2) 锁定版本:
面对众多的依赖,有一种方法不用考虑依赖路径、声明优化等因素可以采用直接锁定版本的方法确定依赖构件的版本,版本锁定后可以统一在一个地方设置依赖的版本号则所有使用了该坐标的工程中的依赖都使用该版本。此方法在企业开发中常用。
<!--定义版本号变量-->
<properties> <mybatis.version>3.4.5</mybatis.version> </properties>
<!-- 锁定依赖版本 -->
<dependencyManagement> <dependencies> <dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency> </dependencies> </dependencyManagement>
<!-- 添加依赖 -->
<dependencies> <dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency> </dependencies>
注意:在工程中锁定依赖的版本并不代表在工程中添加了依赖,如果工程需要添加锁定版本的依赖则需要单独添加<dependencies></dependencies>标签,当在<dependencyManagement>中锁定了版本,所以在<dependency>下不需要再指定版本。
3. 使用Maven分模块构建工程:
(1) 继承和聚合:
继承:父工程有的子工程也要有,可以将子工程中重复的配置提取出来在父工程的 pom.xml 中定义。
聚合:将一个工程拆分成多个子工程,某个聚合子工程可以独立给予其它工程作为依赖。
(2) 依赖范围对传递依赖的影响:
依赖会有依赖范围,依赖范围对传递依赖也有影响,例如有 A、B、C,A依赖 B、B 依赖 C,C 可能是 A 的传递依赖,如下图:最左边一列为直接依赖,理解为 A 依赖 B 的范围,最顶层一行为传递依赖,理解为 B 依赖 C 的范围,行与列的交叉即为 A 传递依赖 C 的范围。
传递依赖 |
compile |
provided |
runtime |
test |
compile |
compile |
- |
runtime |
- |
provided |
provided |
provided |
provided |
- |
runtime |
runtime |
- |
runtime |
- |
test |
test |
- |
test |
- |
举例一:比如A对B有compile 依赖,B对C有 runtime 依赖,那么根据表格所示 A对 C 有 runtime 依赖。
举例二:如果修改 ssm_dao 工程依赖 junit 的 scop 为 compile,ssm_dao 工程所依赖的 junit 的 jar 包会 加入到 ssm_service 工程中,符合上边表格所示。
4. Maven私服:
关于Maven私服的安装、配置和第三方jar包的上传和下载请查看nexus安装的详细文档。
26. Git工具的使用
1. Git概述:
Git是分布式版本控制系统,SVN是集中式版本控制系统。
2. Git工作流程( 重点,必须掌握 ):
(1) 从远程版本库中克隆(仓库,工作目录) (2) 在工作目录中修改具体的文件, (3) 将修改提交到暂存区 (4) 将修改从暂存区提交到本地版本库(新版本号) (5) 可以加个本地版本库中的版本推送到远程版本库 (6) 可以从远程版本库中拉取最新的修改版本 |
3. Git安装和使用:
关于Git安装和使用以及更详细的配置请查看Git的安装文档
27. 框架概述
1. 什么是框架:
框架(Framework)是整个或者部分系统的可重用设计,是J2EE底层技术的封装。框架是可以被应用开发者(程序员)定制的应用骨架。简而言之,框架其实就是别人搭好了舞台,你来做表演。
2. 框架解决的问题:
(1) 框架解决了技术整合问题。在J2EE体系中,有着各种各样的技术。不同的软件企业,根据自身的业务需求选择不同的技术,容易造成应用依赖技术,增加了项目开发实现的复杂性和技术风险性。企业项目中应该将应用的设计与实现技术解耦。
(2) 框架解决了提升开发效率的问题。企业项目中使用框架,程序员不再需要重复造轮子,只需要专注实现业务需求。使用框架的方便性,提升了开发效率。
(3) 框架解决了稳定性的问题。一个成熟的框架,经过了在众多企业项目中的验证使用。稳定性有保障
3. 软件开发中的分层思想:
4. 分层开发下常见框架:
(1) MyBatis:解决数据持久化问题的框架;
(2) Spring MVC:解决web表现层的mvc框架;
(3) Spring:解决技术整合问题的框架;
28. MyBatis
28.1. mybatis介绍:
(1) mybaits框架的早期版本叫做Ibatis,目前托管在github。
(2) mybatis框架是一个持久层的框架,是对jdbc的封装。
(3) mybatis框架通过xml或者注解进行配置,实现java对象与sql语句的映射(对应关系)。
28.2. mybatis入门程序( 能够使用mybatis框架对数据库进行操作 ) :
(1) 配置pom.xml文件,加入依赖,即导入jar包( 加入后需刷新右侧的Maven,看jar包是否已经导入 );
(2) 编写配置文件( 使用框架的两大特点:一个是框架的jar包;另外一个则是框架的配置文件 ):
- 编写mybatis框架的主配置文件,该文件名称可以修改,默认使用sqlMapConfig.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 运行环境配置 --> <!-- 加载mapper映射文件,此文件详情请看步骤(5) -->
</configuration>
- 编写日志的配置文件( 此配置文件可以在运行过程中进行日志的打印 ):
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
日志文件的依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
(3) 编写用户实体类对象;
(4) 编写mapper.xml映射文件( 此配置文件的主要用于配置java对象与sql语句的对应关系 ):
一般来说,一个mapper.xml文件对应一个实体类对象,所以在一个项目中存在很多的该映射文件,可以创建一个文件夹来放置;另外,使用框架,程序的入口是主配置文件,需要将其它配置文件在主配置文件中进行加载。所以要在主配置文件中添加<mappers>标签,用来加载mapper.xml文件,请看步骤(2)。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:名称空间,相当于java中的package,用于防止sql语句名称的冲突(sql语句的隔离) -->
<!--mybatis框架针对每一种数据库语句:新增/查询/修改/删除,提供了对应的标签:select/update等来放置-->
<!-- select:用于放置查询的sql语句 id:唯一标识一条sql语句, parameterType:输入参数的类型
resultType:返回值类型(暂时注意是类的全限定名称) #{id}:占位符,相当于jdbc中的?-->
(5) 编写测试代码:
//1.加载主配置文件sqlMapConfig.xml (一般封装到工具类中)
//2.读取主配置文件内容 (一般封装到工具类中)
/**SessionFactory对象:
* a.它是mybatis框架的核心对象
* b.它是线程安全的,一个应用中通常只需要一个即可
* c.它可以给我们打开SqlSession对象
*/
//3.打开SqlSession对象 (一般使用工具类获取的SqlSessionFactory对象进行打开)
/**SqlSession对象:
* a.它给我们提供了操作数据库的CRUD方法
* b.它是线程不安全的,每一个执行的方法都需要创建一个
*/
// 4.调用API方法执行
/**
* selectOne方法:查询单条记录
* 参数一:执行的sql语句(名称空间+"."+sql语句的id) 参数二:传入的参数值
*/
Object user = sqlSession.selectOne("test.queryUserById", 24);
//5.释放资源
sqlSession.close();
27.3. mybaits中的小知识点:
(1) 占位符#{}和${}的区别 ( 在项目中一般使用#{},当进行模糊查询时才考虑使用${} ):
- 占位符#{},相当于jdbc中的问号?。当参数传递的是java简单类型(八种基本类型+字符串String)的时候,花括号中的内容可以是任意字符串。
- 字符串拼接符${},当参数传递的是java简单类型的时候,花括号中的内容只能是:value
- 占位符#{}与字符串拼接符${},当参数传递的是pojo类型的时候,花括号中的内容都是pojo的属性
(2) mybaits中的提交事务:
- 手动提交事务( sqlSession.commit(); ):
当需要执行的sql语句全部执行完后,通过代码手动提交数据,可以保证所有的sql语句全部执行成功后才会改变数据库中的数据,如果其中的某条sql语句异常,不会执行提交的代码,能保证数据安全性。
- 自动提交事务( 打开sqlSession对象的时候,指定自动提交事务,代码:sessionFactory.openSession(true); ):
在打开sqlSession对象时,如果设置为true就为自动提交事务,不设置就不会自动提交;如果设置为自动提交事务那只要操作一完成就提交事务,如果有多个操作,且要考虑事务回滚的情况下,需要使用手动提交事务的方式。
(3) 获取数据库维护的主键值:
在企业项目中,如果数据库表的主键字段值由数据库自行维护,则不需要我们在java程序中进行传递。但是我们有这样的需求,比如新增一个用户后,需要给该用户分配权限,需要该用户id值。即需要把数据库维护的主键值查询出来。
方式一: selectKey:查询数据库维护的主键值,说明: keyColumn:主键字段 keyProperty:主键属性 resultType:主键类型 order:指定在insert语句执行之前,还是之后获取主键值。 AFTER:在insert执行后;BEFORE:在insert执行前 <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER"> select last_insert_id() </selectKey> |
方式二: 在要执行的sql语句的标签中添加如下属性: useGeneratedKeys="true" keyColumn="id" keyProperty="id" 即可以获取主键值 |
27.4. mybaits的框架原理:
a. Configuration:配置对象,它的内容是主配置文件(sqlMapConfig.xml),具体mapper映射文件(User.xml.......)
b. MappedStatment:输入输出映射对象,paramterType参数输入,resultType返回值输出
c. Executor:执行器对象,执行数据库的CRUD操作
27.5. mapper代理开发原则:
(1) 要求mapper映射文件中namespace属性值,必须是mapper代理接口的全限定名称;
(2) 要求mapper映射文件中sql标签的声明,与mapper代理接口中方法的声明一致;
- sql标签中resultType属性指定的类型(如果返回的结果是集合,那么resultType指定的是集合中存放的类型),与mapper接口方法返回值类型一致
- sql标签中id属性值,与mapper接口方法名称一致
- sql标签中parameterType属性指定的类型,与mapper接口方法的形参类型一致
(3) 代码实现:
- 编写mapper代理接口,即编写一个dao层的数据库访问的接口;
- 编写UserMapper.xml映射文件,命名需根据mapper代理开发原则来命名;
- 在sqlMapConfig.xml文件中,加载UserMapper.xml文件;
- 具体代码调用:
// 1.创建sqlSession对象(使用工具类)
SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();
//2.使用sqlSession对象,调用API方法获取mapper代理对象
// getMapper方法:获取mapper代理对象 参数:被代理接口的字节码
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//3.使用mapper对象,调用具体的方法,实现对数据库的操作
User user = mapper.queryUserById(2);
//4.释放资源
sqlSession.close();
27.6. mybatis主配置文件:
(1) 主配置文件sqlMapConfig.xml文件可以配置内容如下:
顺序 |
配置标签名称 |
说明 |
|
1 |
properties |
属性 |
1.红色字体内容要求掌握 |
2 |
settings |
配置全局参数 |
|
3 |
typeAliases |
类型别名 |
|
4 |
typeHandlers |
类型处理器 |
|
5 |
objectFactory |
对象工厂 |
|
6 |
plugins |
插件 |
|
7 |
environments |
环境集合属性对象 |
|
8 |
databaseIdProvider |
多数据库支持 |
|
9 |
mappers |
映射器 |
(2) properties(属性):
- 作用:加载属性文件(比如db.properties)和定义属性
- 编写db.properties文件:
db.driver=com.mysql.jdbc.Driver db.url=jdbc:mysql://127.0.0.1:3308/mybatis
db.username=root db.password=admin
- 加载db.properties文件:
<!--加载属性文件,说明: resource:加载本地的属性文件 url:加载网络上的属性文件 -->
<properties resource="db.properties"></properties>
- 使用db.properties文件中的属性:
//在进行数据库配置时可以如下方法使用 <property name="driver" value="${db.driver}" />
- 使用property标签的其他声明:
可以使用resource加载本地的属性文件,可以使用url属性加载网络上的属性文件。先加载内部property标签定义的属性,再加载属性文件中的属性。如果相同,属性文件中的属性覆盖property标签定义的属性。
(3) typeAliases(类型别名):
- 内置别名:
内置别名可以直接使用,别名不区分大小写;
- 自定义别名:
方式一( 了解 ): <!--配置自定义别名--> <typeAliases> <!--配置单个别名,说明: 1.type:别名的类型 2.默认使用类的名称作为别名的名称 3.alias:别名的名称 --> <typeAlias type="cn.itheima.po.User" alias="user"/> </typeAliases> |
方式二( 很重要 ): <!--配置自定义别名--> <typeAliases> <!--包扫描方式配置别名,说明: 1.name:要扫描的包 2.有多个包,在同一个父包下,配置父包即可 3.不在同一个父包,配置多个package标签 4.在企业项目中,推荐使用包扫描方式 --> <package name="cn.itheima.po"/> </typeAliases> |
(4) mappers( 映射器 ):
a. 可以进行包扫描方式加载mapper映射文件:
<!--加载mapper映射文件-->
<mappers>
<!--加载User.xml文件,说明: resource:指定映射文件的位置 -->
<mapper resource="sqlmap/User.xml" />
<!--加载UserMapper.xml
<mapper resource="sqlmap/UserMapper.xml"/>-->
<!--包扫描方式加载别名,说明:
1.前提是mapper代理开发方法
2.要求mapper映射文件,与mapper接口在同一目录
3.要求mapper映射文件的名称,与mapper接口名称一致
4.企业项目中推荐使用这种方式
-->
<package name="cn.itheima.mapper"/>
</mappers>
b. 注意事项:使用idea开发工具,所有配置文件都需要放在resources资源目录下。此时需要在resources下 创建对应的目录。比如cn.itheima.mapper,并且把UserMapper.xml文件移动到该目录下。
27.7.mybatis输入输出映射
- 1. ParameterType输入映射:
(1) 可以是简单类型,当为简单类型时,直接在ParameterType中写入具体的简单类型即可;
(2) 可以是pojo参数类型:'%${user.username}%'
- 2. ResultType输出映射:
(1) java简单类型:在ResultType中直接写入具体的简单类型即可;
(2) pojo类型:在ResultType中写入具体映射的对象;
- 3. ResultMap输出映射:
<resultMap id="ordersResultMap" type="orders">
<!--配置订单的主键对应关系,说明:
column:主键字段 property:主键属性 -->
<id column="id" property="id"/>
<!--配置订单普通字段对应关系-->
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
</resultMap>
<!--查询全部订单数据,使用ResultMap实现结果映射-->
<select id="queryAllOrdersByResultMap" resultMap="ordersResultMap">
select o.id,o.user_id,o.number,o.createtime,o.note from orders o
</select>
27.8.mybatis动态sql
- 1. if标签:判断传入的参数情况,拼装sql语句。
<!--if标签:判断用户名称不为空,且不为空字符串,就作为查询条件-->
<if test="username !=null and username !=''">
username like #{username} </if>
- 2. where标签:
where标签,相当于sql语句中的where关键字;根据传入的参数情况,智能的去掉多余的and、or条件关键字;根据传入的参数情况,智能的去掉多余的where关键字。
- 3. set标签:
相当于sql语句中的set关键字,根据传入的参数情况,智能的去掉多余的逗号。
- 4. sql(include)标签:
说明:sql标签:提取公共的sql语句片段;include标签:用于引用sql片段。
<!--提供查询订单字段列表,说明: id:唯一标识名称,通过id引用该sql片段 -->
<sql id="select_orders_list">
o.id,o.user_id,o.number,o.createtime,o.note
</sql>
<!--查询全部订单数据-->
<select id="queryAllOrders" resultType="orders">
<!-- select o.id,o.user_id,o.number,o.createtime,o.note from orders o-->
<!--include标签:引用sql片段,说明: refid:被引用的sql片段的id -->
select <include refid="select_orders_list"/> from orders o
</select>
- 5. foreach标签:
作用:循环处理参数集合(list、数组)。
<!--批量新增用户-->
<insert id="batchInsertUsers" parameterType="list">
insert into `user`(username,birthday,sex,address) values
<!--('用户1','2018-04-30','1','地址1'),('用户2','2018-04-30','1','地址12')
foreach标签:循环处理参数集合
collection:参数集合,这里是list
item:当前遍历的对象
separator:元素间的分割符
-->
<foreach collection="list" item="u" separator=",">
(#{u.username},#{u.birthday},#{u.sex},#{u.address})
</foreach>
</insert>
27.9.mybatis关联查询
- 1. 关联关系分类:
(1) 一对一关联关系,人和身份证的关系。一个人只能有一张身份证,一张身份证只能属于一个人。双向的【一对一】关联关系。
(2) 一对多关联关系,人和订单的关系。一个人可以有多个订单,从人到订单是【一对多】关联关系。一个订单只能属于一个人,从订单到人是【一对一】的关联关系。
(3) 多对多关联关系,学生和课程的关系。一个学生可以选择多门课程,一门课程也可以被多个学生选择。多对多关联关系,在实际项目中,通常看成两个一对多的关联关系。因此我们这里讲的其实是一对一关联关系,和一对多关联关系。
- 2. 一对一关联查询:
<!--配置订单到用户的一对一关联关系,说明:
id:唯一标识名称,通过id引用该ResultMap type:要映射的类型 -->
<resultMap id="ordersUsersResultMap" type="orders">
<!--配置订单的主键对应关系-->
<id column="id" property="id"/>
<!--配置订单的普通字段对应关系-->
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!--配置订单到用户的一对一关联关系: association:配置一对一关联关系
属性: property:映射的属性名称 javaType:映射的属性类型(必须要指定)-->
<association property="user" javaType="User">
<!--配置用户主键对应关系-->
<id column="user_id" property="id"/>
<!--配置用户普通字段对应关系-->
<result column="username" property="username"/>
<result column="address" property="address"/>
</association>
</resultMap>
<!--查询全部订单数据,并且关联查询出所属的用户数据-->
<select id="queryAllOrdersAndUsers" resultMap="ordersUsersResultMap">
SELECT o.id, o.user_id, o.number, o.createtime, o.note, u.username, u.address FROM
orders o LEFT JOIN `user` u ON o.user_id = u.id
</select>
- 3. 一对多关联查询:
<!--配置用户到订单一对多关联关系,说明:
id:唯一标识名称,通过id引用该resultMap; type:要映射的类型 -->
<resultMap id="usersAndOrdersResultMap" type="user">
<!--配置用户的主键对应关系-->
<id column="id" property="id"/>
<!--配置用户的普通字段对应关系-->
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!--配置用户到订单一对多关联关系,说明: collection:配置一对多关联关系
属性:
property:要映射的属性名称
javaType:要映射的属性类型(可以指定,可以不指定,建议都指定)
ofType:集合中存放的类型(必须要指定)
-->
<collection property="ordersList" javaType="List" ofType="Orders">
<!--配置订单主键对应关系-->
<id column="oid" property="id"/>
<!--配置订单普通字段对应关系-->
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
</collection>
</resultMap>
<!--查询全部用户数据,并且关联查询出用户的所有订单数据-->
<select id="queryAllUsersAndOrders" resultMap="usersAndOrdersResultMap">
SELECT u.id, u.username, u.birthday, u.sex, u.address, o.id oid, o.number, o.createtime
FROM user LEFT JOIN orders o ON u.id = o.user_id
</select>
29. 组件开发和依赖问题
1. 组件式开发概念:
组件式开发,也叫模块化开发。各模块之间、各子系统之间,需要保持相对的独立性。
2. 依赖问题( 通过JDBC连接数据库操作演示依赖问题 ):
(1) 存在的问题:
使用DriverManager.registerDriver(new com.mysql.jdbc.Driver());语句加载驱动,我们发现应用程序对mysql数据库的驱动有很强的编译期依赖关系,紧密耦合。
(2) 面向对象编程的原则:高内聚,低耦合。在编译的时候不依赖,在运行时才依赖。
(3) 解决方法:通过反射技术,加载驱动的的字符串名称,实现运行时加载( Class.forName("com.mysql.jdbc.Driver"); )
(4) 依然存在的问题:
- 应用程序依然存在对数据库驱动的具体依赖;
- 假如需要从mysql数据库,换成oracle数据库,还是要需改java代码;
- 有没有更好的方法,实现在数据库之间进行切换,也不需要修改java代码
3. 依赖问题解决(工厂模式解耦):
(1) 对解决依赖问题的说明:
在上述依赖问题中,我们发现应用程序的类和类之间,不可避免都会产生依赖关系,我们把这种依赖关系,称为耦合。在实际的项目开发中,有些依赖关系是必须的,有些依赖关系可以通过优化实现方式清除。接下来我们使用工厂模式,实现依赖关系的解耦。
(2) 工厂模式概述:
工厂模式是我们最常见的实例化对象模式了,是用工厂方法代替new操作的一种模式。工厂模式在Java程序系统可以说是随处可见,因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如 A a = new A()工厂模式也是用来创建实例对象的,使用以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
(3) 使用工厂模式解耦最终版( 只需掌握最终版 );思路:使用配置文件,配置需要实现的类,在工厂类中,通过加载配置文件,根据配置文件内容,使用反射技术运行时创建对象。:
- 准备配置文件( bean.properties ):
例:CUSTOMERDAO=cn.itheima.dao.impl.CustomerDaoImpl
- 编写工厂类:
步骤一:声明私有的工厂类对象( 把工厂类构造方法私有化,使用静态代码块初始化工厂类对象; );
步骤二:提供公有的静态的方法,获取工厂类对象;
步骤三:通过传入的beanName去配置文件中获取类的全限定名称,在通过反射技术创建目标对象;
例:String classPathName = prop.getProperty(beanName); //beanName相当于配置文件左侧名字
Object obj = Class.forName(classPathName).newInstance();
4. 工厂模式解耦了解:
(1) 说明:在实际项目开发中,我们可以通过配置文件把controller、service、dao对象配置起来,当启动服务器加载应用的时候,读取配置文件,创建配置文件中的对象并且保存起来。由于在一个应用中,会需要大量的对象,所以在应用加载时候,创建一个Map,用于存放controller、service、dao对象,这个Map我们把它称为容器。
(2) 什么是工厂?工厂就是负责创建对象,并且把对象放到容器中。并且在使用的时候,帮助我们从容器获取指定的对象。此时我们获取对象的方式发生了改变。
(3) 总结:用来我们获取对象时,都是采用new的方式。是主动获取。现在我们获取对象时,找工厂要,由工厂创建或者提供给我们。是被动接收。这种将对象创建的权利,由在程序代码中主动new对象,转变为由工厂创建提供,我们使用的地方被动接收的方式。称为控制反转。控制反转也叫IOC(Inversion Of Control),即我们接下来要学习的spring框架中的一个重点知识点。在这里我们首先明确一个事情:spring的IOC解决的问题,即是工厂模式解耦解决的问题。
30. Spring
30.1. spring概述:
- A. spring介绍:
spring是分层的Java SE/EE应用的full-stack轻量级开源框架。它是以IOC(Inversion Of Control)控制反转和AOP(Aspect Oriented Programming)面向切面编程为核心,提供了表现层springmvc和持久层spring JDBC以及业务层的事务管理等企业级应用解决方案。还能实现将开源世界中众多优秀的第三方框架和类库整合,成为越来越受欢迎的Java EE企业级应用框架。
- B.
spring优点:
- IOC解耦,简化开发:通过spring提供的IOC容器,可以将对象间的依赖关系交由spring管理,避免硬编码造成的程序间过渡耦合。用户也不必再为了编写工厂类,属性文件解析等底层实现编写代码,可以更加专注于业务系统需求的实现;
- AOP面向切面编程支持:通过spring的AOP功能,方便实现面向切面编程,很多使用传统OOP编程不容易实现的业务功能,可以通过AOP轻松实现。比如事务管理,日志功能。
- 声明式事务支持:通过声明式方式灵活实现事务管理,提高开发效率和质量,将我们(程序员)从单调烦闷的事务管理代码中解脱出来。
- 方便程序测试:可以使用非容器依赖的方式进行程序测试工作,让测试工作更加轻松,更加方便。
- 集成第三方优秀框架:spring框架降低了第三方框架的集成使用难度,提供了对各种框架的直接支持。
- 学习java源码的经典案例:spring的源码设计精妙、结构清晰、匠心独具,处处体现了大师对java设计模式的灵活应用以及java技术的高深造诣。它的源代码无疑是java技术的最佳实践案例。
- C. spring体系结构:
30.2. spring的IOC( 基于xml方式配置IOC ):
- A. IOC的基本概述:
IOC(Inversion Of Control)控制反转。是面向对象编程的一个重要法则,用于削减计算机程序间的耦合问题。控制反转中分为两种类型,一种是DI(Dependency Injection)依赖注入;另外一种是DL(Dependency Lookup)依赖查找。实际应用中依赖注入使用更多。
- B. IOC的基本配置:
a) 准备spring的jar包:
spring官方网址:http://spring.io/
下载地址一( 官方 ):https://projects.spring.io/spring-framework/
下载地址二:http://repo.springsource.org/libs-release-local/org/springframework/spring/
b) 创建表现层,业务逻辑层,数据访问层的三层架构所需的类;
c) 配置pom.xml文件,加入spring依赖包:beans包,core包,context包,expression包,等
d) 编写bean.xml配置文件:
这里bean.xml文件,就相当于我们工厂模式解耦中的bean.properties属性文件。用于配置javaBean对象。
<?xml version="1.0" encoding="UTF-8"?>
<!--导入约束-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--使用bean标签配置javaBean对象,说明:
属性: id:bean对象的唯一标识名称 class:类的全限定名称
细节:默认调用无参数构造方法创建bean对象
-->
<!--配置客户service对象-->
<bean id="customerService" class="cn.itheima.service.impl"></bean>
</beans>
e) 在Java代码中调用框架,获取具体的对象:
// 加载spring配置文件bean.xml,创建spring框架提供的工厂对象
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
// 从工厂容器对象中,获取java对象
CustomerService service = (CustomerService) context.getBean("customerService");
- C. 基于xml的IOC配置细节:
a) ApplicationContext:
它是spring框架提供的一个大工厂,提供了根据bean的id获取对象的方法,主要有两个常用的实用类:
ClassPathXmlApplicationContext:从类根路径下加载配置文件(企业项目开发中使用较多)【需要掌握】
FileSystemXmlApplicationContext:从文件系统(磁盘上)加载配置文件【了解即可】
b) BeanFactory与ApplicationContext区别:
不同点一:BeanFactory是工厂顶层接口,ApplicationContext是BeanFactory子接口
不同点二:默认创建对象的时间点不一样:
BeanFactory创建对象:什么时候使用,什么时候创建。采用延迟创建的思想;
ApplicationContext创建对象:加载配置文件,立即创建对象。采用立即创建的思想。
- D. bean标签细节:
a) 作用:配置javaBean对象,让spring容器创建管理。默认是使用无参的构造方法创建对象。
b) 属性:
id:给bean取一个唯一标识名称
class:指定类的全限定名称
scope:指定bean的作用范围( singleton:单例。默认值;prototype:多例 )
init-method:指定初始化执行方法名称,在构造方法执行后立即执行。一般用于执行初始化【了解】
destroy-method:指定销毁执行方法名称,在spring容器销毁前执行。一般用于执行释放资源【了解】
c) 作用范围和声明周期:
单例对象:scope="singleton";作用范围:一个应用只有一个对象实例,范围是整个应用;
生命周期:加载配置文件,容器创建,对象出生;容器存在,对象就存在;容器销毁,对象死亡
多例对象:scope="prototype";作用范围:在一次使用的过程中;
生命周期:和普通对象类似,创建是对象出生,使用过程中存活,没有使用和没有被引用时,消亡
- E. bean创建对象的三种方式:
a) 使用无参数构造方法创建对象【掌握】:
<bean id="customerDao" class="cn.itheima.dao.impl.CustomerDaoImpl">
b) 使用静态工厂方法创建对象【了解】:
<bean id="staticDao" class="cn.itheima.factory.StaticFactory"
factory-method="getCustomerDao"></bean>
c) 使用实例工厂方法创建对象【了解】:
//第一步:配置实例工厂对象
//第二步:使用实例工厂对象,实例工厂方法,创建客户dao对象
<bean id="instanceFactory" class="cn.itheima.factory.InstanceFactory"></bean>
<bean id="instanceDao" factory-bean="instanceFactory"
factory-method="getCustomerDao"></bean>
- F. 依赖注入:
a) 依赖注入是什么:
在前面的spring的IOC中,已经让spring框架为我们创建了客户业务层、以及客户持久层对象。还差层与层之间的关系没有维护起来。接下来我们来看spring框架的依赖注入。首先给依赖注入下一个定义。依赖注入即在spring创建容器时,为我们维护好层与层之间对象的关系。我们在使用中,只需要提供构造方法或者set方法即可。简单说就是在层与层之间缺少什么,就传入什么。
b) 构造方法注入【了解】:
<!--配置构造方法注入,说明: constructor-arg标签:调用构造方法给成员变量赋值
index:指定参数在构造方法参数列表中的索引 name:指定参数在构造方法参数列表中的名称
type:指定参数类型(通常不需要指定) value:给简单参数类型赋值(八种基本类型+字符串String)
ref:给其它bean类型赋值
-->
<bean id="constructorDependency" class="cn.itheima.dao.impl.ConstructorDaoImpl">
<constructor-arg index="0" type="int" value="1"></constructor-arg>
<constructor-arg name="name" value="小明"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<!--配置日期对象-->
<bean id="now" class="java.util.Date"/>
c) set方法注入【掌握】:
<!--配置set方法注入,说明: property标签:调用set方法给成员变量赋值
name:成员变量的名称; value:给简单类型赋值(八种基本类型+字符串String);
ref:给其它bean类型赋值
-->
<bean id="setDenpendency" class="cn.itheima.dao.impl.SetDaoImpl">
<property name="id" value="1"></property>
<property name="name" value="小花"></property>
<property name="age" value="18"></property>
<property name="birthday" ref="now" ></property>
</bean>
d) p名称空间注入【了解】:
<!--配置p名称空间注入方式,说明:
第一步:导入p名称空间(xmlns:p="http://www.springframework.org/schema/p")
第二步:配置
p:属性:给简单类型赋值
p:属性-ref:给其它bean类型赋值
-->
<bean id="pDependency" class="cn.itheima.dao.impl.SetDaoImpl"
p:id="1" p:name="小王" p:age="18" p:birthday-ref="now">
</bean>
e) 集合属性注入【了解】
<property name="array">
<array>
<value>array1</value> <value>array2</value>
</array>
</property>
30.3. spring的IOC( 基于注解和xml配置IOC )
- A. 使用注解的步骤:
a) 创建项目,架设必要的三层架构;
b) 搭建spring IOC开发环境( 基于注解的开发环境 ):
l 配置pom.xml文件,加入依赖jar包( 除spring中的4个必要包和日志包外还需导入spring aop包 )
l 编写bean.xml文件:
导入context名称空间( 如下所示 ):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
配置context:component-scan标签,扫描包:
<!--配置扫描包,说明:配置context:component-scan,指定spring创建容器时扫描的包。
它会扫描配置的当前包和它的子包
-->
<context:component-scan base-package="cn.itheima"></context:component-scan>
c) 改造实现类:
在实现类上加上必要注解,注解详情请看下面常用注解模块
- B. 常用注解:
a) 创建对象相关注解( @Component ):[ 例:@Component("customerService") ]
作用:此注解添加于类名上方,相当于bean.xml中,bean标签配置
属性:value,给bean取一个名称,相当于bean标签中的id属性。
但value属性可以省略,当省略时默认使用类的名称(首字母小写),作为bean的名称
细节:由@Component衍生的三个注解,衍生三个注解的目的是语义更加明确:
分别是:@Controller:一般用于表现层
@Service: 一般用于业务层
@Repository:一般用于持久层
b) 设置bean作用域相关注解( @Scope ):[ 例:@Scope("singleton") ]
作用:此注解也添加于类名上方,用于设置bean的作用范围,相当bean标签中的scope属性
属性:value,属性名即value一般省略,只写属性值即可,属性可以取如下值:
singleton:单例。默认值,当没有添加@Scope注解时默认为此值
prototype:多例
request:web项目中,request域【了解】
session:web项目中,session域【了解】
globalsession:web项目中,全局session域【了解】
c) 注入数据相关注解:
l @Autowired注解( 此注解无属性 ):[ 例:@Autowired ]
作用:写于类型为bean的成员变量上方,默认按照bean的类型注入数据,即如果spring容器中存 在跟bean类型相同的对象,就会将该对象赋值给该成员变量。
细节:在spring容器中,同一个类型存在多个bean。先根据bean的类型进行注入,再根据bean
的名称进行匹配。匹配上注入成功;匹配不上注入失败。即如果该成员变量的类型为Student, 名称为student,在进行注入时会先将spring容器中所有的Student对象都查找出来,如果存 在多个,就会查找名称为student的对象,如果能查到注入成功,不能就注入失败。
l @Qualifier注解:[ 例:@Qualifier("customerDao2") ]
作用:配合@Autowired注解使用。在按照类型注入的基础上,再按照此注解的value的值注入
属性:value:指定注入的bean名称
细节:在成员变量上使用,不能单独使用,需要配合@Autowired注解一起使用
在方法形参上,可以独立使用
l @Resource注解:[ 例:@Resource(type= CustomerDaoImpl.class) ]
作用:写于类型为bean的成员变量上方,默认按照bean的名称注入数据
属性:name:指定注入bean的名称
type:指定注入bean的类型
细节:默认按照bean的名称注入数据,如果名称匹配不上,会自动再按照bean的类型进行注入
l @Value注解:[ 例:@Value("1") ]
作用:写于类型为简单类型的成员变量上方,给基本数据类型注入数据
属性:value:数据值
d) 与bean生命周期相关注解:
l @PostConstruct:[ 例:@PostConstruct ]
作用:写于方法上方,指定执行初始化操作的方法。相当于bean标签中的init-method属性。
l @PreDestroy:[ 例:@PreDestroy ]
作用:写于方法上方,指定执行销毁操作的方法。相当于bean标签中的destroy-method属性。
- C. spring整合junit单元测试:
a) 加入junit单元测试框架包;
b) 除spring基础包外加入spring注解开发(aop)包和测试(test)包;
c) 使用@Runwith注解,把junit框架的测试类,替换成spring提供的测试类:SpringJUnit4ClassRunner:
例:@RunWith(SpringJUnit4ClassRunner.class) //此注解写于测试类上方
d) 使用@ContextConfiguration注解,加载spring的配置文件(bean.xml):
@ContextConfiguration(value={"classpath:bean.xml"}) //此注解写于测试类上方
e) 此时已加载好spring容器,里面的对象均可以直接使用;
30.4. 动态代理
A. 代理模式定义:
为目标对象提供一种机制,用于控制对这个对象的访问。在某些情况下,一个对象不适合或者不能
直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
B. 代理模式优点:
安全性好:代理对象,在客户端和目标对象之间起到中介的作用。实现了对目标对象的保护。
扩展性好:在运行时实现对目标对象的增强,属于字节码增强,不需要修改目标java源代码。
职责清晰:真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务。通过后期的代理完成一件
完整事务,附带的结果就是编程简洁清晰。
C. 动态代理的常用方式一( 基于接口的动态代理 ):
a) 原理:
提供者:jdk( Proxy类 ) 要求:被代理类至少要实现一个接口
b) 实现( 以剧组-经纪人-演员举例来实现 ):
前提条件:
有演员的接口:其中有baseAct,difficultyAct等抽象方法
有一个演员的类,实现了演员的接口,将抽象方法一一实现了
创建经纪人的具体步骤:
//创建演员对象,没有演员就没有经纪人,并使用final修饰
final Actor actor = new ActionActor();
/*创建经纪人代理对象:
涉及到的类:Proxy
涉及到的方法:newProxyInstance()
涉及到的参数:
Classloader:类加载器。与被代理类使用相同的类加载器。固定写法
Interfaces:实现的接口列表。与被代理类实现相同的接口列表。固定写法
InvocationHandler:如何代理。这里是实现增强功能的地方
*/
Actor actorProxy = (Actor) Proxy.newProxyInstance(
actor.getClass().getClassLoader(),
actor.getClass().getInterfaces(),
new InvocationHandler(){
/**
*方法:invoke()
* 参数:
* proxy:代理对象引用。一般用不到
* method:当前执行的方法对象
* args:当前执行方法的参数
*/
public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
//执行对演员的代理,即判断该添加是否可以执行演员内的方法
//如果可以通过,就使用方法执行演员对象的方法
String methodName = method.getName(); //获取操作的方法名称
Float money = (Float) args[0]; //对每个参数进行解析
//通过反射使用传进来的方法对象执行actor演员对象中的该方法(并将参数传入),并将结果返回
return method.invoke(actor, money * 4 / 5);
}
}
);
//此时可以直接使用经济人的对象执行接口actor中的方法
actorProxy.baseAct(5000f);
D. 动态代理的常用方式二( 基于子类的动态代理 ):
a) 原理:
提供者:第三方cglib 要求:被代理类不能是最终类(即使用final修饰的类)
c) 实现( 以剧组-经纪人-演员举例来实现 ):
前提条件:
配置pom.xml,进入cglib依赖包
跟常用方式一类似,创建相应的接口和类
创建经纪人的具体步骤:
//创建演员类的对象,并使用final修饰
final ArtActor actor = new ArtActor();
/**
* 创建代理对象:
* 涉及到的类:Enhancer
* 涉及到的方法:create()
* 涉及到的参数:
* Class:被代理类字节码。固定写法
* Callback:如何代理。这里是实现增强功能的地方。相当于InvocationHandler
*/
ArtActor actorProxy = (ArtActor) Enhancer.create(
actor.getClass(),
new MethodInterceptor() {
/**
*方法:intercept()
* 参数:
* proxy:代理对应引用。一般用不到
* method:当前执行的方法对象
* args:当前执行方法的参数列表
* methodProxy:当前执行方法的对象代理引用。一般用不到
*/
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
跟常用方式一类似,对演员对象进行代理,并将使用反射执行演员对象的方法的结果返回
}
});
30.5. spring的AOP( 基于xml方式配置AOP )
A. AOP的概述:
a) AOP是什么:
AOP(Aspect Oriented Programming),即面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件系统开发中的一个热点,也是spring框架的一个重点。利用AOP可以实现业务逻辑各个部分的隔离,从而使得业务逻辑各个部分的耦合性降低,提高程序的可重用性,同时提高开发效率。
一句话概括:aop是面向切面编程,是使用动态代理技术,实现在不修改java源代码的情况下,运行时实现方法功能的增强。
aop的具体应用:
b) AOP的作用及优势:
作用:在程序运行期间,不修改源代码对已有方法功能进行增强
优势:减少重复代码 提高开发效率 统一管理统一调用 方便维护
c) AOP常用术语( 术语详解请看下面内容 ):
Joinpoint(连接点):在spring中,连接点指的都是方法(指的是那些要被增强功能的候选方法),spring
只支持方法类型的连接点。
Pointcut(切入点):在运行时已经被spring 的AOP实现了增强的方法。
Advice(通知):通知指的是拦截到Joinpoint之后要做的事情。即增强的功能。通知类型:前置通知/后 置通知/异常通知/最终通知/环绕通知。
Target(目标对象):被代理的对象。比如动态代理案例中的演员。
Weaving(织入):织入指的是把增强用于目标对象,创建代理对象的过程。spring采用动态代理织入,
AspectJ采用编译期织入和类装载期织入
Proxy(代理):一个类被AOP织入增强后,即产生一个结果代理类。比如动态代理案例中的经纪人。
Aspect(切面):切面指的是切入点和通知的结合。
d) 学习spring AOP需要明确的事情:
l 开发阶段:
编写核心业务代码,需要熟悉业务需求;
把公用代码抽取出来,制作成通知;
在配置文件中,配置切入点与通知的关系
l 运行阶段:
spring框架监控切入点方法执行。一旦监控到切入点方法被执行,使用动态代理机制,创建目标对象的代理对象,根据通知类型,在代理对象当前执行方法的对应位置,织入通知功能,完成完整的代码逻辑执行。
B. 基于xml的AOP配置( 基本配置 ):
a) 配置pom.xml文件,进入依赖包:
spring基础开发包:beans,context,core,expression,logging,log4j等
springaop开发jar包:aopalliance,aop,aspects,aspectjweaver等
b) 编写核心业务代码;
c) 编写公用代码,将其制作成通知类和通知方法;
d) 编写spring配置文件bean.xml:
第一步:导入aop名称空间:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
第二步:使用aop:config声明aop配置
第三步:使用aop:aspect配置切面
第四步:使用aop:before配置前置通知
第五步:使用aop:pointcut配置切入点表达式
<!--aop配置步骤-->
<!--第二步:使用aop:config声明aop配置-->
<aop:config>
<!--第三步:使用aop:aspect配置切面,说明:
id:给切面取一个唯一标识名称 ref:引用通知类对象bean的名称 -->
<aop:aspect id="logAspect" ref="logger">
<!--第四步:使用aop:before配置前置通知,说明:
method:指定通知中的方法名称 pointcut-ref:引用切入点表达式id -->
<aop:before method="printLog" pointcut-ref="pt1"></aop:before>
<!--第五步:使用aop:pointcut配置切入点表达式,说明:
id:给切入点表达式取一个唯一标识名称 expression:配置切入点表达式 -->
<aop:pointcut id="pt1" expression="execution(public void
cn.itheima.service.impl.CustomerServiceImpl.saveCustomer())"/>
</aop:aspect>
</aop:config>
C. 切入点表达式演化 ( 格式:访问修饰符 返回值 包名称 类名称 方法名称 (参数列表) ):
l 全匹配方式:public void cn.itheima.service.impl.CustomerServiceImpl.saveCustomer()
l 访问修饰符可以省略:void cn.itheima.service.impl.CustomerServiceImpl.saveCustomer()
l 返回值可以使用通配符*:* cn.itheima.service.impl.CustomerServiceImpl.saveCustomer()
l 包名称可以使用通配符,有多少级包就写多少个:* *.*.*.*.CustomerServiceImpl.saveCustomer()
l 包名称可以使用..表示当前包和子包:* *..CustomerServiceImpl.saveCustomer()
l 类名称可以使用通配符*:* *..*.saveCustomer()
l 方法名称可以使用通配符*:* *..*.*()
l 参数列表可以使用通配符*,此时必须要有参数:* *..*.*(*)
l 参数列表可以使用..,有无参数均可:* *..*.*(..)
l 实际项目中的配置案例:* cn.itheima.service..*.*(..)
D. AOP常用标签说明:
l aop:config: 作用:用于声明aop配置
l aop:aspect: 作用:用于配置切面
属性:id:配置切面的唯一标识名称 ref:引用通知类bean的id
l aop:pointcut: 作用:用于配置切入点表达式
属性:id:配置切入点表达式唯一标识名称 expression:定义切入点表达式
l aop:before: 作用:用于配置前置通知
属性:method:指定通知方法的名称 pointcut:定义切入点表达式 pointcut-ref:引用切入点表达式
l aop:after-returning : 作用:用于配置后置通知 属性同上
l aop:after-throwing: 作用:用于配置异常通知 属性同上
l aop:after: 作用:用于配置最终通知 属性同上
l aop:around: 作用:用于配置环绕通知 属性同上
E. 通知类型:
a) 通知类型模板如下:
<aop:after-throwing method="afterThrowingLog" pointcut-ref="pt1"></aop:after-throwing>
b) 不同通知类型执行机制说明:
前置通知:在切入点方法执行前执行。
后置通知:在切入点方法正常执行之后执行。它和异常通知只能执行一个。
异常通知:在切入点方法发生异常后执行。它和后置通知只能执行一个。
最终通知:无论切入点方法执行是否发生异常。它总是可以执行。
c) 环绕通知:
说明:它是spring框架,为我们提供的一种手动控制通知执行时间点的机制。使用起来更加灵活。
原理分析:spring框架,为环绕通知提供了ProceedingJoinPoint接口,作为环绕通知方法的形参。在执行 环绕通知的时候,提供实例化对象,我们直接使用即可。该对象有一个proceed()方法,相当 于 method.invoke()方法。
例:
public void aroundLog(ProceedingJoinPoint pjp){
try {
System.out.println("【环绕通知中-前置通知】记录日志。");
pjp.proceed(); //调用目标方法
System.out.println("【环绕通知中-后置通知】记录日志。");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("【环绕通知中-异常通知】记录日志。");
}
System.out.println("【环绕通知中-最终通知】记录日志。");
}
30.6. spring的AOP( 基于注解的AOP配置 )
A. 改造bean.xml文件,配置注解扫描包;
B. 启用spring对注解aop的支持:
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
C. 改造各个类,使用注解配置:
l @Aspect: 作用:声明当前类为切面类。相当于bean.xml文件中aop:aspect标签配置。
l @Before: 作用:配置前置通知 例:@Before("pt1()")
l @AfterReturning: 作用:配置后置通知
l @AfterThrowing: 作用:配置异常通知
l @After: 作用:配置最终通知
l @Around: 作用:配置环绕通知
l @Pointcut: 作用:配置切入点表达式
@Pointcut("execution(* cn.itheima.service..*.*(..))")
public void pt1(){}
30.7. spring中的JdbcTemplate
A. JdbcTemplate概述:
它是spring框架中提供的一个持久层操作对象,是对jdbc API的封装。如下为持久层总图:
JdbcTemplate在spring-jdbc-xxx.RELEASE.jar包中(xxx是具体的版本号)。在使用JdbcTemplate时,除了导入spring-jdbc-xxx.RELEASE.jar包以外,还需要导入一个spring-tx-xxx.RELASE.jar包。它们是配套使用的。
B. JdbcTemplate入门案例:
a) 创建账号表:在数据库中创建需要使用的表;
b) 创建项目,配置pom.xml文件,进入所需的依赖:
spring中的包:beans包,core包,context包,expression包,spring-jdbc包,
其他包:mysql包,log4j包,org.slf4j包等
c) 编写bean.xml文件:
把JdbcTemplate和DriverManagerDataSource对象配置到bean.xml文件中,让spring容器管理起来。
配置spring内置的数据源对象,需进入数据库连接必需的四个条件。
d) 编写测试代码:
// 1.加载bean.xml文件,创建spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean.xml");
// 2.获取jdbcTemplate对象
JdbcTemplate jt = (JdbcTemplate) context.getBean("jt");
// 3.向账户表中新增记录
jt.update("insert into account(name,money) values('大杨',3000)");
C. JdbcTemplate实现CRUD操作:
a) 无论使用哪一种持久化技术,要对数据库表进行操作,我们首先都需要建立表的实体类对象。
b) 在进行查询时,JdbcTemplate与RunnerQuery的查询不同,如下代码所示:
List<Account> list = jt.query("select * from account", new RowMapper<Account>() {
/** 结果集映射方法,对应查询结果集中每一条记录,都会调用执行一次
* 参数: rs:结果集 rowNum:结果集记录索引 */
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
// 创建Account对象,并将结果集中查到数据赋值到Account中,会返回该Account对象
Account account = new Account();
account.setId(rs.getInt("id")); account.setName(rs.getString("name"));
return account;
}
});
30.8. spring中的事务控制
A. 事务的定义和特性:
a) 事务的定义:
事务(transaction),一般是指要做的或者所做的事情。在程序中,尤其是在操作数据库的程序中,指的是访问并且可能更新数据库中数据项的一个执行单元(unit),这个执行单元由事务开始(begin transaction)和事务结束(end transaction)之间执行的全部操作组成。
b) 事务的特性( ACID原则 ):
l 原子性(atomicity):一个事务是一个不可再分割的工作单位(最小单位),事务中的全部操作要么都做,要么都不做。
l 一致性(consistency):事务必须是使得数据库状态从一个一致性状态,转变到另外一个一致性状态。也就是说在事务前,和事务后,被操作的目标资源状态一致。比如银行转账案例中,转账前和转账后,总账不变。
l 隔离性(isolation):一个事务的执行不能被其他事务的影响。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,多个并发事务之间不能相互干扰。
l 持久性(durability):一个事务一旦提交,它对数据库中数据的改变会永久存储起来。其他操作不会对它产生影响。
B. spring事务控制中需要明确的事项:
第一:j2EE体系中项目按照分层进行设计开发,有表现层、业务层、持久层。事务处理位于业务层。Spring 提供了分层设计业务层的事务处理解决方案。
第二:spring框架为我们提供了一组事务控制接口,该组接口位于spring-tx-xxx.RELEASE.jar包中。具体我们
在后面的内容中详细介绍。
第三:spring的事务都是基于AOP的实现,它既可以使用编程的方式实现,也可以使用配置的方式实现。我 们这里重点是使用配置的方式来实现。
C. spring中事务控制API介绍:
a) PlatformTransactionManager:
l 说明:它是一个接口,是spring的事务管理器核心接口,spring并不实现具体的事务,而是负责包装底层事务,提供规范。应用底层支持什么样的事务策略,spring就支持什么样的事务策略。该接口提供了我们操作事务的常用方法。
l 此接口中的常用方法如下:
提交事务:void commit( TransactionStatus status )
回滚事务:void rollback( TransactionStatus status )
获取事务状态信息:TransactionStatus getransaction( TransactionDefinition definition )
l 我们在开发中都是直接使用它的实现类( 有不同的实现类,我们一般使用如下类 ):
DataSourceTransactionManager:使用jdbc或者mybatis框架进行数据持久化时使用。
b) TransactionDefinition:
l 说明:它是一个接口,是定义事务的信息对象;
l 此接口通过了如下方法:
获取事务对象名称:String getName()
获取事务隔离级别:int getIsolationLevel()
获取事务传播行为:int getPropagationBehavior()
获取事务超时时间:int getTimeout()
以秒为单位进行设置。如果设置为-1(默认值),表示没有超时限制。在企业项目中使用默认 值即可。
获取事务是否只读:boolean isReadOnly()
只读事务比读写事务性能要高,实际项目中,查询一般建议设置为只读。
l 事务隔离级别( 事务隔离级别反应了事务在并发访问时的处理态度 ):
ISOLATION_DEFAULT:默认级别,归属于下列某一种隔离级别。在项目中使用默认值即可。
ISOLATION_READ_UNCOMMITTED:可以读取其他事务未提交的数据(脏读)
ISOLATION_READ_COMMITTED:只能读取其他事务已提交的数据,解决脏读的问题(oracle默认级别)
ISOLATION_REPEATABLE_READ:是否读取其他事务提交修改后的数据,解决不可重复读的问题mysql
ISOLATION_SERIALIZABLE:是否读取其他事务添加后的数据,解决幻影读的问题
注意:事务级别从低到高:脏读->不可重复读->可重复读->解决幻读
事务级别越高,消耗的资源越多,数据库操作性能越低
在企业项目中,使用哪一种级别的事务,需要根据业务需求来确定
l 事务传播行为:
REQUIRED:如果已经有事务,就加入该事务中执行;如果没有事务,则新建一个事务。对应增/删/改 操作一般的选择(默认值)。
SUPPORTS:如果已经有事务,支持当前事务的执行;如果没有事务,就以非事务的方式执行。对应 查询操作一般的选择。
c) TransactionStatus:
l 说明:它是一个接口,提供了事务具体的执行状态,描述了某一个时间点上事务对象的状态信息。
l 提供了如下常用方法:
刷新事务: void flush();
获取是否有存储点: boolean hasSavepoint();
事务是否完成: boolean isCompleted();
是否是一个新的事务:boolean isNewTransaction();
事务是否回滚: boolean isRollbackOnly();
设置事务回滚: void setRollbackOnly()
D. 基于xml的声明式事务配置:
a) 配置pom.xml,加入依赖包( 需要导入aop开发相关的jar包 )
b) 在bean.xml文件中导入aop和tx名称空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
c) 完整配置:
<!--基于xml的声明式事务配置-->
<!--第一步:配置事务管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源对象-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--第二步:配置aop与切入点表达式-->
<aop:config>
<aop:pointcut id="pt1"
expression="execution(* cn.itheima.service..*.*(..))"></aop:pointcut>
<!--第三步:建立通知与切入点表达式的关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>
<!--第四步:配置通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--第五步:配置事务属性-->
<tx:attributes>
<!--tx:method标签:配置业务方法的名称规则,说明:
name:方法名称规则,可以使用通配符*
isolation:事务隔离级别,使用默认值即可
propagation:事务传播行为,增/删/改方法使用REQUIRED。查询方法使用SUPPORTS。
read-only:是否只读事务。增/删/改方法使用false。查询方法使用true。
timeout:配置事务超时。使用默认值-1即可。永不超时。
rollback-for:发生某种异常时,回滚;发生其它异常不回滚。没有默认值,任何异常都回滚
no-rollback-for:发生某种异常时不回滚;发生其它异常时回滚。没有默认值,任何异常都回滚。
-->
<tx:method name="transfer*" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
E. 基于注解和xml的事务配置:
a) 配置pom.xml,加入依赖包( 需要导入aop开发相关的jar包 );
b) 导入必要的名称空间,如上述所示;
c) 改造dao和service中的类,使用注解配置该类;
d) 继续改造service中的类,使用@Transactional注解配置事务
在完成事务的方法上加入如下注释:
@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
e) 配置bean.xml文件
配置扫描包,将所有的类的对象加入spring容器中;
删除aop的配置,只保留事务管理器即可
开启spring对注解事务的支持
f) @Transaction注解特别说明:
@Transactional注解和xml中属性含义一致。该注解可以出现在接口上、类上、方法上 出现在接口上,表面该接口的所有实现类都有事务支持 出现在类上,表示类中所有方法都有事务支持 出现在方法上,表明该方法有事务支持 三者同时出现,优先级为:方法>类>接口 |
31. springMVC
31.1. springMVC入门程序
1. 准备环境:
Jdk 1.8版本以上,idea开发软件201732版本以上,web容器tomcat7以上
2. 创建项目:创建好maven web项目即可
3. 配置pom.xml文件:
(1) 加入如下依赖包:
spring基础包:spring-core,spring-beans,spring-context,spring-expression
spring-aop包:spring-aop,spring-aspects
spring数据库事务包:spring-tx,spring-jdbc
springMVC包:spring-webmvc(核心包),spring-web
spring其他包:spring-context-support
jsp的包:jstl
(2) 配置Tomcat插件
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8080</port> <!-- tomcat 的端口号 -->
<path>/springmvc-first</path> <!-- 访问应用的路径 -->
<uriEncoding>UTF-8</uriEncoding> <!-- URL按UTF-8进行编码,解决中文参数乱码 -->
<server>tomcat7</server> <!-- tomcat名称 -->
</configuration>
</plugin>
4. 准备配置文件springmvc.xml:这是springmvc的主配置文件,名字可以修改,内容跟spring的配置文件类似
5. 配置web.xml:
(1) 请注意:使用maven项目生成的web.xml是2.3,为了更方便使用,需改成2.5版本:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
(2) 配置一个核心控制器(前端控制器):DispatcherServlet
这是springmvc框架提供的一个servlet。用于接收从浏览器发送的请求。会直接将该请求转入后端控制器。
<!--配置前端控制器:DispatcherServlet-->
<servlet>
<servlet-name>springmvc-first</servlet-name> //取名,一般为项目名,每个项目中一个
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param> <!--加载springmvc主配置文件-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup> //配置什么时候加载此控制器,一般服务器启动时就加载
</servlet>
<servlet-mapping></servlet-mapping> //配置此控制器的映射文件,一般为/,所有的请求都要
6. 编写controller控制器( 后端控制器 ):
此控制器跟web项目中的servlet一样,只需在类名上方加上@controller注释即可,在配置文件中配置包扫描
@RequestMapping("/hello.do") //请求的url
public ModelAndView hello(){
创建ModelAndView,在该对象中进入需要的值,设置需要响应的视图名称
return mav;
}
31.2. springMVC三大组件和spring框架原理:
1. 三大组件:
处理器映射器(HandlerMapping):根据请求的url,查找处理器(处理器方法)。
处理器适配器(HandlerAdapter):执行处理器方法。
视图解析器(ViewResolver):把逻辑视图(在处理器controller中设置的视图名称)解析成物理视图(在浏览器 实际看到的页面)。
2. 三大组件的配置:
<mvc:annotation-driven/>:等于同时配置了RequestMappingHandlerMapping/RequestMappingHandlerAdapter; |
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <!--配置视图的公共目录路径--> <property name="suffix" value=".jsp"/> <!--配置视图的扩展名称--> </bean> |
3. spring框架原理:
31.3. springmvc中的小知识点
1. 默认支持的参数类型
(1) HttpServletRequest:通过request对象,获取请求域的参数数据。
(2) HttpServletResponse:通过response对象,响应。
(3) HttpSession:通过session对象,操作会话域中的数据。
(4) Model/ModelMap:
Model是一个接口,是模型,用于设置响应的模型数据。ModelMap是一个实现类,使用Model和使用ModelMap是一样的。如果使用Model,springmvc会实例化成ModelMap。使用Model响应模型数据,就可以不使用ModelAndView,视图可以使用字符串String响应。
2. 简单参数类型:
(1) Integer:可以在方法形参上使用Integer接收商品id等Integer类型的数据
注意:使用简单类型接收请求的参数数据,推荐使用简单类型的包装类型(Integer),不建议使用简单类型
的基础类型(int)。原因是基础类型不能为null,如果不传递会报异常。
(2) 常用的简单类型:
类型 |
包装类型 |
基础类型 |
长整形 |
Long |
long |
整形 |
Integer |
int |
单精度浮点型 |
Float |
float |
双精度浮点型 |
Double |
double |
字符串 |
String |
String |
(3) @RequestParam注解:
作用:设置请求的参数名称,与方法的形参名称匹配。
示例:public String queryItemById(Model model,@RequestParam(value="itemId",required = true,
defaultValue = "2")Integer id){方法体}
属性:value属性:设置请求的参数名称;
required属性:设置参数是否必须要传递。true要传递;false:可以传也可以不传。默认true
defaultValue属性:设置参数的默认值。如果传递参数,使用实际的参数值;如果不传递,使用默认值
(4) pojo参数和pojo包装参数类型:
当前端页面需进行修改商品等需传入较多数据到后台的操作时,可以是使用此参数类型;
例:public String updateItem(Item item){} Item为pojo类型;
如有需要是可以将Item作为另一个类的成员变量,此时使用了pojo包装参数类型;
(5) 自定义参数类型:
a. 说明:自定义参数类型解决的问题,比如日期类型的数据,格式多,需要根据业务需求来确定。
b. 步骤:
第一步:自定义转换器;实现org.springframework.core.convert.converter.Converter接口
此接口中有2个参数Converter<S, T>:
S,Source,源,转换之前的数据,这里是字符串String类型的商品生产日期;
T,Target,目标,转换之后的数据,这里是Date类型的商品生产日期;
第二步:在springmvc.xml中,配置自定义转换器:
<!--在注解驱动方式配置处理器映射器与处理器适配器中加载转换器-->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 配置自定义转换器 -->
<bean id="conversionService"class="org.springframework.format.
support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set> <bean class="cn.itheima.ssm.converter.DateConverter"/> </set>
</property>
</bean>
3. 高级参数类型:
(1) 数组参数类型:
在controller的方法中,可以放置一个数组类型的参数,用来接收从前端页面传来的数组
例:public ModelAndView queryItem(QueryVo queryVo,Integer[] ids)
ids:接收请求的多个商品Id,演示数组参数绑定
(2) list参数类型:
使用list集合参数类型绑定,list需要作为pojo的属性。不能直接在方法形参中使用list,否则不能完成绑定。
4. @RequestMapping注解:
(1) 作用一:配置请求的url:@RequestMapping(value={"queryItem"})
value:是一个数组,可以配置多个请求的url,这些url请求均可以访问此资源;
(2) 作用二:限制http请求方法:
@RequestMapping(value={"queryItem"},method={RequestMethod.POST,RequestMethod.GET})
method:是一个数组,配置允许的http方法:
method={RequestMethod.POST}:只允许post请求
method={RequestMethod.POST,RequestMethod.GET}:只允许post/get请求
(3) 作用三:在类上面使用,对请求的url进行分类管理:
例:@RequestMapping(“item”)
5. Controller方法返回值:
(1) 返回ModelAndView:返回响应的模型数据,返回响应的视图。
需要在方法中创建ModelAndView视图对象,并使用setViewName方法设置响应的视图的地址。
(2) 返回void:使用Request和Response响应。
需要在形参上设置HttpServletRequest request,HttpServletResponse response属性,并通过转发和重定向才能实现页面的跳转。
(3) 返回String:返回响应的视图( 通过返回目标视图的字符串地址,从而跳转到该位置 )
forward转发:forward+":"+目标url;例:return "forward:queryItem.do";
redirect重定向:redirect+":"+目标url;return "redirect:queryItem.do";
6. 异常处理:
(1) 异常介绍:异常,就是不正常。异常可以分类为预期的异常和运行时异常。预期的异常可以通过捕获(try...catch...)进行处理。运行时的异常只能通过规范代码的编写,增加测试来减少。
(2) 处理思路:
请求处理流程:客户端(浏览器)->前端控制器(DispatcherServlet)->表现层(controller)->业务
层(service)->持久层(dao)。
异常处理思路:从dao开始,每一层发生异常都向上一层抛出,一直抛到前端控制器,前端控制器不能再抛 出,前端控制器需要请求异常处理器来包装异常。返回一个友好的异常提示页面。
(3) 自定义异常处理:
第一步:自定义异常类,需继承Exception类。
第二步:自定义异常处理器:需要实现接口(HandlerExceptionResolver)。
第三步:编写异常界面,即错误友好界面,如果出现异常就跳转到此页面。
第四步:在springmvc.xml文件中配置异常处理器( bean class=”自定义的异常类的全路径名称”/> )
7. 文件上传:
(1) 配置pom.xml文件,加入文件上传的依赖包:
commons-fileupload.jar commons-io.jar commons-codec.jar
(2) 在springmvc.xml文件中配置文件上传解析器:
<!-- 配置文件上传解析器 ,框架提供了文件上传解析器接口:MultipartResolver
细节:文件上传解析器的id属性值,必须是文件上传解析器接口的名称的首字母小写(multipartResolver)-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--maxUploadSize:文件上传大小的限制,以字节为单位。 10M=10*1024*1024-->
<property name="maxUploadSize" value="104835760"/>
<!-- maxInMemorySize:配置内存缓冲区大小,以字节为单位。 4k=4*1024-->
<property name="maxInMemorySize" value="4096"/>
<!-- defaultEncoding:配置默认的字符集编码 -->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
(3) 编辑jsp页面,支持文件上传:
实现文件上传提交表单,表单中必须要设置属性(enctype="multipart/form-data")
(4) 图片上传的controller代码实现:
public String updateItem(Item item,MultipartFile pictureFile){
if(pictureFile != null && pictureFile.getOriginalFilename() !=null){
// 1.获取上传文件的名称
String oriName = pictureFile.getOriginalFilename();
String extName = oriName.substring(oriName.lastIndexOf("."));
// 2.重新命名文件名称
String newName = System.currentTimeMillis()+"";
newName = newName+extName;
// 3.上传文件
File dest =
new File("图片存放地址"+newName);
try {
pictureFile.transferTo(dest);
} catch (Exception e) {
e.printStackTrace();
}
// 4.保存上传文件的名称
item.setPic(newName);
}
return "具体视图地址";
}
请注意:如果实现上传商品等操作时,可以先实现图片上传,再实现将商品信息存入数据库的操作,如果出现异常就停止执行。如此可以将商品图片顺利上传到服务器。
8. json数据交互:
(1) 配置pom.xml文件,加入jackson依赖包:
jackson-databind jackson-core jackson-annotations
(2) 配置springmvc.xml配置文件:
<mvc:annotation-driven />默认就支持jackson的数据转换。不需要再做额外的配置。
(3) 在controller中使用@RequestBody注解和@ResponseBody注解:
说明:在处理器方法的形参上使用,把请求的json格式的数据,转换成java对象。
说明:在处理器方法返回值上,或者方法上使用。把响应的java对象,转换成json格式的数据。
例:/**请求商品格式的json数据->使用商品pojo接收参数->响应商品对象->转换回json格式的数据*/
@RequestMapping("/testJson.do")
@ResponseBody
public Item testJson(@RequestBody Item item){
return item;
}
9. restful支持:
10. 拦截器:
(1) 拦截器介绍:在springmvc框架中提供了拦截器,它相当于servlet中的过滤器(filter),过滤器可以用于实现前置增强和后置增强。这里拦截器也是用于实现前置增强和后置增强。可以对处理器方法执行预处理(在处理器方法执行前执行);也可以对处理器方法执行后处理(在处理器方法执行后执行)。
(2) 自定义拦截器( 相当于JavaWeb中的filter过滤器 ):
第一步:自定义拦截器(类)需实现HandlerInterceptor接口;并实现接口中的3个方法。
第二步:在springmvc.xml中,配置拦截器。
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 配置拦截器的url规则,说明:
1.拦截单个url:/interceptor.do,表示拦截请求:/interceptor.do
2.拦截多个url:/inter/**,表示拦截以/inter开始的所有请求 -->
<mvc:mapping path="/interceptor.do"/>
<bean class="cn.itheima.ssm.interceptor.FirstInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
(3) 拦截器执行结果说明:
当preHandle方法返回true时: 执行拦截器的preHandle方法 执行处理器的testInterceptor方法 执行拦截器的postHandle方法 响应jsp页面 执行拦截器的afterCompletion方法 |
当preHandle方法返回false时: 只执行了拦截器preHandle方法。终止执行。 |
(4) 拦截器方法作用说明:
preHandle: l preHandle方法,在处理器方法执行前执行,在响应jsp页面前执行。是对处理器方法执行预处理。 l 该方法返回布尔类型的值。返回true继续执行;返回false终止执行。 l 在实际项目中,适合于在该方法实现检查用户是否登录、是否有资源操作的权限等业务逻辑处理。 |
postHandle: l postHandle方法,在处理器方法执行后执行,在响应jsp页面前执行。是对处理器方法执行后处理。 l 该方法中提供了ModelAndView参数对象,可以设置响应的模型数据。 l 在实际项目中,适合于在该方法实现公共模型数据的设置。比如页面头部的欢迎信息、页面尾部的友情链接、备案、免责声明等信息。 |
afterCompletion: l afterCompletion方法,在处理器方法执行后执行,在响应jsp页面后执行。是对处理器方法执行后处理。 l 该方法的特点是只要当前拦截器preHandle方法返回true,就可以得到执行。 l 在实际项目中,适合于在该方法实现用户访问操作日志的记录。 |
(5) 配置多个拦截器时各个方法的执行顺序:
全部符合true时: 拦截器preHandle方法按照配置的顺序执行 拦截器postHandle方法按照配置的逆序执行 拦截器afterCompletion方法按照配置的逆序执行 |
拦截器一返回true、拦截器二返回false测试: 拦截器afterCompletion方法,只要当前拦截器返回true,就可以得到执行。 |
32. springmvc+spring+mybatis整合
1. 整合思路:
springmvc是表现层框架,mybatis是持久层框架、spring是整合层的框架。在我们前边学习的spring框架
中,它的IOC容器用于创建对象和管理对象。因此整合的思路即:把springmvc、mybatis框架的对象,交给spring
管理。
2. 项目分层:
(1) 表现层,springmvc( controller ):把表现层的对象交给spring管理,在表现层中可以调用业务成的对象;
(2) 业务层,service:把业务层的对象交给spring管理起来,事务也管理起来。在业务层中调用持久层对象;
(3) 持久层,mybatis( mapper ):把持久层的对象,交给spring管理起来,完成数据库的CRUD操作;
3. 创建项目,配置pom.xml文件,加入依赖:
mybatis框架包,spring框架包(包括springmvc),mybatis-spring整合包,数据库驱动包,
数据库连接池包(dbcp),jstl标签库包,log4j日志包
4. 准备配置文件(配置文件是框架的核心):
(1) sqlMapConfig.xml配置文件:
这是myBatis的核心配置文件,因为spring框架接管了myBatis的很多内容,故在此配置文件中只需配置别名
<typeAliases>
<package name="cn.itheima.ssm.po"/>
</typeAliases>
(2) springmvc.xml
l 配置包扫描controller:
<context:component-scan base-package="cn.itheima.ssm.controller"/>
l 配置处理器映射器和处理器适配器:
<mvc:annotation-driven/>
l 配置视图解析器:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/>
</bean>
(3) applicationContext-dao.xml
l 配置数据源对象(DataSource):
<!-- 加载db.properties文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.driverClassName}"/>
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<property name="maxActive" value="${db.maxActive}"/> <!-- 最大连接数量 -->
<property name="minIdle" value="${db.minIdle}"/> <!-- 最小空闲连接 -->
<property name="maxIdle" value="${db.maxIdle}"/> <!-- 最大空闲连接 -->
<property name="initialSize" value="${db.initialSize}"/> <!-- 初始化连接数 -->
<property name="maxWait" value="${db.maxWait}"/> <!-- 超时等待时间以毫秒为单位 -->
</bean>
l 配置mybatis框架核心对象(SqlSessionFactory):
<!-- 配置sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据源对象 -->
<property name="dataSource" ref="dataSource"/>
<!-- 加载mybatis主配置文件 -->
<property name="configLocation" value="classpath:mybatis/sqlMapConfig.xml"/>
</bean>
l 配置mapper扫描器(MapperScannerConfigurer):
<!-- 配置mapper扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 配置要扫描的包,说明:
1.如果有多个包,在同一个父包下,配置父包即可
2.如果不在同一个父包下,以半角逗号进行分割 -->
<property name="basePackage" value="cn.itheima.ssm.mapper"/>
</bean>
(4) applicationContext-service.xml
配置包扫描service:
<context:component-scan base-package="cn.itheima.ssm.service"/>
(5) applicationContext-trans.xml
l 配置事务管理器(transactionManager):
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 指定数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
l 配置通知(txAdvice):
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 配置传播行为 -->
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="query*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
l 配置切面(aop:config):
<aop:config>
<!-- 指定cn.itheima.ssm.service包下的任意类的任意方法,需要事务 -->
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* cn.itheima.ssm.service..*.*(..))"/>
</aop:config>
(6) db.properties和log4j.properties
5. 配置好web.xml:
(1) 配置spring提供的监听器:
配置监听器的目的是当web容器启动,创建ServletContext对象的时候,自动创建spring的容器,并且
把spring容器放入ServletContext域中。
<!-- 使用全局参数context-param 加载spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<!-- 配置spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
(2) 配置前端控制器:DispatcherServlet
<servlet>
<servlet-name>ssm01</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载springmvc的主配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<!--服务器启动时就创建好前端控制器-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ssm01</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
6. 进行项目整合:
(1) controller:
后端控制器,进行url的具体处理
(2) service:
业务逻辑层,进行具体的业务逻辑处理
(3) dao:
只需要创建对应接口即可,在resources的同一目录下创建对应的同名映射文件
7. 总结:
第一步:准备基础环境(编写实体类对象、持久层对象、业务层对象)
第二步:确保spring框架独立运行(导入jar包,准备配置文件:bean.xml)
第三步:确保springmvc框架独立运行(导入spring-web和spring-webmvc包,准备主配置文件:springmvc.xml,配 置一个前端控制器:DispatcherServlet)
第四步:整合spring和springmvc框架(ServletContextListener监听ServletContext对象创建、配置ContextLoaderListener 继承了ServletContextListener,帮助我们创建spring容器,并且放入ServletContext中)
第五步:确保mybatis框架独立运行(导入mybatis框架包、编写主配置文件:sqlMapConfig.xml、编写数据库属性文 件db.properties、编写log4j.properties文件、编写mapper映射文件)
第六步:整合spring和mybatis框架(就是把mybatis框架的对象,交给spring管理起来:数据源对象、SqlSessionFactory、 mapper代理对象、事务也让spring管理起来)
33. 框架的补充知识点
1. 解决不能加载静态资源的问题:
当我们进行框架整合后发现不能加载静态资源文件( css/js )。原因是我们在web.xml文件中前端控制器的配置/,表示拦截所有请求,包括静态资源加载的请求。springmvc的前端控制器它不能加载静态资源的请求。静态资源的加载需要交给默认的servlet处理器来处理,相当于给tomcat来处理。
此时需在springmvc.xml文件配置默认的servlet处理器,用来加载静态资源。
<mvc:default-servlet-handler/>
2. 拦截url中 / 和 /* 区别:
/,拦截所有请求,包括动态请求(*.do),静态资源(css/js/img)
/*,拦截所有请求,包括动态请求(.do),jsp页面,静态资源(css/js/img)
3. 在applicationContext-dao.xml中整合别名:
<!-- 整合别名 -->
<property name="typeAliasesPackage" value="cn.itheima.crm.po"/>
说明:此时从技术角度,可以删除sqlMapConfig.xml文件,但是在实际项目中建议保留它,这样项目结构会更加
清晰方便维护。
4. 项目声明周期:
需求提出-》可行性分析-》立项-》功能需求分析-》设计(数据库设计、概要设计、详细设计)-》编码-》测试(单元测试、集成测试)-》上线运行。
5. log4j的介绍和使用:
(1) 导入log4j的jar包:log4j, slf4j-api, slf4j-log4j12;
(2) 配置log4j的配置文件:
# Set root logger
#DEBUG INFO WARN ERROR FATAL
log4j.rootLogger=DEBUG,stdout,A2
###################
# stdout Appender
###################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Threshold=DEBUG
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %-5p ~ %m%n
log4j.appender.A2=org.apache.log4j.RollingFileAppender
log4j.appender.A2.Threshold=INFO
log4j.appender.A2.File=E:/teach/0346/log/rollinglogfile.log
log4j.appender.A2.MaxFileSize=5KB
log4j.appender.A2.MaxBackupIndex=3
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n
6. StringUtils工具类的使用:
(1) 导入jar包:commons-lang;
(2) StringUtils中一共有如下四个方法:
StringUtils.isNotBlank(str1) (自动去除空格) StringUtils.isNotEmpty(str1) (不会去除空格)
StringUtils.isBlank(str1) StringUtils.isEmpty(str1)
34. crawler(爬虫)
1. 爬虫基础:
(1) 什么是爬虫:爬虫,又叫网络爬虫,或者网络蜘蛛。是一种运行在互联网上用来获取数据的自动化程序。
(2) 有哪些数据需要爬取:
可以分为内部数据和外部数据,主要注意内部数据中的用户数据(无论是网站、还是用户注册都会填写邮箱、电话、身份证号码等数据,这些数据其实非常有价值,此外还要加上用户使用公司产品留下的行为数据)。
(3) 爬虫分类:
l 通用爬虫:爬取全网的数据,百度、360、搜狗
l 垂直爬虫:爬取单一网站的数据,爬取某个细分领域的数据。
l 学习的是垂直爬虫。现在公司中基本上都是垂直爬虫。
2. 如何开发爬虫:
(1) 开发爬虫的步骤:
第一步:指定一个新闻详情页面的地址(url)
第二步:模拟浏览器发起http请求(可以使用serverSocket,HttpUrlConnection和第三方提供的HttpClient[推荐])
第三步:得到网页的二进制数据
第四步:把二进制数据转换成字符串的数据
第五步:解析数据(字符串新闻数据)(使用jsoup框架操作Document对象)
第六步:持久化新闻数据(将数据保存到数据库)
(2) DNS解析步骤:
l 第一次抓取:将一个种子URL存放到队里中 l 从队列中读取一个URL l 发起网络请求(上图4-5-6步) 域名解析,得到IP地址 发起HTTP请求 下载页面 l 解析HTML文档(上图7-8-9步) 把当前URL放入(已抓取URL队列中) 把当前网页内容,保存到数据库中 解析HMTL文档获取网页中所有URL 判断新解析出的URL是否已经抓取过 是,直接丢弃 否,把新的URL放入(待抓取URL队列中) |
(3) 爬虫开发的两个核心技术:
HttpClient:用于发送http请求 jsoup:用于解析html文档
3. 使用第三方HttpClient发送GET&POST请求:
(1) 配置pom.xml文件,加入HttpClient依赖,httpclient;
(2) 创建HttpClient对象:CloseableHttpClient httpClient = HttpClients.createDefault();
(3) 创建HttpGet或Post对象:HttpGet get = new HttpGet("http://www.itheima.com");
(4) 设置请求头信息:get.addHeader("User-Agent","Mozilla/5.0");
(5) 执行请求:CloseableHttpResponse response = httpClient.execute(get);
(6) 获取网页内容:HttpEntity entity = response.getEntity();
(7) 打印网页内容:String html = EntityUtils.toString(entity,"utf-8"); System.out.println(html);
(8) 释放:response.close();
增加内容:HttpClient中的流畅API使用,在pom.xml配置文件中,进入流畅api依赖,fluent-hc
String html = Request.Get("http://www.itheima.com").execute().returnContent().asString(Charset.forName("utf-8"));
4. 解析html文档:
(1) html基础知识回顾:
(2) 使用jsoup操作document对象:
- jsoup是什么:
jsoup 是一款Java 的html解析器,可直接解析某个URL地址、html文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
- jsoup核心功能:
输入信息源:字符串,URL地址,文件;
提取数据:使用Document语法进行解析数据,使用选择方式进行解析;
- jsoup选择器:
a) jsoup支持类似于CSS(或jquery)的选择器语法,来实现非常强大和灵活的查找功能。这个select方法在Document,Element,或Elements对象中都可以使用。且是上下文相关的,因此可实现指定元素的过滤,或者链式选择访问。Select方法将返回一个Elements集合,并提供一组方法来抽取和处理结果。
b) Selector选择器概述:
tagname:通过标签查找元素,例如 a
ns|tag: 通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找元素
id:通过ID查找元素,例如 #logo
.class:按类名查找元素,例如 .masthead
[attribute] : 利用属性查找元素,比如:[href]
[^attr]:带有属性名称前缀的[^data-]元素
[attr=value]:具有属性值的元素,例如[width=500]
[attr^=value],[attr$=value],[attr=value]:用与启动,结束,或包含所述的值,例如元素[href=/path/]
[attr~=regex]:具有与正则表达式匹配的属性值的元素; 例如img[src~=(?i).(png|jpe?g)]
*:所有元素
c) Selector选择器组合使用:
el#id:带ID的元素,例如 div#logo
el.class:有类的元素,例如 div.masthead
el[attr]:具有属性的元素,例如 a[href]任何组合,例如 a[href].highlight
ancestor child:从祖先开始下降的子元素,例如,在具有类“body”的块下.body p找到p元素
parent > child:直接从父项下降的子元素,例如div.content > p查找p元素; 并body > *找到身体标签 的直接子女
5. 1
35. Lucene(搜索)
- 1.
36. solr(搜索)
1. solr介绍:
(1) solr是什么:Solr是Apache下的一个顶级开源项目,基于Lucene的全文搜索服务,可以独立运行于Jetty,Tomcat等web容器中。
(2) 使用solr创建索引:客户端可以通过http的post方法向solr服务器发送一个描述Field及其内容的xml文档,solr服务器根据xml文档添加、更新、删除索引。
(3) 使用solr搜索索引:客户端可以通过http的get方法向solr服务器发送请求,对solr服务器返回的xml、json格式结果进行解析。solr不提供构建页面UI的功能。solr提供了一个管理界面,通过管理界面可以查询solr的配置和运行情况。
2. lucene与solr区别:
Lucene是一个全文检索工具包,提供了索引引擎和查询引擎功能,不是一个完整的服务,不能独立运行。Solr是基于Lucene构建的全文检索服务,是一个完整的服务,可以独立运行于web容器中。基于Solr可以快速构建企业级的搜索引擎。
3. solr安装部署:
4. solrj使用:
(1) solrj介绍:solrj就是访问服务的java客户端程序,提供了索引和搜索请求的方法。solrj与solr的关系,就好比小海豚与mysql的关系。
(2) 使用solrj需要导入的jar包:
(3) 添加(更新)索引:
solr是根据id域(唯一约束)执行索引的添加。先根据id域搜索,搜索到执行更新;搜索不到执行添加。
//1.建立HttpSolrServer服务对象,连接solr服务
HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1:8081/solr/");
//2.建立文档对象(SolrInputDocument)
SolrInputDocument sif = new SolrInputDocument();
sif.addField("id", "9527");
sif.addField("name", "solr is a good thing");
//3.使用HttpSolrServer对象,执行添加(更新)
httpSolrServer.add(sif);
//4.提交
httpSolrServer.commit();
(4) 根据Id删除索引:
//1.建立HttpSolrServer服务对象,连接solr服务
HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1:8081/solr/");
//2.使用HttpSolrServer对象,执行删除
httpSolrServer.deleteById("9527");
//3.提交
httpSolrServer.commit();
(5) 根据条件删除索引:
//1.建立HttpSolrServer服务对象,连接solr服务
HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1:8081/solr/");
//2.使用HttpSolrServer对象,执行删除
httpSolrServer.deleteByQuery("name:solr");
//3.提交
httpSolrServer.commit();
(6) 查询索引:
//1.建立HttpSolrServer服务对象,连接solr服务
HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1:8081/solr/");
//2.建立查询对象(SolrQuery);查询所有
SolrQuery sq = new SolrQuery("*:*");
//3.使用HttpSolrServer对象,执行搜索,返回搜索结果(QueryResponse)
QueryResponse query = httpSolrServer.query(sq);
//4.从QueryResponse中,获取搜索的结果集(SolrDocumentList)
SolrDocumentList results = query.getResults();
//5.处理结果集
//5.1.获取实际搜索到的数量
System.out.println("实际搜索到的数量:"+results.getNumFound());
//5.2.获取具体的文档数据
for (SolrDocument result : results) {
System.out.println("id域: "+result.get("id"));
System.out.println("name域: "+result.get("name"));
System.out.println("title域: "+result.get("title"));
}
(7)
- 5.
1