स्प्रिंग MVC @PathVariable हो रही है


142

मेरे पास एक नियंत्रक है जो सूचना के लिए उपयोगी पहुंच प्रदान करता है:

@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request,
                            HttpServletResponse response) {

मुझे जो समस्या आ रही है, वह यह है कि अगर मैं सर्वर को विशेष वर्णों के साथ पथ चर के साथ मारता हूं तो वह छोटा हो जाता है। उदाहरण के लिए: http: // localhost: 8080 / blah-server / blah / get / blah2010.08.19-02: 25: 47

पैरामीटर blahName blah2010.08 होगा

हालाँकि, request.getRequestURI () के लिए कॉल में शामिल सभी जानकारी शामिल हैं।

किसी भी विचार कैसे @PathVariable truncating से वसंत को रोकने के लिए?


जवाबों:


149

@RequestMappingतर्क के लिए एक नियमित अभिव्यक्ति का प्रयास करें :

RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")

1
उत्तर के लिए धन्यवाद, इससे मुझे एक ऐसे मामले को हल करने में मदद मिली जहां उपयोगकर्ता नाम किसी भी तरह से छंट गए .. (-: 'useDefaultSuffixPattern' के साथ दूसरा विकल्प कोई विकल्प नहीं था क्योंकि हम XML के बजाय @Configuration वसंत कक्षाओं का उपयोग कर रहे हैं।
evandongen

3
यह काम करता है, लेकिन रेगेक्स में बृहदान्त्र का क्या महत्व है?
नूह येटर

6
नूह, मैंने लंबे समय से इसका उपयोग नहीं किया है, लेकिन मुझे लगता है कि बृहदान्त्र नियमित अभिव्यक्ति को तर्क नाम से अलग करने के लिए इसे बांधता है।
इलडूगलस

3
हमारे पास एक समान problam /item/user@abc.com था, @ के बाद कुछ भी काट दिया गया था, यह एक और स्लैश /item/user@abc.com/ को जोड़कर हल किया गया था
Titi Wangsa bin Damhore

59

यह संभवतः SPR-6164 से निकटता से संबंधित है । संक्षेप में, फ्रेमवर्क यूआरआई व्याख्या में कुछ स्मार्ट को लागू करने की कोशिश करता है, जो यह सोचता है कि फाइल एक्सटेंशन हैं। इस मोड़ के प्रभाव होता है blah2010.08.19-02:25:47में blah2010.08, क्योंकि यह सोचता है, .19-02:25:47एक फाइल एक्सटेंशन है।

जैसा कि लिंक किए गए मुद्दे में वर्णित है, आप इस व्यवहार DefaultAnnotationHandlerMappingको ऐप संदर्भ में अपनी स्वयं की बीन घोषित करके और उसकी useDefaultSuffixPatternसंपत्ति को सेट करके अक्षम कर सकते हैं false। यह डिफ़ॉल्ट व्यवहार को ओवरराइड करेगा, और इसे आपके डेटा से छेड़छाड़ करना बंद कर देगा।


3
डिफ़ॉल्ट रूप से एक्सटेंशन आधारित सामग्री वार्ता को चालू करना इस तरह के एक अजीब विकल्प की तरह लगता है। कितने सिस्टम वास्तव में व्यवहार में विभिन्न स्वरूपों में एक ही संसाधन को उजागर करते हैं?
Affe

मैंने सुबह यह कोशिश की और अभी भी पथ चर काट दिया था।
फॉगल

30
एक महान जवाब के लिए +1 और "आपके डेटा से छेड़छाड़" वाक्यांश का उपयोग करने के लिए
क्रिस थॉम्पसन

11
स्प्रिंग 3.1 उपयोगकर्ताओं के लिए - यदि आप RequestMappingHandlerMappingइसके बजाय नए का उपयोग कर रहे हैं , तो सेट करने की संपत्ति useSuffixPatternMatch(भी false) है। @ टेड: लिंक किए गए मुद्दे में उल्लेख किया गया है कि 3.2 में वे थोड़ा और नियंत्रण जोड़ने की उम्मीद करते हैं, इसलिए इसे ऑल-ऑर-नथिंग नहीं होना चाहिए।
निक

2
स्प्रिंग 4.2 में इसे कॉन्फ़िगर करना थोड़ा आसान है। हम जावा कॉन्फिगर कक्षाओं का उपयोग करते हैं और WebMvcConfigurationSupportजो एक साधारण हुक प्रदान करता है, उसका विस्तार करते हैं : public void configurePathMatch(PathMatchConfigurer configurer)- बस इसे ओवरराइड करें और आपको जो पसंद है, उसी से मेल खाते हुए पथ को सेट करें।
pmckown

31

स्प्रिंग मानते हैं कि अंतिम बिंदु के पीछे कुछ भी एक फ़ाइल एक्सटेंशन है जैसे कि .jsonया .xmlअपने पैरामीटर को पुनः प्राप्त करने के लिए इसे छोटा करें।

इसलिए यदि आपके पास /{blahName}:

  • /param, /param.json, /param.xmlया /param.anythingमूल्य के साथ एक परम में परिणाम होगाparam
  • /param.value.json, /param.value.xmlया /param.value.anythingमूल्य के साथ एक परम में परिणाम होगाparam.value

यदि आप अपनी मैपिंग को /{blahName:.+}सुझाव के अनुसार बदलते हैं , तो पिछले एक सहित किसी भी बिंदु को आपके पैरामीटर का हिस्सा माना जाएगा:

  • /param मूल्य के साथ एक परम में परिणाम होगा param
  • /param.json मूल्य के साथ एक परम में परिणाम होगा param.json
  • /param.xml मूल्य के साथ एक परम में परिणाम होगा param.xml
  • /param.anything मूल्य के साथ एक परम में परिणाम होगा param.anything
  • /param.value.json मूल्य के साथ एक परम में परिणाम होगा param.value.json
  • ...

यदि आपको विस्तार मान्यता की परवाह नहीं है, तो आप इसे mvc:annotation-drivenस्वचालित रूप से ओवरराइड करके अक्षम कर सकते हैं :

<bean id="handlerMapping"
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
    <property name="useSuffixPatternMatch" value="false"/>
</bean>

तो, फिर से, यदि आपके पास है /{blahName}:

  • /param, /param.json, /param.xmlया /param.anythingमूल्य के साथ एक परम में परिणाम होगाparam
  • /param.value.json, /param.value.xmlया /param.value.anythingमूल्य के साथ एक परम में परिणाम होगाparam.value

नोट: डिफ़ॉल्ट कॉन्फ़िगरेशन से अंतर केवल तभी दिखाई देता है, जब आपके पास मैपिंग जैसा हो /something.{blahName}Resthub प्रोजेक्ट समस्या देखें ।

यदि आप विस्तार प्रबंधन रखना चाहते हैं, तो स्प्रिंग 3.2 के बाद से आप प्रत्ययपत्थर मान्यता को सक्रिय रखने के लिए, लेकिन पंजीकृत एक्सटेंशन तक सीमित रखने के लिए RequestMappingHandlerMapping सेम की उपयोग की जा सकती है।

यहाँ आप केवल json और 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>

ध्यान दें कि mvc: एनोटेशन-चालित अब एक कस्टम बीन प्रदान करने के लिए एक कंटेंटनॉग्रेशन विकल्प को स्वीकार करता है, लेकिन RequestMappingHandlerMapping की संपत्ति को सही (डिफ़ॉल्ट झूठ) में बदलना होगा (cf. https://jira.pringsource.org/browse/SPR-7632-76 )।

इस कारण से, आपको अभी भी सभी mvc: एनोटेशन-चालित कॉन्फ़िगरेशन को ओवरराइड करना होगा। मैंने कस्टम रिक्वेस्ट के लिए स्प्रिंग के लिए एक टिकट खोला है । मैपिंगहैंडलर मैपिंग: https://jira.springsource.org/browse/SPR-11253 । यदि आपकी रुचि है तो कृपया वोट करें।

ओवरराइड करते समय, कस्टम एक्ज़ीक्यूशन मैनेजमेंट ओवरराइडिंग पर भी विचार करने के लिए सावधान रहें। अन्यथा, आपके सभी कस्टम अपवाद मैपिंग विफल हो जाएंगे। आपको सूची बीन के साथ संदेश भेजने वालों का पुन: उपयोग करना होगा:

<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>

मैंने ओपन सोर्स प्रोजेक्ट रेस्टहब में लागू किया है जिसका मैं हिस्सा हूं, इन विषयों पर परीक्षणों का एक सेट: https://github.com/resthub/resthub-spring-stack/pull/219/files और https: // देखें। github.com/resthub/resthub-spring-stack/issues/217


16

अंतिम बिंदु के बाद सब कुछ फ़ाइल एक्सटेंशन के रूप में व्याख्या की जाती है और डिफ़ॉल्ट रूप से कट जाती है।
अपने स्प्रिंग कॉन्फिग xml में आप (डिफ़ॉल्ट है ) को जोड़ DefaultAnnotationHandlerMappingऔर सेट कर सकते हैं ।useDefaultSuffixPatternfalsetrue

तो अपने स्प्रिंग xml को खोलें mvc-config.xml(या फिर इसे कहा जाता है) और जोड़ें

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

अब आपके @PathVariable blahName(और सभी अन्य, भी) सभी डॉट्स सहित पूरा नाम शामिल होना चाहिए।

संपादित करें: यहाँ वसंत एपीआई के लिए एक कड़ी है


मैंने कोशिश नहीं की है, लेकिन दूसरों का दावा है कि <mvc:annotation-driven />यदि लागू हो तो आपको भी निकालना होगा।
अर्जन १

7

मैं भी एक ही मुद्दे में भाग गया, और संपत्ति को झूठी स्थापित करने से मुझे मदद नहीं मिली। हालाँकि, एपीआई का कहना है :

ध्यान दें कि पथ में एक ".xxx" प्रत्यय शामिल है या "/" के साथ पहले से ही किसी भी मामले में डिफ़ॉल्ट प्रत्यय पैटर्न का उपयोग करके रूपांतरित नहीं किया जाएगा।

मैंने अपने Restful URL में "/ end" जोड़ने की कोशिश की, और समस्या दूर हो गई। मैं समाधान के साथ खुश नहीं हूँ, लेकिन यह काम किया है।

BTW, मुझे नहीं पता कि स्प्रिंग डिज़ाइनर क्या सोच रहे थे जब उन्होंने इस "फीचर" को जोड़ा और फिर इसे डिफ़ॉल्ट रूप से चालू किया। IMHO, इसे हटा दिया जाना चाहिए।


मैं सहमत हूँ। मैं हाल ही में इसके द्वारा बिट गया था।
llambda

7

सही जावा कॉन्फ़िगरेशन क्लास का उपयोग करना:

@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);
    }
}

यह मेरे लिए बहुत अच्छा काम किया। टॉमकैट स्प्रिंग संस्करण 4.3.14
डेव

4

मैंने इस हैक द्वारा हल किया

1) @PathVariable में नीचे की तरह HttpServletRequest जोड़ा गया

 @PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception { 

2) अनुरोध में सीधे URL प्राप्त करें (इस स्तर पर कोई छंटनी नहीं)

request.getPathInfo() 

स्प्रिंग MVC @PathVariable डॉट (।) के साथ छोटा हो रहा है


3

मैं बस इसमें भाग गया और यहाँ के समाधान आम तौर पर काम नहीं करते थे जैसा कि मुझे उम्मीद थी।

मेरा सुझाव है कि एक स्पेल अभिव्यक्ति और कई मैपिंग का उपयोग करें, जैसे

@RequestMapping(method = RequestMethod.GET, 
    value = {Routes.BLAH_GET + "/{blahName:.+}", 
             Routes.BLAH_GET + "/{blahName}/"})

3

फ़ाइल एक्सटेंशन समस्या केवल तभी मौजूद होती है जब पैरामीटर URL के अंतिम भाग में होता है। परिवर्तन

@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")

सेवा

@RequestMapping(
   method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/safe")

और सब फिर से ठीक हो जाएगा-


3

यदि आप उस पते को संपादित कर सकते हैं जिसे अनुरोध भेजे गए हैं, तो उन्हें ठीक करने के लिए एक सरल स्लैश जोड़ना होगा (और @RequestMappingमूल्य में भी ):

/path/{variable}/

इसलिए मानचित्रण ऐसा दिखेगा:

RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/")

स्प्रिंग एमवीसी @PathVariable को डॉट (।) के साथ भी देखें ।


3
//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>       

3

": + +" को जोड़ने से मेरे लिए काम हुआ, लेकिन तब तक नहीं जब तक कि मैंने बाहरी घुंघराले कोष्ठकों को हटा नहीं दिया।

value = {"/username/{id:.+}"} काम नहीं किया

value = "/username/{id:.+}" काम करता है

आशा है कि मैंने किसी की मदद की:]


2

ट्रंकेशन को रोकने के लिए जावा आधारित कॉन्फ़िगरेशन सॉल्यूशन (एक नहीं-वंचित वर्ग का उपयोग करके):

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;
    }
}

स्रोत: http://www.javacodegeeks.com/2013/01/spring-mvc-customizing-requestmappinghandlermapping.html

अपडेट करें:

मुझे लगा कि स्प्रिंग बूट ऑटो-कॉन्फ़िगरेशन के साथ कुछ समस्याएं हैं जब मैंने ऊपर के दृष्टिकोण का उपयोग किया (कुछ ऑटो-कॉन्फ़िगरेशन प्रभावी नहीं है)।

इसके बजाय, मैंने BeanPostProcessorदृष्टिकोण का उपयोग करना शुरू कर दिया । यह बेहतर काम कर रहा था।

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);
    }
}

से प्रेरित: http://ronaldxq.blogspot.com/2014/10/spring-mvc-setting-alwaysusefullpath-on.html


2

यदि आप सुनिश्चित हैं कि आपका पाठ किसी भी डिफ़ॉल्ट एक्सटेंशन से मेल नहीं खाएगा, तो आप नीचे दिए गए कोड का उपयोग कर सकते हैं:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setUseRegisteredSuffixPatternMatch(true);
    }
}

1

वसंत MVC @PathVariable को छंटनी से बचाने के लिए मेरा बेहतर समाधान पथ चर के अंत में अनुगामी स्लैश जोड़ना है।

उदाहरण के लिए:

@RequestMapping(value ="/email/{email}/")

तो, अनुरोध इस तरह दिखेगा:

http://localhost:8080/api/email/test@test.com/

1

समस्या यह है कि आप का सामना कर रहे की वजह से है वसंत की व्याख्या पिछले uri का हिस्सा के बाद बिंदु (।) एक के रूप में फाइल एक्सटेंशन .json या .xml की तरह। इसलिए जब वसंत पथ चर को हल करने की कोशिश करता है तो यह यूरि के अंत में एक डॉट (।) से सामना करने के बाद बाकी डेटा को छोटा कर देता है। नोट: यह भी केवल तभी होता है जब आप यूआरआई के अंत में पथ चर रखते हैं।

उदाहरण के लिए विचार करें 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) {
        // ...  
    }
}

उपरोक्त url में firstValue = "Gallery.df" और दूसराValue = "लिंक", के बाद अंतिम बिट। जब पथ चर की व्याख्या हो जाती है तो छोटा हो जाता है।

इसलिए, इसे रोकने के लिए दो संभावित तरीके हैं:

1.) एक regexp मानचित्रण का उपयोग करना

मैपिंग के अंत भाग में एक रेगेक्स का उपयोग करें

@GetMapping("/example/{firstValue}/{secondValue:.+}")   
public void example(
  @PathVariable("firstValue") String firstValue,
  @PathVariable("secondValue") String secondValue) {
    //...
}

+ का उपयोग करके, हम किसी भी मान को इंगित करते हैं कि डॉट भी पथ चर का हिस्सा होगा।

2.) हमारे @PathVariable के अंत में एक स्लैश जोड़ना

@GetMapping("/example/{firstValue}/{secondValue}/")
public void example(
  @PathVariable("firstValue") String firstValue,
  @PathVariable("secondValue") String secondValue) {
    //...
}

यह हमारे दूसरे चर को स्प्रिंग के डिफ़ॉल्ट व्यवहार से बचाते हुए संलग्न करेगा।

3) वसंत के डिफ़ॉल्ट वेबमेक कॉन्फ़िगरेशन को ओवरराइड करके

स्प्रिंग एनोटेशन @EnableWebMvc का उपयोग करके आयात किए जाने वाले डिफ़ॉल्ट कॉन्फ़िगरेशन को ओवरराइड करने के तरीके प्रदान करता है । हम आवेदन के संदर्भ में अपने स्वयं के DefaultAnnotationHandlerMapping बीन की घोषणा करके और इसके उपयोग को सेट कर सकते हैं। उदाहरण:

@Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {

    @Bean
    public RequestMappingHandlerMapping 
      requestMappingHandlerMapping() {

        RequestMappingHandlerMapping handlerMapping
          = super.requestMappingHandlerMapping();
        handlerMapping.setUseSuffixPatternMatch(false);
        return handlerMapping;
    }
}

ध्यान रखें कि इस डिफ़ॉल्ट कॉन्फ़िगरेशन को ओवरराइड करने से सभी यूआरएल प्रभावित होते हैं।

नोट: यहां हम डिफ़ॉल्ट विधियों को ओवरराइड करने के लिए WebMvcConfigurationSupport वर्ग का विस्तार कर रहे हैं। WebMvcConfigurer इंटरफ़ेस को लागू करके बहरी कॉन्फ़िगरेशन को ओवरराइड करने का एक और तरीका है। इस बारे में अधिक जानकारी के लिए पढ़ें: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/anfation/EnableWebMvc.html

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.