2014-11-10 11 views
6

Sono abbastanza nuovo a Spring MVC quindi per favore sii facile con me.Spring MVC form non supportato da un oggetto modello

Sto avendo difficoltà a capire come realizzare i seguenti requisiti in Spring MVC:

  • JSP forma di lista, per elencare gli utenti dal database (servizio, cosa repository funzionano correttamente).
  • Il modulo non è supportato da un oggetto attributo modello. Questa è una lista/modulo di ricerca!
  • ho bisogno di elencare gli utenti che corrispondono alcuni criteri presi da diversi campi "filtro" come:
    • Regione (elenco a discesa)
    • è facile da archiviare? (Sì/no a discesa)

userList.jsp

<spring:url value="strFormAction" var="/rest/security/user/list" /> 
<form:form id="userListForm" method="GET" action="${strFormAction}" modelAttribute="user"> 

<form:select id="strRegionId" path="${strRegionId}" cssClass="form-control" onchange="updateUsersList('1');"> 
    <spring:message var="strSelectRegionLabel" code="select.region" />       
    <form:option value="0" label="${strSelectRegionLabel}" /> 
    <form:options items="${regions}" itemValue="intId" itemLabel="strNameFr" /> 
</form:select> 

<form:select id="strArchived" path="${strArchived}" cssClass="form-control"> 
    <spring:message var="strYesLabel" code="yes" /> 
    <form:option value="true" label="${strYesLabel}"/> 

    <spring:message var="strNoLabel" code="no" /> 
    <form:option value="false" label="${strNoLabel}"/> 
</form:select> 

<table> 

... 

<c:forEach items="${users}" var="user"> 
...rows generated here... 
</c:forEach> 
... 
</table> 

</form:form> 

UserController.java

@RequestMapping(value = "/list", method = RequestMethod.GET) 
public String processUserList( @ModelAttribute("user") User user, 
           @RequestParam(value = "strRegionId", required = false) String strRegionId, 
           @RequestParam(value = "strArchived", required = false) String strArchived, 
           @RequestParam(value = "strSortBy", required = false) String strSortBy, 
           Model model) { 

    int intRegionId = strRegionId != null && strRegionId.equals("0") == false ? Integer.valueOf(strRegionId) : 0; 
    boolean booArchived = strArchived != null && strArchived.length() > 0 ? Boolean.valueOf(strArchived) : false;  
    int intSortBy = strSortBy != null && strSortBy.length() > 0 ? Integer.valueOf(strSortBy) : 1; 

    List<Region> regions = this.locationService.lstRegions(); 
    model.addAttribute("strRegionId", String.valueOf(intRegionId)); 
    model.addAttribute("strArchived", String.valueOf(booArchived)); 
    model.addAttribute("strSortBy", String.valueOf(intSortBy)); 

    List<User> users = this.securityService.listUsersByRegionAndArchiveState(intRegionId, booArchived, intSortBy); 

    model.addAttribute("user", new User()); 
    model.addAttribute("users", users); 
    model.addAttribute("regions", regions); 

    return "user/userList"; 
} 

Sembra che non posso utilizzare il modulo taglib primavera a tutti senza fornire un modelloAttributo nel modulo. Ho poi messo un manichino modelAttribute dal mio controller, ma ora ottengo:

javax.servlet.ServletException: javax.servlet.jsp.JspException: org.springframework.beans.NotReadablePropertyException: proprietà non valido '0' di classe bean [spring4base.model.security.User]: La proprietà Bean '0' non è leggibile o ha un metodo getter non valido: il tipo restituito del getter corrisponde al tipo di parametro del setter?

Come ho detto prima, quella pagina non è pensata per essere supportata da alcun POJO specifico. Questa è una pagina di ricerca, che deve restituire un elenco di utenti (User entity bean) basato su filtri selezionati in precedenza (regione, stato archiviato). Il modulo deve presentarsi su se stesso ogni volta che viene modificato un menu a discesa (l'utente sceglie una regione, l'invio viene eseguito sulla stessa mappatura e quindi l'elenco degli utenti viene ricaricato solo da utenti di quella specifica regione).

Provengo da Struts 1 in cui avevamo bisogno di creare ActionForm per ogni singola pagina. Da quanto ho letto dalla documentazione, i moduli non sono necessari in questi giorni quindi non vedo l'ora di risolvere il problema.

Qualsiasi aiuto sarebbe molto apprezzato.

risposta

4

Vorrei solo creare classe di supporto contenente i criteri di ricerca, per esempio:

public class UserSearchCriteria { 
    private String regionId; 
    private Boolean archived; 
    private String sortBy; 

    // Getters and setters 
} 

quindi vorrei modificare il metodo di controllo in questo modo (un codice non è presente, ma questo dovrebbe dare l'idea).

@RequestMapping(value = "/list", method = RequestMethod.GET) 
public String processUserList(@ModelAttribute("searchCriteria") UserSearchCriteria userSearchCriteria, Model model) { 
    // Retrieve users and perform filtering based on search criteria 
    List<User> users = this.securityService.listUsers(searchCriteria); 

    model.addAttribute("users", users); 
    model.addAttribute("regions", regions); 

    return "user/userList"; 
} 

E poi si usa il modulo di filtro in questo modo:

<spring:url value="/rest/security/user/list" var="formAction" /> 
<form:form id="userListForm" method="GET" action="${formAction}" modelAttribute="searchCriteria"> 

<form:select path="regionId" cssClass="form-control" onchange="updateUsersList('1');"> 
    <spring:message var="strSelectRegionLabel" code="select.region" />       
    <form:option value="0" label="${strSelectRegionLabel}" /> 
    <form:options items="${regions}" itemValue="intId" itemLabel="strNameFr" /> 
</form:select> 

<form:select path="archived" cssClass="form-control"> 
    <spring:message var="strYesLabel" code="yes" /> 
    <form:option value="true" label="${strYesLabel}"/> 

    <spring:message var="strNoLabel" code="no" /> 
    <form:option value="false" label="${strNoLabel}"/> 
</form:select> 

Hai avuto diversi errori nella forma in tuo snippet. Ad esempio l'attributo path accetta String contenente il nome (o il percorso) della proprietà a cui eseguire il bind, lo stavate passando ad alcune variabili.Inoltre avevi value e var acceso nel tuo <spring:url>, penso.

Provalo, non è una soluzione completa, ma spero che ti fornisca alcune indicazioni su come implementarlo. Se riscontri dei problemi, lascia un commento e aggiornerò la risposta.

+0

Questa risposta è unica nel suo genere. Funziona come un fascino. Grazie mille per la risposta rapida. –

+0

Che cosa intendi spostando la logica di filtro sul livello servizio/repository? L'utente deve avere la possibilità di scegliere l'opzione di ordinamento dal datagrid (elenco utenti). Diciamo che fa clic sull'intestazione della tabella "Nome", la query deve alternare l'ordine di ordinamento sul nome. Vuoi dire che dovrei creare diversi piccoli metodi come "listUsersSortedByFirstName", che alla fine userebbero lo stesso metodo privato? Qualunque consiglio da parte tua sarebbe molto apprezzato. –

+1

Sì, ora che ci sto guardando, probabilmente stavate facendo il filtro sul vostro livello di servizio per tutto il tempo. L'ho scritto in una sorta di fretta e guardando il metodo del controller probabilmente ho pensato che lo stavi filtrando sul controller. Ad ogni modo vorrei solo creare un metodo 'listUsers()' sul tuo servizio e passare l'oggetto dei criteri di ricerca, che potrebbe essere la soluzione più pulita. Rimuoverò la parte non pertinente dalla risposta ... –

Problemi correlati