2014-12-11 22 views
10

Sto tentando di impostare un endpoint REST che consenta di interrogare un utente tramite il suo indirizzo email. L'indirizzo email è l'ultima parte del percorso, quindi Spring sta trattando il valore [email protected] come valore [email protected] e troncando l'estensione .com.Spring: variabile troncata dopo punto - annotazione

ho trovato una domanda simile qui Spring MVC @PathVariable with dot (.) is getting truncated Tuttavia, ho una configurazione base di annotazione utilizzando AbstractAnnotationConfigDispatcherServletInitializer e WebMvcConfigurerAdapter. Poiché non ho alcuna configurazione XML, questa soluzione non funziona per me:

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> 
    <property name="useDefaultSuffixPattern" value="false" /> 
</bean> 

Ho anche provato questa soluzione che utilizza espressioni regolari, ma non ha funzionato neanche.

@RequestMapping(value = "user/by-email/{email:.+}") 

Qualcuno sa come disattivare il troncamento del modello di suffisso senza xml?

+0

fa questo [questo] (https://github.com/resthub/resthub-spring-stack/issues/188) ti aiuta –

risposta

18

Il punto nella variabile percorso alla fine dell'URI causa due comportamenti imprevisti (imprevisti per la maggior parte degli utenti, ad eccezione di quelli che hanno familiarità con l'enorme numero di proprietà di configurazione Spring).

Il primo (che può fissati secondo la {email:.+} regex) è che la configurazione di default Spring soddisfa tutte le estensioni di percorso. Pertanto, l'impostazione di una mappatura per /api/{file} significa che Spring associa una chiamata a /api/myfile.html all'argomento String myfile. Ciò è utile quando si desidera , /api/myfile.txt e altri per indicare la stessa risorsa. Tuttavia, possiamo disattivare questo comportamento a livello globale, senza, dovendo ricorrere a un regex hack su ogni endpoint.

Il secondo problema è correlato al primo e corretto correttamente da @masstroy. Quando /api/myfile.* punta alla risorsa myfile, Spring presuppone che l'estensione del percorso (.html, .txt, ecc.) Indichi che la risorsa deve essere restituita con un formato specifico. Questo comportamento può anche essere molto utile in alcune situazioni. Ma spesso, ciò significa che l'oggetto restituito da un metodo di mappatura non può essere convertito in questo formato, e Spring genererà un HttpMediaTypeNotAcceptableException.

Siamo in grado di girare sia fuori con il seguente (supponendo Primavera Boot):

@Configuration 
public class WebConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void configurePathMatch(PathMatchConfigurer configurer) { 
    // turn off all suffix pattern matching 
    configurer.setUseSuffixPatternMatch(false); 
    // OR 
    // turn on suffix pattern matching ONLY for suffixes 
    // you explicitly register using 
    // configureContentNegotiation(...) 
    configurer.setUseRegisteredSuffixPatternMatch(true); 
    } 

    @Override 
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 
    configurer.favorPathExtension(false); 
    } 
} 

più su Content Negotiation.

7

ho trovato la soluzione a questo utilizzando il fagiolo ContentNegotiationConfigurer da questo articolo: http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

ho aggiunto la seguente configurazione per la mia classe WebConfig:

@EnableWebMvc 
@Configuration 
@ComponentScan(basePackageClasses = { RestAPIConfig.class }) 
public class WebConfig extends WebMvcConfigurerAdapter {  
    @Override 
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 
     configurer.favorPathExtension(false); 
     configurer.defaultContentType(MediaType.APPLICATION_JSON); 
    } 
} 

Impostando .favorPathExtension(false), Primavera non sarà più utilizzare l'estensione del file per sovrascrivere l'accetta mediaType della richiesta. Il Javadoc per questo metodo legge Indicate whether the extension of the request path should be used to determine the requested media type with the highest priority.

Poi ho impostato il mio @RequestMapping utilizzando l'espressione regolare

@RequestMapping(value = "/user/by-email/{email:.+}") 
+0

Nota che invece di usare l'hack {{email:. +} 'Puoi anche disabilitare corrispondenza del modello di suffisso sovrascrivendo 'WebMvcConfigurerAdapter.configurePathMatch (Configuratore PathMatcherConfigurer)' e impostando 'configurer.setUseSuffixPatternMatch (false)'. È inoltre possibile limitare la corrispondenza del modello di suffisso alle estensioni di file esplicitamente registrate. – bkjvbx

+0

{email:. +} Ha funzionato per me senza alcuna configurazione aggiuntiva. Ciò significa che non ha troncato una parte dopo il punto. Ma c'era un altro problema. ExceptionHandler non ha funzionato correttamente con variabili tratteggiate. La tua soluzione ha risolto anche questo problema – jasiustasiu

+0

@bkjvbx puoi pubblicare la tua soluzione come risposta, sembra migliore di questa e la contrassegnerò come risposta accettata – masstroy

0

per la gente java-config:

Con molla 4 si può semplicemente disattivare questa funzione da:

@Configuration 
public class WebMvcConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void configurePathMatch(PathMatchConfigurer configurer) { 
    configurer.setUseSuffixPatternMatch(false); 
    } 

} 

poi in tutta puntini applicazione sarà trattata come punti.