###前提・実現したいこと
Spring Bootで、画面入力値を加工(大文字化等)したい。
###発生している問題・エラーメッセージ
・現在の状態
1.AOPでsetterに渡す文字列を事前に加工した。文字列は、StringBuiderを使用。
2.同時にバリデーションを掛けている。(@NotEmpty等)
・問題
1.は成功したが、2.が必ずエラーとなる。
しかし、form.getXxx()の返り値は大文字化された値が返される。
・聞きたいこと
(1)上記AOPとバリデーションの二律背反を回避することは、可能か?
(2)回避不可の場合、より簡単で、なるべくコードが分散しない方法はありますか?
AOPを止め、独自バリデーションで、文字列加工する方法を試行し、所期の結果を得られることを確認済みですが、全メンバーに付与するのが難点なので、よりよい方法があれば、ご教授いただきたい。
###該当のソースコード
Java
1@Controller 2@RequestMapping("/test01") 3public class Test01 { 4 @PostMapping() 5 public ModelAndView procPost(@Validated @ModelAttribute("contentsForm") Test01Form form, 6 BindingResult result, 7 ModelAndView mav) { 8 // form.getItem01()は、入力値が大文字変換された値が返される。 9 mav.setViewName("test01"); 10 return mav; 11 } 12} 13 14@Component 15@Data 16public class Test01Form { 17 // 必ずエラーとなる 18 @NotEmpty 19 StringBuilder item01; 20 21 @NotEmpty 22 StringBuilder item02; 23} 24 25 26@Aspect 27@Component 28public class TestAOP { 29 @Around("execution (* com.example.demo.*.setItem*(..))") 30 public void around(ProceedingJoinPoint pjp) { 31 // 入力値を大文字に変換する。 32 Object[] args = pjp.getArgs(); 33 StringBuilder sb = (StringBuilder) args[0]; 34 String val = sb.toString().toUpperCase(); 35 sb.delete(0, sb.length()); 36 sb.append(val); 37 args[0] = sb; 38 try { 39 pjp.proceed(args); 40 } catch (Throwable e) { 41 e.printStackTrace(); 42 } 43 } 44} 45
html
1 2 <form th:action="@{/test01}" th:method="post" th:object="${contentsForm}"> 3 <span>Item01:</span> 4 <input th:type="text" th:field="*{item01}" /> 5 <label th:if="${#fields.hasErrors('*{item01}')}" th:errors="*{item01}">×</label> 6 <br /> 7 <span>Item02:</span> 8 <input th:type="text" th:field="*{item02}" /> 9 <label th:if="${#fields.hasErrors('*{item02}')}" th:errors="*{item02}">×</label> 10 <br /> 11 <input th:type="submit" th:value="@{実行}" /> 12 </form> 13
###試したこと
eclipseで変数を調査した結果から、以下が原因と思われます。
フォームクラスは、AOPを適用したことで、ラッピングされており、メンバー変数は、ずべてnullであったが、内部に、元のフォームクラス(メンバー変数値は正常)を保持しており、form.getXxx()を実行すると、元のフォームクラスの値を返している。
しかし、バリデーションは、ラッピングクラスのメンバー変数を直接?参照してしまい、結果として、未入力と判断されていると思われる。
###補足情報(言語/FW/ツール等のバージョンなど)
Spring Bootバージョン 1.5.3
Test01#procPostで止めて、変数タブでformを選択した状態:
form Test01Form$$EnhancerBySpringCGLIB$$6956de2b (id=124)
Test01Form(item01=ABCDE, item02=2)
見た目では、正常に値が設定されているように見える。
formのツリーを開いた状態:
form Test01Form$$EnhancerBySpringCGLIB$$6956de2b (id=124)
CGLIB$BOUND false
CGLIB$CALLBACK_0 CglibAopProxy$DynamicAdvisedInterceptor (id=186)
CGLIB$CALLBACK_1 CglibAopProxy$StaticUnadvisedInterceptor (id=189)
CGLIB$CALLBACK_2 CglibAopProxy$SerializableNoOp (id=191)
CGLIB$CALLBACK_3 CglibAopProxy$StaticDispatcher (id=193)
CGLIB$CALLBACK_4 CglibAopProxy$AdvisedDispatcher (id=196)
CGLIB$CALLBACK_5 CglibAopProxy$EqualsInterceptor (id=199)
CGLIB$CALLBACK_6 CglibAopProxy$HashCodeInterceptor (id=201)
item01 null
item02 null
id=124はラッピングされたインスタンスと思われる。
そのメンバー変数(item01, item02)は、null。
さらに、CGLIB$CALLBACK_0等を、開いた状態:
targetSource SingletonTargetSource (id=186)
target Test01Form (id=109)
item01 StringBuilder (id=309)
item02 StringBuilder (id=310)
id=109のTest01Formが、本来のフォームクラスのインスタンスと思われます。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/12/04 00:22