2012-07-23 9 views
9

Ho un oggetto User memorizzato nella sessione con @SessionAttributes. E un metodo straight-forward decorato con @ModelAttribute per inizializzarlo ogni volta che il valore della sessione è nullo.Valori di @PathVariable e @ModelAttribute che si sovrappongono

classe

utente:

@Entity 
@Table(name="USER") 
public class User implements java.io.Serializable { 

    private Long id; 
    private String username; 
    private String password; 
    .... 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name ="ID") 
    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 
    ... 

Controller:

@RequestMapping("/item") 
@Controller 
@SessionAttributes({"user"}) 
public class MyController { 

metodo @ModelAttribute:

@ModelAttribute("user") 
    public User createUser(Principal principal) { 
     return userService.findByUsername(principal.getName()); 
    } 

Tutto sembra funzionare come previsto se non in questo particolare metodo:

@RequestMapping(value = "/{id}", method = RequestMethod.GET) 
    public String showItem(@PathVariable("id") Long id, @ModelAttribute("user") User user, 
      Model uiModel) { 
    ...  
} 

Il problema è che User.id sia impostata con @PathVariable("id"). Credo di essermi imbattuto in questo con @RequestParam. Suppongo che sia perché hanno lo stesso nome e tipo. Dopo aver letto Spring's documentation (vedi sotto) presumo che questo comportamento sia previsto:

Il passaggio successivo è il collegamento dei dati. La classe WebDataBinder corrisponde ai nomi dei parametri di richiesta, inclusi parametri della stringa di query e campi modulo, per modellare i campi degli attributi in base al nome. I campi di corrispondenza vengono popolati dopo che la conversione del tipo (da stringa al tipo di campo di destinazione) è stata applicata laddove necessario.

Tuttavia, penso che questo scenario sia abbastanza comune, come lo gestiscono le altre persone? Se i miei risultati sono corretti e questo è il comportamento previsto (o bug), questo sembra essere molto incline agli errori.

Possibili soluzioni:

  1. Change @PathVariable("id") a @PathVariable("somethingElse"). Funziona ma non è così semplice con @RequestParam (ad esempio, non so come cambiare l'ID del parametro di richiesta di jqgrid in qualcos'altro, ma questo è un altro problema).
  2. Cambia @PathVariable("id") tipo da Lungo a Int. Questo renderà i tipi User.id e id diversi, ma il cast su Long sembra brutto :)
  3. Non utilizzare @ModelAttribute qui e richiedere nuovamente il DB per User. Non coerente con altri metodi e comporta chiamate DB ridondanti.

Qualche suggerimento?

+0

un hack quarta opzione, che cosa succede se si cambia l'ordine - '@ ModelAttribute' prima e poi' @ PathVariable' . –

+0

Il risultato è stato lo stesso, comunque vale la pena provare. – Ulises

+0

Sì, in realtà ho realizzato in seguito che le proprietà corrispondenti dell'utente verranno confrontate dalle variabili uri. I tuoi approcci sembrano buoni, ne ho aggiunto uno in più come risposta. –

risposta

5

Che ne dite di questo approccio -

@RequestMapping(value = "/{id}", method = RequestMethod.GET) 
public String showItem(@PathVariable("id") Long id, 
      Model uiModel) { 
     User user = (User)uiModel.asMap().get("user"); 
    ...  
} 
+0

Non male. È un piccolo cambiamento e funziona. Domanda veloce, non ho visto 'getAttribute()' su 'Modello', dovrei semplicemente' (Utente) uiModel.asMap(). Get ("utente") '? – Ulises

+0

Sì, mio ​​errore! fammi modificare la risposta per cambiare questo. –

+0

+1 Mi piace la tua risposta, prima che la contrassegnassi anche se mi piacerebbe vedere se sento di più. Grazie mille per il tuo aiuto. – Ulises

0

uso @SessionAttribute

@RequestMapping(value = "/{id}", method = RequestMethod.GET) 
    public String showItem(@PathVariable("id") Long id, @SessionAttribute("user") User user, 
      Model uiModel) { 
    ...  
} 
Problemi correlati