Java Sun HTTPServer-如何编写后处理筛选器?
我正在尝试使用Sun JRE的HTTP服务器。在阅读了两遍文档之后,我仍然感到困惑 javadoc说: 要求此筛选器对给定的交换进行预处理/后处理。过滤器可以:Java Sun HTTPServer-如何编写后处理筛选器?,java,com.sun.net.httpserver,Java,Com.sun.net.httpserver,我正在尝试使用Sun JRE的HTTP服务器。在阅读了两遍文档之后,我仍然感到困惑 javadoc说: 要求此筛选器对给定的交换进行预处理/后处理。过滤器可以: 检查或修改请求头 通过创建合适的过滤流并调用HttpExchange.setStreams(InputStream,OutputStream),过滤请求正文或响应正文 在exchange中设置其他筛选器或exchange处理程序可以访问的属性对象 决定: 通过调用filter.chain.doFilter(HttpExchange)
- 检查或修改请求头
- 通过创建合适的过滤流并调用HttpExchange.setStreams(InputStream,OutputStream),过滤请求正文或响应正文
- 在exchange中设置其他筛选器或exchange处理程序可以访问的属性对象
- 决定:
- 通过调用filter.chain.doFilter(HttpExchange)调用链中的下一个过滤器
- 通过不调用Filter.chain.doFilter(HttpExchange)终止调用链
请帮我弄清楚。每个过滤器都是前置过滤器和后置过滤器。我的意思是,请求在堆栈中移动时通过它,然后响应通过它返回到客户端。过滤器的调用顺序取决于您在
web.xml
文件中装入过滤器的顺序
如果您将其用作预过滤器,则会修改InputStream
,如果您希望将其用作帖子,则会修改OutputStream
。您甚至可以通过链向下传递自己的InputStream
和OutputStream
例如,假设您有一些
Filter1
,Filter2
和Filter3
。InputStream
将首先经过Filter1
,然后是Filter2
,最后是Filter3
,然后再进行处理。生成的OutputStream
在发送到客户端之前,将通过Filter3
,然后是Filter2
,最后是Filter1
返回。因此,通过这种方式,您可以修改预处理和/或后处理。我自己也很想知道这一点,我不知道setStreams
方法如何对此有所帮助。我能做到这一点的唯一方法是包装HttpExchange
此示例演示如何使用筛选器应用gzip压缩:
在调用HttpHandler.handle()之前,只调用一次Filter.doFilter()
这意味着您无法在处理程序运行后修改HTTP响应的内容。所以,它更自然地是一个预过滤器
但是,在doFilter()的实现中,您可以使用自己的FilterOutputStream包装响应的OutputStream,以便拦截对HttpExchange.getResponseBody().write(…)的调用
类MyFilter扩展了过滤器{
@凌驾
public void doFilter(HttpExchange exch,Chain Chain)引发IOException{
exch.setStreams(null,新的MyInterceptedOutputStream(exch.getResponseBody());
链式过滤器(exch);
}
...
}
这个MyInterceptedOutputStream类需要扩展OutputStream并实现其常用方法(write()和close())
有一个技巧:包装器必须确保在调用HttpExchange.sendResponseHeaders()之前不会向原始输出流写入任何内容。这意味着您必须确保您的包装器构造函数(上面示例中的MyInterceptedOutputStream(OutputStream os))不写任何东西,这与例如gziOutputStream()不同
奖励:OutputStream包装器压缩流的示例。。。并在HttpFilter.doFilter()中工作
import java.io.IOException;
导入java.io.OutputStream;
导入java.util.zip.GZIPOutputStream;
公共类GZIPDelayedOutputStream扩展了OutputStream{
gzip输出流gzip流;
OutputStream originalStream;
公共GZIPDelayedOutputStream(OutputStream os){
超级();
原始流=os;
}
private void creategzipstreamifEssential()引发IOException{
如果(gzipStream==null){
gzip流=新的gzip输出流(原始流);
}
}
@凌驾
公共无效写入(int b)引发IOException{
creategzipstreamifEssential();
gzipStream.write(b);
}
@凌驾
公共无效写入(字节buf[])引发IOException{
creategzipstreamifEssential();
gzipStream.write(buf);
}
@凌驾
公共无效写入(字节[]buf,int off,int len)引发IOException{
creategzipstreamifEssential();
写入(buf、off、len);
}
@凌驾
public void close()引发IOException{
creategzipstreamifEssential();
gzipStream.close();
}
}
对不起,web.xml
是JEE规范的一部分。我知道你提到了Sun HTTP服务器,我相信它是通过代码配置的-但是过滤器堆栈仍然链接在一起,所以你仍然根据你修改的流过滤pre或post。我只是忘记了这个主题。我发现这是以我想象的不同方式实现的。如果我有足够的时间,我会在这里添加一些关于这些东西如何工作的文档