天天看點

jsp之javabean與标簽

一、Javabean

JavaBean是特殊的Java類,滿足了以下幾點特征:

1、這個Java類必須具有一個無參的構造函數

2、屬性必須私有化。

3、私有化的屬性必須通過public類型的方法暴露給其它程式,并且方法的命名也必須遵守一定的命名規範。

javabean示例:

package com.demo.test;

/**
 * Created by ForMe
 * com.demo.test
 * 2018/12/2
 * 14:04
 */
public class JavaBean {
    private String name;
    private String password;
    private int id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}
           

1、在jsp中使用javabean

JSP技術提供了三個關于JavaBean元件的動作元素,即JSP标簽,它們分别為:

<jsp:useBean >标簽:用于在JSP頁面中查找或執行個體化一個JavaBean元件。

<jsp:setProperty >标簽:用于在JSP頁面中設定一個JavaBean元件的屬性。

<jsp:getProperty >标簽:用于在JSP頁面中擷取一個JavaBean元件的屬性。

jsp:usebean标簽

<jsp:useBean >标簽的文法格式如下:

"id"屬性用于指定JavaBean執行個體對象的引用名稱和其存儲在域範圍中的名稱。

  "class"屬性用于指定JavaBean的完整類名(即必須帶有包名)。

  "scope"屬性用于指定JavaBean執行個體對象所存儲的域範圍,其取值隻能是page、request、session和application等四個值中的一個,其預設值是page。

簡單示例:

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2018/12/2
  Time: 15:05
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="person" class="com.demo.person.Person" />
<jsp:setProperty name="person" property="name" value="ForMe" />
<jsp:setProperty name="person" property="age" value="20"/>
<jsp:setProperty name="person" property="password" value="113456"/>
<jsp:setProperty name="person" property="sex" value="male"/>
<html>
<head>
    <title>jspTest1</title>
</head>
<body>
<jsp:getProperty property="name" name="person"/><br>
<jsp:getProperty property="password" name="person"/><br>
<jsp:getProperty name="person" property="age"/><br>
<jsp:getProperty name="person" property="sex"/><br>
<hr>
<%=person.getName()%><br>
<%=person.getPassword()%><br>
<%=person.getAge()%><br>
<%=person.getSex()%><br>
<hr>

</body>
</html>
           

結果:

jsp之javabean與标簽

二、自定義标簽

自定義标簽庫是一種非常優秀的表現層元件技術。通過使用自定義标簽庫,可以在簡單的标簽中封裝複雜的功能。

那麼為什麼需要使用自定義的标簽呢?主要是基于以下幾個原因:

JSP腳本非常不好閱讀,而且這些<%! %>、<% %>這些東西也非常不好寫;

當JSP腳本和HTML混在一起時,那更痛苦,當需要表現一些複雜資料時,更是如此;

很多公司的美工是直接參與表現層的代碼編寫的,而相比于HTML來說,JSP代碼則更難寫。

于是,我們需要一種類似于HTML那種簡單寫法的文法來完成JSP的工作,是以JSP中就有了自定義标簽這個強大的功能。

自定義标簽最終都得通過Java類來進行處理,通過标簽類來封裝哪些複雜的功能,對上層提供簡單的标簽。是以當我們定義我們自己的标簽時,工作重點都在編寫這個标簽類。

自定義标簽類都繼承一個父類:

javax.servlet.jsp.tagext.SimpleTagSupport

,除了這個條件以外,自定義标簽類還要有如下要求:

如果标簽類包含屬性,每個屬性都需要有對應的getter和setter方法

需要重寫doTag()方法,這個方法用于生成頁面内容;也就是說,當我們在表現層使用自定義标簽時,使用标簽的地方将使用doTag()輸出的内容替代

分情況示例:

1、簡單輸出結果:

繼承SimpleTagSupport類的java類

package com.tagclass;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;

/**
 * Created by ForMe
 * com.tagclass
 * 2018/12/3
 * 13:26
 */
public class TagTest2_12_03 extends SimpleTagSupport {
    public void doTag() throws IOException, JspException {
    	// 得到代表jsp标簽體的JspFragment
        JspFragment jspFragment = this.getJspBody();
        // 将标簽體的内容輸出到浏覽器
        jspFragment.invoke(null);
    }
}
           

tld檔案

<?xml version="1.0" encoding="ISO-8859-1" ?>
<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/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">
    <description>ForMe建立的用于測試自定義标簽的tld檔案</description>
    <tlib-version>1.0</tlib-version>
    <short-name>ForMe</short-name>
    <uri>/ForMe</uri>
    <tag>
        <name>output</name>
        <tag-class>com.tagclass.TagTest2_12_03</tag-class>
        <body-content>scriptless</body-content>
    </tag>
</taglib>
           

web.xml檔案

<?xml version="1.0" encoding="iso-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <jsp-config>
        <taglib>
            <taglib-uri>/ForMe</taglib-uri>
            <taglib-location>/tlds/TagTest2_12_03.tld</taglib-location>
        </taglib>
    </jsp-config>
</web-app>
           

jsp檔案

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2018/12/3
  Time: 15:19
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="zph" uri="/ForMe" %>
<html>
<head>
    <title>用于測試自定義标簽</title>
</head>
<body>
<zph:output>更上一層樓</zph:output>
</body>
</html>
           

結果會在浏覽器上輸出

更上一層樓

如果在TagTest2_12_03.java類中沒有

jspFragment.invoke(null);

,則不會在浏覽器上輸出結果。

标簽庫的uri不能設定成相同的,否則在Jsp頁面中通過uri引用标簽庫時就不知道引用哪一個标簽庫了

2、修改jsp檔案中的内容

與以上操作不同的地方在于.java檔案中,例如:

package com.tagclass;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.io.StringWriter;

/**
 * Created by ForMe
 * com.tagclass
 * 2018/12/3
 * 15:31
 */
public class TagTest3_12_03 extends SimpleTagSupport {
    public void doTag() throws IOException, JspException {
        JspFragment jspFragment = this.getJspBody();
        StringWriter stringWriter  = new StringWriter();
        jspFragment.invoke(stringWriter);//将标簽體的内容寫入到sw流中
        String s = stringWriter.getBuffer().toString();
        s = s.toUpperCase();  //可以看成對字元串的常用操作
        PageContext pageContext = (PageContext)this.getJspContext();//下面兩步是将修改後的content輸出到浏覽器中
        pageContext.getOut().write(s);
    }
}
           

3、JspFragment類

javax.servlet.jsp.tagext.JspFragment類是在JSP2.0中定義的,它的執行個體對象代表JSP頁面中的一段符合JSP文法規範的JSP片段,這段JSP片段中不能包含JSP腳本元素。

  WEB容器在處理簡單标簽的标簽體時,會把标簽體内容用一個JspFragment對象表示,并調用标簽處理器對象的setJspBody方法把JspFragment對象傳遞給标簽處理器對象。JspFragment類中隻定義了兩個方法,如下所示:

getJspContext方法

用于傳回代表調用頁面的JspContext對象.

public abstract void invoke(java.io.Writer out)

用于執行JspFragment對象所代表的JSP代碼片段,參數out用于指定将JspFragment對象的執行結果寫入到哪個輸出流對象中,如果 傳遞給參數out的值為null,則将執行結果寫入到JspContext.getOut()方法傳回的輸出流對象中。(簡而言之,可以了解為寫給浏覽器)

invoke()方法:

 JspFragment.invoke方法是JspFragment最重要的方法,利用這個方法可以控制是否執行和輸出标簽體的内容、是否疊代執行标簽體的内容或對标簽體的執行結果進行修改後再輸出。例如:

  在标簽處理器中如果沒有調用JspFragment.invoke方法,其結果就相當于忽略标簽體内容;

  在标簽處理器中重複調用JspFragment.invoke方法,則标簽體内容将會被重複執行;

  若想在标簽處理器中修改标簽體内容,隻需在調用invoke方法時指定一個可取出結果資料的輸出流對象(例如StringWriter),讓标簽體的執行結果輸出到該輸出流對象中,然後從該輸出流對象中取出資料進行修改後再輸出到目标裝置,即可達到修改标簽體的目的。

4、帶屬性的标簽

執行個體:

TagTest4_12_03.java

package com.tagclass;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.util.Date;

/**
 * Created by ForMe
 * com.tagclass
 * 2018/12/3
 * 16:09
 */
public class TagTest4_12_03 extends SimpleTagSupport {
    private int num1;
    private int num2;

    private Date date;

    public void setDate(Date date) {
        this.date = date;
    }

    public int getNum1() {
        return num1;
    }

    public void setNum1(int num1) {
        this.num1 = num1;
    }

    public int getNum2() {
        return num2;
    }

    public void setNum2(int num2) {
        this.num2 = num2;
    }
    public void doTag() throws IOException, JspException {
        PageContext pageContext = (PageContext)this.getJspContext();
        pageContext.getOut().write("num1 + num2 = " + (num1 + num2) + " " + date);
    }
}
           

TagTest4_12_03.tld

<?xml version="1.0" encoding="ISO-8859-1" ?>
<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/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">
    <description>帶屬性的自定義标簽執行個體</description>
    <tlib-version>1.0</tlib-version>
    <short-name>attribute</short-name>
    <uri>/attr</uri>

    <tag>
        <name>add</name>
        <tag-class>com.tagclass.TagTest4_12_03</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>num1</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
            <!-- rtexprvalue用來訓示标簽的屬性值是否可以是一個表達式,
            一般設定為true,true就表示允許标簽的屬性值可以是一個表達式 -->
        </attribute>
        <attribute>
            <name>num2</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>date</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>
           

web.xml

<?xml version="1.0" encoding="iso-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <jsp-config>
        <taglib>
            <taglib-uri>/attr</taglib-uri>
            <taglib-location>/tlds/TagTest4_12_03.tld</taglib-location>
        </taglib>
    </jsp-config>
</web-app>
           

TagTest4_12_03.jsp

<%@ page import="java.util.Date" %><%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2018/12/3
  Time: 16:19
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="zph" uri="/attr" %>
<html>
<head>
    <title>帶屬性的自定義标簽</title>
</head>
<body>
<zph:add num1="5" num2="9" date="<%=new Date()%>"/>
</body>
</html>
           

結果如下: