2015-06-03 15 views
5

Chcę utworzyć witrynę internetową, która wyświetla formularz. Pola formularza zależą od parametru żądania (a także od komponentu bean formularza). To jest mój kontroler, który powoduje, że różne formy:Jak wysłać ogólne obiekty do kontrolera Spring?

@Controller 
public class TestController { 

    @Autowired 
    private MyBeanRegistry registry; 

    @RequestMapping("/add/{name}") 
    public String showForm(@PathVariable String name, Model model) { 
     model.addAttribute("name", name); 
     model.addAttribute("bean", registry.lookup(name)); 

     return "add"; 
    } 

} 

Odpowiedni widok wygląda następująco:

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> 
<head> 
</head> 
<body> 
    <form method="post" th:action="@{|/add/${name}|}" th:object="${bean}"> 
     <th:block th:replace="|${name}::fields|"></th:block> 
     <button type="submit">Submit</button> 
    </form> 
</body> 
</html> 

Poniżej przykładowy fragment, który wyświetla pól formularza:

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> 
<head> 
</head> 
<body> 
    <th:block th:fragment="fields"> 
     <label for="firstName">First name</label><br /> 
     <input type="text" id="firstName" th:field="*{firstName}" /><br /> 
     <label for="lastName">Last name</label><br /> 
     <input type="text" id="lastName" th:field="*{lastName}" /> 
    </th:block> 
</body> 
</html> 

Podlegająca fasola wyglądałaby tak:

public class MyExampleBean { 

    private String firstName; 

    private String lastName; 

    // Getters & setters 

} 

Formularz jest renderowany poprawnie, ale jak mogę otrzymać formularz z powrotem w kontrolerze? A jak mogę sprawdzić poprawność przesłanego komponentu? Próbowałem następującą metodę, ale oczywiście nie może pracować:

@RequestMapping(value = "/add/{name}", method = RequestMethod.POST) 
public String processForm(@PathVariable String name, @Valid Object bean) { 
    System.out.println(bean); 

    return "redirect:/add/" + name; 
} 

Wiosna tworzy nową instancję Object ale przedstawione wartości są tracone. Jak mogę wykonać to zadanie?

+0

To wygląda na problem zakresu, istnieje parametr powiedzieć chcesz zakresu sesji dla tej postaci? –

+0

Nie ustawiłem zakresu na formularzu. – stevecross

Odpowiedz

2

Gdybyś tylko chciał do czynienia z ograniczoną liczbą ziaren, można hav e jeden metoda @RequestMapping dla każdego komponentu bean, wszystkie delegujące do prywatnej metody, która wykonywałaby zadanie. Możesz znaleźć przykład here.

Jeśli chcesz, aby móc przyjąć fasoli dynamicznie, trzeba będzie zrobić ręcznie co wiosna robi automagicznie:

  • używać tylko żądania, a nie modelu atrybut
  • znaleźć fasoli w rejestrze o imieniu PathVariable
  • zrobić jawnie wiązanie

Ale mam nadzieję, że wiosna oferuje sub Klasy WebDataBinder jak pomocnicy:

@RequestMapping(value = "/add/{name}", method = RequestMethod.POST) 
public String processForm(@PathVariable String name, WebRequest request) { 
    //System.out.println(bean); 

    Object myBean = registry.lookup(name); 
    WebRequestDataBinder binder = new WebRequestDataBinder(myBean); 
    // optionnaly configure the binder 
    ... 
    // trigger actual binding of request parameters 
    binder.bind(request); 
    // optionally validate 
    binder.validate(); 
    // process binding results 
    BindingResult result = binder.getBindingResult(); 
    ... 

    return "redirect:/add/" + name; 
} 
+0

Dzięki. Drugie podejście działa bardzo dobrze, ale jak dodać walidację? Dodałem walidator dla mojego obiektu, używając 'binder.addValidators()'. Walidator sprawdza, czy 'firstName' i' lastName' z powyższego przykładu są puste przy użyciu 'ValidationUtils'. Kiedy przesyłam pusty formularz i sprawdzam "BindingResult", oznacza to, że nie ma błędów. – stevecross

+0

Właśnie widziałem, że muszę wywołać 'binder.validate()' po powiązaniu. – stevecross

+0

Wygląda na to, że o tym zapomniałem ... Post edytowany –

0

Co do walidacji nie wiem, ale do pobierania wartości, można spróbować poniższego

(UWAGA: nie próbowałem tego kodu, ponieważ nie mogłem w czasie pisania) .

Zmień obsługi processForm obsłużyć HttpServletRequest INSEAD typu Object i uzyskać sumbitted wartości z mapy paramters, przykład:

@RequestMapping(value="/add/{name}", method=RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) 
public String processForm(@PathVariable String name, HttpServletRequest request) { 
    Map<String, String[]> parameterMap = request.getParameterMap(); 
    ... 
} 
0

należy dokonać dwóch zmian w kodzie,

  1. Opisz swój numer TestController za pomocą @SessionAttributes("bean"), aby zachować atrybut modelu o nazwie bean przechowywany w sesji

  2. Dodaj @ModelAttribute("bean") do swojej metody processForm, czyli processForm(@PathVariable String name, @Valid @ModelAttribute("bean") Object bean). Jako atrybut modelu bean jest zarejestrowany jako atrybut sesji, jak również będzie pobierać go z sesji, i będą trzymać wartości

Jeśli metoda processForm przebywa w innym kontrolerze, upewnij się adnotacje, że kontroler z @SessionAttributes("bean") jak dobrze

Poniższy powinny być przykładem kontrolera roboczego

@SessionAttributes("bean") 
@Controller 
public class TestController { 

    @Autowired 
    private MyBeanRegistry registry; 

    @RequestMapping("/add/{name}") 
    public String showForm(@PathVariable String name, Model model) { 
     model.addAttribute("name", name); 
     model.addAttribute("bean", registry.lookup(name)); 

     return "add"; 
    } 

    @RequestMapping(value = "/add/{name}", method = RequestMethod.POST) 
    public String processForm(@PathVariable String name, @Valid @ModelAttribute("bean") Object bean) { 
     System.out.println(bean); 
     return "redirect:/add/" + name; 
    } 
} 
+0

Pokonuje cel budowy aplikacji RESTful –

Powiązane problemy