[Servlet&JSP] 封装器的使用
过滤器可以在执行servlet的service()方法前后,进行前置和后置处理。但是有些信息无法更改,例如请求参数。使用请求封装器及相应封装器,将容器产生的请求与相应对象加以封装,可以针对某个请求信息或响应进行加工处理。
请求封装器
httpservletrequestwrapper实现了httpservletrequest接口,以下范例通过继承httpservletrequestwrapper实现了一个请求封装器,可以请请求参数中的角括号替换为替代字符。
import java.util.iterator; import java.util.map; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletrequestwrapper; public class characterrequestwrapper extends httpservletrequestwrapper{ private map escapemap; public characterrequestwrapper(httpservletrequest request, map escapemap) { super(request); //封装传入的请求对象 this.escapemap = escapemap; } @override public string getparameter(string name) { //重写getparameter()方法 return doescape(this.getrequest().getparameter(name)); } private string doescape(string parameter) { if (parameter == null) { return null; } string result = parameter; iterator it = escapemap.keyset().iterator(); while(it.hasnext()) { string origin = it.next(); string escape = escapemap.get(origin); result = result.replaceall(origin, escape); } return result; } }
可以使用这个请求封装器搭配过滤器,以进行字符过滤的服务。例如:
import java.io.bufferedreader; import java.io.ioexception; import java.io.inputstreamreader; import java.util.hashmap; import java.util.map; import java.util.logging.level; import java.util.logging.logger; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servlet.servletrequest; import javax.servlet.servletresponse; import javax.servlet.http.httpservletrequest; public class characterfilter implements filter { private map escapemap; @override public void init(filterconfig filterconfig) throws servletexception { bufferedreader reader = null; try { string escapelistfile = filterconfig.getinitparameter("escape_list"); reader = new bufferedreader(new inputstreamreader( filterconfig.getservletcontext().getresourceasstream(escapelistfile))); string input = null; escapemap = new hashmap(); while ((input = reader.readline()) != null) { string[] token = input.split("\t"); escapemap.put(token[0], token[1]); } } catch (ioexception ex) { logger.getlogger(characterfilter.class.getname()) .log(level.severe, null, ex); } finally { try { reader.close(); } catch (ioexception ex) { logger.getlogger(characterfilter.class.getname()) .log(level.severe, null, ex); } } } @override public void dofilter(servletrequest request, servletresponse response, filterchain chain) throws ioexception, servletexception { //将原请求对象封装到characterrequestwrapper中 httpservletrequest requestwrapper = new characterrequestwrapper((httpservletrequest)request, escapemap); //将characterrequestwrapper对象当做请求参数传入dofilter() chain.dofilter(requestwrapper, response); } @override public void destroy() { // todo auto-generated method stub } }
响应封装器
如果想要对响应的内容进行压缩处理等,可以在响应封装器部分继承httpservletresponsewrapper类来对httpservletresponse对象进行封装。
如要对进行输出响应,必须通过getwriter()取得printwriter,或是通过getoutputstream()取得servletoutputstream。所以针对压缩输出的请求,主要就是继承httpservletresponsewrapper之后,通过重写这两个方法来达成的。
在这里压缩功能将采用gzip格式,这是浏览器可以接受的压缩格式,可以使用gzipoutputstream类来实现。由于getwriter()的printwriter在创建时也是必须要用到servletoutputstream,所以这里首先扩展servletoutputstream类,让它具有压缩功能。
gzipservletoutputstream.java:
package club.chuxing; import java.io.ioexception; import java.util.zip.gzipoutputstream; import javax.servlet.servletoutputstream; import javax.servlet.writelistener; public class gzipservletoutputstream extends servletoutputstream{ private gzipoutputstream gzipoutputstream; public gzipservletoutputstream(servletoutputstream servletoutputstream) throws ioexception { this.gzipoutputstream = new gzipoutputstream(servletoutputstream); } public void write(int b) throws ioexception { //输出时通过gzipoutputsteam的write()压缩输出 gzipoutputstream.write(b); } public gzipoutputstream getgzipoutputstream() { return gzipoutputstream; } @override public boolean isready() { // todo auto-generated method stub return false; } @override public void setwritelistener(writelistener listener) { // todo auto-generated method stub } }
compressionresponsewrapper.java:
package club.chuxing; import java.io.ioexception; import java.io.outputstreamwriter; import java.io.printwriter; import java.util.zip.gzipoutputstream; import javax.servlet.servletoutputstream; import javax.servlet.http.httpservletresponse; import javax.servlet.http.httpservletresponsewrapper; public class compressionresponsewrapper extends httpservletresponsewrapper { private gzipservletoutputstream gzservletoutputstream; private printwriter printwriter; public compressionresponsewrapper(httpservletresponse resp) { super(resp); } @override public servletoutputstream getoutputstream() throws ioexception { if (printwriter != null) { throw new illegalstateexception(); } if (gzservletoutputstream == null) { gzservletoutputstream = new gzipservletoutputstream( getresponse().getoutputstream()); } return gzservletoutputstream; } @override public printwriter getwriter() throws ioexception { if (gzservletoutputstream != null) { throw new illegalstateexception(); } if (printwriter == null) { gzservletoutputstream = new gzipservletoutputstream( getresponse().getoutputstream()); outputstreamwriter osw = new outputstreamwriter( gzservletoutputstream, getresponse().getcharacterencoding()); printwriter = new printwriter(osw); } return printwriter; } @override public void setcontentlength(int len) { } public gzipoutputstream getgzipoutputstream() { if (this.gzservletoutputstream == null) { return null; } return this.gzservletoutputstream.getgzipoutputstream(); } }
compressionfilter.java(压缩过滤器):
package club.chuxing; import java.io.ioexception; import java.util.zip.gzipoutputstream; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servlet.servletrequest; import javax.servlet.servletresponse; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; public class compressionfilter implements filter { @override public void init(filterconfig filterconfig) throws servletexception { // todo auto-generated method stub } @override public void dofilter(servletrequest request, servletresponse response, filterchain chain) throws ioexception, servletexception { httpservletrequest req = (httpservletrequest)request; httpservletresponse res = (httpservletresponse)response; string encodings = req.getheader("accept-encoding"); if ((encodings != null) && encodings.indexof("gzip") > -1) { //建立响应封装 compressionresponsewrapper responsewrapper = new compressionresponsewrapper(res); //设置响应内容编码为gzip格式 responsewrapper.setheader("content-encoding", "gzip"); chain.dofilter(request, responsewrapper); gzipoutputstream gzipoutputstream = responsewrapper.getgzipoutputstream(); if (gzipoutputstream != null) { //调用gzipoutputstream的finish()方法完成压缩输出 gzipoutputstream.finish(); } } else { chain.dofilter(request, response); } } @override public void destroy() { // todo auto-generated method stub } }
最后,将过滤器设置在web.xml中,响应就会是压缩过后的内容。