struts2 / Freemarkerでpublicフィールドを参照できるようにする
Freemarkerでは通常getterを見るようになっていてpublicフィールドは参照しません。
ちなみにこれは
${hoge.hoge1}
みたいな場合で
<@s.property value="hoge.hoge1"/>
のようにすればpublicフィールドも参照可能です。(これはfreemarkerではなくstruts2のValueStackを使っているため)
なので、フィールドはprivateにしてgetter/setterを使うというのが正攻法だと思います。
ただ、好みの問題ではありますがpublicフィールドを使っているところもあります。
そのほうがコードとしてはシンプルです。
S2JDBCなんかもpublicフィールドにしています。
なので、publicフィールドも使えると便利です。
いくつか見つけた中では、
http://d.hatena.ne.jp/colun/20100102
これは一般論なので、そのままstruts2で使うわけにはいきません。
http://d.hatena.ne.jp/runfor/20090911
これはライブラリをそのまま書き換えてます。
stuts2のバージョンアップとかが面倒になるので、あまりやりたくないです。
提案したい方法は次のとおりです。
上のリンク先にあるように、やることとしては簡単に言うと
ObjectWrapper#setExposeFields(true);
とするだけです。
- ライブラリ内のプログラムを継承して上書き
- 設定で新しく作ったクラスを使うように変更
FreemarkerManagerを上書きする場合
クラス作成(MyFreemarkerManager)
package kamegu.common.freemarker; import javax.servlet.ServletContext; import org.apache.struts2.views.freemarker.FreemarkerManager; import freemarker.ext.beans.BeansWrapper; import freemarker.template.ObjectWrapper; public class MyFreemarkerManager extends FreemarkerManager { protected ObjectWrapper createObjectWrapper(ServletContext servletContext) { ObjectWrapper wrapper = super.createObjectWrapper(servletContext); ((BeansWrapper) wrapper).setExposeFields(true); return wrapper; } }
(省略) <constant name="struts.freemarker.manager.classname" value="kamegu.common.freemarker.MyFreemarkerManager"/> (省略)
FreemarkerResultを上書きする場合
クラス作成(MyFreemarkerResult)
package kamegu.common.freemarker; import org.apache.struts2.views.freemarker.FreemarkerResult; import freemarker.ext.beans.BeansWrapper; import freemarker.template.ObjectWrapper; public class MyFreemarkerResult extends FreemarkerResult { protected ObjectWrapper getObjectWrapper() { ObjectWrapper wrapper = super.getObjectWrapper(); ((BeansWrapper) wrapper).setExposeFields(true); return wrapper; } }
(省略) <package ~~~~~> <result-types> <result-type name="freemarker" class="kamegu.common.freemarker.MyFreemarkerResult"/> </result-types> (省略)