最近要用struts2做一个体育类的系统,由于系统本身的原因(要求可操作性强,用户交互性高),所以不可避免地要用到ajax.在我的前一篇文章里已经提到了有关在struts2中运用ajax的一些东西了.这次重新再拾起来,仔细对比下其中的差别.
在前一个例子性系统中,由于所有的编码都是以UTF-8进行编码的,所以也没有碰到过有关乱码的问题.普通调用和ajax调用都很正常地运行了.而在新的系统中,要求所有的页面(包括数据库)都要求运用GBK编码.这样,一些有关于乱码的问题就出现了,乱码...与struts2有关.
大家都知道,在struts2的配置文件中,有一个配置项直接跟编码有关."struts.i18n.encoding"这个配置项表示struts2将对数据进行何种形式的编码操作,默认的编码为utf-8,这也是为什么在前一个新闻系统中没有乱码的原因,因为它本身都和系统默认编码一致.而在新的系统中,由于要求必须将编码改成GBK,配置如下:
<constant name="struts.i18n.encoding" value="GBK"/>
在这种情况下,加上在tomcat serve.xml中修改URIEncoding=GBK,保证传送到服务器的数据都是GBK格式.实际测试中,这种方式是正确的,编码正确.
然而好境不长,当运用到ajax时,问题出现了.我最先采用的是struts2的json插件,看它的要求,它要求工程编码应该为UTF-8,而我的工程编码实际为GBK,这是不可能改回去的事情.先不管它,在页面中配置完成,进行ajax调用.果然,数据乱码.在action中,对数据进行了测试,发现数据在进行action时已经是乱码.对数据进行转码操作,发现将数据按
x = new String(x.getBytes("GBK"),"UTF-8");
时,数据正常了.这就表示数据是按照utf-8格式进行传送的,而在sturts中可能将数据又转回了gbk,导致乱码产生.一开始从js入手,因为我用的prototype.js采用post进行传送.设置的encoding为"UTF-8",修改js的encoding为"GBK",发现并没有按照想像的方向发展,仍然乱码.而采用get方式发送时,数据仍然是乱码.
只有从java方向入手了,处理方向有两种,就像我在前面两篇有关jsp乱码中提到一样.第一种是加拦截器,拦截到ajax请求时,将编码重新转码操作.第二种就是像过滤器一样,在进行参数编码前设置正确的编码.在struts2中采用的是第二种方法.其实struts.i18n.encoding采用的也是这种方法.相应的代码如下:
public void prepare(HttpServletRequest request, HttpServletResponse response) {
String encoding = null;
if (defaultEncoding != null) {
encoding = defaultEncoding;
}
Locale locale = null;
if (defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
}
if (encoding != null) {
try {
request.setCharacterEncoding(encoding);
} catch (Exception e) {
LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
}
}
if (locale != null) {
response.setLocale(locale);
}
if (paramsWorkaroundEnabled) {
request.getParameter("foo"); // simply read any parameter (existing or not) to "prime" the request
}
}
这个方法这是org.apache.struts2.dispatcher.Dispatcher中而被FilterDispatcher调用,后都大家都知道吧,是struts2的标准过滤器.它调用的地方如下:
protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
Dispatcher du = Dispatcher.getInstance();
// Prepare and wrap the request if the cleanup filter hasn't already, cleanup filter should be
// configured first before struts2 dispatcher filter, hence when its cleanup filter's turn,
// static instance of Dispatcher should be null.
if (du == null) {
Dispatcher.setInstance(dispatcher);
// prepare the request no matter what - this ensures that the proper character encoding
// is used before invoking the mapper (see WW-9127)
dispatcher.prepare(request, response);
} else {
dispatcher = du;
}
try {
// Wrap request first, just in case it is multipart/form-data
// parameters might not be accessible through before encoding (ww-1278)
request = dispatcher.wrapRequest(request, getServletContext());
} catch (IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
LOG.error(message, e);
throw new ServletException(message, e);
}
return request;
}
由上可以看出,filter在实例化dispatcher后,调用其的prepare方法,而prepare方法中,好像涉及到的其他相关操作不多,只是操作request 和 response的,在prepare方法中,判断encoding是不是空,如果不为空则将其设置编码入request中.而在defaultEncoding的设置上,可以看出这个参数是跟struts.i18n.encoding相关的,相关代码如下:
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public static void setEncoding(String val) {
encoding = val;
}
在上面这个方法中,将把struts.i18n.encoding注入到encoding中,也就是说,如果我们设置encoding为GBK,无论在何种条件下,它就是GBK编码了.
尝试修改这种方式,因为直接影响的就是
prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response)
这个方法,于是直接修改如为如下:
public class TextFilter extends FilterDispatcher{
private static final Log log = LogFactory.getLog(TextFilter.class);
private FilterConfig filterConfig;
private static String defaultEncoding;
private static String defaultLocale;
private static String paramsWorkaroundEnabled = "false";
@Inject(org.apache.struts2.StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND)
public static void setParamsWorkaroundEnabled(String enabled) {
paramsWorkaroundEnabled = enabled;
}
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public static void setEncoding(String encoding) {
defaultEncoding = encoding;
}
@Inject(value = StrutsConstants.STRUTS_LOCALE, required = false)
public static void setLocale(String locale) {
defaultLocale = locale;
}
public void init(FilterConfig filterConfig) throws ServletException {
super.init(filterConfig);
this.filterConfig = filterConfig;
}
protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
Dispatcher du = Dispatcher.getInstance();
if(du == null) {
Dispatcher.setInstance(dispatcher);
prepare(request, response);
} else {
dispatcher = du;
}
try {
request = dispatcher.wrapRequest(request, getServletContext());
} catch(IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
log.error(message, e);
throw new ServletException(message, e);
}
return request;
}
private void prepare(HttpServletRequest request, HttpServletResponse response) {
String encoding = request.getCharacterEncoding();
if(encoding == null) {
encoding = defaultEncoding;
}
Locale locale = null;
if(defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
}
if(encoding != null) {
try {
request.setCharacterEncoding(encoding);
} catch(Exception e) {
log.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
}
}
if(locale != null) {
response.setLocale(locale);
}
if(isParamsWorkaroundEnabled()) {
request.getParameter("foo");
}
}
public boolean isParamsWorkaroundEnabled() {
ServletContext servletContext = filterConfig.getServletContext();
return servletContext != null && servletContext.getServerInfo() != null && servletContext.getServerInfo().indexOf("WebLogic") >= 0 ||
paramsWorkaroundEnabled.equalsIgnoreCase("true");
}
}
可以看出,整个就是继承filterDispatcher,再修改其中的一个方法.将dispatcher.prepare()这一名改成filter.prepare的形式,实际上效果是一样的.惟一让人感觉不爽的就是,由于在filter中设置的各种变量都是私有而且是是静态的(我尝试用反射都不能得到它的值),导致直接不能得到父类的属性值,没办法,只有再加变量了.在上面的prepare中,判断request中的编码是不是为空,一般来说,从jsp页面传送的编码都是空的.当由js进行传送时,由于已经设置传送编码为UTF-8,故getCharacterEncoding()不为空,则不再进行设置编码了.其他由设置传送编码为defaultEncoding(即sturts.i18n.encoding).
在上面的有一句
if(isParamsWorkaroundEnabled()) { request.getParameter("foo"); }
专为weblogic设置,由于没有接触过,略过.值得不提的是,request.getParamter("foo").这一句,在tomcat里面是直接将编码固定化,即只要调用了这一句,都将使得request(在tomcat的实现中)不能再接受其他编码(参数已经被转化了).
最后,将filter设置在struts.xml中,以便窗口将参数@inject注入到filter中.
<bean class="m_ylf.cs.sicau.struts2.TextFilter" static="true"/>
上面一句必须要,不然相应的静态参数都没有被注入,是会产生NullPointerException的哦.
先解决这一个问题,下一个问题将介绍struts2的json插件,及改进方法.
分享到:
相关推荐
在IE的Unicode编码情况下,Struts2的JSON插件未能正确识别并转换这些Unicode编码,从而导致中文乱码。而FF由于不进行Unicode编码,所以解析正常。 为了解决这个问题,可以考虑更换JSON解析库。例如,使用Google的...
2. **引入依赖**:添加struts2的核心库、JSON插件(jsonplugin.jar)、Struts2-Spring插件、Hibernate库、Spring库、JDBC驱动以及jQuery库。 3. **数据库设计**:创建合适的数据库表并能够在MyEclipse中管理。 4. **...
在Struts2中,开发者可以使用内置的JSON插件或者手动编码的方式来实现JSON数据的输出。 首先,我们来了解Struts2的Action类。Struts2的Action是一个实现了Action接口或继承ActionSupport类的Java类,其主要作用是...
8. **struts2-dojo-plugin.jar** 或 **struts2-jquery-plugin.jar** (取决于具体包内容): 这些插件提供了与JavaScript库(如Dojo或jQuery)的集成,便于在页面中创建富客户端效果。 9. **struts2-spring-plugin.jar...
1. **Struts2**:这是一个基于Java的Web框架,继承了Struts1的优良特性并进行了大幅改进,支持动态调用、拦截器、插件等机制,使得Web应用的开发更加灵活高效。 2. **Spring**:Spring框架是Java平台的一个全面的、...
与Struts1相比,Struts2的设计思想和架构有着根本的不同。Struts2的核心是基于WebWork框架,并且大量采用了拦截器技术,使得业务逻辑控制器能够更好地与Servlet API相分离。 **Struts2的特点**: - **灵活性**:...
Struts2与ExtJS结合,可以创建功能丰富的前端界面,并通过JSON(JavaScript Object Notation)与服务器端进行数据交换。JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,因此它是Web...
4. **Struts与ExtJS交互**:通过Ajax请求,ExtJS可以调用Struts的Action,获取服务器端处理后的数据,实现异步更新界面。 结合以上内容,开发者可以通过ExtJS创建富客户端界面,利用Struts处理业务逻辑和控制流程,...
\contentsline {chapter}{Contents}{2}{section*.1} {1}Java基础}{17}{chapter.1} {1.1}基本语法}{17}{section.1.1} {1.2}数字表达方式}{17}{section.1.2} {1.3}补码}{19}{section.1.3} {1.3.1}总结}{23}{...
**Spring MVC与其他框架的区别**,例如与Struts2: Spring MVC更灵活,支持更多的视图技术,且与Spring框架集成更紧密。Struts2则更注重Action概念,配置相对较多。 **处理请求方法**: - 重定向和转发可通过`...
13. **字符转换**:不同系统间可能存在字符集差异,字符转换工具可以帮助解决乱码问题,例如ISO-8859-1与UTF-8之间的转换。 总结来说,这个CRM项目运用了SSM框架进行开发,涵盖了后端架构、数据库操作、数据处理、...
SpringMVC与Struts2区别 SpringMVC和Struts2都是流行的Web开发框架,但它们之间存在一些关键差异: - **设计模式**:Spring MVC遵循传统的MVC模式,而Struts2则采用了拦截器模式。 - **灵活性**:Spring MVC提供了...