|
下面我從一個(gè)例子來(lái)重新審視這個(gè)參數(shù)的作用.首先我們來(lái)做一個(gè)實(shí)驗(yàn),看看改參數(shù)是否用在了請(qǐng)求流程,是否用在了返回流程.首先下載struts2.0所有的包,我們會(huì)得到一個(gè)blank的例子程序.
<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:
/**
*
* @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";
}
}
訪問(wèn): http://localhost:8080/demo/test!jsp.action
頁(yè)面輸出:Languages · requestEncoding:UTF-8 · responseEncoding:ISO-8859-1 http://localhost:8080/demo/test!freemarker.action
頁(yè)面輸出:Languages · requestEncoding:UTF-8 · responseEncoding:ISO-8859-1 http://localhost:8080/demo/test!velocity.action
頁(yè)面輸出:Languages · requestEncoding:UTF-8 · responseEncoding:ISO-8859-1 看上去返回流的編碼沒(méi)有變化,都是iso-8859-1. struts.i18n.encoding換成GBK之后,3個(gè)頁(yè)面的requestEncoding:都變成了requestEncoding:GBK,也就是該參數(shù)確實(shí)用在了請(qǐng)求流程中. 而且response的encoding還是iso-8859-1,看到這個(gè)結(jié)果可能有人會(huì)產(chǎn)生疑惑,不是說(shuō)這個(gè)參數(shù)可以用在返回流中的嗎,為什么沒(méi)有體現(xiàn)出來(lái)呢? 其實(shí)問(wèn)題出在一個(gè)時(shí)間上,但是請(qǐng)大家看看HelloWorldAction里的代碼,其實(shí)是有問(wèn)題的,因?yàn)樵赾heck方法是在action里的方法里調(diào)用的.而這個(gè)時(shí)候沒(méi)有執(zhí)行到result,struts2.0會(huì)在result中會(huì)設(shè)置response的一些參數(shù)(如果需要設(shè)置的話),所以這個(gè)時(shí)候的response中的encoding其實(shí)不是response最終的encoding.如何才能看到response中最終的encoding呢,只有在result被執(zhí)行之后. 于是下面我們寫(xiě)一個(gè)filter.如下:
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之前:
<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>
然后分別請(qǐng)求 http://localhost:8080/demo/test!jsp.action
· 控制臺(tái)輸出: · responseEncoding:UTF-8 http://localhost:8080/demo/test!freemarker.action
控制臺(tái)輸出: · responseEncoding:GBK http://localhost:8080/demo/test!velocity.action
控制臺(tái)輸出: · responseEncoding:GBK 由此可見(jiàn)在freemarker和velocity中struts.i18n.encoding確實(shí)被用來(lái)作為response返回流中content-type的charset值. 那么為什么jsp不是這樣的呢. 因?yàn)閖sp并不是模板,而是一個(gè)類,在真正運(yùn)行的時(shí)候,servlet容器會(huì)把jsp編譯成一個(gè)類.我們的HelloWorld.jsp就變成了HelloWorld_jsp.java,在這個(gè)類中我們可以看到如下代碼:
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標(biāo)簽中的charset為GBK之后,控制臺(tái)也輸出了responseEncoding:GBK 這說(shuō)明,在jsp中,返回流的參數(shù)是由jsp的@page標(biāo)簽指定的,而不是有truts.i18n.encoding指定的. 由此可見(jiàn), struts.i18n.encoding確實(shí)用在了請(qǐng)求和返回兩個(gè)階段,而且在返回階段不同的view技術(shù)可能使用或者不使用struts.i18n.encoding,freemarker和velocity會(huì)以該值作為返回流的charset,而jsp會(huì)以頁(yè)面上的@page標(biāo)簽中的charset作為返回流的charset. 至于源代碼,它們分別在VelocityResult,freemarkermanager,dispatcher, FilterDispatcher,大家有興趣可以自行查看. 對(duì)于之前誤導(dǎo)大家認(rèn)為該參數(shù)只用在返回流程中,我向大家說(shuō)一聲對(duì)不起.從這件事情中我也學(xué)習(xí)到很多,尤其是態(tài)度上,之前做實(shí)驗(yàn)的時(shí)候發(fā)現(xiàn)這個(gè)參數(shù)用在一個(gè)地方,便認(rèn)為它只會(huì)用在這個(gè)地方,但是事實(shí)上這種想法是不對(duì)的,它用在一個(gè)地方不代表不能用在另外一個(gè)地方.我們應(yīng)該抱著更為嚴(yán)謹(jǐn)?shù)膽B(tài)度去看待所有的問(wèn)題,其實(shí)當(dāng)時(shí)只要在源碼里search “struts.i18n.encoding”這個(gè)字符串就會(huì)立刻得到完整的結(jié)論,但是正因?yàn)樽约翰粐?yán)謹(jǐn)?shù)膽B(tài)度導(dǎo)致之前作出了片面的結(jié)論. 最后共享一些我放在之前放在一邊的座右銘:態(tài)度決定高度,所以不管做什么事情都要先端正自己的態(tài)度,希望能與大家共勉. 附,由于ahuaxuan水平有限,很有可能還是沒(méi)有挖掘出更深層次的見(jiàn)解,希望您能多指正. |
|
|