LoginSignup
8
9

More than 5 years have passed since last update.

Thymeleaf version 2.1.5 で独自のダイアレクトを実装する

Last updated at Posted at 2016-10-17

概要

Thymeleafで独自のダイアレクトを実装する方法のまとめです。
ダイアレクトでどのようなことが出来るのかを中心にしているので、サンプルコードに実用性はあまりありません。
また、このサンプルコードで説明するダイアレクトのprefixはmyとしています。

ダイアレクトとプロセッサについては公式サイトのチュートリアルの説明が詳しかったので下記にその一部を引用します。
引用部分に書かれているとおり、基本的にはスタンダードダイアレクトだけで十分間に合うことが多いのですが、同じロジックを多くのテンプレートに記述しなければいけないなどの場合は、独自プロセッサに任せることでテンプレート上から冗長性を排除することができます。

1.3 ダイアレクト: スタンダードダイアレクト

http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html#ダイアレクト-スタンダードダイアレクト

DOMノードにロジックを適用するものを「プロセッサ」と呼びます。そして、プロセッサ一式 — と、いくつかの特別な生成物 — のことをダイアレクトと呼びます。Thymeleafでは「スタンダードダイアレクト」というそのまますぐに使えるコアライブラリを提供していて、大半のユーザーにとってはこれで十分です。

もちろん、ライブラリの拡張機能を利用して独自の処理ロジックを定義したい、など(スタンダードダイアレクトを拡張することも含めて)独自のダイアレクトを作りたい場合があるかもしれません。テンプレートエンジンは複数のダイアレクトを同時に使用できます。

環境

  • Windows10 Professional
  • Java 1.8.0_101
  • Spring Boot 1.4.1
    • thymeleaf 2.1.5

参考

実装方法

独自のダイアレクトの実装は、大きく分けると以下の3つの実装が必要です。

  1. プロセッサの実装
  2. ダイアレクトの実装
  3. 設定の実装

検証用のコントローラーとモデル

サンプルコードの検証に使用するモデルとコントローラーです。

モデル

UserModel
public class UserModel implements Serializable {
  private static final long serialVersionUID = 1595768734175347794L;

  public UserModel() {
  }

  public UserModel(Long id, String name) {
    this.id = id;
    this.name = name;
  }

  private Long id;
  private String name;

  ...getter/setterは省略...

  @Override
  public String toString() {
    return "User [id=" + id + ", name=" + name + "]";
  }

}
ItemModel
public class ItemModel implements Serializable {
  private static final long serialVersionUID = 4429386992827915231L;

  public ItemModel() {
  }

  public ItemModel(Long id, String name, Integer price, Integer remaining, String imageUrl) {
    this.id = id;
    this.name = name;
    this.price = price;
    this.remaining = remaining;
    this.imageUrl = imageUrl;
  }

  private Long id;
  private String name;
  private Integer price;
  private Integer remaining;
  private String imageUrl;

  // ...getter/setterは省略...

  @Override
  public String toString() {
    return "ItemModel [id=" + id + ", name=" + name + ", price=" + price + ", remaining=" + remaining
      + ", imageUrl=" + imageUrl + "]";
  }

}

コントローラー

MyController
@Controller
public class MyController {

  private static final Map<Long, ItemModel> LIST;
  static {
    Map<Long, ItemModel> tmp = new HashMap<Long, ItemModel>();
    tmp.put(1L, new ItemModel(1L, "うまい棒", 10, 50, "/path/to/image/umaibou.png"));
    tmp.put(2L, new ItemModel(2L, "チョコバット", 20, 20, "/path/to/image/chocobat.png"));
    tmp.put(3L, new ItemModel(3L, "ベビースター", 30, 5, null));
    LIST = Collections.unmodifiableMap(tmp);
  }

  @RequestMapping(value = "/my/{id}", method = RequestMethod.GET)
  public String my(@PathVariable(name = "id", required = true) Long id, HttpServletRequest request, Model model) {

    UserModel user = new UserModel(100L, "rubytomato");
    HttpSession session = request.getSession();
    session.setAttribute("user", user);

    ItemModel item = LIST.get(id);
    model.addAttribute("item", item);

    return "my/my";
  }

}

1. プロセッサの実装

プロセッサではHTMLの要素や属性を操作する処理を実装します。基本的な機能はThymeleafのスタンダードダイアレクトで使われている抽象クラスで実装されているので、これらを継承して必要なプロセッサを開発します。また、必要があればプロセッサ内からリクエストやセッションスコープのオブジェクトへのアクセス、ThymeleafをSpringと併用する場合にはSpringが管理するBeanを使用することもできます。

プロセッサには、属性プロセッサと要素プロセッサがあります。version 2.1.5ではほとんどが属性プロセッサで、要素プロセッサは1つしかありません。

属性プロセッサ

DOMの属性として使う、例えば下記のようなth:ifなどです。

<div th:if="${price} gt 10000" th:remove="tag">
  ...何かの処理...
</div>

要素プロセッサ

それ自体をDOMの要素として扱います。いまのところth:blockしかありません。

<th:block th:if="${price} gt 10000">
  ...何かの処理...
</th:block>

属性プロセッサの実装例

AbstractConditionalVisibilityAttrProcessor

AbstractConditionalVisibilityAttrProcessorを継承するとth:ifと同じような機能を持つ属性プロセッサを実装することができます。
オーバーライドするメソッドで重要なのはisVisibleです。isVisibleメソッドの戻り値で要素の表示を制御します。trueを返せば自身の要素と子要素を表示し、falseを返せば表示しません。

サンプルコード
MyIfAttrProcessor
public class MyIfAttrProcessor extends AbstractConditionalVisibilityAttrProcessor {
  private static final String ATTR_NAME = "if";
  private static final int ATTR_PRECEDENCE = 1000;

  public MyIfAttrProcessor() {
    super(ATTR_NAME);
  }

  @Override
  public int getPrecedence() {
    return ATTR_PRECEDENCE;
  }

  @Override
  protected boolean isVisible(Arguments arguments, Element element, String attributeName) {
    // ...オーバーライドします...
  }

}

式を評価する

属性に指定された式を評価します。
式はプロセッサ内から文字列として取得できるので、それをパーサーで評価します。

テンプレート
<div my:if="${item.remaining gt 10}">
  <p>trueなら表示される</p>
</div>
@Override
protected boolean isVisible(Arguments arguments, Element element, String attributeName) {

  final String attributeValue = element.getAttributeValue(attributeName);
  System.out.println(attributeValue);
  // → ${item.remaining gt 10}

  final Configuration configuration = arguments.getConfiguration();
  final IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration);
  final IStandardExpression expression = parser.parseExpression(configuration, arguments, attributeValue);

  final Boolean result = (Boolean) expression.execute(configuration, arguments);
  System.out.println(result);
  // → true

  return result;
}
レンダリング
<div>
  <p>trueなら表示される</p>
</div>

オブジェクトを扱う

属性にオブジェクトが指定された場合でも、パーサーで評価すればそのオブジェクトを取得することができます。

テンプレート
<div my:if="${item}">
  <p>trueなら表示される</p>
</div>
@Override
protected boolean isVisible(Arguments arguments, Element element, String attributeName) {

  final String attributeValue = element.getAttributeValue(attributeName);
  System.out.println(attributeValue);
  // → ${item}

  // ...省略...

  final ItemModel item = (ItemModel) expression.execute(configuration, arguments);
  System.out.println(item.toString());
  // → ItemModel [id=1, name=うまい棒, price=10, remaining=50, imageUrl=/path/to/image/umaibou.png]

  return item.getRemaining() > 10;
}
レンダリング
<div>
  <p>trueなら表示される</p>
</div>

HttpServletRequest、HttpServletResponse、HttpSessionを扱う

プロセッサ内からHttpServletRequestHttpServletResponseHttpSessionを扱うことができます。

@Override
protected boolean isVisible(Arguments arguments, Element element, String attributeName) {
  // ...省略...

  final IContext context = arguments.getContext();

  final SpringWebContext springWebContext = (SpringWebContext) context;
  final HttpServletRequest request = springWebContext.getHttpServletRequest();
  final HttpServletResponse response = springWebContext.getHttpServletResponse();

  final HttpSession session = springWebContext.getHttpSession();
  UserModel user = (UserModel) session.getAttribute("user");
  System.out.println(user.toString());
  // → User [id=100, name=rubytomato]

  // ...省略...
}

ThymeleafをSpringと併用しない場合は下記のコードになります。

Springと併用していない場合はこちら
final IWebContext webContext = (IWebContext) context;
final HttpServletRequest request = webContext.getHttpServletRequest();
final HttpServletResponse response = webContext.getHttpServletResponse();

SpringのApplicationContextを参照する

ThymeleafをSpringと併用している場合は、SpringのApplicationContextのインスタンスを参照することができます。

@Override
protected boolean isVisible(Arguments arguments, Element element, String attributeName) {
  // ...省略...

  final IContext context = arguments.getContext();

  final SpringWebContext springWebContext = (SpringWebContext) context;
  final ApplicationContext applicationContext = springWebContext.getApplicationContext();

  // ...省略...
}

他の属性値を取得する

同じ要素の他の属性の値も取得できます。

<div my:if="${item.remaining gt 10}" data-hoge="fuga">
 <p>trueなら表示される</p>
</div>
final String hoge = element.getAttributeValue("data-hoge");
System.out.println("hoge:" + hoge);
// → fuga
AbstractSingleAttributeModifierAttrProcessor

AbstractSingleAttributeModifierAttrProcessorを継承するとth:srcと同じような機能を持つ属性プロセッサを実装することができます。
オーバーライドするメソッドで重要なのはgetTargetAttributeNamegetTargetAttributeValueです。
getTargetAttributeNameメソッドの戻り値で値を設定する属性を指定します。
getTargetAttributeValueメソッドの戻り値が指定した属性へセットする値になります。

サンプルコード
MySrcAttrProcessor
public class MySrcAttrProcessor extends AbstractSingleAttributeModifierAttrProcessor {
  private static final String ATTR_NAME = "src";
  private static final int ATTR_PRECEDENCE = 1000;

  public MySrcAttrProcessor() {
    super(ATTR_NAME);
  }

  @Override
  public int getPrecedence() {
    return ATTR_PRECEDENCE;
  }

  @Override
  protected String getTargetAttributeName(Arguments arguments, Element element, String attributeName) {
    // 通常はプロセッサの属性名と同じにします。
    return ATTR_NAME;
  }

  @Override
  protected String getTargetAttributeValue(Arguments arguments, Element element, String attributeName) {
    // ...オーバーライドします...
  }

  @Override
  protected ModificationType getModificationType(Arguments arguments, Element element, String attributeName, String newAttributeName) {
    // 属性値の設定方法を指定します。
    return ModificationType.SUBSTITUTION;
  }

  @Override
  protected boolean removeAttributeIfEmpty(Arguments arguments, Element element, String attributeName, String newAttributeName) {
    // 属性にセットする値が空の場合に属性を削除するか
    return true;
  }

  @Override
  protected boolean recomputeProcessorsAfterExecution(Arguments arguments, Element element, String attributeName) {
    // 用途不明です。
    return false;
  }

}

オブジェクトを扱う

プロセッサでできることは上記のmy:ifと同じです。
この例では、属性に指定したItemModelのインスタンスのimageUrlフィールドがnullの場合に代替URLを、nullでない場合にimageUrlの値を返します。

テンプレート
<img my:src="${item}" />
@Override
protected String getTargetAttributeValue(Arguments arguments, Element element, String attributeName) {

  final String attributeValue = element.getAttributeValue(attributeName);
  System.out.println("attribute:" + attributeValue);
  // → ${item}

  final Configuration configuration = arguments.getConfiguration();
  final IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration);

  final IStandardExpression expression = parser.parseExpression(configuration, arguments, attributeValue);
  final ItemModel item = (ItemModel) expression.execute(configuration, arguments);
  System.out.println("request item:" + item.toString());
  // → ItemModel [id=1, name=うまい棒, price=10, remaining=50, imageUrl=/path/to/image/umaibou.png]

  return StringUtils.isEmpty(item.getImageUrl()) ? "/path/to/image/noimage.png" : item.getImageUrl();
}
レンダリング
<img src="/path/to/image/umaibou.png">

属性値の設定方法を指定する

getModificationTypeメソッドの戻り値で、属性値の設定方法を選択します。返せる値はModificationTypeというEnumで定義されています。

VALUE 実行内容
SUBSTITUTION 指定する属性の値を置き換える
APPEND 指定する属性の値の末尾に加える
APPEND_WITH_SPACE APPENDを空白区切りで行う
PREPEND 指定する属性の値の先頭に加える
PREPEND_WITH_SPACE PREPENDを空白区切りで行う

要素プロセッサの実装例

できることは属性プロセッサと変わりませんが、属性プロセッサと違って属性を必要としませんのでいく分かテンプレート上はすっきりします。

AbstractConditionalVisibilityElementProcessor

AbstractConditionalVisibilityElementProcessorを継承するとth:ifと同じように条件によって内部の要素を表示するか制御することができます。
オーバーライドするメソッドで重要なのは属性プロセッサと同じでisVisibleです。

サンプルコード
MyIfElementProcessor
public class MyIfElementProcessor extends AbstractConditionalVisibilityElementProcessor {
  private static final String ELEMENT_NAME = "if";
  private static final int PRECEDENCE = 1000;

  public MyIfElementProcessor() {
    super(ELEMENT_NAME);
  }

  @Override
  public int getPrecedence() {
    return PRECEDENCE;
  }

  @Override
  protected boolean isVisible(Arguments arguments, Element element) {
    // ...オーバーライドします...
  }

  @Override
  protected boolean removeHostElementIfVisible(Arguments arguments, Element element) {
    // 通常は独自の要素を削除するのでtrueを返します
    return true;
  }

}

オブジェクトを扱う

属性プロセッサで説明したmy:ifを要素プロセッサで書き換える例です。

テンプレート
<my:if>
<div>
 <p>trueなら表示される</p>
</div>
</my:if>
@Override
protected boolean isVisible(Arguments arguments, Element element) {
  final IContext context = arguments.getContext();

  final SpringWebContext springWebContext = (SpringWebContext) context;

  final HttpServletRequest request = springWebContext.getHttpServletRequest();
  final ItemModel item = (ItemModel) request.getAttribute("item");
  System.out.println(item.toString());
  // → ItemModel [id=1, name=うまい棒, price=10, remaining=50, imageUrl=/path/to/image/umaibou.png]

  return item.getRemaining() > 10;
}
レンダリング
<div>
 <p>trueなら表示される</p>
</div>

要素を出力する

プロセッサで任意の要素を出力させることができます。(属性プロセッサでは触れていませんが属性プロセッサでもできます。)
(多用するとThymeleafの良さを削ぐことになるので使いどころをよく検討する必要があると思います。)

テンプレート
<my:if />
@Override
protected boolean isVisible(Arguments arguments, Element element) {
  final IContext context = arguments.getContext();

  final SpringWebContext springWebContext = (SpringWebContext) context;

  final HttpServletRequest request = springWebContext.getHttpServletRequest();
  final ItemModel item = (ItemModel) request.getAttribute("item");
  System.out.println(item.toString());
  // → ItemModel [id=1, name=うまい棒, price=10, remaining=50, imageUrl=/path/to/image/umaibou.png]

  boolean isVisible = item.getRemaining() > 10;

  if (isVisible) {
    Element pEle = new Element("p");
    pEle.addChild(new Text("trueなら表示される"));
    Element divEle = new Element("div");
    divEle.addChild(pEle);
    element.getParent().insertBefore(element, divEle);
  }

  return isVisible;
}
レンダリング
<div><p>trueなら表示される</p></div>

2. ダイアレクトの実装

用意されている抽象クラスAbstractDialectを継承して独自のダイアレクトを実装します。
ダイアレクトで行うことは、実装したプロセッサのインスタンスを生成することと、このダイアレクトのprefixの指定です。
prefixはプロセッサのネームスペースの役割を果たします。ちなみにスタンダードダイアレクトのprefixは"th"です。

public class MyDialect extends AbstractDialect {
  private static final String PREFIX = "my";
  private static final Set<IProcessor> PROCESSORS;

  static {
    Set<IProcessor> tmp = new HashSet<>();
    tmp.add(new MyIfAttrProcessor());
    tmp.add(new MySrcAttrProcessor());
    tmp.add(new MyIfElementProcessor());
    PROCESSORS = Collections.unmodifiableSet(tmp);
  }

  @Override
  public String getPrefix() {
    return PREFIX;
  }

  @Override
  public boolean isLenient() {
    return false;
  }

  @Override
  public Set<IProcessor> getProcessors() {
    return PROCESSORS;
  }

}

3. 設定の実装

実装したダイアレクトを有効にするために下記のコードで有効化します。

@Configuration
public class MyDialaectConfigurer {

  // 独自ダイアレクト
  @Bean
  MyDialect myDialect() {
    return new MyDialect();
  }

}

若しくは

@SpringBootApplication
public class App {

  public static void main( String[] args ) {
    SpringApplication.run(App.class, args);
  }

  // 独自ダイアレクト
  @Bean
  MyDialect myDialect() {
    return new MyDialect();
  }

}

以上で独自のダイアレクトとプロセッサの実装方法の説明は終了です。

独自のユーティリティオブジェクトを実装する

おまけです。
実装方法は、カスタム Utility Object を追加する ー Thymeleafという記事の通りです。

実装方法

  1. ユーティリティオブジェクトの実装
  2. ダイアレクトの実装

ユーティリティオブジェクトの実装

ViewHelper
public interface ViewHelper {
  public String hello(String message);
}
ViewHelperImpl
@Component
public class ViewHelperImpl implements ViewHelper {

  @Autowired
  MessageSource messageSource;

  @Override
  public String hello(String message) {
    return messageSource.getMessage("message.text1", new Object[]{message}, Locale.getDefault());
  }

}

ダイアレクトの実装

独自のダイアレクトクラスにIExpressionEnhancingDialectインターフェースを実装します。

public class MyDialect extends AbstractDialect implements IExpressionEnhancingDialect {

  // ...省略...

  @Override
  public Map<String, Object> getAdditionalExpressionObjects(IProcessingContext processingContext) {
    final SpringWebContext springWebContext = (SpringWebContext) processingContext.getContext();
    final ApplicationContext applicationContext = springWebContext.getApplicationContext();

    ViewHelper viewHelper = applicationContext.getBean(ViewHelper.class);

    Map<String, Object> tmp = new HashMap<>();
    tmp.put("vh", viewHelper);

    return Collections.unmodifiableMap(tmp);
  }

}

メッセージリソースファイル

message_ja.properties
message.text1 = こんにちは {0}.
message.properties
message.text1 = hello {0}.

テンプレート

テンプレート
<p th:text="${#vh.hello(user.name)}"></p>
レンダリング
<p>こんにちは rubytomato.</p>

補足資料

thymeleaf 2.1.5.RELEASE

Dialect

PREFIX Class
th AbstractDialect
  └ AbstractXHTMLEnabledDialect
      └ StandardDialect

Processor

Attribute一覧
ATTR
NAME
ATTR
PRECEDENCE
Class
assert 1550 AbstractAssertionAttrProcessor
  └ AbstractStandardAssertionAttrProcessor
      └ StandardAssertAttrProcessor
inline 1000 AbstractAttrProcessor
  └ AbstractStandardTextInlinerAttrProcessor
      └ StandardInlineAttrProcessor
attr 700 AbstractAttributeModifierAttrProcessor
  └ AbstractStandardAttributeModifierAttrProcessor
      └ StandardAttrAttrProcessor
attrappend 900 AbstractAttributeModifierAttrProcessor
  └ AbstractStandardAttributeModifierAttrProcessor
      └ StandardAttrappendAttrProcessor
attrprepend 800 AbstractAttributeModifierAttrProcessor
  └ AbstractStandardAttributeModifierAttrProcessor
      └ StandardAttrprependAttrProcessor
alt-title 990 AbstractAttributeModifierAttrProcessor
  └ AbstractStandardSingleValueMultipleAttributeModifierAttrProcessor
      └ StandardAltTitleAttrProcessor
lang-xmllang 990 AbstractAttributeModifierAttrProcessor
  └ AbstractStandardSingleValueMultipleAttributeModifierAttrProcessor
      └ StandardLangXmlLangAttrProcessor
async... 1000 AbstractConditionalFixedValueAttrProcessor
  └ AbstractStandardConditionalFixedValueAttrProcessor
      └ StandardConditionalFixedValueAttrProcessor
case 275 AbstractConditionalVisibilityAttrProcessor
  └ AbstractStandardCaseAttrProcessor
      └ StandardCaseAttrProcessor
if 300 AbstractConditionalVisibilityAttrProcessor
  └ AbstractStandardConditionalVisibilityAttrProcessor
      └ StandardIfAttrProcessor
unless 400 AbstractConditionalVisibilityAttrProcessor
  └ AbstractStandardConditionalVisibilityAttrProcessor
      └ StandardUnlessAttrProcessor
include 100 AbstractFragmentHandlingAttrProcessor
  └ AbstractStandardFragmentHandlingAttrProcessor
      └ StandardIncludeFragmentAttrProcessor
replace 100 AbstractFragmentHandlingAttrProcessor
  └ AbstractStandardFragmentHandlingAttrProcessor
      └ StandardReplaceFragmentAttrProcessor
substituteby 100 AbstractFragmentHandlingAttrProcessor
  └ AbstractStandardFragmentHandlingAttrProcessor
      └ StandardSubstituteByFragmentAttrProcessor
each 200 AbstractIterationAttrProcessor
  └ AbstractStandardIterationAttrProcessor
      └ StandardEachAttrProcessor
with 600 AbstractLocalVariableDefinitionAttrProcessor
  └ AbstractStandardLocalVariableDefinitionAttrProcessor
      └ StandardWithAttrProcessor
switch 250 AbstractLocalVariableDefinitionAttrProcessor
  └ AbstractStandardSwitchStructureAttrProcessor
      └ StandardSwitchAttrProcessor
remove 1600 AbstractMarkupRemovalAttrProcessor
  └ StandardRemoveAttrProcessor
fragment 1500 AbstractNoOpAttrProcessor
  └ StandardFragmentAttrProcessor
object 500 AbstractSelectionTargetAttrProcessor
  └ AbstractStandardSelectionAttrProcessor
      └ StandardObjectAttrProcessor
action 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardActionAttrProcessor
classappend 1100 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardClassappendAttrProcessor
onabort... 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardDOMEventAttributeModifierAttrProcessor
href 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardHrefAttrProcessor
method 990 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardMethodAttrProcessor
name... 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardSingleNonRemovableAttributeModifierAttrProcessor
abbr... 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardSingleRemovableAttributeModifierAttrProcessor
src 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardSrcAttrProcessor
styleappend 1100 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardStyleappendAttrProcessor
value 1010 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardValueAttrProcessor
xmlbase 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardXmlBaseAttrProcessor
xmllang 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardXmlLangAttrProcessor
xmlspace 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ StandardXmlSpaceAttrProcessor
text 1300 AbstractTextChildModifierAttrProcessor
  └ AbstractStandardTextChildModifierAttrProcessor
      └ StandardTextAttrProcessor
utext 1400 AbstractUnescapedTextChildModifierAttrProcessor
  └ AbstractStandardUnescapedTextChildModifierAttrProcessor
      └ StandardUtextAttrProcessor
block 100000 AbstractNoOpElementProcessor
  └ StandardBlockElementProcessor
100 AbstractTextNodeProcessor
  └ StandardTextInliningTextProcessor

thymeleaf-spring4 2.1.5.RELEASE

Dialect

PREFIX Class
th AbstractDialect
  └ AbstractXHTMLEnabledDialect
      └ StandardDialect
          └ SpringStandardDialect

Processor

Attribute一覧
ATTR
NAME
ATTR
PRECEDENCE
Class
field 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
checkbox 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
      └ SpringInputCheckboxFieldAttrProcessor
file 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
      └ SpringInputFileFieldAttrProcessor
text... 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
      └ SpringInputGeneralFieldAttrProcessor
password 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
      └ SpringInputPasswordFieldAttrProcessor
radio 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
      └ SpringInputRadioFieldAttrProcessor
option 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
      └ SpringOptionFieldAttrProcessor
select 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
      └ SpringSelectFieldAttrProcessor
textarea 1200 AbstractAttrProcessor
  └ AbstractSpringFieldAttrProcessor
      └ SpringTextareaFieldAttrProcessor
action 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ SpringActionAttrProcessor
errorclass 1500 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ SpringErrorClassAttrProcessor
method 990 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ SpringMethodAttrProcessor
src 1000 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ SpringSrcAttrProcessor
value 1010 AbstractSingleAttributeModifierAttrProcessor
  └ AbstractStandardSingleAttributeModifierAttrProcessor
      └ SpringValueAttrProcessor
errors 1200 AbstractAttrProcessor
  └ AbstractStandardTextInlinerAttrProcessor
      └ SpringErrorsAttrProcessor
object 500 AbstractSelectionTargetAttrProcessor
  └ AbstractStandardSelectionAttrProcessor
      └ SpringObjectAttrProcessor
8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9