JSPカスタムタグStruts2タグの最初の分析

1.カスタムラベルの役割

バックエンドプログラムの開発中に、頻繁に使用されるコードの一部がカプセル化され、再利用されて開発がスピードアップし、エラーが減少します。バグがある場合は、他の参照場所を一度変更して自動的に修復できます。フロントエンドのWebページで、固定形式の表示関数を頻繁に使用し、サーバー側のロジック操作を伴う場合は、カスタムタグを使用する必要があります。カスタムタグを使用すると、共通のコードを簡単に呼び出すことができます。Spring MVCやStruts2などのフレームワークは独自のJSPページタグを定義しているため、struts2の<s:property value = "message" />タグなどのタグを再利用することで一部の固定機能を実現できます。その後、タグを使用できます。アクションのプロパティとセッションやリクエストなどのフィールドのプロパティ値を読んで、Javaでのカスタムタグの定義プロセスを理解するためにプロパティタグの分析から始めましょう。

2.struts2のプロパティタグのクラス階層分析

struts2のプロパティタグのクラス階層
上記のクラス階層図から、プロパティタグの最上位の親クラスがTagSupportであることがわかります。このクラスのパッケージはjavax.servlet.jsp.tagextです。階層全体でクラスのパッケージ名を確認することにより、 、TagSupportクラスとBodyTagSupportが2つあることがわかります。1つのクラスはJava JDKで定義され、他の3つのクラスはstruts2フレームワークで定義されているため、カスタムタグを実装する場合は、TagSupportから継承する必要があります。クラスまたはBodyTagSupportクラス。もちろん、フレームワークTagSupportクラスおよびBodyTagSupport拡張サブクラスで定義されたものから直接継承することもできますが、これにより、struts2などの特定のフレームワークに依存することになります。必要がない場合は、から拡張することをお勧めします。 TagSupportクラスとBodyTagSupportクラスの上。

3.TagSupportとBodyTagSupportの分析

TagSupportとBodyTagSupportの主な違いは、タグ処理クラスがタグ本体と対話する必要があるかどうかです。対話する必要がない場合はTagSupportを使用し、そうでない場合はBodyTagSupportを使用します。相互作用は、タグ処理クラスがタグ本体のコンテンツを読み取り、タグ本体によって返されるコンテンツを変更する必要があるかどうかです。BodyTagSupportはTagSupportを継承するため、TagSupportで実装されるすべてのタグはBodyTagSupportで実装できます。
タグ処理クラス:TagSupportクラスまたはそのサブクラスから派生したサブクラスを指します。たとえば、図のPropertyTagクラスは、ラベル処理クラスです。
タグ本体:<s:property value = "message" />タグなど、最初に述べたタグであり、その特定の定義はWEB-INFtldファイルtag.tldで確立する必要があります。tag.tldの定義形式については、struts2のタグtld定義ファイルを参照してください。struts21.3.37バージョンを使用しています。特定のtldファイルは、struts2-core-2.3.37.jarパッケージのMETA-INFではstruts2-tags.tldという名前です。特定のコードは次のとおりです。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
  <description><![CDATA['To make it easier to access dynamic data the Apache Struts framework includes a library of custom tags. The tags interact with the framework validation and internationalization features to ensure that input is correct and output is localized. The Struts Tags can be used with JSP FreeMarker or Velocity.']]></description>
  <display-name>Struts Tags</display-name>
  <tlib-version>2.3</tlib-version>
  <short-name>s</short-name>
  <uri>/struts-tags</uri>
  <tag>
    <description><![CDATA[Print out expression which evaluates against the stack]]></description>
    <name>property</name>
    <tag-class>org.apache.struts2.views.jsp.PropertyTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
      <description><![CDATA[The default value to be used if <u>value</u> attribute is null]]></description>
      <name>default</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Deprecated. Use 'escapeHtml'. Whether to escape HTML]]></description>
      <name>escape</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Whether to escape CSV (useful to escape a value for a column)]]></description>
      <name>escapeCsv</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Whether to escape HTML]]></description>
      <name>escapeHtml</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Whether to escape Javascript]]></description>
      <name>escapeJavaScript</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Whether to escape XML]]></description>
      <name>escapeXml</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Value to be displayed]]></description>
      <name>value</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <dynamic-attributes>false</dynamic-attributes>
  </tag>
  </taglib>

タグで定義されているstruts2-tags.tldには多くのタグが定義されてい<tag></tag>ます。スペースの長さのため、プロパティを使用してタグの定義のみを投稿しました。tldファイル(タグライブラリファイル)で定義できます。タグはいくつでもあります。タグごとに1つの<tag></tag>定義を使用します。

3.1。タグライブラリ(tldファイル)の定義

以下に、tldファイル(タグライブラリファイル)の形式定義について説明します(tldファイルはタグライブラリに対応し、特定のコード定義は上記のstruts2-tags.tldファイルの定義形式を参照できます)。

1.名前空間(のxmlns)を導入してのtaglibタグ
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
2.記述のタグが定義されての説明、タグライブラリを<[CDATA [内容]]!>タグ内の記述に注意を払うが、
3.表示名タグStruts2の-tags.tldファイルに定義され、現在のタグライブラリの表示名は、Strutsのタグで定義します。
4. TLIBバージョンのタグが定義のバージョン現在のタグライブラリを、そしてStruts2の-tags.tldファイル内の定義は2.3です;
5.短期名のタグの定義引用をSとStruts2の-tags.tldファイルで定義されている場合、現在のタグライブラリが使用できるプレフィックス;
6. URIタグは、現在のタグライブラリを作る際に必要であることをuri属性を定義しますstruts2-tags.tldファイルでのjspページの参照での定義は/ struts-tagsです。
上記の6つのパラメーター、特にJSPページでタグライブラリを参照する場合の最後の2つのパラメーターを定義した、特定の構成は次のようになります。したがって、prefixタグとuriタグは、tldファイルで定義されているものと一致している必要があります。

<%@ taglib prefix="s" uri="/struts-tags" %>

jspページのヘッダーに<%@ taglib prefix="s" uri="/struts-tags" %>タグライブラリを導入した後、ページで<s:property value="message"/>タグを使用できます

3.2。タグの定義

<taglib>タグは上記定義されていますが<taglib>まだ使用できません。タグで特定のタグを定義する必要があり<tag>ます。各<tag>タグはタグに対応します。<taglib>タグには次の4つの要素が含まれます。

  1. <description>タグの説明。<![CDATA [Content]]>タグの説明に注意してください。

  2. <name> 上記のコードで定義されたプロパティなどのラベルの名前。

  3. <tag-class>タグ処理クラスの場合、パッケージパスを含む完全なクラス名に注意してください。上記のコードはorg.apache.struts2.views.jsp.PropertyTagです。この章の冒頭で説明したタグ処理クラスをここで紹介します。これは、TagSupportクラスまたはそのサブクラスから派生したサブクラスです。

  4. <body-content>body-contentの値には、次の4つのタイプがあります
    。tagdependent:タグbodyのコンテンツはBodyContentに直接書き込まれ、カスタムタグクラスによって処理され、JSPコンテナによって解釈されません。

           <test:myList>
                 select name,age from users
           </test:myList>
    

    JSP:カスタムタグまたは内部タグ、スクリプト、静的HTML、スクリプト要素、JSP命令、アクションなど、すべてのJSP構文を受け入れます。といった:

          <my:test>
    
               <%=request.getProtocol()%>    // ②
        
          </my:test>
    

    empty:空のタグ。つまり、開始タグと終了タグの間にコンテンツはありません。次の書き込み方法はすべて有効です。

           <test:mytag />
    
           <test:mytag uname="Tom" />
    
          <test:mytag></test:mytag>
    

    スクリプトレス:テキスト、EL、JSPアクションを受け入れます。上記②を使用した<body-content> scriptless </body-content>場合、エラーが報告されます。
    上記の4つの値の説明を通じて、body-content要素の意味を明確に理解できます。これは、などのタグの開始記号と終了記号の間の許容値を指し<s:property value="message">这个位置不可以写值,因为是定义的empty</s:property>ます。

  5. <attribute>ラベルの特性について、<s:property value = "message">タグの例を見てみましょう。

<attribute>
      <description><![CDATA[Value to be displayed]]></description>
      <name>value</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
</attribute>

上記のコードは<s:property />タグの機能であり、<description>要素は上記のものと同じであるため、名前はこの機能を説明することを示唆しています。<name>要素は、名前を書き込まないプロパティの名前を定義しますが、タグハンドラークラスに一貫したプロパティ値を定義します。つまり<s:property/>、値タグハンドラークラスフィールドが存在するため、setValue()メソッドが必要です。セッター、これは必須の仕様です。逆に、タグ本体が処理クラスに値を渡す必要があるラベル処理クラスに複数のセッターがある場合は、タグで複数のセッターを<tag>定義する必要があります<attribute><required>この要素は、現在の属性が必要かどうかを指定します。trueとして指定されている場合は、この属性をラベルに設定する必要があります。場合<s:property/>のvalue属性ラベルをとして指定され<required>false</required>、その後、<s:property/>使用されたときのラベルは、この形式でなければなりません<s:property value="具体的值"/><rtexprvalue>要素の説明:rtexprvalueのフルネームは、JSP式が使用できるかどうかを示すために使用されるファイル名を指定して実行時の式の値であり、タグで指定されている場合は真、それはカスタムタグの属性の値ができることを意味します。直接または動的に指定され<myTag:cupSize cupSize="1" cupSizes="${result}"></myTag:cupSize>ます。などの指定

上記の紹介により、タグライブラリ(tld)ファイルを完全に定義できます。tldファイルは定義されていますが、タグ処理クラスがまだ定義されていないため、タグを使用できません。具体的には、タグはTagSupportクラスから派生しています。またはそのサブクラス。クラスを処理する方法については、次のセクションで説明します。

3.3ラベル処理クラスの定義

3.3.1TagSupportクラスのクラス図

TagSupportクラスのクラス図の説明
のTagSupportは、インターフェイスを実装することが分かるにIterationTag、このインターフェースの継承タグインターフェイス、およびタグインターフェイス継承JspTagのインターフェイスを。JspTagのインターフェースは空インタフェースであり、直列化インターフェースは、タグインターフェースです。最初タグインターフェイスを見てみましょう。コメントを付けてコードに直接記述します。

package javax.servlet.jsp.tagext;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;

public interface Tag extends JspTag {
   //四个静态常量,等同于修饰符public static final(默认不写)
   //表示不显示标签间的文字
    int SKIP_BODY = 0;
    //表示将显示标签间的文字
    int EVAL_BODY_INCLUDE = 1;
    //表示不处理接下来的JSP网页
    int SKIP_PAGE = 5;
    //表示处理完标签后继续执行以下的JSP网页
    int EVAL_PAGE = 6;
   //页面上下文
    void setPageContext(PageContext var1);
    //设置父Tag
    void setParent(Tag var1);
   //获取父Tag
    Tag getParent();
   //遇到标签开始时会呼叫的方法,其合法的返回值是
   //EVAL_BODY_INCLUDE与SKIP_BODY,前者表示将显示标签间的文字,后者表示不显示标签间的文字
    int doStartTag() throws JspException;
   //在遇到标签结束时呼叫的方法,其合法的返回值是EVAL_PAGE与SKIP_PAGE
   //前者表示处理完标签后继续执行以下的JSP网页,后者是表示不处理接下来的JSP网页
    int doEndTag() throws JspException;
   //释放资源
    void release();
}

package javax.servlet.jsp.tagext;

import javax.servlet.jsp.JspException;

public interface IterationTag extends Tag {
    //会再显示一次标签间的文字
    int EVAL_BODY_AGAIN = 2;
    //这个方法是在显示完标签间文字之后呼叫的,其返回值有EVAL_BODY_AGAIN与SKIP_BODY
    //前者会再显示一次标签间的文字,后者则继续执行标签处理的下一步
    int doAfterBody() throws JspException;
}

IterationTagインターフェイスは、メソッドの定義と名前から確認でき、繰り返しアクションを提供します。
以下では、TagSupportクラスを見ていきます。

package javax.servlet.jsp.tagext;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;

public class TagSupport implements IterationTag, Serializable {
    private Tag parent;
    private Hashtable values;
    protected String id;
    protected PageContext pageContext;
public static final Tag findAncestorWithClass(Tag from, Class klass) {
    boolean isInterface = false;
    if (from != null && klass != null && ((class$javax$servlet$jsp$tagext$Tag == null ? (class$javax$servlet$jsp$tagext$Tag = class$("javax.servlet.jsp.tagext.Tag")) : class$javax$servlet$jsp$tagext$Tag).isAssignableFrom(klass) || (isInterface = klass.isInterface()))) {
        while(true) {
            Tag tag = from.getParent();
            if (tag == null) {
                return null;
            }

            if (isInterface && klass.isInstance(tag) || klass.isAssignableFrom(tag.getClass())) {
                return tag;
            }

            from = tag;
        }
    } else {
        return null;
    }
}

public TagSupport() {
}

public int doStartTag() throws JspException {
    return 0;表示不显示标签间的文字
}

public int doEndTag() throws JspException {
    return 6;//表示处理完标签后继续执行以下的JSP网页
}

public int doAfterBody() throws JspException {
    return 0;表示不显示标签间的文字
}

public void release() {
    this.parent = null;
    this.id = null;
    if (this.values != null) {
        this.values.clear();
    }

    this.values = null;
}

public void setParent(Tag t) {
    this.parent = t;
}

public Tag getParent() {
    return this.parent;
}

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

public String getId() {
    return this.id;
}

public void setPageContext(PageContext pageContext) {
    this.pageContext = pageContext;
}

public void setValue(String k, Object o) {
    if (this.values == null) {
        this.values = new Hashtable();
    }

    this.values.put(k, o);
}

public Object getValue(String k) {
    return this.values == null ? null : this.values.get(k);
}

public void removeValue(String k) {
    if (this.values != null) {
        this.values.remove(k);
    }

}

public Enumeration getValues() {
    return this.values == null ? null : this.values.keys();
}

}

doStartTag()メソッドとdoAfterBody()メソッドは、タグ間にテキストを表示せずにデフォルトで戻ります。doEndTag()メソッドは、タグが処理された後も次のJSPページを実行し続けるためにデフォルトで戻ります。これらの3つのメソッドは最も便利なメソッドです。タグをカスタマイズする場合。pageContextはセッターを介して挿入され、pageContextは、ペイント、リクエスト、出力ストリームの出力など、現在のページのコンテキストを操作できます。BodyTagSupport
クラスのクラス図を見てみましょう
BodyTagSupportクラス図
。BodyTagSupportクラスはBodyTagインターフェイスを実装し、TagSupportクラスを継承します。BodyTagSupportクラスに新しく追加されたprotected BodyContent bodyContent;フィールドのゲッターとセッターは、jspページの文字出力ストリームであるJspWriterを直接保持します。 、ページ出力文字に送信できます。これまでのところ、BodyTagSupportクラスがbodyContentを介してタグと相互作用していることがわかります。
さらに、doStartTag()の戻り値は2であり、EVAL_BODY_AGAINはタグ間のテキストを再度表示します。
さて、私はカスタムラベルに関する最初の記事のためにたくさん書きました。次の記事はカスタムラベルを書く方法を記録します。

おすすめ

転載: blog.csdn.net/u011930054/article/details/88199420