Servlet 學習筆記
一、動態網頁技術發展
- 靜態網頁技術
- HTML: 無法進行用戶交互
- 動態網頁技術
- CGI: 效率低
- ASP: html+javascript+com
- PHP:php+mysql+linux+apache(流行結構)
- JSP:html + java片段 + jsp + js
二、B/S結構與C/S結構比較
- C/S結構:服務器和客戶端都需要開發,例如QQ,服務器和客戶端都需要騰訊開發和升級。
- B/S結構:客戶端是現成的,例如客戶端為瀏覽器,只需要開發服務器,客戶端為瀏覽器,不用開發。
三、Servlet技術(B/S)
3.1 什么是Servlet
- Applet: java客戶端小程序
- Servlet:java服務器小程序
3.2 servlet運行環境
瀏覽器
Web服務器(Tomcat,jBoss)
-
數據庫
圖片3.png
3.3 Tomcat
- 免費的開源的servlet容器
- 位于服務器端
- 功能
- web服務器:即可以接收瀏覽器的http請求,轉發給servlet處理并返回頁面
- jsp和servlet的容器:存放jsp和servlet
- 修改默認端口
- /conf/server.xml
- 修改虛擬目錄
- /conf/server.xml
- 在</Host>之前,加入
<Context path = "/MyWebSite" docBase="D:\MyWebSite" debug = "0">
- 修改管理員密碼
- /conf/tomcat-users.xml
- 防止非法用戶遠程登錄到tomcat并發布有害站點(例如關閉服務器)
3.4 Servlet開發方法
-
開發流程
- 在%TOMCAT_HOME%/webapps下WEB-INF的文件夾,寫一個文件web.xml(該網站的配置信息),建立一個classes的子文件夾,也可以從別的目錄ROOT下拷貝
- 開發servlet(見以下三種方法)
- 部署servlet(修改web.xml文件配置)
<servlet> <servlet-name>hello</servlet-name> <!—給servlet取名,可以隨意取名--> <servlet-class>com.test.Hello</servlet-class> <!—指明servlet的路徑,就是servlet的包+類名--> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <!—給servlet取名,與上面的名字相同--> <url-pattern>/hello<url-pattern> <!—瀏覽器中輸入的url,可以隨意取名--> </servlet-mapping>
- 啟動Tomcat,訪問你的servlet,在瀏覽器的地址欄中輸入:http://127.0.0.1:8080/myWebSite/hello 回車就可以看到servlet的輸出
-
三種開發方法
- 實現servlet接口
- 需要實現init service destroy方法
- 配置web.xml文件
- 繼承GenericServlet
- 需要實現service方法,相對簡單
- 配置web.xml文件
- 繼承HttpServlet(目前用的最多的方法)
- 需要重寫doGet,doPost方法
- 表單提交數據get和post請求的區別
- 從安全性看get < post。get提交的數據會在瀏覽器的地址欄顯示
- 從提交的內容大小看get<post。get提交的數據不能大于2K,而post提交的數據理論上不受限制,但是實際編程中建議不要大于64K
- 從請求響應速度看get>post。get請求服務器立即處理請求,而post請求可能形成一個隊列請求
3.5 Servlet生命周期
- servlet部署在容器里(我們使用的是Tomcat,也可是別的,比如jboss,weblogic...),它的生命周期由容器來管理。
- servlet的生命周期分為以下幾個階段:
- 裝載servlet,由相應的容器來完成
- 創建一個servlet實例
- 調用servlet的init()方法,該方法只會在第一次訪問servlet時被調用一次
- 服務:調用servlet的service()方法,一般業務邏輯在這里處理,該方法在訪問該servlet時,會被調用
- 銷毀:調用servlet的destroy()方法,銷毀該servlet實例,該方法在以下情況被調用:
a. tomcat重新啟動
b. reload該webapps
c. 重新啟動電腦
3.6 Servlet共享數據方法
3.6.1 同一用戶的不同頁面共享數據
即同一個賬號的用戶,如何在不同的http頁面之間(即不同的servlet之間)共享信息
-
cookie技術(客戶端)
- 什么是cookie
-
Name Value String String Name Value String String
-
- cookie可以用來做什么
- 保存用戶名、密碼,在一定時間不用重新登錄
- 記錄用戶訪問 網站的喜好,比如有無背景音樂、網頁的背景色是什么
- 網站的個性化,比如定制網站的服務、內容
- cookie使用
- cookie有點像一張表,分兩列,一個是名字,一個是值,數據類型都是String
- 如何創建一個cookie(在服務器端創建的)
Cookie c=new Cookie(String name, String val);
- 如何將一個cookie添加到客戶端
response.addCookie(c);
- 如何讀取cookie(從客戶端讀到服務器)
request.getCookie();
- cookie其他說明
- 可以通過IE—工具—internet選項—隱私—高級來啟用或是禁用cookie
- 由于cookie的信息是保存在客戶端的,因此安全性不高
- cookie信息的生命周期可以在創建時設置(比如30s),從創建那一時刻起,就開始計時,到時該cookie的信息就無效了
- 什么是cookie
-
sendRedirect()跳轉
sendRedirect("welcome?name="+user+"&pass="+psw);
- 其中welcome是sevlet的url,?后面是兩個傳遞的變量name和pass,第二個變量需要加AND符號&
- 傳送較快,但只能傳字符串,不能傳類
- 傳送的變量會在瀏覽器url中顯示,密碼等敏感信息不能傳送
-
隱藏表單提交
- hidden 不會顯示在頁面上,但是后臺servlet可以獲取該值
<form action=login> <input type=hidden name=a value=b> </form>
- hidden 不會顯示在頁面上,但是后臺servlet可以獲取該值
-
session技術(服務器端)
-
什么是session
- 當用戶打開瀏覽器,訪問某個網站時,服務器就會在服務器的內存為該瀏覽器分配一個空間,該空間被這個瀏覽器獨占。這個空間就是session空間,該空間中的數據默認存在時間為30min,你也可以修改該值。一個瀏覽器實例擁有一個session。
-
如何理解session
-
可以把session看做一張表,這張表有兩列,而表有多少行理論上沒有限制,每一行就是session的一個屬性。每個屬性包含有兩個部分,一個是該屬性的名字String,另外一個是它的值Object。
Name Value String Object
-
-
如何使用session
- 得到session
HttpSession hs=request.getSession(true);
- 向session添加屬性
hs.setAttribute(String name,Object val);
- 從session得到某個屬性
String name=hs.getAttribute(String name);
- 從session中刪除掉某個屬性
hs.removeAttribute(String name);
- 注銷session中的內容(比較安全的一種方式)
ht.setMaxInactiveInterval(0);
- 得到session
-
session注意事項
- session中屬性存在的默認時間是30min,你也可修改它存在的時間:
(a)修改web.xml 全局修改改Tomcat/conf文件夾下面的web.xml,僅改某一個webapp的默認時間,則修改webapp下面的web.xml(b)在程序中修改 - 上面說的這個30min指的是用戶的發呆時間,而不是累計時間
- 當某個瀏覽器訪問網站時,服務器會給瀏覽器分配一個唯一的session id,并以此來區分不同的瀏覽器(即客戶端)
- 因為session的各個屬性要占用服務器的內存,因此軟件公司都是在迫不得已的情況下才使用
- session中屬性存在的默認時間是30min,你也可修改它存在的時間:
-
session應用實例
- 網上商城中的購物車
- 保存登陸用戶的信息
- 將某些數據放入到session中,供同一用戶的各個方面使用
- 防止用戶非法登陸到某個頁面
-
-
cookie和session比較
- 存在的位置
- cookie保存在客戶端,session保存在服務器端
- 安全性
- cookie的安全性比session要弱
- 網絡傳輸量
- cookie通過網絡在客戶端與服務器端傳輸,而session保存在服務器端,不需要傳輸
- 生命周期
- cookie的過期時間是從創建開始計算的,session的過期時間是從最近一次使用時間開始計算的;
- 關機會導致session生命周期結束,而對cookie沒有影響;
- sessionCookie與persistentCookie
- sessionCookie
- session是以cookie或URL重寫為基礎的,默認使用cookie來實現,系統會創造一個名為JSESSIONID的輸出cookie,稱為sessionCookie
- 存儲于瀏覽器內存中的,并不是寫到硬盤上的,這也就是我們剛才看到的JSESSIONID,我們通常情是看不到JSESSIONID的,但是當我們把瀏覽器的cookie禁止后,web服務器會采用URL重寫的方式傳遞Sessionid,我們就可以在地址欄看到sessionid=KWJHUG6JJM65HS2K6之類的字符串
- persistentCookie
- 通常所說的cookie,存儲在硬盤上
- sessionCookie
- 內在聯系
- 大部分session機制都使用會話cookie來保存session id,而關閉瀏覽器后這個session id就消失了,再次連接服務器時也就無法找到原來的session。如果服務器設置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發出的HTTP請求頭,把原來的session id發送給服務器,則再次打開瀏覽器仍然能夠找到原來的session
- 存在的位置
3.6.2 不同用戶之間共享數據
-
ServletContext
-
ServletContext、cookie與session區別
圖片4.png -
ServletContext使用方法
- 得到ServletContext實例
this.getServletContext();
- 添加屬性setAttribute(String name, Object ob);
- 得到值getAttribute(String name); 返回Object
-
Name Value String Object Name Value String Object
- 得到ServletContext實例
-
ServletContext生命周期
- ServletContext中的生命周期從創建開始,到服務器關閉而結束。
-
ServletContext注意事項
- ServletContext長時間占用服務器內存,建議不要向ServletContext中添加過大的數據,切忌。
- 總之如果是涉及到不同用戶共享數據,而這些數據量不大,同時又不希望寫入數據庫中,我們就可以考慮使用ServletContext來實現。
-
ServletContext應用實例
- 網站計數器
- 網站在線用戶顯示
- 簡單的聊天系統
-
3.7 servlet數據庫操作
-
采用JDBC連接數據庫
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb","test","020048");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select password from userinfo where username='"+ uname+"'");
- 注意在finally語句中逆序關閉
-
采用連接池方式連接數據庫
- 配置連接池
在 /conf/server.xml中添加代碼 or 在Tomcat中直接配置
-
類似線程池,給數據庫連接預先分配連接池,以提高性能。原先每次連接數據庫都需要加載驅動得到一根連接,分配連接池后,如果連接池中有空閑的連接,就直接將其分配給請求客戶端;如果沒有空閑連接,則請求客戶端在隊列池中等待空閑連接;
圖片1.png
- 使用連接池
- 引入
javax.sql
,javax.naming
包 Context ctt=new javax.naming.InitialContext();
DataSource ds=(DataSource)ctt.lookup(“java:comp/env/數據源名”);
conn=ds.getConnection();
- 引入
- 配置連接池
-
sql注入漏洞
select * from users where username='abc'and password = '123' or 1='1'
- 當用戶輸入的密碼為"123' or 1='1'"時,數據庫所有數據泄露
-
分頁技術詳解
- 需要定義四個變量:
- int pageSize:每頁顯示多少條記錄
- int pageNow:希望顯示第幾頁
- int pageCount:一共有多少頁
- int rowCount:一共有多少條記錄
- 數據庫操作
select top pageSize 字段名列表 from 表名 where id not in(select top pageSize*(pageNow-1) id from 表名)
- 需要定義四個變量:
-
注意事項
- 需要將連接數據庫的jar包,拷貝到tomcat服務器。具體有兩種方法:
- 將jar包拷貝到tomcat目錄下的lib文件夾里
- 在webapps目錄的WEB-INF文件下建立一個lib文件夾,然后將jar包拷貝到該文件夾下
- 兩種方法的區別:
- 所有webapps都可以使用jar【公用lib庫】
- 只有放入jar的那個webapps能使用jar【私用lib庫】
- 需要將連接數據庫的jar包,拷貝到tomcat服務器。具體有兩種方法:
3.8 網站框架改進
- Model1模式(界面和業務邏輯混合)
代碼冗余
框架層次模糊
-
代碼可讀性、可維護性差(界面改動會影響業務邏輯)
圖片2.png
- MV模式(M:Model,V:view)
-
進行分層,將界面層和業務邏輯層分離
圖片1.png
-
- MVC模式(M:Model,V:view,C:controller)