2016-04-09 1 views
6

Я новичок в Spring Boot. В моем контроллере я использую UUID s как @PathVariable. По умолчанию весна возвращает MethodArgumentTypeMismatchException при прохождении недопустимого UUID.пользовательские преобразователи, не зарегистрированные в весеннем ботинке

Когда клиент проходит недействительный UUID Я хочу бросить пользовательский InvalidUUIDException, так что я могу вернуть настроенный ErrorDto с использованием этого исключения.

Чтобы архивировать, что я пытаюсь зарегистрировать заказ UUIDConverter (внедрение org.springframework.core.convert.converter.Converter).

@Component 
public class UUIDConverter implements Converter<String, UUID> 
{ 
    private static final Pattern pattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"); 

    @Override 
    public UUID convert(String input) throws InvalidUuidException 
    { 
     if (!pattern.matcher(input).matches()) { 
      throw new InvalidUuidException(input); 
     } 

     return UUID.fromString(input); 
    } 
} 

Чтобы зарегистрировать этот компонент, я добавляю этот конвертер для пружин ConversionService. Использование ConversionServiceFactoryBean.

@Configuration 
public class ConversionServiceConfiguration 
{ 
    @Bean 
    public ConversionServiceFactoryBean conversionService() 
    { 
     ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean(); 
     bean.setConverters(getConverters()); 

     return bean; 
    } 

    private Set<Converter> getConverters() 
    { 
     Set<Converter> converters = new HashSet<>(); 
     converters.add(new UUIDConverter()); 

     return converters; 
    } 
} 

Я пытался также использовать @Component вместо @Configuration, как это было упомянуто здесь: Spring not using mongo custom converters

Другие решения Я попробовал: Именование боб conversionServiceFactoryBean вместо conversionService. Или позвонив bean.afterPropertiesSet() и перенастройки с ConversionService использованием bean.getObject() ...

Я также попытался продлить от WebMvcConfigurerAdapter, перекрывая addFormatters и добавить свой конвертер там, используя addConverter ...

Как уже упоминалось здесь: How to register custom converters in spring boot? Я также попытался зарегистрировать преобразователь как @Bean напрямую.

Не имеет значения, что я пробовал, UUIDConverter не будет применяться.

Какое правильное решение делает что-то подобное в весенней обуви?
Может ли кто-нибудь помочь? Что я делаю неправильно?

+0

У меня есть тот же вопрос – wasabi

+0

У вас есть SprinbWebMvc включен? – hovanessyan

ответ

0

Идиоматический способ весны, чтобы обработать этот случай, - это использовать пользовательский ExceptionHandler. В основном вы говорите Spring, что вы будете обрабатывать этот конкретный класс ошибок.

Идея заключается в том, что вы определяете ExceptionHandler, который перехватывает брошенную ошибку (например, MethodArgumentTypeMismatchException) и возвращает пользовательские ResponseEntity населенную с любой структурой (например, ErrorDto), Вам необходимо, коды ошибок, заголовки и т.д.

Вот пример:

@ExceptionHandler({ MethodArgumentTypeMismatchException.class }) 
public ResponseEntity<Object> handleMethodArgumentTypeMismatch(
    MethodArgumentTypeMismatchException ex, WebRequest request) { 

    //populate your ErrorDto with the desired information 
    ErrorDto errorDto = 
     new ErrorDto(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), ex); 

    //return your ErrorDto wrapped in ResponseEntity 
    return new ResponseEntity<Object>(errorDto, HttpStatus.BAD_REQUEST); 
} 

UPDATE

я был фактически в состоянии запустить образец кода fé но, что происходит, Исключение, которое вы бросаете, завершается в ConversionFailedException, затем в TypeMismatchException и, наконец, в MethodArgumentTypeMismatchException, и это то, что возвращается клиенту. Поэтому, даже если вам удастся запустить его с помощью настраиваемого конвертера, есть дополнительная работа по распространению вашего исключения клиенту и не обернута в MethodArgumentTypeMismatchException.

+0

Извините, этот код не имеет отношения к проблеме. Исключение ** обработка ** отлично работает .. Проблема здесь заключается в том, чтобы бросить ** настраиваемое исключение **, чтобы явно указать клиенту, что UUID является недопустимым элементом в запросе с использованием конвертера весенних загрузок. Что касается вашего обновления: это то, что вы можете избежать, используя пользовательские исключения – Tim

+0

Действительно ли вы отлаживали свой код, чтобы узнать, вызывается ли метод конвертации? – hovanessyan

+0

С ExceptionHandler вы все равно можете отправить клиенту любую информацию, которую вы хотите. Насколько я понимаю, ваше приложение отправит обратно JSON, так что неважно, построите ли вы JSON из того или иного исключения или из какого-либо другого класса. Обычно в REST состояние ошибки указывается через коды состояния HTTP, которые вы можете установить с помощью ExceptionHandler. – hovanessyan

1

Я знаю только об этой проблеме, потому что я сделал то же самое себя с другим классом и часов отладки провел ...

The UUIDConverter является боб already a registered by Spring itself. Выбирайте буквально любое другое имя, и вы должны увидеть его.

+0

Да, нужно попробовать. В этом случае я ожидал бы исключения NoUniqueBean или что-то подобное:/Спасибо за ваш намек! – Tim