1. 程式人生 > >《Servlet與JSP核心程式設計》讀書筆記

《Servlet與JSP核心程式設計》讀書筆記

雖然Servlet和JSP學習也使用了挺長時間了,但是最近讀了下《Servlet和JSP核心程式設計》這本書,雖然是熟悉的知識,但是仍然有些因為過長時間沒使用而忘記了,記下這篇讀書筆記,就當是對Servlet和JSP涉及的核心知識點進行一個整理與回顧吧。書中對Servlet與JSP進行了完整的介紹,總體上還是非常基礎的,如果是初學者,或者有了一定開發經驗的開發人員,都能從書中得到收穫。

下面的條目是我在閱讀過程中記下的筆記,調理也許不是那麼清晰,但是對於自己在需要的時候複習還是很有幫助的。

1、應該儘可能覆蓋doGet()和doPost()方法,不要為了省事直接覆蓋service()方法。

原因由兩個:一是喪失想要覆蓋其他doXXX()方法的可能性,不排除以後需要覆蓋這些方法的可能性;二是無法實現getLastModified方法,該欄位可以得到請求最後修改的時間,如果請求的資源沒有發生修改,那麼服務端將返回304狀態碼,表示請求的資源已經是最新的,上次請求的資源可以繼續使用。

getLastModified擴充套件:如果方法返回的是整數,並且客戶端請求頭沒有包含If-Modified-Since欄位或者已經包含If-Modified-Since欄位,但是返回值比If-Modified-Since指定的時間更新的話,會呼叫doGet方法請求最新的資源,並返回包含Last-Modified頭欄位的響應資訊。如果返回值比If-Modified-Since欄位指定的時間小的話(發生在之前),那麼服務端可以做出判斷上次響應給客戶端的資源仍然可用,於是返回304狀態碼,告訴客戶端你上次請求的這個資源可以繼續使用。

2、不要為了阻止併發訪問Servlet例項而去實現SingleThreadModel介面,原因有二:

1) 由於實現SingleThreadModel介面就相當於對Servlet例項進行了同步,表面上不用擔心因為多執行緒併發訪問的問題造成資料的安全性和一致性,但是如果servlet被頻繁地訪問,那麼同步對效能造成的影響是巨大的。比如在servlet等待IO任務的時候,servlet不能處理其他的請求

2) servlet規範允許伺服器使用多個例項處理請求,來替代對單個例項的請求進行排隊的方案。當然我們並不希望使用多個例項,因為多個servlet例項都擁有變數的單獨副本,從而造成資料不能正確共享,在servlet之間傳遞訊息也有困難。

注:SingleThreadModel在servlet規範2.4中明確反對使用這種方式。為了實現同步,使用synchronized往往是更好的選擇。

3、如果需要讀取請求引數,為了防止跨站指令碼攻擊(XSS),必須過濾出特殊的HTML字元。這種過濾方式的問題可能導致輸出部分缺失。比如將’<’替換成’<’,’>’替換成’>’,’”’替換成’"’,’&’替換成’&’。

4、使用Servlet構建Excel電子表格

設定響應頭:

response.setContentType("application/vnd.ms-excel");
        PrintWriter out = response.getWriter();

例子:

public class App1 extends HttpServlet{
            public void doGet(HttpServletRequest req,HttpServletResponse res){
                response.setContentType("application/vnd.ms-excel");
                PrintWriter out = response.getWriter();
                out.println(\tQ1\tQ2\tQ3\tQ4\tTotal);
                out.println("Apples\t78\t87\t92\t29\t=SUM(B2:E2)");
                out.println("Oranges\t78\t87\t92\t29\t=SUM(B3:E3)");
            }

5、使用Servlet生成JPEG影象

第一步:建立一個BufferedImage

int width = 100px;
        int height = 100px;
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

第二步:在BufferedImage繪製圖像

Graphics2D g = (Graphics2D)image.getGraphics();
        g.setXXX();
        g.fill();
        g.draw();

第三步:設定Content-Type響應頭

response.setContentType("image/jpeg");

第四步:獲取輸出流

OutputStream out = response.getOutputStream();

第五步:以JPEG格式將影象傳送到輸出流

ImageIO.write(image,"jpg",out);

6、使用Cookie記錄偏好
form.jsp

        <form action="/register" method="post">
            firstName:<input name="firstName"/><br>
            lastName:<input name="lastName"/><br>
            <input type="submit"/>
        </form>

RegisterServlet.java

        @WebServlet("/register");
        public class RegisterServlet extends HttpServlet{
            public void doGet(...){
                response.setContentType("text/html");
                String firstName = request.getParameter("firstName");
                String lastName = request.getParameter("lastName");
                Cookie c1 = new Cookie("firstName",firstName);
                response.addCookie(c1);
                Cookie c2 = new Cookie("lastName".lastName);
                response.addCookie(c2);
            }
        }

7、對發往客戶端的URL進行編碼

如果使用URL重寫進行會話跟蹤,大部分頁面或者全部頁面都必須動態生成,站點的任何靜態HTML文件都不能指向站點的動態頁面的連結

情況一:在servlet生成的Web頁面中含有嵌入的URL,應該呼叫response的encodeURL,確定當前是否在使用URL重寫,僅在必須時附加回話資訊;否則不做任何修改直接返回傳入的URL。

情況二:在sendRedirect呼叫中,應該呼叫encodeRedirectURL
如果最終可能使用URL重寫替代Cookie,那麼使用URL編碼是最好的選擇

8、JSP的好處
1) 易於編寫HTML並維護
2) 可以使用標準的開發工具開發
3) 開發人員可以集中精力在表示上
4) JSP擅長生成結構化的HTML頁面,Servlet擅長業務的處理,可以生成二進位制的資料

9、JSP指令碼、表示式編譯成的Servlet
Foo.jsp

<h2>foo</h2>
        <!-- JSP表示式,呼叫後會顯示bar方法執行返回的結果,結尾不需要分號 -->
        <%= bar() %>
        <!-- JSP scriplet,直接呼叫bar(),結尾需要分號 -->
        <% bar(); %>

Foo_jsp.java,之後被編譯成Foo_jsp.class
public void _jspInit(){ ..} – 當JSP網頁一開始執行時,最先執行此方法,執行初始化工作

public void _jspDestory(){...} – JSP網頁最後執行的方法

        public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {
            HttpSession session = request.getSession();
            JspWriter out = response.getWriter();
            out.println(<h2>Foo</h2>);
            out.println(bar());
            bar();
        }

10、對於JSP的初始化和清理工作,可以使用JSP宣告覆蓋jspInit()和jspDestroy()方法

    JSP宣告格式
    <%! 變數或者方法 %>
    現考慮如下JSP宣告:
    <%! private int accessCount = 0;%>
    <%= ++accessCount%>

不同的客戶端得到的技術不是唯一的,也就是由於多個請求共享accessCount變數,該程式碼不是執行緒安全的。但是在伺服器重新啟動之前,所有使用者看到的都是同樣的結果

11、session屬性

使用形式:<%@ page session = “true” %><%– default –%>

session屬性屬於jsp的page指令。可以控制是否參與會話,
true表示如果存在會話,則繫結到現有的會話中,如果沒有則建立一個新的session會話(session的型別是HttpSession);

值為false,表示不會自動建立會話,在將jsp轉為servlet時,對變數session的訪問會導致出錯。但是false也不是無之地,對於高流量的網站,使用false可以節省大量的伺服器記憶體。但是使用false並不表示會禁用會話跟蹤,而且會話只是針對使用者,並不針對頁面,所以關閉頁面的會話跟蹤沒有任何益處

12、isELIgnored屬性

預設為false,表示對JSP表示式進行正常的求值,為true則忽略表示式語言。也就是在JSP頁面${expression}得到的就是表示式。

在JSP1.2之前(包括JSP1.2)該屬性的值都是true,只有在Servlet2.4之後(JSP2.0)該值的預設屬性為false。所以如果在訪問JSP的時候出現直接輸出JSP表示式的情況,需要檢查一下你的Servlet版本是否在2.4之前,如果不想更換版本,只需要在JSP頁面只能中直接新增該屬性為false即可

13、jsp:include動作與include指令

前者會對被包含的JSP的頁面在請求時進行處理,後者在頁面轉換期間就被處理。而且前者會生產兩個Servlet檔案,後者只會產生一個。

在維護和能力兩方面造成jsp:include動作優於include指令。

由於jsp:include動作會會產生兩個Servlet而後者則有兩個,那麼如果通過include指令被包含的頁面發生了修改,那麼所有包含該頁面的jsp檔案都需要重新轉換成新的Servlet,不然下次請求訪問的仍然是修改之前的Servlet。

對於檔案包含應該儘可能用jsp:include動作,僅在所包含的檔案中定義了主頁面需要用到的欄位或者方法,或者在所包含的檔案中設定了主頁面的響應頭的時候,才應該使用include指令。

然而,不能因為在所包含的頁面定義了主頁面的需要的欄位或者方法就認為必須應該使用include指令。對此合理的解釋是,如果使用jsp:include動作,那麼針對類似訪問計數功能的頁面來說,所有使用該頁面的主jsp頁面都將顯示相同的計數。核心就是產生了兩個Servlet,而這兩個Servlet之間是無法共享計數值的。

14、基於請求的共享

public class NumberBean{
        private int num;
        ...
    }
    public class NumberServlet extends HttpServlet{
        ... doGet(...){
            NumberBean number = new NumberBean(new Random().nextInt(Integer.MAX_VALUE));
            request.setAttribute("number",number);
            String addr = "/WEB-INF/view/number.jsp";
            request.getRequestDispatcher(addr).forward(request,response);
            }
    }
    number.jsp
    ...
    <jsp:useBean id = "number" type="servlet.NumberServlet" scope="request"/>
    Your number is: 
    <jsp:getProperty name="number" property="num">

以上這種組合方式只能訪問簡單型別的屬性,對於包裝的POJO的屬性則需要複雜的語法才能實現,在現在主流的MVC框架中(包括Struts2和Spring Web MVC)都對這點進行了封裝,讓使用者可以像訪問簡單POJO的屬性一樣訪問包裝型別的POJO的屬性。

15、EL
&#36;{bash}
輸出
${bash}

\${1+1} is ${1+1}
輸出
${1+1} is 2

${name}

作用域訪問次序:PageContext–>HttpServletRequest–>HttpSession–>ServletContext

等同於呼叫JSP表示式:<%= pageContext.findAttribute(“name”)%>
等同於:

<jsp:useBean id="name" type="somePackage.someClass" scope="...">
        <%= name%>

返回某個作用域變數的某個屬性

customer.fistName{customer[“fistName”]}(這種方式很少使用,不推薦使用)

等同於

<%@ page import="bean.Customer"%>
        <% Customer customer = (Customer)pageContext.findAttribute("customer"); %>
        <%= customer.getFistName() %>

等同於

<jsp:useBean id="customer" type="bean.Customer" scope="request,session, or application" />
        <jsp:getProperty name="customer" property="fistName" />

但是對於類似${customer.address.zipCode},使用和則不能完成相同的獲取屬性的工作

訪問集合
${attributeName[entryName]}

對於JSP2.0,Servlet2.4以上(包含)的版本,還規定了以下的隱式物件:

pageContext:一次擁有request、response、session、out和servletContext屬性。獲取會話ID可以用${pageContext.session.id}
paramparamValues:允許訪問基本的引數值和請求引數值陣列
headerheaderValues:訪問HTTP請求報頭的主要值和全部值
cookie:
initParam:
pageScoperequestScopesessionScopeapplicationScope

算數運算子:+,-,*,/(div)
關係運算符:==和eq(比較兩個引數是否相等)、!=和ne(比較兩個引數是否不等)、<和lt、>和gt、<=和le、>=和ge
邏輯運算子:&&、and、or、||、!、not
空運算子:empty

16、JDBC

使用JDBC連線資料庫:
1) 載入JDBC連線資料庫的驅動檔案
Class.forName(“com.mysql.jdbc.Driver”);

2) 定義要開啟的連線
String url = “jdbc:mysql://localhost:3306/test”;

3) 建立連線
String username = “root”;
String password = 1234;
Connection connection = DriverManager.getConnection(url,username,password);
4) 建立Statement物件
Statement statement = connection.createStatement();
5) 執行查詢
String sql = “select * from user where user_id = 3”;
ResultSet rs = statement.executeQuery(sql);
6) 結果處理
ResultSet的第一行的索引是1
while(rs.next()){
rs.getString(COLUMN_NAME);
}
7) 關閉連線
connection.close();

呼叫資料庫的儲存過程:
1) 定義對資料庫儲存過程的呼叫
? = call procedure_name(?,?..?);

2) 準備CallableStatement
String procedure = {? = call procedure_name(?..?)}
CallableStatement statement = connection.prepareCall(procedure);

3) 註冊輸出引數的型別
statement.registerOutParameters(n,type);
n是輸出引數的索引(第一個的索引是1),type是java.sql.Types定義的常量

4) 提供輸入值
statement.setInt(2,12);
statement.setString(3,”name”);
將第一個輸入引數設為12,將第二個輸入引數設為name,輸入引數的索引從第一個輸出引數開始計起

5) 執行儲存過程
statement.execute();

6) 訪問返回的輸出引數
int res = statement.getInt(1);

這裡返回的是第一個輸出引數,如果是第二個引數則將引數1變為2,其他以此類推

事務管理模板:

        Connection connection = DriverManager.getConnection(url.username,password);
        boolean autoCommit = connection.getAutoCommit();
        try{
            connection.setAutoCommit(fasle);
            Statement st = connection.createStatement();
            //執行事務單元
            ...
            st.close();
        }catch(SQLException e){
            connection.rollBack();
            throw new Throwable(e.getCause());
        }finally{
            connection.commit();
            connection.setAutoCommit(autoCommit);
        }

mysql使用者授權

grant all privileges on database_name.* to [email protected]"%" identified by 'PASSWORD'

相關推薦

ServletJSP核心程式設計 讀書筆記

                        雖然Servle

ServletJSP核心程式設計讀書筆記

雖然Servlet和JSP學習也使用了挺長時間了,但是最近讀了下《Servlet和JSP核心程式設計》這本書,雖然是熟悉的知識,但是仍然有些因為過長時間沒使用而忘記了,記下這篇讀書筆記,就當是對Servlet和JSP涉及的核心知識點進行一個整理與回顧吧。書中對S

ServletJSP核心編程》讀書筆記

技術問題 內容 是我 一段 讀書筆記 易用性 讀書 理解 相關 這本書實際是我進入JavaWeb開發的入門書籍,而且是日常碰到一些技術問題需要確認時的參考書,前一段時間在解決一個他人的問題時,我突然發現我的第一遍閱讀對這本書的內容的理解還不夠透徹,所以又開始N多

linux核心程式設計讀書筆記【第三章程序管理】

第三章程序管理 應專業選修Linux程式設計老師的要求,記錄讀書筆記 3.1程序 1)程序:處於執行期的程式(目標碼存放在某種介質上),包含程式碼段還包含其他資源(開啟的檔案、核心內部資料、存放全域性變數的資料段),是正在執行的程式程式碼的實時結果,Linux通

Python核心程式設計讀書筆記

本次筆記針對原書第6章節 列表 列表型別 內建函式: list.append(obj) 新增一個物件 list.count(obj) 返回一個物件在列表中出現的次數 list.extend(seq) 把序列seq的內容新增到;列表中 list.index(obj,i=0

python核心程式設計---讀書筆記:第16章 網路程式設計

第16章網路程式設計 套接字:用於程序間通訊,或IPC 種類:基於檔案的和基於網路的 地址家族:AF,AddressFamily 兩個程序都執行在同一臺機器,且套接字是基於檔案的 基於網路的套接字:AF_INET,Internet,最廣泛使用 AF_INET6 套接字

《大型網站技術架構:核心原理案例分析》-- 讀書筆記 (5) :網購秒殺系統

案例 並發 刷新 隨機 url 對策 -- 技術 動態生成 1. 秒殺活動的技術挑戰及應對策略 1.1 對現有網站業務造成沖擊 秒殺活動具有時間短,並發訪問量大的特點,必然會對現有業務造成沖擊。對策:秒殺系統獨立部署 1.2 高並發下的應用、

《進化:運維技術變革實踐探索》讀書筆記1 —— 以應用為核心

應用 運維 規範 服務 第一章介紹的是運維的本質,開頭以Netflix 公司(業界微服務架構的最佳實踐者)為例,介紹了在其內部"運維工程師"的角色。在Netflix 內部沒有運維工程師這一角色,取而代之的是SRE(site Reliability Engineer)

Linux命令.編輯器shell程式設計讀書筆記-7

1,檢視檔案系統可以使用parted命令 可以後面直接跟著掛載磁碟路徑,也可以進入命令列之後使用select選擇對應路徑, print all可以顯示所有資訊。   2,fdisk -l可以檢視所有磁碟裝置及其分割槽列表 紅色的就代表磁碟有分割槽,名字依次是s

《大型網站技術架構之核心原理案例分析》讀書筆記

      架構!對於工作經驗尚淺的我是理應遠遠不用考慮的倆字。不過就像這本書所說到的一個好的網站架構體系,不僅僅是架構師個人的架構,而是和參與共同建設的人共同貢獻,讓參與的人覺得自己是架構體系的建設者之一,就越是自動承擔開發過程的責任和共同維護架構和改善軟體。  

《Spark核心原始碼分析開發實戰》讀書筆記之一

第1章 Spark系統概述 1.1 Spark是什麼 1. Spark比Hadoop快在哪裡 (1)Spark使用記憶體計算,而Hadoop使用IO (2)Hadoop的計算是按部就班一步一步進行的,而Spark則是提前生成了DAG,優化了運算路徑   1.2 Sp

《大型網站技術架構:核心原理案例分析》讀書筆記 - 第2篇 架構

第2篇 架構 4 瞬時響應:網站的高效能架構 34 4.1 網站效能測試 35 效能測試是效能優化的前提和基礎,也是效能優化結果的檢查和度量標準。 4.1.1 不同視角下的網站效能 35 使用者:直觀感受到的快慢 開發:應用程式本身 運維:基礎設施效能和資源利用率 4.1.2 效

《深入Linux核心架構底層原理》讀書筆記一——核心架構核心資料結構知識

1、核心架構常見架構正規化:Linux核心上下層通訊方式橫向系統和縱向系統橫向系統如cgroup,proc,sys檔案系統,系統呼叫的組織,除錯系統,Core Dump,訊號,記憶體管理等;縱向系統是指具體的功能模組,如USB功能,一個對USB檔案的操作要走完核心中的很多個層

《大型網站技術架構:核心原理案例分析》讀書筆記

第六章伸縮性,網站的演化分離過程可以分為三類, 第一類大的系統級別的分離,例如資料庫系統,快取系統,檔案管理系統(靜態資源),演化過程為:為單一伺服器->資料庫分離->快取分離->靜態資源分離。 第二類業務流程的抽象分離,從下到上的模組為:資料庫->基礎技術服務->可複用業務

PHPMySQL程式設計讀書筆記(一)

一、PHP基本型別及函式 1. 短標籤 sprintf??? 2. 型別自動裝換 3. 與型別相關的函式 gettype(),settype(),判斷是否為某個型別:is_name() 變數賦

《大型網站技術架構核心原理案例分析》讀書筆記之RAID技術

        RAID(廉價磁碟冗餘陣列)技術主要是為了改善磁碟的訪問延遲,增強磁碟的可用性和容錯能力。目前伺服器級別的計算機都支援插入多塊磁碟(8塊或者更多),通過使用RAID技術,實現資料在多塊磁碟上的併發讀寫和資料備份。        假設伺服器有N塊磁碟。     

《深入理解Spark-核心思想原始碼分析》讀書筆記(1)

前兩章 第一章主要是講如何安裝和配置spark,以及如何匯入spark原始碼除錯執行;第二章主要講的是上次那本書《Spark快速大資料分析》的內容,科普一下spark的知識。 第三章 SparkContext的初始化 1. 概述 這章的主要內容就

《大數據日知錄:架構算法》讀書筆記(多圖)

打通 導論 ges wid 技術分享 二次 思維 知識點 很好 第二次讀這本書,這次是精讀,畫了思維導圖。書很好,完整的知識結構和由淺入深的介紹,非常全面以至於知識點都梳理了三天。 作為導論式的總覽,對大數據領域有了個總體的認識,接下來可以更針對性地加強和實踐。 總體上

圖解 servlet jsp的關系

網絡傳輸 context 並發 線程 tom 初始 blank string ons Servlet是Java提供的用於開發Web服務器應用程序的一個組件,運行在服務器端,由Servlet容器所管理,用於生成動態的內容。Servlet是平臺獨立的Java類,編寫一個Se

《深入理解Java虛擬機:JVM高級屬性最佳實踐》讀書筆記(更新中)

pen 內存區域 深度 span 進化 ria 最短 描述 core 第一章:走進Java 概述 Java技術體系 Java發展史 Java虛擬機發展史 1996年 JDK1.0,出現Sun Classic VM HotSpot VM, 它是 Sun JDK 和 Open