9

Mam formularz Spring 3 MVC z 2 parametrami Próbuję wysłać do mojej metody kontrolera, a otrzymuję błąd 404. Problem polega na tym, że formularz ma 2 przyciski przesyłania, a kliknięcie przycisku "Wyślij" określa wartość jednego z parametrów. Oto moja forma.Wiosna 3 - formularz z 2 przyciskami, wysyłając 2 parametry do metody kontrolera

<form:form action="/approve/${bulletin.id}" method="post"> 
     <table> 
      <tr> 
       <td colspan="2"><b>From:</b> <c:out value="${bulletin.name}" /></td> 
      </tr> 
      <tr> 
       <td colspan="2"><b>Subject:</b> <c:out 
         value="${bulletin.subject}" /></td> 
      </tr> 
      <tr> 
       <td colspan="2"><b>Date:</b> <c:out value="${bulletin.date}" /> 
        <br></td> 
      </tr> 
      <tr> 
       <td colspan="2"><t:notePrint note="${bulletin.note}" /> <input 
        type="hidden" name="id" value="${bulletin.id}" /></td> 
      </tr> 
      <tr> 
       <td><input type="submit" name="approve" value="Approve" /></td> 
       <td><input type="submit" name="deny" value="Deny" /></td> 
      </tr> 
     </table> 
     <br /> 
    </form:form> 

Oto moja forma kontrolera.

@RequestMapping(value = "/approve/{id}", method = RequestMethod.POST) 
public String approveBulletin(@RequestParam int id, 
     @RequestParam(required = false, value = "approve") String approve, 
     @RequestParam(required = false, value = "deny") String deny, Model model) { 
    try { 
     if (approve.equalsIgnoreCase("approve")) { 
      bulletinDAO.approveBulletin(id); 
      model.addAttribute("approval", 
        "Your bulletin has been approved."); 
     } 
     if (deny.equalsIgnoreCase("deny")) { 
      bulletinDAO.denyBulletin(id); 
      model.addAttribute("approval", "Your bulletin has been denied."); 
     } 

     List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins(); 
     model.addAttribute("bulletins", bulletins); 
    } catch (Exception e) { 
     System.out.println(e.getMessage()); 
     return "FailurePage"; 
    } 

    return "ApproveBulletin"; 
} 

Odpowiedz

15

Rozwiązałem mój własny problem. Publikuję mój kod z korzyścią dla każdego, kto trafi w ten wątek z tym samym problemem. Oto moja forma.

<form:form action="approve" method="post"> 
    <table> 
     <tr> 
      <td colspan="2"><b>From:</b> <c:out value="${bulletin.name}" /></td> 
     </tr> 
     <tr> 
      <td colspan="2"><b>Subject:</b> <c:out 
        value="${bulletin.subject}" /></td> 
     </tr> 
     <tr> 
      <td colspan="2"><b>Date:</b> <c:out value="${bulletin.date}" /> 
       <br></td> 
     </tr> 
     <tr> 
      <td colspan="2"><t:notePrint note="${bulletin.note}" /> <input 
       type="hidden" name="id" value="${bulletin.id}" /></td> 
     </tr> 
     <tr> 
      <td><input type="submit" name="approve" value="Approve" /></td> 
      <td><input type="submit" name="deny" value="Deny" /></td> 
     </tr> 
    </table> 
    <br /> 
</form:form> 

Oto moje metody kontrolera.

@RequestMapping(value = "/approve", method = RequestMethod.POST, params = { "approve" }) 
public String approve(@RequestParam int id, @RequestParam String approve, Model model) { 
    try { 
     bulletinDAO.approveBulletin(id); 
     model.addAttribute("approval", "Your bulletin has been approved."); 

     List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins(); 
     model.addAttribute("bulletins", bulletins); 
    } catch (Exception e) { 
     System.out.println(e.getMessage()); 
     return "FailurePage"; 
    } 

    return "ApproveBulletin"; 
} 

@RequestMapping(value = "/approve", method = RequestMethod.POST, params = { "deny" }) 
public String deny(@RequestParam int id, @RequestParam String deny, Model model) { 
    try { 
     bulletinDAO.denyBulletin(id); 
     model.addAttribute("approval", "Your bulletin has been denied."); 

     List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins(); 
     model.addAttribute("bulletins", bulletins); 
    } catch (Exception e) { 
     System.out.println(e.getMessage()); 
     return "FailurePage"; 
    } 

    return "ApproveBulletin"; 
} 
+0

Jak można to przetestować za pomocą MockMVC? –

+0

To nie zostało przetestowane z MockMVC. Zostało to przetestowane za pomocą aplikacji w Tomcat, ponieważ użytkownik normalnie z niej korzysta. –

9

Formularz na action jest ustawiony na "/ zatwierdzać" jeszcze swoją mapowanie kontrolerów jest "/ zatwierdzenie/{action}/{id}"; serwlet Dispatchera nie ma możliwości połączenia między tymi dwoma.

Nawet jeśli metoda był odwzorowane prawidłowo to nie zrobi to, czego od niego oczekujesz: jesteś mylące action i input i co one odpowiadają w żądaniu HTTP.

action ustawia adres URL żądania formularza, w twoim przypadku jest to "/zatwierdzić". każdego <input> elementu name parametr służy do dodawania parametrów HTTP o wartości value, więc wniosek musiałby kombinacji:

  • id=${id} (wszystkie żądania)
  • approve=Approve (jeśli użytkownik kliknął „zatwierdzenie”)
  • deny=Deny (jeśli użytkownik kliknął „deny”)

Aby obsługiwać oba te przypadki podpis kontrolera powinien zostać zmieniony coś takiego:

@RequestMapping(value = "/approve", method = RequestMethod.POST) 
public String approveBulletin(@RequestParam int id, 
      @RequestParam(required=false, defaultValue="") String approve, 
      @RequestParam(required=false, defaultValue="") String deny, 
      Model model) { 
    if (approve.equals("Approve")) { 
     // user clicked "approve" 
    } else if (deny.equals("Deny")) { 
     // user clicked "deny"    
    } else { 
     throw new IllegalArgumentException("Need either approve or deny!"); 
    } 

    // (...) 
} 

Ale wolałbym sugerować zmianę parametrów poszczególnych przycisków złożyć:

<td><input type="submit" name="approveParam" value="approveVal" /></td> 
<td><input type="submit" name="approveParam" value="denyVal" /></td> 

W ten sposób można zawsze dostać dokładnie dwa parametry: id i approve, wtedy można po prostu sprawdzić wartość approve aby zobaczyć, czy to był "zatwierdzić" lub "deny":

public String approveBulletin(@RequestParam int id, 
     @RequestParam(value = "approveParam") String approveOrDeny, 
     Model model) { 
    if (approveOrDeny.equalsIgnoreCase("approveVal")) { 
     // user clicked "approve" 
    } else if (approveOrDeny.equalsIgnoreCase("denyVal")) { 
     // user clicked "deny" 
    } else { 
     // wrong parameter sent 
    } 

Co pomaga w diagnozowaniu takich problemów (np. niezależnie od tego, czy jest to problem klienta czy serwera) sprawdza wychodzące żądanie za pomocą narzędzi internetowych przeglądarki (Firebugs w Firefox, Narzędzia dla programistów w Chrome itp.). Możesz łatwo przechwycić żądanie i zobaczyć, jakie parametry, adres URL i metoda HTTP były i porównać je z oczekiwaniami.

+0

Zaktualizowałem mój oryginalny wpis z najnowszą wersją mojego kodu, zgodnie z Twoimi sugestiami. Identyfikator jest teraz przekazywany, ale nie wartość klikniętego przycisku. –

+0

Czy możesz potwierdzić, czy możesz zobaczyć parametr "zatwierdzić" lub "odmówić" w żądaniu? (używając narzędzi przeglądarki) Właśnie przetestowałem to na uproszczonym formularzu, wysyła on poprawnie wartość przycisku. – kryger

+0

Właśnie znalazłem parametr w Firebug. Pod Net/All/Post widzę to: id =% 25% 7Bid% 7D & approve = Zatwierdź. Jak powinienem przepisać kod? –

Powiązane problemy