1. 程式人生 > >jsp之javabean與標籤

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 >標籤的語法格式如下:

<jsp:useBean id="beanName" class="package.class" scope="page|request|session|application"/>

"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>

結果:
FuaEdS.png
二、自定義標籤
自定義標籤庫是一種非常優秀的表現層元件技術。通過使用自定義標籤庫,可以在簡單的標籤中封裝複雜的功能。
那麼為什麼需要使用自定義的標籤呢?主要是基於以下幾個原因:
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>

結果如下:

num1 + num2 = 14 Mon Dec 03 16:31:44 CST 2018