在 ControllerAdvice 之前捕获反序列化异常

2024-04-07

这是一个问题:我有一个采用输入模型的控制器。可以说

public class AppUserUpdateData {

  @NotNull
  @Size(min = 1, max = 50)
  protected String login;  
  @JsonDeserialize(using = MyDateTimeDeserializer.class)  
  protected Date startWorkDate;
  *************
  other properties and methods
  *************
}

问题是,当我想限制某个日期的下降时,尽管我在代码中处理了这种情况,但我最终得到了一个 HTTP 异常 400,没有任何消息! 这是一个控制器:

 @RequestMapping(
      value = "/users/{userId}", method = RequestMethod.PUT,
      produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
  public @ResponseBody AbstractSuccessResult updateUser(@PathVariable Long userId,
      @RequestBody AppUserUpdateData  appUserUpdateRequest, HttpServletRequest request) {    
    AbstractSuccessResult response = new AbstractSuccessResult();
    appUserService.updateUser(appUserUpdateRequest, userId);
    return response;
  }

这是一个反序列化器:

public class MyDateTimeDeserializer extends JsonDeserializer<Date> {

  @Override
  public Date deserialize(JsonParser jsonParser, DeserializationContext context)
      throws IOException, JsonProcessingException {
    try {
      return DataTypeHelper.stringToDateTime(jsonParser.getText());
    } catch (MyOwnWrittenException ex) {
      throw ex;
    }
  }  
}

In a DataTypeHelper.stringToDateTime是一些阻止无效日期字符串的验证。 我的异常有一个处理程序:

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

  @ExceptionHandler({ MyOwnWrittenException .class})
  protected ResponseEntity<Object> handleInvalidRequest(RuntimeException exc, 
    WebRequest request) {

    MyOwnWrittenException ex = (MyOwnWrittenException) exc;
    BasicErrorMessage message; = new BasicErrorMessage(ex.getMessage());    
    AbstractUnsuccessfulResult result = new AbstractUnsuccessfulResult(message);
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    return handleExceptionInternal(exc, result, headers, HttpStatus.BAD_REQUEST, request);
  }
}

问题是当一个异常MyDateTimeDeserializer已被抛出,但不会落入MyExceptionHandler但我不明白为什么?我究竟做错了什么? 响应中只是一个空响应,代码为 400(

UPD感谢 @Joe Doe 的回答,问题已经解决。这是我更新的处理程序:

@Order(Ordered.HIGHEST_PRECEDENCE)    
@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

  @ExceptionHandler({ MyOwnWrittenException .class})
  protected ResponseEntity<Object> handleInvalidRequest(RuntimeException exc, 
    WebRequest request) {

    MyOwnWrittenException ex = (MyOwnWrittenException) exc;
    BasicErrorMessage message; = new BasicErrorMessage(ex.getMessage());    
    AbstractUnsuccessfulResult result = new AbstractUnsuccessfulResult(message);
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    return handleExceptionInternal(exc, result, headers, HttpStatus.BAD_REQUEST, request);
  }

  @Override
  protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
      HttpHeaders headers, HttpStatus status, WebRequest request) {
    Throwable cause = ex.getCause();
    String message = null;
    if (cause instanceof JsonMappingException) {
      if (cause.getCause() instanceof MyOwnWrittenException) {
        return handleInvalidRequest((RuntimeException) cause.getCause(), request);
      } else {
        message = cause.getMessage();
      }
    } else {
      message = ex.getMessage();
    }
    AbstractUnsuccessfulResult result = new AbstractUnsuccessfulResult(
        new BasicErrorMessage(message));
    headers.setContentType(MediaType.APPLICATION_JSON);
    return handleExceptionInternal(ex, result, headers, HttpStatus.BAD_REQUEST, request);
  }
}

UPD在我的项目中,如果没有注释,它就无法工作@Order(Ordered.HIGHEST_PRECEDENCE)我相信这是因为项目中的 ControllerAdvices 数量


Before updateUser当你的控制器被调用时,它的参数必须被解析。这是哪里HandlerMethodArgumentResolverComposite进来,并代表一位预先登记的HandlerMethodArgumentResolvers - 在这种特殊情况下,它委托给RequestResponseBodyMethodProcessor.

通过委托,我的意思是调用解析器的resolveArgument方法。该方法间接调用deserialize反序列化器中的方法,它会抛出类型的异常MyOwnWrittenException。问题是这个异常被包裹在另一个异常中。事实上,当它传播回resolveArgument,它的类型是HttpMessageNotReadableException.

所以,与其抓MyOwnWrittenException在自定义异常处理程序中,您需要捕获类型的异常HttpMessageNotReadableException。然后,在处理该情况的方法中,您可以检查“原始”异常是否实际上是MyOwnWrittenException- 您可以通过重复调用来做到这一点getCause方法。就我而言(您的情况可能会相同),我需要致电getCause两次“解开”原始异常(HttpMessageNotReadableException -> JsonMappingException -> MyOwnWrittenException).

请注意,您不能简单地替换MyOwnWrittenException with HttpMessageNotReadableException在您的异常处理程序中,因为它与另一个方法(在运行时)冲突,专门设计用于处理后一种类型的异常,称为handleHttpMessageNotReadable.

总之,你可以这样做:

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // ex.getCause().getCause().getClass() gives MyOwnWrittenException
        // the actual logic that handles the exception...
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 ControllerAdvice 之前捕获反序列化异常 的相关文章

  • 如何在 Antlr4 中为零参数函数编写语法

    我的函数具有参数语法 如下面的词法分析器和解析器 MyFunctionsLexer g4 lexer grammar MyFunctionsLexer FUNCTION FUNCTION NAME A Za z0 9 DOT COMMA L
  • 不同类型的数组

    是否可以有一个包含两种不同类型数据的数组 我想要一个包含双精度型和字符串的数组 我尝试过 ArrayList
  • 大数据使用什么数据结构

    我有一个包含一百万行的 Excel 工作表 每行有 100 列 每行代表一个具有 100 个属性的类的实例 列值是这些属性的值 哪种数据结构最适合在这里使用来存储数百万个数据实例 Thanks 这实际上取决于您需要如何访问这些数据以及您想要
  • 如何根据运行的 jar 的结果让我的 ant 任务通过或失败?

    我正在运行 CrossCheck 无浏览器 js 单元测试 作为 ant 脚本的一部分 如果 CrossCheck 测试失败 我希望 ant 报告失败 这是 build xml 中的相关部分
  • ConcurrentHashMap 内部是如何工作的?

    我正在阅读有关 Java 并发性的 Oracle 官方文档 我想知道Collection由返回 public static
  • 如何使用 Hibernate (EntityManager) 或 JPA 调用 Oracle 函数或过程

    我有一个返回 sys refcursor 的 Oracle 函数 当我使用 Hibernate 调用该函数时 出现以下异常 Hibernate call my function org hibernate exception Generic
  • 合并来自多个 spring-boot YAML 文件的列表

    是否可以组合使用 YAML 编写的多个 spring boot 配置文件中相同元素的列表 Example postgres yml包含我的 postgres 数据库信息 它还包含我的迁移脚本的飞行路径位置 flyway locations
  • 从 GitHub 上托管的 Spring Cloud Config Server 访问存储库的身份验证问题

    我在 GitHub 上的存储库中托管配置 如果我将回购公开 一切都好 但如果我将其设为私有 我将面临 org eclipse jgit errors TransportException https github com my user m
  • 在另一个模块中使用自定义 gradle 插件模块

    我正在开发一个自定义插件 我希望能够在稍后阶段将其部署到存储库 因此我为其创建了一个独立的模块 在对其进行任何正式的 TDD 之前 我想手动进行某些探索性测试 因此 我创建了一个使用给定插件的演示模块 到目前为止 我发现执行此操作的唯一方法
  • @Autowire注释的问题(空)

    我在验证器类中自动连接的两个服务有问题 这些服务工作正常 因为在我的控制器中是自动连接的 我有一个 applicationContext xml 文件和 MyApp servlet xml 文件 我的基础包是 es unican meteo
  • 使用架构注册表对 avro 消息进行 Spring 云合约测试

    我正在查看 spring 文档和 spring github 我可以看到一些非常基本的内容examples https github com spring cloud samples spring cloud contract sample
  • 在 SWT/JFace RCP 应用程序中填充巨大的表

    您将如何在 SWT 表中显示大量行 巨大是指超过 20K 行 20 列的东西 不要问我为什么需要展示那么多数据 这不是重点 关键是如何让它尽可能快地工作 这样最终用户就不会厌倦等待 每行显示某个对象的实例 列是其属性 一些 我想使用 JFa
  • 如何在 Java 中创建接受多个值的单个注释

    我有一个名为 Retention RetentionPolicy SOURCE Target ElementType METHOD public interface JIRA The Key Bug number JIRA referenc
  • java库维护数据库结构

    我的应用程序一直在开发 所以偶尔 当版本升级时 需要创建 更改 删除一些表 修改一些数据等 通常需要执行一些sql代码 是否有一个 Java 库可用于使我的数据库结构保持最新 通过分析类似 db structure version 信息并执
  • 使用布尔值进行冒泡排序以确定数组是否已排序

    我有以下用于冒泡排序的代码 但它根本不排序 如果我删除布尔值那么它工作正常 我知道 由于我的 a 0 小于所有其他元素 因此没有执行交换 任何人都可以帮助我解决这个问题 package com sample public class Bub
  • Java Swing:需要一个高质量的带有复选框的开发 JTree

    我一直在寻找一个 Tree 实现 其中包含复选框 其中 当您选择一个节点时 树中的所有后继节点都会被自动选择 当您取消选择一个节点时 树中其所有后继节点都会自动取消选择 当已经选择了父节点 并且从其后继之一中删除了选择时 节点颜色将发生变化
  • Resteasy 可以查看 JAX-RS 方法的参数类型吗?

    我们使用 Resteasy 3 0 9 作为 JAX RS Web 服务 最近切换到 3 0 19 我们开始看到很多RESTEASY002142 Multiple resource methods match request警告 例如 我们
  • OpenCSV:将嵌套 Bean 映射到 CSV 文件

    我正在尝试将 bean 映射到 CSV 文件 但问题是我的 bean 具有其他嵌套 bean 作为属性 所发生的情况是 OpenCSV 遍历属性找到一个 bean 然后进入其中并映射该 bean 内的所有数据 如果找到另一个 bean 它就
  • 如何重新启动死线程? [复制]

    这个问题在这里已经有答案了 有哪些不同的可能性可以带来死线程回到可运行状态 如果您查看线程生命周期图像 就会发现一旦线程终止 您就无法返回到新位置 So 没有办法将死线程恢复到可运行状态 相反 您应该创建一个新的 Thread 实例
  • 在java中使用多个bufferedImage

    我正在 java 小程序中制作游戏 并且正在尝试优化我的代码以减少闪烁 我已经实现了双缓冲 因此我尝试使用另一个 BufferedImage 来存储不改变的游戏背景元素的图片 这是我的代码的相关部分 public class QuizApp

随机推荐

  • SvelteKit:如何通过别名(如 $routes)从组件和端点引用 /routes 文件夹?

    接下来是我的 简化的 项目结构 appname src lib routes jsconfig json 在 jsconfig js 文件中 我有一个路径键 其别名为 lib 形式的 src lib 文件夹 compilerOptions
  • 无法从客户端连接到 PostgreSQL - 错误超时

    经过很多天尝试连接到我的 PostgreSQL 实例后 我决定是时候寻求帮助了 我正在尝试从 Windows 计算机连接到我的 PostgreSQL 数据库 我正在尝试 pgAdmin 4 和 dBeaver 但都无法连接 下面是我使用 d
  • 如何在 TypeScript 中使用 Mocha 和 Jest 而不发生冲突?

    我正在尝试在一个项目上安装带有类型的 Mocha 和 Jest 我们使用严格的类型检查 因此我收到与冲突的全局类型相关的错误 我试图创建不明确的模块声明 仅定义 Mochatypes at tsconfig 我一直在尝试删除 Jest 的声
  • 如何在二维码上添加徽标

    我正在使用 zxing java 生成二维码 想知道一种向二维码添加徽标的方法 是否有任何内置方法可以为其添加徽标或任何替代方法 您可能必须使用另一个图像库添加图像覆盖 我设法找到了能够做到这一点的资源 http skrymerdev wo
  • JVM CPU 峰值故障排除

    我们在其中一台应用程序服务器上发现了一个有趣的 尽管相当严重 问题 在某个时间点 运行 Web 应用程序的 JVM 的 CPU 使用率开始上升 并持续上升 直到应用程序最终减慢到爬行 修复此问题的唯一方法是重新启动应用程序服务器软件 应用服
  • 使用 REST API 将端口绑定到主机接口

    命令行界面的文档说明如下 将容器的端口绑定到主机的特定接口 系统 使用docker run命令的 p参数 一般语法 docker run p
  • 是否可以使用 Apache 记录所有 HTTP 请求标头?

    如何将 apache 收到的 HTTP 请求标头 全部 的内容记录到日志文件中 目前我的apache组合日志格式配置是 LogFormat h l u t r gt s b Referer i User Agent i Cookie i c
  • 使用 Jquery 的模态 PDF IFRAME

    这是我的脚本 运行完美 没有问题 现在为什么我将其发布在这里 主要是为了我可以增强它并使其变得更好 我也认为这可以帮助其他人 JQUERY 这是一个工作示例http jsfiddle net cornelas 4eUgf 2 http js
  • vim 中递归搜索模式的函数

    我有一个包含简单文本行的文本文件 我想创建一个函数vim and gvim 文本编辑器 can be sent a variable number of patterns and it should find lines will all
  • CDF 累积分布函数误差

    我正在尝试为多列数据文件中的一列绘制 CDF 当数据文件中仅存在一列时 它可以很好地绘制 当我尝试从数据中获取特定列时 它给了我错误 我还尝试使用 for 循环来读取它读起来很好的特定列 如果我在 for 循环之外给出绘图语句 则绘图仅显示
  • C++ 中字符串文字的类型是什么? [复制]

    这个问题在这里已经有答案了 例如 字符串文字 Hello 的类型是什么 const char 6 or const char 字符串文字的类型 Hello 是 6 的数组const char 普通字符串文字和 UTF 8 字符串文字也称为窄
  • 使用 URL 进行简单的 Swift 文件下载

    因此 我将 URL 作为字符串 在本例中为 JPG 但如果可能的话 希望有一个适用于任何文件类型的通用过程 并将文件路径作为字符串 用于保存文件 实现这一点的最快方法是什么 请记住 这是针对 OSX 命令行应用程序的 我尝试了这里找到的一些
  • 如何一键点击链接即可实现“链接另存为”功能? [复制]

    这个问题在这里已经有答案了 因此 正如你们大多数人可能知道的那样 当您在网页上放置文件的链接时 您必须右键单击该链接 然后单击 链接另存为 才能下载该文件 我想知道是否有一种方法可以单击链接并自动下载文件 有一个方法 使用header 调用
  • 在 C# 中追加两个或多个字节数组

    在 C 中是否有最好的 见下文 方法来附加两个字节数组 假装我拥有完全的控制权 我可以使第一个字节数组足够大以在末尾保存第二个字节数组并使用数组 复制到 https msdn microsoft com en us library syst
  • 当返回自定义对象列表时,RxJava 突出显示错误但编译

    我正在进行 RxJava 调用 我订阅的最终结果是预订列表 代码工作正常 但我得到了这个恼人的亮点 演员阵容在这里不起作用 因为我无法演员阵容List
  • 为什么 Linux 重定向会截断文件?

    我有一个名为 test txt 的文件 如下所示 hello world 它只是一个 hello world 字符串 如果我使用 perl 正则表达式 perl pe s hello bye g test txt it says bye w
  • 使用 itextsharp 使用数据库中的图像创建 pdf

    我有一个过程 其中 html 与图像链接存储在数据库中 图像也存储在数据库中 我创建了一个从数据库读取图像的控制器操作 我生成的路径是这样的 File Image path Root test jpg 该图像路径嵌入在 html 的 img
  • 使用自定义配置在调试模式下运行 sbt 项目

    我想使用特殊配置在我的 sbt 0 11 项目中引入调试模式 我尝试使用以下代码来实现这一点 但不幸的是 它似乎没有按预期工作 我正在启动debug run但运行并未按预期暂停 object Test extends Build lazy
  • 如何在 Windows 10 上解锁詹金斯

    我使用下载的 msi 在我的 Windows 10 机器上安装了 jenkins 它安装得很好 现在启动了浏览器 提示我使用初始管理员密码解锁詹金斯 我在任何地方都找不到这个文件 我查看了安装目录 C Program Files x86 J
  • 在 ControllerAdvice 之前捕获反序列化异常

    这是一个问题 我有一个采用输入模型的控制器 可以说 public class AppUserUpdateData NotNull Size min 1 max 50 protected String login JsonDeserializ