やっぱり一々getter作るのは、書くのも読むのも面倒だよね。
ということで、publicフィールドで行く方向で考えます。
要するにリクエストパラメータのセットから特定のフィールドを除外してやれば良いわけです。
「特定のフィールド」を指定するにはやはりアノテーションが良いでしょう。
以下のアノテーションを作成します。
| 1 | @Target(ElementType.FIELD) |
|---|---|
| 2 | @Retention(RetentionPolicy.RUNTIME) |
| 3 | public @interface Readonly |
| 4 | { |
| 5 | } |
リクエストパラメータのセットはS2RequestProcessorで行っているので、これを改造してしまいます。
| 1 | public class RequestProcessor extends S2RequestProcessor |
|---|---|
| 2 | { |
| 3 | @SuppressWarnings({"unchecked", "rawtypes"}) |
| 4 | @Override |
| 5 | protected void setSimpleProperty(Object bean, String name, Object value) |
| 6 | { |
| 7 | if (bean instanceof Map) |
| 8 | { |
| 9 | setMapProperty((Map)bean, name, value); |
| 10 | return; |
| 11 | } |
| 12 | |
| 13 | BeanDesc beanDesc = BeanDescFactory.getBeanDesc(bean.getClass()); |
| 14 | if (!beanDesc.hasPropertyDesc(name)) |
| 15 | return; |
| 16 | |
| 17 | PropertyDesc pd = beanDesc.getPropertyDesc(name); |
| 18 | if (!pd.isWritable()) |
| 19 | return; |
| 20 | |
| 21 | // @Readonlyアノテーションが有ったらセットしない |
| 22 | Field f = pd.getField(); |
| 23 | if (f != null && f.getAnnotation(Readonly.class) != null) |
| 24 | return; |
| 25 | |
| 26 | if (pd.getPropertyType().isArray()) |
| 27 | pd.setValue(bean, value); |
| 28 | else if (List.class.isAssignableFrom(pd.getPropertyType())) |
| 29 | { |
| 30 | List<String> list = ModifierUtil.isAbstract(pd.getPropertyType()) ? new ArrayList<String>() : (List<String>)ClassUtil.newInstance(pd.getPropertyType()); |
| 31 | list.addAll(Arrays.asList((String[]) value)); |
| 32 | pd.setValue(bean, list); |
| 33 | } |
| 34 | else if (value == null) |
| 35 | pd.setValue(bean, null); |
| 36 | else if (value instanceof String[]) |
| 37 | { |
| 38 | String[] values = (String[]) value; |
| 39 | pd.setValue(bean, values.length > 0 ? values[0] : null); |
| 40 | } |
| 41 | else |
| 42 | pd.setValue(bean, value); |
| 43 | } |
| 44 | } |
struts-config.xmlを書き換えてセットします。
<controller
maxFileSize="1024K"
bufferSize="1024"
processorClass="jp.ku6.seasar.struts.action.RequestProcessor"
multipartClass="org.seasar.struts.upload.S2MultipartRequestHandler"/>使い方は、publicなフィールドに@Readonlyを付けるだけです。
| 1 | @Readonly |
|---|---|
| 2 | public List<Homu> homus; |
あと、publicにするとAutoBindingの対象になるので、一応ActionのAutoBindingDefを変更してみました。
<component name="actionCreator" class="org.seasar.framework.container.creator.ActionCreator"> <initMethod name="setAutoBindingDef"> <arg>@org.seasar.framework.container.assembler.AutoBindingDefFactory@SEMIAUTO</arg> </initMethod> </component>
別に対象になっても実際に設定されることはまず無いとは思うのですが、
どうせ設定したい物には明示的に@Resourceを付けるので一応やっておくかなと。
何かだめなところが見つかるまではこれで行ってみます。