Ho un controller che fornisce un accesso REST alle informazioni:
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}") public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request, HttpServletResponse response) {
Il problema che sto vivendo è che se colpisco il server con una variabile di percorso con caratteri speciali, viene troncato. Ad esempio: http: // localhost: 8080 / blah-server / blah / get / blah2010.08.19-02: 25: 47
Il parametro blahName sarà blah2010.08
Tuttavia, la chiamata a request.getRequestURI () contiene tutte le informazioni passate.
Qualche idea su come impedire a Spring di troncare la variabile @PathVariable?
Prova un’espressione regolare per l’argomento @RequestMapping
:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")
Questo è probabilmente strettamente correlato a SPR-6164 . In breve, il framework tenta di applicare alcune intelligenze all’interpretazione URI, rimuovendo ciò che pensa siano estensioni di file. Ciò avrebbe l’effetto di trasformare blah2010.08.19-02:25:47
in blah2010.08
, dal momento che pensa che il .19-02:25:47
sia un’estensione di file.
Come descritto nel problema collegato, è ansible disabilitare questo comportamento dichiarando il proprio bean DefaultAnnotationHandlerMapping
nel contesto dell’app e impostando la proprietà useDefaultSuffixPattern
su false
. Ciò sostituirà il comportamento predefinito e impedirà il molesting dei dati.
Spring ritiene che qualsiasi cosa dietro l’ultimo punto sia un’estensione di file come .json
o .xml
e la tronca per recuperare il parametro.
Quindi se hai /{blahName}
:
/param
, /param.json
, /param.xml
o /param.anything
risulteranno in un parametro con valore param
/param.value.json
, /param.value.xml
o /param.value.anything
risulteranno in un parametro con valore param.value
Se cambi la mapping in /{blahName:.+}
come suggerito, qualsiasi punto, incluso l’ultimo, sarà considerato come parte del tuo parametro:
/param
risulterà in un parametro con valore param
/param.json
genererà un parametro con valore param.json
/param.xml
risulterà in un parametro con valore param.xml
/param.anything
risulterà in un parametro con valore param.anything
/param.value.json
genererà un parametro con valore param.value.json
Se non ti interessa il riconoscimento dell’estensione, puoi disabilitarlo mvc:annotation-driven
override di mvc:annotation-driven
automagic mvc:annotation-driven
:
Quindi, di nuovo, se hai /{blahName}
:
/param
, /param.json
, /param.xml
o /param.anything
risulteranno in un parametro con valore param
/param.value.json
, /param.value.xml
o /param.value.anything
risulteranno in un parametro con valore param.value
Nota: la differenza dalla configurazione di default è visibile solo se si ha una mapping come /something.{blahName}
. Vedi il problema del progetto Resthub .
Se si desidera mantenere la gestione delle estensioni, dalla spring 3.2 è anche ansible impostare la proprietà useRegisteredSuffixPatternMatch del bean RequestMappingHandlerMapping per mantenere triggersto il riconoscimento suffixPattern ma limitato all’estensione registrata.
Qui definisci solo le estensioni json e xml:
json=application/json xml=application/xml
Nota che mvc: annotation-driven accetta ora un’opzione contentNegotiation per fornire un bean personalizzato ma la proprietà di RequestMappingHandlerMapping deve essere cambiata in true (default false) (vedere https://jira.springsource.org/browse/SPR-7632 ).
Per questo motivo, devi comunque eseguire l’override di tutte le configurazioni di mvc: annotation-driven. Ho aperto un biglietto per Spring per richiedere un Custom RequestMappingHandlerMapping: https://jira.springsource.org/browse/SPR-11253 . Si prega di votare se siete interessati a.
Mentre si esegue l’override, fare attenzione a considerare anche l’esecuzione prioritaria della gestione Esecuzione personalizzata. In caso contrario, tutti i mapping delle eccezioni personalizzati avranno esito negativo. Dovrai riutilizzare messageCoverters con un bean di elenco:
Ho implementato, nel progetto open source Resthub di cui faccio parte, una serie di test su questi argomenti: vedere https://github.com/resthub/resthub-spring-stack/pull/219/files e https: // github.com/resthub/resthub-spring-stack/issues/217
Tutto dopo l’ultimo punto viene interpretato come estensione del file e tagliato per impostazione predefinita.
Nel tuo xml di configurazione spring puoi aggiungere DefaultAnnotationHandlerMapping
e impostare useDefaultSuffixPattern
su false
(l’impostazione predefinita è true
).
Quindi apri la tua molla xml mvc-config.xml
(o comunque viene chiamata) e aggiungi
Ora il tuo @PathVariable
blahName
(e anche tutti gli altri) dovrebbe contenere il nome completo compresi tutti i punti.
EDIT: Ecco un link alla api spring
Ho anche avuto lo stesso problema, e l’impostazione della proprietà su false non mi è stata d’aiuto. Tuttavia, l’API dice :
Tieni presente che i percorsi che includono un suffisso “.xxx” o che terminano con “/” non verranno mai trasformati utilizzando il modello di suffisso predefinito in ogni caso.
Ho provato ad aggiungere “/ end” al mio URL RESTful e il problema è andato via. Non sono per favore con la soluzione, ma ha funzionato.
A proposito, non so cosa stessero pensando i designer di Spring quando hanno aggiunto questa “funzionalità” e quindi l’abbiamo triggersta per impostazione predefinita. IMHO, dovrebbe essere rimosso.
Utilizzando la class di configurazione Java corretta:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); } @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(false); } }
Ho risolto con questo trucco
1) Aggiunto HttpServletRequest in @PathVariable come sotto
@PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception {
2) Ottieni direttamente l’URL (a questo livello nessun troncamento) nella richiesta
request.getPathInfo()
Spring MVC @PathVariable con punto (.) Viene troncato
Mi sono imbattuto in questo e le soluzioni qui in generale non funzionano come mi aspettavo.
Suggerisco di usare un’espressione SpEL e più mappature, ad es
@RequestMapping(method = RequestMethod.GET, value = {Routes.BLAH_GET + "/{blahName:.+}", Routes.BLAH_GET + "/{blahName}/"})
Il problema dell’estensione del file esiste solo se il parametro si trova nell’ultima parte dell’URL. Modificare
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
a
@RequestMapping( method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/safe")
e tutto andrà bene di nuovo-
Se è ansible modificare l’indirizzo a cui vengono inviate le richieste, la soluzione semplice sarebbe aggiungere una barra finale a loro (e anche nel valore @RequestMapping
):
/path/{variable}/
quindi la mapping sarebbe simile a:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/")
Vedi anche Spring MVC @PathVariable con punto (.) Che viene troncato .
//in your xml dispatcher add this property to your default annotation mapper bean as follow
aggiungendo il “:. +” ha funzionato per me, ma non prima di aver rimosso parentesi graffe esterne.
value = {"/username/{id:.+}"}
non ha funzionato
value = "/username/{id:.+}"
funziona
Spero di aver aiutato qualcuno:]
Soluzione di configurazione basata su Java per prevenire il troncamento (utilizzando una class non deprecata):
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @Configuration public class PolRepWebConfig extends WebMvcConfigurationSupport { @Override @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { final RequestMappingHandlerMapping handlerMapping = super .requestMappingHandlerMapping(); // disable the truncation after . handlerMapping.setUseSuffixPatternMatch(false); // disable the truncation after ; handlerMapping.setRemoveSemicolonContent(false); return handlerMapping; } }
Fonte: http://www.javacodegeeks.com/2013/01/spring-mvc-customizing-requestmappinghandlermapping.html
AGGIORNARE:
Mi sono reso conto di avere alcuni problemi con la configurazione automatica di Spring Boot quando ho usato l’approccio sopra (alcune auto-configurazione non diventano efficaci).
Invece, ho iniziato a utilizzare l’approccio BeanPostProcessor
. Sembrava funzionare meglio.
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor { private static final Logger logger = LoggerFactory .getLogger(MyBeanPostProcessor.class); @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof RequestMappingHandlerMapping) { setRemoveSemicolonContent((RequestMappingHandlerMapping) bean, beanName); setUseSuffixPatternMatch((RequestMappingHandlerMapping) bean, beanName); } return bean; } private void setRemoveSemicolonContent( RequestMappingHandlerMapping requestMappingHandlerMapping, String beanName) { logger.info( "Setting 'RemoveSemicolonContent' on 'RequestMappingHandlerMapping'-bean to false. Bean name: {}", beanName); requestMappingHandlerMapping.setRemoveSemicolonContent(false); } private void setUseSuffixPatternMatch( RequestMappingHandlerMapping requestMappingHandlerMapping, String beanName) { logger.info( "Setting 'UseSuffixPatternMatch' on 'RequestMappingHandlerMapping'-bean to false. Bean name: {}", beanName); requestMappingHandlerMapping.setUseSuffixPatternMatch(false); } }
Ispirato da: http://ronaldxq.blogspot.com/2014/10/spring-mvc-setting-alwaysusefullpath-on.html
se sei sicuro che il tuo testo non corrisponderà a nessuna delle estensioni predefinite, puoi utilizzare il seguente codice:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseRegisteredSuffixPatternMatch(true); } }
La mia soluzione preferibile per evitare che Spring MVC @PathVariable venga troncata consiste nell’aggiungere la barra finale alla fine della variabile path.
Per esempio:
@RequestMapping(value ="/email/{email}/")
Quindi, la richiesta sarà simile a:
http://localhost:8080/api/email/[email protected]/