JavaWeb教程大全

文章目錄

一、HTML5 超文本標記語言

1. 常用標籤

  1. 文件標籤:構成html最基本的標籤
html:html文檔的根標籤
head:頭標籤。用於指定html文檔的一些屬性。引入外部的資源
title:標題標籤。
body:體標籤
<!DOCTYPE html>:html5中定義該文檔是html文檔
  1. 文本標籤:和文本有關的標籤
* 註釋:<!-- 註釋內容 -->
* <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. 數值%:佔比相對於父元素的比例
  1. 圖片標籤:
* img:展示圖片
	* 屬性:
		* src:指定圖片的位置
* 代碼:
		<!--展示一張圖片 img-->
	<img src="image/jingxuan_2.jpg" align="right" alt="古鎮" width="500" height="500"/>
	<!--
		相對路徑
			* 以.開頭的路徑
				* ./:代表當前目錄  ./image/1.jpg
				* ../:代表上一級目錄
		-->
	<img src="./image/jiangwai_1.jpg">
	<img src="../image/jiangwai_1.jpg">
  1. 列表標籤:
* 有序列表:
	* ol:
	* li:
* 無序列表:
	* ul:
	* li:
  1. 鏈接標籤:
* a:定義一個超鏈接
	* 屬性:
		* href:指定訪問資源的URL(統一資源定位符)
		* target:指定打開資源的方式
			* _self:默認值,在當前頁面打開
			* _blank:在空白頁面打開

* 代碼:
	<!--超鏈接  a-->
	<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>
	
  1. div和span:
* div:每一個div佔滿一整行。塊級標籤
* span:文本信息在一行展示,行內標籤 內聯標籤
  1. 語義化標籤:html5中爲了提高程序的可讀性,提供了一些標籤。
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. 表單

概念:用於採集用戶輸入的數據的。用於和服務器進行交互。
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:默認多少行。

二、CSS3 層疊樣式表

1. 引用CSS

* a.css文件:
	div{
		color:green;
	}
<link rel="stylesheet" href="css/a.css">
<div>hello css</div>
<div>hello css</div>

* 注意:
 <link rel="stylesheet" href="css/a.css">格式可以寫爲:
	<style>
		@import "css/a.css";
	</style>

2. 選擇器

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. 僞類選擇器:選擇一些元素具有的狀態
		* 語法: 元素:狀態{}
		* 如: <a>
			* 狀態:
				* link:初始化的狀態
				* visited:被訪問過的狀態
				* active:正在訪問狀態
				* hover:鼠標懸浮狀態
  1. 常用css屬性
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

三、JavaScript

1. 基礎語法

1.1 數據類型

1. 原始數據類型(基本數據類型)1. number:數字。 整數/小數/NaN(not a number 一個不是數字的數字類型)
	2. string:字符串。 字符串  "abc" "a" 'abc'
	3. boolean: truefalse
	4. null:一個對象爲空的佔位符
	5. undefined:未定義。如果一個變量沒有給初始化值,則會被默認賦值爲undefined
	
2. 引用數據類型:對象

1.2 變量

* 變量:一小塊存儲數據的內存空間
* Java語言是強類型語言,而JavaScript是弱類型語言。
	* 強類型:在開闢變量存儲空間時,定義了空間將來存儲的數據的數據類型。只能存儲固定類型的數據
	* 弱類型:在開闢變量存儲空間時,不定義空間將來的存儲數據類型,可以存放任意類型的數據。
* 語法:
	* var 變量名 = 初始化值;

* typeof運算符:獲取變量的類型。
	* 注:null運算後得到的是object
	typeof(num1)

1.3 運算符

1. 一元運算符:只有一個運算數的運算符
	++--+(正號)  
	* ++ --: 自增(自減)
		* ++(--) 在前,先自增(自減),再運算
		* ++(--) 在後,先運算,再自增(自減)
	* +(-):正負號
	* 注意:在JS中,如果運算數不是運算符所要求的類型,那麼js引擎會自動的將運算數進行類型轉換
		* 其他類型轉number:
			* string轉number:如果字母轉數字,則轉爲NaN(不是數字的數字類型)
			* boolean轉number:true轉爲1false轉爲0
2. 算數運算符
	+ - * / % ...

3. 賦值運算符
	= += -+....

4. 比較運算符
	> < >= <= == ===(全等於)
	* 比較方式
		1. 類型相同:直接比較
			* 字符串:按照字典順序比較。按位逐一比較,直到得出大小爲止。
		2. 類型不同:先進行類型轉換,再比較
			* ===:全等於。在比較之前,先判斷類型,如果類型不一樣,則直接返回false

1.4 邏輯運算符

&& || !
* 其他類型轉boolean:
	1. number:0NaN爲假,其他爲真
	2. string:除了空字符串(""),其他都是true  
	3. null&undefined:都是false
	4. 對象:所有對象都爲true
    特別是在if語句中
    if(obj){} // 代表對象不爲null 或string不爲""
三元運算符:var c = a > b ? 1:0;

1.5 流程控制語句

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.6 JS特殊語法

1. 語句以;結尾,如果一行只有一條語句則;可以省略 (不建議)
2. 變量的定義使用var關鍵字,也可以不使用 在函數中:
	* 用:定義的變量是局部變量
	* 不用:定義的變量是全局變量(不建議)

1.7 常用9大對象

更多對象詳情

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():獲取毫秒值。返回當前如期對象描述的時間到197011日零點的毫秒值差
        
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 字符串,並把它作爲腳本代碼來執行。

2. DOM

我的博客

3. BOM

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	設置或返回完整的 URL5. History:歷史記錄對象
    1. 創建(獲取)1. window.history
        2. history

    2. 方法:
        * back()	加載 history 列表中的前一個 URL* forward()	加載 history 列表中的下一個 URL* go(參數)	加載 history 列表中的某個具體頁面。
            * 參數:
                * 正數:前進幾個歷史記錄
                * 負數:後退幾個歷史記錄
    3. 屬性:
        * length	返回當前窗口歷史列表中的 URL 數量。

4. 事件與監聽

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	重置按鈕被點擊。

四、XML 可擴展標記語言

1. 組成部分:

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[ 數據 ]]>

2. 約束

2.1 引入DTD

  • 與Schema比,不能約束標籤的文本內容
內部dtd:將約束規則定義在xml文檔中
外部dtd:將約束的規則定義在外部的dtd文件中
	本地:<!DOCTYPE 根標籤名 SYSTEM "dtd文件的位置">
	網絡:<!DOCTYPE 根標籤名 PUBLIC "dtd文件名字(任意)" "dtd文件的位置URL">

2.2 引入Schema

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" (別名)
示例:
<students   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.tdte.cn/xml"
	xsi:schemaLocation="http://www.tdte.cn/xml  student.xsd">

3. 解析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方式的。

3.1 Jsoup 解析器

Jsoup:jsoup 是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似於jQuery的操作方法來取出和操作數據。

<dependency>
	<groupId>org.jsoup</groupId>
	<artifactId>jsoup</artifactId>
	<version>1.10.2</version>
</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的父類

快捷查詢方式:

  1. selector:選擇器
* 使用的方法:Elements	select​(String cssQuery)
	* 語法:參考Selector類中定義的語法
// 示例:
Elements elements1 = document.select("student[number='h_0001']");
System.out.println(elements1);
  1. XPath:XPath即爲XML路徑語言,它是一種用來確定XML(標準通用標記語言的子集)文檔中某部分位置的語言
<dependency>
	<groupId>cn.wanghaomiao</groupId>
	<artifactId>JsoupXpath</artifactId>
	<version>0.3.2</version>
</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);
	}

五、Tomcat 網絡應用服務器

1. 項目部署方式

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文件的名稱

2. java動態項目的目錄結構

-- 項目的根目錄
	-- WEB-INF目錄:
		-- web.xml:web項目的核心配置文件
		-- classes目錄:放置字節碼文件的目錄
		-- lib目錄:放置依賴的jar包

3. HTTP協議

概念: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	

4. Servlet (Server Applet) 小服務程序

  • 概念:運行在服務器端的小程序
    • Servlet就是一個接口,定義了Java類被瀏覽器訪問到(tomcat識別)的規則。
    • 將來我們自定義一個類,實現Servlet接口,複寫方法。
  • 起步
1. 創建JavaEE項目
2. 定義一個類,實現Servlet接口
	* public class ServletDemo1 implements Servlet
3. 實現接口中的抽象方法
4. 配置Servlet
		在web.xml中配置:
	<!--配置Servlet -->
	<servlet>
		<servlet-name>demo1</servlet-name>
		<servlet-class>top.tdte.servlet.ServletDemo1</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>demo1</servlet-name>
		<url-pattern>/demo1</url-pattern>
	</servlet-mapping>

4.1 執行流程(原理)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-V6THEmMX-1592309818764)(JavaWeb.assets/image-20200523174153179.png)]

4.2 Servlet中的生命週期方法

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被銷燬之前執行,一般用於釋放資源

4.3 Servlet3.0 註解

  • 支持註解配置。可以不需要web.xml了。
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目錄下的資源不能被瀏覽器直接訪問。

4.4 Servlet中常用類

Servlet的體系結構

Servlet -- 接口
	|
GenericServlet -- 抽象類
	|
HttpServlet  -- 抽象類 對http協議的封裝,一般用此類

* GenericServlet:將Servlet接口中其他的方法做了默認空實現,只將service()方法作爲抽象

* HttpServlet:對http協議的一種封裝,簡化操作

4.4.1 Request類

1. request對象和response對象的原理
	1. request和response對象是由服務器創建的。我們來使用它們
	2. request對象是來獲取請求消息,response對象是來設置響應消息

2. request對象繼承體系結構:	
	ServletRequest		--	接口
		|	繼承
	HttpServletRequest	-- 接口
		|	實現
	org.apache.catalina.connector.RequestFacade 類(tomcat實現的)

request功能:獲取請求消息數據

4.4.1.1 獲取請求行數據
* 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()
4.4.1.2 獲取請求頭數據
* 方法:
	* (*)String getHeader(String name):      //通過請求頭的名稱獲取請求頭的值
	* Enumeration<String> getHeaderNames():  //獲取所有的請求頭名稱
	- //上面兩個方法互相配合,可以獲得所有頭信息
4.4.1.3 獲取請求體數據:
* 請求體:只有POST請求方式,纔有請求體,在請求體中封裝了POST請求的請求參數
* 步驟:(請求頭被封裝成流了,因此需要流的方式獲取請求頭內容)
	1. 獲取流對象
		*  BufferedReader getReader()://獲取字符輸入流,只能操作字符數據
		*  ServletInputStream getInputStream()://獲取字節輸入流,可以操作所有類型數據
			* 在文件上傳知識點後講解

	2. 再從流對象中拿數據
      
4.4.1.4 獲取參數和解決中文亂碼
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"); 
4.4.1.5 請求轉發
  • 一種在服務器內部的資源跳轉方式
1. 步驟:
	1. 通過request對象獲取請求轉發器對象:RequestDispatcher getRequestDispatcher(String path)
	2. 使用RequestDispatcher對象來進行轉發:forward(ServletRequest request, ServletResponse response) 
示例:request.getRequestDispatcher("/a").forward(request,response); //寫資源路徑
2. 特點:
	1. 瀏覽器地址欄路徑不發生變化
	2. (*)只能轉發到當前服務器內部資源中。
	3. 轉發是一次請求
4.4.1.6 共享數據
  • 域對象:一個有作用範圍的對象,可以在範圍內共享數據
request域:代表一次請求的範圍,一般用於請求轉發的多個資源中共享數據
方法:
	1. void setAttribute(String name,Object obj):存儲數據
	2. Object getAttitude(String name):通過鍵獲取值
	4. void removeAttribute(String name):通過鍵移除鍵值對

4. 獲取ServletContext:
	* ServletContext getServletContext()

4.4.3 Response 類

  • 響應消息:服務器端發送給客戶端的數據
4.4.3.1 http響應簡介
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. 響應體: 傳輸的數據
4.4.3.2 常用方法
1. 設置響應行
	1. 格式:HTTP/1.1 200 ok
	2. 設置狀態碼方法:setStatus(int sc) 
2. 設置響應頭:setHeader(String name, String value) 
3. 設置響應體:
	* 使用步驟:
		1. 獲取輸出流
			* 字符輸出流:PrintWriter getWriter()
			* 字節輸出流:ServletOutputStream getOutputStream()
		2. 使用輸出流,將數據輸出到客戶端瀏覽器
4.4.3.3 重定向
方式一: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對象來共享數據
4.4.3.4 響應數據和亂碼問題

亂碼問題:

//獲取的流的默認編碼是ISO-8859-1
1. PrintWriter pw = response.getWriter(); 
2. 設置該流的默認編碼
3. 告訴瀏覽器響應體使用的編碼
//簡單的形式,設置編碼,是在獲取流之前設置
//使用下面的方式就不用再設置response.setCharsetEncoding("utf-8"),tomcat會根據ContentType內容自動修改服務端的字符集
response.setContentType("text/html;charset=utf-8");

4.4.4 ServletContext

  • ServletContext代表整個web應用,可以和程序的容器(服務器)來通信
  1. 獲取:
1. 通過request對象獲取
	request.getServletContext();
2. 通過HttpServlet獲取
	this.getServletContext();
  1. 常用方法:
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);

4.4.5 Filter

  • web中的過濾器:當訪問服務器的資源時,過濾器可以將請求攔截下來,完成一些特殊的功能。
  • 過濾器的作用:一般用於完成通用的操作。如:登錄驗證、統一編碼處理、敏感字符過濾…

起步: 註解

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>demo1</filter-name>
	<filter-class>cn.tdte.web.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
	<filter-name>demo1</filter-name>
	<!-- 攔截路徑 -->
	<url-pattern>/*</url-pattern>
</filter-mapping>
4.4.5.1 過濾器執行流程
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回來了...");
}
4.4.5.2 過濾器生命週期方法
init     //在服務器啓動後會創建Filter對象,然後調用init方法。只執行一次。用於加載資源
doFilter //每一次請求被攔截資源時,會執行。執行多次
destroy  //在服務器關閉後,Filter對象被銷燬。如果服務器是正常關閉,則會執行destroy方法。只執行一次。用於釋放資源
4.4.5.3 過濾器路徑配置詳解
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>ASYNC</dispatcher>
				</filter-maping>標籤即可
4.4.5.4 過濾器鏈(配置多個過濾器)
執行順序:如果有兩個過濾器:過濾器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();
    }
}

4.4.6 Listener

  • 概念:web的三大組件之一。
    • 事件監聽機制
      • 事件 :一件事情
      • 事件源 :事件發生的地方
      • 監聽器 :一個對象
      • 註冊監聽:將事件、事件源、監聽器綁定在一起。 當事件源上發生某個事件後,執行監聽器代碼

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>src</param-name>
    <param-value>/WEB-INF/web.xml</param-value>
  </context-param>
</web-app>

4.5 路徑問題

1. 相對路徑:通過相對路徑不可以確定唯一資源
	* 如:./index.html
	* 不以/開頭,以.開頭路徑
	* 使用規則:找到當前資源和目標資源之間的相對位置關係
		* ./:當前目錄
		* ../:後退一級目錄
2. 絕對路徑:通過絕對路徑可以確定唯一資源
	* 如:http://localhost/day15/responseDemo2		/day15/responseDemo2
	* 以/開頭的路徑
	* 使用規則:判斷定義的路徑是給誰用的?判斷請求將來從哪兒發出
		* 給客戶端瀏覽器使用:需要加虛擬目錄(項目的訪問路徑)
			* 建議虛擬目錄動態獲取:request.getContextPath()
			* 使用在:<a> , <form>  重定向...
		* 給服務器使用:不需要加虛擬目錄
			* 轉發路徑

4.6 文件下載

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">圖片1</a>
    <a href="/day15/img/1.avi">視頻</a>
    <hr>
    <a href="/day15/downloadServlet?filename=九尾.jpg">圖片1</a>
    <a href="/day15/downloadServlet?filename=1.avi">視頻</a>
</body>

4.7 會話

  1. 會話:一次會話中包含多次請求和響應。
    • 一次會話:瀏覽器第一次給服務器資源發送請求,會話建立,直到有一方斷開爲止
  2. 功能:在一次會話的範圍內的多次請求間,共享數據
  3. 方式:
    1. 客戶端會話技術:Cookie
    2. 服務器端會話技術:Session

4.7.1 Cookie

  • 客戶端會話技術,將數據保存到客戶端

使用步驟:

1. 創建Cookie對象,綁定數據
	* new Cookie(String name, String value) 
2. 發送Cookie對象
	* response.addCookie(Cookie cookie) 
3. 獲取Cookie,拿
    到數據
	* Cookie[]  request.getCookies()  

詳細介紹

  • 實現原理:基於http協議的響應頭set-cookie和請求頭cookie實現
  1. cookie的細節:
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的特點和作用
1. cookie存儲數據在客戶端瀏覽器 不安全,易修改
2. 瀏覽器對於單個cookie 的大小有限制(4kb) 以及 對同一個域名下的總cookie數量也有限制(20)

* 作用:
	1. cookie一般用於存出少量的不太敏感的數據
	2. 在不登錄的情況下,完成服務器對客戶端的身份識別

4.7.2 Session

  • 服務器端會話技術,在一次會話的多次請求間共享數據,將數據保存在服務器端的對象中。HttpSession

起步:

1. 獲取HttpSession對象:
	HttpSession session = request.getSession();
2. 使用HttpSession對象:
	Object getAttribute(String name)  
	void setAttribute(String name, Object value)
	void removeAttribute(String name)  
  • 原理: Session的實現是依賴於Cookie的。如果沒有Cookie的JSESSIONID,req.getSession()會創建一個新的session,如果JSESSIONID存在,則根據JSESSIONID取相應的Session

詳細介紹

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相對於不安全

5. 驗證碼

手動寫(瞭解)

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.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>4.6.8</version>
</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>

6. MVC設計典範

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. 使得項目架構變得複雜,對開發人員要求高

軟件設計三層架構

  1. 界面層(表示層):用戶看的得界面。用戶可以通過界面上的組件和服務器進行交互
  2. 業務邏輯層:處理業務邏輯的。
  3. 數據訪問層:操作數據存儲文件。

7. JSP (Java Service Page)

  • 原理: JSP本質上就是一個Servlet

7.1 JSP 腳本

JSP定義Java代碼的方式(下面說明的都是jps生成java文件的,就是在xxx_jsp.java文件中)

1. <% 代碼 %>  //在service方法中,service方法中可以定義什麼,該腳本中就可以定義什麼
2. <%! 代碼 %> //在jsp轉換後的java類的成員位置。如:成員變量、代碼塊等,不推薦有現車安全問題
3. <%= 代碼 %> //在service方法中,會輸出到頁面上。 out.print("xxxx")

7.2 JSP 內置對象

  • 在jsp頁面中不需要獲取和創建,可以直接使用的對象
  • jsp一共有9個內置對象。
* 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 異常對象

7.3 JSP指令

  • 用於配置JSP頁面,導入資源文件
  • 格式:<%@ 指令名稱 屬性名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

7.4 EL 表達式

  • 概念:Expression Language 表達式語言
  • 作用:替換和簡化jsp頁面中java代碼的編寫
  • 語法:${表達式}
  • 注意:
    • jsp默認支持el表達式的。如果要忽略el表達式
      1. 設置jsp中page指令中:isELIgnored=“true” 忽略當前jsp頁面中所有的el表達式
      2. \${表達式} :忽略當前這個el表達式

基本使用:

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} 態獲取虛擬目錄

7.5 JSTL(JSP標準標籤庫)

  1. 概念:JavaServer Pages Tag Library JSP標準標籤庫

    • 是由Apache組織提供的開源的免費的jsp標籤 <標籤>
  2. 作用:用於簡化和替換jsp頁面上的java代碼

  3. 使用步驟:

    1. 導入jstl相關jar包
    2. 引入標籤庫:taglib指令: <%@taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
    3. 使用標籤
<dependency>
	<groupId>Javax.servlet</groupId>
	<artifactId>jstl</artifactId>
	<version>1.2</version>
</dependency>
<dependency>
	<groupId>javax.servlet.jsp.jstl</groupId>
	<artifactId>jstl-api</artifactId>
	<version>1.2</version>
</dependency>
  1. 常用的JSTL標籤:
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);%>
    <c:choose>
        <c:when test="${number == 1}">星期一</c:when>
        <c:when test="${number == 2}">星期二</c:when>
        <c:when test="${number == 3}">星期三</c:when>
        <c:when test="${number == 4}">星期四</c:when>
        <c:when test="${number == 5}">星期五</c:when>
        <c:when test="${number == 6}">星期六</c:when>
        <c:when test="${number == 7}">星期天</c:when>
        <c:otherwise>數字輸入有誤</c:otherwise>
    </c:choose>

3. foreach:相當於java代碼的for語句
	3.1普通循環
		屬性:
		begin:開始值
		end:結束值
		var:臨時變量
		step:步長
		varStatus:循環狀態對象
			index:容器中元素的索引,從0開始
			count:循環計次,從1開始
示例:
<c:forEach begin="1" end="10" var="i" step="2" varStatus="s">
  <span>${i}</span><br>
  <h3>${s.index}</h3>
  <h4>${s.count}</h4>
</c:forEach>
<hr>
3.2遍歷容器
	* 屬性:
		items:容器對象
		var:容器中元素的臨時變量
<%
  List<String> list = new ArrayList<>();
  list.add("aaa");
  list.add("bbb");
  list.add("ccc");
  request.setAttribute("list", list);
%>
<c:forEach items="${list}" var="str" varStatus="s">
  ${s.index}  ${s.count}  ${str}<br>
</c:forEach>

8. BeanUtils (封裝Bean工具類)

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.4</version>
</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();
    }

9. Transaction(事務的高性能與併發安全)

  • 使用ThreadLocal保證線程之間的隔離
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.21</version>
</dependency>
<!-- commons-dbutils -->
<dependency>
    <groupId>commons-dbutils</groupId>
    <artifactId>commons-dbutils</artifactId>
    <version>1.7</version>
</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());
        }
    }
}

六、jQuery

概念: 一個JavaScript框架。簡化JS開發

  • jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨 是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝JavaScript常用的功能代碼,提供一種簡便的JavaScript設計模式,優 化HTML文檔操作、事件處理、動畫設計和Ajax交互。

  • JavaScript框架:本質上就是一些js文件,封裝了js的原生代碼而已

1. 起步說明

版本說明

  • 目前jQuery有三個大版本:
    1.x:兼容ie678,使用最爲廣泛的,官方只做BUG維護,
    功能不再新增。因此一般項目來說,使用1.x版本就可以了,
    最終版本:1.12.4 (2016年5月20日)
    2.x:不兼容ie678,很少有人使用,官方只做BUG維護,
    功能不再新增。如果不考慮兼容低版本的瀏覽器可以使用2.x,
    最終版本:2.2.4 (2016年5月20日)
    3.x:不兼容ie678,只支持最新的瀏覽器。除非特殊要求,
    一般不會使用3.x版本的,很多老的jQuery插件不支持這個版本。
    目前該版本是官方主要更新維護的版本。最新版本:3.2.1(2017年3月20日)
  • jquery-xxx.js 與 jquery-xxx.min.js區別:
    1. jquery-xxx.js:開發版本。給程序員看的,有良好的縮進和註釋。體積大一些
    2. jquery-xxx.min.js:生產版本。程序中使用,沒有縮進。體積小一些。程序加載更快

JQuery對象和JS對象區別與轉換

  1. JQuery對象在操作時,更加方便。
  2. JQuery對象和js對象方法不通用的.
  3. 兩者相互轉換
    • jq – > js : jq對象[索引] 或者 jq對象.get(索引)
    • js – > jq : $(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");

2. jQuery 選擇器

  • 篩選具有相似特徵的元素(標籤)

2.1 基本選擇器

1. 標籤選擇器(元素選擇器)
	* 語法: $("html標籤名") 獲得所有匹配標籤名稱的元素
2. id選擇器 
	* 語法: $("#id的屬性值") 獲得與指定id屬性值匹配的元素
3. 類選擇器
	* 語法: $(".class的屬性值") 獲得與指定的class屬性值匹配的元素
4. 並集選擇器:
	* 語法: $("選擇器1,選擇器2....") 獲取多個選擇器選中的所有元素

2.2 層級選擇器

1. 後代選擇器
	* 語法: $("A B ") //所有b孫子
2. 子選擇器
	* 語法: $("A > B") //選擇所有b兒子
1. 基本選擇器

2.3 屬性選擇器

1. 屬性名稱選擇器 
	* 語法: $("A[屬性名]") 包含指定屬性的選擇器
2. 屬性選擇器
	* 語法: $("A[屬性名='值']") 包含指定屬性等於指定值的選擇器 "A[屬性名(^,$,*,!)='值']"
3. 複合屬性選擇器 (&&關係)
	* 語法: $("A[屬性名='值'][]...") 包含多個屬性條件的選擇器

2.4 過濾選擇器

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')

2.5 表單過濾選擇器

1. 可用元素選擇器 
	* 語法: :enabled 獲得可用元素
2. 不可用元素選擇器 
	* 語法: :disabled 獲得不可用元素
3. 選中選擇器 
	* 語法: :checked 獲得單選/複選框選中的元素
4. 選中選擇器 
	* 語法: :selected 獲得下拉框選中的元素
    
// 示例:
// 利用 jQuery 對象的 val() 方法改變表單內可用 <input> 元素的值"  
$('input[type="text"]:enabled').val("aaaa")
// 利用 jQuery 對象的 val() 方法改變表單內不可用 <input> 元素的值"  
$('input[type="text"]:disabled').val("aaaa")
//利用 jQuery 對象的 length 屬性獲取複選框選中的個數"  
alert($('input[type="checkbox"]:checked').length)
// 利用 jQuery 對象的 length 屬性獲取下拉框選中的個數"
alert($('#job >option:selected').length)

3. jQueryDOM操作

3.1 內容操作

1. html(): 獲取/設置元素的標籤體內容   <a><font>內容</font></a>  --> <font>內容</font>
2. text(): 獲取/設置元素的標籤體純文本內容   <a><font>內容</font></a> --> 內容
// 注意,使用text()修改也都會覆蓋所有子標籤內容(標籤+文本)
3. val(): 獲取/設置元素的value屬性值

3.2 屬性操作

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")

3.3 CRUD操作

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())
    })
});

4. jQuery其他操作

4.1 動畫

  • 三種方式顯示和隱藏元素

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]])

4.2 遍歷

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 容器對象)

4.3 事件綁定

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>

5. jQuery插件

  • 增強JQuery的功能
  1. 實現方式:
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));

6. Ajax異步交互

  1. 概念: ASynchronous JavaScript And XML 異步的JavaScript 和 XML

6.1 原生的JS實現方式(瞭解)

//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);
	}
}

6.2 JQeury實現方式

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:響應結果的類型

7. JSON

  1. 概念: JavaScript Object Notation JavaScript對象表示法
Person p = new Person();
p.setName("張三");
p.setAge(23);
p.setGender("男");

var p = {"name":"張三","age":23,"gender":"男"};
  • json現在多用於存儲和交換文本信息的語法
  • 進行數據的傳輸
  • JSON 比 XML 更小、更快,更易解析。

7.1 語法

1. 基本規則
	* 數據在名稱/值對中:json數據是由鍵值對構成的
		* 鍵用引號(單雙都行)引起來,也可以不使用引號
		* 值得取值類型:
			1. 數字(整數或浮點數)
			2. 字符串(在雙引號中)
			3. 邏輯值(truefalse4. 數組(在方括號中)	{"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]);
				}
			}

7.2 JSON與Java對象

<!--json-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.11.0</version>
</dependency>
<!-- jackson-annotations -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.11.0</version>
</dependency>
<!-- jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.0</version>
</dependency>
  • JSON解析器:
    • 常見的解析器:Jsonlib,Gson,fastjson,jackson

7.2.1JSON轉爲Java對象

1. 導入jackson的相關jar包
2. 創建Jackson核心對象 ObjectMapper
3. 調用ObjectMapper的相關方法進行轉換
	1. readValue(json字符串數據,Class)

7.2.2Java對象轉換JSON

  • 注意前端接收:
    • 前端ajax接收時一定要指定dataType爲Json格式
    • 或在服務器端指定mime爲json,ajax會mime類型自動判斷
      • response.setContentType(“application/json;charset=utf-8”);
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"}

七、Redis 內存數據庫

1. 什麼是NOSQL

​ 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
典型應用:社交網絡
數據模型:圖結構
優勢:利用圖結構相關算法。
劣勢:需要對整個圖做計算才能得出結果,不容易做分佈式的集羣方案。

2. 什麼是Redis

​ Redis是用C語言開發的一個開源的高性能鍵值對(key-value)數據庫,官方提供測試數據,50個併發執行100000個請求,讀的速度是110000次/s,寫的速度是81000次/s ,且Redis通過提供多種鍵值數據類型來適應不同場景下的存儲需求,目前爲止Redis支持的鍵值數據類型如下:
​ 1) 字符串類型 string
​ 2) 哈希類型 hash
​ 3) 列表類型 list
​ 4) 集合類型 set
​ 5) 有序集合類型 sortedset

  1. 官網:https://redis.io
  2. 中文網:http://www.redis.net.cn/

3. redis的應用場景

• 緩存(數據查詢、短連接、新聞內容、商品內容等等)
• 聊天室的在線好友列表
• 任務隊列。(秒殺、搶購、12306等等)
• 應用排行榜
• 網站訪問統計
• 數據過期處理(可以精確到毫秒)
• 分佈式集羣架構中的session分離

redis.windows.conf //配置文件
redis-cli.exe //redis的客戶端
redis-server.exe //redis服務器端

5. 常見錯誤

# 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

6. 通用命令

1. keys * : 查詢所有的鍵
2. type key : 獲取鍵對應的value的類型
3. del key:刪除指定的key value

其他詳細情況Redis文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章