Spring 3 MVC Обработка нескольких форм отправки с одним контроллером - PullRequest
7 голосов
/ 31 января 2011

Spring 3 MVC Обработка нескольких форм отправки с контроллером.

Я занимаюсь разработкой страницы 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 внутри контроллера выше, скажем 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 и @Biju Kunjummen также очень полезны и являются хорошей (возможно, лучшей?) Альтернативой для отправки нескольких форм.

Ответы [ 4 ]

12 голосов
/ 31 января 2011

Ваши отображения не полностью корректны @TMan:

  1. Отображения в web.xml должны получить сервлет Spring Dispatcher для обработки вашего запроса - например.как в вашем случае:

    <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 Так что теперь любой запрос к URI, заканчивающемуся на .do, будет обрабатываться DispatcherServlet Spring

  2. Контроллер может иметь отображение, как в вашем случае:

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

Но где у вас естьНеправильная ошибка в RequestMapping для контроллера:

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

.do в конце RequestMapping не должен быть там, так как он вызывается исключительно для сервлета Dispatcher, после его вызова он будетобработать диспетчеризацию для правильного метода Controller, поэтому ваш вызов /search.do в конечном итоге будет с контроллером.

Теперь каждый метод может быть аннотирован с RequestMapping, как в вашем случае, с атрибутом RequestMethod RequestMapping, указывающим, следует ли отправлять методу в случае POST или GET:

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

Таким образом, при наличии POST для URI /search.do будет вызван соответствующий метод.

В вашем случае существует несколько методов, аннотированных атрибутом RequestMethod.POST, поэтомуAnnotationMethodHandlerAdapter компонент Spring просто не знает, какой метод для отправки.

Есть несколько вещей, которые вы можете сделать:

  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 allвместе и зависит отВ @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

5 голосов
/ 18 августа 2011

У меня была та же проблема: две формы (зарегистрироваться и связаться) на одной странице с двумя кнопками отправки.Каждая форма имеет свою собственную проверку Spring.

Мне удалось сделать это в одном контроллере:

@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 голосов
/ 31 января 2011

Если у вас несколько форм, почему бы вам не сопоставить три формы с разными URL-адресами?

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

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

И ваши действия в форме должны быть направлены на /search/products и /search/customers (не нужно .do)

2 голосов
/ 27 ноября 2012

Вы можете написать

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

при использовании нескольких методов на одном контроллере. Это полезно, когда иногда пользователь хочет отправить данные с помощью GET или когда вы используете return "forward:url"; с другого контроллера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...