如何深入學習JSP?JSP學習方法|教程

來源:互聯網
上載者:User

常規JSP

JSP頁面最終會由容器來產生Servlet類的,比如Tomcat容器產生JSP的Servlet類放在work目錄裡。因此在JSP裡可以用很多簡化的文法供容器使用,這篇就來整理一下。

JSP文法

    scriptlet:<% %>
    可以在裡面寫Java代碼,如<%out.print("27");%>;
    指令:<%@ %>
    可以在頁面轉換時向容器給出特殊的指示;它有三個指令:page、include和taglib;而指令又有很多屬性如import是page的屬性:<%@ page import="foo.*,java.util.*"%>;
    運算式:<%= %>
    運算式會成為out.println()或out.print()的參數,因此<%=27%>等價於<%out.print(27);%>;
    聲明:<%! %>
    是JSP轉換成Servlet類的聲明,因此可以聲明類變數(靜態變數)、執行個體變數、方法等;
    注釋:<%-- %>
    就像Java代碼中的注釋一樣,在把JSP轉換成Servlet時會把注釋去掉;

隱式對象

JSP的隱式對象不僅僅有out,還有一些其他的:

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out;
    final java.lang.Object page = this;
    final javax.servlet.http.HttpServletRequest request;
    final javax.servlet.http.HttpServletResponse response;

JSP產生的Servlet

在Tomcat的work目錄裡我們可以看到由JSP產生的Servlet類,該類繼承org.apache.jasper.runtime.HttpJspBase,其中有以下三個方法

    _jspInit()
    _jspDestroy()
    _jspService()

他們分別由父類的init()、destroy()和service()方法調用;前面都帶有"_"號,表明我們不能去覆蓋他們,底線的意思是“不要碰我!”.如我用的是Tomcat7,在JSP中:

    <%! public void _jspDestroy(){
    int i=5;
    }%>

會報異常:

    org.apache.jasper.JasperException: Unable to compile class for JSP:

初始化JSP

通常,我們會把初始化參數分配給單獨的servlet或JSP頁面。這個指定的servlet或者JSP頁面通過ServletConfig的 getInitParameter方法來讀取這些參數。但在某些情況下,需要提供系統範圍內的初始化參數,任何servlet或者JSP頁面可以通過 ServletContext的getInitParameter方法來讀取這些初始化參數。但並不推薦這樣做,通常是使用MVC架構,在C中非常合適。

為JSP配置初始化參數是在<servlet>標記中增加一個<jsp-file>元素

    <!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
    <display-name>Archetype Created Web Application</display-name>
    <context-param>
    <param-name>qq</param-name>
    <param-value>38602359</param-value>
    </context-param>
    <servlet>
    <servlet-name>index</servlet-name>
    <!-- 與Servlet的不同,使用的是jsp-file和URL -->
    <jsp-file>/index.jsp</jsp-file>
    <init-param>
    <param-name>email</param-name>
    <param-value>kevin@oseye.net</param-value>
    </init-param>
    </servlet>
    </web-app>

而index.jsp

    <%@page import="java.util.Enumeration"%>
    <html>
    <body>
    <h2>Hello World!</h2>
    <%=config.getInitParameter("email")%><br>
    <%=getServletConfig().getInitParameter("email")%><br>
    <%=application.getInitParameter("qq")%><br>
    <%=getServletContext().getInitParameter("qq")%>
    </body>
    </html>

但輸出

    Hello World!
    null
    null
    38602359
    38602359

可見並為取到JSP的初始化參數,但如果我在web.xml設定<servlet-mapping>就能取到

    <servlet-mapping>
    <servlet-name>index</servlet-name>
    <url-pattern>/index.jsp</url-pattern>
    </servlet-mapping>

這是為什麼呢?沒明白,先留著!

JSP屬性

    JSP比普通的Servlet多了一個範圍,共有4個範圍

而pageContext的setAttribute和getAttribute都有重載,就多了一個int類型的範圍設定

    public static final int PAGE_SCOPE = 1;
    public static final int REQUEST_SCOPE = 2;
    public static final int SESSION_SCOPE = 3;
    public static final int APPLICATION_SCOPE = 4;

只能取到相應的範圍的屬性,但pageContext還有一個方法findAttribute,它從最嚴格的範圍查起,逐步轉向不那麼嚴格的範圍,也就是先在請求範圍尋找,再尋找會話範圍,最後尋找應用範圍,只要在一個作用查到就停止。例如

    <html>
    <body>
    <h2>Hello World!</h2>
    <%pageContext.setAttribute("name", "kevin",PageContext.REQUEST_SCOPE); %>
    pageContext: <%=pageContext.getAttribute("name") %><br>
    session: <%=session.getAttribute("name") %><br>
    application: <%=application.getAttribute("name") %><br>
    request: <%=request.getAttribute("name") %><br>
    find: <%=pageContext.findAttribute("name") %><br>
    </body>
    </html>

輸出

    Hello World!
    pageContext: null
    session: null
    application: null
    request: kevin
    find: kevin

page指令

page指令的屬性有import、contentType、isThredSafe、Sessioin、buffer、autoflush、extends、info、errorpage、isErrorPage、language、pageEncoding等。格式:

    <%@ page page_directive_attr_list %>

    import屬性指定由Servlet匯入的package。

        <%@ page import="package.class" %>

    isThreadSafe屬性控制從JSP頁中產生的Servlet是否將實現SingleThreadModel介面。isThreadSafe屬性的使用採用以下兩種格式之一,前者是預設的:

        <%@ page isThreadSafe = "True" %>
        <%@ page isThreadSafe = "false" %>

    session屬性控制頁面是否參與HTTP會話。
    –預設值true,表明頁面將加入一個HTTPsession;
    –設定為false,表明不會自動使用任何會話;
    buffer屬性指明JspWriter的緩衝區大小。buffer屬性採用以下兩種格式之一:

        <%@ page buffer="sizekb" %>
        <%@ page buffer="none" %>

    autoFlush屬性配合輸出緩衝區 buffer屬性使用。控制輸出緩衝區在裝滿時是否應該清除,或者當緩衝區溢位時是否應給出異常處理。
    extends屬性指定為JSP頁產生的Servlet的超類。

        <%@ page extends= "package.class" %>

    info屬性定義一個通過getServletInfo方法可以從Servlet中檢索到的串。

        <%@ page info= "some infomation" %>

    isErrorpage屬性指明當前頁是否能充當其他JSP頁面的錯誤頁。預設值為false。
    errorpage屬性指明如果拋出一個異常,而異常沒有被捕獲時,此錯誤處理所指向的URL。
    contentType屬性指明字元編碼和JSP響應的MIME類型。contentType屬性的預設值為text/html ;charset屬性的預設值為 ISO-8859-1

        <%@ page contentType="TYPE" %>
        <%@ page contentType="TYPE; charset=CHARSET" %>

    pageEncoding屬性定義了頁的編碼字元。除非指定page指令的contentType屬性,否則預設值為 ISO-8859-1。
    language屬性指定將要使用的程式設計語言。

無指令碼JSP

使用scriptlet、運算式和聲明不僅代碼混了難以維護,而且不利於頁面設計人員和伺服器開發人員的分工合作,因此這裡介紹EL(運算式語言)、標準動作和JSTL。

標準動作

JSP動作使用格式為:<jsp:標記名>,利用XML文法格式的標記來控制Servlet引擎的行為。這些jsp標籤動作元素是在使用者要求階段執行的,這些標準動作元素是內建在jsp檔案中的,所以可以直接使用。有以下動作元素

    <jsp:useBean> //定義jsp頁面使用一個JavaBean執行個體;
    <jsp:setProperty> //設定一個JavaBean中的屬性值;
    <jsp:getProperty> //從JavaBean中擷取一個屬性值;
    <jsp:include> //在JSP頁麵包含一個外在檔案;
    <jsp:forward> //清空緩衝區把到達的請求轉寄另一個頁面進行處理;
    <jsp:param> //用於傳遞參數值;
    <jsp:plugin> //用於指定在客戶瀏覽器中插入外掛程式的屬性;
    <jsp:params> //用於向HTML頁面的外掛程式傳遞參數值;
    <jsp:fallback> //指定如何處理用戶端不支援外掛程式啟動並執行情況;

這裡要稍作解釋JavaBean的概念,到底什麼是bean法則呢?

就是遵循”古老“JavaBeans規範的法則。我們說的是JavaBean,而不是企業JavaBean(EJB),這兩個東西完全不相干(要搞清楚)。普通的非企業JavaBean規範定義了一個類怎麼才算是JavaBean。儘管這個規範確實很複雜,不過,結合JSP和servlet使用bean時,你只要知道以下規則就行了(只列出了與使用servlet和JSP相關的規則):

    必須有一個無參公用建構函式;
    必須按命名規範來命名公用的擷取方法和設定方法,首先是"get"(或者如果是一個布爾性質,擷取方法的首碼是"is")和"set",如getName何setName。要獲得性質名,先去掉get和set,並把首字母小寫。
    設定方法的參數類型和擷取方法的傳回型別必須一樣,如String getName()和void setName(String name)。
    性質名和類型是由get和set方法推導得出,而不是得自於類中的一個成員。
    結合JSP使用時,性質類型必須是String,或者是一個基本類型。如果不是這樣,儘管也許是一個合法的bean,可如此一來,你可能還得使用指令碼。

例如我有一個JavaBean

    package net.oseye;
    
    public class Person{
    private String name;
    private int age;
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    }

再servlet的doGet()中

    Person p=new Person();
    p.setName("kevin");
    p.setAge(22);
    
    request.setAttribute("person", p);
    
    RequestDispatcher view=request.getRequestDispatcher("/index.jsp");
    view.forward(request, response);

然後在index.jsp中使用指令碼可能是這樣的

    <%
    Person p=(Person)request.getAttribute("person");
    if(p!=null){
    out.print(p.getName());
    }else{
    out.print("null");
    }
    %>

而如果使用JSP標準動作是

    <jsp:useBean id="person" class="net.oseye.Person" scope="request" />
    <jsp:getProperty property="name" name="person"/>

對標準動作的一點點說明(最好查看Tomcat/work目錄產生的java檔案更好來理解):

    <jsp:useBean id="person" class="net.oseye.Person" scope="request" />

    id為屬性名稱,class為屬性值的類型,scope為屬性範圍;
    如果屬性不存在person,則建立一個新的屬性,是class的樣本對象;因此它也可以有體來設定性質值

        <jsp:useBean id="person2" class="net.oseye.Person" scope="request">
        <jsp:setProperty property="name" name="person2" value="kevin2"/>
        </jsp:useBean>
        <%=((Person)request.getAttribute("person2")).getName()%>

    帶體的只有找不到相應的屬性時才建立。
    如果建立多態JavaBean的話使用type屬性,含義是

        type id=new class();

    type是參考型別,而class為物件類型,因此type可以是介面、抽象類別、父類等等,如果沒有type其實預設的是type和class一樣。如果只有type,而沒有class,屬性bean必須存在。
    scope預設為“page”。

    <jsp:param>

param是用於接收form表單提交的參數,如果表單元素名和JavaBean的性質名不同,則需要使用param,如form表單

    <form method="get" action="http://localhost:8080/mytest/Index">
    <input name="username" type="text" value="Anders" />
    <input type="submit" name="Submit" value="提交" />
    </form>

在index.jsp中

    <jsp:useBean id="person" class="net.oseye.Person" scope="request">
    <jsp:setProperty property="name" name="person" param="username" />
    </jsp:useBean>

如果表單的元素名稱和JavaBean的姓名相同,就可以省略param參數,如果表單的元素與JavaBean的性質完全符合還可以在property使用萬用字元

    <jsp:useBean id="person" class="net.oseye.Person" scope="request">
    <jsp:setProperty property="*" name="person" />
    </jsp:useBean>

EL
如在表中動作中所說,如果JavaBean的性質類型不是String的話,儘管它是一個合法的JavaBean但仍需要使用指令碼,其實還有一種方式就是EL(express language)。EL文法相當簡單,格式是:

    ${firstThing.secondThing}

其中firstThing可以是隱式對象:pageScope、requestScope、sessionScope、applicationScope、pageContext、param、paramValues、header、headerValues、cookie、initParam,或屬性
pageScope屬性、requestScope屬性、sessionScope屬性、applicationScope屬性。
訪問映射值或性質時可以使用點號(.),但除了性質和映射值外還有很多的其他特殊的,隨意最通用的是中括弧([]),如在servlet中

    Person p=new Person();
    p.setName("kevin");
    p.setAge(22);
    request.setAttribute("person", p);
    RequestDispatcher view=request.getRequestDispatcher("/index.jsp");
    view.forward(request, response);

在JSP中

    <%@page isELIgnored="false" %>
    <html>
    <body>
    ${person.name}<br>
    ${person["name"]}<br>
    ${10+10 }
    </body>
    </html>

PS:由於版本的不同,可能預設啟用了EL,或者預設沒啟用EL,如果預設沒啟用需要手動啟用,所以第一行不能少的,當然也可以在DD檔案中配置。而且EL還可以自訂函數,這點先不深入了。
JSTL
JSTL全名為JavaServer Pages Standard Tag Library。JSLT標籤庫,是日常開發經常使用的,也是眾多標籤中效能最好的。需要添加JSTL的JAR包

    <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
    </dependency>

然後在JSP文檔中添加聲明

    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

然後就可以使用JSTL了

    <c:out value="dddd"></c:out>

    常用的標籤:如<c:out>、<c:remove>、<c:catch>、<c:set>等;
    條件標籤:如<c:if><c:when>、<c:choose>、<c:otherwise>等;
    URL標籤:如<c:import>、<c:redirect>和<c:url>等;
    XML標籤:如<xml:out>等;
    國際化輸出標籤:如<fmt:timeZone>等;
    SQL標籤:如<sql:query>、<sql:update>、<sql:transaction>等;

當然,如果JSTL不夠用的話,還可以定製一些JSTL,定製JSTL暫時不深入。

PS:include指令、<jsp:include>標準動作和JSTL的不同:前者是在編譯期複製,後者是在執行期複製。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.