0

我有一个带有 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);
            }
        }

我的问题是如何从响应过滤器中抛出的自定义异常返回响应?

谢谢!

4

0 回答 0