Filter过滤器高级应用
-
由于开发人员在filter中可以得到代表用户请求和响应 的request、response对象,因此在编程中可以使用 Decorator(装饰器)模式对request、response对象进行 包装,再把包装对象传给目标资源,从而实现一些特 殊需求。
-
增强模式
- 当某个对象的方法不适应业务需求时,通常有2种方式可以对方法进行增强:
- 编写子类,覆盖需增强的方法
- 使用Decorator设计模式对方法进行增强
- 当某个对象的方法不适应业务需求时,通常有2种方式可以对方法进行增强:
-
Decorator设计模式的实现
- 首先看需要被增强对象继承了什么接口或父类,编写一个 类也去继承这些接口或父类。
- 在类中定义一个变量,变量类型即需增强对象的类型。
- 在类中定义一个构造函数,接收需增强的对象。
- 覆盖需增强的方法,编写增强的代码
- Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper ,(HttpServletRequestWrapper类实现了request接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的request对象的对应方法)以避免用户在对request对象进行增强时需要实现request接口中的所有方法
- 案例一:解决乱码
//为解决全站乱码
public class CharacterEncodingFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
request.setCharacterEncoding("gb2312");
response.setCharacterEncoding("gb2312");
response.setContentType("text/html;charset=gb2312");
MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);
chain.doFilter(requestWrapper, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
/*
1.实现与被增强对象相同的接口
2、定义一个变量记住被增强对象
3、定义一个构造器,接收被增强对象
4、覆盖需要增强的方法
5、对于不想增强的方法,直接调用被增强对象(目标对象)的方法
*/
class MyCharacterEncodingRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
public MyCharacterEncodingRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) {
try{
String value= this.request.getParameter(name);
if(value==null){
return null;
}
if(!this.request.getMethod().equalsIgnoreCase("get")) {
return value;
}
value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
return value;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
- 案例2:压缩响应
//解决全站压缩
public class GzipFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
BufferResponse myresponse = new BufferResponse(response);
chain.doFilter(request, myresponse);
//拿出缓存中的数据,压缩后再打给浏览器
byte out[] = myresponse.getBuffer();
System.out.println("原始大小:" + out.length);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
GZIPOutputStream gout = new GZIPOutputStream(bout);
gout.write(out);
gout.close();
byte gzip[] = bout.toByteArray();
System.out.println("压缩后的大小:" + gzip.length);
response.setHeader("content-encoding", "gzip");
response.setContentLength(gzip.length);
response.getOutputStream().write(gzip);
}
public void destroy() {
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}
class BufferResponse extends HttpServletResponseWrapper{
private ByteArrayOutputStream bout = new ByteArrayOutputStream();
private PrintWriter pw;
private HttpServletResponse response;
public BufferResponse(HttpServletResponse response) {
super(response);
this.response = response;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyServletOutputStream(bout);
}
@Override
public PrintWriter getWriter() throws IOException {
pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding())); //PrintWriter.write(中国) <br>
return pw;
}
public byte[] getBuffer(){
try{
if(pw!=null){
pw.close();
}
if(bout!=null){
bout.flush();
return bout.toByteArray();
}
return null;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class MyServletOutputStream extends ServletOutputStream{
private ByteArrayOutputStream bout;
public MyServletOutputStream(ByteArrayOutputStream bout){
this.bout = bout;
}
@Override
public void write(int b) throws IOException {
this.bout.write(b);
}
}
- 案例3:缓存数据到内存
//缓存数据到内存
public class CachedFilter implements Filter {
private Map<String,byte[]> map = new HashMap<String,byte[]>();
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//1.得到用户请求的uri
String uri = request.getRequestURI();
//2.看缓存中有没有uri对应的数据
byte b[] = map.get(uri);
//3.如果缓存中有,直接拿缓存的数据打给浏览器,程序返回
if(b!=null){
response.getOutputStream().write(b);
return;
}
//4.如果缓存没有,让目标资源执行,并捕获目标资源的输出
BufferResponse1 myresponse = new BufferResponse1(response);
chain.doFilter(request, myresponse);
byte out[] = myresponse.getBuffer();
//5.把资源的数据以用户请求的uri为关键字保存到缓存中
map.put(uri, out);
//6.把数据打给浏览器
response.getOutputStream().write(out);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
}
class BufferResponse1 extends HttpServletResponseWrapper{
private ByteArrayOutputStream bout = new ByteArrayOutputStream(); //捕获输出的缓存
private PrintWriter pw;
private HttpServletResponse response;
public BufferResponse1(HttpServletResponse response) {
super(response);
this.response = response;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyServletOutputStream1(bout);
}
@Override
public PrintWriter getWriter() throws IOException {
pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));
return pw;
}
public byte[] getBuffer(){
try{
if(pw!=null){
pw.close();
}
return bout.toByteArray();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class MyServletOutputStream1 extends ServletOutputStream{
private ByteArrayOutputStream bout;
public MyServletOutputStream1(ByteArrayOutputStream bout){ //接收数据写到哪里
this.bout = bout;
}
@Override
public void write(int b) throws IOException {
bout.write(b);
}
}
- 案例4:敏感词过滤
//脏话过滤器
public class DirtyFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
DirtyRequest dirtyrequest = new DirtyRequest(request);
chain.doFilter(dirtyrequest, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
}
class DirtyRequest extends HttpServletRequestWrapper{
private List<String> dirtyWords = Arrays.asList("傻B","操蛋","畜生");
private HttpServletRequest request;
public DirtyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) {
String value = this.request.getParameter(name);
if(value==null){
return null;
}
for(String dirtyWord : dirtyWords){
if(value.contains(dirtyWord)){
value = value.replace(dirtyWord, "****");
}
}
return value;
}
}
- 案例5:html转义
//html转义过滤器
public class HtmlFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
MyHtmlRequest myrequest = new MyHtmlRequest(request);
chain.doFilter(myrequest, response);
}
public void destroy() {
// TODO Auto-generated method stub
}
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
class MyHtmlRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
public MyHtmlRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) {
String value = this.request.getParameter(name);
if(value==null){
return null;
}
return filter(value);
}
public String filter(String message) {
if (message == null)
return (null);
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
}