我正在使用Jersey生成RESTful服务,它生成UTF-8编码的回复。 这是一段代码:
public static class Data {
private String value;
public Data(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response method() {
Data response = new Data("€");
return Response.status(Response.Status.OK)
.type(MediaType.APPLICATION_JSON + ";charset=UTF-8")
.entity(response)
.build();
}
应该产生以下答复:
{"value":"€"}
或作为字节数组:
[123, 34, 118, 97, 108, 117, 101, 34, 58, 34, -30, -126, -84, 34, 125]
请注意,欧元符号编码为三个字节-30,-126,-84或0xe2 0x82 0xac。
但是,它产生以下响应
{"value":"â¬"}
或作为字节数组:
[123, 34, 118, 97, 108, 117, 101, 34, 58, 34, -61, -94, -62, -126, -62, -84, 34, 125]
注意,欧元符号现在编码为6个字节-61,-94,-62,-126,-62,-84或0xc3 0xa2 0xc2 0x82 0xc2 0xac。
我发现了一个转换序列,导致这种损坏,在某些时候,UTF-8编码数据被视为Latin1编码数据。
Data data = new Data("€");
org.codehaus.jackson.map.ObjectMapper mapper
= new org.codehaus.jackson.map.ObjectMapper();
try {
String strData = mapper.writeValueAsString(data);
System.out.println(strData);
byte[] rawData = mapper.writeValueAsBytes(data);
System.out.println(Arrays.toString(rawData));
String asLatin1 = new String(rawData, "ISO-8859-1");
byte[] brokenUtf8 = asLatin1.getBytes("UTF-8");
System.out.println(Arrays.toString(brokenUtf8));
} catch (IOException e) {
System.out.println("Fail " + e.getMessage());
}
该服务在两台机器上运行,一台使用apache-tomcat-7.0.30,另一台运行在apache-tomcat-7.0.23中。前者产生正确的UTF-8响应,而后者则损坏了UTF-8。我无法找出导致行为差异的原因以及可以解决问题的原因。
答案 0 :(得分:1)
问题有一个非常悲伤的原因,很难找到。 Ant的javac任务有明确的编码集:
<javac destdir="${classes}" includeantruntime="false" source="1.6" target="1.6" debug="true" encoding="ISO-8859-1" classpathref="main.classpath">
它在一个Tomcat下工作,因为它是用Eclipse构建的,另一个部署是用Ant构建的,破坏了所有Unicode字符。
答案 1 :(得分:0)
如果它在7.0.30而不是在7.0.23中工作,也许这是一个被发现并修复的错误?您是否检查了Tomcat changelog以确定其中是否有任何内容?