web-dev-qa-db-ja.com

Spring 3MVC単一のコントローラーで複数のフォーム送信を処理

Spring 3MVCコントローラーを使用して複数のフォーム送信を処理します。

複数のフォームでJSPページを開発しています。 1)顧客の検索、2)製品の検索、3)何かの印刷など。各フォームに関連付けられた異なるフォームバインドオブジェクトがあり、コントローラーコードは次のようになります。

  @Controller
  @RequestMapping(value="/search.do")
  public class SearchController {

    @RequestMapping(method = RequestMethod.GET)
    public String pageLoad(ModelMap modelMap) {
      modelMap.addAttribute("productSearch", new ProductSearchCriteria());
        modelMap.addAttribute("customerSearch", new CustomerSearchCriteria());
        modelMap.addAttribute("print", new PrintForm());
    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView searchProducts(@ModelAttribute("productSearch") ProductSearchCriteria productSearchCriteria,
            BindingResult result, SessionStatus status) {
            //Do Product search
            return modelAndView;
    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView searchCustomers(@ModelAttribute("customerSearch") CustomerSearchCriteria customerSearchCriteria,
            BindingResult result, SessionStatus status) {
            //Do Customer search
            return modelAndView;
    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView printSomething(@ModelAttribute("print") PrintForm printForm,
            BindingResult result, SessionStatus status) {
            //Print something
            return modelAndView;
    }
  }

上記は確かに私が思っていたようには機能しません。例外が発生します 'リクエストメソッド' POST 'はサポートされていません'。上記のコントローラー内にPOSTメソッドが1つしかない場合は、searchProductsと言ってください。ただし、POSTで複数のメソッドを使用することはできません。また、JSPに非表示パラメーターを追加し、メソッドシグネチャを変更してみました。以下と同様ですが、同じ例外が再度発生します。

  @RequestMapping(method = RequestMethod.POST, params="pageAction=searchProduct")
    public ModelAndView searchProducts(@ModelAttribute("productSearch") ProductSearchCriteria productSearchCriteria,
            BindingResult result, SessionStatus status) {
            //Do Product search
            return modelAndView;
   }

誰かが上記を達成するための正しい方法を提案できますか?また、ソース資料への参照またはさらなる読み物は大歓迎です。ありがとう。

編集#1: params = "pageAction = searchProduct"を使用した上記のアプローチは、JSPで非表示のパラメーターを正しく取得する限り、完全に機能します(以下のコメントを参照)。それに加えて、@ Bozhoと@BijuKunjummenによる回答も非常に役立ち、複数のフォーム送信に取り組むための優れた(おそらくより良い?)代替手段です。

8
TMan

マッピングは完全に正しくありません@TMan:

  1. Web.xmlのマッピングは、SpringDispatcherサーブレットにリクエストを処理させるためのものです。あなたの場合のように:

    <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/META-INF/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    

    appServlet * .doしたがって、.doで終わるURIへのリクエストは、SpringのDispatcherServletによって処理されるようになりました。

  2. あなたの場合のように、コントローラーはマッピングを持つことができます:

    @Controller @RequestMapping(value = "/ search.do")

しかし、間違っているのは、コントローラーのRequestMappingです。

@Controller
@RequestMapping(value="/search")

RequestMappingの最後にある.doは、純粋にDispatcherサーブレットが呼び出されるためのものであるため、そこにあるべきではありません。呼び出されると、正しいControllerメソッドへのディスパッチが処理されるため、/ search.doの呼び出しは終了します。コントローラーで。

  1. これで、各メソッドに、あなたの場合のようにRequestMappingで注釈を付けることができ、RequestMappingのRequestMethod属性を使用して、POSTまたはGET:の場合にメソッドにディスパッチするかどうかを指定します。

    @RequestMapping(method = RequestMethod.GET)
    @RequestMapping(method = RequestMethod.POST)
    

したがって、/ search.doURIにPOSTがある場合、適切なメソッドが呼び出されます。

あなたの場合、RequestMethod.POST属性でアノテーションが付けられた複数のメソッドがあるため、SpringのAnnotationMethodHandlerAdapterコンポーネントは単にどのメソッドにディスパッチするかを知りません。

できることがいくつかあります。

  1. @Bozhoによって提案された方法で各メソッドのリクエストマッピングを配置します:@RequestMapping(value = "/ Customers" method = Request.POST)@RequestMapping(value = "/ products" method = Request.POST)これで、リクエストURIはだろう

    /search/customers.do/search/products.doを実行すると、正しいディスパッチ方法を取得するためにPOSTを実行する必要があります。

  2. Method = Request.POSTをすべて一緒に取り除き、上記のように@RequestMappingに依存して正しいメソッドを見つけます。

  3. オプションのparams属性をRequestMappingに渡すことができます。これも、Springがディスパッチする正しいメソッドを見つけるのに役立つ方法です。

    @RequestMapping(method = Request.POST、params = "customers")

リクエストに顧客パラメータを含めるか、リクエストに製品パラメータを言います。

ただし、最も単純なのはオプション1です。

編集1:優れたSpringドキュメントへの参照を追加する http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html

12
Biju Kunjummen

複数のフォームがある場合、3つのフォームを異なるURLにマップしてみませんか?

@RequestMapping("/products")
public ModelAndView searchProducts(..)

@RequestMapping("/customers")
public ModelAndView searchCustomers(..)

そして、フォームのアクションを/search/products/search/customersに向けてもらいます(.doは必要ありません)

5
Bozho

同じ問題が発生しました。同じページに2つの送信ボタンがある2つのフォーム(登録と連絡先)です。各フォームには、Springによる独自の検証があります。

私は1つのコントローラーでこれを行うことができました:

@RequestMapping(value = "/contactOrRegister.do", method = RequestMethod.GET)
public void contactOrRegisterFormGet(@ModelAttribute("contactForm") ContactForm contactForm, @ModelAttribute("registerForm") RegisterForm registerForm) {
    //-----prepare forms for displaying here----
}

@RequestMapping(value = "/contact.do", method = RequestMethod.POST)
public String contactFormPost(@ModelAttribute("contactForm") ContactForm contactForm, BindingResult result, final Model model) {        
    contactValidator.validate(contactForm, result);
    if (result.hasErrors()) {
        model.addAttribute("registerForm", new RegisterForm());
        return "contactOrRegister";
    }
    //--- validation is passed, do submit for contact form here ---
}

@RequestMapping(value = "/register.do", method = RequestMethod.POST)
public String registerFormPost(@ModelAttribute("registerForm") RegisterForm registerForm, BindingResult result, final Model model) {        
    registerValidator.validate(registerForm, result);
    if (result.hasErrors()) {
        model.addAttribute("contactForm", new ContactForm());
        return "contactOrRegister";
    }
    //--- validation is passed, do submit for register form here ---
}

「contactOrRegister」ビューでは両方のフォームを表示する必要があるため、新しいフォーム(連絡先または登録)を作成し、検証が失敗したときにモデルに配置する必要があります。そのため、「お問い合わせ」フォームが送信され、エラーが発生すると、「登録」フォームの内容が消去されます。この方法は私にぴったりです。

ContactOrRegister.jspには、アクションが異なる両方のフォームが含まれています。

 <form:form action="/register.do" modelAttribute="registerForm" method="POST">
    <!-- register form here -->
 </form:form>

 <form:form action="/contact.do" modelAttribute="contactForm" method="POST">
    <!-- contact form here -->
 </form:form>
5
Svetlana

あなたは書ける

@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})

同じコントローラーで複数の方法を使用する場合。これは、ユーザーがGETを使用してデータを送信したい場合や、別のコントローラーからreturn "forward:url";を使用した場合に役立ちます。

2
shreks7