这让我困惑了好几个小时,而且似乎天生就不太可能,但请多多包涵;我相信我有证据。
我已将其简化为最小的测试用例(如下)。要测试代码,您需要使用EmailTest.java
(如下),然后导入 SOAP 服务。为此,我使用了:
wsimport -d bin -s src -keep -extension 'http://www.webservicex.net/stockquote.asmx?wsdl'
为方便起见,我也把代码放在了github上,所以你可以简单地克隆它并运行它;这wsimport
已经执行了。
以下代码的作用如下:
- 调用
testMime()
,它创建了一个quoted-printable
部分,然后正确显示它(使用以 开头的序列转义的最高位设置字符=
); - 调用
stockQuoteTest
,它只是获取一个新的 Web 服务入口点——它不需要实际调用 Web 服务; - 再次调用
testMime()
,它创建了一个quoted-printable
部分,但显示不正确,没有转义字符;system.out.Println
然后(可以预见地)将它们替换为?
.
我使用了多个 SOAP 库,它们都做同样的事情——我选择了一个简单的演示来演示。实际上没有必要调用 SOAP 端点。getPort
对(此处)的调用getStockQuoteSoap12
似乎是问题所在。
到目前为止,我的调试已经确定我所知道的默认 Java 编码都没有改变,而且问题似乎是在第二次调用时,quoted-printable
编码器永远不会被调用。这似乎是因为当它工作时part.dh.dataContentHandler
被设置为某种类型ObjectDataContentHandler
,而StringDataContentHandler
当它不工作时被设置为类型。
关于这里发生了什么或如何解决它的任何想法?
我正在使用javax.mail
1.5.2(最新的,但旧版本是相同的) - 和
$ java -version
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)
这里是EmailTest.java
package emailtest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
// use any SOAP service. This one was generated using
// wsimport -d bin -s src -keep -extension http://www.webservicex.net/stockquote.asmx?wsdl
import net.webservicex.StockQuote;
import net.webservicex.StockQuoteSoap;
public class Emailtest {
public static void stockQuoteTest() {
StockQuote stockService = new StockQuote();
StockQuoteSoap s = stockService.getStockQuoteSoap12();
// We don't actually need to call SOAP to demonstrate the problem
// System.out.println("quote is "+s.getQuote("GOOG"));
}
public static void testMime() throws MessagingException {
String msg = "\u0287x\u01DD\u0287 u\u028Dop \u01DDp\u1D09sdn";
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("" + msg, "utf-8");
messageBodyPart.setHeader("Content-Type", "text/plain; charset=\"utf-8\"");
messageBodyPart.setHeader("Content-Transfer-Encoding", "quoted-printable");
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
messageBodyPart.writeTo(os);
String aString = new String(os.toByteArray(),"UTF-8");
System.out.println(aString);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("");
}
public static void main(String args[]) {
try {
System.out.println("Before call to SOAP:");
testMime();
stockQuoteTest();
System.out.println("After call to SOAP:");
testMime();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
这是输出:
Before call to SOAP:
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
=CA=87x=C7=9D=CA=87 u=CA=8Dop =C7=9Dp=E1=B4=89sdn
After call to SOAP:
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
?x?? u?op ?p?sdn
哦,如果重要的话,编码文本是:
ʇxǝʇ uʍop ǝpᴉsdn
您可以看到quoted-printable
使用普通字母创建的“颠倒”字母显示在哪里无法工作(第二次调用)。调查表明它根本没有做quoted-printable
。
更新
这似乎是jax-ws 中的一个错误,并且可以说是 javax.mail 中的一个错误,因为它依赖于text/plain
恰好位于 JAF 而不是它自己的处理程序。任何解决方法的想法?(使用 Java 7,据称在 jax-ws 中修复的地方不是一个选项)