Ich habe einen Controller, der REST-gerechten Zugriff auf Informationen bietet:
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request,
HttpServletResponse response) {
Ich habe das Problem, dass der Server abgeschnitten wird, wenn ich eine Pfadvariable mit Sonderzeichen auf den Server trete. Zum Beispiel: http: // localhost: 8080/blah-server/blah/get/blah2010.08.19-02: 25: 47
Der Parameter blahName lautet blah2010.08
Der Aufruf von request.getRequestURI () enthält jedoch alle übergebenen Informationen.
Irgendeine Idee, wie Spring daran gehindert werden kann, die @PathVariable abzuschneiden?
Versuchen Sie einen regulären Ausdruck für das @RequestMapping
Streit:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")
Dies hängt wahrscheinlich eng mit SPR-6164 zusammen. Kurz gesagt, das Framework versucht, einige Smarts auf die URI-Interpretation anzuwenden, wobei es das entfernt, was es für Dateierweiterungen hält. Dies hätte den Effekt, dass blah2010.08.19-02:25:47
into blah2010.08
, da denkt es das .19-02:25:47
ist eine Dateierweiterung.
Wie im verlinkten Problem beschrieben, können Sie dieses Verhalten deaktivieren, indem Sie Ihre eigene DefaultAnnotationHandlerMapping
-Bean im App-Kontext deklarieren und die Eigenschaft useDefaultSuffixPattern
auf false
setzen. Dies überschreibt das Standardverhalten und verhindert, dass Ihre Daten missbraucht werden.
Spring geht davon aus, dass alles hinter dem letzten Punkt eine Dateierweiterung wie .json
Oder .xml
Ist, und schneidet sie ab, um Ihren Parameter abzurufen.
Wenn Sie also /{blahName}
Haben:
/param
, /param.json
, /param.xml
Oder /param.anything
Führen zu einem Parameter mit dem Wert param
/param.value.json
, /param.value.xml
Oder /param.value.anything
Ergeben einen Parameter mit dem Wert param.value
Wenn Sie Ihre Zuordnung wie vorgeschlagen in /{blahName:.+}
Ändern, wird jeder Punkt, einschließlich des letzten, als Teil Ihres Parameters betrachtet:
/param
Führt zu einem Parameter mit dem Wert param
/param.json
Führt zu einem Parameter mit dem Wert param.json
/param.xml
Führt zu einem Parameter mit dem Wert param.xml
/param.anything
Führt zu einem Parameter mit dem Wert param.anything
/param.value.json
Führt zu einem Parameter mit dem Wert param.value.json
Wenn Sie die Erweiterungserkennung nicht interessieren, können Sie sie deaktivieren, indem Sie mvc:annotation-driven
Automagic überschreiben:
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="useSuffixPatternMatch" value="false"/>
</bean>
Also nochmal, wenn Sie /{blahName}
Haben:
/param
, /param.json
, /param.xml
Oder /param.anything
Führen zu einem Parameter mit dem Wert param
/param.value.json
, /param.value.xml
Oder /param.value.anything
Ergeben einen Parameter mit dem Wert param.value
Hinweis: Der Unterschied zur Standardkonfiguration ist nur sichtbar, wenn Sie ein Mapping wie /something.{blahName}
Haben. Siehe Problem mit dem Resthub-Projekt .
Wenn Sie die Erweiterungsverwaltung beibehalten möchten, können Sie seit Spring 3.2 auch die useRegisteredSuffixPatternMatch-Eigenschaft der RequestMappingHandlerMapping-Bean festlegen, um die SuffixPattern-Erkennung zu aktivieren, jedoch auf die registrierte Erweiterung zu beschränken.
Hier definieren Sie nur die Erweiterungen json und xml:
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="useRegisteredSuffixPatternMatch" value="true"/>
</bean>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false"/>
<property name="favorParameter" value="true"/>
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
Beachten Sie, dass mvc: annotation-driven jetzt eine contentNegotiation-Option akzeptiert, um eine benutzerdefinierte Bean bereitzustellen. Die Eigenschaft von RequestMappingHandlerMapping muss jedoch in true (Standardwert false) geändert werden (vgl. https://jira.springsource.org/browse)/SPR-7632 ).
Aus diesem Grund müssen Sie immer noch die gesamte Konfiguration von mvc: annotation überschreiben. Ich habe ein Ticket für Spring geöffnet, um eine benutzerdefinierte RequestMappingHandlerMapping anzufordern: https://jira.springsource.org/browse/SPR-1125 . Bitte stimmen Sie ab, wenn Sie interessiert sind.
Berücksichtigen Sie beim Überschreiben auch das Überschreiben der benutzerdefinierten Ausführungsverwaltung. Andernfalls schlagen alle benutzerdefinierten Ausnahmezuordnungen fehl. Sie müssen messageCoverters mit einer List-Bean wiederverwenden:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
<util:list id="messageConverters">
<bean class="your.custom.message.converter.IfAny"></bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</util:list>
<bean name="exceptionHandlerExceptionResolver"
class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
<property name="order" value="0"/>
<property name="messageConverters" ref="messageConverters"/>
</bean>
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService" />
<property name="validator" ref="validator" />
</bean>
</property>
<property name="messageConverters" ref="messageConverters"/>
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
</bean>
Ich habe im Open-Source-Projekt Resthub , an dem ich beteiligt bin, eine Reihe von Tests zu diesen Themen implementiert: siehe https://github.com/resthub/resthub-spring-stack)/pull/219/files und https://github.com/resthub/resthub-spring-stack/issues/217
Alles nach dem letzten Punkt wird als Dateierweiterung interpretiert und standardmäßig abgeschnitten.
In Ihrer Spring-Konfigurations-XML können Sie DefaultAnnotationHandlerMapping
hinzufügen und useDefaultSuffixPattern
auf false
setzen (Standard ist true
).
Also öffne deinen Frühling xml mvc-config.xml
(oder wie auch immer es heißt) und addieren
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="useDefaultSuffixPattern" value="false" />
</bean>
Nun ist dein @PathVariable
blahName
(und auch alle anderen) sollten den vollständigen Namen einschließlich aller Punkte enthalten.
BEARBEITEN: Hier ist ein Link zur Frühlings-API
Ich bin auch auf dasselbe Problem gestoßen, und es hat mir auch nicht geholfen, die Eigenschaft auf false zu setzen. Allerdings die API sagt :
Beachten Sie, dass Pfade, die das Suffix ".xxx" enthalten oder bereits mit "/" enden, in keinem Fall unter Verwendung des Standardsuffixmusters transformiert werden.
Ich habe versucht, meiner RESTful-URL "/ end" hinzuzufügen, und das Problem ist behoben. Ich bin nicht zufrieden mit der Lösung, aber es hat funktioniert.
Übrigens, ich weiß nicht, was die Spring-Designer gedacht haben, als sie dieses "Feature" hinzugefügt und es dann standardmäßig aktiviert haben. IMHO sollte es entfernt werden.
Verwendung der richtigen Java Konfigurationsklasse:
@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);
}
}
Ich habe mich durch diesen Hack entschlossen
1) HttpServletRequest in @PathVariable wie unten hinzugefügt
@PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception {
2) Rufen Sie die URL direkt in der Anforderung ab (auf dieser Ebene keine Kürzung)
request.getPathInfo()
//in your xml dispatcher add this property to your default annotation mapper bean as follow
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="alwaysUseFullPath" value="true"></property>
</bean>
Ich bin nur darauf gestoßen und die Lösungen hier haben im Allgemeinen nicht wie erwartet funktioniert.
Ich schlage vor, einen SpEL-Ausdruck und mehrere Zuordnungen zu verwenden, z.
@RequestMapping(method = RequestMethod.GET,
value = {Routes.BLAH_GET + "/{blahName:.+}",
Routes.BLAH_GET + "/{blahName}/"})
das Hinzufügen von ":. +" hat bei mir funktioniert, aber erst, wenn ich die äußeren geschweiften Klammern entfernt habe.
value = {"/username/{id:.+}"}
hat nicht funktioniert
value = "/username/{id:.+}"
funktioniert
Hoffe ich habe jemandem geholfen:]
Wenn Sie die Adresse bearbeiten können, an die Anforderungen gesendet werden, besteht eine einfache Lösung darin, einen abschließenden Schrägstrich hinzuzufügen (und auch im Feld @RequestMapping
Wert):
/path/{variable}/
das Mapping würde also so aussehen:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/")
Siehe auch Spring MVC @PathVariable mit Punkt (.) Wird abgeschnitten .
Das Dateierweiterungsproblem besteht nur, wenn sich der Parameter im letzten Teil der URL befindet. Veränderung
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
zu
@RequestMapping(
method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/safe")
und alles wird wieder gut
Java-basierte Konfigurationslösung zum Verhindern von Kürzungen (mithilfe einer nicht veralteten Klasse):
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;
}
}
UPDATE:
Ich habe festgestellt, dass Probleme mit der automatischen Konfiguration von Spring Boot aufgetreten sind, als ich den oben beschriebenen Ansatz verwendet habe (einige automatische Konfigurationen werden nicht wirksam).
Stattdessen habe ich begonnen, den BeanPostProcessor
-Ansatz zu verwenden. Es schien besser zu funktionieren.
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);
}
}
Inspiriert von: http://ronaldxq.blogspot.com/2014/10/spring-mvc-setting-alwaysusefullpath-on.html
wenn Sie sicher sind, dass Ihr Text keiner der Standarderweiterungen entspricht, können Sie den folgenden Code verwenden:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseRegisteredSuffixPatternMatch(true);
}
}
Meine bevorzugte Lösung, um zu verhindern, dass die Spring MVC @PathVariable abgeschnitten wird, ist das Hinzufügen eines abschließenden Schrägstrichs am Ende der Pfadvariablen.
Beispielsweise:
@RequestMapping(value ="/email/{email}/")
Die Anfrage sieht also so aus:
http://localhost:8080/api/email/[email protected]/
Das Problem, mit dem Sie konfrontiert sind, ist auf die Feder Interpretation des letzten Teils zurückzuführen des Uri nach dem Punkt (.) als Dateierweiterung wie .json oder .xml. Wenn spring also versucht, die Pfadvariable aufzulösen, schneidet es den Rest der Daten einfach ab, nachdem es auf einen Punkt (.) Am Ende des URL stößt. Hinweis: Auch dies geschieht nur, wenn Sie die Pfadvariable am Ende der URL belassen.
Betrachten Sie zum Beispiel uri: https: //localhost/example/gallery.df/link.ar
@RestController
public class CustomController {
@GetMapping("/example/{firstValue}/{secondValue}")
public void example(@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
// ...
}
}
In der obigen URL firstValue = "gallery.df" und secondValue = "link" steht das letzte Bit nach dem. wird abgeschnitten, wenn die Pfadvariable interpretiert wird.
Um dies zu verhindern, gibt es zwei Möglichkeiten:
1.) Verwenden eines regulären Ausdrucks
Verwenden Sie am Ende des Mappings einen regulären Ausdruck
@GetMapping("/example/{firstValue}/{secondValue:.+}")
public void example(
@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
//...
}
Mit + geben wir jeden Wert an, nachdem der Punkt auch Teil der Pfadvariablen ist.
2.) Hinzufügen eines Schrägstrichs am Ende unserer @PathVariable
@GetMapping("/example/{firstValue}/{secondValue}/")
public void example(
@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
//...
}
Dies schließt unsere zweite Variable ein, die sie vor dem Standardverhalten von Spring schützt.
3) Durch Überschreiben der Standard-Webmvc-Konfiguration von Spring
Spring bietet Möglichkeiten zum Überschreiben der importierten Standardkonfigurationen mithilfe der Anmerkungen @ EnableWebMvc. Sie können die Spring MVC-Konfiguration anpassen, indem Sie eine eigene DefaultAnnotationHandlerMapping Bean im Anwendungskontext und Setzen seines useDefaultSuffixPattern Eigenschaft auf falsch. Beispiel:
@Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {
@Bean
public RequestMappingHandlerMapping
requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping
= super.requestMappingHandlerMapping();
handlerMapping.setUseSuffixPatternMatch(false);
return handlerMapping;
}
}
Beachten Sie, dass das Überschreiben dieser Standardkonfiguration alle URLs betrifft.
Hinweis: Hier erweitern wir die WebMvcConfigurationSupport-Klasse, um die Standardmethoden zu überschreiben. Es gibt eine weitere Möglichkeit, die deaktivierten Konfigurationen zu überschreiben, indem Sie die WebMvcConfigurer-Schnittstelle implementieren. Weitere Informationen hierzu finden Sie unter: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html