Tapestry 4.1.2中的国际化页面属性
Tapestry应用程序中的登录页面具有一个属性,其中存储了用户键入的密码,然后将其与数据库中的值进行比较。如果用户输入包含多字节字符的密码,例如:
áéíóú
...检查getPassword()的返回值(对应属性的抽象方法)得出:
?????-?3?o
显然,编码不正确。但是Firebug报告说该页面是使用UTF-8进行服务的,因此,表单提交请求也可能会以UTF-8进行编码。检查来自数据库的值会产生正确的字符串,因此不会出现OS或者IDE编码问题。我尚未在.application文件中覆盖Tapestry的org.apache.tapestry.output-encoding的默认值,并且Tapestry 4文档指出该属性的默认值为UTF-8.
那么,为什么在设置属性时Tapestry似乎会破坏编码?
相关代码如下:
Login.html
<html jwcid="@Shell" doctype='html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"' ...> <body jwcid="@Body"> ... <form jwcid="@Form" listener="listener:attemptLogin" ...> ... <input jwcid="password"/> ... </form> ... </body> </html>
登录页面
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE page-specification PUBLIC "-//Apache Software Foundation//Tapestry Specification 4.0//EN" "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd"> <page-specification class="mycode.Login"> ... <property name="password" /> ... <component id="password" type="TextField"> <binding name="value" value="password"/> <binding name="hidden" value="true"/> ... </component> ... </page-specification>
Login.java
... public abstract class Login extends BasePage { ... public abstract String getPassword(); ... public void attemptLogin() { // At this point, inspecting getPassword() returns // the incorrectly encoded String. } ... }
更新
@Jan Soltis:好吧,如果我检查来自数据库的值,它将显示正确的字符串,因此看来我的编辑器,OS和数据库都正确地编码了该值。我还检查了.application文件;它不包含org.apache.tapestry.output-encoding条目,并且Tapestry 4文档指示此属性的默认值为UTF-8. 我已经更新了上面的描述,以反映问题的答案。
@myself:找到了解决方案。
解决方案
回答
一切似乎都是正确的。
我们真的确定getPassword()返回垃圾内容吗?是不是其他人(编辑器,OS,数据库等)在向我们显示密码时可能不知道它是unicode字符串,但密码可能还可以吗?究竟是什么使我们认为这是垃圾?
我还要确保在.application配置文件中没有设置任何奇怪的编码
<meta key="org.apache.tapestry.output-encoding" value="some strange encoding"/>
回答
我发现了问题。 Tomcat在Tapestry或者我的页面类甚至还没有破解之前就修改了参数。创建强制实施所需字符编码的Servlet过滤器即可解决该问题。
CharacterEncodingFilter.java
package mycode; import java.io.IOException; import javax.servlet.*; /** * Allows you to enforce a particular character encoding on incoming requests. * @author Robert J. Walker */ public class CharacterEncodingFilter implements Filter { private static final String ENCODINGPARAM = "encoding"; private String encoding; public void init(FilterConfig config) throws ServletException { encoding = config.getInitParameter(ENCODINGPARAM); if (encoding != null) { encoding = encoding.trim(); } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(encoding); chain.doFilter(request, response); } public void destroy() { // do nothing } }
web.xml
<web-app> ... <filter> <filter-name>characterEncoding</filter-name> <filter-class>mycode.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncoding</filter-name> <url-pattern>/app/*</url-pattern> </filter-mapping> ... </web-app>