Quiero usar una forma genérica de administrar códigos de error 5xx, digamos específicamente el caso cuando la base de datos está inactiva en toda mi aplicación de primavera. Quiero un bonito json de error en lugar de un seguimiento de pila.
Para los controladores, tengo una @ControllerAdvice
clase para las diferentes excepciones y esto también está detectando el caso de que la base de datos se detiene en medio de la solicitud. Pero esto no es todo. También tengo una CorsFilter
extensión personalizada OncePerRequestFilter
y allí, cuando llamo, doFilter
obtengo el CannotGetJdbcConnectionException
y no será administrado por el @ControllerAdvice
. Leí varias cosas en línea que solo me confundieron más.
Entonces tengo muchas preguntas:
- ¿Necesito implementar un filtro personalizado? Encontré el
ExceptionTranslationFilter
pero esto solo manejaAuthenticationException
oAccessDeniedException
. - Pensé en implementar la mía propia
HandlerExceptionResolver
, pero esto me hizo dudar, no tengo ninguna excepción personalizada para administrar, debe haber una forma más obvia que esta. También intenté agregar un try / catch y llamar a una implementación deHandlerExceptionResolver
(debería ser lo suficientemente bueno, mi excepción no es nada especial) pero esto no devuelve nada en la respuesta, obtengo un estado 200 y un cuerpo vacío.
¿Hay alguna buena forma de lidiar con esto? Gracias
fuente
Respuestas:
Entonces esto es lo que hice:
Leí los conceptos básicos sobre los filtros aquí y descubrí que necesito crear un filtro personalizado que será el primero en la cadena de filtros y tendrá una captura de prueba para detectar todas las excepciones de tiempo de ejecución que puedan ocurrir allí. Entonces necesito crear el json manualmente y ponerlo en la respuesta.
Así que aquí está mi filtro personalizado:
Y luego lo agregué en web.xml antes de
CorsFilter
. ¡Y funciona!fuente
Quería brindar una solución basada en la respuesta de @kopelitsa . Las principales diferencias son:
HandlerExceptionResolver
.Primero, debe asegurarse de tener una clase que maneja las excepciones que ocurren en un RestController / Controller normal (una clase anotada con
@RestControllerAdvice
o@ControllerAdvice
y métodos anotados con@ExceptionHandler
). Esto maneja sus excepciones que ocurren en un controlador. Aquí hay un ejemplo usando RestControllerAdvice:Para reutilizar este comportamiento en la cadena de filtros de Spring Security, debe definir un Filtro y conectarlo a su configuración de seguridad. El filtro necesita redirigir la excepción al manejo de excepciones definido anteriormente. Aquí hay un ejemplo:
Luego, el filtro creado debe agregarse a SecurityConfiguration. Debe conectarlo a la cadena muy pronto, porque no se detectarán todas las excepciones de filtro anteriores. En mi caso, era razonable agregarlo antes del
LogoutFilter
. Vea la cadena de filtros predeterminada y su orden en los documentos oficiales . Aquí hay un ejemplo:fuente
Me encontré con este problema y realicé los pasos a continuación para reutilizar mi
ExceptionController
que está anotado@ControllerAdvise
paraExceptions
arrojarlo en un filtro registrado.Obviamente, hay muchas formas de manejar la excepción pero, en mi caso, quería que la excepción fuera manejada por mi
ExceptionController
porque soy terco y también porque no quiero copiar / pegar el mismo código (es decir, tengo algo de procesamiento / registro código enExceptionController
). Me gustaría devolver la hermosaJSON
respuesta al igual que el resto de las excepciones lanzadas no desde un filtro.De todos modos, logré hacer uso de mi
ExceptionHandler
y tuve que hacer un poco más como se muestra a continuación en los pasos:Pasos
@ControllerAdvise
ejemplo, MyExceptionControllerCódigo de muestra
Y ahora el controlador Spring de muestra que se maneja
Exception
en casos normales (es decir, excepciones que generalmente no se lanzan en el nivel de filtro, el que queremos usar para las excepciones lanzadas en un filtro)Compartiendo la solución con quienes deseen utilizarla
ExceptionController
paraExceptions
lanzarla en un Filtro.fuente
@Component
clase y usarla en el Filtro y en el controlador.answer
esta es una de las formas. No he dicho que sea la mejor forma. Gracias por compartir su inquietud @psv Estoy seguro de que la comunidad apreciará la solución que tiene en mente :)Entonces, esto es lo que hice basado en una combinación de las respuestas anteriores ... Ya teníamos una
GlobalExceptionHandler
anotación con@ControllerAdvice
y también quería encontrar una manera de reutilizar ese código para manejar las excepciones que provienen de los filtros.La solución más simple que pude encontrar fue dejar el controlador de excepciones solo e implementar un controlador de errores de la siguiente manera:
Por lo tanto, los errores causados por excepciones primero pasan por el
ErrorController
y se redirigen al controlador de excepciones volviéndolos a lanzar desde dentro de un@Controller
contexto, mientras que cualquier otro error (no causado directamente por una excepción) pasa por elErrorController
sin modificación.¿Alguna razón por la que esto es realmente una mala idea?
fuente
@Override public String getErrorPath() { return null; }
Si desea una forma genérica, puede definir una página de error en web.xml:
Y agregue mapeo en Spring MVC:
fuente
Esta es mi solución al anular el controlador Spring Boot / error predeterminado
fuente
Solo para complementar las otras buenas respuestas proporcionadas, ya que recientemente quería un solo componente de manejo de errores / excepciones en una aplicación SpringBoot simple que contiene filtros que pueden arrojar excepciones, con otras excepciones potencialmente lanzadas desde métodos de controlador.
Afortunadamente, parece que no hay nada que le impida combinar los consejos de su controlador con una anulación del controlador de errores predeterminado de Spring para proporcionar cargas útiles de respuesta coherentes, permitirle compartir lógica, inspeccionar excepciones de filtros, capturar excepciones específicas lanzadas por servicios, etc.
P.ej
fuente
Cuando desee probar el estado de una aplicación y, en caso de un problema, devolver el error HTTP, sugeriría un filtro. El siguiente filtro maneja todas las solicitudes HTTP. La solución más corta en Spring Boot con un filtro javax.
En la implementación puede haber varias condiciones. En mi caso, el applicationManager prueba si la aplicación está lista.
fuente
Después de leer los diferentes métodos sugeridos en las respuestas anteriores, decidí manejar las excepciones de autenticación utilizando un filtro personalizado. Pude manejar el estado y los códigos de respuesta usando una clase de respuesta de error usando el siguiente método.
Creé un filtro personalizado y modifiqué mi configuración de seguridad usando el método addFilterAfter y lo agregué después de la clase CorsFilter.
Clase SecurityConfig
Clase ErrorResponse
fuente
Puede utilizar el siguiente método dentro del bloque de captura:
Tenga en cuenta que puede usar cualquier código HttpStatus y un mensaje personalizado.
fuente
Es extraño porque @ControllerAdvice debería funcionar, ¿está detectando la excepción correcta?
También intente capturar esta excepción en CorsFilter y envíe el error 500, algo como esto
fuente
Filter
no se atrape@ControllerAdvice
porque es posible que no alcanceDispatcherServlet
.No es necesario crear un filtro personalizado para esto. Resolvimos esto creando excepciones personalizadas que extienden ServletException (que se lanza desde el método doFilter, que se muestra en la declaración). Estos son luego capturados y manejados por nuestro controlador de errores global.
editar: gramática
fuente