sitemesh2.x+velocity+springmvc乱码解决方案

sitemesh2.x+velocity乱码解决方案.md

引言

通常我们在采用springmvc+velocity架构的时候只需要跳转到action然后在转回html页面,此时即可通过velocity的固有语法在html中取出各种变量。当当我们想在以上的架构中加入sitemesh2.x 的时候会发现配置装饰页面时采用action会出现一些错误,而只能直接使用.vm来配置装饰器页面,可是这样直接跳转的做法很多时候会出现一些乱码问题。

正文

有人会说,可以在velocity的配置文件中加入字符集设置,配置如下:

1 input.encoding = UTF-8
2  output.encoding = UTF-8
3 response.setContentType("text/html;charset=utf-8");
4 request.setContentType("text/html;charset=utf-8");

然后再在spring配置velocity试图解析器的时候加入如下代码,其中<property name="contentType" value="text/html;charset=utf-8" />约定了编码格式为utf-8

 1 <!-- Velocity视图解析器 -->
 2     <bean id="viewResolver"
 3         class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
 4             <property name="prefix" value="" />
 5             <property name="suffix" value=".html" />
 6             <!-- Whether we should cache views, once resolved -->
 7             <property name="cache" value="false" />
 8             <property name="contentType" value="text/html;charset=utf-8" />
 9             <!-- 暴露Spring本身的宏 -->
10             <property name="exposeSpringMacroHelpers" value="true" />
11
12             <!-- 格式化日期 :$dateTool.format("yyyy-MM-dd",$!{})  -->
13             <property name="dateToolAttribute" value="dateTool" />
14             <!-- 格式化数字 :  -->
15             <property name="numberToolAttribute" value="numberTool" />
16             <property name="toolboxConfigLocation" value="/WEB-INF/cla
17
18 sses/velocity/toolbox.xml" />
19     </bean>

我相信以上方法已经解决了部分人的乱码问题,但是这一类相关文章我也看了很多,我的问题依然没有解决。
其实上述方法无法解决问题的时候,还有一套终极手段,就是修改服务器的编码方式为utf-8,这种方案通常可以解决绝大部分的乱码问题。但是,这种方法不到万不得已的时候不能使用,因为很有可能公用服务器的时候,你根本没有权限甚至你根本就不能去修改服务器的编码方式,因为这很可能对公用服务器造成一系列未知问题。
我出现的乱码情况比较奇异,因为我访问的内容页是 localhost:8080/sourceDemo/index.action ,而按照sitemesh的组合后的页面的规则来看实际应该就是 访问test.vm这个文件,在这个文件中我有如下变量声明:

其中${body} 是取得用户访问的页面的body标签内的所有元素,而我得到的结果是
哈利路亚四个字乱码了,也就是说装饰器页面乱码,而用户访问的页面没有乱码。
然后通过velocity解析成html页面
于是乎,出于上述考虑,我便决定查看sitemesh源码。
以下先给出我的sitemesh在配置文件中的相应配置:
web.xml中的配置:

 1 <!-- sitemesh -->
 2     <filter>
 3             <filter-name>sitemesh</filter-name>
 4             <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
 5     </filter>
 6     <filter-mapping>
 7             <filter-name>sitemesh</filter-name>
 8             <url-pattern>/*</url-pattern>
 9     </filter-mapping>
10     <!-- sitemesh -->
11
12     <!-- sitemesh servlet配置 START -->
13     <servlet>
14             <servlet-name>site-mesh-velocity</servlet-name>
15             <servlet-class>com.cloudwinker.source.sitemesh.module.velocity.VelocityDecoratorServlet</servlet-class>
16             <load-on-startup>1</load-on-startup>
17     </servlet>
18
19     <servlet-mapping>
20             <servlet-name>site-mesh-velocity</servlet-name>
21             <url-pattern>*.vm</url-pattern>
22     </servlet-mapping>
23     <!-- sitemesh servlet配置 END -->

sitemesh.xml中的配置

<sitemesh>
         <property name="decorators-file" value="/WEB-INF/config/sitemesh/decorators.xml" />
        <excludes file="${decorators-file}" /> 

    <page-parsers>
            <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />
        </page-parsers>

        <decorator-mappers>

            <mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
                <param name="property.1" value="meta.decorator" />
                <param name="property.2" value="decorator" />
            </mapper>

            <mapper class="com.opensymphony.module.sitemesh.mapper.FrameSetDecoratorMapper">
            </mapper>

            <mapper class="com.opensymphony.module.sitemesh.mapper.AgentDecoratorMapper">
                <param name="match.MSIE" value="ie" />
                <param name="match.Mozilla [" value="ns" />
                <param name="match.Opera" value="opera" />
                <param name="match.Lynx" value="lynx" />
            </mapper>

            <mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper">
                <param name="decorator" value="printable" />
                <param name="parameter.name" value="printable" />
                <param name="parameter.value" value="true" />
            </mapper>

            <mapper class="com.opensymphony.module.sitemesh.mapper.RobotDecoratorMapper">
                <param name="decorator" value="robot" />
            </mapper>

            <mapper class="com.opensymphony.module.sitemesh.mapper.ParameterDecoratorMapper">
                <param name="decorator.parameter" value="decorator" />
                <param name="parameter.name" value="confirm" />
                <param name="parameter.value" value="true" />
            </mapper>

            <mapper class="com.opensymphony.module.sitemesh.mapper.FileDecoratorMapper">
            </mapper>

            <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
                    <param name="config" value="${decorators-file}" />
            </mapper>

        </decorator-mappers>

</sitemesh>

decorator.xml中的配置

<?xml version="1.0" encoding="ISO-8859-1"?>

<decorators defaultdir="/decorators">
    <!-- Any urls that are excluded will never be decorated by Sitemesh -->
<!--     <excludes> -->
<!--         <pattern>/frontpage/pages/source/product/product_para.jsp</pattern> -->
<!--     </excludes> -->

<decorator name="adminMain" page="/test.vm">
         <pattern>/views/admin/*</pattern>
</decorator>

<!--      <decorator name="adminFooter" page="views/admin/pages/decorators/foot.html"/>  -->
</decorators>

其中根目录下得test.vm即为装饰器页面,我将用它来装饰内容页
sitemesh是通过filter来实现的,因此入口其实就是filter部分,
而我配置在web.xml的filter中的部分,实际上是一个与velocity结合的工具,其原本的配置并非是这个,而是com.opensymphony.module.sitemesh.velocity.VelocityDecoratorServlet

<servlet>
            <servlet-name>site-mesh-velocity</servlet-name>
            <servlet-class>com.cloudwinker.source.sitemesh.module.velocity.VelocityDecoratorServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
            <servlet-name>site-mesh-velocity</servlet-name>
            <url-pattern>*.vm</url-pattern>
    </servlet-mapping>

我使用jd-gui工具反编译了sitemesh的源码,发现他实际上继承了org.apache.velocity.tools.view.servlet.VelocityViewServlet;也就是velocity-tools-2.0的jar包,目的就在于将sitemesh出来的页面整合到vm文件中去
这是我修改后的VelocityDecoratorServlet

该文件是直接copysitemeshjar包种的org.apache.velocity.tools.view.servlet.VelocityViewServlet 内容,其中最后一句发现
getTemplate(template)实际上是取得velocity的api中的velocity的一个方法,我从debug中得到最后return velocityTemplate时,该对象的encoding属性为ISO-8859-1 ,因为这个原因导致最终显示在页面时,原本属于test.vm的数据全部显示乱码!因此后续的内容就变更为改变在省城velocity模板之前,改变文件的encoding属性!

于是我通过debug追踪,找到了这个文件,也就是velocity-tool-2.0jar包中的 org.apache.velocity.tools.view.velocityView.java这个文件,我截取部分源码给大家看一下:

这就是最后实际调用的方法,从方法内部发现,当encoding==null时实际上使用的是默认的编码方式。我在debug时发现代码运行的这一句的时候,实际encoding的值是null。
因此无论我们在velocity文件中如何配置,都只能得到ISO-8859-1的编码格式文件,于是中文乱码就成了必然情况。
知道了原因后,剩下的就是修改代码了。之所以这里的encoding是null,我想很有可能跟springmvc+velocity 的配置时,实际上使用的spring的响应机制,因此直接从actiong访问时所有编码正常,而直接sitemesh将vm作为装饰器文件时却出现乱码情况,因为sitemesh只是简单的在web.xml中配置了filter,并没有与spring做相应整合。
于是理论上解决方案有两种:其中一种就是改写sitemesh的filter,使之能够在spring的机制中使用,这样的话就能透过spring来取得velocity的相关编码的配置了。由于我太懒了,目前懒得用这种方式去改写,因为嫌他太麻烦。
第二种方式:实际上就是重写org.apache.velocity.tools.view.velocityView.java 这个文件,将getTemplate这个方法改写成如下

之后重启服务器,运行,问题解决!

sitemesh2.x+velocity+springmvc乱码解决方案,布布扣,bubuko.com

时间: 2024-08-08 09:34:37

sitemesh2.x+velocity+springmvc乱码解决方案的相关文章

Spring velocity 中文乱码 解决方案

主要有这么几步,在spring web 的  [sevlet-name]-servlet.xml文件中,修改为: 黑体字体为关键,其它根据你的实际情况配置: <!-- ========================= VIEW DEFINITIONS ========================= -->     <bean id="velocityViewResolver" class="org.springframework.web.servlet

客户端cmd打开mysql,执行插入中文报错或插入中文乱码解决方案

最近在制作一个安装包,需要安装的时候执行mysql脚本儿,做了一个批处理,但是发现总是执行到 插入中文的时候报错,或者插入中文是乱码. 网上查了好多资料,说是把编码改成GBK什么的,终究还是不成功. 最后经过多次测试,现把解决方案分享给大家. 第一步:打开mysql中的配置文件,my.ini,看一看配置文件中 [mysql] default-character-set=utf8 [mysqld] character-set-server=utf8 看是不是这样配置的.因为utf8 是国际通用的,

PHP函数imagefttext( )因--enable-gd-jis-conv引发中文乱码解决方案

阐述 最近几天与公司的PHP开发人员测试即将上线的WEB站点(致难忘的青春岁月:http://hd.gfan.com),在内网测试环境没有任何问题,但在线上测试时,发现通过PHP的GD函数 imagefttext()引用FreeType字体将文本信息写入图像时,出现中文乱码:对此问题,我们在整个排查过程中,总结了三个能引起中文乱码的原因,如下: 1.Linux系统字符集是否支持中文? [email protected]:~#locale LANG=en_US.UTF-8 LANGUAGE=en_

jquery 或ajax返回的中文数据总是乱码解决方案

要将Servlet中的 response.setContentType("text/html;charset=utf-8")这行代码放在 PrintWriter out = response.getWriter()之前. jquery 或ajax返回的中文数据总是乱码解决方案,布布扣,bubuko.com

GET和POST提交乱码解决方案

写在开头: 一般说来在每个页面的开始处,都会加入: <%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%> contentType="text/html;charset=UTF-8"的作用是指定对服务器响应进行重新编码的编码, 当我们提交表单时浏览器会根据contentType对表单的内容进行

Intellij IDEA 各种乱码解决方案

一次解决所有问题,只需做配置文件的修改即可 解决方案: 在      IntelliJ IDEA 2016.1\bin\idea64.exe.vmoptions IntelliJ IDEA 2016.1\bin\idea.exe.vmoptions 都添加 -Duser.country=EN -Duser.language=us -Dfile.encoding=UTF-8 到此ok~! 以下是具体说明 IDEA有分很多种乱码,菜单栏乱码,console输出中文乱码,代码乱码等等,以下提供一些解决

springMVC乱码问题-转

彻底解决Spring MVC 中文乱码 问题 1:表单提交controller获得中文参数后乱码解决方案 注意:  jsp页面编码设置为UTF-8 form表单提交方式为必须为post,get方式下面spring编码过滤器不起效果 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <form action="${ctx}/user/

MYSQL 命令行显示乱码 解决方案

中文乱码是因为编码集不支持,所以要改变编码 先查看下设置的编码 使用如下命令 show variables like 'character%'; 在 mysql.conf (Ubuntu mysql5.5)中的 [client]区域加上 default-character-set = utf8 在[mysqld]区域加上 character_set_server = utf8 重启服务 原文地址:MYSQL 命令行显示乱码 解决方案

MySQL命令行导入sql文件时出现乱码解决方案

Note: sql> source F:weibo.sql(执行相关sql文件) sql> select * from sina into outfile "/weibo.txt"(导出相应数据到C:的weibo.txt) 1. mysql 5.0后其客户端仅支持gbk,故可在sql> set names gbk; 例如: set names gbk; /* Navicat MySQL Data Transfer Source Server : localhost_3