使用ControllerAdvice自定义NohandLerexception响应

发布于 2025-02-10 02:39:09 字数 4244 浏览 1 评论 0原文

我尝试在Spring Boot REST应用程序中实现一个自定义错误响应,以解决404个错误。 我阅读了Stackoverflow中介绍的许多解决方案,没有成功。

当我调用一个无效的入口点时,我会获得此结果:

{
    "timestamp": "2022-06-22T10:38:41.114+00:00",
    "status": 404,
    "error": "Not Found",
    "path": "/ws-facturx/fx2"
}

但是我想有一个应该这样的响应:

{
    "operationId": "u044eZg2gHwtadqxB5CVv6aeMBjj0w",
    "status": "ERROR",
    "operation": "webserviceName",
    "clientName": "ACME Inc",
    "errorMessage": "Error message from Server",
    "createdAt": "2022-06-22T09:15:04.844+00:00"
}

我首先尝试使用@RestControllerAdvice在投掷时拦截异常。

@ExceptionHandler(value = {AppServiceException.class, NoHandlerFoundException.class, ServletServiceException.class })
public ResponseEntity<Object> handleAppServiceException(Exception ex,
                                                        WebRequest req) throws JsonProcessingException {
    FacturxDto request = context.getFacturxDtoContext();
    ErrorMessage errorMessage = errorMessageBuilder(request, ex);
    return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}

我还修改了我的应用程序

spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false

。我试图使用拦截器。 我向添加了一个用于将拦截器添加到InterceptorRegistry的课程:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    private final ApplicationExchangeContext context;

    public WebMvcConfig(ApplicationExchangeContext context) {
        this.context = context;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ApplicationInterceptor(context)).addPathPatterns("/**");
    }
}

我的ApplicationInterspection看起来像这样:

@Component
public class ApplicationInterceptor implements HandlerInterceptor {
    private final ApplicationExchangeContext context;

    @Autowired
    public ApplicationInterceptor(ApplicationExchangeContext context) {
        this.context = context;
    }

    //unimplemented methods comes here. Define the following method so that it
    //will handle the request before it is passed to the controller.
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (response.getStatus() == HttpStatus.NOT_FOUND.value()) {
            // si on a un 404
            System.out.println(handler);
            String requestData = request.getReader().lines().collect(Collectors.joining());
            System.out.println(requestData);
            Gson gson = new Gson();
            FacturxDto facturxDto = gson.fromJson(requestData, FacturxDto.class);
            context.setFacturxDtoContext(facturxDto);
            throw new ServletServiceException("404...");
        }
        System.out.println("Done in preHandle");
        return true;
        // return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        System.out.println(request);
        System.out.println(response);
        if (response.getStatus() == HttpStatus.NOT_FOUND.value()) {
            // si on a un 404
            System.out.println(handler);
            String requestData = request.getReader().lines().collect(Collectors.joining());
            System.out.println(requestData);
            Gson gson = new Gson();
            FacturxDto facturxDto = gson.fromJson(requestData, FacturxDto.class);
            context.setFacturxDtoContext(facturxDto);
            throw new ServletServiceException("404...");
        }
        System.out.println("Done in afterCompletion");
    }
}

在预汉中,我确实到达了代码块的捕获部分,但我无法访问应该处理此例外并构建我的预期对象的RestControllerRADVICE方法。

抛出了例外。但是我不会将其退还给用户。相反,我确实有一个HTML页面。

I try to implement a custom error response in a spring boot rest application for 404 errors.
I read many of the solutions presented in stackoverflow, without success.

When I call an invalid entry point I obtain this result:

{
    "timestamp": "2022-06-22T10:38:41.114+00:00",
    "status": 404,
    "error": "Not Found",
    "path": "/ws-facturx/fx2"
}

But i'd like to have a response that should look like this:

{
    "operationId": "u044eZg2gHwtadqxB5CVv6aeMBjj0w",
    "status": "ERROR",
    "operation": "webserviceName",
    "clientName": "ACME Inc",
    "errorMessage": "Error message from Server",
    "createdAt": "2022-06-22T09:15:04.844+00:00"
}

I first tried to use @RestControllerAdvice to intercept the exception when they are thrown.

@ExceptionHandler(value = {AppServiceException.class, NoHandlerFoundException.class, ServletServiceException.class })
public ResponseEntity<Object> handleAppServiceException(Exception ex,
                                                        WebRequest req) throws JsonProcessingException {
    FacturxDto request = context.getFacturxDtoContext();
    ErrorMessage errorMessage = errorMessageBuilder(request, ex);
    return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}

I also modified my application.properties :

spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false

If i call a non defined entry point I do not reach this method. I tried to use an interceptor.
I firs added a class for adding interceptor to InterceptorRegistry:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    private final ApplicationExchangeContext context;

    public WebMvcConfig(ApplicationExchangeContext context) {
        this.context = context;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ApplicationInterceptor(context)).addPathPatterns("/**");
    }
}

My ApplicationInterception looks like this:

@Component
public class ApplicationInterceptor implements HandlerInterceptor {
    private final ApplicationExchangeContext context;

    @Autowired
    public ApplicationInterceptor(ApplicationExchangeContext context) {
        this.context = context;
    }

    //unimplemented methods comes here. Define the following method so that it
    //will handle the request before it is passed to the controller.
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (response.getStatus() == HttpStatus.NOT_FOUND.value()) {
            // si on a un 404
            System.out.println(handler);
            String requestData = request.getReader().lines().collect(Collectors.joining());
            System.out.println(requestData);
            Gson gson = new Gson();
            FacturxDto facturxDto = gson.fromJson(requestData, FacturxDto.class);
            context.setFacturxDtoContext(facturxDto);
            throw new ServletServiceException("404...");
        }
        System.out.println("Done in preHandle");
        return true;
        // return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        System.out.println(request);
        System.out.println(response);
        if (response.getStatus() == HttpStatus.NOT_FOUND.value()) {
            // si on a un 404
            System.out.println(handler);
            String requestData = request.getReader().lines().collect(Collectors.joining());
            System.out.println(requestData);
            Gson gson = new Gson();
            FacturxDto facturxDto = gson.fromJson(requestData, FacturxDto.class);
            context.setFacturxDtoContext(facturxDto);
            throw new ServletServiceException("404...");
        }
        System.out.println("Done in afterCompletion");
    }
}

On the preHandle, i do reach the catch part of the code block but i do not access the RestControllerAdvice method that should handle this exception and build my expected object.

enter image description here

The exception is thrown. But i do not return it to user. Instead I do have an HTML page.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文