今天学习《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();
}
}
}
}