Netty之HTTP+XML编解码框架开发

本文详细介绍了使用Netty框架构建HTTP+XML编解码框架的过程,包括HTTP+XML请求消息编码类、解码类的实现,以及客户端和服务端的开发。在编码类中,自定义了HttpXmlRequestEncoder和HttpXmlRequestDecoder,实现了HTTP请求消息的XML编码和解码。服务端和客户端的处理类HttpXmlServerHandler和HttpXmlClientHandler分别处理接收到的请求和应答,确保业务逻辑与协议栈解耦。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Netty之HTTP+XML编解码框架开发

一.HTTP+XML请求消息编码类

    对于上层业务,构造订购请求消息后,以HTTP+XML协议将消息发送给服务端,如果要实现对业务零侵入或者尽可能少的侵入看,协议层和应用层应该解耦。

    考虑到HTTP+XML协议栈需要一定的定制扩展能力,例如通过HTTP消息头携带业务自定义字段,应该允许业务利用Netty的HTTP协议栈接口自行构造私有的HTTP消息头。

    HTTP+XML的协议编码仍然采用ChannelPipeline中增加对应的编码handler类实现。

1.1 HttpXmlRequestEncode实现

  packagejibx;

 

import java.net.InetAddress;

import java.util.List;

 

importio.netty.channel.ChannelHandlerContext;

importio.netty.handler.codec.http.DefaultFullHttpRequest;

importio.netty.handler.codec.http.FullHttpRequest;

importio.netty.handler.codec.http.HttpHeaders;

/*

 *HTTP+XML HTTP请求消息编码类

 *

 */

public class HttpXmlRequestEncoder

     extends AbstarctHttpXmlEncoder<HttpXmlRequest>{

        

   @Override

   protected void encode(ChannelHandlerContext ctx,HttpXmlRequestmsg,List<Object> out)

   throws Exception{

             // 调用父类的encode0,将业务需要发送的POJO对象Order实例通过jibx序列化为XML字符串

             // 随后将它封装成netty的bytebuf

             ByteBufbody=encode0(ctx,msg.getBody());

             FullHttpRequestrequest=msg.getRequest();

             // 对消息头进行判断,如果业务侧自定义和定制了消息头,则使用业务侧设置的HTTP消息头

             // 如果业务侧没有设置,则构造新的HTTP消息头

             if(request==null){

                       // 构造和设置默认的HTTP消息头,由于通常情况下HTTP通信双方更关注消息体本身,

                       // 所以这里采用了硬编码方式,如果要产品化,可以做成XML配置文件,允许业务自定义配置,

                       // 以提升定制的灵活性

                       request=newDefaultFullHttpRequest(HttpVersion.HTTP_1_1,HttpMethod.GET,"/do",body);

                       HttpHeadersheaders=request.headers();

                       headers.set(HttpHeaders.Names.HOST,InetAddress.getLocalHost().getHostAddress());

                       headers.set(HttpHeaders.Names.CONNECTION,HttpHeaders.Value.CLOSE);

                       headers.set(HttpHeaders.Names.ACCEPT_ENCODING,HttpHeaders.Value.GZIP.toString()+','+

                                         HttpHeaders.Value.DEFLATE.toString());

                       headers.set(HttpHeaders.Names.ACCEPT_CHARSET,"ISO-8859,utf-8,q=0.7,*;q=0.7");

                       headers.set(HttpHeaders.Names.USER_AGENT,"Nettyxml Http Client side");

                       headers.set(HttpHeaders.Names.ACCEPT,"text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8");

             }

             // 由于请求消息消息体不为空,也没有chunk方式,所以在HTTP消息头中设置消息体的长度conent-length

             // 完成消息体的XML序列化后将重新构造的HTTP请求消息加入到out中

             // 由后续netty的http请求编码器继续对HTTP请求消息进行编码

             HttpHeaders.setContentLength(request,body.eradableBytes());

             out.add(request);

}

}

1.2 AbstrctHttpXmlEncoder实现

package jibx;

 

import java.io.StringWriter;

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

importio.netty.channel.ChannelHandlerContext;

importio.netty.handler.codec.MessageToMessageEncoder;

/*

 *HTTP+XML HTTP请求消息编码基类

 */

public classAbstractHttpXmlEncoder<T>

 extends MessageToMessageEncoder<T>{

         IBindingFactoryfactory=null;

         StringWriterwriter=null;

         finalstatic String CHARSET_NAME="UTF-8";

         finalstatic Charset UTF-8=

                            Charset.forName(CHARSET_NAME);

         //将业务的Order实例序列化为XML字符串

         protectedByteBuf encode0(ChannelHandlerContext ctx,Object body) throws Exception{

                   factory=BindingDirectory.getFactory(body.getClass());

                   writer=newStringWriter();

                   IMarshallingContextmctx=factory.createMarshallingContext();

                   mctx.setIndent(2);

                   mctx.marshalDocument(body,CHARSET_NAME,null,writer);

                   StringxmlStr=writer.toString();

                   writer.close();

                   writer=null;

                   //将XML字符串包装成netty的ByteBuf并返回,实现了HTTP请求消息的XML编码

                   ByteBufencodeBuf=Unpooled.copiedBuffer(xmlStr,UTF-8);

                   returnencodeBuf;

         }

        

         @Override

         publicvoid exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throwsException{

                   //释放资源

                   if(writer!=null){

                            writer.close();

                            writer=null;

                           

                   }

         }

}

1.3 HttpXmlRequest实现

package jibx;

/*

 *HTTP+XML请求消息  用于实现和协议栈之间的解耦

 */

importio.netty.handler.codec.http.FullHttpRequest;

 

public class HttpXmlRequest {

         privateFullHttpRequest request;

         privateObject body;

        

         publicHttpXmlRequest(FullHttpRequest request,Object body){

                   this.request=request;

                   this.body=body;

                  

         }

        

         publicfinal FullHttpRequest getRequest(){

                   returnrequest;

         }

        

         publicfinal void setRequest(FullHttpRequest request){

                   this.request=request;

         }

        

         publicfinal Object getBody(){

                   returnbody;

         }

        

         publicfinal void setBody(Object body){

                   this.body=body;

         }

 

}

    它包含2个成员变量FullHttpRequest和编码对象Object,用于实现和协议栈之间的解耦。

二.HTTP+XML请求消息解码类

   Http服务端接收到HTTP+XML请求消息后,需要从http消息体重获取请求码流,通过jibx框架对它进行反序列化,得到请求POJO对象,然后对结果进行封装,回调到业务handler对象,业务得到的就是解码后的POJO对象和HTTP消息头。

2.1 HttpXmlRequestDecoder实现

package jibx;

 

import io.netty.buffer.Unpooled;

importio.netty.channel.ChannelFutureListener;

importio.netty.handler.codec.http.HttpResponseStatus;

/*

 *HTTP+XML http请求消息解码类

 */

public class HttpXmlRequestDecoder

  extends AbstactHttpXmlDecode<FullHttpRequest>{

        

         publicHttpXmlRequestDecoder(Class<?> clazz) {

                   this(clazz,false);

         }

         //HttpXmlRequestDecoder有2个参数,分别为需要解码的对象的类型信息和

         //是否打印HTTP消息体码流的码流开关,码流开关默认关闭

         publicHttpXmlRequestDecoder(Class<?> clazz,boolean isPrint){

                   super(clazz,isPrint);

         }

  

         @Override

         protectedvoid decode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值