servlet过滤器中应该注意的字符编码问题

今天学习《Tomcat与java web开发技术详解》中过滤器一章,也做了实验。第一个例子很简单,结果很容易就出来了,第二个例子有点复杂,我做了好久,一直是乱码。其中,我也System.out.println()看了下字符串是对的,查看网页源代码也是对的,就是乱码,后来发现以GB2312编码来看的时候是正常的。

   这说明是字符编码的问题,将filter去掉的时候,网页显示是正常的,加上过滤器就不行,最后将错误定位到过滤器中出现了编码问题。

但是转念一想,不对,那为什么第一个过滤器就没有这个问题,而第二个过滤器就出现了呢?我仔细比较了两个过滤器的不同之处,除了功能上的不同,两者仅仅有一处差别:第二个过滤器中有新建String的动作,而第一个过滤器没有。

我立马查了下文档,new String()在不指定编码的情况下,会采用系统默认的字符编码创建字符串,而我在response中设置的字符编码是utf-8,但是系统默认编码是GB2312,所以网页乱码。

问题终得解决!!

感觉自然是爽,但是也说明了我以前学习java是多么的三心二意,String的编码折腾了我这么久。以后要加强基础的学习。下面我将我的代码贴出。

package chap13.filter;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * 
 * @author dvking
 * servlet response设置了utf-8
 */
public class NoteServlet extends HttpServlet{
	public void service(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException,IOException{
		response.setContentType("text/html;charset=utf-8");
	//	response.setCharacterEncoding("utf-8");
		ServletOutputStream out = response.getOutputStream();
		out.println("<html>");
		out.println("<head><title>message</title></head>");
		out.println("<body>");
		
		request.setCharacterEncoding("utf-8");
		String username = request.getParameter("username");
		String content = request.getParameter("content");
		
		
		
		if(content != null && !content.equals("")){
			out.println("<p>" + username + "的留言为:" + content+ "</p>");
		}
		
		out.println("<form action='" + request.getContextPath()  + "/note' method='post'>");
	//	out.println("<from action='hello/note' method='post'>");
		out.println("<b>姓名:</b>");
		out.println("<input type=text name=username /><br/>");
		out.println("<b>留言:</b><br/>");
		out.println("<textarea name=content rows=5 cols=20 ></textarea><br/>");
		out.println("<input type=submit value=提交 />");
		out.println("</form></body></html>");

	}
}
package chap13.filter;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

/**
 * 
 * @author dvking
 * 将某些字符串替换为另外一字符串的过滤器
 */
public class ReplaceTextFilter implements Filter {

	private FilterConfig config = null;
	
	public void destroy() {
		// TODO Auto-generated method stub
		this.config = null;
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub

		ReplaceTextWrapper wrapper = new ReplaceTextWrapper(
											response,
											config.getInitParameter("oldstr"),
											config.getInitParameter("newstr"));
		config.getServletContext().log("ReplaceTextFilter:before call chain.doFilter()" + 
										config.getInitParameter("oldstr") + "->"
										+ config.getInitParameter("newstr")
										);
		//注意,这是是wrapper	
		chain.doFilter(request, wrapper);
		config.getServletContext().log("ReplaceTextFilter:after call chain.doFilter()");
		wrapper.getOutputStream().close();
	}

	public void init(FilterConfig config) throws ServletException {
		// TODO Auto-generated method stub
		this.config = config;
	}
	
}


 
 
 
 

 package chap13.filter; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; /** * * @author dvking * */ public class ReplaceTextWrapper extends HttpServletResponseWrapper { private ReplaceTextStream rpStream; public ReplaceTextWrapper(ServletResponse response, String oldstr, String newstr) throws IOException { super((HttpServletResponse)response); this.rpStream = new ReplaceTextStream(response.getOutputStream(), oldstr, newstr); } public ServletOutputStream getOutputStream() throws IOException{ return this.rpStream; } } 
 
package chap13.filter;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class ReplaceTextStream extends ServletOutputStream {

	private OutputStream intStream;
	private ByteArrayOutputStream baStream;
	private boolean closed = false;
	private String oldstr;
	private String newstr;
	
	public ReplaceTextStream(OutputStream outStream, String oldstr, String newstr){
		this.intStream  = outStream;
		this.baStream = new ByteArrayOutputStream();
		this.oldstr = oldstr;
		this.newstr = newstr;
	}
	
	@Override
	public void write(int arg0) throws IOException {
		// TODO Auto-generated method stub
		this.baStream.write(arg0);
	}
	
	public void println(String s) throws IOException{
	//	System.out.print(s);
		s += "\n";
		byte [] bs = s.getBytes();
		this.baStream.write(bs);
	}
	
	public byte[] replaceContent(byte [] bs) throws UnsupportedEncodingException{
		
		String retstr = null;
		
		String old = new String(bs);
		int i = old.indexOf(this.oldstr);
		if(i != -1){
			retstr = old.substring(0, i) 
					+ this.newstr 
					+ old.substring(i + this.oldstr.length());
					
		}else{
			retstr = old;
		}
//		return retstr.getBytes();
		return retstr.getBytes("UTF-8");  //注意这里一定要主要字符编码的转换
	}
	
	public void processStream() throws IOException{
		System.out.print(new String(replaceContent(this.baStream.toByteArray())));
		this.intStream.write(replaceContent(this.baStream.toByteArray()));
		this.intStream.flush();
	}
	
	public void close() throws IOException{
		if(!closed){
			processStream();
			this.intStream.close();
			closed = true;
		}
	}
	
	public void flush() throws IOException{
		//首先判断大小
		if(this.baStream.size() != 0){
			if(!closed){
				this.processStream();
				this.baStream = new ByteArrayOutputStream();
			}
		}
	}

}


 
 
 
 
 

转载于:https://www.cnblogs.com/dvking/archive/2012/01/02/2368702.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值