2010-03-23 18 views
36

Sto cercando di implementare gli URL RESTful nella mia applicazione Spring MVC. Tutto va bene, tranne per la gestione delle richieste di modulo. Devo reindirizzare o al modulo originale o alla pagina "successo".Spring MVC Controller reindirizza utilizzando i parametri URL anziché in risposta

@Controller 
@RequestMapping("/form") 
public class MyController { 

    @RequestMapping(method = RequestMethod.GET) 
    public String setupForm() { 
     // do my stuff 
     return "myform"; 
    } 

    @RequestMapping(method = RequestMethod.POST) 
    public String processForm(ModelMap model) {    
     // process form data 

     model.addAttribute("notification", "Successfully did it!"); 
     return "redirect:/form"; 
    } 
} 

Tuttavia, come ho letto nella Spring documentation, se si reindirizza qualsiasi parametro sarà messo in l'url. E questo non funziona per me. Quale sarebbe il modo più aggraziato intorno a questo?

+0

Quale URL di reindirizzamento stai cercando di raggiungere? – skaffman

+0

Non ha importanza, devo solo reindirizzare dopo aver elaborato i dati del post in una pagina e notificare all'utente che ciò che hanno inviato è stato elaborato correttamente. Sembra che questa sia una richiesta comune http://jira.springframework.org/browse/SPR-1294. Ma potrebbe non essere risolto per un po '. – predhme

+0

In realtà non sembra che nessuna delle correzioni descritte nei due ticket correlati risolverà il tuo particolare problema: uno di questi riguarda il controllo degli attributi del modello esposti come querystrings (ma ne esporremo ancora alcuni) e l'altro riguarda l'aggiunta attributi come parte del percorso dell'URL (che è piacevolmente riposante per gli ID, diciamo, ma non ti dà ancora un posto dove portare un messaggio di successo). –

risposta

7

http://jira.springframework.org/browse/SPR-6464 mi ha fornito ciò di cui avevo bisogno per far funzionare le cose fino a quando Spring MVC offre la funzionalità (potenzialmente nella versione 3.0.2). Anche se ho semplicemente implementato le classi che hanno temporaneamente e aggiunto il filtro al mio contesto di applicazione web. Funziona alla grande!

+1

Proprio come un aggiornamento, questa funzionalità è prevista per la primavera 3.1 – predhme

+2

Ed è effettivamente implementato nella primavera 3.1. – praseodym

+1

Il collegamento è interrotto. –

8

È possibile avere processForm() restituire invece un oggetto View e restituirlo il tipo concreto RedirectView che ha un parametro per setExposeModelAttributes().

Quando ritorni un nome di vista prefisso "redirect:", Spring MVC trasforma ad un oggetto RedirectView in ogni caso, lo fa solo così con setExposeModelAttributes true (che credo sia un valore dispari di default a).

+0

Se il messaggio di successo non è esposto come una querystring, come arriva alla vista reindirizzata? –

+0

Questo è quello che stavo chiedendo. – predhme

+0

Come vuoi che arrivi alla pagina di successo? Se si desidera eseguire un reindirizzamento, sembra che sia necessario passarlo come parametro di richiesta oppure impostarlo nella sessione e rimuoverlo nella pagina successiva. Ma deve essere passato in qualche modo. –

4

Se non si desidera il messaggio di successo nell'URL, una opzione è quella di inserirla nella sessione (nel metodo processForm) e quindi controllarla (e rimuoverla) nel metodo setupForm.

Modificato per aggiungere: se questo è un problema da eseguire manualmente, è possibile scrivere una sottoclasse di RedirectView che aggiunge un attributo "messaggio" e avvolge il processo di inserimento nella sessione. Non sono sicuro, però, se c'è un modo semplice per avvolgere il messaggio di ritorno dalla sessione ...

Onestamente, non penso ci sia una risposta facile - la natura di un reindirizzamento HTTP è che lo stato non è trasportato; se vuoi mantenere lo stato comunque, sei bloccato con i vari modi usuali per mantenere lo stato nelle applicazioni web: la sessione, un cookie, una querystring ...

+0

Certamente possibile, ma dal momento che la mia applicazione è molto più grande di quella sola, diventa piuttosto un dolore doverlo fare per ogni singola forma. – predhme

+0

Struts sembra offrire qualcosa chiamato ActionMessages. Non sono del tutto sicuro di cosa sia. Inoltre, con Ruby On Rails, offrono un flash [: notifica]. Che è essenzialmente ciò che sto cercando di ottenere. Il messaggio flash viene memorizzato fino all'azione successiva (reindirizzamento risultante o cosa hai). Sembra che http://www.jroller.com/raible/entry/migrating_from_struts_to_spring abbia tentato di affrontarlo. La sua strada sembra interessante. – predhme

+0

Bene, mi sembra che il suo approccio stia essenzialmente avvolgendo la sessione e inserendo il messaggio nella sessione, sulla falsariga di ciò che avevo in mente. Ma dà il codice attuale, quindi sicuramente più utile. –

30

Ho avuto lo stesso problema. risolto in questo modo:

return new ModelAndView("redirect:/user/list?success=true"); 

E poi il mio metodo di controllo simile a questa:

public ModelMap list(@RequestParam(required=false) boolean success) { 
    ModelMap mm = new ModelMap(); 
    mm.put(SEARCH_MODEL_KEY, campaignService.listAllCampaigns()); 
    if(success) 
     mm.put("successMessageKey", "campaign.form.msg.success"); 
    return mm; 
} 

funziona perfettamente se non si desidera inviare i dati semplici, non collezioni diciamo. Quindi dovresti usare la sessione credo.

9

Questo problema è causato (come altri hanno affermato) dagli attributi del modello che vengono mantenuti nella stringa di query - questo di solito è indesiderabile ed è a rischio di creare buchi di sicurezza e stringhe di query ridicole.La mia solita soluzione è di non usare mai le stringhe per i reindirizzamenti in Spring MVC, invece utilizzare un RedirectView che può essere configurato per non esporre gli attributi modello (vedi: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/view/RedirectView.html)

RedirectView(String url, boolean contextRelative, boolean http10Compatible, boolean exposeModelAttributes) 

Così ho tendono ad avere un metodo util che fa un 'redirect sicuro' come:

public static RedirectView safeRedirect(String url) { 
    RedirectView rv = new RedirectView(url); 
    rv.setExposeModelAttributes(false); 
    return rv; 
} 

L'altra opzione è quella di utilizzare XML di configurazione di fagioli:

<bean id="myBean" class="org.springframework.web.servlet.view.RedirectView"> 
    <property name="exposeModelAttributes" value="false" /> 
    <property name="url" value="/myRedirect"/> 
</bean> 

Anche in questo caso, si potrebbe abstract questo nella sua propria classe per evitare la ripetizione (ad es. SafeRedirectView).


Una nota su 'cancellare il modello' - questo non è lo stesso di 'non esporre il modello' in tutte le circostanze. Un sito su cui ho lavorato aveva molti filtri che aggiungevano cose al modello, questo significava che la cancellazione del modello prima del reindirizzamento non avrebbe impedito una lunga stringa di query. Suggerirei anche che "non mostrare gli attributi del modello" è un approccio più semantico rispetto a "cancellare il modello prima di reindirizzare".

+0

RedirectView - il reindirizzamento sicuro ha funzionato per me. Grazie MatCarey! –

3

Hey si può solo fare una cosa semplice invece di utilizzare il modello per inviare l'uso dei parametri HttpServletRequest oggetto e farlo

HttpServletRequest request; 
request.setAttribute("param", "value") 

ora i tuoi parametri predefiniti non verranno mostrati nella tua intestazione URL spero che funziona :)

0
@RequestMapping(path="/apps/add", method=RequestMethod.POST) 
public String addApps(String appUrl, Model model, final RedirectAttributes redirectAttrs) { 
    if (!validate(appUrl)) { 
     redirectAttrs.addFlashAttribute("error", "Validation failed"); 
    } 
    return "redirect:/apps/add" 
} 

@RequestMapping(path="/apps/add", method=RequestMethod.GET) 
public String addAppss(Model model) { 
    String error = model.asMap().get("error"); 
} 
Problemi correlati