1. 程式人生 > >ApacheJames 介紹(轉)

ApacheJames 介紹(轉)

這篇文章是介紹ApacheJames郵件企業伺服器的第一部分,也是James的介紹知識。它介紹了使用James開發服務端郵件程式的基礎知識。它概括的介紹了Apache組織設計James目標以及如何安裝配置一個可以執行的工作環境。你還可以瞭解到ApacheJames都提供哪些功能。你還將看到James提供匹配器(matcher)和mailet實現的有關描述,以及它與創通郵件伺服器的不同。
Java Apache郵件伺服器一般是指Apache組織開發的James,它是一個輕便的、安全的100%純Java實現的郵件伺服器。不僅如此James還可以提供更多的功能,感謝James給我們提供了外掛化協議架構和mailet底層構造,它可以讓我們利用web伺服器的servlets處理郵件。Email服務到處都是,開始是DARPA(國防部高階研究計劃局)的一個計劃並最終發展為Internet,但是James成為了打破這一傳統規則的第一個應用。

這篇文章的第一部分首先向我們概要的介紹了James並給出了James開發的高層定位。在第二部分我們將實現一個mailet應用用於處理無效的訊息。你會驚訝的發現用James完成這個應用非常簡單。每天有成千上萬的人在使用Email,所以首先讓我們來看看它是怎麼工作的。

Email是如何工作的
總的來說email是簡單的,你可以使用MUA(郵件使用者代理)向一個或多個地址傳送訊息。MUA有多種表現形式,可以是文字格式的、網頁格式的或者一個GUI應用程式。微軟的outlook和網景的Messenger屬於最後一種。每一個客戶端軟體都可以通過配置向一個MTA(郵件傳輸代理)傳送郵件以及選擇一個MTA來發送郵件訊息到指定的郵件地址。為了完成這些你需要在郵件伺服器上註冊一個帳號,可以使用標準的網路協議,離線Email協議(pop3)或者線上Email協議(IMAP)。這些使用者在客戶端與MTA或MTA之間傳送訊息的協議稱為SMTP(簡單郵件傳輸協議)。
值得注意的是MTA之間到底是如何執行的。郵件伺服器主要依賴於DNS和email規範記錄或者教郵件傳輸(MX)記錄。郵件傳輸記錄於DNS解析URL的記錄略有不同,它還包含一些附加的優先資訊以便更有效的傳送郵件。我不準備對此作更深入的介紹,但是瞭解這一點是很重要的,DNS是成功有效的傳送郵件的關鍵。James是一個MTA,而JavaMail API為MUA提供了一個框架。在這篇文章中我們會用JavaMailAPI建立一個應用,以便測試我們的James,在這篇文章的第二部分我會向你展示如何使用James mailet API建立自己的James應用。

James的設計目標
James被設計為實現幾個確定的目標。比如它完全使用Java開發以便試映最大的輕便行;它提供了很多安全特性用於保護伺服器的執行環境安全還提供了安全服務。James是多執行緒的,它使用了很多Avalon架構提供的功能。
James提供了完善的服務,包括一個完全可以執行的Email伺服器。這些服務主要是有Macther和MailetAPI實現的,這兩個API提供了Email檢查和處理功能。James支援標準的email協議(SMTP,POP3,IMAP),另外還提供了一些附加功能,它使用了鬆散耦合的外掛設計方式使訊息框架從協議中抽象出來。這種設計方式非常有用,你可以把James當作一個通常的訊息伺服器或者為即時訊息傳輸提供支援。
James一個更重要的設計目標是提出了mailet概念,mailet提供了一個開發郵件應用程式的完整生命週期。當然你也可以在這裡使用其他MTA,比如SendMail,要這樣作的話你需要提供一個可呼叫的程式然後將資料傳送給它來完成工作,不過,James提供了一套更簡單、通用的API來完成這些工作。下面讓我們來更進一步的瞭解Matcher和MailetAPI。

James的安裝與配置
James位於Apache站點(你可以在資源中找到它的連線),你應該下載最新的發行版本,寫這篇文章時的最新版本是2.1.2。你可以在James的主頁左邊找到下載連線,然後選擇Download->Binaries,然後選擇2.1發行版本根據你的需要下載james-2.1.2.tar.gz 或 james-2.1.2.zip。
我們還會用到JavaMailAPI來測試我們的應用程式,所以你還需要下載JavaMail。當前的發現版本是1.3檔名為javamail_1_3.zip。在Javamail的主頁上你應該注意到一個JAF的連線,這是JavaMail必須的支援包。JAF的當前版本是1.0.2檔名為jaf-1_0_2.zip,下載了所有這些資源之後你就可以安裝配置你的James了。
我們將把開發所需的所有檔案放到一個目錄中,從產品化的角度來說,這裡的安裝有很大的不同,首先需要考慮安全性和功能性兩個方面。對於我們來說,比如,我們可以在本地執行(localhost),但把它作為一個真正的email伺服器來部署是不夠的。有很多文件介紹如何將James配置為MTA或者結合SendMail使用,而且在一些郵件列表中你也可以找到相關的支援。
當把所有的檔案解壓縮到James目錄中時,我們的檔案結構應該如列表1所示,為了讓整個結構更簡潔清晰,我去掉了一些javadoc文件和src資料夾以及JavaMail webapp的演示資料夾。


James
   +---jaf-1.0.2
   |   +---demo
   |   \---docs
   |       \---javadocs
   +---james-2.1.2
   |   +---apps
   |   +---bin
   |   |   \---lib
   |   +---conf
   |   +---docs
   |   |   +---images
   |   |   \---stylesheets
   |   +---ext
   |   +---lib
   |   +---logs
   \---javamail-1.3
       +---demo
       |   +---client
       |   +---servlet
       |   \---webapp
       +---docs
       |   \---javadocs
       \---lib


這裡假定你已經安裝了JDK1.4,並且有一個獨立的James資料夾。在James的配置宣告中提到James在JDK1.3中會出現問題,所有建議你使用JDK.1.3.1或更高的版本,原則上在JVM1.4下是不會有問題的。
我們首先要作的是啟動James,因為只有執行一次伺服器配置檔案才會被解壓縮。在James的bin目錄下你會看到一個執行教本。當你執行這個教本時你應該看到和下面類似的結果。

Using PHOENIX_HOME:   D:\James\james-2.1.2
Using PHOENIX_TMPDIR: D:\James\james-2.1.2\temp
Using JAVA_HOME:      c:\programming\java14

Phoenix 4.0.1

James 2.1.2
Remote Manager Service started plain:4555
POP3 Service started plain:110
SMTP Service started plain:25
NNTP Service started plain:119
Fetch POP Disabled


你可以通過Ctrl+C的組合鍵關閉應用程式,這時你會得到一個退出的訊息。嚴格講James的關閉路徑是由遠端控制介面來完成的。這裡我使用了Ctrl+C組合鍵的方式,在部署階段你應該使用一個關閉命令來完成。
第一次關閉James之後你會在james-2.1-2/apps/james/SAR-INF路徑下發現一個名為config.xml的檔案,你應該仔細看看這個檔案。你需要注意的第一件事是改變administrator帳號,它預設的被設定為root密碼也是root。你可以不管它,但是在部署為產品時這樣作顯然是不明智的。下一個需要改變的通常是DNS伺服器的地址,如果你要把James部署為一個完全的郵件伺服器這是必須的。你也可以不管它,因為我們可以在localhost下進行開發,但是一定要注意配置DNS是非常重要的。對於我們的開發階段來說預設設定也可以使用,但瞭解這些是非常重要的,更詳細的配置資訊可以檢視james-2.1-2/doc/中的說明。

在開始下非同步之前,需要先增加一些使用者,執行命令 telnet localhost 4555,你可以通過root使用者登入。登入之後我們將增加一個新的使用者,增加使用者的命令是adduser,它接收兩個引數:使用者名稱和密碼。我們將增加red,green,blue三個使用者,每個使用者的密碼和使用者名稱相同(在實際執行中這樣的使用者名稱和密碼當然是不好的,但為了開發簡單這裡就這樣設定了)。增加完使用者之後你可以使用listusers命令來檢視登註冊的使用者最後使用quit來退出控制檯。整個會話過程看起來跟列表3差不多,其中高亮顯示的是使用者鍵入的內容。
JAMES Remote Administration Tool 2.1.2
Please enter your login and password
Login id:
root
Password:
root
Welcome root. HELP for a list of commands
adduser red red
User red added
adduser green green
User green added
adduser blue blue
User blue added
listusers
Existing accounts 3
user: blue
user: green
user: red
quit
Bye


現在James執行伺服器的設定已經完成,如你所見通過遠端控制部署和設定James非常簡單直接。很明顯,如果你希望你的James伺服器更加安全你需要對其引數進行配置,不過這並不麻煩。實際上,使用郵件伺服器的關鍵更多的在於在多使用者和多伺服器的情況下正確的配置DNS。這是今後我們要講到的,不過那也同樣不是什麼負責的過程。
通過JavaMail測試James
為了驗證James,我將快速的開發一個簡單的類,它將模擬標準的email客戶端實現傳送郵件並列出收件箱中內容的功能。我們將開發兩個類,一個類是如列表4所示的,它可以用於測試任何負責的應用,在文章的第二部分當我們開發自己的James應用時還會用到它。

列表4:模擬email客戶端的基本功能。
import java.io.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;

public class MailClient
  extends Authenticator
{
  public static final int SHOW_MESSAGES = 1;
  public static final int CLEAR_MESSAGES = 2;
  public static final int SHOW_AND_CLEAR =
    SHOW_MESSAGES + CLEAR_MESSAGES;
 
  protected String from;
  protected Session session;
  protected PasswordAuthentication authentication;
 
  public MailClient(String user, String host)
  {
    this(user, host, false);
  }
 
  public MailClient(String user, String host, boolean debug)
  {
    from = user + '@' + host;
    authentication = new PasswordAuthentication(user, user);
    Properties props = new Properties();
    props.put("mail.user", user);
    props.put("mail.host", host);
    props.put("mail.debug", debug ? "true" : "false");
    props.put("mail.store.protocol", "pop3");
    props.put("mail.transport.protocol", "smtp");
    session = Session.getInstance(props, this);
  }
 
  public PasswordAuthentication getPasswordAuthentication()
  {
    return authentication;
  }
 
  public void sendMessage(
    String to, String subject, String content)
      throws MessagingException
  {
    System.out.println("SENDING message from " + from + " to " + to);
    System.out.println();
    MimeMessage msg = new MimeMessage(session);
    msg.addRecipients(Message.RecipientType.TO, to);
    msg.setSubject(subject);
    msg.setText(content);
    Transport.send(msg);
  }
 
  public void checkInbox(int mode)
    throws MessagingException, IOException
  {
    if (mode == 0) return;
    boolean show = (mode & SHOW_MESSAGES) > 0;
    boolean clear = (mode & CLEAR_MESSAGES) > 0;
    String action =
      (show ? "Show" : "") +
      (show && clear ? " and " : "") +
      (clear ? "Clear" : "");
    System.out.println(action + " INBOX for " + from);
    Store store = session.getStore();
    store.connect();
    Folder root = store.getDefaultFolder();
    Folder inbox = root.getFolder("inbox");
    inbox.open(Folder.READ_WRITE);
    Message[] msgs = inbox.getMessages();//自己替換[]
    if (msgs.length == 0 && show)
    {
      System.out.println("No messages in inbox");
    }
    for (int i = 0; i < msgs.length; i++)
    {
      MimeMessage msg = (MimeMessage)msgs[i];//自己替換[]
      if (show)
      {
        System.out.println("    From: " + msg.getFrom()[0]);//自己替換[]
        System.out.println(" Subject: " + msg.getSubject());
        System.out.println(" Content: " + msg.getContent());
      }
      if (clear)
      {
        msg.setFlag(Flags.Flag.DELETED, true);
      }
    }
    inbox.close(true);
    store.close();
    System.out.println();
  }
}


MailClient類主要用於傳送郵件並顯示或刪除指定使用者的郵件資訊。我聲明瞭一些有用的常量使我們可以完成SHOW_MESSAGES、CLEAR_MESSAGES等操作。MailClient類還實現了Authenticator介面,這樣在使用者接收郵件的時候可以簡單的控制登入過程。
我建立了兩個建構函式,其中一個設定了JavaMail的除錯標誌。它可以在控制檯打印出客戶端與伺服器之間的互動資訊,這樣你可以對它們的內部執行一目瞭然。另外兩個引數是使用者名稱和主機名稱,這裡假設著可以通過使用者名稱和主機名得到Email地址。我們還建立了一個PasswordAuthentication物件,它可以通過getPasswordAuthentication()方法獲得,這個物件實現了Authenticator介面。
這兩個建構函式通過指定的使用者名稱和主機配置了JavaMail的屬性,並且明確指定了我們要使用的協議。一旦我們獲得了Properties物件,我們就可以呼叫靜態的Session方法getInstance()來獲得一個有效的Session引用,這個引用存在在一個本地變數中。一旦建構函式被呼叫我們就可以向指定的主機發送或接收郵件了。
sendMessage()方法非常簡單,它建立一個包含特定標題和內容的MimeMessage,然後通過JavaMail 的靜態方法 send()把這個訊息傳送到Transport類,為了更容易的看到內部執行情況,我們同樣把它列印到控制檯上。
checkInbox()方法需要完成更多工作,因為它要列出訊息,以便可以任意的刪除這些訊息,它同樣可以在不看訊息的情況下就刪除訊息。實際上要獲得這些消耗,我們需要獲得儲存在會話中的物件,連線到伺服器然後開啟收件箱資料夾。
現在我們有了可以重用的MailClient類,我們可以準備開始測試本機上的James伺服器了。列表5中的JamesConfigTest類建立了3個MailClient例項,每個對於一個我們已經建立的使用者(red,green,blue)。在執行這個測試之前必須保證這3個使用者已經在郵件伺服器上建立好了。

列表5:測試郵件伺服器的類JamesConfigTest
public class JamesConfigTest
{
  public static void main(String[] args)//自己替換[]
    throws Exception
  {
    // CREATE CLIENT INSTANCES
    MailClient redClient = new MailClient("red", "localhost");
    MailClient greenClient = new MailClient("green", "localhost");
    MailClient blueClient = new MailClient("blue", "localhost");
   
    // CLEAR EVERYBODY'S INBOX
    redClient.checkInbox(MailClient.CLEAR_MESSAGES);
    greenClient.checkInbox(MailClient.CLEAR_MESSAGES);
    blueClient.checkInbox(MailClient.CLEAR_MESSAGES);
    Thread.sleep(500); // Let the server catch up
   
    // SEND A COUPLE OF MESSAGES TO BLUE (FROM RED AND GREEN)
    redClient.sendMessage(
      "[email protected]",
      "Testing blue from red",
      "This is a test message");
    greenClient.sendMessage(
      "[email protected]",
      "Testing blue from green",
      "This is a test message");
    Thread.sleep(500); // Let the server catch up
   
    // LIST MESSAGES FOR BLUE (EXPECT MESSAGES FROM RED AND GREEN)
    blueClient.checkInbox(MailClient.SHOW_AND_CLEAR);
  }
}

建立MailClient例項之後,JamesConfigTest通過CLEAR_MESSAGES模式使用checkInbox() 方法清除了每一個郵箱,之後等待半分鐘以確保郵件伺服器刪除了資訊。之後我們會從red和green給blue傳送一封郵件,並通過blue帳號檢測這個郵件。當你執行JamesConfigTest時,你應該看到類似列表6的輸出資訊。
Clear INBOX for [email protected]

Clear INBOX for [email protected]

Clear INBOX for [email protected]

SENDING message from [email protected] to [email protected]

SENDING message from [email protected] to [email protected]

Show and Clear INBOX for [email protected]
    From: [email protected]
Subject: Testing blue from green
Content: This is a test message

    From: [email protected]
Subject: Testing blue from red
Content: This is a test message


這表明我們的James伺服器配置的沒有問題,在進一步開發之前你要確保你的環境配置沒有問題。在開始第二部分之前我們不會再對此進一步描述,不過在文章的剩餘部分我們會講講Matcher 和 Mailet APIs以及前面提到的它在James中發揮的作用,我們還會大概的講講James提供的附加功能。
Matchers
James提供了很多標準的匹配器,每一個都實現了Matcher API如列表7所示,它提供了標準的退出MTA的功能,以及其他一些有用的擴充套件。這個介面非常簡單,它包含了一系列有關生命週期的方法,init() 和 destroy()還有一對簿記方法:getMatcherInfo() 和 getMatcherConfig(),以及main方法,match()方法,整個方法用於操作Mail物件。Mail例項提供了訪問容器狀態、郵件訊息和元資料的過程。

列表7:Matcher介面
public interface Matcher
{
  void init(MatcherConfig config);
  void destroy();
  String getMatcherInfo();
  MatcherConfig getMatcherConfig();
  Collection match(Mail mail);
}


一個Matcher負責解析一系列的收件人資訊,並返回一個字串物件集合,整個集合包含了由mailet處理的收集人資訊。結合Matcher的解析功能和mailet的處理功能你可以開發一個負責的應用來處理一個郵件資訊。
James的matcher提供的部分功能可以幫你完成很多事情,你不必開發自己的Matcher。如果你要開發自己的Matcher有幾件事情是非常重要的,在很多情況下你需要的功能已經實現了,下面是對此的描述:
Matcher 描述
All 匹配所有的email被處理並且返回所有的收件人。
HasHeader 匹配一個指定的header。
HasAttachment 如果資訊由多個部分。
SubjectStartsWith 資訊的主題以特定的文字開頭。
SubjectIs 資訊有一個特定的主題。
HostIs 資訊來自一個特定的主機。
HostIsLocal 資訊來自 localhost
UserIs 資訊來自一個特定的使用者
SenderIs 來自一個特定的發件人。
SenderInFakeDomain 匹配主機地址無法解析的發件人。
SizeGreaterThan 匹配資訊容量超出指定範圍的。
Recipients 匹配收件人的資訊來自一個指定的列表
RecipientsLocal 匹配本地收件人的資訊。
IsSingleRecipient 匹配只有收件人資訊的資訊。
RemoteAddrInNetwork 匹配資訊來自特定的IP列表或域的。
RemoteAddrNotInNetwork 匹配資訊不是來自特定的IP列表或域的。
RelayLimit 匹配資訊通過指定數量伺服器傳送而來的。
InSpammerBlackList 匹配資訊來自mail-abuse.org
NESSpamCheck 匹配從Netscape Mail Server來的垃圾資訊。
HasHabeasWarrantMark Matches mail with a Habeas Warrant
FetchedFrom Matches the X-fetched-from header used by FetchPOP
CommandForListserv 匹配來自已經列出的伺服器中的命令。
如你所見,你可以完成很多匹配操作而無需自己重寫,從最簡單的匹配header主題等到高階內容比如匹配是否為來自列表伺服器的命令。
Mailets
James的很多功能都是通過實現Mailet API(列表8)實現的,對於使用Servlet開發的人來說這段程式碼很眼熟。和Matcher API一樣Mailet提供了兩個生命週期方法init ()和destroy(),二個附加方法用於返回資訊,第一個是getMailetInfo()方法,它返回一個字串物件,這個字串包含有關mailet 的作者,版本號, 和 版權等資訊。第二個getMailetConfig()方法返回了當前Mailet的配置資訊。Init()方法有一個MailetConfig引數,它可以通過getMailetConfig()獲得。
列表8:Mailet介面
public interface Mailet
{
  void init(MailetConfig config);
  void destroy();
  String getMailetInfo();
  MailetConfig getMailetConfig();
  void service(Mail mail);
}



主要的操作在services()方法中,它有一個Mail物件引數。這個物件提供了訪問容器狀態、郵件訊息和元資料的過程。
James已經實現了很多Mailet應用如下表所示:
Mailet 描述
Null 結束email訊息的處理。
AddHeader 給資訊加一個文字頁首。
AddFooter 給資訊加一個文字頁尾。
Forward 將資訊發給一組收件人。
Redirect 提供可配置的轉發服務。
ToProcessor 將email轉發到指定的處理器。
ToRepository 將資訊的拷貝放到指定的目錄中。
NotifySender 將資訊作為附件傳送給最初的發件人。
NotifyPostmaster 將資訊作為附件傳送給管理員。
RemoteDelivery 控制 SMTP 主機的傳送。
LocalDelivery 將資訊傳送到本地的郵箱中。
JDBCAlias 使用JDBC 資料來源進行別名翻譯。
JDBCVirtualUserTable 使用JDBC 資料來源進行更負責的別名翻譯。
UseHeaderRecipient 從訊息頭中重建收件人。
ServerTime 傳送一個伺服器時間戳資訊。
PostmasterAlias 通過[email protected]<domain>把資訊轉發給到一個特定的地址。
AddHabeasWarrantMark Adds a Habeas Warrant mark to the message
AvalonListserv 提供基本的列表伺服器的功能。
AvalonListservManager 傳輸列表伺服器控制命令。
如你所見,很多功能已經有James的Mailet實現了,包括複雜的列表伺服器支援、別名、儲存和路由等功能。
附加功能
James提供的很多功能已經超出了本文的範圍,但是這裡我還是簡單的說一下,以便你可以瞭解James的強大。首先是它對NNTP的支援,這可以是James作為一個新聞伺服器。James還實現了FetchPOP協議來支援以郵件為基礎的遠端控制特性。RemoteManager和SpoolManager提供了一個抽象,它允許多種儲存型別和目前支援的控制。對於開發而言,它主要依賴與以檔案為基礎的SpoolManager,比如對於部分或完全以資料庫為中心的方案也是支援的。
James提供的介面和服務允許使用者別有效的控制,對郵件列表也提供了有效的支援。實際上郵件列表是James提供的主要功能之一,也是大多數管理員選擇James作為郵件伺服器的原因。

接下來是什麼?
James的底層被設計為平滑的易於開發的。Email應用程式也許限制了你的想像空間。在文章的後半部分,我們將開發一個簡單的應用程式,它允許使用者把郵件傳送到指定的James地址。使用者可以先草擬一個郵件它將發給收件人,直到使用者給其他特定使用者發出一個取消的資訊來關閉它。它模擬了通常由郵件客戶端實現的功能,不過它存在地理位置的限制。因為,一旦你關閉了郵件客戶端,這些功能將不作工作。對於目前在郵件伺服器上實現這些功能,我們仍然可以從一個地方檢查我們的郵件,如果我們的計劃改變我們可以簡單的修改“away”資訊來作適當的回覆。

相關推薦

ApacheJames 介紹

這篇文章是介紹ApacheJames郵件企業伺服器的第一部分,也是James的介紹知識。它介紹了使用James開發服務端郵件程式的基礎知識。它概括的介紹了Apache組織設計James目標以及如何安裝配置一個可以執行的工作環境。你還可以瞭解到ApacheJames都提供哪些功能。你還將看到James提供匹配器

局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介紹

false 這樣的 rds 場景 創建 大量 net bsp 好處 局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介紹 本文主要介紹一種用於海量高維數據的近似最近鄰快速查找技術——局部敏感哈希(Locality-Sensitive Has

Oracle數據庫測試和優化最佳實踐: OTest介紹

1-1 log 數據 bsp 下載 pan alt style 發送 當前Oracle數據庫最佳測試工具OTest * Otest是用於Oracle數據庫測試、優化、監控軟件。 * Otest是免費提供給Oracle客戶和廣大DBA工程師使用的軟件。由原廠技

Java靜態檢測工具/Java代碼規範和質量檢查簡單介紹

pub 詳細 職責 web 循環 問題: 集成 死鎖 參考 靜態檢查: 靜態測試包括代碼檢查、靜態結構分析、代碼質量度量等。它可以由人工進行,充分發揮人的邏輯思維優勢,也可以借助軟件工具自動進行。代碼檢查代碼檢查包括代碼走查、桌面檢查、代碼審查等,主要檢查代碼和設計的一致

Flume架構以及應用介紹

exe 安全 ipc sele 可靠性 代理 詳細 倉庫 bug 在具體介紹本文內容之前,先給大家看一下Hadoop業務的整體開發流程: 從Hadoop的業務開發流程圖中可以看出,在大數據的業務處理過程中,對於數據的采集是十分重要的一步,也是不可避免的一步

執行緒安全的集合類、CopyOnWrite機制介紹

看過併發程式設計的書,這兩種機制都有所瞭解,但不紮實其實。看到別人的部落格描述的很精闢,於是轉過來,感謝! 原文連結:https://blog.csdn.net/yen_csdn/article/details/51705687   inkedList、ArrayList、HashSet是非

JQuery入門介紹

1、JQuery概述:Jquery是繼prototype之後又一個優秀的Javascrīpt框架。它是輕量級的js庫(壓縮後只有21k) ,它相容CSS3,還相容各種瀏覽器(IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+)。jQuery使使用者能更方便地處理HTML doc

C檔案讀寫函式介紹

1.    首先要理解幾個概念: 檔案: 按一定規則儲存在磁碟上的資料集合。 檔名: 能唯一標識某個磁碟檔案的字串。形式: 碟符:/ 路徑 / 檔名.副檔名 文字檔案:: 資料以其數字字元的ASCII碼形式、一個位元組一個位元組地儲存在磁碟上。 二進位制檔案:資料以二進位制形式在儲存在磁碟上。 裝置檔案:輸入

有贊.測試團隊介紹

轉載自:友贊技術團隊主頁 轉載原因:學習、借鑑先進生產力 一、基本概況        有贊,旨在為商戶提供強大的微商城和完整的移動零售解決方案,是一個移動零售服務商,正在新零售的潮流中激流勇進、開疆拓土,用產品技術撬動巨大的市場。有贊擁有世界級的 Saa

MS SQL SERVER 中merge join合併連線介紹

1概述Merge join 合併連線。兩個集合進行merge join,需要有一個等值的條件,然後需要兩個已排序好的集合。2 one-to-many與many-to-many 2.1 One-to-many 當參與merge join的兩個集合中,其中一個集合在等值條件上是

vim note(6)--vim的一個較全的介紹

vim的配置檔案  ~/.vimrc        使用者的預設配置檔案   ~/.vim/plugin/   使用者的預設指令碼檔案的存放目錄   ~/.vim/ftplugin/ 使用者的預設檔案型別相關指令碼檔案的存放目錄 vim提供的程式設計支援文字資訊(行號、檔名

python httplib2與urllib2包的介紹

剛剛發現了一個比urllib2更好用的庫httplib2,可以比較簡單的解決本文遇到的一些問題http://code.google.com/p/httplib2/————————————————————最近用urllib2寫了一個公司內部用的指令碼這個指令碼要訪問一個webs

Android intent.Action 引數值及對應功能介紹

4 Intent.Action.ALL_APPS String: andriod.intent.action.ALL_APPS 列出所有的應用。 Input:Nothing. Output:Nothing. 5 Intent.ACTION_ANSWER Stirng:android.intent.action

cronExpression介紹

一個Cron-表示式是一個由六至七個欄位組成由空格分隔的字串,其中6個欄位是必須的而一個是可選的,如下:欄位名 允許的值 允許的特殊字元 秒 0-59 , - * / 分 0-59 , - * / 小時 0-23 , - * / 日 1-31 , - *

SQL 索引 include 介紹

5.3.1 使用索引INCLUDE在這個技巧中,將展示如何在非聚集索引中包含非鍵列。覆蓋查詢(covering query)是指其引用的所有列均能在非聚集索引中找到的查詢。這個方案經常會帶來出眾的查詢效能,因為SQL Server不需要從聚集索引或堆中檢索實際的資料--它只需

AndroidManifest中Application、Activity、Service屬性介紹

一. application 標籤屬性 <application/> 應用的宣告。 該節點必須包含在android <manifest/>節點中。 而<application/>節點包含了<activity/>

消息隊列使用的四種場景介紹

rom 第三方 des soc 有一個 repl 訪問 都是 storm集群 消息隊列中間件是分布式系統中重要的組件,主要解決應用耦合,異步消息,流量削鋒等問題 實現高性能,高可用,可伸縮和最終一致性架構 使用較多的消息隊列有ActiveMQ,RabbitMQ,ZeroM

IPsec技術介紹

IPsec IPsec簡介 IPsec(IP Security)是IETF制定的三層隧道加密協議,它為Internet上傳輸的資料提供了高質量的、可互操作的、基於密碼學的安全保證。特定的通訊方之間在IP層通過加密與資料來源認證等方式,提供了以下的安全服務: l              資料機密性(Conf

Scala中協變(+)、逆變(-)、上界(<:)、下界(>:)簡單介紹

定義類 word ref 一個 pla 而不是 關系 repl 協變 看源碼的時候看到: trait ExtensionId[T <: Extension] {沒見過這個符號啊<: Scala上界(<:)和下界(>:) 1) U >: T

Android開發書籍推薦:從入門到精通系列學習路線書籍介紹

成長 程序員 理論 targe base 官方 app als 自己的 Android開發書籍推薦:從入門到精通系列學習路線書籍介紹 轉自:http://blog.csdn.net/findsafety/article/details/52317506 很多時候我們都會