Spring Boot集成Camel开发REST接口JSON校验空指针问题求助
问题原因分析
1. 第一种写法校验不生效的原因
Camel Rest DSL的执行逻辑是:只有写在.route()闭包内的处理器才会被纳入请求处理链。第一种写法中将json-validator调用放在了.route()之前,这部分配置不会被执行,请求直接进入后续的Bean调用逻辑,因此校验没有生效。
2. 调整后抛出NullPointerException的原因
你配置了restConfiguration().bindingMode(RestBindingMode.json)且指定了.type(Book.class),Camel会自动将入站的JSON请求反序列化为Book POJO对象。而json-validator组件默认要求入站消息为原始JSON字符串,收到POJO对象后无法正常读取JSON内容,再加上你使用的json-schema-validator 1.0.38版本存在已知bug:当JSON Schema没有配置$id属性时,加载schema会触发空指针异常,两个因素叠加导致报错。
解决方案
第一步:修复Schema文件
在你的book-fe.json和后续要编写的后端Schema文件头部添加$id属性,示例如下:
{ "$id": "http://example.com/schemas/book-fe.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "id": {"type": "integer"}, "name": {"type": "string"}, "author": {"type": "string"}, "price": {"type": "number"} }, "required": ["id", "name", "author", "price"] }
如果不想修改Schema,也可以直接升级json-schema-validator依赖版本到1.0.49及以上,该版本已经修复了空指针问题。
第二步:调整路由逻辑
调整路由顺序,先校验原始JSON请求,再做反序列化和转换,完整路由示例如下,同时兼容JSON/XML两种格式:
@Component public class BookRoute extends RouteBuilder { @Autowired private ObjectMapper objectMapper; @Override public void configure() throws Exception { // 配置rest支持json和xml两种格式 restConfiguration() .component("servlet") .bindingMode(RestBindingMode.auto) .dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES"); rest("/books") .consumes("application/json,application/xml") .produces("application/json,application/xml") .post() .route() // 根据Content-Type选择对应校验器 .choice() .when(header(Exchange.CONTENT_TYPE).isEqualTo(MediaType.APPLICATION_JSON_VALUE)) .to("json-validator:book-fe.json") // 校验通过后转成前端POJO .unmarshal().json(JsonLibrary.Jackson, BookFe.class) .when(header(Exchange.CONTENT_TYPE).isEqualTo(MediaType.APPLICATION_XML_VALUE)) .to("validator:book-fe.xsd") // 校验通过后转成前端POJO .unmarshal().jacksonXml(BookFe.class) .end() // 前端格式转后端格式 .bean(BookConverter.class, "convertFeToBe(${body})") // 后端格式校验 .marshal().json(JsonLibrary.Jackson) .to("json-validator:book-be.json") // 转成后端POJO .unmarshal().json(JsonLibrary.Jackson, BookBe.class) // 调用Mock服务,这里用mock组件模拟,实际可替换为http请求 .to("mock:backend-service") // 构造返回响应 .setBody(constant(Map.of("code", 200, "msg", "操作成功", "data", body()))) .endRest() .get() .route() .bean(BookService.class, "getAllBooks()") .end(); // 配置Mock服务的响应 from("mock:backend-service") .log("Mock服务收到后端格式请求:${body}") .setBody(constant(Map.of("result", "success", "bookId", simple("${body.id}")))); } }
第三步:补充必要的类定义
- 定义前端
BookFe、后端BookBe两个POJO类 - 编写
BookConverter转换器实现前后端字段映射 - 补充后端JSON Schema
book-be.json和XML Schemabook-fe.xsd、book-be.xsd
验证方式
启动服务后发送POST请求到/books接口,传入不符合Schema的参数会直接返回校验错误,符合要求的请求会完成转换并返回Mock响应。
内容的提问来源于stack exchange,提问作者Alvaro Mancera Diaz
相关产品推荐
相关产品推荐

