Spring MVC @PathVariable가 잘림


142

정보에 대한 RESTful 액세스를 제공하는 컨트롤러가 있습니다.

@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 () 호출에는 전달 된 모든 정보가 포함됩니다.

Spring이 @PathVariable을 자르지 못하게하는 방법에 대한 아이디어가 있습니까?


이것은 스프링 3.2-M2에서 해결 된 것 같습니다. 컨텐츠 협상을위한 유효한 파일 확장자 경로 지정해당 문서를 참조하십시오 .
Arjan

답변:


149

@RequestMapping인수에 대한 정규식을 시도하십시오 .

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

1
답을 주셔서 감사합니다. 이렇게하면 사용자 이름이 어떻게 든 잘린 경우를 해결할 수있었습니다 .. (-: 'useDefaultSuffixPattern'을 사용하는 다른 옵션은 XML 대신 @Configuration 스프링 클래스를 사용하기 때문에 옵션이 아니 었습니다.
evandongen

3
이것은 효과가 있지만 정규 표현식에서 콜론의 중요성은 무엇입니까?
노아 Yetter

6
노아, 나는 이것을 오랫동안 사용하지 않았지만 콜론은 정규 표현식을 인수 이름과 분리하여 묶는 것으로 생각합니다.
earldouglas

3
우리는 비슷한 problam /item/user@abc.com을 가졌습니다. @가 잘린 후에도 다른 슬래시 /item/user@abc.com/을 추가함으로써 해결되었습니다.
Titi Wangsa bin Damhore

59

이것은 아마도 SPR-6164 와 밀접한 관련이 있습니다. 간단히 말해서 프레임 워크는 URI 해석에 스마트를 적용하여 파일 확장자라고 생각하는 것을 제거하려고합니다. 이것은 파일 확장자 라고 생각하기 때문에 blah2010.08.19-02:25:47로 바뀌는 효과가 있습니다.blah2010.08.19-02:25:47

연결된 문제에 설명 된대로 DefaultAnnotationHandlerMapping앱 컨텍스트에서 고유 한 Bean 을 선언 하고 해당 useDefaultSuffixPattern속성을로 설정 하여이 동작을 비활성화 할 수 있습니다 false. 이것은 기본 동작을 무시하고 데이터를 희롱하는 것을 중지합니다.


3
기본적으로 확장 기반 컨텐츠 협상을 켜는 것은 이상한 선택처럼 보입니다. 실제로 실제로 동일한 리소스를 다른 형식으로 몇 개의 시스템에 노출합니까?
Affe

나는 아침에 이것을 시도했지만 여전히 경로 변수가 잘 렸습니다.
14:55에 Pogel

30
좋은 답변과 "데이터를 가장하는"문구를 사용하는 경우 +1
Chris Thompson

11
Spring 3.1 사용자의 경우- RequestMappingHandlerMapping대신 new 를 사용하는 경우 설정하는 속성은 useSuffixPatternMatch(입니다 false). @ 테드 : 링크 된 문제는 3.2에서 조금 더 많은 제어를 추가하여 전혀 또는 아무것도 할 필요가 없다는 것을 언급합니다.
Nick

2
Spring 4.2에서는 구성이 약간 더 쉽습니다. 우리는 Java 설정 클래스를 사용 WebMvcConfigurationSupport하고 간단한 후크를 제공하는 것을 확장합니다 public void configurePathMatch(PathMatchConfigurer configurer).-그냥 무시하고 원하는 방식으로 경로를 설정하십시오.
pmckeown 2016 년

31

봄의 마지막 점 뒤에 아무것도 같은 파일 확장자를 것을 고려 .json하거나 .xml당신의 매개 변수를 검색을 절단.

그래서 당신이 가지고 있다면 /{blahName}:

  • /param, /param.json, /param.xml또는 /param.anything값으로 될 것이다 PARAMparam
  • /param.value.json, /param.value.xml또는 /param.value.anything값으로 될 것이다 PARAMparam.value

매핑을 /{blahName:.+}제안대로 변경 하면 마지막 점을 포함한 점이 매개 변수의 일부로 간주됩니다.

  • /param 가치가있는 매개 변수가됩니다 param
  • /param.json 가치가있는 매개 변수가됩니다 param.json
  • /param.xml 가치가있는 매개 변수가됩니다 param.xml
  • /param.anything 가치가있는 매개 변수가됩니다 param.anything
  • /param.value.json 가치가있는 매개 변수가됩니다 param.value.json
  • ...

확장 인식을 신경 쓰지 않으면 mvc:annotation-drivenautomagic 을 재정 의하여 확장 인식을 비활성화 할 수 있습니다 .

<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값으로 될 것이다 PARAMparam
  • /param.value.json, /param.value.xml또는 /param.value.anything값으로 될 것이다 PARAMparam.value

참고 : 기본 구성과의 차이점은와 같은 매핑이있는 경우에만 표시됩니다 /something.{blahName}. Resthub 프로젝트 문제를 참조하십시오 .

확장 관리를 유지하려면 Spring 3.2부터 suffixPattern 인식을 활성화하지만 등록 된 확장으로 제한하기 위해 RequestMappingHandlerMapping Bean의 useRegisteredSuffixPatternMatch 특성을 설정할 수도 있습니다.

여기에 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 : annotation-driven은 이제 customN을 제공하기 위해 contentNegotiation 옵션을 허용하지만 RequestMappingHandlerMapping의 특성을 true (기본값 false)로 변경해야합니다 ( https://jira.springsource.org/browse/SPR-7632). ).

이러한 이유로 여전히 모든 mvc : annotation-driven 구성을 대체해야합니다. 사용자 정의 RequestMappingHandlerMapping을 요청하기 위해 Spring 티켓을 열었습니다 ( https://jira.springsource.org/browse/SPR-11253) . 관심이 있으시면 투표하십시오.

재정의하는 동안 사용자 지정 실행 관리 재정의도 고려해야합니다. 그렇지 않으면 모든 사용자 지정 예외 매핑이 실패합니다. messageCoverters를 목록 Bean과 함께 재사용해야합니다.

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

오픈 소스 프로젝트 인 Resthub 에서 이러한 주제에 대한 일련의 테스트를 구현했습니다. https://github.com/resthub/resthub-spring-stack/pull/219/fileshttps : // 참조 github.com/resthub/resthub-spring-stack/issues/217


16

마지막 점 뒤의 모든 것은 파일 확장자로 해석되며 기본적으로 잘립니다.
귀하의 스프링 구성 XML에서는 추가 할 수 있습니다 DefaultAnnotationHandlerMapping및 설정 useDefaultSuffixPatternfalse(기본값은 true).

따라서 스프링 XML을 열거 mvc-config.xml나 호출하십시오.

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

이제 당신의 @PathVariable blahName(그리고 다른 모든 것들도) 모든 점을 포함한 성명을 포함해야합니다.

편집 : 여기 에 봄 API에 대한 링크가 있습니다


시도하지는 않았지만 다른 사람들은<mvc:annotation-driven /> 해당되는 경우 제거해야 한다고 주장 합니다 .
Arjan

7

또한 같은 문제가 발생하여 속성을 false로 설정해도 도움이되지 않았습니다. 그러나 API는 다음 과 같이 말합니다 .

".xxx"접미사를 포함하거나 "/"로 끝나는 경로는 이미 기본 접미사 패턴을 사용하여 변환되지 않습니다.

RESTful URL에 "/ end"를 추가하려고했는데 문제가 해결되었습니다. 나는 해결책에 만족하지 않지만 효과가 있었다.

BTW, 나는 스프링 디자이너가이 "기능"을 추가 한 다음 기본적으로 켰을 때 무슨 생각을했는지 모르겠다. IMHO, 제거해야합니다.


나는 동의한다. 나는 최근에 이것에 조금 물렸다.
llambda

7

올바른 Java 구성 클래스 사용

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

이것은 나를 위해 잘 작동했습니다. Tomcat Spring 버전 4.3.14에서 실행
Dave


3

방금 이것에 부딪 쳤으며 여기의 솔루션은 일반적으로 예상대로 작동하지 않았습니다.

SpEL 표현식과 여러 매핑을 사용하는 것이 좋습니다.

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

잘리지 않는 클래스를 사용하여 잘림을 방지하는 Java 기반 구성 솔루션 :

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

최신 정보:

위의 접근법을 사용할 때 Spring Boot 자동 구성에 문제가 있음을 깨달았습니다 (일부 자동 구성이 효과적이지 않음).

대신, 나는 그 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

Spring MVC @PathVariable이 잘리지 않도록하는 가장 좋은 해결책은 경로 변수 끝에 슬래시를 추가하는 것입니다.

예를 들면 다음과 같습니다.

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

따라서 요청은 다음과 같습니다.

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

1

직면하고있는 문제 는 점 (.) 의 URI 의 마지막 부분을 .json 또는 .xml과 같은 파일 확장자 로 해석하는 스프링 때문 입니다. 따라서 스프링이 경로 변수를 해결하려고 시도하면 URI가 끝날 때 점 (.)을 만나면 나머지 데이터가 잘립니다. 참고 : 또한 URI 끝에 경로 변수를 유지하는 경우에만 발생합니다.

예를 들어 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"및 secondValue = "link"에서. 다음의 마지막 비트입니다. 경로 변수가 해석 될 때 잘립니다.

따라서이를 방지하기 위해 가능한 두 가지 방법이 있습니다.

1.) 정규식 매핑 사용

매핑의 끝 부분에서 정규식을 사용하십시오.

@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) {
    //...
}

이것은 Spring의 기본 동작으로부터 변수를 보호하는 두 번째 변수를 포함합니다.

3) Spring의 기본 webmvc 구성을 재정의함으로써

Spring은 @EnableWebMvc 주석을 사용하여 가져온 기본 구성을 무시하는 방법을 제공 합니다. 애플리케이션 컨텍스트에서 자체 DefaultAnnotationHandlerMapping Bean 을 선언하고 useDefaultSuffixPattern 속성을 false로 설정 하여 Spring MVC 구성을 사용자 정의 할 수 있습니다 . 예:

@Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {

    @Bean
    public RequestMappingHandlerMapping 
      requestMappingHandlerMapping() {

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

이 기본 구성을 재정의하면 모든 URL에 영향을 미칩니다.

참고 : 여기에서는 기본 메소드를 재정의하도록 WebMvcConfigurationSupport 클래스를 확장합니다. WebMvcConfigurer 인터페이스를 구현하여 deault 구성을 대체하는 방법이 하나 더 있습니다. 이 읽기에 대한 자세한 내용은 https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html을 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.