1. 程式人生 > >菜鳥程式猿之JSP+EL表示式

菜鳥程式猿之JSP+EL表示式

一、JSP
1.jsp介紹
   是SUN公司提供動態的web技術之一。Servlet顯示功能時,非常麻煩,編寫與程式碼維護非常麻煩;

   通過檢視..\apache-tomcat-7.0.53\work\...\index_jsp.java發現該類繼承了org.apache.jasper.runtime.HttpJspBase
類,該類又繼承了HttpServlet(apache-tomcat-6.0.36-src\java\org\apache\jasper\runtime\),所以jsp本質
上是一個Servlet。

對比Servlet:
   Servlet是在java程式碼中嵌入了Html頁面程式碼;
   JSP是在Html頁面中嵌入了Java程式碼。

 JSP執行流程:.jsp-(翻譯)->.java-(編譯)-->.class
  jsp會在第一次訪問時被翻譯成.java檔案(Servlet類),對jsp的訪問其實就是翻譯後的Servlet
向外輸出資訊。


2、修改jsp生成模板
   找到**\MyEclipse10\Common\pluginscom.genuitec.eclipse.wizards_9.0.0.me201108091322.jar
   開啟templates\jsp\Jsp.vtl
----------------------
*#<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title></title>
  </head>
  <body>

  </body>
</html>
--------------------------------

3、JSP基本語法
3.1模板元素!
html的頁面元素,比如:<html>、<head>、<title>
3.2指令碼表示式
<%= 表示式 %>
jsp中:
<%= new Date().toLocaleString() %>
翻譯後的servlet中:
 out.print(new Date().toLocaleString() );
<%= 表示式%>  裡邊內容是一段java表示式,在jsp翻譯到servlet中,利用
out.print(...)將表示式結果輸出。
3.3指令碼片段!!
<% java程式碼  %>
(1)可以在<% %>中編寫java程式碼,其中的java原始碼將會直接拷貝到對應Servlet對應的位置。

(2)在某一個java指令碼片段中,java程式碼可以是不完整的,但是要求在翻譯過去的Servlet中是完整。
3.4JSP宣告!
<%!  %>在其中編寫java程式碼,翻譯後將宣告中的程式碼拷貝到Servlet中的service方法之外;可以
利用宣告定義全域性變數、方法、程式碼塊{}、靜態程式碼塊、內部類等等
<%! int i =100; %>
<%! public void sleep(){} %>
<%! class Student{}%>
<%! {}%>
<%! static{}%>
經典面試題!!!:
 <%! int a = 0;%>
<% int b= 0; %>
<%
a++;
b++;
out.write(a+"<br/>");
out.write(b+"<br/>");
%>
 第一次訪問時,a,b的值分別是多少
 第二次訪問時,a,b的值分別是多少
3.5註釋
jsp註釋<%-- 註釋說明文字 --%>:不會被翻譯到servlet中
java註釋:<%  //   %>:不會被編譯到.class檔案中
html註釋:<!-- 註釋說明文字 -->將會被當成html模板元素,直接輸出到瀏覽器中,瀏覽器將不會顯示
        html註釋,但是在檢視頁面原始碼時可以看到。
新建一個2.jsp:
--------------------
 <%-- out.write("abc"); --%>
<% //out.write("efg"); %>
<!-- html註釋 -->
--------------------
============原始碼==========
 //out.write("efg");
out.write("   <!-- html註釋 -->\r\n");
============================

思考題:思考i的值時多少?
<%int i = 100;%>
<%-- i=10; --%>
<%// i=8;%>
<!-- <% i = 1;%> -->
<%=i%>
結果為1。
3.6、page指令

用來通知翻譯引擎,如何翻譯當前的JSP
[! language="java" ] 當前JSP使用的開發語言(以便將來擴充套件)
[ !extends="package.class" ] 當前jsp翻譯成servlet後要繼承的類,注意此值必須是一個servlet的子類,一般情況下不要改
[!!import="{package.class | package.*}, ..." ] 匯入需要使用到的包 java.lang.*;javax.servlet.*;javax.servlet.jsp.*;javax.servlet.http.*;
[!!session="true | false" ] 用來指定當前頁面是否使用session,如果設定為true,則翻譯過來的servlet中將會有對session物件的引用,於是可以直接在jsp中使用session隱式物件。但是這將導致一旦訪問jsp就會呼叫
pageContext.getSession();方法,可能導致不必要的空間浪費。如果確定jsp中不需要session可以設為false
[ !isThreadSafe="true | false" ] 翻譯過來的servlet是否實現SingleThreadModel
[ !!errorPage="relative_url" ] 如果頁面出錯,將要跳轉到的頁面,除了在jsp中使用此屬性指定錯誤頁面外也可以在web.xml中配置整個web應用的錯誤頁面,如果兩個都設定則jsp中的此屬性起作用
[ !!!isErrorPage="true | false" ] 如果設定此屬性為true,翻譯過來的servlet中將含有Exception隱式物件,其中封裝的就是上一個頁面中丟擲的異常物件
[ !!!contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ] 和jsp亂碼相關的指令,用來指定jsp輸出時,設定的Content-Type響應頭用來指定瀏覽器開啟的編碼
[ !!!pageEncoding="characterSet | ISO-8859-1" ] 伺服器翻譯jsp時使用的編碼集.如果向防止jsp亂碼,應該保證檔案的儲存編碼和jsp翻譯成servlet用的編碼以及輸出到瀏覽器後瀏覽器開啟的編碼一致.此屬性一旦設定好,翻譯引擎會間接幫我們設定content-type屬性.
[ !isELIgnored="true | false" ] 當前頁面是否使用el表示式,設定為false時表示啟用el,j2ee4.0開始預設支援,j2ee4.0一下做開發時,如果要使用el表示式,需將此屬性設定為false
[ !!!buffer="none | 8kb | sizekb" ] out隱式物件所使用的緩衝區的大小
[ autoFlush="true | false" ] out隱式物件是否自動重新整理緩衝區,預設為true,不需要更改;如果設定為false,需要手動呼叫out.flush()方法否則報錯。

isThreadSafe
   |-false:
       實現了SingleThreadModel 介面,表示以Singleton模式執行。
       同一個時刻只有一個例項。不會出現多執行緒同步的安全問題。
       缺點:如果用多個使用者同時訪問該頁面,先訪問者完全執行完之後,後訪問者才可訪問(效率較低)。
   |-true(預設值):不實現該介面。
 
3.7!!!include指令
靜態引入
<%@include file="" %>在當前頁面靜態引入其他頁面中的內容。
在原始檔級別進行的合併,多個jsp頁面生成一個servlet(.java),最終由這個servlet生成響應,推薦使用。
多個檔案中不能出現同名的變數。

動態引入:
<% request.getRequestDispatcher("/_head.jsp").include(request, response);%>
在執行時將多個頁面進行合併(每一個jsp頁面分別進行編譯,分別產生一個servlet),
最終由這多個servlet組成一個輸出流來進行相應。效率相對較低。

通過演示發現動態引入時順序有問題,解決方案在body2.jsp頁面中page指令新增buffer="none/0kb"


3.8 !!taglib指令
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>用於引入標籤庫
uri:指定被引入標籤庫的名稱空間。
prefix:對該名稱空間的一個縮寫。

4、!!!九大隱式物件
jsp翻譯成servlet(.java)時,jsp翻譯引擎在翻譯的過程中,預先定義了一些變數,可以在jsp中
不需要定義而直接使用。共9個,被稱為jsp的九大隱式物件。
分別是:
   page
   config
   application
   response
   request
   session
   exception
   out
   pageContext
4.1、out物件!!
    out相當於response.getWriter(),區別在於out自帶緩衝區,如果out和response.getWriter()
同時使用的話,會出現順序混亂的問題。
    演示案例見:4out.jsp
   出現順序混亂,原因out自帶快取區導致的問題。解決辦法時,在當前頁面上page指令新增buffer="0kb/none"

  page指令中buffer和autoFlush是用來設定out快取區的(可以設定buffer="none" autoFlush="true" 預設是true;該處如果改為false將拋錯)
頁面上也可以通過手動新增重新整理快取區out.flush();
  總結:如果想在jsp頁面上輸出內容,直接使用out就可以了,儘量不要使用response.getWriter()。

4.2 pageContext!!!
4.2.1作為入口物件:可以通過該物件獲取其他八大隱式物件。
  PageContext  pageContext;
  HtttpSession pageContext.getSession();//返回session物件
  ServletContext pageContext.getServletContext();//返回application物件
  pageContext.getRequest();//返回request物件
  pageContext.getResponse();//返回response物件
  pageContext.getPage();//返回page物件
  pageContext.getException();//返回exception物件
  pageContext.getServletConfig();//返回config物件
  pageContext.getOut();//返回out物件
 
4.2.2作為入口物件獲取其他作用域中的資料。!!!
之前學習過的作用域物件:request\session\application
以及pageContext作用域物件,被稱為四大作用域。
範圍有小到大:
pageContext->request->session->application

pageContext操作所有域中屬性的方法
    getAttribute(String name,int scope)
    setAttribute(String name, Object value,int scope)
    removeAttribute(String name,int scope)
    其中pageContext中代表域的常量:
        PageContext.APPLICATION_SCOPE
        PageContext.SESSION_SCOPE
        PageContext.REQUEST_SCOPE
        PageContext.PAGE_SCOPE
    findAttribute方法:
    在四大域中搜尋屬性,搜尋的順序是pageContext域、request域、session域、application域,
  從小域到大域開始搜尋,如果搜尋到就直接獲取該值,如果所有域中都找不到,返回一個null

演示見:5pc.jsp

4.2.3作為域物件使用!!!
    作用的範圍:這個jsp頁面,是四大作用域中最小的一個。
    生命週期:當對jsp的請求開始時生成,當響應結束時銷燬。
    作用:在當前的這個jsp頁面中範圍內共享資料

4.2.4跳轉到其他資源!
    其身上提供了forward和include方法,簡化轉發和包含的操作
    request.getRequestDispatcher("...").forward(request, response);
    request.getRequestDispatcher("...").include(request, response);
    相當於:
    pageContext.forward("...");
    pageContext.include("...");



5、jsp標籤技術!!
由sun公司提供,屬於jsp規範中的內容,不需要引入第三方標籤庫,我們介紹其中的三個。
<jsp:include>用來替代request.getRequestDispatcher().include()
<jsp:forward>用來替代request.getRequestDispatcher().forward()
<jsp:param>配合前兩個標籤使用,可以在包含或轉發時,帶一些引數過去

二、EL表示式!!!
2.1.    EL概述
EL 全名為Expression Language,用來替代<%=  %>指令碼表示式或out.write()或out.print()。
在j2ee1.4以前預設是不支援el,如果需要需要指定page指令[isELIgnored="true | false" ]為false,
J2EE4.0後預設支援el
EL具有獲取資料、執行運算、獲取常用開發物件、呼叫java方法這四方面的功能
2.2.獲取資料
程式碼見:el/1el.jsp
!1.獲取常量資料:支援數字、字串、布林型別。。。el表示式的值就是常量的值。
!!!2.獲取變數資料:el可以獲取變數的值,它底層呼叫了pageContext物件的findAttribute()方法。
按照從小到大的順序從pageContext、request、session、application依次查詢,找到則顯示;如果四個
作用域物件中均不存在要找的屬性,則神馬都不顯示;
3獲取陣列中資料:可以通過  名稱[下標]獲取陣列中的內容
String names[]={"喬峰","段譽","虛竹","夢姑"};
 pageContext.setAttribute("names", names);
4、獲取List集合中的資料:可以通過 名稱[下標]獲取指定位置的元素
5、獲取Map集合中的資料:可以通過 名稱.鍵或名稱[鍵]來獲取map集合中的資料
6、獲取javabean物件的資料:名稱.屬性名   .什麼就相當於.get什麼()
                                        .name 就相當於.getName()
                

總結:
     (1)“."和"[]"使用.的地方可以使用中括號[],如果屬性名稱是數字或包含特殊符號(.)就必須
     使用[](比如map.son.wife丟擲,只能使用map["son.wife"])
     (2)EL只能讀取不能設定
     (3)EL只能讀取不能遍歷
     (4)在獲取資料時,如果使用了雙引號表示常量,不使用表示變數,如:
       ${map["wife"]--葉二孃
       ${map[wife]-少林寺CEO(前提條件: pageContext.setAttribute("wife", "job");)

2.3進行簡單的運算