??xml version="1.0" encoding="utf-8" standalone="yes"?>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.4</source>
<target>1.4</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
讄环境变量MAVEN_OPTS=-Xms64m -Xmx128m -Dfile.encoding=UTF-8
2.q行mvn test时ؕ码(IDE上运行TestCase时OKQ但是运行maven testq,l果试不通过Q修改pom.xml增加如下内容卛_
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<configuration>
<forkMode>once</forkMode>
<argLine>-Dfile.encoding=UTF-8</argLine>
<systemProperties>
<property>
<name>net.sourceforge.cobertura.datafile</name>
<value>target/cobertura/cobertura.ser</value>
</property>
</systemProperties>
</configuration>
</plugin>
]]>
E過分析整理Q我們發珑֕出?QueryString 的解析,以前?Tomcat 4.x 時代Q無?SUBMIT 時採?GET or POSTQTomcat server ?parameters 的處理都採用相同的編|但在 Tomcat 5.x 版,不知何故Q卻?QueryString 的解析獨立出來,目前QForm ?Method 採用 GET 及直接將參數寫在 URL 上的中文Q上傛_ Tomcat 時,無論如何轉碼Q都會變成亂|那怕你事先作過 URLEncode 也一樣?br/>
E站上,有h針對這個問,所有中文改採用 base64 R碼Q到?server 上,E式自行土 base64 decode 回來Q確保中文不會發生問。這樣作法當然可以解決這個問,但是所有網頁變成限定要採用 POSTQ且E式a計師要隨時分清楚,那個參數是採用 GET 上傳Q那個參數是採用 POST 上傳Q然後再針對不同的方式採用不同的解析Q這樣的程式一點兒UL性都沒有Q更別提跨^台、跨國際語言了?br/>
研究 Tomcat 的文件及原始|我們找C問題所在及解決的方法,只有按著以下的作法,才能?Form submit 的資料完全按?ISO8859-1 的編|當然Q若是全照著 Tomcat 的文件說明去作,肯定還是不行Q你還是得加上這個參數到 server.xml 中才行?br/>
解決Ҏ
請先研究 $TOMCAT_HOME/webapps/tomcat-docs/config/http.html 這個說明檔Q擷錄重點如下:
URIEncodingQThis specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.
useBodyEncodingForURIQThis specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitely set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false.
上述二?Tomcat 參數Q是a定?server.xml 中的 http <Connector /> 區塊,要解?QueryString 中文變成亂碼的問,你必須至設定這二個參數其中之一?br/>URIEncoding 請設定為 URIEncoding="ISO-8859-1" 指定?"ISO-8859-1" R碼Q讓 QueryString 的字元編D post body 相同?br/>useBodyEncodingForURI 這是用來相容 Tomcat 4.x 版的Q設定的值是 "true" or "false"Q意思是?"要不要讓 QueryString ?POST BODY 採用相同的字元編??"Q若是設?trueQ那也可達到 "ISO-8859-1" R碼的需求?br/>Q採?URIEncoding 的設定,畢竟 useBodyEncodingForURI 的作法是Z相容 Tomcat 4.X。不過若照原文的說明Q理論上這二個參敔R不設QTomcat 也該採用 "ISO-8859-1" 的編|那為什麼還是會有問呢 ? 我們由 Tomcat Source Code 來看清楚了?br/>
1 |
// 這一D늢?Tomcat 用來?QueryString 的程式, // ?org.apache.tomcat.util.http.Parameters 這?class ?private String urlDecode(ByteChunk bc, String enc) throws IOException { if( urlDec==null ) { urlDec=new UDecoder(); } urlDec.convert(bc); String result = null; if (enc != null) { bc.setEncoding(enc); result = bc.toString(); } else { CharChunk cc = tmpNameC; cc.allocate(bc.getLength(), -1); // Default encoding: fast conversion byte[] bbuf = bc.getBuffer(); char[] cbuf = cc.getBuffer(); int start = bc.getStart(); for (int i = 0; i < bc.getLength(); i++) { cbuf[i] = (char) (bbuf[i + start] & 0xff); } cc.setChars(cbuf, 0, bc.getLength()); result = cc.toString(); cc.recycle(); } return result; } |
1 |
<Connector debug="0" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" port="80" redirectPort="8443" enableLookups="false" minSpareThreads="25" maxSpareThreads="75" maxThreads="150" maxPostSize="0" URIEncoding="ISO-8859-1" > </Connector> |
分析了一下commons mail的源码找C原因。源码如?
public class SimpleEmail extends Email
{
public Email setMsg(String msg) throws EmailException, MessagingException
{
if (EmailUtils.isEmpty(msg))
{
throw new EmailException("Invalid message supplied");
}
setContent(msg, TEXT_PLAIN);
return this;
}
}
Email代码片段
public void setContent(Object aObject, String aContentType)
{
this.content = aObject;
if (EmailUtils.isEmpty(aContentType))
{
this.contentType = null;
}
else
{
// set the content type
this.contentType = aContentType;
// set the charset if the input was properly formed
String strMarker = "; charset=";
int charsetPos = aContentType.toLowerCase().indexOf(strMarker);
if (charsetPos != -1)
{
// find the next space (after the marker)
charsetPos += strMarker.length();
int intCharsetEnd =
aContentType.toLowerCase().indexOf(" ", charsetPos);
if (intCharsetEnd != -1)
{
this.charset =
aContentType.substring(charsetPos, intCharsetEnd);
}
else
{
this.charset = aContentType.substring(charsetPos);
}
}
}
}
email.send();的sendҎ调?br/>public void buildMimeMessage() throws EmailException
{
try
{
this.getMailSession();
this.message = new MimeMessage(this.session);
if (EmailUtils.isNotEmpty(this.subject))
{
if (EmailUtils.isNotEmpty(this.charset))
{
this.message.setSubject(this.subject, this.charset);
}
else
{
this.message.setSubject(this.subject);
}
}
// ========================================================
// Start of replacement code
if (this.content != null)
{
this.message.setContent(this.content, this.contentType);
}
// end of replacement code
// ========================================================
else if (this.emailBody != null)
{
this.message.setContent(this.emailBody);
}
else
{
this.message.setContent("", Email.TEXT_PLAIN);
}
if (this.fromAddress != null)
{
this.message.setFrom(this.fromAddress);
}
else
{
throw new EmailException("Sender address required");
}
if (this.toList.size() + this.ccList.size() + this.bccList.size() == 0)
{
throw new EmailException(
"At least one receiver address required");
}
if (this.toList.size() > 0)
{
this.message.setRecipients(
Message.RecipientType.TO,
this.toInternetAddressArray(this.toList));
}
if (this.ccList.size() > 0)
{
this.message.setRecipients(
Message.RecipientType.CC,
this.toInternetAddressArray(this.ccList));
}
if (this.bccList.size() > 0)
{
this.message.setRecipients(
Message.RecipientType.BCC,
this.toInternetAddressArray(this.bccList));
}
if (this.replyList.size() > 0)
{
this.message.setReplyTo(
this.toInternetAddressArray(this.replyList));
}
if (this.headers.size() > 0)
{
Iterator iterHeaderKeys = this.headers.keySet().iterator();
while (iterHeaderKeys.hasNext())
{
String name = (String) iterHeaderKeys.next();
String value = (String) headers.get(name);
this.message.addHeader(name, value);
}
}
if (this.message.getSentDate() == null)
{
this.message.setSentDate(getSentDate());
}
if (this.popBeforeSmtp)
{
Store store = session.getStore("pop3");
store.connect(this.popHost, this.popUsername, this.popPassword);
}
}
catch (MessagingException me)
{
throw new EmailException(me);
}
}
׃码可以知道纯文本方式最l调用了Java Mail?br/>message.setContent(this.content, this.contentType);
content是内?br/>contentType是类型,如text/plain,
(我们可以试试直接用Java mail发邮Ӟ讄文本内容不用setTextҎQ也使用setContent("试", "text/plain")方式Q你可以看到内容也是q)
关键在于text/plainQ我们改成text/plain;charset=gb2312Qokq解决了。在commons mail我们看SimpleEmail cMsetMsgҎ调用的就?setContent(msg, TEXT_PLAIN);我们只需要将EmailcM的常量TEXT_PLAIN修改一下加?charset=你的字符?Q重新打包jarQ这样就可以?br/>
import java.util.Date;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class TestMail {
public final static String SMTPSERVER = "smtp.163.com";
public final static String POPSERVER = "pop.163.com";
public final static String ACCOUNT = "test";
public final static String PWD = "test";
public final static String MAILADDR = "test@163.com";
public void sendMail(String to, String from, String subject, String body) throws AddressException, MessagingException {
Properties pro = System.getProperties();
pro.put("mail.smtp.host", SMTPSERVER);
pro.put("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(pro, null);
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
msg.setRecipient(Message.RecipientType.TO, InternetAddress.parse(to, false)[0]);
msg.setSubject(subject);
msg.setText(body);
msg.setHeader("X-Mailer", "LOTONtechEmail");
msg.setSentDate(new Date());
Transport transport = session.getTransport("smtp");
System.out.println("connecting...");
transport.connect(SMTPSERVER, ACCOUNT, PWD);
System.out.println("Sending message");
transport.sendMessage(msg, msg.getAllRecipients());
transport.close();
}
public static void main(String[] args) {
TestMail test = new TestMail();
try {
test.sendMail(MAILADDR, MAILADDR, "test", "我的一个测?);
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
在eclipse下开发基于axis的WebService其实很简单,但也有不步骤,以下Ҏ个步骤进行说?/p>
/**
*
* @author honghao
* @axis.service scope = "Request" urn = "TestService"
*/
public class TestService {
/**
* @param name
* @axis.method
*/
public String test(String name){
return "hello " + name;
}
}
其中@axis.service表示TestService作ؓ服务c,@axis.method表示输出test()Ҏ作ؓWebService
4) 配置xdoclet
打开project->propertiesQ在XDoclet Configurations中添加一个新的配|,可以L取名Q此处ؓ"webservice"Q在q个配置中添加ejbdoclet,在其中再dfileset用于指定对哪些文件执行xdoclet(要指明文件的路径)Q和axisdeployQaxisdeploy不用q行M讄。在ejbdoclet中需要指定destdir生用于指C生成的文g所在的路径?/span>
5) q行xdoclet.叛_目工程Q执行Run Xdoclet菜单Q如果配|没有错误的话,应该在目标\径下生成deploy-TestService.xml,q是一个axis用于生成server-config.wsdd文g的部|文件?br/>q里需要注意的是,如果cL件是攑֜某个包下的时候,我无法生?/span>deploy-TestService.xml文gQ但是将cL件放在根路径下就可以生成了,原因不名.
6) 生成server-config.wsdd部v文g.q个文g其实是由axis的一个工L成的Q但是直接运行这个工具太ȝQ所以我们还需要生成一个ant构徏文gQ其能自动生成Q?br/>在web目的根路径下新建build.xmlQ输入以下文本:
<?xml version="1.0" encoding="UTF-8"?>
<property name="axis_lib_path" value="${axis.lib}"/>
<property name="wsdl.dir" location="wsdl" />
<path id="axis.lib.path">
<fileset dir="${axis_lib_path}">
<include name="*.jar" />
</fileset>
</path>
<path id="project.classpath">
<pathelement location="wsdl"/>
</path>
<target name="deploy">
<java classname="org.apache.axis.utils.Admin" fork="true" dir="WEB-INF"> <!--dir对应生成文g的位|?->
<classpath refid="axis.lib.path" />
<arg value="server" />
<arg value="${wsdl.dir}/deploy-TestHandler.xml" /> <!--TestHandler对应上面的xml文g名TestService-->
</java>
</target>
</project>
注意Qwsdl是刚才生成的deploy-TestService.xml所在的目录,org.apache.axis.utils.Admin是axis提供的工LQ其他\径设|请Ҏ实际目q行适当调整?br/>保存后,叛_build.xml执行Run->Ant 构徏Q如果配|正,则会在WEB-INF目录下生成server-config.wsdd文g
q有ant~译的时候需要axis的lib?br/>
7) 仉Kaxis提供的sample工程在tomcat中进行部|Ԍ在浏览器中输?br/>http://localhost:8080/axis/services
会列出所有的WebService
输入http://localhost:8080/axis/services/TestService?wsdl
会输出相应的wsdl内容
然后可以用相应的工兯行测试了?br/>