(1) Tapestry中文问题
在目前的Tapestry5.0.5-SNAPSHOT版本中,Tapestry还没有提供对中文的支持。查找了Tapestry的邮件列表,看到如下的解决办法。
首先,可以写一个
UTF8properties的java文件。该文件可以到w3c的网站上找到,代码如下:
- public class Utf8Properties extends Properties {
- /**
- * use serialVersionUID from JDK 1.1.X for interoperability
- */
- private static final long serialVersionUID = 5907218757225133892L;
- /**
- * Encoding used to read properties from a file
- */
- public static final String ENCODING = "UTF-8";
- /**
- * Characters used to write comment lines in a property file
- */
- private static final String COMMENT = "#!";
- /**
- * Possible Separator between key and value of a property in a property
- * file
- */
- private static final String keyValueSeparators = "=: \t\r\n\f";
- /**
- * Creates an empty property list with no default values.
- *
- * @see java.util.Properties#Properties()
- */
- public Utf8Properties() {
- this(null);
- }
- /**
- * Creates an empty property list with the specified defaults.
- *
- * @param defaults the defaults.
- * @see java.util.Properties#Properties(java.util.Properties)
- */
- public Utf8Properties(Properties defaults) {
- this.defaults = defaults;
- }
- /**
- * Reads a property list (key and element pairs) from the input
- * stream. The stream is assumed to be using the UTF-8
- * character encoding or compatible.
- * Characters can be written with their unicode escape sequence.
- *
- * @param inStream the input stream.
- * @exception IOException if an error occurred when reading from the
- * input stream.
- * @throws IllegalArgumentException if the input stream contains a
- * malformed Unicode escape sequence.
- * @see java.util.Properties#load(java.io.InputStream)
- */
- public synchronized void load(InputStream inStream) throws IOException {
- BufferedReader in = new BufferedReader(new InputStreamReader(inStream, ENCODING));
- String line = in.readLine();
- while(line != null) {
- line = removeWhiteSpaces(line);
- if(!line.equals("") && COMMENT.indexOf(line.charAt(0)) == -1) {
- // Removes the beginning separators
- String property = line;
- // Reads the whole property if it is on multiple lines
- while(continueLine(line)) {
- property = property.substring(0, property.length() - 1);
- line = in.readLine();
- property += line;
- }
- //property = new String(property.getBytes(ENCODING), ENCODING);
- if(!property.equals("")) {
- int endOfKey = 0;
- // calculates the ending index of the key
- while(endOfKey < property.length() &&
- (keyValueSeparators.indexOf(property.charAt(endOfKey)) == -1)) {
- endOfKey++;
- }
- String key = property.substring(0, endOfKey);
- String value = property.substring(endOfKey + 1, property.length());
- key = loadConversion(key);
- value = loadConversion(removeWhiteSpaces(value));
- put(key, value);
- For debugging only
- //System.out.println("key: " + key);
- //System.out.println("value: " + value);
- //System.out.println("-----------");
- }
- }
- line = in.readLine();
- }
- }
- /**
- * A simple method to remove white spaces
- * at the beginning of a String
- * @param line the String to treat
- * @return the same String without white spaces at the beginning
- */
- public static String removeWhiteSpaces(String line) {
- int index = 0;
- while(index < line.length() && keyValueSeparators.indexOf(line.charAt(index)) != -1) {
- index++;
- }
- return line.substring(index, line.length());
- }
- /**
- * Replaces all characters preceded by a '\' with the corresponding special
- * character and converts unicode escape sequences to their value
- * @param line the String to treat
- * @return the converted line
- */
- private String loadConversion(String line) {
- StringBuffer val = new StringBuffer(line.length());
- int index = 0;
- // Replace all the "\." substrings with their corresponding escaped characters
- for(; index < line.length(); index++) {
- char currentChar = line.charAt(index);
- if(currentChar == '\\') {
- index++;
- currentChar = line.charAt(index);
- switch(currentChar) {
- case 't':
- currentChar = '\t';
- break;
- case 'r':
- currentChar = '\r';
- break;
- case 'n':
- currentChar = '\n';
- break;
- case 'f':
- currentChar = '\f';
- break;
- case 'u':
- index++;
- // Read the xxxx
- int value=0;
- for (int i=0; i<4; i++) {
- currentChar = line.charAt(index++);
- //System.out.println(currentChar);
- switch (currentChar) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- value = (value << 4) + currentChar - '0';
- break;
- case 'a': case 'b': case 'c':
- case 'd': case 'e': case 'f':
- value = (value << 4) + 10 + currentChar - 'a';
- break;
- case 'A': case 'B': case 'C':
- case 'D': case 'E': case 'F':
- value = (value << 4) + 10 + currentChar - 'A';
- break;
- default:
- throw new IllegalArgumentException(
- "Malformed \\uxxxx encoding.");
- }
- }
- // index must point on the last character of the escaped
- // sequence to avoid missing the next character
- index--;
- currentChar = (char) value;
- default:
- break;
- }
- }
- val.append(currentChar);
- }
- return val.toString();
- }
- /**
- * Replaces special characters with their '2-chars' representation.<br/>
- * For example, '\n' becomes '\\' followed by 'n'
- * @param line the String to treat
- * @return the resulting String
- */
- private String storeConversion(String line) {
- int length = line.length();
- StringBuffer outBuffer = new StringBuffer(length*2);
- for(int i = 0; i < length; i++) {
- char currentChar = line.charAt(i);
- switch(currentChar) {
- case '\\':
- outBuffer.append('\\');
- outBuffer.append('\\');
- break;
- case '\t':
- outBuffer.append('\\');
- outBuffer.append('t');
- break;
- case '\n':
- outBuffer.append('\\');
- outBuffer.append('n');
- break;
- case '\r':
- outBuffer.append('\\');
- outBuffer.append('r');
- break;
- case '\f':
- outBuffer.append('\\');
- outBuffer.append('f');
- break;
- default:
- outBuffer.append(currentChar);
- break;
- }
- }
- return outBuffer.toString();
- }
- /**
- * Indicates wether the property continues on the next line or not
- * @param line the beginning of the property that might be continued on the next line
- * @return true if the propertiy continues on the following line, false otherwise
- */
- private boolean continueLine(String line) {
- if(line != null && !line.equals("")) {
- return line.charAt(line.length() - 1) == '\\';
- }
- return false;
- }
- /**
- * The same method as java.util.Properties.store(...)
- *
- * @param out an output stream
- * @param header a description of the property list
- * @see java.util.Properties#store(java.io.OutputStream, java.lang.String)
- */
- public void store(OutputStream out, String header) throws IOException {
- BufferedWriter output;
- output = new BufferedWriter(new OutputStreamWriter(out, ENCODING));
- if (header != null) {
- output.write("#" + header);
- output.newLine();
- }
- output.write("#" + new Date());
- output.newLine();
- // we do not want that a Thread could modify this Utf8Properties
- // while storing it
- synchronized (this) {
- Enumeration e = keys();
- while(e.hasMoreElements()) {
- String key = storeConversion((String)e.nextElement());
- String val = storeConversion((String)get(key));
- output.write(key + "=" + val);
- output.newLine();
- }
- }
- output.flush();
- }
- }
然后将该文件编译后放到org\apache\tapestry\util包内。
接下来就可以修改其原文件了。要修改的原文件是org.apache.tapestry.internal.services包下的MessagesSourceImpl类。将该类的readProperties(Resource resource)方法中的java.util.Properties类改为我们编写的Utf8properties类。然后再修改org.apache.tapestry.internal.services包下的RequestImpl和ResponseImpl类文件。
将RequestImpl类文件中的方法改为如下内容:
- public String getParameter(String name)
- {
- String param = _request.getParameter(name);
- if(param != null)
- try
- {
- param = new String(param.getBytes("ISO-8859-1"),"utf-8");
- }
- catch (UnsupportedEncodingException ex)
- {
- //won't error
- }
- return param;
- }
- public String[] getParameters(String name)
- {
- String[] params = _request.getParameterValues(name);
- try
- {
- for(int i=params.length-1;i>=0;i--){
- params[i] = new String(params[i].getBytes("ISO-8859-1"),"utf-8");
- }
- }
- catch (UnsupportedEncodingException ex)
- {
- //won't error
- }
- return params;
- }
将ResponseImpl类文件中的方法改为如下内容:
- public PrintWriter getPrintWriter(String contentType) throws IOException
- {
- notBlank(contentType, "contentType");
- if(contentType.matches("text/html.*"))
- _response.setCharacterEncoding("utf-8");
- _response.setContentType(contentType);
- return _response.getWriter();
- }
- public OutputStream getOutputStream(String contentType) throws IOException
- {
- notBlank(contentType, "contentType");
- if(contentType.matches("text/html.*"))
- _response.setCharacterEncoding("utf-8");
- _response.setContentType(contentType);
- return _response.getOutputStream();
- }
最后重新编译打包就可以了。最后要注意的是此时我们所有应用用到的文件都要以utf-8格式进行编码.
该问题由LinuxBoy在邮件列表中提出,并得到了解决。
https://issues.apache.org/jira/browse/TAPESTRY-1294