html:html文档的根标签
head:头标签。用于指定html文档的一些属性。引入外部的资源
title:标题标签。
body:体标签
:html5中定义该文档是html文档
* 注释:
* <h1> to <h6>:标题标签
* h1~h6:字体大小逐渐递减
* <p>:段落标签
* <br>:换行标签
* <hr>:展示一条水平线
* 属性:
* color:颜色
* width:宽度
* size:高度
* align:对其方式
* center:居中
* left:左对齐
* right:右对齐
* <b>:字体加粗
* <i>:字体斜体
* <font>:字体标签
* <center>:文本居中
* 属性:
* color:颜色
* size:大小
* face:字体
* 属性定义:
* color:
1. 英文单词:red,green,blue
2. rgb(值1,值2,值3):值的范围:0~255 如 rgb(0,0,255)
3. #值1值2值3:值的范围:00~FF之间。如: #FF00FF
* width:
1. 数值:width='20' ,数值的单位,默认是 px(像素)
2. 数值%:占比相对于父元素的比例
* img:展示图片
* 属性:
* src:指定图片的位置
* 代码:
<img src="image/jingxuan_2.jpg" align="right" alt="古镇" width="500" height="500"/>
<img src="./image/jiangwai_1.jpg">
<img src="../image/jiangwai_1.jpg">
* 有序列表:
* ol:
* li:
* 无序列表:
* ul:
* li:
* a:定义一个超链接
* 属性:
* href:指定访问资源的URL(统一资源定位符)
* target:指定打开资源的方式
* _self:默认值,在当前页面打开
* _blank:在空白页面打开
* 代码:
<a href="http://www.tdte.cn">点我a>
<br>
<a href="http://www.tdte.cn" target="_self">点我a>
<br>
<a href="http://www.tdte.cn" target="_blank">点我a>
<br>
<a href="./5_列表标签.html">列表标签a><br>
<a href="mailto:[email protected]">联系我们a>
<br>
<a href="http://www.tdte.cn"><img src="image/jiangwai_1.jpg">a>
* div:每一个div占满一整行。块级标签
* span:文本信息在一行展示,行内标签 内联标签
1. <header>:页眉
2. <footer>:页脚
8. 表格标签:
* table:定义表格
* width:宽度
* border:边框
* cellpadding:定义内容和单元格的距离
* cellspacing:定义单元格之间的距离。如果指定为0,则单元格的线会合为一条、
* bgcolor:背景色
* align:对齐方式
* tr:定义行
* bgcolor:背景色
* align:对齐方式
* td:定义单元格
* colspan:合并列
* rowspan:合并行
* th:定义表头单元格
* <caption>:表格标题
* <thead>:表示表格的头部分
* <tbody>:表示表格的体部分
* <tfoot>:表示表格的脚部分
概念:用于采集用户输入的数据的。用于和服务器进行交互。
2.1 form:用于定义表单的。可以定义一个范围,范围代表采集用户数据的范围
属性:
* action:指定提交数据的URL
* method:指定提交方式
* 分类:一共7种,2种比较常用
* get:
1. 请求参数会在地址栏中显示。会封装到请求行中(HTTP协议后讲解)。
2. 请求参数大小是有限制的。
3. 不太安全。
* post:
2. 请求参数不会再地址栏中显示。会封装在请求体中(HTTP协议后讲解)
2. 请求参数的大小没有限制。
3. 较为安全。
2.2 表单项标签:
表单项中的数据要想被提交:必须指定其name属性
* input:可以通过type属性值,改变元素展示的样式
* type属性:
* text:文本输入框,默认值
* placeholder:指定输入框的提示信息,当输入框的内容发生变化,会自动清空提示信息
* password:密码输入框
* radio:单选框
* 注意:
1. 要想让多个单选框实现单选的效果,则多个单选框的name属性值必须一样。
2. 一般会给每一个单选框提供value属性,指定其被选中后提交的值
3. checked属性,可以指定默认值
* checkbox:复选框
* 注意:
1. 一般会给每一个单选框提供value属性,指定其被选中后提交的值
2. checked属性,可以指定默认值
* file:文件选择框
* hidden:隐藏域,用于提交一些信息。
* 按钮:
* submit:提交按钮。可以提交表单
* button:普通按钮
* image:图片提交按钮
* src属性指定图片的路径
* label:指定输入项的文字描述信息
* 注意:
* label的for属性一般会和 input 的 id属性值 对应。如果对应了,则点击label区域,会让input输入框获取焦点。
* select: 下拉列表
* 子元素:option,指定列表项
* 注意:
1. 一般会给每一个option提供value属性,指定其被选中后提交的值
2. selected属性,可以指定默认值
* textarea:文本域
* cols:指定列数,每一行有多少个字符
* rows:默认多少行。
* a.css文件:
div{
color:green;
}
"stylesheet" href="css/a.css">
hello css
hello css
* 注意:
"stylesheet" href="css/a.css">格式可以写为:
1. 基础选择器
1. id选择器:选择具体的id属性值的元素.建议在一个html页面中id值唯一
* 语法:#id属性值{}
2. 元素选择器:选择具有相同标签名称的元素
* 语法: 标签名称{}
* 注意:id选择器优先级高于元素选择器
3. 类选择器:选择具有相同的class属性值的元素。
* 语法:.class属性值{}
* 注意:类选择器选择器优先级高于元素选择器
2. 扩展选择器:
1. 选择所有元素:
* 语法: *{}
2. 并集选择器:
* 选择器1,选择器2{}
3. 后代选择器:会选中指定标签中,所有的特定后代标签,也就是会选中儿子,孙子,只有放到标签中的特定标签都能选中
* 语法: 选择器1 选择器2{}
4. 子元素选择器:只会选中特定的直接标签,也就是只会选中特定的儿子标签
* 语法: 选择器1 > 选择器2{}
5. 属性选择器:选择元素名称,属性名=属性值的元素
* 语法: 元素名称[属性名="属性值"]{}
6. 伪类选择器:选择一些元素具有的状态
* 语法: 元素:状态{}
* 如:
* 状态:
* link:初始化的状态
* visited:被访问过的状态
* active:正在访问状态
* hover:鼠标悬浮状态
1. 字体、文本
* font-size:字体大小
* color:文本颜色
* text-align:对其方式
* line-height:行高
2. 背景
* background:
3. 边框
* border:设置边框,符合属性
4. 尺寸
* width:宽度
* height:高度
5. 盒子模型:控制布局
* margin:外边距
* padding:内边距
* 默认情况下内边距会影响整个盒子的大小
* box-sizing: border-box; 设置盒子的属性,让width和height就是最终盒子的大小
* float:浮动
* left
* right
1. 原始数据类型(基本数据类型):
1. number:数字。 整数/小数/NaN(not a number 一个不是数字的数字类型)
2. string:字符串。 字符串 "abc" "a" 'abc'
3. boolean: true和false
4. null:一个对象为空的占位符
5. undefined:未定义。如果一个变量没有给初始化值,则会被默认赋值为undefined
2. 引用数据类型:对象
* 变量:一小块存储数据的内存空间
* Java语言是强类型语言,而JavaScript是弱类型语言。
* 强类型:在开辟变量存储空间时,定义了空间将来存储的数据的数据类型。只能存储固定类型的数据
* 弱类型:在开辟变量存储空间时,不定义空间将来的存储数据类型,可以存放任意类型的数据。
* 语法:
* var 变量名 = 初始化值;
* typeof运算符:获取变量的类型。
* 注:null运算后得到的是object
typeof(num1)
1. 一元运算符:只有一个运算数的运算符
++,-- , +(正号)
* ++ --: 自增(自减)
* ++(--) 在前,先自增(自减),再运算
* ++(--) 在后,先运算,再自增(自减)
* +(-):正负号
* 注意:在JS中,如果运算数不是运算符所要求的类型,那么js引擎会自动的将运算数进行类型转换
* 其他类型转number:
* string转number:如果字母转数字,则转为NaN(不是数字的数字类型)
* boolean转number:true转为1,false转为0
2. 算数运算符
+ - * / % ...
3. 赋值运算符
= += -+....
4. 比较运算符
> < >= <= == ===(全等于)
* 比较方式
1. 类型相同:直接比较
* 字符串:按照字典顺序比较。按位逐一比较,直到得出大小为止。
2. 类型不同:先进行类型转换,再比较
* ===:全等于。在比较之前,先判断类型,如果类型不一样,则直接返回false
&& || !
* 其他类型转boolean:
1. number:0或NaN为假,其他为真
2. string:除了空字符串(""),其他都是true
3. null&undefined:都是false
4. 对象:所有对象都为true
特别是在if语句中
if(obj){} // 代表对象不为null 或string不为""
三元运算符:var c = a > b ? 1:0;
1. if...else...
2. switch:
* 在java中,switch语句可以接受的数据类型: byte int shor char,枚举(1.5) ,String(1.7)
* switch(变量):
case 值:
* 在JS中,switch语句可以接受任意的原始数据类型
3. while
4. do...while
5. for
1. 语句以;结尾,如果一行只有一条语句则;可以省略 (不建议)
2. 变量的定义使用var关键字,也可以不使用 在函数中:
* 用:定义的变量是局部变量
* 不用:定义的变量是全局变量(不建议)
更多对象详情
1. Function:函数(方法)对象
1. 创建:
1. var fun = new Function(形式参数列表,方法体); //忘掉吧
2.
function 方法名称(形式参数列表){
方法体
}
3.
var 方法名 = function(形式参数列表){
方法体
}
2. 方法:没有
3. 属性:
length:代表形参的个数
4. 特点:
1. 方法定义是,形参的类型不用写,返回值类型也不写。
2. 方法是一个对象,如果定义名称相同的方法,会覆盖
3. 在JS中,方法的调用只与方法的名称有关,和参数列表无关
4. 在方法声明中有一个隐藏的内置对象(数组),arguments,封装所有的实际参数
5. 调用:
方法名称(实际参数列表);
2. Array:数组对象
1. 创建:
1. var arr = new Array(元素列表);
2. var arr = new Array(默认长度);
3. var arr = [元素列表];
2. 方法
join(参数): 将数组中的元素按照指定的分隔符拼接为字符串
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
3. 属性
length:数组的长度
4. 特点:
1. JS中,数组元素的类型可变的。可以同时存不同类型
2. JS中,数组长度可变的。
3. 越界不报异常,报undefined 原因参考2
3. Boolean
4. Date:日期对象
1. 创建:
var date = new Date();
2. 方法:
toLocaleString():返回当前date对象对应的时间本地字符串格式
getTime():获取毫秒值。返回当前如期对象描述的时间到1970年1月1日零点的毫秒值差
5. Math:数学对象
1. 创建:
* 特点:Math对象不用创建,直接使用。 Math.方法名();
2. 方法:
random():返回 0 ~ 1 之间的随机数。 含0不含1
ceil(x):对数进行上舍入。
floor(x):对数进行下舍入。
round(x):把数四舍五入为最接近的整数。
3. 属性:
PI
6. Number
7. String
8. RegExp:正则表达式对象
1. 正则表达式:定义字符串的组成规则。
1. 单个字符:[]
如: [a] [ab] [a-zA-Z0-9_]
* 特殊符号代表特殊含义的单个字符:
\d:单个数字字符 [0-9]
\w:单个单词字符[a-zA-Z0-9_]
2. 量词符号:
?:表示出现0次或1次
*:表示出现0次或多次
+:出现1次或多次
{m,n}:表示 m<= 数量 <= n
* m如果缺省: {,n}:最多n次
* n如果缺省:{m,} 最少m次
3. 开始结束符号
* ^:开始
* $:结束
2. 正则对象:
1. 创建
1. var reg = new RegExp("正则表达式");
2. var reg = /正则表达式/;
2. 方法
1. test(参数):验证指定的字符串是否符合正则定义的规范
9. Global
1. 特点:全局对象,这个Global中封装的方法不需要对象就可以直接调用。 方法名();
2. 方法:
encodeURI():url编码
decodeURI():url解码
encodeURIComponent():url编码,编码的字符更多 : / 等都被编码了
decodeURIComponent():url解码
parseInt():将字符串转为数字
* 逐一判断每一个字符是否是数字,直到不是数字为止,将前边数字部分转为number
isNaN():判断一个值是否是NaN
* NaN六亲不认,连自己都不认。NaN参与的==比较全部为false,只能使用isNaN判等
eval():将 JavaScript 字符串,并把它作为脚本代码来执行。
我的博客
1. 概念:Browser Object Model 浏览器对象模型
* 将浏览器的各个组成部分封装成对象。
2. 组成:
* Window:窗口对象
* Navigator:浏览器对象
* Screen:显示器屏幕对象
* History:历史记录对象
* Location:地址栏对象
3. Window:窗口对象
1. 创建
2. 方法
1. 与弹出框有关的方法:
alert() 显示带有一段消息和一个确认按钮的警告框。
confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框。
* 如果用户点击确定按钮,则方法返回true
* 如果用户点击取消按钮,则方法返回false
prompt() 显示可提示用户输入的对话框。
* 返回值:获取用户输入的值
2. 与打开关闭有关的方法:
close() 关闭浏览器窗口。
* 谁调用我 ,我关谁
open() 打开一个新的浏览器窗口
* 返回新的Window对象
3. 与定时器有关的方式
setTimeout() 在指定的毫秒数后调用函数或计算表达式。
* 参数:
1. js代码或者方法对象
2. 毫秒值
* 返回值:唯一标识,用于取消定时器
clearTimeout() 取消由 setTimeout() 方法设置的 timeout。
setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式。
clearInterval() 取消由 setInterval() 设置的 timeout。
3. 属性:
1. 获取其他BOM对象:
history
location
Navigator
Screen:
2. 获取DOM对象
document
4. 特点
* Window对象不需要创建可以直接使用 window使用。 window.方法名();
* window引用可以省略。 方法名();
*
4. Location:地址栏对象
1. 创建(获取):
1. window.location
2. location
2. 方法:
* reload() 重新加载当前文档。刷新
3. 属性
* href 设置或返回完整的 URL。
5. History:历史记录对象
1. 创建(获取):
1. window.history
2. history
2. 方法:
* back() 加载 history 列表中的前一个 URL。
* forward() 加载 history 列表中的下一个 URL。
* go(参数) 加载 history 列表中的某个具体页面。
* 参数:
* 正数:前进几个历史记录
* 负数:后退几个历史记录
3. 属性:
* length 返回当前窗口历史列表中的 URL 数量。
1. 点击事件:
1. onclick:单击事件
2. ondblclick:双击事件
2. 焦点事件
1. onblur:失去焦点
2. onfocus:元素获得焦点。
3. 加载事件:
1. onload:一张页面或一幅图像完成加载。
4. 鼠标事件:
1. onmousedown 鼠标按钮被按下。
2. onmouseup 鼠标按键被松开。
3. onmousemove 鼠标被移动。
4. onmouseover 鼠标移到某元素之上。
5. onmouseout 鼠标从某元素移开。
5. 键盘事件:
1. onkeydown 某个键盘按键被按下。
2. onkeyup 某个键盘按键被松开。
3. onkeypress 某个键盘按键被按下并松开。
6. 选择和改变
1. onchange 域的内容被改变。
2. onselect 文本被选中。
7. 表单事件:
1. onsubmit 确认按钮被点击。
2. onreset 重置按钮被点击。
1. 文档声明
1. 格式:<?xml 属性列表 ?>
2. 属性列表:
* version:版本号,必须的属性
* encoding:编码方式。告知解析引擎当前文档使用的字符集,默认值:ISO-8859-1 注意:如果encoding和文件的编码不一致会报错,idea会根据encoding自动转换当前文件编码
* standalone:是否独立 (了解)
* 取值:
* yes:不依赖其他文件
* no:依赖其他文件
2. 指令(了解):结合css的
* <?xml-stylesheet type="text/css" href="a.css" ?>
3. 标签:标签名称自定义的
* 规则:
* 名称可以包含字母、数字以及其他的字符
* 名称不能以数字或者标点符号开始
* 名称不能以字母 xml(或者 XML、Xml 等等)开始
* 名称不能包含空格
4. 属性:
id属性值唯一
5. 文本:
* CDATA区:在该区域中的数据会被原样展示
* 格式: <![CDATA[ 数据 ]]>
内部dtd:将约束规则定义在xml文档中
外部dtd:将约束的规则定义在外部的dtd文件中
本地:
网络:
1.填写xml文档的根元素
2.引入xsi前缀(固定格式) xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3.引入xsd文件命名空间 xsi:schemaLocation="http://www.tdte.cn/xml(命名空间) student.xsd(实际文件)"
4.为每一个xsd约束声明一个前缀,作为标识 xmlns="http://www.tdte.cn/xml" (别名)
示例:
解析xml思想:操作xml文档,将文档中的数据读取到内存中
* 操作xml文档
1. 解析(读取):将文档中的数据读取到内存中
2. 写入:将内存中的数据保存到xml文档中。持久化的存储
* 解析xml的方式:
1. DOM:将标记语言文档一次性加载进内存,在内存中形成一颗dom树
* 优点:操作方便,可以对文档进行CRUD的所有操作
* 缺点:占内存
2. SAX:逐行读取,基于事件驱动的。
* 优点:不占内存。
* 缺点:只能读取,不能增删改
xml常见的解析器:
1. JAXP:sun公司提供的解析器,支持dom和sax两种思想 (慢,麻烦)
2. DOM4J:一款非常优秀的解析器
3. Jsoup:jsoup 是一款Java 的HTML解析器也可以解析xml
4. PULL:Android操作系统内置的解析器,sax方式的。
Jsoup:jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
<dependency>
<groupId>org.jsoupgroupId>
<artifactId>jsoupartifactId>
<version>1.10.2version>
dependency>
* 代码:
//2.1获取student.xml的path
String path = JsoupDemo1.class.getClassLoader().getResource("student.xml").getPath();
//2.2解析xml文档,加载文档进内存,获取dom树--->Document
Document document = Jsoup.parse(new File(path), "utf-8");
//3.获取元素对象 Element
Elements elements = document.getElementsByTag("name");
System.out.println(elements.size());
//3.1获取第一个name的Element对象
Element element = elements.get(0);
//3.2获取数据
String name = element.text();
System.out.println(name);
* 对象的使用:
1. Jsoup:工具类,可以解析html或xml文档,返回Document
* parse:解析html或xml文档,返回Document
* parse(File in, String charsetName):解析xml或html文件的。
* parse(String html):解析xml或html字符串
* parse(URL url, int timeoutMillis):通过网络路径获取指定的html或xml的文档对象
2. Document:文档对象。代表内存中的dom树
* 获取Element对象
* getElementById(String id):根据id属性值获取唯一的element对象
* getElementsByTag(String tagName):根据标签名称获取元素对象集合
* getElementsByAttribute(String key):根据属性名称获取元素对象集合
* getElementsByAttributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合
3. Elements:元素Element对象的集合。可以当做 ArrayList<Element>来使用
4. Element:元素对象
1. 获取子元素对象
* getElementById(String id):根据id属性值获取唯一的element对象
* getElementsByTag(String tagName):根据标签名称获取元素对象集合
* getElementsByAttribute(String key):根据属性名称获取元素对象集合
* getElementsByAttributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合
2. 获取属性值
* String attr(String key):根据属性名称获取属性值
3. 获取文本内容
* String text():获取文本内容
* String html():获取标签体的所有内容(包括字标签的字符串内容)
5. Node:节点对象
* 是Document和Element的父类
快捷查询方式:
* 使用的方法:Elements select(String cssQuery)
* 语法:参考Selector类中定义的语法
// 示例:
Elements elements1 = document.select("student[number='h_0001']");
System.out.println(elements1);
<dependency>
<groupId>cn.wanghaomiaogroupId>
<artifactId>JsoupXpathartifactId>
<version>0.3.2version>
dependency>
* 使用Jsoup的Xpath需要额外导入jar包。
* 查询w3cshool参考手册,使用xpath的语法完成查询
* 代码:
//1.获取student.xml的path
String path = JsoupDemo6.class.getClassLoader().getResource("student.xml").getPath();
//2.获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
//3.根据document对象,创建JXDocument对象
JXDocument jxDocument = new JXDocument(document);
//4.结合xpath语法查询
//4.1查询所有student标签
List<JXNode> jxNodes = jxDocument.selN("//student");
for (JXNode jxNode : jxNodes) {
System.out.println(jxNode);
}
//4.2查询所有student标签下的name标签
List<JXNode> jxNodes2 = jxDocument.selN("//student/name");
for (JXNode jxNode : jxNodes2) {
System.out.println(jxNode);
}
//4.3查询student标签下带有id属性的name标签
List<JXNode> jxNodes3 = jxDocument.selN("//student/name[@id]");
for (JXNode jxNode : jxNodes3) {
System.out.println(jxNode);
}
//4.4查询student标签下带有id属性的name标签 并且id属性值为tdte
List<JXNode> jxNodes4 = jxDocument.selN("//student/name[@id='tdte']");
for (JXNode jxNode : jxNodes4) {
System.out.println(jxNode);
}
1. 直接将项目放到webapps目录下即可。
* /hello:项目的访问路径-->虚拟目录
* 简化部署:将项目打成一个war包,再将war包放置到webapps目录下。
* war包会自动解压缩和删除
2. 配置conf/server.xml文件 (在核心文件中配置,不推荐)
在<Host>标签体内新建配置信息:
<Context docBase="D:\hello" path="/hehe" />
* docBase:项目存放的路径
* path:虚拟目录
3. 在conf\Catalina\localhost创建任意名称的xml文件。在文件中编写 (热部署,推荐)
<Context docBase="D:\hello" />
* 虚拟目录:xml文件的名称
-- 项目的根目录
-- WEB-INF目录:
-- web.xml:web项目的核心配置文件
-- classes目录:放置字节码文件的目录
-- lib目录:放置依赖的jar包
概念:Hyper Text Transfer Protocol 超文本传输协议
* 传输协议:定义了,客户端和服务器端通信时,发送数据的格式
* 特点:
1. 基于TCP/IP的高级协议
2. 默认端口号:80
3. 基于请求/响应模型的:一次请求对应一次响应
4. 无状态的:每次请求之间相互独立,不能交互数据
* 历史版本:
* 1.0:每一次请求响应都会建立新的连接
* 1.1:复用连接
请求消息数据格式
1. 请求行
请求方式 请求url 请求协议/版本
GET /login.html HTTP/1.1
* 请求方式:
* HTTP协议有7中请求方式,常用的有2种
* GET:
1. 请求参数在请求行中,在url后。
2. 请求的url长度有限制的
3. 不太安全
* POST:
1. 请求参数在请求体中
2. 请求的url长度没有限制的
3. 相对安全
2. 请求头:客户端浏览器告诉服务器一些信息
请求头名称: 请求头值
* 常见的请求头:
1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
* 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
2. Referer:http://localhost/login.html
* 告诉服务器,我(当前请求)从哪里来?
* 作用:
1. 防盗链:
2. 统计工作:
3. 请求空行
空行,就是用于分割POST请求的请求头,和请求体的。
4. 请求体(正文):
* 封装POST请求消息的请求参数的
* 字符串格式:
POST /login.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
username=zhangsan
1. 创建JavaEE项目
2. 定义一个类,实现Servlet接口
* public class ServletDemo1 implements Servlet
3. 实现接口中的抽象方法
4. 配置Servlet
在web.xml中配置:
<servlet>
<servlet-name>demo1servlet-name>
<servlet-class>top.tdte.servlet.ServletDemo1servlet-class>
servlet>
<servlet-mapping>
<servlet-name>demo1servlet-name>
<url-pattern>/demo1url-pattern>
servlet-mapping>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6THEmMX-1592309818764)(JavaWeb.assets/image-20200523174153179.png)]
1. 被创建:执行init方法,只执行一次
* Servlet什么时候被创建?
* 默认情况下,第一次被访问时,Servlet被创建
* 可以配置执行Servlet的创建时机。
* 在<servlet>标签下配置
1. 第一次被访问时,创建
* <load-on-startup>的值为负数 默认值为-1
2. 在服务器启动时,创建
* <load-on-startup>的值为0或正整数
* Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
* 多个用户同时访问时,可能存在线程安全问题。
* 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值
2. 提供服务:执行service方法,执行多次
* 每次访问Servlet时,Service方法都会被调用一次。
3. 被销毁:执行destroy方法,只执行一次
* Servlet被销毁时执行。服务器关闭时,Servlet被销毁
* 只有服务器正常关闭时,才会执行destroy方法。
* destroy方法在Servlet被销毁之前执行,一般用于释放资源
1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
2. 定义一个类,实现Servlet接口
3. 复写方法
4. 在类上使用@WebServlet注解,进行配置
* @WebServlet("资源路径") // 不要写项目的虚拟目录
1. urlpartten:Servlet访问路径
1. 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})
2. 路径定义规则:
1. /xxx:路径匹配
2. /xxx/xxx:多层路径,目录结构
3. *.do:扩展名匹配 前面不要下/ 如 /*.do 错误
4. /xxx/* : /xxx/任意字符或符号,都能访问到当前Servlet 优先级低
IDEA与tomcat的相关配置
1. IDEA会为每一个tomcat部署的项目单独建立一份配置文件
* 查看控制台的log:Using CATALINA_BASE: "C:\Users\fqy\.IntelliJIdea2018.1\system\tomcat\_tdte"
2. 工作空间项目和tomcat部署的web项目
* tomcat真正访问的是“tomcat部署的web项目”,"tomcat部署的web项目"对应着"工作空间项目out" 的web目录下的所有资源
* WEB-INF目录下的资源不能被浏览器直接访问。
Servlet的体系结构
Servlet -- 接口
|
GenericServlet -- 抽象类
|
HttpServlet -- 抽象类 对http协议的封装,一般用此类
* GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
* HttpServlet:对http协议的一种封装,简化操作
1. request对象和response对象的原理
1. request和response对象是由服务器创建的。我们来使用它们
2. request对象是来获取请求消息,response对象是来设置响应消息
2. request对象继承体系结构:
ServletRequest -- 接口
| 继承
HttpServletRequest -- 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat实现的)
request功能:获取请求消息数据
* GET /day14/demo1?name=zhangsan HTTP/1.1
* 方法:
1. 获取请求方式 :GET
* String getMethod()
2. (*)获取虚拟目录:/day14
* String getContextPath()
3. 获取Servlet路径: /demo1
* String getServletPath()
4. 获取get方式请求参数:name=zhangsan
* String getQueryString()
5. (*)获取请求URI:/day14/demo1
* String getRequestURI(): /day14/demo1
* StringBuffer getRequestURL(): http://localhost/day14/demo1
* URL:统一资源定位符 : http://localhost/day14/demo1 中华人民共和国
* URI:统一资源标识符 : /day14/demo1 范围大 共和国
6. 获取协议及版本:HTTP/1.1
* String getProtocol()
7. 获取客户机的IP地址:
* String getRemoteAddr()
* 方法:
* (*)String getHeader(String name): //通过请求头的名称获取请求头的值
* Enumeration getHeaderNames(): //获取所有的请求头名称
- //上面两个方法互相配合,可以获得所有头信息
* 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
* 步骤:(请求头被封装成流了,因此需要流的方式获取请求头内容)
1. 获取流对象
* BufferedReader getReader()://获取字符输入流,只能操作字符数据
* ServletInputStream getInputStream()://获取字节输入流,可以操作所有类型数据
* 在文件上传知识点后讲解
2. 再从流对象中拿数据
1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
1. String getParameter(String name) //根据参数名称获取参数值,多用于单个k-v的数据
2. String[] getParameterValues(String name) // 根据参数名称获取参数值的数组,多用于复选框的传值
3. Enumeration<String> getParameterNames() //获取所有请求的参数名称
4. Map<String,String[]> getParameterMap() //获取所有参数的map集合
* 中文乱码问题:
* get方式:tomcat 8 已经将get方式乱码问题解决了
* post方式:会乱码 原因:post方式是从流中获取数据,因此编码时替换掉默认的字符集可解
* 解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");
1. 步骤:
1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
示例:request.getRequestDispatcher("/a").forward(request,response); //写资源路径
2. 特点:
1. 浏览器地址栏路径不发生变化
2. (*)只能转发到当前服务器内部资源中。
3. 转发是一次请求
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
1. void setAttribute(String name,Object obj):存储数据
2. Object getAttitude(String name):通过键获取值
4. void removeAttribute(String name):通过键移除键值对
4. 获取ServletContext:
* ServletContext getServletContext()
1. 响应行
1. 组成:协议/版本 响应状态码 状态码描述
2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
1. 状态码都是3位数字
2. 分类:
1. 1xx:服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
2. 2xx:成功。代表:200
3. 3xx:重定向。代表:302(重定向),304(访问缓存 服务器告诉你资源没有更改,访问本地浏览器缓存)
4. 4xx:客户端错误。
* 代表:
* 404(请求路径没有对应的资源)
* 405:请求方式没有对应的doXxx方法 (xxx为请求方式get/post/···)
5. 5xx:服务器端错误。代表:500(服务器内部出现异常)
2. 响应头:
1. 格式:头名称: 值
2. 常见的响应头:
1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
// Content-Type: text/html;charset=UTF-8
2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据
* 值: in-line: 默认值,数据在当前页面内打开
attachment;filename=xxx:以附件形式打开响应体。文件下载
3. 响应空行
4. 响应体: 传输的数据
1. 设置响应行
1. 格式:HTTP/1.1 200 ok
2. 设置状态码方法:setStatus(int sc)
2. 设置响应头:setHeader(String name, String value)
3. 设置响应体:
* 使用步骤:
1. 获取输出流
* 字符输出流:PrintWriter getWriter()
* 字节输出流:ServletOutputStream getOutputStream()
2. 使用输出流,将数据输出到客户端浏览器
方式一:http协议的方式进行重定义(了解)
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location和重定向路径
response.setHeader("location","/day15/responseDemo2");
方式二:
//简单的重定向方法
response.sendRedirect("/day15/responseDemo2");
* 重定向的特点:redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
//重定向到其他服务器 response.sendRedirect("http://tdte.top");
3. 重定向是两次请求。不能使用request对象来共享数据
* 转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据
乱码问题:
//获取的流的默认编码是ISO-8859-1
1. PrintWriter pw = response.getWriter();
2. 设置该流的默认编码
3. 告诉浏览器响应体使用的编码
//简单的形式,设置编码,是在获取流之前设置
//使用下面的方式就不用再设置response.setCharsetEncoding("utf-8"),tomcat会根据ContentType内容自动修改服务端的字符集
response.setContentType("text/html;charset=utf-8");
1. 通过request对象获取
request.getServletContext();
2. 通过HttpServlet获取
this.getServletContext();
1. 获取MIME类型:
* MIME类型:在互联网通信过程中定义的一种文件数据类型
* 格式: 大类型/小类型 //示例:text/html image/jpeg
* 获取指定文件的mime类型:String getMimeType(String file)
2. 域对象:共享数据
1. setAttribute(String name,Object value)
2. getAttribute(String name)
3. removeAttribute(String name)
* ServletContext对象范围:所有用户所有请求的数据
3. 获取文件的真实(服务器)路径
1. 方法:String getRealPath(String path)
String b = context.getRealPath("/b.txt");//web目录下资源访问
System.out.println(b);
// 注意,这里的参数path是指out目录的项目绝对路径,根据项目绝对路径,获取服务器真实路径
String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
System.out.println(c);
String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
System.out.println(a);
起步: 注解
1. 步骤:
1. 定义一个类,实现接口Filter
2. 复写方法
3. 配置拦截路径
1. web.xml
2. 注解
//访问所有资源之前,都会执行该过滤器
@WebFilter("/*")
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo1被执行了....");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
web.xml配置
<filter>
<filter-name>demo1filter-name>
<filter-class>cn.tdte.web.filter.FilterDemo1filter-class>
filter>
<filter-mapping>
<filter-name>demo1filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
1. 执行过滤器
2. 执行放行后的资源
3. 回来执行过滤器放行代码下边的代码
// 示例
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//对request对象请求消息增强
System.out.println("filterDemo2执行了....");
//放行
chain.doFilter(req, resp);
//对response对象的响应消息增强
System.out.println("filterDemo2回来了...");
}
init //在服务器启动后会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
doFilter //每一次请求被拦截资源时,会执行。执行多次
destroy //在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
1.拦截路径配置:
1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
2.拦截方式配置:资源被访问的方式
* 注解配置:
* 设置dispatcherTypes属性
1. REQUEST:默认值。浏览器直接请求资源
2. FORWARD:转发访问资源
3. INCLUDE:包含访问资源
4. ERROR:错误跳转资源
5. ASYNC:异步访问资源
* web.xml配置
* 设置 <filter-maping>
<dispatcher>ASYNCdispatcher>
filter-maping>标签即可
执行顺序:如果有两个过滤器:过滤器1和过滤器2
1. 过滤器1
2. 过滤器2
3. 资源执行
4. 过滤器2
5. 过滤器1
过滤器先后顺序问题:
1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
* 如: AFilter 和 BFilter,AFilter就先执行了。
2. web.xml配置: <filter-mapping>谁定义在上边,谁先执行
案例:敏感词汇过滤
* 需求:
1. 对day17_case案例录入的数据进行敏感词汇过滤
2. 敏感词汇参考 敏感词汇.txt
3. 如果是敏感词汇,替换为 ***
* 分析:
1. 对request对象进行增强。增强获取参数相关方法
2. 放行。传递代理对象
* 增强对象的功能:
* 设计模式:一些通用的解决固定问题的方式
1. 装饰模式
2. 代理模式
* 概念:
1. 真实对象:被代理的对象
2. 代理对象:
3. 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
* 实现方式:
1. 静态代理:有一个类文件描述代理模式
2. 动态代理:在内存中形成代理类
* 实现步骤:
1. 代理对象和真实对象实现相同的接口
2. 代理对象 = Proxy.newProxyInstance();
3. 使用代理对象调用方法。
4. 增强方法
* 增强方式:
1. 增强参数列表
2. 增强返回值类型
3. 增强方法体执行逻辑
//示例
public class ProxyTest {
public static void main(String[] args) {
//1.创建真实对象
Lenovo lenovo = new Lenovo();
//2.动态代理增强lenovo对象
/*
三个参数:
1. 类加载器:真实对象.getClass().getClassLoader()
2. 接口数组:真实对象.getClass().getInterfaces()
3. 处理器:new InvocationHandler()
*/
SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
/*
代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
参数:
1. proxy:代理对象
2. method:代理对象调用的方法,被封装为的对象
3. args:代理对象调用的方法时,传递的实际参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*
System.out.println("该方法执行了....");
System.out.println(method.getName());
System.out.println(args[0]);
*/
//判断是否是sale方法
if(method.getName().equals("sale")){
//1.增强参数
double money = (double) args[0];
money = money * 0.85;
System.out.println("专车接你....");
//使用真实对象调用该方法
String obj = (String) method.invoke(lenovo, money);
System.out.println("免费送货...");
//2.增强返回值
return obj+"_鼠标垫";
}else{
Object obj = method.invoke(lenovo, args);
return obj;
}
}
});
//3.调用方法
/* String computer = proxy_lenovo.sale(8000);
System.out.println(computer);*/
proxy_lenovo.show();
}
}
ServletContextListener //监听ServletContext对象的创建和销毁
方法:
* void contextDestroyed(ServletContextEvent sce)//ServletContext对象被销毁之前会调用该方法
* void contextInitialized(ServletContextEvent sce)//ServletContext对象创建后会调用该方法
使用步骤:
1. 定义一个类,实现ServletContextListener接口
2. 复写方法
3. 配置
1. web.xml
<listener>
<listener-class>cn.tdte.web.listener.ContextLoaderListener</listener-class>
</listener>
* 指定初始化参数<context-param>
2. 注解:
* @WebListener
示例:获取web.xml中的context-param值,一般用于加载配置文件
@WebListener
public class ContextListenerDemo implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// 通过getInitParameter的参数key 获取context-param的value
String src = sce.getServletContext().getInitParameter("src");
System.out.println(src); // /WEB-INF/web.xml
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
<web-app>
<context-param>
<param-name>srcparam-name>
<param-value>/WEB-INF/web.xmlparam-value>
context-param>
web-app>
1. 相对路径:通过相对路径不可以确定唯一资源
* 如:./index.html
* 不以/开头,以.开头路径
* 使用规则:找到当前资源和目标资源之间的相对位置关系
* ./:当前目录
* ../:后退一级目录
2. 绝对路径:通过绝对路径可以确定唯一资源
* 如:http://localhost/day15/responseDemo2 /day15/responseDemo2
* 以/开头的路径
* 使用规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
* 建议虚拟目录动态获取:request.getContextPath()
* 使用在: ,
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求参数,请求下载的文件名称
String filename = request.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename);
//2.2用字节流关联
FileInputStream fis = new FileInputStream(realPath);
//3.设置response的响应头
//3.1设置响应头类型:content-type
String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
response.setHeader("content-type",mimeType);
//3.2设置响应头打开方式:content-disposition
//解决中文文件名问题
//1.获取user-agent 浏览器信息
String agent = request.getHeader("user-agent");
//2.使用工具类方法编码文件名即可,根据浏览器的信息,进行中文编码
filename = DownLoadUtils.getFileName(agent, filename);
response.setHeader("content-disposition","attachment;filename="+filename);
//4.将输入流的数据写出到输出流中
ServletOutputStream sos = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len = 0;
while((len = fis.read(buff)) != -1){
sos.write(buff,0,len);
}
fis.close();
}
解决中文文件名乱码问题工具类:
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
前端页面:
<body>
<a href="/day15/img/1.jpg">图片1a>
<a href="/day15/img/1.avi">视频a>
<hr>
<a href="/day15/downloadServlet?filename=九尾.jpg">图片1a>
<a href="/day15/downloadServlet?filename=1.avi">视频a>
body>
使用步骤:
1. 创建Cookie对象,绑定数据
* new Cookie(String name, String value)
2. 发送Cookie对象
* response.addCookie(Cookie cookie)
3. 获取Cookie,拿
到数据
* Cookie[] request.getCookies()
详细介绍
1. 一次可不可以发送多个cookie?
* 可以
* 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
2. cookie在浏览器中保存多长时间?
1. 默认情况下,当浏览器关闭后,Cookie数据被销毁
2. 持久化存储:
setMaxAge(int seconds) //秒
1. 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
2. 负数:默认值 //关闭浏览器即销毁
3. 零:删除cookie信息
3. cookie能不能存中文?
* 在tomcat 8 之前 cookie中不能直接存储中文数据。
* 需要将中文数据转码---一般采用URL编码(%E3)
* 在tomcat 8 之后,cookie支持中文数据。//特殊字符还是不支持,如空格等,建议使用URL编码存储,URL解码解析
4. cookie 多个项目共享问题?
1. 同一tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
* 默认情况下cookie不能共享
setPath(String path) //设置cookie的获取范围。默认情况下,设置当前的虚拟目录
* 如果要共享,则可以将path设置为"/"
2. 不同的tomcat服务器间cookie共享问题?
* setDomain(String path) //如果设置一级域名相同,那么多个服务器之间cookie可以共享
setDomain(".baidu.com") //那么tieba.baidu.com和news.baidu.com中cookie可以共享
1. cookie存储数据在客户端浏览器 不安全,易修改
2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
* 作用:
1. cookie一般用于存出少量的不太敏感的数据
2. 在不登录的情况下,完成服务器对客户端的身份识别
起步:
1. 获取HttpSession对象:
HttpSession session = request.getSession();
2. 使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
详细介绍
1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
* 默认情况下,不是。
* 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
* 不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
* session的钝化:
* 在服务器正常关闭之前,将session对象序列化到硬盘上
* session的活化:
* 在服务器启动后,将session文件转化为内存中的session对象即可。
//注意:本机tomcat可以,在tomcat正常关闭情况下,在根目录的work会有session序列化的文件
//而在idea中序列化可以,但是反序列化可能失效,原因:idea每次发布项目都会清空work目录
3. session什么时候被销毁?
1. 服务器关闭
2. session对象调用invalidate() 。
3. session默认失效时间 30分钟
配置tomcat的web.xml(非项目的web)修改 //单位分钟
<session-config>
<session-timeout>30</session-timeout>
</session-config>
5. session的特点
1. session用于存储一次会话的多次请求的数据,存在服务器端
2. session可以存储任意类型,任意大小的数据
* session与Cookie的区别:
1. session存储数据在服务器端,Cookie在客户端
2. session没有数据大小限制,Cookie有
3. session数据安全,Cookie相对于不安全
手动写(了解)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100;
int height = 50;
//1.创建一对象,在内存中图片(验证码图片对象)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.美化图片
//2.1 填充背景色
Graphics g = image.getGraphics();//画笔对象
g.setColor(Color.PINK);//设置画笔颜色
g.fillRect(0,0,width,height);
//2.2画边框
g.setColor(Color.BLUE);
g.drawRect(0,0,width - 1,height - 1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
//生成随机角标
Random ran = new Random();
for (int i = 1; i <= 4; i++) {
int index = ran.nextInt(str.length());
//获取字符
char ch = str.charAt(index);//随机字符
//2.3写验证码
g.drawString(ch+"",width/5*i,height/2);
}
//2.4画干扰线
g.setColor(Color.GREEN);
//随机生成坐标点
for (int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面展示
ImageIO.write(image,"jpg",response.getOutputStream());
}
Hutool工具类中的验证码
Hutool验证码详细了解
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>4.6.8version>
dependency>
// 获取验证码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
lineCaptcha.write(resp.getOutputStream());
req.getSession().setAttribute("captcha",lineCaptcha);
}
//验证 验证码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
LineCaptcha captcha = (LineCaptcha) req.getSession().getAttribute("captcha");
if (captcha != null) {
String verife = req.getParameter("verif");
boolean r = captcha.verify(verife);
System.out.println("r:" + r);
if (r) {
resp.getWriter().println("yes");
}else {
resp.getWriter().println("no");
}
req.getSession().removeAttribute("captcha");
return;
}
resp.getWriter().println("no");
}
<form action="/captcha_test_war/verife">
<label>
请输入验证码:<input type="text" name="verif"><br>
label>
<img src="http://localhost:8035/captcha_test_war/captcha" alt=""><br>
<span>看不清换一张span>
<input type="submit" value="提交">
form>
<script>
// 点击图片自动切换
let img = document.getElementsByTagName("img")[0];
console.log(img)
img.onclick = function () {
// 添加无用时间戳,防止浏览器缓存图片
let date = new Date();
img.src = "http://localhost:8035/captcha_test_war/captcha?" + date.getTime()
}
script>
jsp演变历史
1. 早期只有servlet,只能使用response输出标签数据,非常麻烦
2. 后来又jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,有写html表,造成难于维护,难于分工协作
3. 再后来,java的web开发,借鉴mvc开发模式,使得程序的设计更加合理性
MVC模式
1. M:Model,模型。JavaBean
* 完成具体的业务操作,如:查询数据库,封装对象
2. V:View,视图。JSP
* 展示数据
3. C:Controller,控制器。Servlet
* 获取用户的输入
* 调用模型
* 将数据交给视图进行展示
优缺点:
1. 优点:
1. 耦合性低,方便维护,可以利于分工协作
2. 重用性高
2. 缺点:
1. 使得项目架构变得复杂,对开发人员要求高
软件设计三层架构
JSP定义Java代码的方式(下面说明的都是jps生成java文件的,就是在xxx_jsp.java文件中)
1. <% 代码 %> //在service方法中,service方法中可以定义什么,该脚本中就可以定义什么
2. <%! 代码 %> //在jsp转换后的java类的成员位置。如:成员变量、代码块等,不推荐有现车安全问题
3. <%= 代码 %> //在service方法中,会输出到页面上。 out.print("xxxx")
* request
* response
* out:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
* response.getWriter()和out.write()的区别:
* 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。
* response.getWriter()数据输出永远在out.write()之前 即使代码out在resp之前 //注意,尽量不要用response输出,防止打乱顺序
jsp9大内置对象
变量名 | 真实类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据,还可以获取其他八个内置对象 |
request | HttpServletRequest | 一次请求访问的多个资源(转发) |
session | HttpSession | 一次会话的多个请求间 |
application | ServletContext | 所有用户间共享数据 |
response | HttpServletResponse | 响应对象 |
page | Object | 当前页面(Servlet)的对象 this |
out | JspWriter | 输出对象,数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | 异常对象 |
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
分类:只有三种
1.page: 配置JSP页面的
* contentType:等同于response.setContentType()
1. 设置响应体的mime类型以及字符集
2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
//示例:<%@ page contentType="text/html;charset=UTF-8" language="java" %>
* import:导包 //示例:<%@ page import="java.nio.channels.Channel" %>
* errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
// 示例:<%@ page errorPage="500.jsp" %> //当前页面发生异常后,会跳转到500.jsp页面
* isErrorPage:标识当前也是是否是错误页面。一般用来错误页面日志记录的,参数:
* true:是,可以使用内置对象exception
* false:否。默认值。不可以使用内置对象exception
2.include: 页面包含的。导入页面的资源文件 //模板模块
* <%@include file="top.jsp"%>
3.taglib: 导入资源 // 导入标签库
* <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
* prefix:前缀,自定义的xxx
基本使用:
1.运算符:
1. 算数运算符: + - * /(div) %(mod)
2. 比较运算符: > < >= <= == !=
3. 逻辑运算符: &&(and) ||(or) !(not)
4. 空运算符: empty
* 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
* ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
* ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
2.获取值
1. el表达式只能从域对象中获取值
2. 语法:
1. ${域名称.键名}:从指定域中获取指定键的值
* 域名称:
1. pageScope --> pageContext
2. requestScope --> request
3. sessionScope --> session
4. applicationScope --> application(ServletContext)
* 举例:在request域中存储了name=张三
* 获取:${requestScope.name}
2. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
3.获取对象、List集合、Map集合的值
1. 对象:${域名称.键名.属性名}
* 本质上会去调用对象的getter方法
2. List集合:${域名称.键名[索引]} //如果下标越界,则什么都不显示
3. Map集合获取value:
* ${域名称.map名.key名称}
* ${域名称.map名["key名称"]}
3.隐式对象:
* el表达式中有11个隐式对象
* 常用就一个:pageContext:获取jsp其他八个内置对象
//示例:${pageContext.request.contextPath} 态获取虚拟目录
概念:JavaServer Pages Tag Library JSP标准标签库
作用:用于简化和替换jsp页面上的java代码
使用步骤:
<dependency>
<groupId>Javax.servletgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2version>
dependency>
1. if:相当于java代码的if语句
1. 属性:
* test 必须属性,接受boolean表达式
* 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
* 一般情况下,test属性值会结合el表达式一起使用
2. 注意:
* c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
2. choose:相当于java代码的switch语句
1. 使用choose标签声明 相当于switch声明
2. 使用when标签做判断 相当于case
3. 使用otherwise标签做其他情况的声明 相当于default
//示例:
<%request.setAttribute("number",51);%>
星期一
星期二
星期三
星期四
星期五
星期六
星期天
数字输入有误
3. foreach:相当于java代码的for语句
3.1普通循环
属性:
begin:开始值
end:结束值
var:临时变量
step:步长
varStatus:循环状态对象
index:容器中元素的索引,从0开始
count:循环计次,从1开始
示例:
${i}
${s.index}
${s.count}
3.2遍历容器
* 属性:
items:容器对象
var:容器中元素的临时变量
<%
List list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
request.setAttribute("list", list);
%>
${s.index} ${s.count} ${str}
<dependency>
<groupId>commons-beanutilsgroupId>
<artifactId>commons-beanutilsartifactId>
<version>1.9.4version>
dependency>
1.封装前提:
1. 类public修饰
2. 有空参构造
3. 成员变量private修饰
4. 提供公共setter和getter方法
2.封装原理: setter和getter方法截取后的产物
例如:getUsername() --> Username--> username
3.方法:
1. setProperty() //setProperty(对象,封装名,封装值)
2. getProperty() //封装值 getProperty(对象,封装名)
//将map集合的键值对信息,封装到对应的JavaBean对象中
3. populate(Object obj , Map map)
4. 示例:
Map<String, String[]> map = req.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.21version>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.7version>
dependency>
事务处理工具类
public class TransactionDemoUtil {
// ThreadLocal 用于存储Connection对象,线程隔离,获取是副本
private static final ThreadLocal<Connection> tl = new ThreadLocal<>();
// 获取连接
public static Connection getConnection() {
// 获取Connection 如过没有,就从数据源中拿出一个,存储到tl中
Connection tlc = tl.get();
if (tlc == null) {
DataSource dataSource = DruidUtil.getDataSource();
try {
tl.set(dataSource.getConnection());
return tl.get();
} catch (SQLException throwables) {
throw new RuntimeException("获取druid连接异常");
}
}
// 如果有Connection直接复用此链接对象
return tl.get();
}
// 开启事务
public static void startTransaction() throws SQLException {
getConnection().setAutoCommit(false);
}
// 提交事务
public static void commit() throws SQLException {
Connection conn = getConnection();
if (conn != null) {
conn.commit();
}
}
// 回滚
public static void rollback() throws SQLException {
Connection conn = getConnection();
if (conn != null) {
conn.rollback();
}
}
/**
* 关闭连接
* ThreadLocal是线程隔离的,因此不会关闭同一connection
*/
public static void close() throws SQLException {
if (getConnection() != null) {
getConnection().close();
tl.remove();
}
}
}
表的实体类
@Data
public class Account implements Serializable {
private Integer id;
private Double salary;
}
持久层
public class AccountDao {
private final QueryRunner qy = new QueryRunner();
public Account findAccountById(int id) throws SQLException {
return qy.query(TransactionDemoUtil.getConnection(),
"select * from tdte_db.account where id=?",
new BeanHandler<>(Account.class), id);
}
public int updateAccountById(int id, double money) throws SQLException {
return qy.update(TransactionDemoUtil.getConnection(),
"update tdte_db.account set salary=? where id = ?", money, id);
}
}
业务层
public class AccountService {
private final AccountDao dao = new AccountDao();
/**
* 转账操作
* @param fromId 付款人
* @param toId 收款人
* @param money 付款金额
*/
public void transfer(int fromId, int toId,double money) {
try {
TransactionDemoUtil.startTransaction();
Account fromAccount = dao.findAccountById(fromId);
Account toAccount = dao.findAccountById(toId);
if (fromAccount == null || toAccount == null) {
throw new RuntimeException("转账失败,用户不存在");
}
if (fromAccount.getSalary() < money) {
throw new RuntimeException("付款方余额不足");
}
dao.updateAccountById(fromAccount.getId(), fromAccount.getSalary() - money);
//int i = 1 / 0;
dao.updateAccountById(toAccount.getId(), toAccount.getSalary() + money);
TransactionDemoUtil.commit();
} catch (Exception e1) {
try {
System.out.println("转账过程中出现错误,正在回滚...");
TransactionDemoUtil.rollback();
} catch (SQLException e2) {
e2.printStackTrace();
}
}finally {
try {
System.out.println("关闭连接...");
TransactionDemoUtil.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
// 多线程测试
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new AccountService().new test01()).start();
}
}
public class test01 implements Runnable{
@Override
public void run() {
transfer(1,2,1);
System.out.println(Thread.currentThread().getName());
}
}
}
概念: 一个JavaScript框架。简化JS开发
jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨 是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优 化HTML文档操作、事件处理、动画设计和Ajax交互。
JavaScript框架:本质上就是一些js文件,封装了js的原生代码而已
版本说明
JQuery对象和JS对象区别与转换
1. 事件绑定
//1.获取b1按钮
$("#b1").click(function(){
alert("abc");
});
2. 入口函数
$(function () {
});
window.onload 和 $(function) 区别
* window.onload //是属性,通过复制的方式,只能定义一次,如果定义多次,后边的会将前边的覆盖掉
* $(function) //可以定义多次的。
3. 样式控制:css方法
// $("#div1").css("background-color","red");
$("#div1").css("backgroundColor","pink");
1. 标签选择器(元素选择器)
* 语法: $("html标签名") 获得所有匹配标签名称的元素
2. id选择器
* 语法: $("#id的属性值") 获得与指定id属性值匹配的元素
3. 类选择器
* 语法: $(".class的属性值") 获得与指定的class属性值匹配的元素
4. 并集选择器:
* 语法: $("选择器1,选择器2....") 获取多个选择器选中的所有元素
1. 后代选择器
* 语法: $("A B ") //所有b孙子
2. 子选择器
* 语法: $("A > B") //选择所有b儿子
1. 基本选择器
1. 属性名称选择器
* 语法: $("A[属性名]") 包含指定属性的选择器
2. 属性选择器
* 语法: $("A[属性名='值']") 包含指定属性等于指定值的选择器 "A[属性名(^,$,*,!)='值']"
3. 复合属性选择器 (&&关系)
* 语法: $("A[属性名='值'][]...") 包含多个属性条件的选择器
1. 首元素选择器
* 语法: :first 获得选择的元素中的第一个元素
2. 尾元素选择器
* 语法: :last 获得选择的元素中的最后一个元素
3. 非元素选择器
* 语法: :not(selector) 不包括指定内容的元素
4. 偶数选择器
* 语法: :even 偶数,从 0 开始计数
5. 奇数选择器
* 语法: :odd 奇数,从 0 开始计数
6. 等于索引选择器
* 语法: :eq(index) 指定索引元素
7. 大于索引选择器
* 语法: :gt(index) 大于指定索引元素
8. 小于索引选择器
* 语法: :lt(index) 小于指定索引元素
9. 标题选择器
* 语法: :header 获得标题(h1~h6)元素,固定写法
// 示例:
// " 改变第一个 div 元素的背景色为 红色"
$("div:first").css('backgroundColor','red')
// 改变最后一个 div 元素的背景色为 红色"
$("div:last").css('backgroundColor','red')
// 改变class不为 one 的所有 div 元素的背景色为 红色"
$("div:not('.one')").css('backgroundColor','red')
// 改变索引值为偶数的 div 元素的背景色为 红色"
$("div:even").css('backgroundColor','red')
// 改变索引值为奇数的 div 元素的背景色为 红色"
$("div:odd").css('backgroundColor','red')
// 改变索引值为大于 3 的 div 元素的背景色为 红色"
$("div:gt(3)").css('backgroundColor','red')
// 改变索引值为等于 3 的 div 元素的背景色为 红色"
$("div:eq(3)").css('backgroundColor','red')
// value=" 改变索引值为小于 3 的 div 元素的背景色为 红色"
$("div:lt(3)").css('backgroundColor','red')
// 改变所有的标题元素的背景色为 红色"
$(":header").css('backgroundColor','red')
1. 可用元素选择器
* 语法: :enabled 获得可用元素
2. 不可用元素选择器
* 语法: :disabled 获得不可用元素
3. 选中选择器
* 语法: :checked 获得单选/复选框选中的元素
4. 选中选择器
* 语法: :selected 获得下拉框选中的元素
// 示例:
// 利用 jQuery 对象的 val() 方法改变表单内可用 元素的值"
$('input[type="text"]:enabled').val("aaaa")
// 利用 jQuery 对象的 val() 方法改变表单内不可用 元素的值"
$('input[type="text"]:disabled').val("aaaa")
//利用 jQuery 对象的 length 属性获取复选框选中的个数"
alert($('input[type="checkbox"]:checked').length)
// 利用 jQuery 对象的 length 属性获取下拉框选中的个数"
alert($('#job >option:selected').length)
1. html(): 获取/设置元素的标签体内容 <a><font>内容</font></a> --> <font>内容</font>
2. text(): 获取/设置元素的标签体纯文本内容 <a><font>内容</font></a> --> 内容
// 注意,使用text()修改也都会覆盖所有子标签内容(标签+文本)
3. val(): 获取/设置元素的value属性值
1. 通用属性操作
1. attr(): 获取/设置元素的属性
2. removeAttr():删除属性
3. prop():获取/设置元素的属性
4. removeProp():删除属性
* attr和prop区别?
1. 如果操作的是元素的固有属性,则建议使用prop //查文档,看哪些是固有的
2. 如果操作的是元素自定义的属性,则建议使用attr
// 示例:
//获取id=bj的name属性值
console.log($('#bj').attr('name'))
//设置北京节点的name属性的值为dabeijing
$('#bj').attr('name','dabeijing')
//新增北京节点的discription属性 属性值是didu
$('#bj').attr('discription','didu')
//删除北京节点的name属性并检验name属性是否存在
$('#bj').removeAttr('name')
//获得hobby的的选中状态
var status = $('#hobby').prop('checked');
alert(status)
//获取不到,弹出undefined
var checked = $("#hobby").attr("checked");
2. 对class属性操作
1. addClass():添加class属性值
2. removeClass():删除class属性值
3. toggleClass():切换class属性
演示:toggleClass("one") 判断如果元素对象上存在class="one",则将属性值one删除掉。 如果元素对象上不存在class="one",则添加
4. css():
// 示例:
//采用属性增加样式(改变id=one的样式)"
$('#one').addClass("second")
// value="removeClass"
$('#one').removeClass("second")
//切换样式
$('#one').toggleClass("second")
// 通过css()获得id为one背景颜色"
console.log($('#one').css("backgroundColor"));
// 通过css()设置id为one背景颜色为绿色"
$('#one').css("backgroundColor","red")
1. append():父元素将子元素追加到末尾,并删除移动前的位置
* 对象1.append(对象2): 将对象2添加到对象1元素内部,并且在末尾
2. prepend():父元素将子元素追加到开头
* 对象1.prepend(对象2):将对象2添加到对象1元素内部,并且在开头
3. appendTo():
* 对象1.appendTo(对象2):将对象1添加到对象2内部,并且在末尾
4. prependTo():
* 对象1.prependTo(对象2):将对象1添加到对象2内部,并且在开头
5. after():添加元素到元素后边
* 对象1.after(对象2): 将对象2添加到对象1后边。对象1和对象2是兄弟关系
6. before():添加元素到元素前边
* 对象1.before(对象2): 将对象2添加到对象1前边。对象1和对象2是兄弟关系
7. insertAfter()
* 对象1.insertAfter(对象2):将对象1添加到对象2后边。对象1和对象2是兄弟关系
8. insertBefore()
* 对象1.insertBefore(对象2): 将对象1添加到对象2前边。对象1和对象2是兄弟关系
9. remove():移除元素
* 对象.remove():将对象删除掉
10. empty():清空元素的所有后代元素。
* 对象.empty():将对象的后代元素全部清空,但是保留当前对象以及其属性节点
11.clone() :克隆当前对象
//头函数的this永远指向其上下文的this,没有办改变其指向,普通函数的this指向调用它的对象
//在全局执行环境中(在任何函数体外部),this都是指向全局对象。在浏览器中,window对象即是全局对象
// 克隆示例
$(function () {
$('ul img').click(function (){
$('.word').append($(this).clone())
})
});
1. 默认显示和隐藏方式
1. show([speed,[easing],[fn]])
1. 参数:
1. speed:动画的速度。三个预定义的值("slow","normal", "fast")或表示动画时长的毫秒数值(如:1000)
2. easing:用来指定切换效果,默认是"swing",可用参数"linear"
* swing:动画执行时效果是 先慢,中间快,最后又慢
* linear:动画执行时速度是匀速的
3. fn:在动画完成时执行的函数,每个元素执行一次。
2. hide([speed,[easing],[fn]])
3. toggle([speed],[easing],[fn])
//$('#showDiv').toggle(1000,'swing')
2. 滑动显示和隐藏方式
1. slideDown([speed],[easing],[fn])
2. slideUp([speed,[easing],[fn]])
3. slideToggle([speed],[easing],[fn])
3. 淡入淡出显示和隐藏方式
1. fadeIn([speed],[easing],[fn])
2. fadeOut([speed],[easing],[fn])
3. fadeToggle([speed,[easing],[fn]])
1. js的遍历方式
* for(初始化值;循环结束条件;步长)
2. jq的遍历方式
1. jq对象.each(callback)
1. 语法:
jquery对象.each(function(index,element){});
* index:就是元素在集合中的索引
* element:就是集合中的每一个元素对象
* this:集合中的每一个元素对象
2. 回调函数返回值:
* true:如果当前function返回为false,则结束循环(break)。
* false:如果当前function返回为true,则结束本次循环,继续下次循环(continue)
2. $.each(object, [callback])
3. for..of: jquery 3.0 版本之后提供的方式
for(元素对象 of 容器对象)
1. jquery标准的绑定方式
* jq对象.事件方法(回调函数);
* 注:如果调用事件方法,不传递回调函数,则会触发浏览器默认行为。
* 表单对象.submit();//让表单提交
2. on绑定事件/off解除绑定
* jq对象.on("事件名称",回调函数)
* jq对象.off("事件名称")
* 如果off方法不传递任何参数,则将组件上的所有事件全部解绑
3. 事件切换:toggle //注意需要引入插件
* jq对象.toggle(fn1,fn2...)
* 当单击jq对象对应的组件后,会执行fn1.第二次点击会执行fn2..... 往复循环执行
* 注意:1.9版本 .toggle() 方法删除,jQuery Migrate(迁移)插件可以恢复此功能。
<script src="../js/jquery-migrate-1.0.0.js" type="text/javascript" charset="utf-8"></script>
1. $.fn.extend(object)
* 增强通过Jquery获取的对象的功能 $("#id")
2. $.extend(object)
* 增强JQeury对象自身的功能 $/jQuery
// 示例
// 1.$.fn.extend(object)
$.fn.extend({
// 定义两个jq对象增强方法,this指代调用的jq对象
check:function () {
this.prop('checked',true)
},
uncheck:function () {
this.prop('checked',false)
}
})
$(function () {
$("#btn-check").click(function () {
$("input[type='checkbox']").check();
})
$("#btn-uncheck").click(function () {
$("input[type='checkbox']").uncheck();
})
})
//2.$.extend(object)
//对全局方法扩展
$.extend({
sum:function (a,b) {
alert(a+b)
},
max:function (a,b) {
}
})
console.log($.sum(1, 2));
//1.创建核心对象
var xmlhttp;
if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//2. 建立连接
/*
参数:
1. 请求方式:GET、POST
* get方式,请求参数在URL后边拼接。send方法为空参
* post方式,请求参数在send方法中定义
2. 请求的URL:
3. 同步或异步请求:true(异步)或 false(同步)
*/
xmlhttp.open("GET","ajaxServlet?username=tom",true);
//3.发送请求
xmlhttp.send();
//4.接受并处理来自服务器的响应结果
//获取方式 :xmlhttp.responseText
//什么时候获取?当服务器响应成功后再获取
//当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange。
xmlhttp.onreadystatechange=function()
{
//判断readyState就绪状态是否为4,判断status响应状态码是否为200
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//获取服务器的响应结果
var responseText = xmlhttp.responseText;
alert(responseText);
}
}
1. $.ajax()
* 语法:$.ajax({键值对});
//使用$.ajax()发送异步请求
$.ajax({
url:"ajaxServlet1111" , // 请求路径
type:"POST" , //请求方式
//data: "username=jack&age=23",//请求参数
data:{"username":"jack","age":23},
success:function (data) {
alert(data);
},//响应成功后的回调函数
error:function () {
alert("出错啦...")
},//表示如果请求响应出现错误,会执行的回调函数
dataType:"text"//设置接受到的响应数据的格式
});
2. $.get():发送get请求
* 语法:$.get(url, [data], [callback], [type])
* 参数:
* url:请求路径
* data:请求参数
* callback:回调函数
* type:响应结果的类型
3. $.post():发送post请求
* 语法:$.post(url, [data], [callback], [type])
* 参数:
* url:请求路径
* data:请求参数
* callback:回调函数
* type:响应结果的类型
Person p = new Person();
p.setName("张三");
p.setAge(23);
p.setGender("男");
var p = {"name":"张三","age":23,"gender":"男"};
1. 基本规则
* 数据在名称/值对中:json数据是由键值对构成的
* 键用引号(单双都行)引起来,也可以不使用引号
* 值得取值类型:
1. 数字(整数或浮点数)
2. 字符串(在双引号中)
3. 逻辑值(true 或 false)
4. 数组(在方括号中) {"persons":[{},{}]}
5. 对象(在花括号中) {"address":{"province":"陕西"....}}
6. null
* 数据由逗号分隔:多个键值对由逗号分隔
* 花括号保存对象:使用{}定义json 格式
* 方括号保存数组:[]
2. 获取数据:
1. json对象.键名
2. json对象["键名"]
3. 数组对象[索引]
4. 遍历
//1.定义基本格式
var person = {"name": "张三", age: 23, 'gender': true};
var ps = [{"name": "张三", "age": 23, "gender": true},
{"name": "李四", "age": 24, "gender": true},
{"name": "王五", "age": 25, "gender": false}];
//获取person对象中所有的键和值
//for in 循环
/* for(var key in person){
//这样的方式获取不行。因为相当于 person."name"
//alert(key + ":" + person.key);
alert(key+":"+person[key]);
}*/
//获取ps中的所有值
for (var i = 0; i < ps.length; i++) {
var p = ps[i];
for(var key in p){
alert(key+":"+p[key]);
}
}
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.11.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.11.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.11.0version>
dependency>
1. 导入jackson的相关jar包
2. 创建Jackson核心对象 ObjectMapper
3. 调用ObjectMapper的相关方法进行转换
1. readValue(json字符串数据,Class)
1. 创建Jackson核心对象 ObjectMapper
2. 调用ObjectMapper的相关方法进行转换
1. 转换方法:
* writeValue(参数1,obj):
参数1:
File:将obj对象转换为JSON字符串,并保存到指定的文件中
Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中
* writeValueAsString(obj) //将对象转为json字符串并返回
2. 注解:
1. @JsonIgnore:排除属性,位置:属性或get方法。
2. @JsonFormat:属性值得格式化
* @JsonFormat(pattern = "yyyy-MM-dd")
3. 复杂java对象转换 // 直接交给writerValue就可以转换
1. List:数组
2. Map:对象格式一致
// 前端操作
JSON.parse(JSON.stringify({"name":"abcde"})) => {name:"abcde"}
NoSQL(NoSQL = Not Only SQL),意即“不仅仅是SQL”,是一项全新的数据库理念,泛指非关系型的数据库。
随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
1.1.1. NOSQL和关系型数据库比较
优点:
1)成本:nosql数据库简单易部署,基本都是开源软件,不需要像使用oracle那样花费大量成本购买使用,相比关系型数据库价格便宜。
2)查询速度:nosql数据库将数据存储于缓存之中,关系型数据库将数据存储在硬盘中,自然查询速度远不及nosql数据库。
3)存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型。
4)扩展性:关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。
缺点:
1)维护的工具和资料有限,因为nosql是属于新的技术,不能和关系型数据库10几年的技术同日而语。
2)不提供对sql的支持,如果不支持sql这样的工业标准,将产生一定用户的学习和使用成本。
3)不提供关系型数据库对事务的处理。
1.1.2. 非关系型数据库的优势:
1)性能NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。
2)可扩展性同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
1.1.3. 关系型数据库的优势:
1)复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。
2)事务支持使得对于安全性能很高的数据访问要求得以实现。对于这两类数据库,对方的优势就是自己的弱势,反之亦然。
1.1.4. 总结
关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库,
让NoSQL数据库对关系型数据库的不足进行弥补。
一般会将数据存储在关系型数据库中,在nosql数据库中备份存储关系型数据库的数据
1.2.主流的NOSQL产品
• 键值(Key-Value)存储数据库
相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
典型应用: 内容缓存,主要用于处理大量数据的高访问负载。
数据模型: 一系列键值对
优势: 快速查询
劣势: 存储的数据缺少结构化
• 列存储数据库
相关产品:Cassandra, HBase, Riak
典型应用:分布式的文件系统
数据模型:以列簇式存储,将同一列数据存在一起
优势:查找速度快,可扩展性强,更容易进行分布式扩展
劣势:功能相对局限
• 文档型数据库
相关产品:CouchDB、MongoDB
典型应用:Web应用(与Key-Value类似,Value是结构化的)
数据模型: 一系列键值对
优势:数据结构要求不严格
劣势: 查询性能不高,而且缺乏统一的查询语法
• 图形(Graph)数据库
相关数据库:Neo4J、InfoGrid、Infinite Graph
典型应用:社交网络
数据模型:图结构
优势:利用图结构相关算法。
劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供测试数据,50个并发执行100000个请求,读的速度是110000次/s,写的速度是81000次/s ,且Redis通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型如下:
1) 字符串类型 string
2) 哈希类型 hash
3) 列表类型 list
4) 集合类型 set
5) 有序集合类型 sortedset
• 缓存(数据查询、短连接、新闻内容、商品内容等等)
• 聊天室的在线好友列表
• 任务队列。(秒杀、抢购、12306等等)
• 应用排行榜
• 网站访问统计
• 数据过期处理(可以精确到毫秒)
• 分布式集群架构中的session分离
redis.windows.conf //配置文件
redis-cli.exe //redis的客户端
redis-server.exe //redis服务器端
# window下安装redis或启动报错:
# creating server tcp listening socket 127.0.0.1:6379: bind No error
# 的解决方案如下按顺序输入如下命令就可以连接成功
1. redis-cli.exe
2. shutdown
3. exit
4. redis-server.exe redis.windows.conf
1. keys * : 查询所有的键
2. type key : 获取键对应的value的类型
3. del key:删除指定的key value
其他详细情况Redis文档