2014-12-11 3 views
10

Я пытаюсь настроить конечную точку REST, которая позволяет запрашивать пользователя по их адресу электронной почты. Адрес электронной почты является последней частью пути, поэтому Spring обрабатывает [email protected] как значение [email protected] и усекает расширение .com.Spring - Path variable truncate after dot - аннотация

Я нашел подобный вопрос здесь Spring MVC @PathVariable with dot (.) is getting truncated Однако, у меня есть конфигурации на основе аннотаций с использованием AbstractAnnotationConfigDispatcherServletInitializer и WebMvcConfigurerAdapter. Поскольку у меня нет конфигурации XML, это решение не будет работать для меня:

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

Я также попытался это решение, которое использует регулярное выражение, но он не работал ни.

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

Кто-нибудь знает, как отключить усечение шаблона суффикса без xml?

+0

делает это [это] (https://github.com/resthub/resthub-spring-stack/issues/188) поможет вам –

ответ

18

Точка в переменной пути в конце URI вызывает два неожиданных поведения (неожиданно для большинства пользователей, кроме тех, которые знакомы с огромным количеством свойств конфигурации Spring).

Первый (который может установить с использованием регулярного выражения {email:.+}) заключается в том, что конфигурация Spring по умолчанию соответствует всем расширениям пути. Поэтому настройка отображения для /api/{file} будет означать, что Spring сопоставляет вызов /api/myfile.html аргументу String myfile. Это полезно, если вы хотите, чтобы /api/myfile.html, /api/myfile.md, /api/myfile.txt и другие указывали на тот же ресурс. Тем не менее, мы можем отключить это поведение во всем мире, без, вынуждены прибегать к регулярному выражению на каждой конечной точке.

Вторая проблема связана с первым и правильно зафиксирована @masstroy. Когда /api/myfile.* указывает на ресурс myfile, Spring предполагает расширение пути (.html, .txt и т. Д.) Указывает, что ресурс должен быть возвращен с определенным форматом. Такое поведение также может быть очень полезно в некоторых ситуациях. Но часто это будет означать, что объект, возвращенный сопоставлением метода, не может быть преобразован в этот формат, а Spring выдает HttpMediaTypeNotAcceptableException.

Мы можем включить и выключить следующее (при условии, Спринг загрузки):

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

Подробнее о Content Negotiation.

7

Я нашел решение этой проблемы с помощью ContentNegotiationConfigurer боба из этой статьи: http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

я добавил следующую конфигурацию в моем 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); 
    } 
} 

Устанавливая .favorPathExtension(false), весна больше не будет используйте расширение файла, чтобы переопределить принимаемый mediaType запроса. Javadoc для этого метода читает Indicate whether the extension of the request path should be used to determine the requested media type with the highest priority.

Затем я создал свой @RequestMapping с помощью регулярных выражений

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

Обратите внимание, что вместо использования '{email:. +}' Hack вы также можете отключить суффикс, путем переопределения 'WebMvcConfigurerAdapter.configurePathMatch (PathMatcherConfigurer configurer)' и установки 'configurer.setUseSuffixPatternMatch (false)'. Вы также можете ограничить сопоставление шаблонов суффикса с явно зарегистрированными расширениями файлов. – bkjvbx

+0

{email:. +} Работал для меня без дополнительной настройки. Это означает, что он не усекал часть после точки. Но была и другая проблема. ExceptionHandler не работал должным образом с пунктирными переменными. Ваше решение также исправило эту проблему. – jasiustasiu

+0

@bkjvbx вы можете разместить свое решение в качестве ответа, оно выглядит лучше, чем этот, и я собираюсь отметить его как принятый ответ – masstroy

0

Для людей Java-Config:

С весной 4 вы можете просто отключить эту функцию с помощью:

@Configuration 
public class WebMvcConfig extends WebMvcConfigurerAdapter { 

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

} 

Тогда в целых точках приложения будет рассматриваются как точки.