#
1、六頂思考帽的概念:
白帽子:信息(陳述事實,數據。客觀情況的陳述)
紅帽子:情緒(情感,感受)
黃帽子:利益(邏輯的積極因素)
黑帽子:謹慎(邏輯的消極因素)
綠帽子:創意(思考創新點子)--頭腦風暴法,隨機詞匯法,概念提取法等等
藍帽子:控制(總恐思考流程)--主持人的角色,要求不帶個人意見,針對思考內容,需要合理及時調整思考者討論問題的方向(所帶帽子)
2、六頂思考帽的實質
思維方式的轉變
對立--平行
辯論--合作
同時討論--依次討論
3、應用場景
a)個人思考問題--可借助freemind工具
b)雙人,多人討論問題
c)團隊會議
。。。。。。。
今天在做項目的時候,遇到這樣一個需求,這個需求也比較常見:
在顯示的一組list版面,當用戶鼠標移動到標題的時候,出現tips提示,里面顯示當前欄一些詳細信息。
難點如下:
1)由于list有多個標題(比如20個),不可能在一個request中,把所有的詳細信息取出來put到頁面上。所以只能通過ajax異步請求的方式取的數據。
2)取詳細信息比較耗性能,需要走一次搜索引擎,走一次數據庫多表查詢進行結果統計。雖然取的過程比較耗服務器性能,但是取的結果集對象是很小的。
3)單條詳細信息load次數只跟個別會員有關,比如,只有a會員的list頁面需要load 標題A的詳細信息,而且當a用戶多次將鼠標移到該標題上,會多次load數據。反觀站點整體訪問中,其他會員幾乎不用load 標題A的信息。所以,把這些詳細信息放到全局cache中,比如memcached中,命中率也會很低。不值得。(放session就更別提了,session不是用來放這些數據的:比如某個集群環境中,是使用session復制的機制;比如session過期,短時間內--甚至比較長的時間內,session依舊存在內存中,等等。。。)
那么如何來解決這個問題呢?
正當想說服需求方放棄這個需求時,出現了一個靈感,可以把數據cache在html頁面上。思路如下:
1、在html頁面上放n個input元素:<input id="list1" type="hidden" value="" />。視為cache對象;
2、首次取詳細信息,通過ajax異步訪問服務端,將得到的數據存放到相應的input元素中,并且在指定的div上顯示詳細信息;
3、之后,取同內容的詳細信息,只要從相應的input元素中取得即可,并顯示在指定的div上。
通過這樣處理,可以避免用戶多次向服務端取相同的信息。當然這樣處理,不能防止惡意用戶的訪問,但是能滿足80%用戶的正常流程,還是值得這么做的。
總結一下,符合這種cache的應用場景:
1)全局cache命中率低
2)取數據過程耗性能,取得的結果集本身非常小。
3)在某種場景下,需要多次重復取數據
如果不滿足其中一條,那么這種cache思路,將毫無價值。
文中所描述的,僅僅是一種cache的實現思路,并不是一種技術。
jstatd
啟動jvm監控服務。它是一個基于rmi的應用,向遠程機器提供本機jvm應用程序的信息。默認端口1099。
實例:jstatd -J-Djava.security.policy=my.policy
my.policy文件需要自己建立,內如如下:
grant codebase "file:$JAVA_HOME/lib/tools.jar" {
permission java.security.AllPermission;
};
這是安全策略文件,因為jdk對jvm做了jaas的安全檢測,所以我們必須設置一些策略,使得jstatd被允許作網絡操作
jps
列出所有的jvm實例
實例:
jps
列出本機所有的jvm實例
jps 192.168.0.77
列出遠程服務器192.168.0.77機器所有的jvm實例,采用rmi協議,默認連接端口為1099
(前提是遠程服務器提供jstatd服務)
輸出內容如下:
jones@jones:~/data/ebook/java/j2se/jdk_gc$ jps
6286 Jps
6174 Jstat
jconsole
一個圖形化界面,可以觀察到java進程的gc,class,內存等信息。雖然比較直觀,但是個人還是比較傾向于使用jstat命令(在最后一部分會對jstat作詳細的介紹)。
jinfo(linux下特有)
觀察運行中的java程序的運行環境參數:參數包括Java System屬性和JVM命令行參數
實例:jinfo 2083
其中2083就是java進程id號,可以用jps得到這個id號。
輸出內容太多了,不在這里一一列舉,大家可以自己嘗試這個命令。
jstack(linux下特有)
可以觀察到jvm中當前所有線程的運行情況和線程當前狀態
jstack 2083
輸出內容如下:
jmap(linux下特有,也是很常用的一個命令)
觀察運行中的jvm物理內存的占用情況。
參數如下:
-heap:打印jvm heap的情況
-histo:打印jvm heap的直方圖。其輸出信息包括類名,對象數量,對象占用大小。
-histo:live :同上,但是只答應存活對象的情況
-permstat:打印permanent generation heap情況
命令使用:
jmap -heap 2083
可以觀察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的內存使用情況
輸出內容:
jmap -histo 2083 | jmap -histo:live 2083
可以觀察heap中所有對象的情況(heap中所有生存的對象的情況)。包括對象數量和所占空間大小。
輸出內容:

寫個腳本,可以很快把占用heap最大的對象找出來,對付內存泄漏特別有效。
jstat
最后要重點介紹下這個命令。
這是jdk命令中比較重要,也是相當實用的一個命令,可以觀察到classloader,compiler,gc相關信息
具體參數如下:
-class:統計class loader行為信息
-compile:統計編譯行為信息
-gc:統計jdk gc時heap信息
-gccapacity:統計不同的generations(不知道怎么翻譯好,包括新生區,老年區,permanent區)相應的heap容量情況
-gccause:統計gc的情況,(同-gcutil)和引起gc的事件
-gcnew:統計gc時,新生代的情況
-gcnewcapacity:統計gc時,新生代heap容量
-gcold:統計gc時,老年區的情況
-gcoldcapacity:統計gc時,老年區heap容量
-gcpermcapacity:統計gc時,permanent區heap容量
-gcutil:統計gc時,heap情況
-printcompilation:不知道干什么的,一直沒用過。
一般比較常用的幾個參數是:
jstat -class 2083 1000 10 (每隔1秒監控一次,一共做10次)
輸出內容含義如下:
Loaded |
Number of classes loaded. |
Bytes |
Number of Kbytes loaded. |
Unloaded |
Number of classes unloaded. |
Bytes |
Number of Kbytes unloaded. |
Time |
Time spent performing class load and unload operations. |
jstat -gc 2083 2000 20(每隔2秒監控一次,共做10)
輸出內容含義如下:
S0C
|
Current survivor space 0 capacity (KB). |
EC
|
Current eden space capacity (KB). |
EU
|
Eden space utilization (KB). |
OC
|
Current old space capacity (KB). |
OU
|
Old space utilization (KB). |
PC
|
Current permanent space capacity (KB). |
PU
|
Permanent space utilization (KB). |
YGC
|
Number of young generation GC Events. |
YGCT
|
Young generation garbage collection time. |
FGC
|
Number of full GC events. |
FGCT
|
Full garbage collection time. |
GCT
|
Total garbage collection time. |
輸出內容:
如果能熟練運用這些命令,尤其是在linux下,那么完全可以代替jprofile等監控工具了,誰讓它收費呢。呵呵。
用命令的好處就是速度快,并且輔助于其他命令,比如grep gawk sed等,可以組裝多種符合自己需求的工具。
截圖工具不常用,但是真到要用的時候,也還得找一個。scrot口碑不錯,網上推薦的文章很多,就選它了。
用了,確實好使,小巧,功能也不弱。
ubuntu下,安然很方便,sudo apt-get install scrot。(當然,我個人還是喜歡編譯源碼的方式安裝。)
介紹下幾個常用的參數。(下面的列表就是通過scrot截圖出來的)

-b:在選擇窗口截圖的時候,選中邊框截圖
-d:延遲n秒后進行截圖
-e:截圖后,執行某個命令
-q:截圖畫面質量,1-00,越高質量好,壓縮就少。默認是75
-s:通過鼠標選擇截圖區域
-t:生成縮略圖,比如50x60,80x20
整體評價,小巧并且功能不弱,完全勝任普遍的一些截圖需求。
effective java中提供了57條建議。針對這些建議,我談談自己的理解。
1.考慮用靜態工廠方法代替構造函數
靜態工廠方式相比于構造函數的兩個優點:
1)可以有符合自己身份的方法名,方便客戶端代碼的閱讀
2)調用的時候,不要求創建一個新的實例??梢苑祷鼐彺鎸嵗?,或者singleton實例等
靜態工廠方法的最大缺點:
如果類中沒有public或者protected的構造函數,使用靜態工廠方法的方式得到實例,那么這個類就無法被繼承。
比如
public class Demo {
private static Demo demo = new Demo();
public static Demo getInstance() {
return demo;
}
private Demo() {
}
}
那么這個類就無法被繼承。
(當然,鼓勵使用組合,而不是繼承)
在spring沒有流行起來的那些日子里,我大量使用工廠方法,但是使用spring等ioc容器后,這一切都是交給容器去處理了?;蛟S,在客戶端代碼中,工廠模式會因為這些ioc的出>現,而遭受淘汰。
2.使用私有構造函數強化singleton屬性
一旦存在public或者protected的構造函數,那么無法保證一個類,一定是sinleton的。因為無法得知客戶端代碼是使用構造函數,還是同構靜態方法去得到類實例。所以對于一個嚴格要求singleton的類,那么其構造函數必須是私有的。
既然說到singleton了,那么順便說下幾個常見的創建方法
1)
/**
* 優點:簡單,而且可以確保一定是singletion實例
* 缺點:類加載時,就會初始化實例,不能做到延遲初始化。
*/
public class Demo {
private static final Demo demo = new Demo();
public static Demo getInstance() {
return demo;
}
private Demo() {
}
}
2)
/**
* 優點:lazy load(延遲初始化實例),提高效率
* 缺點:多線程情況下,可能初始化多份實例
*/
public class Demo {
private static Demo demo = null;
public static Demo getInstance() {
if(demo == null ) {
demo = new Demo();
}
return demo;
}
private Demo() {
}
}
3)
/**
* 優點:lazy load(延遲初始化實例),提高效率
* 采用double check并且同步的方式,理論上確保在多線程的應用場景中,也只創建一份實例
* 備注:(涉及到jvm的實現,在實際應用中,也可能生成多份實例,但是幾率是相當地低)
*/
public class Demo {
private static Demo demo = null;
public static Demo getInstance() {
if(demo == null ) {
synchronized(Demo.class) {
if(demo == null) {
demo = new Demo();
}
}
}
return demo;
}
private Demo() {
}
}
3.使用私有構造函數強化不可實例化能力
咋一看這個標題,覺得不可思議,居然讓類不具備實例化能力。但是確實也有一些應用場景,比如一些util類,就不需要實例化。但是有很大的副作用,就是類無法被繼承。所以換成我,就算是util類,我還是會保留其public的構造函數的。客戶端就算要實例化這些util,也無傷大雅。
4.避免創建重復對象
一般情況下,請重復使用同一個對象,而不是每次需要的時候創建一個功能上等價的新對象。這主要是為了性能上的考慮,何況在一般的應用場景下,確實沒有必要去重復創建對象。當然有時候為了OO設計考慮,也不特別排斥創建重復的小對象。
需要明確的是,避免創建重復的對象,請不要產生一個誤區就是:創建對象的成本非常昂貴。事實上,創建小對象的開銷是非常小的,而且現在的jdk gc對于小對象的GC代價也是非常廉價(在之后的日子里,我會針對sun jdk gc,做一次介紹)。比如在做Swing開發的時候,會創建很多EventListener對象,比如在Spring Framework中,就創建很多匿名內隱類對象實現類似ruby等動態語言的Closure(閉包)。
但是也不可否認的是,創建大對象,對大對象的GC 的開銷是比較大的。比如初始化一個對象的時候,需要加載10m的文件內容到內存;創建數據庫連接對象等等,在這些場景下,創建的開銷是相當昂貴了,一定要盡可能避免重復對象的創建(除非特殊需求)。
對于這些大對象,一般采用singleton模式,cache,或者object pool等方式,避免重復的創建。至于采用具體什么方式,需要根據具體的應用場景來決定了。
5.消除過期對象的引用
為什么要這么做?其實只要理解“java內存泄露”這個概念就可以了。java中的內存泄漏不同于C++中的內存泄漏。C++是需要程序員手工管理內存的語言,創建一個對象,用完之后,需要手工刪除這個對象。而java不一樣,jdk gc替程序員做了這件事情,一旦對象失去了引用之后,jdk gc就會自動回收這個對象。
為了避免java中的內存泄漏,只需要知道一點就可以:對于無用的對象,必須消除對這個對象的引用。
怎么消除對象的引用呢?難道需要手工設置“object=null;”,那么一旦程序中到處充斥著這樣的代碼,將會是一件非常惡心的事情,嚴重影響程序的閱讀性。
正確的做法是,每個定義的變量給予最緊湊的作用域,一旦對象結束生命周期,自然就消除了對其的引用。
當然在必要的場合,也不反對采用清空對象引用的方法,但是不推薦。
內存泄漏的癥狀不能在短時間內反應出來,往往是在程序運行一段時間,一天,一周,一個月,甚至一年,才逐漸顯現的,一個經驗豐富的程序員,也不能確保其代碼一定不存在內存泄漏的問題。檢查內存泄漏問題,往往需要借助工具,heap profile,比如jprofile等等。在linux下面,可以使用jps jstat jinfo jmap等命令去觀察。
最近沒有系統學習的計劃,看了開源的YOYOPlayer(一個相當強大的播放器軟件,基于java編寫),心里癢癢,比較膚淺的學習下javasound。
javasound是比較小巧的底層api,引用網上的一幅 javasound體系結構圖:
javasound實現: 目前使用最多的是 jdk中javax.sound組件 (包括javax.sound.sampled 和 javax.sound.midi包) 和 開源的 Tritonus(http://www.tritonus.org/)組件
SPI:是Service Provider Interface(服務提供接口),它的作用是以插件的形式提供音頻擴展模塊。比如,javax.sound組件中,只支持au,mid,wav等少許音頻格式,其中不包括mp3。要想支持mp3格式,那么就需要相應的解碼器和SPI。所幸的是,已經有相應的開源包。
javazoom(http://www.javazoom.net)下的jlayer,是mp3格式的解碼包。
javazoom下的mp3spi就是spi。
只要添加了相應的開源組建包,可以在不修改任何一行代碼的情況下,支持其他音頻格式。這就是spi的魅力。
簡單介紹了javasound的體系結構,下面就介紹一個簡易的mp3播放器的實現(所謂簡易,就是沒有界面,除了能播放mp3等文件外,就啥都不能干了 :) )
幾個步驟:
1)得到音頻流:
AudioSystem.getAudioInputStream(input)
2)得到音頻格式:
audioInputStream.getFormat()
3)初始化數據行信息
數據行信息包括(受數據行支持的音頻格式;其內部緩沖區的最小和最大大小
)
DataLine.Info info = new DataLine.Info(SourceDataLine.class, decodedFormat);
4)從混頻器獲得源數據行
SourceDataLine
接口提供將音頻數據寫入數據行的緩沖區中的方法。播放或混合音頻的應用程序應該以足夠快的速度將數據寫入源數據行,以防緩沖區下溢(排空),下溢可能導致單擊時音頻數據中出現可感知的間斷
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
5)將音頻數據寫入源數據行中
line.start();
int readLenth = 0;
while (readLenth != -1) {
readLenth = decodedAudioStream.read(AUDIO_BUFER, 0, AUDIO_BUFER.length);
if (readLenth != -1) {
line.write(AUDIO_BUFER, 0, readLenth);
}
}
line.drain();
line.stop();
line.close();
下面提供完整的簡易mp3播放器代碼:
其中
AudioPlayer僅僅是一個接口。
/**
* <pre>
* MP3播放器實現
* 線程不安全,沒有必要多個線程去啟動播放器
* </pre>
*
* @author Lee Jones
*/
public class Mp3Player implements AudioPlayer {
private static final Log log = LogFactory.getLog(Mp3Player.class);
private static final byte[] AUDIO_BUFER = new byte[4096];
private AudioInputStream audioStream;
private AudioFormat decodedFormat;
private AudioInputStream decodedAudioStream;
@Override
public void play(InputStream input) {
if (input == null) {
log.warn("input stream is null");
return;
}
try {
init(input);
play();
} catch (Exception e) {
log.error("play error:", e);
}
}
@Override
public void play(File file) {
if (file == null) {
log.warn("audio file is null");
return;
}
try {
play(new FileInputStream(file));
} catch (FileNotFoundException e) {
log.error("file to inputStream error:", e);
}
}
@Override
public void play(URL url) {
if (url == null) {
log.warn("url is null");
return;
}
try {
play(url.openStream());
} catch (IOException e) {
log.error("url open inputStream error:", e);
}
}
/**
* init
*
* @param input
* @throws UnsupportedAudioFileException
* @throws IOException
*/
protected void init(InputStream input) throws UnsupportedAudioFileException, IOException {
initAudioStream(input);
initDecodedFormat();
initDecodedAudioStream();
}
/**
* init audio input stream
*
* @param input:audio input stream
* @throws IOException
* @throws UnsupportedAudioFileException
*/
protected void initAudioStream(InputStream input) throws UnsupportedAudioFileException, IOException {
audioStream = AudioSystem.getAudioInputStream(input);
}
/**
* init decoded format
*
* @throws UnsupportedAudioFileException
* @throws IOException
*/
protected void initDecodedFormat() throws UnsupportedAudioFileException, IOException {
AudioFormat baseFormat = audioStream.getFormat();
decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,
baseFormat.getChannels(), baseFormat.getChannels() * 2,
baseFormat.getSampleRate(), false);
}
/**
* init decoded audio stream
*/
protected void initDecodedAudioStream() {
decodedAudioStream = AudioSystem.getAudioInputStream(decodedFormat, audioStream);
}
/**
* get source data line
*
* @param input audio input stream
* @return
* @throws UnsupportedAudioFileException
* @throws IOException
* @throws LineUnavailableException
*/
protected SourceDataLine getSourceDataLine() throws UnsupportedAudioFileException, IOException,
LineUnavailableException {
DataLine.Info info = new DataLine.Info(SourceDataLine.class, decodedFormat);
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
line.open(decodedFormat);
return line;
}
/**
* play audio
*
* @throws UnsupportedAudioFileException
* @throws IOException
* @throws LineUnavailableException
*/
protected void play() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
SourceDataLine line = getSourceDataLine();
line.start();
int readLenth = 0;
while (readLenth != -1) {
readLenth = decodedAudioStream.read(AUDIO_BUFER, 0, AUDIO_BUFER.length);
if (readLenth != -1) {
line.write(AUDIO_BUFER, 0, readLenth);
}
}
line.drain();
line.stop();
line.close();
decodedAudioStream.close();
audioStream.close();
}
}
最后附上簡易播放器:
easy mp3 player
啟動方式:linux用戶使用./mp3player.sh,windows用戶使用mp3player.bat啟動(需要說明的是,必須設置好JAVA_HOME和PATH,并且使用jdk5以上版本。因為啟動腳本中的指定classpath的方法需要jdk5版本以上才支持。如果是jdk1.4下的用戶,請修改啟動腳本)
lib目錄:是簡易播放器的lib包支持
log目錄:記錄log,如果有錯誤等情況,可查看log。
conf目錄:因為沒有圖形界面,所以需要把播放的mp3文件路徑手工寫入。支持兩種形式,一個是本地mp3文件,另一個是網絡mp3資源,分別寫入到local.txt和net.txt文件中。
比如
local.txt
/home/jones/data/music/misc/xin_nian_hao.mp3
/home/jones/data/music/misc/guo_ge.mp3
net.txt
http://lubai.com.cn/CGI-BIN/shuanxing.mp3
http://lubai.com.cn/CGI-BIN/shuanxing.mp3
因多媒體方向非自己的工作方向,所以了解的相當膚淺。有興趣的朋友請多多指教。
春節放假,難得有10天放松的機會,欲把本本從開發機稍稍改裝一下,添加上娛樂軟件。
裝上beep-media-player,mplayer+w32codes,好歹本本可以聽聽音樂,看看電影了。
唯可惜,本本上沒有任何資源。
于是乎,想裝上電驢,下載點東東。從網上搜索下,發現linux有幾款工具,amule,Azureus,mldonkey。
amule以前用過,感覺一般,沒什么特色可言。
Azureus是同事推薦,但沒用過,沒有發言權。
mldonkey是網上朋友極力推薦的,最終我選擇mldonkey,原因如下:
1)速度快,據說可以達到帶寬的上限
2)可以同時連接多個server
3)搜索沒有限制,不像windows下的emule,屏蔽了大量的敏感詞。
。。。
更多優點待挖掘中。
貪圖方便的朋友,其實安裝這三款軟件,都比較方便,在ubuntu7.10源中,都有。
sudo apt-get install amule
sudo apt-get install azureus
sudo apt-get install mldonkey-server mldonkey-gui
我個人是比較傾向于編譯源碼安裝的。
mldonkey下載地址:http://mldonkey.sourceforge.net/Main_Page 截至當前,最新版本是
2.9.3
sancho下載地址:http://sancho-gui.sourceforge.net/download.phtml 最新版本
sancho-0.9.4-58-linux-gtk-java.sh
下載mldonkey,解壓,configure(指定安裝路徑),make ,make install。
下載sancho,添加執行權限,執行腳本。
在mldonkey目錄下,執行bin/mlnet
在sancho目錄下,執行sancho命令,進行配置,并且選擇mlnet的安裝路徑。此后,只要運行sacho就可以了,不必要再運行mlnet。
需要明確一個概念:mldonkey是核心,支持
ed2k、bittorrent、http、ftp……等協議。而sancho是基于mldonkey的一個圖形化界面。所以,只要你愿意使用命令,那么不安裝sancho,也無所謂。只不過我也是懶惰的人,所以需要圖形界面。
至此,其實軟件都安裝完成了,只不過還需要一些簡單的配置,
在sancho界面進行連接數和下載速度等的配置
編輯~/.mldonkey/downloads.ini文件,進行下載路徑的配置
(* The directory where temporary files should be put *)
temp_directory = temp
把temp目錄修改成你需要的臨時目錄
{ dirname = "incoming/files"
strategy = incoming_files
priority = 0
};
把incoming/files修改文件輸出路徑
我自己是沒有作這個修改,只是建立了一個軟鏈接
ln -s
~/.mldonkey/incomfing/files ~/tmp/mldonkey 以后只需要關注這個目錄就可以了。
萬事大吉,但是發覺下載速度沒有想象中那么快,稍有遺憾。不過這個軟件還真不錯,值得推薦。
在項目中,一直來是使用spring對java mail的封裝,來發郵件的。雖然spring的封裝已經大大簡化了發送郵件的復雜度,但是今天要介紹下apache commons email組件,對java mail進行了更好的封裝,對于客戶端的調用,已經是相當地方便了。
commons-email maven庫地址:
<dependency>
<groupId>commons-email</groupId>
<artifactId>commons-email</artifactId>
<version>1.1</version>
</dependency>
commons-email實現是相當的簡單,下面介紹下幾個重要的類實現
1)Email
一個抽象類,對java mail進行了封裝,提供主要接口如下
setHostName(String):設置smtp服務器地址
setSmtpPort(int):設置smtp服務器端
setAuthenticator(Authenticator):設置授權帳號和密碼
setSSL(boolean ssl):是否采用ssl方式連接服務
setMailSession(Session):設置與服務器連接session
setCharset(String):設置郵件主體編碼
setFrom(String):設置發件人地址
addTo(String):添加收件人地址
addCc(String):添加抄送人地址
addBcc(String):添加密送人地址
addReplyTo(String):添加回復人地址
setSubject(String):設置郵件標題
setMsg(String):設置郵件主體
send():發送郵件
2)SimpleEmail
繼承Email,實現了setMsg(String msg)方法,發送文本格式郵件,調用非常簡單
SimpleEmail email = new SimpleEmail();
email.setSSL(true);
email.setSmtpPort(SMTP_PORT);
email.setHostName(SMTP_SERVER);
email.setAuthentication(USER_NAME, PASSWORD);
email.addTo("**@**.com");
email.setFrom("**@**.com");
email.setSubject("subject");
email.setCharset("GBK");
email.setMsg("message");
email.send();
3)MultiPartEmail
繼承Email,多了一個添加附件的方法:
attach(URL, String, String)
attach(URL, String, String, String)
attach(DataSource, String, String)
attach(DataSource, String, String, String)
attach(EmailAttachment)
調用方式如下:
MultiPartEmail email = new MultiPartEmail();
email.setSSL(true);
email.setSmtpPort(SMTP_PORT);
email.setHostName(SMTP_SERVER);
email.setAuthentication(USER_NAME, PASSWORD);
email.addTo("**@**.com");
email.setFrom("**@**.com");
email.setSubject("subject");
email.setCharset("GBK");
email.setMsg("message");
email.attach("file:///***.pom.xml", "pom.xml", "pom");
email.send();
4)HtmlEmail
繼承MultiPartEmail,與SimpleEmail相比,多了一個setHtmlMsg(String msg)方法,用戶設置html格式內容,調用方式同SimpleEmail幾乎一致
HtmlEmail email = new HtmlEmail();
email.setSSL(true);
email.setSmtpPort(SMTP_PORT);
email.setHostName(SMTP_SERVER);
email.setAuthentication(USER_NAME, PASSWORD);
email.addTo("**@**.com");
email.setFrom("**@**.com");
email.setSubject("subject");
email.setCharset("GBK");
email.setHtmlMsg("<html><body><b>this is email message!</body></html>");
email.send();
當然,commons email只提供了對smtp協議的封裝,不包括對pop協議的封裝,所以只能發送郵件,不能接受郵件。
在杭州一直使用無限網絡上網,今天回紹興,只能用adsl上網。
adsl上網是采用pppoe協議上網的,幸好ubuntu默認情況下,已經安裝了pppoe程序
如果沒有安裝的用戶,可以使用
sudo apt-get install pppoe pppoeconf
安裝pppoe程序和pppoe配置程序
接下來,使用
sudo pppoeconf
進行上網參數配置,主要是配置adsl上網的帳號和密碼
最后,使用
sudo pon dsl-provider 聯網
sudo poff dsl-provider 斷網
整個過程還是比較方便的。
在本本上編程,老是不小心碰到觸摸板,導致光標亂飛。
以下是禁用觸摸板的方法。
一般情況下,是使用synaptics觸摸板驅動。
最直接的方法,就是卸載synaptics驅動。sudo apt-get autoremove synaptics
但是如果一旦需要使用觸摸板,還要把驅動裝上,太麻煩了。
還有一種比較簡單的方法。
編輯xorg.conf文件:sudo vi /etc/X11/xorg.conf
Section "InputDevice"
Identifier "Synaptics Touchpad"
Driver "synaptics"
Option "SendCoreEvents" "true"
Option "Device" "/dev/psaux"
Option "Protocol" "auto-dev"
Option "HorizEdgeScroll" "0"
Option "SHMConfig" "on"
EndSection
添加 Option "SHMConfig" "on" 這行內容
SHMConfig on 表明開啟觸摸板的參數設置權限
命令:synclient touchpadoff=1 --關閉觸摸板
命令:synclient touchpadoff=0 --開啟觸摸板
自己寫一個關閉觸摸板命令的sh文件,加入到自啟動欄目中,就萬事大吉了。