Я не знаю, есть ли идиоматический c способ сделать это, но я нашел способ программно добавлять обработчики исключений.
(я подожду несколько недель, чтобы пометить это как принимаются, если кто-то хочет предложить альтернативу.)
Код здесь:
https://gist.github.com/drewctaylor/f838eb8304d7c526872ed29934a1e830
В конечном счете, я подкласс ExceptionHandlerExceptionResolver
. Под капотом ExceptionHandlerExceptionResolver
по существу отображается от java.lang.Class<java.lang.Exception>
до java.lang.reflect.Method
; если происходит исключение данного типа, система возвращает данный метод.
Эта реализация принимает список сопоставлений от java.lang.Class<java.lang.Exception>
до java.lang.reflect.Method
. Если возникает исключение типа в этом списке, он возвращает связанный метод; в противном случае относится к суперклассу.
Код для реализации, ExceptionHandlerExceptionResolverFromList
:
public class ExceptionHandlerExceptionResolverFromList
extends ExceptionHandlerExceptionResolver
{
private final Map<Class<?>, ExceptionHandlerWithExceptionClassAndMethod<?>> map;
public ExceptionHandlerExceptionResolverFromList(
final List<ExceptionHandlerWithExceptionClassAndMethod<?>> list)
{
requireNonNull(list);
map = list.stream().collect(toMap(ExceptionHandlerWithExceptionClassAndMethod::getExceptionClass, Function.identity()));
}
@Nullable
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
@Nullable final HandlerMethod handlerMethod,
final Exception exception)
{
requireNonNull(exception);
return map.containsKey(exception.getClass()) ?
new ServletInvocableHandlerMethod(map.get(exception.getClass()), map.get(exception.getClass()).getMethod()) :
super.getExceptionHandlerMethod(handlerMethod, exception);
}
}
Отображение определяется реализацией интерфейса ExceptionHandlerWithExceptionClassAndMethod
:
public interface ExceptionHandlerWithExceptionClassAndMethod<E extends Exception>
{
Class<E> getExceptionClass();
Method getMethod();
}
Специфической реализацией c является ExceptionHandlerForHttpRequestMethodNotSupportedException
, аналогично примеру в вопросе:
public class ExceptionHandlerForHttpRequestMethodNotSupportedException
implements ExceptionHandlerWithExceptionClassAndMethod<HttpRequestMethodNotSupportedException>
{
@Override
public Class<HttpRequestMethodNotSupportedException> getExceptionClass()
{
return HttpRequestMethodNotSupportedException.class;
}
@Override
public Method getMethod()
{
try
{
return getClass().getDeclaredMethod(
"handle",
HttpRequestMethodNotSupportedException.class,
HttpServletRequest.class,
HttpServletResponse.class);
}
catch (Exception exception)
{
throw new RuntimeException(exception);
}
}
public ResponseEntity<String> handle(
final HttpRequestMethodNotSupportedException httpRequestMethodNotSupportedException,
final HttpServletRequest httpServletRequest,
final HttpServletResponse httpServletResponse)
{
return ResponseEntity.status(METHOD_NOT_ALLOWED).body(
format(
"Unsupported method '%s' for URI '%s'; expected method among: %s.",
httpRequestMethodNotSupportedException.getMethod(),
httpServletRequest.getRequestURI(),
join(", ", asList(httpRequestMethodNotSupportedException.getSupportedMethods()).stream().map(object -> "'" + object + "'").collect(toList()))));
}
}
Обратите внимание, что вышеприведенное объединяет отображение с реализацией обработчика, который не является строго необходимо, но в настоящее время кажется уместным.
Чтобы добавить обработчик в приложение, расширьте Configuration
с WebMvcConfigurationSupport
и переопределите createExceptionHandlerExceptionResolver
для возврата экземпляра ExceptionHandlerExceptionResolverFromList
:
@org.springframework.context.annotation.Configuration
public class Configuration
extends WebMvcConfigurationSupport
{
protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver()
{
return new ExceptionHandlerExceptionResolverFromList(asList(
new ExceptionHandlerForHttpRequestMethodNotSupportedException()));
}
}
Приложение теперь будет использовать ExceptionHandlerForHttpRequestMethodNotSupportedException
для обработки HttpRequestMethodNotSupportedException
; для других исключений он будет использовать любые другие определенные обработчики.