struts.i18n.encoding

下面我从一个例子来重新审视这个参数的作用.首先我们来做一个实验,看看改参数是否用在了请求流程,是否用在了返回流程.首先下载struts2.0所有的包,我们会得到一个blank的例子程序.

首先有三个返回类型:

Java代码
  1. <constant name="struts.enable.DynamicMethodInvocation" value="true" />
  2. <constant name="struts.devMode" value="false" />
  3. <constant name="struts.i18n.encoding" value="UTF-8" />
  4. <constant name="struts.velocity.manager.classname" value="demo.DemoVelocityManager"/>
  5. <package name="/" namespace="/" extends="struts-default">
  6. <action name="test" class="demo.HelloWorldAction">
  7. <result name="jsp">helloworld.jsp</result>
  8. <result name="velocity" type="velocity">helloworld.vm</result>
  9. <result name="freemarker" type="freemarker">helloworld.ftl</result>
  10. </action>
  11. </package>
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <constant name="struts.devMode" value="false" />
<constant name="struts.i18n.encoding" value="UTF-8" />
<constant name="struts.velocity.manager.classname" value="demo.DemoVelocityManager"/>

<package name="/" namespace="/" extends="struts-default">
		
		<action name="test" class="demo.HelloWorldAction">
			<result name="jsp">helloworld.jsp</result>
			<result name="velocity" type="velocity">helloworld.vm</result>
			<result name="freemarker" type="freemarker">helloworld.ftl</result>
		</action>
	</package>



接着定义action:

Java代码
  1. /**
  2. *
  3. * @author ahuaxuan
  4. * @date 2008-6-8
  5. * @version $id$
  6. */
  7. public class HelloWorldAction {
  8. private String requestEncoding;
  9. private String responseEncoding;
  10. public void check() {
  11. requestEncoding = ServletActionContext.getRequest().getCharacterEncoding();
  12. responseEncoding = ServletActionContext.getResponse().getCharacterEncoding();
  13. }
  14. public String doJsp() {
  15. check();
  16. return "jsp";
  17. }
  18. public String doVelocity() {
  19. check();
  20. return "velocity";
  21. }
  22. public String doFreemarker() {
  23. check();
  24. return "freemarker";
  25. }
  26. }
/**
 * 
 * @author ahuaxuan
 * @date 2008-6-8
 * @version $id$
 */
public class HelloWorldAction {

	private String requestEncoding;
	
	private String responseEncoding;
	
	public void check() {
		requestEncoding = ServletActionContext.getRequest().getCharacterEncoding();
		responseEncoding = ServletActionContext.getResponse().getCharacterEncoding();
	}
	public String doJsp() {
		check();
		return "jsp";
	}
	
	public String doVelocity() {
		check();
		return "velocity";
	}
	
	public String doFreemarker() {
		check();
		return "freemarker";
	}
}


访问:
http://localhost:8080/demo/test!jsp.action

Java代码
  1. 页面输出:Languages
  2. • requestEncoding:UTF-8
  3. • responseEncoding:ISO-8859-1
页面输出:Languages
•	requestEncoding:UTF-8 
•	responseEncoding:ISO-8859-1 



http://localhost:8080/demo/test!freemarker.action

Java代码
  1. 页面输出:Languages
  2. • requestEncoding:UTF-8
  3. • responseEncoding:ISO-8859-1
页面输出:Languages
•	requestEncoding:UTF-8 
•	responseEncoding:ISO-8859-1 



http://localhost:8080/demo/test!velocity.action

Java代码
  1. 页面输出:Languages
  2. • requestEncoding:UTF-8
  3. • responseEncoding:ISO-8859-1
页面输出:Languages
•	requestEncoding:UTF-8 
•	responseEncoding:ISO-8859-1 



看上去返回流的编码没有变化,都是iso-8859-1.
struts.i18n.encoding换成GBK之后,3个页面的requestEncoding:都变成了requestEncoding:GBK,也就是该参数确实用在了请求流程中.
而且response的encoding还是iso-8859-1,看到这个结果可能有人会产生疑惑,不是说这个参数可以用在返回流中的吗,为什么没有体现出来呢?

其实问题出在一个时间上,但是请大家看看HelloWorldAction里的代码,其实是有问题的,因为在check方法是在action里的方法里调用的.而这个时候没有执行到result,struts2.0会在result中会设置response的一些参数(如果需要设置的话),所以这个时候的response中的encoding其实不是response最终的encoding.如何才能看到response中最终的encoding呢,只有在result被执行之后.

于是下面我们写一个filter.如下:

Java代码
  1. public void doFilter(ServletRequest req, ServletResponse res,
  2. FilterChain fc) throws IOException, ServletException {
  3. fc.doFilter(req, res);
  4. System.out.println("responseEncoding : " + res.getCharacterEncoding());
  5. }
public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain fc) throws IOException, ServletException {
		fc.doFilter(req, res);
		System.out.println("responseEncoding : " + res.getCharacterEncoding());
	}



然后在web.xml中配置在struts2的filter之前:

Java代码
  1. <filter-mapping>
  2. <filter-name>encode</filter-name>
  3. <url-pattern>/*</url-pattern>
  4. </filter-mapping>
  5. <filter-mapping>
  6. <filter-name>struts2</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>
<filter-mapping>
        <filter-name>encode</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>



然后分别请求

http://localhost:8080/demo/test!jsp.action

Java代码
  1. • 控制台输出:
  2. • responseEncoding:UTF-8
•	控制台输出:
•	responseEncoding:UTF-8



http://localhost:8080/demo/test!freemarker.action

Java代码
  1. 控制台输出:
  2. • responseEncoding:GBK
控制台输出:
•	responseEncoding:GBK



http://localhost:8080/demo/test!velocity.action

Java代码
  1. 控制台输出:
  2. • responseEncoding:GBK
控制台输出:
•	responseEncoding:GBK


由此可见在freemarker和velocity中struts.i18n.encoding确实被用来作为response返回流中content-type的charset值.

那么为什么jsp不是这样的呢.
因为jsp并不是模板,而是一个类,在真正运行的时候,servlet容器会把jsp编译成一个类.我们的HelloWorld.jsp就变成了HelloWorld_jsp.java,在这个类中我们可以看到如下代码:

Java代码
  1. try {
  2. _jspxFactory = JspFactory.getDefaultFactory();
  3. response.setContentType("text/html; charset=UTF-8");
  4. pageContext = _jspxFactory.getPageContext(this, request, response,
  5. null, true, 8192, true);
  6. _jspx_page_context = pageContext;
try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html; charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;


修改jsp中@page标签中的charset为GBK之后,控制台也输出了responseEncoding:GBK
这说明,在jsp中,返回流的参数是由jsp的@page标签指定的,而不是有truts.i18n.encoding指定的.

由此可见, struts.i18n.encoding确实用在了请求和返回两个阶段,而且在返回阶段不同的view技术可能使用或者不使用struts.i18n.encoding,freemarker和velocity会以该值作为返回流的charset,而jsp会以页面上的@page标签中的charset作为返回流的charset.

至于源代码,它们分别在VelocityResult,freemarkermanager,dispatcher, FilterDispatcher,大家有兴趣可以自行查看.

对于之前误导大家认为该参数只用在返回流程中,我向大家说一声对不起.从这件事情中我也学习到很多,尤其是态度上,之前做实验的时候发现这个参数用在一个地方,便认为它只会用在这个地方,但是事实上这种想法是不对的,它用在一个地方不代表不能用在另外一个地方.我们应该抱着更为严谨的态度去看待所有的问题,其实当时只要在源码里search “struts.i18n.encoding”这个字符串就会立刻得到完整的结论,但是正因为自己不严谨的态度导致之前作出了片面的结论.

最后共享一些我放在之前放在一边的座右铭:态度决定高度,所以不管做什么事情都要先端正自己的态度,希望能与大家共勉.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值