Javaweb----知識點總結3
今天介紹一些jsp頁面。
首先先來強調一點,現在很多人都說jsp過時了。jsp確實過時了,但是這不代表我們在工作中就真的見不到jsp了,你肯定有一些老的專案要維護。何況我們學校這學期還在教這個。不能因噎廢食。
我們以後在工作中可能要維護老的專案,就可能遇見jsp頁面,看懂的前提就是自己要會。
但是jsp的前後端分離性確實太差了,現在都是後端生成json傳給前端,實現了前後端分離。
首先來介紹一下什麼是jsp吧,jsp表面上類似於html語言,只不過中間有一些java語言。
其實jsp頁面本質上就是servlet程式,瀏覽器第一次請求jsp頁面的時候tomcat伺服器會把jsp檔案經過編譯生成一個java檔案,這個java檔案裡面的程式就是servlet程式。再經過編譯生成.class位元組碼檔案交給JVM執行,相應瀏覽器的需求。
說到底,jsp就是封裝了servlet的java程式而已。
jsp長得很像html檔案,jsp檔案裡面有一些特殊的語法:
<%! //極少使用 //宣告java程式碼,作用是可以給jsp翻譯出來的java類定義屬性和方法,甚至是靜態程式碼塊內部類等 %> <%=12//表示式 常用! //表示式指令碼 作用是在jsp頁面上輸出資料 //1. 所有的表示式指令碼都會被翻譯到_jspService()方法中 //2. 表示式指令碼都會被翻譯成為out.print()輸出到頁面上 //3. 由於表示式指令碼翻譯的內容都在_jspService()方法中,所以_jspService方法中的物件都可以直接使用 //4.表示式指令碼中的表示式不能以 ';' 結束 %> <% //程式碼指令碼 //java語句 //作用是可以在JSP頁面中編寫我們自己的功能 //特點是 /* 1.翻譯之後都在_jspService方法中 2.程式碼指令碼由於翻譯到_jspService方法中,所以在_jspService方法中的現有物件都可以直接使用 3.還可以由多個程式碼指令碼塊組合完成一個完整的java語句 4.程式碼指令碼還可以和表示式指令碼一起組合使用,在jsp頁面上一起組合使用 */ %> <%--這是jsp註釋 可以註釋掉jsp頁面中所有程式碼--%>
示例:
<%=12%> 輸出整形<br/> <%=12.12%> 輸出浮點型<br/> <%="我是字串"%> 輸出字串<br/>
瀏覽器:
<%! //定義程式碼塊 static { map = new HashMap<String, Object>(); map.put("key1","value1"); map.put("key2","value2"); map.put("key3","value3"); } %> <%=map%> 輸出物件<br/>
瀏覽器:
但是這種jsp語言太過於麻煩了,尤其體現在html語言和jsp語言的混合使用
比如說我們用for迴圈寫一個表格:
<table border="1" cellspacing="0"> <% for(int j=0;j<10;j++){ %> <tr> <td>第<%=j+1%>行</td> </tr> <% } %> </table>
要混合使用表示式,程式碼指令碼和html語言,這樣的程式碼可讀性比較差。
所以要引入EL表示式和JSTL標籤,這些我們後面再說。
JSP的九大內建物件:是指tomcat在翻譯jsp頁面成為Servlet原始碼後內部提供的九大物件叫內建物件
request 請求物件
response 響應物件
pageContext jsp上下文物件
session 會話物件
application ServletContext物件
config ServletConfig物件
out jsp輸出流物件
page 指向當前jsp的物件
exception 異常物件(需要開啟 isErrorPage)
其中的四大域物件:
pageContext(PageContextImpl 類) 當前jsp頁面範圍內有效
request(HttpServletRequest類) 一次請求內有效
session(HttpSession類) 一個會話範圍內有效(會話:開啟瀏覽器,訪問伺服器,直到關閉瀏覽器)
application(ServletContext類) 整個web工程範圍內都有效
它們的範圍從上往下是由小到大的,而四個域在使用的時候,優先順序分別是:他們從小到大的範圍的順序
pageContext -> request -> session -> application
示例:
scope.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>scope.jsp頁面</h1> <% //往四個域中都分別儲存了資料 pageContext.setAttribute("key","pageContext"); request.setAttribute("key","requestContext"); session.setAttribute("key","sessionContext"); application.setAttribute("key","applicationContext"); %> pageContext域是否有值:<%=pageContext.getAttribute("key")%> <br/> requestContext域是否有值:<%=request.getAttribute("key")%> <br/> sessionContext域是否有值:<%=session.getAttribute("key")%> <br/> applicationContext域是否有值:<%=application.getAttribute("key")%> <br/> <% request.getRequestDispatcher("/scope2.jsp").forward(request,response); %> </body> </html>
我們首先向四大域物件中儲存資料,在請求轉發到scope2.jsp頁面
scope2.jsp頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>scope2.jsp頁面</h1> pageContext域是否有值:<%=pageContext.getAttribute("key")%> <br/> requestContext域是否有值:<%=request.getAttribute("key")%> <br/> sessionContext域是否有值:<%=session.getAttribute("key")%> <br/> applicationContext域是否有值:<%=application.getAttribute("key")%> <br/> </body> </html>
最終頁面顯示:
我們可以發現pageContext域的值沒了,因為pageContext的值只在當前頁面內有效。
如果我們再進入這個網址:
http://localhost:8080/demo/scope2.jsp
頁面顯示:
如果我們關閉瀏覽器再訪問這個頁面那麼sessionContext的值就也是null了(由於我還要寫部落格,這裡不方便展示了)。
我們關閉web工程那麼applicationContext域中肯定就沒有值了呀。
response物件和out物件的區別:
這兩個物件都可以在客戶端列印資料,但是他們的區別就是優先權不同
我們使用out.wirte(內容)的時候,會把資料寫入到out緩衝區,我們使用response.getWriter().write(內容)的時候會把資料寫入到response緩衝區。
當jsp頁面所有的程式碼執行完成後,會進行如下兩個操作:
1. 會執行out.flush()操作,會把out緩衝區中的資料追加寫入到response緩衝區末尾 2. 會執行response的重新整理操作,把全部資料寫給客戶端
也就是說無論你是先用out輸出,還是用response輸出,只要你沒有在程式碼中使用out.flush()方法,那麼最後在客戶端的資料最先是response輸出的內容,而不是你寫在前面的out物件輸出的內容。
這樣就會出現順序混亂的情況,所以我們如果想在頁面輸出資料,統一使用Out物件輸出,這樣就不會產生順序問題。
這裡還要注意一點out.write()和out.print()的區別。
區別就是如果我們想輸出數字的話,out.write()會自動把數字轉換成對應的ASCII碼字元輸出,而不是我們想輸出的數字。
而out.print()會把我們其中寫的內容轉換成字串輸出,所以我們就統一使用out.print()來輸出。
jsp的內容差不多就是這麼多了,我們最後再綜合使用一下這些知識點:
servlet程式:
public class Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //獲取請求的引數 //發sql語句查詢學生資訊 List<Student> studentList = new ArrayList<Student>(); for(int i =0;i< 10 ; i ++) { int t = i+1; studentList.add(new Student(t,"name"+t,(int)(Math.random()*5-2)+18,"Phone"+t)); } //儲存查詢到的結果到request域中 req.setAttribute("stuList",studentList); //請求轉發到showStudent.jsp req.getRequestDispatcher("/showStudent.jsp").forward(req,resp); } }
jsp頁面:
<%@ page import="bean.Student" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <style> table{ } td,tr{ border: 1px solid red; } </style> </head> <body> <% List<Student> studentList = (List<Student>) request.getAttribute("stuList"); %> <table style="width: 600px;text-align: center;border: 1px solid red;border-collapse: collapse"> <tr> <td>姓名</td> <td>學號</td> <td>年齡</td> <td>電話</td> </tr> <% for(Student student : studentList) { %> <tr style="border: 1px solid red;"> <% String name = student.getName(); int id = student.getId(); int age = student.getAge(); String phone = student.getPhone(); %> <td><%=name%></td> <td><%=id%></td> <td><%=age%></td> <td><%=phone%></td> <%}%> <tr> </table> </body> </html>
頁面顯示: