使用 HttpResponse.Filter 实现简繁/繁简转换

本文介绍了一个简单的网站简繁转换实现方案,通过自定义过滤器在HttpResponse.Filter中进行简繁文字转换,同时解决了转换过程中可能遇到的Session丢失问题。

HttpResponse.Filter 属性,类似于 HttpRequest.Filter(参见使用 HttpRequest.Filter 来过滤或转换 Http 输入流),只不过一个是出口,一个是入口(想像一下停车场),在这两个点之间的数据由服务器端处理,在这两点之外的,则由用户浏览器处理。那么,在出口处能做些什么呢?当然是对数据进行一些统一的处理,比如说简繁转换、过滤非法词汇等等。

在这里说说如何做简繁转换,其实网上已经有很多例子,所以只是针对一些重点的部分说明一下:

首先,依然是实现自己的过滤器,需要继承 Stream:

        public class ResponseFilter : Stream

在重写基类方法时,最重要的是 Write() 方法,所有的转换都在该方法中实现,主要代码如下:

  1. public override void Write(byte[] buffer, int offset, int count)
  2. {
  3.     //判断 Session,若 Session["Lang"] 等于 "ZH-TW",则启动转换
  4.     if (HttpContext.Current.Session != null && HttpContext.Current.Session["Lang"].ToString() == "ZH-TW")
  5.     {
  6.         //对于 UTF-8 编码,必须提供简繁字对照,为提高处理效率,应删除简繁体写法相同的字,这样至少可以减少 2/3 的字数(网上提供的字库大多包含了相同字符的)
  7.         //GB 转 Big5 可使用 Microsoft.VisualBasic.Strings.StrConv 方法,不需要字库。
  8.         String  simple  = "简体字库";
  9.         String  tradit  = "繁體字庫";
  10.         
  11.         //获取当前响应流的编码方式,即使整个网站都使用 UTF-8 编码,但仍然会存在其它的编码方式,尤其是采用微软的 Ajax 控件时,若编码方式不一致,则会导致错误,动态获取编码,可避免这个问题
  12.         System.Text.Encoding curEncoding = HttpContext.Current.Response.ContentEncoding;
  13.         string strBuff = curEncoding.GetString(buffer);
  14.         int len = strBuff.Length;
  15.         System.Text.StringBuilder sbBuff = new System.Text.StringBuilder();
  16.         for (int i = 0; i != len; ++i)
  17.         {
  18.             int index = simple.IndexOf(strBuff[i]);
  19.             if (index != -1)
  20.                 sbBuff.Append(tradit[index]);
  21.             else
  22.                 sbBuff.Append(strBuff[i]);
  23.         }
  24.         byte[] output = System.Text.Encoding.UTF8.GetBytes(sbBuff.ToString());
  25.         m_sink.Write(output, 0, count);
  26.     }
  27.     else
  28.         m_sink.Write(buffer, 0, count);
  29. }

写好自己的过滤器后,就可以加载到网站中了,注意,跟 HttpRequest.Filter 一样,HttpResponse.Filter 的加载也是在 Global.asax 的 Application_BeginRequest 事件中,另外,因为在该事件触发时,Session 尚未启动,所以不能在此使用Session 判定当前的语言,代码如下:

  1. void Application_BeginRequest(object sender, EventArgs e)
  2. {       
  3.     string rawUrl = Request.RawUrl.ToLower();
  4.     // rawUrl.IndexOf(".axd")用於屏蔽 Asp.net Ajax 生成的异步请求。否则部分使用 Ajax 的页面会报错,原因不明。
  5.     if (rawUrl.IndexOf(".axd") == -1)
  6.     {
  7.         this.Response.Charset = "UTF-8";
  8.         this.Response.Buffer = false;
  9.         this.Response.Filter = new ResponseFilter(Response.Filter);
  10.     }               
  11. }

至此,一个简单的网站简繁转换就完成了,但在实际应用中,出现过这样一种情况,有时在访问网站时,会提示

        工作阶段状态已经建立工作阶段 ID,但由于应用程序已经清除回应而无法储存。

出现的频率不高,并且无规律,即使当前未进行转换也会出现,并且只出现在页面下方,也不像通常的错误显示一样,仅出现错误信息,而是错误信息和本来的页面都显示出来。

后来在一份文档中看到说是使用 Response.Flush、Response.Write 等导致输出缓冲区刷新的语句,有时会造成 Session 丢失(因为网站另外使用了一些 Session 来储存一些状态值),所以在 Global.asax 的创建 Session 事件中,重建网站需要的状态 Session 值:

  1. void Session_Start(object sender, EventArgs e)
  2. {
  3.     //判断 Session 是否丢失
  4.     if (!String.IsNullOrEmpty(Session.SessionID))
  5.     {
  6.         //网站状态 Session 设为默认值(这里不用管用于判断是简体还是繁体那个 Session)
  7.         … …
  8.     }
  9. }

问题解决。

有可能还会有这种需求,要将一些带有简体字的图片也转换为繁体,怎么办呢?呵呵,其实很简单,对需要转换的图片名称后加一个特殊的字串,比如简体的图片名为 "image__zh__.gif“,相应的繁体图片为 "image__tw__.gif",将 __zh__ 替换为 __tw__就可以了。

<think>好的,用户的问题是关于如何将基于Netty的FullHttpResponse代码转换为Java 11中的HttpResponse实现。首先,我需要明确用户的需求。他们可能正在迁移现有的Netty项目到使用Java 11的标准HTTP客户端,或者他们想利用Java 11的新特性来简化代码。 首先,我应该回忆一下Netty的FullHttpResponse结构和Java 11的HttpResponse之间的区别。Netty的FullHttpResponse通常用于处理HTTP响应,包含状态、头部和内容。而Java 11引入了新的HttpClient,提供了HttpResponse类,用于接收响应。 接下来,需要了解用户提供的示例代码可能的结构。假设用户有一个使用Netty处理FullHttpResponse的代码片段,他们希望用Java 11的API替代。例如,Netty中可能通过ChannelHandlerContext写入FullHttpResponse对象,而Java 11则使用异步的send方法获取HttpResponse对象。 然后,我需要考虑如何将Netty的组件转换为Java 11的实现。例如,Netty的聚合器(用于将多个消息部分合并为完整的FullHttpResponse)在Java 11中可能不再需要,因为HttpClient会自动处理响应体的聚合。 另外,需要注意HTTP消息的构建。在Netty中,可能会使用DefaultFullHttpResponse来构建响应,设置状态、头部和内容。而Java 11中,需要通过HttpRequest构建请求,并使用BodyHandlers来处理响应体,比如转换为字符串或字节数组。 还需要处理异步和同步调用的区别。Netty通常是异步的,而Java 11的HttpClient既可以同步也可以异步。用户可能需要调整代码结构,使用CompletableFuture来处理异步响应,或者使用sendAsync方法。 此外,错误处理也是一个重点。Netty有特定的异常处理机制,而Java 11的HttpClient会抛出特定的异常,如IOExceptions,需要适当处理。 最后,可能需要提供一个示例代码,展示如何用Java 11的HttpClient发送请求并处理响应,包括状态码、头部和内容的获取。同时,要指出两者的差异,比如是否需要手动聚合消息部分,以及异步处理的方式。 总结步骤应该是:创建HttpClient实例,构建请求,发送请求并处理响应,提取状态码、头部和内容,并处理异常。同时,比较Netty和Java 11实现的差异,帮助用户理解迁移过程中的注意事项。</think>### 分步解答:将Netty的FullHttpResponse迁移到Java 11的HttpResponse #### 1. **理解Netty与Java 11的HTTP模型差异** - **Netty**:需要手动聚合HTTP消息片段(通过`HttpObjectAggregator`)生成`FullHttpResponse`[^2]。 - **Java 11 HttpClient**:自动处理消息聚合,直接通过`BodyHandlers`获取完整的响应体(如字符串、字节数组或流)。 #### 2. **关键代码转换示例** 假设原始Netty代码片段如下: ```java FullHttpResponse response = new DefaultFullHttpResponse( HTTP_1_1, OK, Unpooled.wrappedBuffer(content.getBytes())); response.headers().set(CONTENT_TYPE, "text/plain"); ctx.writeAndFlush(response); ``` 对应的Java 11实现: ```java // 创建HttpClient HttpClient client = HttpClient.newHttpClient(); // 构建请求 HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://example.com")) .header("Content-Type", "text/plain") .build(); // 发送请求并处理响应 client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenApply(httpResponse -> { System.out.println("Status: " + httpResponse.statusCode()); System.out.println("Headers: " + httpResponse.headers().map()); System.out.println("Body: " + httpResponse.body()); return httpResponse; }); ``` #### 3. **核心差异说明** - **消息聚合**:Java 11无需手动处理分块消息,通过`BodyHandlers.ofString()`或`BodyHandlers.ofByteArray()`直接获取完整内容。 - **异步处理**:Netty使用`ChannelFuture`,Java 11使用`CompletableFuture<HttpResponse>`。 - **异常处理**:Java 11需通过`.exceptionally(ex -> {...})`捕获网络错误。 #### 4. **完整流程对比** | Netty步骤 | Java 11等效实现 | |-------------------------------|----------------------------------| | 安装`HttpObjectAggregator`[^2] | 使用`BodyHandlers`自动聚合 | | 读取`FullHttpResponse`内容 | 直接调用`httpResponse.body()` | | 手动设置响应头 | 通过`.header()`方法设置请求头 | | 处理ByteBuf内容[^3] | 使用`BodyHandlers.ofByteArray()` | #### 5. 特殊场景处理 若需要流式处理响应体(非聚合模式),可使用: ```java HttpResponse<InputStream> response = client.send( request, HttpResponse.BodyHandlers.ofInputStream() ); try (InputStream bodyStream = response.body()) { // 流式读取内容 } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值