概述
自5.8.0版以来,Tapestry为将REST端点作为页面类中的常规事件处理程序方法写入提供了现成的支持。它们的工作方式与激活
事件(即。onActivate()
方法)的工作方式,包括事件处理程序方法参数的工作方式@请求正文
注释已创建,因此事件处理程序方法可以访问请求正文。创建@StaticActivationContextValue注释是为了编写仅在URL路径的一个或多个部分与给定值匹配时才调用的事件处理程序方法。这两个注释都不是REST特定的,可以在任何事件处理程序方法中使用。一个新的子项目/JAR tapestry-rest-jackson自动使用jackson Databind进行JSON转换。tapestry-Swagger/OpenAPI 3.0描述是自动生成的,可以轻松定制。一个新的子项目/JAR tapestry-openapi-viewer为使用Swagger UI生成的openapi描述提供了一个现成的查看器。对于Tapestry REST支持示例项目,请查看https://github.com/thiagohp/tapestry-rest-example.
一些重要警告:
- Tapestry的REST支持不是JAX-RS的实现,所以他们希望它的任何概念都能在这里工作。它是以Tapestry方式实现的REST。
- 组件中的REST端点事件处理程序方法被忽略,就像
onActivate()
是。
支持以下HTTP方法:
HTTP方法 | Tapestry事件名称 | 事件常量 常量名称 | 事件处理程序 方法名称 |
---|
GET(获取) | httpGet(http获取) | HTTP_获取 | onHttpGet上 |
邮政 | httpPost(httpPost) | HTTP_测试 | 在HttpPost上 |
删除 | http删除 | HTTP_选择 | onHttpDelete |
PUT(输出) | httpPut | HTTP_输出 | 打开HttpPut |
头部 | httpHead(http头) | HTTP_抬头 | 在HttpHead上 |
补丁 | http补丁 | HTTP_附件 | onHttpPatch |
写入REST端点
在Tapestry中编写REST端点与编写完全相同启用()
方法。一切都是一样的:参数处理、返回值处理、优先级规则、类继承、URL等。如果您知道如何编写onActivate()
方法,您已经了解了编写REST端点事件处理程序所需的几乎所有内容。两者之间只有2个小差异onActivate()
和REST端点事件处理程序方法:
- REST事件处理程序方法在
onActivate()
. - 根据要处理的HTTP方法,事件名称不同。
因此,例如,如果您想要一个URL/userendpoint/[id]的REST端点,假设id是长
,处理GET(获取)
HTTP方法,您只需编写以下页面类和事件处理程序:
公共类UserEndpoint{对象onHttpGet(长id){(...)}(...)}
也可以使用@OnEvent(OnEvent)
注释,其工作原理相同:
公共类UserEndpoint{@OnEvent(事件常量.HTTP_GET)对象getById(长id){//或任何其他方法名(...)}(...)}
使用读取请求正文@请求正文
很多时候,特别是对于POST、PUT和PATCH请求,数据都是通过请求体发送的。要获取此数据,事件处理程序方法需要添加一个参数@请求正文
注释。它只有一个属性,allowEmpty(允许空)
,使用假
作为其默认值,用于定义空的请求体是否为空。否则,将引发异常。
@OnEvent(事件常量.HTTP_PUT)对象保存(@RequestBody User用户){(...)}@OnEvent(事件常量.HTTP_PUT)对象保存(长id,@RequestBody User用户){(...)}
现成支持以下类型:
字符串
阅读器
InputStream(输入流)
JSON对象
JSON数组
- 基元类型及其包装类型
实际转换逻辑在HttpRequestBodyConverter(HttpRequestBodyConverter)
服务,定义为的有序配置HttpRequestBodyConverter
实例。该服务调用所有提供的实例,直到其中一个实例返回非空值。如果它们都没有返回非空值,则返回到尝试从HttpServlet请求
到所需类型。
下面是一个实现新HttpRequestBodyConverter
然后将代码添加到应用程序模块
或任何其他Tapestry-IoC模块类@请求正文
:
/***将HTTP请求体转换为{@link User}实例。它委派此任务*到{@link UserService#toObject(String)}。*/公共类UserHttpRequestBodyConverter实现Http请求BodyConverser{私有最终UserService UserService;公共UserHttpRequestBodyConverter(UserService UserService){super();this.userService=用户服务;}@禁止警告(“未选中”)@覆盖public转换(HttpServletRequest请求,Class类型){T值=空;//检查此转换器是否处理给定类型if(User.class.equals(type)){//实际转换逻辑尝试{value=(T)userService.toObject(IOUtils.toString(request.getReader()));}捕获(IOException e){抛出新的RuntimeException(e);} }返回值;}}
公共静态void contributeHttpRequestBodyConverter(OrderedConfiguration(有序配置<HttpRequestBodyConverter>配置){configuration.addInstance(“用户”,UserHttpRequestBodyConverter.class);//自动实例化和依赖项注入//或configuration.add(“用户”,new UserHttpRequestBodyConverter(…));}
回答REST请求
与任何其他Tapestry事件处理程序方法一样,返回的值定义了要发送给发出请求的用户代理的内容。此逻辑写入组件事件结果处理器
实现,通常但不一定每个返回类型/类都有一个实现组件事件结果处理器
服务。这些实现还可以设置其他HTTP头并设置HTTP状态代码。
REST请求响应通常分为两种类型:只返回HTTP状态和标头的响应(例如,头部
和删除
请求)和返回请求以及内容的请求(例如,GET(获取)
,有时还有其他方法)。
内容回复
对于内容响应,Tapestry提供了现成的支持流式响应
(主要是二进制内容)文本流响应
(简单文本内容),JSON数组
(自Tapestry 5.8.0起)和JSON对象
(自5.8.0起)。下面是一个添加类支持的示例,用户
,将其转换为JSON格式:
/***处理事件处理程序方法返回的{@link User}实例。*灵感来自Tapestry本身的{@link JSONCollectionEventResultProcessor}。*/最终公共类UserComponentEventResultProcessor实现ComponentEventResultProcessor<用户>{私人最终响应;私有最终ContentType ContentType;私有最终UserService UserService;public UserComponentEventResultProcessor(响应响应,@符号(TapestryHttpSymbolConstants.CHARSET)字符串输出编码,用户服务用户服务){this.response=响应;this.userService=用户服务;contentType=新contentType(InternalConstants.JSON_MIME_TYPE).withCharset(outputEncoding);}public void processResultValue(用户用户)引发IOException{PrintWriter pw=响应.getPrintWriter(contentType.toString());pw.write(userService.toJsonString(用户));pw.close();//您还可以在此处设置额外的HTTP头或状态代码} }
公共void contributeComponentEventResultProcessor(MappedConfiguration<类,组件事件结果处理器>配置){configuration.addInstance(User.class,UserComponentEventResultProcessor.class);}
非内容回复
对于没有内容、只有HTTP状态和标头的响应,以及简单的String响应,Tapestry 5.8.0引入了Http状态
类。您可以使用与HTTP状态名称匹配的实用程序静态方法来创建它的实例,例如ok()
,创建()
,接受()
, 未找到()
和禁止()
或使用其构造函数之一。在这两种情况下,您都可以通过使用流畅的接口和特定于header的方法进一步定制响应,例如带位置(url)
和包含内容位置(url)
或通用withHttpHeader(字符串名称,字符串值)
.检查Http状态
JavaDoc获取方法的完整列表。
@OnEvent(事件常量.HTTP_PUT)对象保存(@RequestBody User用户){userService.save(用户);return HttpStatus.created().withContentLocation(“某些URL”).withHttpHeader(“X-Something”,“X-Value”);}
映射实体管理器
服务
这是一个提供映射实体列表的服务。它们通常是映射到JSON和XML等其他格式的类,用于表示接收或发送到外部进程(例如REST端点)的数据。贡献由包完成,贡献中的所有类都被视为映射实体。这个[根包]。rest.实体
包是自动贡献的。
Tapestry代码使用此服务,包括OpenAPI描述生成器和挂毯rest jackson,以了解哪些类应该被视为Web应用程序外部API的一部分。
以下是一个贡献示例:
public static void contributeMappedEntityManager(配置<String>配置){configuration.add(“com.example.rest.entities”);}
与Jackson Databind与tapestry-rest-Jackson集成
JSON被广泛用作REST端点中的数据交换格式,而Jackson Databind可能是JSON映射最常用的Java库。tapestry-rest-jackson公司
自动在Tapestry中使用Jackson Databind,定义对象映射器源
服务,贡献组件事件结果处理器
和HttpRequestBodyConverter(HttpRequestBodyConverter)
所有映射实体类的实现(由映射实体管理器
服务),并使用victorools/jsonschema生成器.
这个对象映射器源
服务定义了tapestry-rest-jackson如何获得对象映射器
实例用于给定实体类。它的有序配置为对象映射器源
.方法单一,ObjectMapper get(类<?>clasz)
。调用时,它会遍历所有贡献的实例,对它们调用相同的方法,直到其中一个实例返回非空值。当返回非空值时,服务方法将返回该值。如果未找到任何值,则回退始终返回由新建ObjectMapper()
。对对象映射器
实例应作为对对象映射器源
服务。下面是一个定义所有实体类应使用哪种日期格式的示例:
/***自定义Jackson数据绑定的{@link ObjectMapper}的示例,特别是*日期格式。*/公共静态void contributeObjectMapperSource(OrderedConfiguration<ObjectMapperResource>configuration){configuration.add(“自定义”,新的CustomObjectMapperSource());}私有静态最终类CustomObjectMapperSource实现ObjectMapperResource{最终私有ObjectMapper映射器;公共CustomObjectMapperSource(){mapper=新ObjectMapper(/*…*/);mapper.setDateFormat(新的SimpleDateFormat(“yyyy/MM/dd hh:MM:ss”));//此处显示任何其他自定义设置。}@覆盖public ObjectMapper get(类<?>clasz){//您可以检查类以提供特定于类的ObjectMapper//实例,但本例并非如此返回映射器;}}
OpenAPI 3.0(Swagger)描述的自动生成
Tapestry提供了一个现成的OpenAPI 3.0(Swagger)描述生成器,由REST端点事件处理程序(即处理本页顶部表格中列出的事件的处理程序)、配置符号和国际化消息(即app.properties)驱动。描述采用JSON格式。
默认情况下,它是禁用的。通过设置tapestry.publish-openapi-描述
(符号常量。发布_操作_定义
)配置符号到真的
。如果启用,它将在/openapi.json软件
URL。可以使用磁带.openapi-description-path
(符号常量。OPENAPI_DESCRIPTION_PATH(打开_描述_路径)
)配置符号。
MappedEntityManager.getEntities()返回的所有实体类都会自动添加到模式部分。
使用消息和配置符号自定义名称、摘要和描述
摘要、名称和描述以及消息首先取自消息,其次取自配置符号,但OpenAPI版本除外,该版本仅取自磁带.openapi-version
(符号常量。打开版本(_V)
)符号,默认值为3.0.0
。给定消息键,相应的配置符号为挂毯。[信息键]
格式。
HTTP方法名称是小写的。
构建消息密钥时,如果它基于路径,则不会删除起始斜杠。例如/某物
POST方法的端点为openapi/某物.帖子.摘要
.
通过设置org.apache.tapestry5.internal.services.rest.DefaultOpenApiDescriptionGenerator
类到调试
.
使用自定义端点的已使用和生成MIME内容类型@RestInfo(重置信息)
这个@RestInfo(重置信息)
注释允许您仅为OpenAPI描述生成目的定义REST端点事件处理程序方法接受的MIME内容类型、生成的类型以及方法执行成功时的实际返回值类型。许多REST事件处理程序方法的返回类型通常为对象
因此它可以返回Http状态
调用成功时,出现错误的实例和映射的实体类实体。
这里有一个例子:
@RestInfo(products=“text/plain”,produces=“application/json”,returnType=User.class)对象onHttpGet(@RequestBody长id){用户用户=。。。;if(!未找到){return HttpStatus.notFound()}其他{返回用户;}}
进一步自定义
可以通过实现OpenApiDescriptionGenerator
接口并将其贡献给OpenApiDescriptionGenerator
服务。这个JSON对象生成(JSONObject文档)
方法将接收生成的描述,可以使用JSON对象
方法。返回值应与作为参数接收的对象相同。
tapestry-openapi-viewer
tapestry-openapi-viewer tapestry子项目/JAR嵌入了开源Swagger用户界面OpenAPI/Swagger并在/openapi查看器
URL。除了在类路径中包含JAR之外,不需要任何配置。