如何用过滤器过滤HTTP协议和非HTTP协议编码
在编写web时,最苦恼的事情就是乱码了。
一直没怎么考虑过JSP第一句话中<%@ page language="java" contentType="text/html; charset=GBK" pageEncoding="GBK"%>的ContentType和pageEncoding具体是用做什么的,害自己做了过滤器也老是出现问题。
Google下:
contentType ------------指定的是JSP页最终 Browser(客户端)所见到的网页内容的编码. pageEncoding ------------指定JSP编写时所用的编码如果害怕忘了在每个jsp都加上这样的编码,或者由于不同环境所需的客户端所见编码的不同。加上过滤器来解决
1.HTTP协议下的过滤:
(1.login.jsp )用来模拟输入数据登录
<%@ page language="java" pageEncoding="GBK"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" > <title>HTTP协议和URL编码</title> </head> <body> <p>这里仅仅POST编码测试</p> <form action="main.jsp" method="post"> <label>测试HTTP协议</label> <input type="text" name="infoPost" /> <input type="submit" value="提交"> </form> <hr> <p>测试通过GET传送(url方式)</p> <form action="main.jsp" method="get"> <label>测试URL</label> <input type="text" name="infoGet" /> <input type="submit" value="提交"> </form> </body> </html>
(2.main.jsp )用来模拟得到数据
<%@ page language="java" pageEncoding="GBK"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" > <title>获取页面传过来的值</title> </head> <body> 获取通过HTTP协议传送过来的值 <%=request.getParameter("infoPost") %> <hr> 获取通过URL传送过来的值 <%=request.getParameter("infoGet") %> </body> </html>(3.web.xml)配置
<!-- 编码过滤器 -->
<filter>
<filter-name>EncodeFilter</filter-name>
<filter-class>demo.filter.EncodeFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(4.EncodeFilter.java)过滤器类
package demo.filter;
import java.io.IOException;
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 EncodeFilter implements Filter {
protected String encoding;
protected FilterConfig filterConfig;
public EncodeFilter() {
this.encoding = null;
this.filterConfig = null;
}
public void destroy() {
filterConfig = null;
encoding = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
/*
* 处理通过HTTP协议提交的数据
*/
HttpServletRequest hrequest = (HttpServletRequest) request;
HttpServletResponse hresponse = (HttpServletResponse) response;
// 这里省略前面两段,直接用request..setCharacterEncoding(encoding);效果是一样的,这里为了说明这个是通过HTTP
// 协议提交
System.out.println("编码格式" + encoding);
hrequest.setCharacterEncoding(encoding);
filterChain.doFilter(request, response);
}
/*
* 过滤器初始化
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
encoding = filterConfig.getInitParameter("encoding");
}
}
结果:
post方式参数存放在请求数据包的消息体中。get方式参数存放在请求数据包的请求行的URI字段中,以?开始以param=value&¶me2=value2的形式附加在URI字段之后。而request.setCharacterEncoding(charset); 只对消息体中的数据起作用,对于URI字段中的参数不起作用。
可以继承扩展HttpServletRequestWrapper 增加过滤功能
添加一个MyEncodeFilter类
package demo.filter;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class MyEncodeFilter extends HttpServletRequestWrapper{
private String encoding="GBK";
public MyEncodeFilter(HttpServletRequest request) {
super(request);
}
public MyEncodeFilter(HttpServletRequest request,String encoding) {
super(request);
this.encoding=encoding;
}
//新增加一个转码方法
public String encodeName(String en){
try {
return new String(en.trim().getBytes("ISO-8859-1"),encoding);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
return en;
}
}
//增强过滤的方法,就是将URI字段中的参数编码(重写)
public String getParameter(String name) {
//直接调用父类的getParameter方法获取参数的值
String value=super.getParameter(name);
//如果不为空就将其转码
value=value==null?null:encodeName(value);
return value;
}
}
改变后的Filter:
package demo.filter;
import java.io.IOException;
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 EncodeFilter implements Filter {
protected String encoding;
protected FilterConfig filterConfig;
public EncodeFilter() {
this.encoding = null;
this.filterConfig = null;
}
public void destroy() {
filterConfig = null;
encoding = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
/*
* 处理通过HTTP协议提交的数据
*/
HttpServletRequest hrequest = (HttpServletRequest) request;
// 这里省略前面两段,直接用request..setCharacterEncoding(encoding);效果是一样的,这里为了说明这个是通过HTTP
// 协议提交
System.out.println("编码格式" + encoding);
hrequest.setCharacterEncoding(encoding);
//新增加方法<只要通过url来头中肯定有get>
if(hrequest.getMethod().equalsIgnoreCase("get")){
hrequest=new MyEncodeFilter(hrequest,encoding);
}
//
filterChain.doFilter(hrequest, response);
}
/*
* 过滤器初始化
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
encoding = filterConfig.getInitParameter("encoding");
}
}
解决成功!