web-dev-qa-db-ja.com

SpringのConversionService

私はSpringアプリケーションでこのスキームに従っています。

  1. リクエストは、オブジェクトのIDとこのオブジェクトに入力される他のいくつかのパラメーターとともにサーバーに送信されます
  2. このIDのオブジェクトはデータベースからロードされます
  3. このオブジェクトでゲッターとセッターが呼び出され、値が入力されます
  4. 次にオブジェクトが保存されます

私は尋ねました この他の質問 リクエストのパラメータを入力する前にオブジェクトを準備する最良の方法は何ですか?答えは、@ ModelAtributeアノテーション付きメソッドで使用する代わりに、またはinitBinderのエディターで 変換サービス を使用することでした。

そのため、コンバーターを使用しようとしましたが、同様の例が見つからず、少し行き詰まっています。私は以下のようなコードを書きました:initバインダーに変換サービスを登録します。したがって、Userオブジェクトの値を入力する前に、データベースからオブジェクトをロードするために、convert()メソッドが呼び出されます。問題は、オブジェクトUserのID(ユーザー名フィールド)をオブジェクトユーザーに変換するため、この構成が機能しないことですが、オブジェクトでsetUsername()を作成しようとするため、「Java.lang .IllegalArgumentException:引数の型が一致しません。

誰かが、ConversionServiceを使用して目的の動作を得る方法の手掛かりまたは例を教えてもらえますか?

ありがとう。

@Autowired
private ConversionService conversionService;

@InitBinder("user")
public void initBinder(@RequestParam("username")String username, WebDataBinder binder){
    binder.setConversionService(conversionService);
}

@RequestMapping(value="/user/save", method=RequestMethod.POST)
public String save(@ModelAttribute("user") User user, Model model) {        
    ...
}

次のようなもので:

@Component
public class UserConversionService implements ConversionService{
    ...        
    @Override
    public Object convert(Object name, TypeDescriptor arg1, TypeDescriptor arg2) {
        return userService.find((String)name); 
    }
}
25
Javi

文字列とユーザーオブジェクト間の変換を行うためにConversionServiceを実装しようとしています。ただし、この部分を行うのはConverter実装です。あなたがしたいことは:

  1. コンバーターを書く
  2. そのコンバーターをConversionServiceに登録します。
  3. ConversionServiceを利用します。

あなたのコンバーターは次のようなものです:

final class UserConverter implements Converter<String, User> {
    ...
    public User convert(String username) {
        return userService.find(username);
    }

}

次に、そのコンバーターを登録する必要があります。独自のConversionServiceFactoryBeanを作成するか、デフォルトをオーバーライドできます。

<bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="example.UserConverter"/>
        </list>
    </property>
</bean>

ご存じのとおり、ConversionServiceを明示的に使用したい場合は、自動配線できるもののままにしてください。春とそのファクトリービーンの定義が残りを処理します。

ただし、コンテキストですでに<mvc:annotation-driven>タグを使用している場合は、そのconversion-service属性を使用してConversionServiceFactoryBeanを参照できます。その場合、クラスにInitBinderやConversionServiceを含める必要はまったくありません。@ RequestMappingのパラメーターにターゲットタイプUserを指定するだけで、ユーザーが介入しなくても変換が行われます。

41
GaryF

私はゲイリーが上で言っていることを正確に行い、それはうまくいきました:

ソリューションにいくつかの情報を追加したいと思います。 Springドキュメント here に従って、URIテンプレート変数はConverter/ConversionServiceを使用してターゲットオブジェクトに変換されます。 @RequestParam("id") @ModelAttribute("contact") Contact contactを使用しようとしましたが、ビューedit.jspにモデルオブジェクトcontactがないため、_IllegalStateException: Neither BindingResult nor plain target object for bean name 'contact' available as request attribute_を取得していました。これは、_Model model_およびmodel.addAttribute(contact);を宣言することで簡単に解決できます。ただし、さらに良い方法があります。 URIテンプレート変数を使用します。 _@RequestParam_が機能しない理由は奇妙です。

動作しませんでした

_@RequestMapping("edit") //Passing id as .. edit?id=1
public String editWithConverter(@RequestParam("id") @ModelAttribute("contact") Contact contact){
    logger.info("edit with converter");
     return "contact/edit";
}
_

うまくいった

_@RequestMapping("edit/{contact}") //Passing id as .. edit/1
public String editWithConverter(@PathVariable("contact") @ModelAttribute("contact") Contact contact){ // STS gave a warning for using {contact} without @PathVariable 
    logger.info("edit with converter");
     return "contact/edit";
}
_

つまり、これは何をするのか... _...edit/1_のようなリンクは、暗黙的にString '1'からContact of id '1'への変換を呼び出し、この連絡先オブジェクトをビューに持ってきます。 _@InitBinder_は必要ありません。Converterに登録されているConversionServiceがあるため、これをどこでも使用できます-暗黙的または明示的に

4
Ajay