我有一个带有 jersey 2.27 服务器应用程序的 glassfish 5,它有一个自定义响应过滤器,在某些情况下会引发自定义业务异常。
响应过滤器如下所示:
public class CustomResponseFilter implements ContainerResponseFilter {
....
@Override
public void filter(ContainerRequestContext request, ContainerResponseContext response) {
....
if (something_is_true) {
throw new CustomException(A_CUSTOM_MESSAGE);
}
}
...
}
异常和异常映射器的定义如下:
public class CustomException extends RuntimeException {
public CustomException(String message) {
super(message);
}
}
@Provider
public class CustomException400Mapper implements ExceptionMapper<CustomException> {
...
@Override
public Response toResponse(CustomException t) {
Error entity = new Error(HttpServletResponse.SC_BAD_REQUEST,
HEADER_INVALID, CONTRACT_NUMBER_HEADER);
return Response.status(HttpServletResponse.SC_BAD_REQUEST).
entity(entity).
type(MediaType.APPLICATION_JSON).
build();
}
}
一个请求通过端点,然后当它到达自定义响应过滤器时,它会抛出上面的自定义异常。
异常由 jersey 框架捕获和处理。使用异常映射器将其转换为响应。
我的问题是响应没有返回给客户端,而是调用了一个processResponse(response)
方法,再次调用所有响应过滤器。这基本上再次抛出相同的错误,女巫被捕获并包装到 Internal Server Error中。
您可以看到下面的球衣框架代码以及我这边的一些评论。
package org.glassfish.jersey.server;
...
public class ServerRuntime {
...
public void process(final Throwable throwable) {
final ContainerRequest request = processingContext.request();
...
ContainerResponse response = null;
try {
final Response exceptionResponse = mapException(throwable);
try {
try {
response = convertResponse(exceptionResponse);
if (!runtime.disableLocationHeaderRelativeUriResolution) {
ensureAbsolute(response.getLocation(), response.getHeaders(), request,
runtime.rfc7231LocationHeaderRelativeUriResolution);
}
processingContext.monitoringEventBuilder().setContainerResponse(response)
.setResponseSuccessfullyMapped(true);
} finally {
processingContext.triggerEvent(RequestEvent.Type.EXCEPTION_MAPPING_FINISHED);
}
// response is correctly mapped from CustomException400Mapper
// this triggers the response filters to be runned again
// throws the same Exception again
processResponse(response);
} catch (final Throwable respError) { // the exception is catched here and retrown again
LOGGER.log(Level.SEVERE, LocalizationMessages.ERROR_PROCESSING_RESPONSE_FROM_ALREADY_MAPPED_EXCEPTION());
processingContext.monitoringEventBuilder()
.setException(respError, RequestEvent.ExceptionCause.MAPPED_RESPONSE);
processingContext.triggerEvent(RequestEvent.Type.ON_EXCEPTION);
throw respError;
}
} catch (final Throwable responseError) { // the exception is catched here
if (throwable != responseError
&& !(throwable instanceof MappableException && throwable.getCause() == responseError)) {
LOGGER.log(Level.FINE, LocalizationMessages.ERROR_EXCEPTION_MAPPING_ORIGINAL_EXCEPTION(), throwable);
}
// I`ve tried to use processResponseError method to return the response exception but it calls processResponse(...) method witch call`s the response filters and it fails and returns false.
if (!processResponseError(responseError)) {
// Pass the exception to the container.
LOGGER.log(Level.FINE, LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER(), responseError);
try {
// here it returns the exception mapped into an Internal Server Error Response
request.getResponseWriter().failure(responseError);
} finally {
completionCallbackRunner.onComplete(responseError);
}
}
} finally {
release(response);
}
}
我的问题是如何从响应过滤器中抛出的自定义异常返回响应?
谢谢!