你應該知道的JSP基礎

Hugo_Gao發表於2018-02-25

JSP到底是什麼

那麼 JSP 到底是個什麼,在 Servlet 組成的 MVC 中模型中,JSP 就代表著 View ,JSP控制著檢視顯示,一切邏輯在 Servlet(Controller) 和Model 中解決完畢後,轉發到 JSP 中生成檢視檔案(HTML),大家也都知道在 Java 中寫 HTML 程式碼是很麻煩的,因為有很多轉義字元需要轉義,所以人們想不如在 HTML 中寫 Java 算了,於是就誕生了JSP。人們編寫的 JSP 會被轉換為.java檔案,然後編譯為 .class,最後載入並初始化為一個 Servlet。

scriplet

scriplet是最簡單的JSP元素了,它只需要在 HTML中插入<% %>標記,在標記中你可以任意輸入 Java 程式碼。

指令

JSP一共有三個指令,分別是 page,taglib,include。

1.page指令

page指令一共有13個屬性,但是常用的就那麼幾個。import 屬性:這個屬性用來導包,用來在 scriplet 中使用。contentType屬性:如果不把這個屬性設定為UTF-8,那麼顯示中文就會出現問題。

程式碼可以是這樣 <%@ page import="foo.,java.util." contentType="UTF-8" %>

2.taglib 指令

目前我學的 taglib 指令只有一個作用:用來匯入EL函式。當我們在EL中想要呼叫其它 Java 類時,就會用到這個指令,步驟如下。

a.建立你想要呼叫的類:

package foo;

public class DiceRoller
{
    public static int rollDice()
    {
        return (int) ((Math.random()*6)+1);
    }
}
複製程式碼

b.建立TLD庫描述檔案:

<?xml version="1.0" encoding="UTF-8"?>  
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/j2ee/dtds/web-jsptaglibrary_2_0.xsd"  
        version="2.0">
<tlib-version>1.2</tlib-version>
<uri>DiceFunctions</uri>
    <function>
        <name>rollIt</name>
        <function-class>foo.DiceRoller</function-class>
        <function-signature>
            int rollDice()
        </function-signature>
    </function>
</taglib>
複製程式碼

c.JSP:

<%@ taglib prefix="mine" uri="DiceFunctions" %>
<html>
<body>
Hello world
${mine:rollIt()}
</body>
</html>
複製程式碼

我們建立TLD的目的就是為了讓EL語言在TLD中找要找的函式,並且這個函式必須是靜態的,taglib 指令為<%@ taglib prefix="mine" uri="DiceFunctions" %> ,可以看到 uri 屬性與 TLD中的 uri 標籤對應,代表 mine 這個名稱空間呼叫 rollIt()函式。

3.include指令

如果我們有很多個 JSP 都有重複的地方怎麼辦呢,比如說都有頁首與頁尾,那麼就可以把這些地方抽取出來作為公用部分,使用include 指令來複用這些頁面。

<%@ include file="Header.jsp" %>

表示式

表示式是形如<%= out.println("Hello World") %> 的一串程式碼,標籤內放置 Java 程式碼,但是值得注意的是,這段 Java 程式碼必須有返回值,不能是 void 的。並且最後不能有分號。

宣告

我們說了,JSP最後仍然會轉換為Java程式碼,並且前面介紹的 scriplet 所定義的變數是區域性變數,那麼如果我想定義一個全域性變數怎麼辦呢,這就需要用到宣告,形如<%! int i=0;%> 注意這句程式碼裡就必須要有分號了。標籤類不僅可以定義變數,也可以定義一個函式。

隱式物件

第一次看到隱式物件有點不明白是什麼東西,後來明白了,說白了就是我們在建立一個Servlet時,我們能夠得到 request,response,ServletContext,ServletConfig,Session等等東西,那麼JSP最後也是會變成Servlet的,我們在JSP中如何使用這些隱式物件呢。原來JSP早就為我們建立好了。證據呢,請看容器將JSP轉化為Servlet的原始碼:

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
複製程式碼

可以看到我們可以直接使用session,application,config,out,pageContext 等隱式物件而不用自己宣告瞭,而request 和response 也是生成的——jspService()函式的引數,我們也可以直接使用,因為在Servlet 中的requestDispatcher.forward(request,response) 引數傳到這裡來了。

 public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
複製程式碼

JSP標準動作

JSP標準動作可以不用指令碼,也就是不使用Java程式碼來完成一些程式設計工作,例如我們在 request 中有一個"person"屬性,對應一個foo.Person 物件,如果我們想在JSP中獲取這個物件,我們可以很輕鬆的使用 scriptlet 來寫一段 Java 程式碼獲取。但是對於不懂Java 的前端人員怎麼辦呢?我們就可以使用標準動作:

<jsp:useBean id="person" class="foo.Person" scope="request">
  <jsp:setProperty name="person" property="name" value="Fred" />
</jsp:useBean>
Person is <jsp:getProperty name="person" property="name" />
複製程式碼

上面的這串程式碼分別做到:

< jsp:useBean > 宣告使用foo.Person類,這個物件存在request,他的鍵為"person"。

< jsp:setProperty > 做到如果 request 沒有這個物件,那麼就自己建立一個,名為 person ,並且把他的name屬性預設地設定為Fred。

< jsp:getProperty > 做到列印出 person 物件的 name 屬性。

<jsp:include page="Header.jsp" >
  <jsp:param name="subTitle" value="This is a subtitle" />
</jsp:include>
複製程式碼

< jsp:include > 標籤作用與上面講的 include 指令很相似,都是複用重複的的jsp頁面。< param>標籤可以向被包含的jsp傳送一個引數,在被包含的標籤用EL語言${param.subtTtle} 就可以獲得了。與 include 指令不同的是, include 指令只適用於靜態頁面,因為使用 include 指令就相當於直接把被包含的頁面程式碼原封不動的搬到目標JSP程式碼中,而< jsp:include > 標籤可以適用與動態元素,因為它是動態的將被包含的程式碼響應的頁面放在目標位置。

EL語言

EL語言十分強大,它幾乎可以做所有標準動作能做到的事情,而且還更加簡單,例如 request 中有一個person 物件,person 物件有一個 dog 物件,dog 物件 有一個 name 性質,我們要列印這個 dog 的 name 怎麼辦呢。使用 EL 就非常簡單 ${perosn.dog.name} 就完成了這個任務,在EL表示式中,我們用request 的Attribute的鍵直接作為EL的物件使用。例如在Servlet中 request.setAttribute("person",xiaohong) 那麼我們在 EL 中直接只用 person 來代替 xiaohong 這個 Person物件了,同理,如果request.setAttribute("map",aHashMap) 將一個 Map 作為引數,那麼我們直接 ${map["key"]}或者 ${map.key},這兩者的區別是${map.key} 點號後面必須符合java 命名規則。

EL 的隱式物件

EL語言這麼強大,當然也有自己的隱式物件了:

EL隱式物件 作用
pageScope 頁面作用域的屬性
requestScope 請求作用域的屬性
sessionScope 會話作用域的屬性
applicationScope 應用作用域的屬性
param {param.id} 相當於request.getParameter("id")
paramValues 如果引數的值為一個集合,應該用此物件
header 相當於request.getHeader("...");
headerValues 適用於header的某個值為集合的情況
initParam 呼叫web.xml中的上下文初始引數
cookie 獲取cookie
pageContext 可以通過pageContext獲取以上所有物件

再次提醒一定要注意 requestScope 與 param 的區別,也就是屬性和引數的區別,引數是使用者提交的表單了的parameter,而屬性是程式設計人員自己設定的Attribute。

獲取上下文引數的幾種方法

1.指令碼

<%= application.getInitParameter("mainEmail")%>
複製程式碼

2.EL使用initParam

${initParam.mainEmail}
複製程式碼

###3.EL使用pageContext

${pageContext.request.getServletContext().getInitParameter("mainEmail")}
複製程式碼

獲取表單引數的幾種方法

1.指令碼

 <%= request.getParameter("foo")%>
複製程式碼

2.EL使用param

${param['foo']}
複製程式碼

3.EL使用pageContext

${pageContext.request.getParameter("foo")}
複製程式碼

相關文章