那麼 JSP 究竟是個什麼,在 Servlet 組成的 MVC 中模型中,JSP 就表明着 View ,JSP控制着視圖顯示,一切邏輯在 Servlet(Controller) 和Model 中解決完畢後,轉發到 JSP 中生成視圖文件(HTML),你們也都知道在 Java 中寫 HTML 代碼是很麻煩的,由於有不少轉義字符須要轉義,因此人們想不如在 HTML 中寫 Java 算了,因而就誕生了JSP。人們編寫的 JSP 會被轉換爲.java文件,而後編譯爲 .class,最後加載並初始化爲一個 Servlet。php
scriplet是最簡單的JSP元素了,它只須要在 HTML中插入<% %>標記,在標記中你能夠任意輸入 Java 代碼。html
JSP一共有三個指令,分別是 page,taglib,include。前端
page指令一共有13個屬性,可是經常使用的就那麼幾個。import 屬性:這個屬性用來導包,用來在 scriplet 中使用。contentType屬性:若是不把這個屬性設置爲UTF-8,那麼顯示中文就會出現問題。java
代碼能夠是這樣 <%@ page import="foo.,java.util." contentType="UTF-8" %>web
目前我學的 taglib 指令只有一個做用:用來導入EL函數。當咱們在EL中想要調用其它 Java 類時,就會用到這個指令,步驟以下。編程
a.建立你想要調用的類:cookie
package foo;
public class DiceRoller {
public static int rollDice() {
return (int) ((Math.random()*6)+1);
}
}
複製代碼
b.建立TLD庫描述文件:session
<?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:app
<%@ 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()函數。dom
若是咱們有不少個 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標準動做能夠不用腳本,也就是不使用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語言十分強大,它幾乎能夠作全部標準動做能作到的事情,並且還更加簡單,例如 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隱式對象 | 做用 |
---|---|
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。
<%= application.getInitParameter("mainEmail")%>
複製代碼
${initParam.mainEmail}
複製代碼
###3.EL使用pageContext
${pageContext.request.getServletContext().getInitParameter("mainEmail")}
複製代碼
<%= request.getParameter("foo")%>
複製代碼
${param['foo']}
複製代碼
${pageContext.request.getParameter("foo")}
複製代碼