2015-12-28 1 views
1

У меня есть несколько контроллеров для конечных точек RESTful, которые в настоящее время возвращают null, если в конечной точке нет ресурсов. Например,Intercept null ResponseBody перед ответом сортировки

@RequestMapping(method = ReqeustMethod.GET, value = "{id}") 
@ResponseBody 
public MyResource get(@PathVariable final Long id) { 
    return this.myService.get(id); // returns null if bad id 
} 

Я хочу вернуть определенный, отличный ресурс для клиента (ErrorResource), когда нет никакого MyResource с заданным идентификатором. Я знаю, что могу сделать это с помощью отдельного метода с @ExceptionHandler, такие как:

@RequestMapping(method = RequestMethod.GET, value = "{id}") 
@ResponseBody 
public MyResource get(@PathVariable final Long id) { 
    final MyResource myResource = this.myService.get(id); 
    if (myResource == null) { 
     throw new NotFoundException(); 
    } 
    return myResource; 
} 

@ExceptionHandler(NotFoundException.class) 
@ResponseStatus(value = HttpStatus.NOT_FOUND) 
@ResponseBody 
public ErrorResource notFoundException(
     final HttpServletRequest request, 
     final NotFoundException exception) { 

    final ErrorResource errorResource = new ErrorResource(); 
    errorResource.setStatus(HttpStatus.NOT_FOUND.value()); 
    errorResource.setDeveloperMessage("No resource found at " + request.getRequestURL()); 
    return errorResource; 
} 

И это хорошо. Но мне бы хотелось, чтобы у меня был какой-то перехватчик, который вычисляет для меня, что всякий раз, когда метод API возвращает null@ResponseBody, он должен вместо этого запустить логику в моем методе notFoundException(). Это сделает все мои методы управления немного чище. Есть ли способ сделать это?

+1

Я думаю, что вы ищете 'HandlerInterceptor'. – chrylis

+0

@chrylis я посмотрел. 'preHandle()' слишком рано, 'postCompletion()' слишком поздно. 'postHandle()' дает мне «ModelAndView». Что мне делать с этим? Проверить значение null и выбросить исключение? Перепишите содержимое части 'Model'' ModelAndView'? –

+0

Вы можете заставить сервис исключить исключение и придерживаться исключений (перемещение '@ ExceptionHandler' в классе базового контроллера) –

ответ

0

Это звучит как работа для весны HttpMessageConverter.

Вы можете написать свой собственный конвертор, реализовав интерфейс HttpMessageConverter<T>.

В вашем случае я бы осуществил конвертер HttpMessageConverter<MyResource> с нулевой проверкой на примере MyResource в методе write. Если экземпляр MyResource имеет значение NULL, тогда создайте и напишите свой экземпляр ErrorResource.

Вот пример:

import java.io.IOException; 

import org.springframework.http.HttpInputMessage; 
import org.springframework.http.HttpOutputMessage; 
import org.springframework.http.MediaType; 
import org.springframework.http.converter.HttpMessageConverter; 
import org.springframework.http.converter.HttpMessageNotReadableException; 
import org.springframework.http.converter.HttpMessageNotWritableException; 

public class MyResourceConverter implements HttpMessageConverter<MyResource> { 

    // a real message converter that will respond to ancillary methods and do the actual work 
    private HttpMessageConverter<Object> delegateConverter; 

    public MyResourceConverter(HttpMessageConverter<Object> delegateConverter){ 
     this.delegateConverter = delegateConverter; 
    } 

    @Override 
    public boolean canRead(Class<?> clazz, MediaType mediaType) { 
     return delegateConverter.canRead(clazz, mediaType) && MyResource.class.equals(clazz); 
    } 

    @Override 
    public boolean canWrite(Class<?> clazz, MediaType mediaType) { 
     return delegateConverter.canWrite(clazz, mediaType) && MyResource.class.equals(clazz); 
    } 

    @Override 
    public MyResource read(Class<? extends MyResource> clazz, 
      HttpInputMessage inputMessage) throws IOException, 
      HttpMessageNotReadableException { 
     return (MyResource) delegateConverter.read(clazz, inputMessage); 
    } 

    @Override 
    public void write(MyResource t, MediaType contentType, 
      HttpOutputMessage outputMessage) throws IOException, 
      HttpMessageNotWritableException { 
     Object result = null; 
     if(t == null){ 
      result = // build your ErrorResource here 
     }else{ 
      result = t; 
     } 
     delegateConverter.write(result, contentType, outputMessage); 

    } 
} 

Обратите внимание, что этот преобразователь должен быть зарегистрирован в конфигурации Spring. Класс конфигурации должен простираться WebMvcConfigurerAdapter и переопределить configureMessageConverters метод, как:

@Override 
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
    // Here we add our custom-configured HttpMessageConverters. 
    // yourDelegateConverter may be a MappingJackson2HttpMessageConverter instance for example 
    converters.add(new EmployeeConverter(yourDelegateConverter)); 
    super.configureMessageConverters(converters); 
} 

Ссылки (из официальной документации Spring):

Смежные вопросы