Rest DSL 绑定与配置
Rest DSL - 绑定与配置
使用 POJO 进行绑定
Rest DSL 支持使用数据格式将 json/xml 内容自动绑定到 POJO 或从 POJO 反绑定。默认情况下,绑定模式是关闭的,也就是说,对于传入和传出的消息都不会进行自动绑定。
如果你开发的 POJO 与 REST 服务的请求和响应类型相对应,那么你可能希望使用绑定功能。这样,作为开发者,你就可以在 Java 代码中直接操作这些 POJO。
绑定模式有:
| 绑定模式 | 说明 |
|---|---|
off | 关闭绑定。这是默认选项。 |
auto | 启用绑定,Caml 采用宽松模式,只要类路径中包含所需的数据格式,就支持 JSON、XML 或两者。请注意,例如若类路径中没有 camel-jaxb,则不会启用 XML 绑定。另外,对于 XML,默认使用 jaxb,若想改用 jackson XML,必须显式设置 xmlDataFormat=jacksonXml。 |
json | 启用与 JSON 之间的绑定,需要类路径中具备支持 JSON 的数据格式。默认情况下,Camel 会使用 jackson 作为数据格式。 |
xm | 启用与 XML 之间的绑定,需要类路径中有 camel-jaxb 或 camel-jacksonxml。 |
json_xml | 启用与 JSON 和 XML 之间的绑定,需要两种数据格式都在类路径中。 |
在 auto 绑定模式下,当传入请求没有 Content-Type 头(或该头未指明 JSON 或 XML)时,consumes 选项用作格式检测的回退依据。它不会拒绝 Content-Type 与 consumes 不匹配的请求。例如,配置为 .consumes("application/json").bindingMode(auto) 的端点,当客户端发送 Content-Type: application/xml 且 classpath 中存在支持 XML 的数据格式(例如 camel-jaxb)时,仍然会接受并反序列化 XML 请求。如果你需要强制要求 Content-Type 与 consumes 声明相匹配,可使用 clientRequestValidation(true) 启用客户端请求与响应校验,对于内容类型不匹配的请求将返回 HTTP 415。或者,使用显式的绑定模式(json 或 xml)来限制可用的数据格式。 |
|---|
使用 camel-jaxb 进行 XML 绑定时,你可以通过 mustBeJAXBElement 选项放宽输出消息体必须是带 JAXB 注解的类这一要求。当消息体本身已经是 XML 格式,并且你希望直接将消息体原样作为输出类型时,可以使用该选项。如果是这种情况,请将 dataFormatProperty 选项 mustBeJAXBElement 设置为 false。
从 POJO 到 JSON/JAXB 的绑定仅在 content-type 头分别包含 json 或 xml 字样时才会发生。这样,当你不希望消息体尝试通过绑定进行编组时,可以指定自定义的 content-type。例如,当消息体是自定义二进制负载等情况时。
当从 POJO 自动绑定到 JSON/JAXB 时,默认情况下现有的 content-type 请求头会被替换为 application/json 或 application/xml。若要禁用该默认行为,以便在生成 JSON/JAXB 响应时使用自定义的 content-type 请求头(例如 application/user.v2+json),可按如下方式配置:
- Java
- XML
- YAML
restConfiguration().dataFormatProperty("contentTypeHeader", "false");<restConfiguration>
<dataFormatProperty key="contentTypeHeader" value="false"/>
</restConfiguration>dataFormatProperty 中的 value 必须定义为字符串值,因此我们使用带引号的字符串 "false"。
- restConfiguration:
dataFormatProperty:
- key: "contentTypeHeader"
value: "false"要使用绑定功能,你必须在 classpath 中包含所需的数据格式依赖,例如 camel-jaxb / camel-jacksonxml 和/或 camel-jackson,然后启用绑定模式。你可以在 rest 配置上全局配置绑定模式,也可以针对每个 rest 服务单独覆盖。
若要使用 Jackson XML 进行 XML 绑定,则必须配置 xmlDataformat=jacksonXml,并在 classpath 中包含 camel-jacksonxml。 |
|---|
要启用绑定,可在 Java DSL 中按如下方式进行配置:
- Java
- XML
- YAML
restConfiguration().component("netty-http").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);<restConfiguration bindingMode="auto" component="netty-http" port="8080"/>- restConfiguration:
bindingMode: "auto"
component: "netty-http"
port: "8080"启用绑定后,Camel 会根据消息的内容类型自动绑定传入和传出的消息。如果消息是 JSON,则执行 JSON 绑定;如果消息是 XML,则执行 XML 绑定。绑定同时适用于传入消息和回复消息。下表总结了传入消息和回复消息所发生的绑定情况。
| 消息体 | 方向 | 绑定模式 | 消息体 |
|---|---|---|---|
| XML | 传入 | auto,xml,json_xml | POJO |
| POJO | 传出 | auto,xml, json_xml | XML |
| JSON | 传入 | auto,json,json_xml | POJO |
| POJO | 传出 | auto,json,json_xml | JSON |
使用绑定时,还必须配置要映射到的 POJO 类型。对于传入消息这是必填项,对于传出消息则是可选的。
当使用绑定模式 json、xml 或 json_xml 时,如果尚未显式配置,Camel 会根据模式自动在 rest 端点上设置 consumers 和 produces。例如,绑定模式为 json 且 outType 设置为 UserPojo,Camel 会将此 rest 端点定义为产出 application/json。 |
|---|
例如,要将 xml/json 映射到 POJO 类 UserPojo,可以按照如下方式进行:
- Java
- XML
- YAML
// configure to use netty-http on localhost with the given port
// and enable auto binding mode
restConfiguration().component("netty-http").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);
// use the rest DSL to define the rest services
rest("/users/")
.post().type(UserPojo.class)
.to("direct:newUser");<restConfiguration component="netty-http" host="localhost" port="{{portNum}}" bindingMode="auto"/>
<rest>
<post path="/users" type="com.foo.UserPojo">
<to uri="direct:newUser"/>
</post>
</rest>- restConfiguration:
component: "netty-http"
host: "localhost"
port: "{{portNum}}"
bindingMode: "auto"
- rest:
post:
- path: "/users"
to: "direct:newUser"
type: "com.foo.UserPojo"注意,我们使用 type 来定义传入的类型。我们还可以选择性地定义传出的类型(这可能是个好主意,这样既能从 DSL 中明确该类型,也能让工具和 JMX API 了解 REST 服务的传入与传出类型)。要定义传出类型,我们使用 outType,如下所示:
- Java
- XML
- YAML
// configure to use netty-http on localhost with the given port
// and enable auto binding mode
restConfiguration().component("netty-http").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);
// use the rest DSL to define the rest services
rest("/users/")
.post().type(UserPojo.class).outType(CountryPojo.class)
.to("direct:newUser");<restConfiguration component="netty-http" host="localhost" port="{{portNum}}" bindingMode="auto"/>
<rest>
<post path="/users" type="com.foo.UserPojo" outType="com.foo.CountryPojo">
<to uri="direct:newUser"/>
</post>
</rest>- restConfiguration:
component: "netty-http"
host: "localhost"
port: "{{portNum}}"
bindingMode: "auto"
- rest:
post:
- path: "/users"
to: "direct:newUser"
type: "com.foo.UserPojo"
outType: "com.foo.CountryPojo"要使用数组来指定输入和/或输出,请在规范类名的末尾添加 [],如下所示:
- Java
- XML
- YAML
注意我们在 Java 中是如何将其声明为数组类的。
// configure to use netty-http on localhost with the given port
// and enable auto binding mode
restConfiguration().component("netty-http").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);
// use the rest DSL to define the rest services
rest("/users/")
.post().type(UserPojo[].class).outType(CountryPojo[].class)
.to("direct:newUser");<restConfiguration component="netty-http" host="localhost" port="{{portNum}}" bindingMode="auto"/>
<rest>
<post path="/users" type="com.foo.UserPojo[]" outType="com.foo.CountryPojo[]">
<to uri="direct:newUser"/>
</post>
</rest>- restConfiguration:
component: "netty-http"
host: "localhost"
port: "{{portNum}}"
bindingMode: "auto"
- rest:
post:
- path: "/users"
to: "direct:newUser"
type: "com.foo.UserPojo[]"
outType: "com.foo.CountryPojo[]"UserPojo 只是一个普通的 POJO,带有 getter/setter,如下所示:
public class UserPojo {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}UserPojo 只支持 JSON,因为 XML 需要使用 JAXB 注解,所以如果想同时支持 XML,可以添加这些注解。
@XmlRootElement(name = "user")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserPojo {
@XmlAttribute
private int id;
@XmlAttribute
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}通过 JAXB 注解,该 POJO 同时支持 JSON 和 XML 绑定。
Camel Rest-DSL 配置
Rest DSL 支持以下选项:
| 名称 | 默认值 | 类型 | 描述 |
|---|---|---|---|
| apiComponent | String | 设置用作 REST API 的 Camel 组件名称(例如 swagger 或 openapi) | |
| apiContextPath | String | 设置 REST API 服务将要使用的前置 API 上下文路径。当使用诸如 camel-servlet 之类以上下文路径方式部署的 Web 应用程序的组件时,可以使用此选项。 | |
| apiHost | String | 为 API 文档(例如 swagger 或 openapi)指定特定的主机名。可用于用该配置的主机名覆盖自动生成的主机名。 | |
| apiProperties | Map | 设置 API 级别的附加选项 | |
| apiVendorExtension | false | boolean | 是否在 Rest API 中启用厂商扩展。如果启用,Camel 会将额外信息作为厂商扩展(例如,以 x- 开头的键)包含进来,如路由 ID、类名等。并非所有第三方 API 网关和工具在导入你的 API 文档时都支持厂商扩展。 |
| bindingMode | off | RestBindingMode | 设置 REST 消费者要使用的绑定模式 |
| clientRequestValidation | false | boolean | 是否启用客户端请求校验,检查:1) Content-Type 请求头是否与 Rest DSL 所消费的类型匹配;校验失败时返回 HTTP 状态码 415。2) Accept 请求头是否与 Rest DSL 所产生的类型匹配;校验失败时返回 HTTP 状态码 406。3) 是否缺少必需的数据(查询参数、HTTP 请求头、消息体);校验失败时返回 HTTP 状态码 400。4) 消息体解析错误(必须启用 JSON、XML 或自动绑定模式);校验失败时返回 HTTP 状态码 400。 |
| clientResponseValidation | false | boolean | 是否检查 Camel 返回给客户端的响应:1) 状态码和 Content-Type 是否与 Rest DSL 的响应消息匹配。2) 检查是否包含 Rest DSL 响应消息头中预期的请求头。3) 如果响应体是 JSON,则检查其是否为有效的 JSON。检测到校验错误时返回 500。 |
| component | String | 设置用作 REST 消费者的 Camel 组件名称 | |
| componentProperties | Map | 设置组件级别的附加选项 | |
| consumerProperties | Map | 设置消费者级别的附加选项 | |
| contextPath | String | 设置 REST 服务将要使用的前置上下文路径。当使用诸如 camel-servlet 之类以上下文路径方式部署的 Web 应用程序的组件时,可以使用此选项;也可用于包含 HTTP 服务器的组件,如 camel-jetty 或 camel-netty-http。 | |
| corsHeaders | Map | 设置在启用 CORS 时要使用的 CORS 请求头。 | |
| dataFormatProperties | Map | 设置数据格式级别的附加选项 | |
| enableCORS | false | boolean | 指定是否启用 CORS,即 Camel 会自动在响应的 HTTP 请求头中加入 CORS 信息。此选项默认为 false。 |
| enableNoContentResponse | false | boolean | 指定当响应包含空的 JSON 对象或 XML 根对象时,是否返回响应体为空的 HTTP 204。 |
| endpointProperties | Map | 设置端点级别的附加选项 | |
| host | String | 设置 REST 消费者要使用的主机名 | |
| hostNameResolver | allLocalIp | RestHostNameResolver | 设置用于解析主机名的解析器 |
| inlineRoutes | true | boolean | 内联 rest-dsl 中通过 direct 端点连接的路由。如果禁用,则 Rest DSL 中的每个服务都是独立的路由,意味着每个服务至少要有两条路由(rest-dsl,以及从 rest-dsl 连接的路由)。默认情况下,这使得 Camel 能够将其优化并内联为单条路由。不过,这要求使用 direct 端点,且每个服务的 direct 端点必须唯一。 |
| jsonDataFormat | String | 设置要使用的自定义 JSON 数据格式。注意:此选项仅用于设置数据格式的自定义名称,而不是引用已有的数据格式实例。 | |
| port | int | 设置 REST 消费者要使用的端口 | |
| producerApiDoc | String | 设置 REST 生产者将使用的 API 文档(swagger API)的位置,用于校验 REST URI 和查询参数是否符合该 API 文档…… | |
| producerComponent | String | 设置用作 REST 生产者的 Camel 组件名称 | |
| scheme | String | 设置 REST 消费者要使用的协议 | |
| skipBindingOnErrorCode | true | boolean | 当存在自定义 HTTP 错误码时,是否跳过输出绑定,而直接使用响应体。此选项默认为 true。 |
| useXForwardHeaders | true | boolean | 是否使用 X-Forward 请求头为 Swagger 设置主机等信息。此选项默认为 true。 |
| xmlDataFormat | String | 设置要使用的自定义 XML 数据格式。注意:此选项仅用于设置数据格式的自定义名称,而不是引用已有的数据格式实例。 |
例如,要在端口 9091 上为 jetty 组件配置请求缓冲区,可以按如下方式进行:
- Java
- XML
- YAML
restConfiguration().component("jetty").port(9091).componentProperty("requestBufferSize", "50000");<restConfiguration component="jetty" port="9091">
<componentProperty key="requestBufferSize" value="50000"/>
</restConfiguration>- restConfiguration:
component: "jetty"
port: "9091"
componentProperty:
- key: "requestBufferSize"
value: "50000"如果尚未显式配置任何组件,Camel 将查找是否存在与 Rest DSL 集成的 Camel 组件,或者注册表中是否注册了 org.apache.camel.spi.RestConsumerFactory。若找到其中之一,便会使用它。
你可以在以下层级配置属性。
- component(组件)—— 用于设置 Component 类上的任意选项。你也可以直接在组件上配置这些选项。
- endpoint(端点)—— 用于设置端点层级的任意选项。许多 Camel 组件在端点层级提供了大量可供设置的选项。
- consumer(消费者)—— 用于设置消费者层级的任意选项。
- data format(数据格式)—— 用于设置数据格式的任意选项。例如,启用 JSON 数据格式的美化打印。
- cors headers(CORS 头)—— 若启用了 CORS,可以设置自定义的 CORS 头。当前使用的默认值见下文。如果设置了自定义头,则该值优先于默认值。
同一层级可以设置多个选项,例如你可以配置两个组件选项、三个端点选项,等等。
OAuth Bearer 令牌校验
对于支持 OAuth Bearer 令牌校验的 HTTP 消费者组件,如 platform-http、servlet、jetty、netty-http 和 undertow,请通过 endpointProperty 设置 oauthProfile 端点选项:
- Java
- XML
- YAML
restConfiguration()
.component("netty-http")
.endpointProperty("oauthProfile", "myprofile");<restConfiguration component="netty-http">
<endpointProperty key="oauthProfile" value="myprofile"/>
</restConfiguration>- restConfiguration:
component: netty-http
endpointProperty:
- key: oauthProfile
value: myprofile使用默认验证器实现时,请将 camel-oauth 组件添加到应用类路径中,并通过 camel.oauth.<profile>.* 属性来配置指定的 profile。OAuth 校验会在路由处理器之前执行。根据所选 HTTP 消费者的不同,传输层可能已经接收、解码或绑定了入站请求的部分内容。
对于有效的令牌,路由代码可以从交换属性中读取验证结果:
OAuthTokenValidationResult result = exchange.getProperty(
"CamelOAuthTokenValidationResult",
OAuthTokenValidationResult.class);启用或禁用 Jackson JSON 功能
使用 JSON 绑定时,你可能希望开启或关闭特定的 Jackson 功能。例如,要禁用“遇到未知属性即失败”的行为(例如 JSON 输入中包含一个无法映射到 POJO 的属性),则可按如下方式通过 dataFormatProperty 进行配置:
- Java
- XML
- YAML
restConfiguration().component("jetty").host("localhost").port(getPort()).bindingMode(RestBindingMode.json)
.dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES");可以通过用逗号分隔各值来禁用更多功能,例如:
.dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE");同样,你可以使用 enableFeatures 来启用相关功能,例如:
restConfiguration().component("jetty").host("localhost").port(getPort()).bindingMode(RestBindingMode.json)
.dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE")
.dataFormatProperty("json.in.enableFeatures", "FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS");<restConfiguration component="jetty" host="localhost" port="9090" bindingMode="json">
<dataFormatProperty key="json.in.disableFeatures" value="FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE"/>
<dataFormatProperty key="json.in.enableFeatures" value="FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS"/>
</restConfiguration>- restConfiguration:
component: "jetty"
host: "localhost"
port: "9090"
bindingMode: "json"
dataFormatProperty:
- key: "json.in.disableFeatures"
value: "FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE"
- key: json.in.enableFeatures
value: "FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS"可用于在 Jackson 上启用和禁用功能的值,是以下三个 Jackson 2.x 类中枚举的名称
com.fasterxml.jackson.databind.SerializationFeaturecom.fasterxml.jackson.databind.DeserializationFeaturecom.fasterxml.jackson.databind.MapperFeature
默认 CORS 头
如果启用了 CORS,默认会使用「以下头」。你可以配置自定义 CORS 头,其优先级高于默认值。
| 键 | 值 |
|---|---|
Access-Control-Allow-Origin | * |
Access-Control-Allow-Methods | GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH |
Access-Control-Allow-Headers | Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers |
Access-Control-Max-Age | 3600 |
评论
登录后参与评论
KnowForge