1. 程式人生 > 其它 >Javaweb----知識點總結3

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>

頁面顯示: