Já falei sobre a anotação @ExceptionHandler do Spring e como você pode usá-la para lidar com erros em um controlador como um controlador de base para dar a você um controle refinado sobre como lidar com erros em seu código. A pergunta para considerar agora é se você quer sempre esse controle refinado, para o qual eu estou supondo que, em determinadas circunstâncias, a resposta será não e, então, acomodar este Spring nos forneceu o SimpleMappingExceptionHandler.
O SimpleMappingExceptionHandler é uma implementação da classe HandlerExceptionResolver do Sprins, que, como já mencionei antes, o Spring usa para gerenciar exceções lançadas pelo seu código. O Spring possui uma limitação (se é que é isso), na medida em que carrega apenas uma implementação HandlerExceptionResolver a qualquer momento. A implementação padrão é AnnotationMethodHandlerExceptionResolver, o que obriga você a fazer uma escolha entre o uso de manipulação de handler fine-grained, tal como fornecido por AnnotationMethodHandlerExceptionResolver e manipulação de handler mais grosseiro fornecido pelo SimpleMappingExceptionHandler.
O cara do Spring tornou bastante simples a adição de um SimpleMappingExceptionHandler para seu aplicativo. Para demonstrar isso, em primeiro lugar, preciso de um controlador flakey que irá lançar uma handler para gente. O código abaixo lança uma IOException quando chamado…
@RequestMapping(value = "/ioexception", method = RequestMethod.GET) public String throwAnIOException(Locale locale, Model model) throws IOException {
logger.info("This will throw an IOException");
boolean throwException = true;
if (throwException) {
throw new IOException("This is my IOException");
}
return "home";
}
… e está garantido para quebrar um webapp.
Se você estivesse com a intenção de manter as coisas super simples, a etapa final seria adicionar o seguinte XML para o arquivo de configuração do Spring:
<beans:bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<beans:property name="exceptionMappings">
<beans:map>
<beans:entry key="java.io.IOException" value="io-exception" />
<beans:entry key="java.lang.Exception" value="generic-error" />
</beans:map>
</beans:property>
</beans:bean>
O XML acima mostra uma definição muito familiar do bean do Spring. O nome dele é “exceptionResolver“, implementado pela classe SimpleMappingExceptionResolver. Essa classe possui uma propriedade map, que é a parte mais interessante dessa definição, já que ela mapeia uma classe de exceção para um nome de exibição. Na amostra, estou mapeando IOException a uma exibição chamada “io-exception” e todas as outras exceções para uma exibição chamada “generic-error’. Note que SimpleMappingExceptionHandler segue o padrão das regras de manipulação de handler do Java, então quando eu digo “todas as outras exceções”, realmente quero dizer todas as exceções, exceto IOException e suas subclasses.
Embora isso encerre as atividades para uma implementação trivial, eu gostaria de acrescentar que prefiro estender o SimpleMappingExceptionHandler para que eu possa adicionar funcionalidades adicionais, tais como um registro de erro específico para a aplicação:
public class SampleExceptionHandler extends SimpleMappingExceptionResolver {
private static final Logger logger = LoggerFactory.getLogger(SampleExceptionHandler.class);
/**
* Log the exception.
*
* @see org.springframework.web.servlet.handler.SimpleMappingExceptionResolver#doResolveException(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse, java.lang.Object,
* java.lang.Exception)
*/
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
logger.error("A " + ex.getClass().getSimpleName() + " has occured in the application", ex);
return super.doResolveException(request, response, handler, ex);
}
}
Uma vez que tenha escrito o seu próprio handler de exceção, então tudo que você tem que fazer é modificar sua configuração do Spring de modo que ele seja pega por Spring quando o webapp for carregado:
<!-- Definition(s) for the SimpleMappingExceptionResolver -->
<beans:bean id="exceptionResolver"
>
<beans:property name="exceptionMappings">
<beans:map>
<beans:entry key="java.io.IOException" value="io-exception" />
<beans:entry key="java.lang.Exception" value="generic-error" />
</beans:map>
</beans:property>
</beans:bean>
O código para este artigo está disponível aqui.
***
Texto original disponível em http://www.captaindebug.com/2012/02/using-springs-simplemappingexceptionhan.html







