今天遇到一个很奇怪的问题,所以花时间研究了下!
csdn的文章编辑确实有点体验不太好,自己截的图明明是大图,发表文章后就变成了小图,小图就看不太清除了,大家凑合着看吧!截图在下面!
首先,大家先看下效果吧,先知道我要做什么?我项目中有一个jsp页面中,jsp页面中有个form表单,这个表单主要是用来收集数据的,然后提交(post提交)到服务器端上的一个servlet类处理,表单的文本框中会输入中文,所以为了处理中文乱码的问题,我专门写了一个处理中文乱码的过滤器,在中文乱码过滤器类中设置了编码格式是utf-8,web.xml文件中配置了这个中文乱码过滤器!web.xml文件中还配置了request监听器对象和request的Attribute属性的监听器对象。大家都知道,过滤器类中有一个init方法,在web容器启动的时候,比如tomcat启动的时候,过滤器类中的init方法就会执行,而request监听器对象也有一个方法,叫requestInitialized方法,但是requestInitialized方法不会在tomcat启动的时候执行,而是会在request对象创建的时候执行requestInitialized方法。
代码如下:
RequestListener类
package com.jiongmeng.listener;
import java.util.Enumeration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
/**
* @Description: (request对象在创建和消亡的监听器)
* @author 囧囧 E-mail:[email protected]
* jerry
* @date: 2017年11月8日 下午1:06:49
* Copyright: Copyright (c) 2005-2017版权归囧萌软件科技公司所有
* @version 创建时间:2017年11月8日 下午1:06:49
*/
public class RequestListener implements ServletRequestListener{
@Override
public void requestDestroyed(ServletRequestEvent requestEvent) {
System.out.println("************request对象消亡************");
}
@Override
public void requestInitialized(ServletRequestEvent requestEvent) {
System.out.println("************request对象创建************");
// ServletRequest request = requestEvent.getServletRequest();
// String hobby = request.getParameter("hobby");
// System.out.println("页面传递的参数hobby(爱好) = " + hobby);
// Enumeration parameterNames = request.getParameterNames();
// while (parameterNames.hasMoreElements()) {
// String parameterName = parameterNames.nextElement();
// System.out.println("参数名 = " + parameterName + " 参数值 = " + request.getParameter(parameterName));
// }
}
}
RequestAttributeListener类
package com.jiongmeng.listener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
/**
* @Description: (request对象在attribute时的监听器)
* @author 囧囧 E-mail:[email protected]
* jerry
* @date: 2017年11月8日 下午1:12:47
* Copyright: Copyright (c) 2005-2017版权归囧萌软件科技公司所有
* @version 创建时间:2017年11月8日 下午1:12:47
*/
public class RequestAttributeListener implements ServletRequestAttributeListener{
@Override
public void attributeAdded(ServletRequestAttributeEvent requestAttributeEvent) {
System.out.println("我是request对象的attributeAdded方法");
System.out.println("request对象中添加属性,名 = " + requestAttributeEvent.getName() + " 值 = " + requestAttributeEvent.getValue());
//System.out.println("请求参数hobby的值 = " + requestAttributeEvent.getServletRequest().getParameter("hobby"));
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent requestAttributeEvent) {
System.out.println("我是request对象的attributeRemoved方法");
//打印的是删除前的值
System.out.println("request对象中删除属性,名 = " + requestAttributeEvent.getName() + " 值 = " + requestAttributeEvent.getValue());
// System.out.println("请求参数hobby的值 = " + requestAttributeEvent.getServletRequest().getParameter("hobby"));
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent requestAttributeEvent) {
System.out.println("我是request对象的attributeReplaced方法");
//打印的是修改前的值
System.out.println("request对象中修改属性,名 = " + requestAttributeEvent.getName() + " 值 = " + requestAttributeEvent.getValue());
System.out.println("请求参数hobby的值 = " + requestAttributeEvent.getServletRequest().getParameter("hobby"));
}
}
ChineseMessyCodeFilter类
package com.jiongmeng.filter;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
*
* 中文乱码过滤器(请求前过滤器)
* @author czh
* @time 2017年10月12日 下午10:48:17
*/
public class ChineseMessyCodeFilter implements Filter{
private String characterEncoding = "utf-8";
@Override
public void destroy() {
System.out.println("*******************中文乱码过滤器destroy()*******************");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
request.setCharacterEncoding(characterEncoding);
System.out.println("*********************脱衣服洗澡!(请求前过滤)*********************"); //前过滤
// System.out.println("请求servlet资源路径 = " + ((HttpServletRequest)request).getServletPath());
// System.out.println("请求方式(get / post) = " + ((HttpServletRequest)request).getMethod());
filterChain.doFilter(request, response);
System.out.println(response.getClass());
System.out.println("*********************穿衣服准备出门!(请求后过滤)*********************");//后过滤
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filterName = " + filterConfig.getFilterName());
characterEncoding = filterConfig.getInitParameter("characterEncoding");
Enumeration names = filterConfig.getInitParameterNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
System.out.println(name + " = " + filterConfig.getInitParameter(name));
}
System.out.println("*******************中文乱码过滤器init()*******************");
}
}
web.xml文件
javaWeb
java.lang.ArithmeticException
/arithmeticError.jsp
500
/error500.jsp
404
/error404.jsp
SystemInit
com.jiongmeng.system.SystemInit
0
com.jiongmeng.listener.ApplicationListener
com.jiongmeng.listener.ApplicationAttributeListener
com.jiongmeng.listener.SessionListenerImpl
com.jiongmeng.listener.SessionAttributeListener
com.jiongmeng.listener.RequestListener
com.jiongmeng.listener.RequestAttributeListener
springConfigLocation
/WEB-INF/applicationContext.xml
city
jiangxiyudu
chineseMessyCodeFilter
com.jiongmeng.filter.ChineseMessyCodeFilter
characterEncoding
utf-8
logType
log4j
chineseMessyCodeFilter
/thermaServlet
/hello
/*
15
testRequestGetParameter
testIncludeAction.jsp
tomcatKnowledge.jsp
myJspHideObject
/9jspHideObject.jsp
userName
令狐冲
myJspHideObject
/hello
firstServlet
com.jiongmeng.FirstServlet
1
firstServlet
/firstServlet
/myfirstServlet
bookInfo
com.jiongmeng.BookInfo
bookInfo
/bookInfo/*
/bookInfo/save
/bookInfo/update
/bookInfo/findAll
testServlet
com.jiongmeng.TestServlet
color
blue
color
red
userName
jiongjiong
0
testServlet
/testServlet
在浏览器地址栏中输入jsp地址,就会执行request监听器对象的requestInitialized方法和request的Attribute属性的监听器对象的attributeReplaced方法。等jsp加载完了,就会执行request监听器对象的requestDestroyed方法,当然这些都不是我们的重点!
点击submit按钮提及到服务器端,发现表单中的中文提交到服务器端的时候,服务器端拿到的中文数据是中文乱码,这就很奇怪了,我明明是写了处理中文乱码的过滤器的嘛!
于是我debug了一下,看看执行的流程和顺序是怎么回事!
debug后,第1步执行的是request监听器对象的requestInitialized方法,所以监听器是优先于过滤器执行的,看下图
第2步执行的是RequestAttributeListener类中的attributeReplaced方法,看下图
第3步执行的是ChineseMessyCodeFilter类(中文乱码过滤器类)中的doFilter方法,看下面的截图
这个时候小伙伴应该明白了为什么我们写了中文乱码过滤器还是会乱码!
没错,就是在执行ChineseMessyCodeFilter类(中文乱码过滤器类)中的doFilter方法之前,我们的程序先执行了request监听器对象的requestInitialized方法和request的Attribute属性的监听器对象的attributeReplaced方法,而这2个方法中又使用了request.getParameter()方法,我们都知道在request.setCharacterEncoding("utf-8");这句话之前,不能使用request.getParameter()方法,这样会导致服务器端获取到的还是中文乱码,所以必须是request.getParameter()这句话只能放在request.setCharacterEncoding("utf-8");这句话之后,才能解决中文乱码的问题,所以知道原因了的话,我们只要把RequestAttributeListener类中的attributeReplaced方法中的getServletRequest().getParameter()这句话注释掉,把RequestListener类中requestInitialized方法中的request.getParameter()注释掉,就可以解决中文乱码过滤器失效的问题,所以大家记住,javaweb开发中监听器中的一些语句会导致过滤器失效,就像这个例子一样,request监听器对象中的一些语句导致了中文乱码过滤器失效!
注释掉后,jsp表单提交,服务器端拿表单数据的时候就不会是中文乱码了!,看下图