sitemesh2.4在Weblogic10.3下中文乱码解决方法

     测试了sitemesh装饰器的使用,在Tomcat6.0下部署时页面显示正常,但是迁移到Weblogic10.3.4下,被装饰器修饰的目标页面中文出现乱码,效果如下:

sitemesh2.4在Weblogic10.3下中文乱码解决方法_第1张图片

    在网上搜索解决方法,但是都不太满意,后来查看sitemesh的源码,分别在Tomcat6.0和Weblogic10.3下调试发现运行方式不一样,在此记录一下这几天辛苦查找历程。

我的目标页面:index.jsp(已设定页面编码方式UTF-8)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div style="background-color:yellow">测试SiteMesh</div>11
</body>
</html>

装饰器页面:decorator.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<html>
    <head>
    	<title>My Site - <decorator:title default="Welcome!" /></title>
        <decorator:head/>
    </head>
    <body>
        <decorator:body/>
        <p><small>使用了sitemesh页面装饰器</small></p>
    </body>
</html>

配置文件:decorators.xml

<?xml version="1.0" encoding="UTF-8"?>
<decorators defaultdir="/decorators">
	<decorator name="main" page="decorator.jsp">
		<pattern>/*</pattern>
	</decorator>
</decorators>

web.xml(项目配置了struts2,不过这里对sitemesh没有影响,只是记录一下过滤器的排列顺序)

    <!-- 清除ActionContext -->
    <filter>
	<filter-name>struts-cleanup</filter-name>
	<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
    </filter>
	
    <!-- Character Encoding filter -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
	
    <!-- 页面装饰器siteMesh -->
    <filter>
        <filter-name>sitemesh</filter-name>
         <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
    </filter>
	
	<!-- struts2的核心过滤器 -->
    <filter>
	<filter-name>struts2</filter-name>
	<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> 
    </filter>
		
<!-- 过滤器链, 以filter-mapping的顺序决定过滤器链的顺序 -->
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!-- ActionContextCleanUp放在SiteMesh之前 -->
    <filter-mapping>
	<filter-name>struts-cleanup</filter-name>
	<url-pattern>/*</url-pattern>
    </filter-mapping>
	
    <!-- sitemesh处于第二位 -->
    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!-- struts过滤器放在sitemesh后面 -->
    <filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>*.action</url-pattern>
    </filter-mapping>

在网上提供的解决方式大概有以下几种:
1、修改domains\mydomain\bin\setDomainEnv.cmd,在set JAVA_OPTIONS=%JAVA_OPTIONS%后面添加 -Dfile.encoding=UTF-8,这样被装饰页面中文乱码的问题解决了,但是weblogic控制台中文信息出现乱码,这样多少让人感觉有点不太舒服。
2、修改sitemesh源代码,com.opensymphony.module.sitemesh.filter.TextEncoder.java,将private static final String DEFAULT_ENCODING = System.getProperty("file.encoding");修改为private static final String DEFAULT_ENCODING =”UTF-8”。

3、自己创建一个Listener,该Listener的关键代码为:Properties prop = System.getProperties();prop.put("file.encoding", "utf-8");接着在web.xml中配置该Listener。Listener的作用和方式一类似,只不过该设置只对应用有效,Weblogic控制台也不会出现乱码。

     在Eclipse下调试发现SiteMeshFilter执行到private Content obtainContent(ContentProcessor contentProcessor, SiteMeshWebAppContext webAppContext,HttpServletRequest request, HttpServletResponse response, FilterChain chain)方法的chain.doFilter(request, contentBufferingResponse);时,会调用ContentBufferingResponse类初始化时构造的PageResponseWrapper 示例的public void setContentType(String contentType)方法,同时传递页面类型参数。Tomcat6.0和Weblogic的区别就在这里,Tomcat6.0只执行一次,传递的参数是“text/html; charset=UTF-8”,而Weblogic执行了三次,第一次传递参数是“text/html”,其余两次则是“text/html; charset=UTF-8”,因为在第一次执行setContentType(String contentType)方法时会初始化一个com.opensymphony.module.sitemesh.filter.Buffer类的实例buffer,由于Weblogic传递参数是“text/html”,导致buffer实例的encoding属性为null,从而后续取内容调用buffer.getContents()时其执行了return TEXT_ENCODER.encode(bufferedStream.toByteArray(), encoding);(其中encoding 参数为null),进而使用了com.opensymphony.module.sitemesh.filter.TextEncoder类的DEFAULT_ENCODING 常量,方式二的修改正是基于这种原因。修改TextEncoder的DEFAULT_ENCODING 常量是可行的,但是我想进一步查找为什么Weblogic第一次执行public void setContentType(String contentType)方法传递参数是“text/html”,后来发现调用setContentType(String contentType)方法的是weblogic.jar包里weblogic.servlet.internal.ServletStubImpl类的public void execute(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChainImpl paramFilterChainImpl)方法有一段代码:

if (getDefaultContentType() != null) {
         paramServletResponse.setContentType(getDefaultContentType());
       }
而getDefaultContentType()的定义是
   protected String getDefaultContentType()
   {
     return null;
   }

所以才会造成没有设置编码的结果吧,这应该是Weblogic的一个bug,在此记录一下。

你可能感兴趣的:(tomcat,weblogic,Decorator,String,struts,encoding)