1. 程式人生 > >JSP 內置對象(上)

JSP 內置對象(上)

技術分享 resp ecp form表單提交 ica 就是 重新 協議 報錯

JSP 內置對象是 Web 容器創建的一組對象,不使用 new 關鍵字就可以直接使用的對象。如上一章中使用腳本實現打印九九乘法表中的out對象

<%-- 腳本:out對象是JSPWriter類的實例,用於向客戶端輸出內容 --%>
<%
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <=i; j++) {
            out.print(i + "*" + j + "=" + (i*j) + "&nbsp;&nbsp;");
        }
        out.println(
"</br>"); } %>

JSP 共有九大內置對象

常用(5個): out, request, response, session, application

不常用(4個): page, pageContext, execption, config

技術分享圖片

緩沖區(Buffer)

所謂緩沖區就是內存的一塊區域用來保存臨時數據。下圖中,可以把一粒一粒米飯想象成字節,把盛米飯的容器想象成緩沖區

技術分享圖片

out 對象

out 對象是 JspWriter 類的實例,是向客戶端輸出內容

常用方法如下:

1、void println() 向客戶端打印字符串

2、void clear() 清除緩沖區的內容,如果在 flush 之後調用會拋出異常

3、void clearBuffer() 清除緩沖區的內容,如果在 flush 之後調用不會拋出異常

4、void flush() 將緩沖區內容輸出到客戶端

5、int getBufferSize() 返回緩沖區以字節數的大小,如不設緩沖區則為0

6、int getRemaining() 返回緩沖區還剩余多少可用

7、boolean isAutoFlush() 返回緩沖區滿時,是自動清空還是拋出異常

8、void close() 關閉輸出流

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding
="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> <% out.println("<h2>靜夜思<h2>"); out.println("床前明月光<br>"); out.println("疑是地上霜<br>"); out.println("舉頭望明月<br>"); out.println("低頭思故鄉<br>"); %> <hr> 獲取緩沖區大小:<%=out.getBufferSize() %> size; <br> 獲取緩沖區可用大小:<%=out.getRemaining() %> size; <br> 是否自動清空緩沖區:<%=out.isAutoFlush() %> </body> </html>

頁面輸出結果:

技術分享圖片

下面在靜夜思中間加入flush,雖然頁面輸出不受影響,但是可用剩余緩沖區變大。然後分別試圖在其後運行 out.clear() 和 out.clearBuffer()

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
    out.println("<h2>靜夜思<h2>");
    out.println("床前明月光<br>");
    out.println("疑是地上霜<br>");
    out.flush();
    // out.clear(); // Error: Attempt to clear a buffer that‘s already been flushed
    // out.clearBuffer();
    out.println("舉頭望明月<br>");
    out.println("低頭思故鄉<br>");
%>
<hr>
獲取緩沖區大小:<%=out.getBufferSize() %> size; <br>
獲取緩沖區可用大小:<%=out.getRemaining() %> size; <br>
是否自動清空緩沖區:<%=out.isAutoFlush() %>
</body>
</html>

技術分享圖片

request 對象

客戶端的請求信息被封裝在request對象中,通過它才能了解到客戶的需求,然後做出響應。request是HttpServerletRequest類的實例。

request 對象具有請求域,即完成客戶端的請求之前,該對象一直有效。常用方法如下:

  • String getParameters(String name): 返回name 指定參數的參數值
  • String[] getParameterValues(String name): 返回包含參數name 的所有值的數組
  • void setAtrribute(String, Object): 存儲此請求中的屬性
  • Object getAttribute(String name): 返回指定屬性的屬性值
  • String getContentType(): 得到請求體的MIME 類型
  • String getProtocol(): 返回請求用的協議類型及版本號
  • String getServerName(): 返回接受請求的服務器主機名
  • int getServerPort(): 返回服務器接受此請求所用的端口號
  • String getCharacterEncoding(): 返回字符編碼的方式
  • void setCharacterEncoding(): 設置請求的字符編碼方式
  • int getContentLength(): 返回請求體的長度(以字節數)
  • String getRemoteAddr(): 返回發送此請求的客戶端IP地址
  • String getRealPath(String path): 返回一虛擬路徑的真實路徑
  • String request.getContextPath(): 返回上下文路徑

創建一個簡單用戶註冊表單: login.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<form name="loginForm" action="request.jsp" method="post">
    用戶名:<input type="text" name="username"><br>
    愛好:<input type="checkbox" name="favorite" value="reading">閱讀
        <input type="checkbox" name="favorite" value="singing">唱歌
        <input type="checkbox" name="favorite" value="basketball">籃球
        <input type="checkbox" name="favorite" value="swimming">遊泳<br>
        <input type="submit" value="提交">
</form>

</body>
</html>

創建一個處理數據的 request.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
    request.setCharacterEncoding("utf-8"); // 解決中文亂碼問題
%>
用戶名:<%=request.getParameter("username") %><br>

愛好:<%
    String[] favorites = request.getParameterValues("favorite");
    for (String favorite:favorites) {
        out.println(favorite);
    }
%>

</body>
</html>

頁面展示效果如圖:

技術分享圖片

現在查看下通過a鏈接跳轉頁面,不走form表單提交的情況,把login.jsp 稍改下

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<form name="loginForm" action="request.jsp" method="post">
    用戶名:<input type="text" name="username"><br>
    愛好:<input type="checkbox" name="favorite" value="reading">閱讀
        <input type="checkbox" name="favorite" value="singing">唱歌
        <input type="checkbox" name="favorite" value="basketball">籃球
        <input type="checkbox" name="favorite" value="swimming">遊泳<br>
        <input type="submit" value="提交">
</form>

<a href="request.jsp?username=Kobe">測試URL傳參數</a>
</body>
</html>

由於a鏈接的帶參參數中只測試username,所以favorite為空的情況下會報錯的,要對request.jsp 稍作修改

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
    request.setCharacterEncoding("utf-8"); // 解決中文亂碼問題
%>
用戶名:<%=request.getParameter("username") %><br>
愛好:<%
        if (request.getParameterValues("favorite") != null) {
            String[] favorites = request.getParameterValues("favorite");
            for (String favorite:favorites) {
                out.println(favorite + "&nbsp;&nbsp;");
            }
        }
    %>
    

</body>
</html>

查看頁面運行效果:

技術分享圖片

但是當 a 鏈接參數中傳參為中文時就會出現亂碼

技術分享圖片

雖然通過request.setCharacterEncoding() 為 utf-8,但是僅限於 request 作用域。要解決 url 中文亂碼問題,就要修改tomcat 的server.xml了

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

----> 增加 URIEncoding屬性
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="utf-8" />

右鍵刪除 eclipse 控制臺 server下的服務器,重新啟動 Tomcat 服務器後,再次運行:

技術分享圖片

接下來測試其它的request方法:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
    request.setCharacterEncoding("utf-8"); // 解決中文亂碼問題
    request.setAttribute("password", "123456");
%>
用戶名:<%=request.getParameter("username") %><br>
愛好:<%
        if (request.getParameterValues("favorite") != null) {
            String[] favorites = request.getParameterValues("favorite");
            for (String favorite:favorites) {
                out.println(favorite + "&nbsp;&nbsp;");
            }
        }
    %><br>
密碼:<%=request.getAttribute("password") %><br>
MIME類型:<%=request.getContentType() %><br>
協議類型及版本號:<%=request.getProtocol() %><br>
服務器主機名:<%=request.getServerName() %><br>
端口號:<%=request.getServerPort() %><br>
字符編碼方式:<%=request.getCharacterEncoding() %><br>
請求體長度:<%=request.getContentLength() %>bytes<br>
客戶端IP地址:<%=request.getRemoteAddr() %><br>
虛擬路徑的真實路徑:<%=request.getRealPath("request.jsp") %><br>
上下文路徑:<%=request.getContextPath() %>

</body>
</html>

頁面輸出結果:

技術分享圖片

response 對象

response對象包含了響應客戶請求的相關信息,但在JSP 中很少直接用到它,它是HTTPServletResponse 類的實例。

response對象具有頁面作用域,即訪問一個頁面時,該頁面內的response對象只能對這次訪問有效,其它頁面的response對象對當前頁面無效。

常用方法:

  • String getCharacterEncoding(): 返回響應的是何種字符編碼方式
  • void setContentType(String type): 設置響應的MIME 類型
  • PrintWriter getWriter(): 返回可以向客戶端輸出字符的一個對象(註意比較:PrintWriter 與內置out對象的區別)
  • sendRedirect(java.lang.String location): 重新定向客戶端的請求
<%@ page language="java" import="java.io.*" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

    <%
        response.setContentType("text/html; charset=utf-8"); // 設置響應的MIME類型
        
        out.println("<h1>response 內置對象</h1>");
        out.println("<hr>");
        
        PrintWriter outer = response.getWriter(); // 獲得輸出流對象
        outer.println("看看我的位置在哪裏");
    %>

向客戶端輸出字符串對象,printWriter 輸出總是提前於 jspWriter 的內置 out 對象

技術分享圖片

如果想讓讓 jspWriter 優於 printWriter 向客戶端輸出字符串對象,可以使用 out.flush() 方法,flush的作用是強制把前面的內容輸入

<%@ page language="java" import="java.io.*" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

    <%
        response.setContentType("text/html; charset=utf-8"); // 設置響應的MIME類型
        
        out.println("<h1>response 內置對象</h1>");
        out.println("<hr>");
        
        out.flush(); // 註意看頁面字符串的先後順序
        
        PrintWriter outer = response.getWriter(); // 獲得輸出流對象
        outer.println("看看我的位置在哪裏");
    %>

註意與上面對比頁面字符串的輸出順序:

技術分享圖片

再來看下重定向方法:

<%@ page language="java" import="java.io.*" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

    <%
        response.setContentType("text/html; charset=utf-8"); // 設置響應的MIME類型
        
        out.println("<h1>response 內置對象</h1>");
        out.println("<hr>");
        
        PrintWriter outer = response.getWriter(); // 獲得輸出流對象
        outer.println("看看我的位置在哪裏");
        response.sendRedirect("login.jsp"); // 請求重定向
    %>

頁面跳轉了:

技術分享圖片

請求重定向 和 請求轉發的區別

請求重定向:

  • 客戶端行為
  • response.sendRedirect()
  • 從本質上講,等同於兩次請求,前一次的請求對象不會保存,地址欄的URL地址會改變

請求轉發:

  • 服務器行為
  • request.getRequestDispatcher().forward(req, res)
  • 是一次請求,轉發後請求對象會保存,地址欄的URL地址不會發生改變

技術分享圖片

JSP 內置對象(上)