映射Netty的请求

从前,在一个遥远的项目中,我需要在Netty上处理http请求。 不幸的是,在Netty中没有用于映射http请求的标准便捷机制(并且该框架根本不用于此目的),因此,决定实施我们自己的机制。


如果读者开始担心项目的命运,那是不值得的; 将来,我们决定在不使用RESTful服务的情况下,在针对RESTful服务更加完善的框架上重写Web服务。 但是成就仍然存在,并且它们可以对某人有用,所以我想与大家分享。

Netty是用于开发高性能网络应用程序的框架。 您可以项目网站上了解更多信息。
Netty为创建套接字服务器提供了非常方便的功能,但是对于我来说,对于创建REST服务器来说,此功能不是很方便。


使用标准Netty引擎请求处理


要在Netty中处理请求您需要从ChannelInboundHandlerAdapter类继承并重写channelRead方法。


 public class HttpMappingHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { } } 

为了获得处理http请求所必需的信息,可以将msg对象HttpRequestHttpRequest


 HttpRequest request = (HttpRequest) msg; 

之后,您可以从该请求中获取任何信息。 例如,请求的URL。


 String uri = request.uri(); 

请求类型。


 HttpMethod httpMethod = request.method(); 

和内容。


 ByteBuf byteBuf = ((HttpContent) request).content(); 

内容可以是例如POST请求正文中传递的json。 ByteBufNetty库中的一个类,因此json解析器不太可能使用它,但是可以很容易地将其转换为字符串。


 String content = byteBuf.toString(StandardCharsets.UTF_8); 

通常,仅此而已。 使用以上方法,您可以处理http请求。 没错,所有内容都必须在一个地方处理,即在channelRead方法中。 即使我们将处理请求的逻辑分为不同的方法和类,您仍然必须将URL映射到这些方法的某个位置。


请求映射


好了,如您所见,可以使用标准的Netty功能实现http请求的映射。 没错,这不会很方便。 我想以某种方式通过不同的方法将http请求的处理完全分开(例如,在Spring中完成)。 在反思的帮助下,尝试实施类似的方法。 num库由此产生。 它的源代码可以在这里找到。
要使用num库使用请求映射,从AbstractHttpMappingHandler类继承就足够了,之后您可以在此类中创建请求处理程序方法。 这些方法的主要要求是它们返回FullHttpResponse或其后代。 您可以通过注释显示通过什么http请求来调用此方法:


  • @Get
  • @Post
  • @Put
  • @Delete

批注名称指示将调用的请求类型。 支持四种类型的请求: GETPOSTPUTDELETE 。 作为注释中的value参数,您必须指定URL,在访问URL时,将调用所需的方法。


GET处理程序的示例,返回字符串Hello, world!


 public class HelloHttpHandler extends AbstractHttpMappingHandler { @Get("/test/get") public DefaultFullHttpResponse test() { return new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, Unpooled.copiedBuffer("Hello, world!", StandardCharsets.UTF_8)); } } 

请求参数


也可以使用注释将参数从请求传递到处理程序方法。 为此,请使用以下注释之一:


  • @PathParam
  • @QueryParam
  • @RequestBody

@PathParam


要传递路径参数,请使用@PathParam批注。 将其用作注释的value参数时,必须指定参数名称。 此外,还必须在请求URL中指定参数名称。


GET处理程序将如何看待传递id路径参数以及返回该参数的示例。


 public class HelloHttpHandler extends AbstractHttpMappingHandler { @Get("/test/get/{id}") public DefaultFullHttpResponse test(@PathParam(value = "id") int id) { return new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, Unpooled.copiedBuffer(id, StandardCharsets.UTF_8)); } } 

@QueryParam


要传递查询参数,请使用@QueryParam批注。 将其用作注释的value参数时,必须指定参数名称。 可以使用required注释参数来控制参数绑定。


GET处理程序的外观示例,向其传递查询参数message并返回此参数。


 public class HelloHttpHandler extends AbstractHttpMappingHandler { @Get("/test/get") public DefaultFullHttpResponse test(@QueryParam(value = "message") String message) { return new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, Unpooled.copiedBuffer(message, StandardCharsets.UTF_8)); } } 

@RequestBody


要传输POST请求的正文,请使用@RequestBody批注。 因此,只允许在POST请求中使用它。 假设json格式的数据将作为请求主体发送。 因此,要使用@RequestBody必须将JsonParser接口的实现传递给处理程序类的构造函数,该处理程序将用于解析来自请求主体的数据。 此外,该库已经具有JsonParserDefault的默认实现。 此实现使用jackson作为解析器。


一个带有请求正文的POST请求处理程序的示例。


 public class HelloHttpHandler extends AbstractHttpMappingHandler { @Post("/test/post") public DefaultFullHttpResponse test(@RequestBody Message message) { return new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, Unpooled.copiedBuffer("{id: '" + message.getId() +"', msg: '" + message.getMessage() + "'}", StandardCharsets.UTF_8)); } } 

Message类如下。


 public class Message { private int id; private String message; public Message() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } 

错误处理


如果在处理请求期间发生任何Exception并且该Exception不会在处理程序方法的代码中被拦截,则将返回第500个代码的答案。 为了编写一些用于错误处理的逻辑,足以在处理程序类中重新定义exceptionCaught方法。


 public class HelloHttpHandler extends AbstractHttpMappingHandler { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { super.exceptionCaught(ctx, cause); ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR)); } } 

结论


通常,仅此而已。 我希望这很有趣并且对某人有用。




使用num库的Netty http服务器示例代码在此处提供

Source: https://habr.com/ru/post/zh-CN435864/


All Articles