#
import java.util.Properties;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class SendMail implements Runnable {
private final String smtp_host = "smtp.gmail.com";
private final String from_userName = "xx@gmail.com";
private final String from_passWord = "xx";
private final String show_name = "xxx";
public String email_address;
public String email_subject;
public String email_content;
public SendMail(String email_address, String email_subject, String email_content) {
this.email_address = email_address;
this.email_subject = email_subject;
this.email_content = email_content;
}
public void run() {
executeMailSend(email_address, email_subject, email_content);
}
/**
*
* @param recipients: the mail send to
* @param sendSubject: the mail subject
* @param sendText: the mail content
*/
public void executeMailSend(String recipients, String sendSubject, String sendText) {
try {
Properties props = System.getProperties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", smtp_host);
props.put("mail.smtp.user", from_userName);
props.put("mail.smtp.password", from_passWord);
props.put("mail.smtp.port", "587"); //gmail smtp port 587
props.put("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(props, null);
session.setDebug(false);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from_userName));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
message.setFrom(new InternetAddress(show_name + "<" + from_userName + ">"));
message.setSubject(sendSubject);
message.setContent(sendText, "text/html;charset=utf-8");
Transport transport = session.getTransport("smtp");
transport.connect(smtp_host, from_userName, from_passWord);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
System.out.println("send an email to " + recipients + " success");
} catch (Exception e) {
e.printStackTrace();
System.out.println("failure! ");
}
}
public static void main (String args[]){
new SendMail("yy@gmail.com","test","hehe").run();
}
}
結(jié)果老是報如下的錯誤
javax.mail.MessagingException: 530 5.7.0 Must issue a STARTTLS command first. 36sm443504yxh.67
failure!
at com.sun.mail.smtp.SMTPTransport.issueCommand(SMTPTransport.java:1020)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:716)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:388)
at SendMail.executeMailSend(SendMail.java:59)
at SendMail.run(SendMail.java:25)
at SendMail.main(SendMail.java:70)
折騰了個把小時,苦苦尋求后發(fā)現(xiàn)一個解決辦法
props.put("mail.smtp.port", "587");
替換成props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.port", "465");
props.setProperty("mail.smtp.socketFactory.port", "465");
究其原因也不太清楚,網(wǎng)上有資料說port 587也可以,不知結(jié)果不行
把上述代碼中的
1.從Object到String
要先用Object對象構(gòu)造一個JSONObject或者JSONArray對象,然后調(diào)用它的toString()方法即可
(1)示例一
1 Book book=new Book();
2 book.setName("Java");
3 book.setPrice(52.3f);
4 JSONObject object=JSONObject.fromObject(book);
5 System.out.println(object.toString());
(2)示例二
1 Book book=new Book();
2 book.setName("Java");
3 book.setPrice(52.3f);
4
5 Book book2=new Book();
6 book2.setName("C");
7 book2.setPrice(42.3f);
8 List list=new ArrayList();
9 list.add(book);
10 list.add(book2);
11 JSONArray arry=JSONArray.fromObject(list);
12 System.out.println(arry.toString());
13 //結(jié)果如下:
14 [{"name":"Java","price":52.3},{"name":"C","price":42.3}]
2.從String到Object
要先用String對象構(gòu)造一個JSONObject或者JSONArray對象
(1)示例一
1 String json="{name:'Java',price:52.3}";
2 JSONObject object=JSONObject.fromObject(json);
3 System.out.println(object.get("name")+" "+object.get("price"));
(2)示例二
1 String json="[{name:'Java',price:52.3},{name:'C',price:42.3}]";
2 JSONArray array=JSONArray.fromObject(json);
3 for(int i=0;i<array.size();i++){
4 Map o=(Map)array.get(i);
5 System.out.println(o.get("name")+" "+o.get("price"));
6 }
3.從String到Bean
(1)單個Bean對象
1 String json="{name:'Java',price:52.3}";
2 JSONObject object=JSONObject.fromObject(json);
3 Product product=(Product)JSONObject.toBean(object,Product.class);
4 System.out.println(product.getName()+" "+product.getPrice());
(2).Bean的數(shù)組
1 String json="[{name:'Java',price:52.3},{name:'C',price:42.3}]";
2 JSONArray array=JSONArray.fromObject(json);
3 Product[] products=(Product[]) JSONArray.toArray(array,Product.class);
4 for(Product p:products){
5 System.out.println(p.getName()+" "+p.getPrice());
6 }
自定義封裝JSON操作的類

1 package com.util;
2
3 import java.util.List;
4 import java.util.Map;
5
6 import net.sf.json.JSONArray;
7 import net.sf.json.JSONObject;
8
9 public class JsonHelper {
10 //從普通的Bean轉(zhuǎn)換為字符串
11 public static String getJson(Object o){
12 JSONObject jo=JSONObject.fromObject(o);
13 return jo.toString();
14 }
15 //從Java的列表轉(zhuǎn)換為字符串
16 public static String getJson(List list){
17 JSONArray ja=JSONArray.fromObject(list);
18 return ja.toString();
19 }
20 //從Java對象數(shù)組轉(zhuǎn)換為字符串
21 public static String getJson(Object[] arry){
22 JSONArray ja=JSONArray.fromObject(arry);
23 return ja.toString();
24 }
25 //從json格式的字符串轉(zhuǎn)換為Map對象
26 public static Map getObject(String s){
27 return JSONObject.fromObject(s);
28 }
29 //從json格式的字符串轉(zhuǎn)換為List數(shù)組
30 public static List getArray(String s){
31 return JSONArray.fromObject(s);
32 }
33 //從json格式的字符串轉(zhuǎn)換為某個Bean
34 public static Object getObject(String s,Class cls){
35 JSONObject jo=JSONObject.fromObject(s);
36 return JSONObject.toBean(jo, cls);
37 }
38 //從json格式的字符串轉(zhuǎn)換為某類對象的數(shù)組
39 public static Object getArray(String s,Class cls){
40 JSONArray ja=JSONArray.fromObject(s);
41 return JSONArray.toArray(ja, cls);
42 }
43 }
摘要: 第一、Logger.getLogger()和LogFactory.getLog()的區(qū)別 1.Logger.getLogger()是使用log4j的方式記錄日志; 2.LogFactory.getLog()則來自apache的common-logging包。common-logging組件: &n...
閱讀全文
懂行的人都知道,log4j日志是個很基礎(chǔ)的東東,與struts這種高層框架無關(guān),只與web開發(fā)了的tomcat有關(guān)。這里之所以寫出struts,是因為筆者一開始用struts的時候,以為是這樣,也是這樣google的。好了,言歸正傳,開工了
給tomcat配置log4j有好幾種方法,我知道的有:
一、tomcat級別的統(tǒng)一日志管理(沒有實際驗證過,只是查了資料):
在tomcat的common/lib下增加log4j的.jar包,以便程序使用的時候,能夠加載到。
在自己的webapps的WEB-INF/classes下添加log4j.properties配置,所有的東西都是自動的
這種方式的缺點(diǎn)很明顯,一個tomcat可能會多個子webapps,都統(tǒng)一到一個日志下,非常不便于管理。所以重點(diǎn)看下面
二、每個webapp分別配置log4j(切實可行的實踐經(jīng)驗)
1、在自己youapp的WEB-INF/lib下增加log4j-xxx.jar文件
2、自己寫一個servlet,初始化log4j的相關(guān)配置信息:
Java代碼
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import org.apache.log4j.PropertyConfigurator;
public class Log4jInitServlet extends HttpServlet {
public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
}
public void init() throws ServletException {
System.setProperty("webappRoot", getServletContext().getRealPath("/"));
PropertyConfigurator.configure(getServletContext().getRealPath("/") + getInitParameter("configfile"));
}
}
3、修改web.xml文件,讓tomcat啟動你app的時候自動加載剛才這個servlet:
Xml代碼
<!-- initialize log4j -->
<servlet>
<servlet-name>log4j config file</servlet-name>
<servlet-class>com.keepc.util.Log4jInitServlet</servlet-class>
<init-param>
<param-name>configfile</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
4、在youapp/WEB-INF/classes先新建log4j.properties文件,內(nèi)容如下:
log4j.rootLogger=debug, A1
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.file=${webappRoot}/logs/youapp_log-
log4j.appender.A1.DatePattern=yyyy-MM-dd'.log'
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss, SSS}[%c]-[%p] %m%n
5、重新啟動tomcat,即可在你的youapp應(yīng)用目錄下看到logs目錄和對應(yīng)的log文件
#:這里說道的webapp目錄是指:c:\program files\tomcat\webapps\youapp目錄
6、在你的app目錄下創(chuàng)建一個jsp做下測試:
Html代碼
<%@ page contentType="text/html; charset=GBK" language="java" import="org.apache.log4j.Logger,java.util.*"%>
<html>
<head>
<link href="style/reg.css" rel="stylesheet" type="text/css">
<title>測試頁面</title>
</head>
<body>
<%
Logger log = Logger.getLogger("test.jsp");
log.debug("測試日志,哈哈");
%>
</body>
</html>
在你的瀏覽器調(diào)用下這個jsp,就可以看到日志內(nèi)容了。
本方法在windows和linux下都通用,完全一樣。
只與log4j.properties的詳細(xì)配置方法,網(wǎng)上隨便google下都有一籮筐,照抄就是了。
一: SVN包括:服務(wù)器端(Subversion)和客服端(TortoiseSVN),安裝時,建議先安裝服務(wù)器端,再安裝客服端(因為安裝完客服端后需要重啟電腦)。
二:安裝完成后,創(chuàng)建服務(wù)器版本庫:創(chuàng)建一個文件夾(比如:D:\\svnserver),然后右鍵:TortoiseSVN ----> create respository here,然后在該目錄下生成六個文件(conf文件 夾、 db文件夾、hooks文件夾、locks文件夾、format文件和README.txt),其中配置文件在conf文件夾中。 其中conf文件夾下包含三個文件:authz(配置用戶權(quán)限:讀,寫權(quán)限 等 等)、
passwd(配置用戶名和密碼)和svnserve.conf(svn的核心配置)。
其中:
1: passwd配置:在該文件中,創(chuàng)建用戶的方式為:
用戶名 = 密碼 ,例如:創(chuàng)建用戶名為:admin,密碼為abcd,即為:admin = abcd
2: svnserve.conf配置:開啟
用戶訪問的功能:即只需開啟:
password-db = passwd 即可,具體操作:把password-db = passwd 前面的#去除即可。否則其他用戶不能訪問。
開啟
用戶權(quán)限的功能:即只需開啟:
authz-db = authz 即可,具體操作:把a(bǔ)uthz-db = authz 前面的#去除即可。否則配置的用戶權(quán)限將不生效。
3:authz 配置:找到該文件的 [groups] :在下一行:有兩種方式配置權(quán)限:
(1):
權(quán)限名稱 = 用戶名 ,然后在相應(yīng)的目錄: 權(quán)限名稱 = 權(quán)限(比如:rw)例如:
[groups] -- 給權(quán)限分組,有利于多個用戶批量分配權(quán)限。
adm = admin -- adm 為組權(quán)限名稱,類似常說的“角色”,admin為用戶名,= 前后最后加上一個空格。
[/] -- / 表示svn服務(wù)器的跟目錄下,當(dāng)然也可以用其他的目錄。比如:[/a/b/] 表示為/a/b/ 目錄下分配目錄權(quán)限 @adm = rw -- @表示組, adm表示組名,r表示只讀,即下載功能;r表示只寫,即上傳功能。
(2):
直接在相應(yīng)的目錄下:用戶名 = 權(quán)限(比如:rw) 例如:
admin = rw -- admin 為用戶名,rw表示讀寫權(quán)限。 如果 svnserve.conf 的
authz-db = authz 不開啟。則權(quán)限分配則無效。當(dāng)然這樣用戶也是可以上傳和下載的。


三:開啟SVN服務(wù):
(1):臨時開啟,在dos界面中輸入: svnserver -d -r + svn服務(wù)器版本庫目錄 例如:svn版本庫目錄為:D:\\svnserver ,即為:
svnserver -d -r D:\\svnserver
-- 注意:-d, -r ,svn服務(wù)器版本庫目錄中間需要用空格隔開。而一旦關(guān)閉dos界面是,svn服務(wù)器也隨之關(guān)閉。 (2):永久開啟:即電腦啟動時自動開啟svn服務(wù)器。這樣需要把svn創(chuàng)建一個服務(wù),然后把該服務(wù)器設(shè)置為自動啟動即可。具體操作:
(i) : 創(chuàng)建服務(wù):在dos界面中輸入:
sc create svnserver binpath= svnserve.exe目錄 --service --root svn版本庫目錄 --
注意:=與svnserve.exe之間必須要加一個空格 例如svn服務(wù)器安裝在:D:\J2EE\SVN\Subversion目錄下
則為:
sc create svnserver binpath= "D:\J2EE\SVN\Subversion\bin\svnserve.exe --service --root D:\\svnserver" -- 雙引號不可缺少 然后:如果創(chuàng)建服務(wù)沒有問題,則輸入:services.msc 到電腦服務(wù)列表中會找到一個:svnserve服務(wù)。如果創(chuàng)建svn服務(wù)失敗,則無法找到svnserve服務(wù)。
如果創(chuàng)建svn服務(wù)出現(xiàn)了問題,還可以刪除svn服務(wù)。具體如: sc delete 服務(wù)名 例如: sc delete svnserver
(ii)把svnserve服務(wù)設(shè)置為自動啟動。以后電腦啟動時即啟動svn服務(wù)器。
四: 這樣svn服務(wù)器就配置好了。然后就可以在svn客服端進(jìn)行各種操作了。
順便說一下:
創(chuàng)建服務(wù):sc create 服務(wù)名 binpath= 程序啟動的位置 --service --root
-- 程序啟動位置即:該軟件啟動的那個文件的位置(如:d:\xx\xxx\xxxx.exe) 刪除服務(wù):sc delete 服務(wù)名
<%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %><%!Color getRandColor(int fc,int bc){//給定范圍獲得隨機(jī)顏色 Random random = new Random(); if(fc>255) fc=255; if(bc>255) bc=255; int r=fc+random.nextInt(bc-fc); int g=fc+random.nextInt(bc-fc); int b=fc+random.nextInt(bc-fc); return new Color(r,g,b); }%><%//設(shè)置頁面不緩存response.setHeader("Pragma","No-cache");response.setHeader("Cache-Control","no-cache");response.setDateHeader("Expires", 0);// 在內(nèi)存中創(chuàng)建圖象int width=60, height=20;BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 獲取圖形上下文Graphics g = image.getGraphics();//生成隨機(jī)類Random random = new Random();// 設(shè)定背景色g.setColor(getRandColor(200,250));g.fillRect(0, 0, width, height);//設(shè)定字體g.setFont(new Font("Times New Roman",Font.PLAIN,18));// 隨機(jī)產(chǎn)生155條干擾線,使圖象中的認(rèn)證碼不易被其它程序探測到g.setColor(getRandColor(160,200));for (int i=0;i<155;i++){ int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x,y,x+xl,y+yl);}// 取隨機(jī)產(chǎn)生的認(rèn)證碼(4位數(shù)字)String codeList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";String sRand="";for (int i=0;i<4;i++){int a=random.nextInt(codeList.length()-1); String rand=codeList.substring(a,a+1); sRand+=rand; // 將認(rèn)證碼顯示到圖象中 g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));//調(diào)用函數(shù)出來的顏色相同,可能是因為種子太接近,所以只能直接生成 g.drawString(rand,13*i+6,16);}// 將認(rèn)證碼存入SESSIONsession.setAttribute("rand",sRand);// 圖象生效g.dispose();// 輸出圖象到頁面ImageIO.write(image, "JPEG", response.getOutputStream());out.clear();out = pageContext.pushBody();%>
背景:因為想寫一個測試tomcat連接的程序,就試試自已去構(gòu)造Http請求。找了一下發(fā)現(xiàn)Apache下有一個比較成熟的輪子HttpComponets.
使用庫:Apache Http Client
HttpClient是一個代碼級的Http客戶端工具,可以使用它模擬瀏覽器向Http服務(wù)器發(fā)送請求。
其中HttpClient是HttpComponents項目其中的一部份,HttpComponents簡稱為hc.
見http://hc.apache.org/
使用HttpClient還需要HttpCore.這里其中包括Http請求與Http響應(yīng)的代碼封裝。
現(xiàn)在導(dǎo)入兩個jar包:
httpclient-4.0.jar
httpcore-4.0.jar
httpmime-4.0.jar
開始一個請求代碼如下:
- HttpClient httpClient = new DefaultHttpClient();
- //構(gòu)造請求,如果想使用POST則new一個HttpPost
- HttpGet get = new HttpGet("http://www.iteye.com");
- HttpResponse response = httpClient.execute(get);
- //先從響應(yīng)頭得到實體
- HttpEntity entity = response.getEntity();
- //得到實體輸入流
- InputStream inSm = entity.getContent();
- Scanner inScn = new Scanner(inSm);
- while(inScn.hasNextLine()){
- System.out.println(inScn.nextLine());
- }
- entity.consumeContent();
HttpClient httpClient = new DefaultHttpClient(); //構(gòu)造請求,如果想使用POST則new一個HttpPost HttpGet get = new HttpGet("http://www.iteye.com"); HttpResponse response = httpClient.execute(get); //先從響應(yīng)頭得到實體 HttpEntity entity = response.getEntity(); //得到實體輸入流 InputStream inSm = entity.getContent(); Scanner inScn = new Scanner(inSm); while(inScn.hasNextLine()){ System.out.println(inScn.nextLine()); } entity.consumeContent();
這個是在HC例子中有代碼作了少量的修改。
輸出:
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
- <title>JavaEye Java編程 Spring框架 AJAX技術(shù) Agile敏捷軟件開發(fā) ruby on rails實踐 - JavaEye做最棒的軟件開發(fā)交流社區(qū)</title>
- <meta name="description" content="Java編程,Spring Struts Webwork框架深入,XMLHTTP AJAX開發(fā),Java Web開發(fā),Java企業(yè)應(yīng)用,Java設(shè)計模式,Java開源框架,Java應(yīng)用服務(wù)器,Rich Client討論,Ruby編程,Ruby DSL開發(fā),Ruby on rails實踐,JavaScript編程,敏捷軟件開發(fā)XP TDD,軟件配置管理,軟件測試,項目管理UML,數(shù)據(jù)庫,C#/.net C/C++ Erlang/FP PHP/Linux平臺,精通Hibernate" />
- <meta name="keywords" content="Java編程 Spring框架 AJAX技術(shù) Agile敏捷軟件開發(fā) ruby on rails實踐 JavaEye深度技術(shù)社區(qū)" />
- <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" />
- <link href="/rss" rel="alternate" title="JavaEye技術(shù)網(wǎng)站RSS頻道訂閱" type="application/rss+xml" />
- <link />
-
- </head>
-
- ...省略,證明以上代碼已經(jīng)成功
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>JavaEye Java編程 Spring框架 AJAX技術(shù) Agile敏捷軟件開發(fā) ruby on rails實踐 - JavaEye做最棒的軟件開發(fā)交流社區(qū)</title> <meta name="description" content="Java編程,Spring Struts Webwork框架深入,XMLHTTP AJAX開發(fā),Java Web開發(fā),Java企業(yè)應(yīng)用,Java設(shè)計模式,Java開源框架,Java應(yīng)用服務(wù)器,Rich Client討論,Ruby編程,Ruby DSL開發(fā),Ruby on rails實踐,JavaScript編程,敏捷軟件開發(fā)XP TDD,軟件配置管理,軟件測試,項目管理UML,數(shù)據(jù)庫,C#/.net C/C++ Erlang/FP PHP/Linux平臺,精通Hibernate" /> <meta name="keywords" content="Java編程 Spring框架 AJAX技術(shù) Agile敏捷軟件開發(fā) ruby on rails實踐 JavaEye深度技術(shù)社區(qū)" /> <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" /> <link href="/rss" rel="alternate" title="JavaEye技術(shù)網(wǎng)站RSS頻道訂閱" type="application/rss+xml" /> <link media="screen" rel="stylesheet" type="text/css" /> </head> ...省略,證明以上代碼已經(jīng)成功
當(dāng)然這個只是大刀一小試。現(xiàn)在還離我的目標(biāo)差一點(diǎn)點(diǎn):
需要做個頭,我還不太清楚有什么頭可以使用,那樣我又寫了個程序看看IE的頭到底是怎樣子的,
沒有抓包程序,只好自已寫個程序:
- ServerSocket socketServer = new ServerSocket(10086);
- Socket client = socketServer.accept();
- InputStream inClient = client.getInputStream();
- Scanner inScn = new Scanner(inClient);
- while(inScn.hasNextLine()){
- System.out.println(inScn.nextLine());
- }
- inScn.close();
- client.close();
- socketServer.close();
ServerSocket socketServer = new ServerSocket(10086); Socket client = socketServer.accept(); InputStream inClient = client.getInputStream(); Scanner inScn = new Scanner(inClient); while(inScn.hasNextLine()){ System.out.println(inScn.nextLine()); } inScn.close(); client.close(); socketServer.close();
在IE地址欄上輸入:
http://locahost:10086/
點(diǎn)確定后可以得到程序輸出:
- GET / HTTP/1.1
- Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
- Accept-Language: zh-CN
- User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; QQWubi 87; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
- Accept-Encoding: gzip, deflate
- Host: localhost:10086
- Connection: Keep-Alive
GET / HTTP/1.1 Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */* Accept-Language: zh-CN User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; QQWubi 87; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0) Accept-Encoding: gzip, deflate Host: localhost:10086 Connection: Keep-Alive
分析請求包中這六個頭信息。可以參考以下文章:
http://zsxxsz.iteye.com/blog/568250
現(xiàn)在我使用HC模擬IE的請求,修改后代碼如下:
- HttpClient httpClient = new DefaultHttpClient();
- HttpGet get = new HttpGet("http://www.iteye.com");
-
- get.setHeader("Accept", "image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*");
- get.setHeader("Accept-Language","zh-CN");
- get.setHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; QQWubi 87; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)");
- get.setHeader("Accept-Encoding","gzip, deflate");
- get.setHeader("Host","you never be know");
- get.setHeader("Connection","Keep-Alive");
-
- HttpResponse response = httpClient.execute(get);
一、TCP/IP 協(xié)議介紹
在介紹 HTTP 協(xié)議之前,先簡單說一下TCP/IP協(xié)議的相關(guān)內(nèi)容。TCP/IP協(xié)議是分層的,從底層至應(yīng)用層分別為:物理層、鏈路層、網(wǎng)絡(luò)層、傳輸層和應(yīng)用層,如下圖所示:

從應(yīng)用層至物理層,數(shù)據(jù)是一層層封裝,封裝的方式一般都是在原有數(shù)據(jù)的前面加一個數(shù)據(jù)控制頭,數(shù)據(jù)封裝格式如下:

其中,對于TCP傳輸協(xié)議,客戶端在于服務(wù)器建立連接前需要經(jīng)過TCP三層握手,過程如下:

二、HTTP協(xié)議
2.1 簡介
超文本傳輸協(xié)議(Hypertext Transfer Protocol,簡稱HTTP)是應(yīng)用層協(xié)議,自 1990 年起,HTTP 就已經(jīng)被應(yīng)用于 WWW 全球信息服務(wù)系統(tǒng)。
HTTP 是一種請求/響應(yīng)式的協(xié)議。一個客戶機(jī)與服務(wù)器建立連接后,發(fā)送一個請求給服務(wù)器;服務(wù)器接到請求后,給予相應(yīng)的響應(yīng)信息。
HTTP 的第一版本 HTTP/0.9是一種簡單的用于網(wǎng)絡(luò)間原始數(shù)據(jù)傳輸?shù)膮f(xié)議;
HTTP/1.0由 RFC 1945 定義 ,在原 HTTP/0.9 的基礎(chǔ)上,有了進(jìn)一步的改進(jìn),允許消息以類 MIME 信息格式存 在,包括請求/響應(yīng)范式中的已傳輸數(shù)據(jù)和修飾符等方面的信息;
HTTP/1.1(RFC2616) 的要求更加嚴(yán)格以確保服務(wù)的可靠性,增強(qiáng)了在HTTP/1.0 沒有充分考慮到分層代理服務(wù)器、高速緩沖存儲器、持久連接需求或虛擬主機(jī)等方面的效能;
安全增強(qiáng)版的 HTTP (即S-HTTP或HTTPS),則是HTTP協(xié)議與安全套接口層(SSL)的結(jié)合,使HTTP的協(xié)議數(shù)據(jù)在傳輸過程中更加安全。
2.2 協(xié)議結(jié)構(gòu)
HTTP協(xié)議格式也比較簡單,格式如下:

2.3 HTTP 協(xié)議舉例
下面是一個HTTP請求及響應(yīng)的例子:

2.4 請求頭格式
a) 通用頭(general-header):
Cache-Control:客戶端希望服務(wù)端如何緩存自己的請求數(shù)據(jù),如"Cache-Control: no-cache","Cache-Control: max-age=0";
Connection:客戶端是否希望與服務(wù)端之間保持長連接,如"Connection: close", "Connection: keep-alive";
Date:只有當(dāng)請求方法為POST或PUT方法時客戶端才可能會有些字段;
Pragma:包含了客戶端一些特殊請求信息,如 "Pragma: no-cache" 客戶端希望代理或應(yīng)用服務(wù)器不應(yīng)緩存與該請求相關(guān)的結(jié)果數(shù)據(jù);
Via:一般用在代理網(wǎng)關(guān)向應(yīng)用服務(wù)器發(fā)送的請求頭中,表明該來自客戶端的請求經(jīng)過了網(wǎng)關(guān)代理,
格式為:"Via: 請求協(xié)議版本 網(wǎng)關(guān)標(biāo)識 [其它信息] ",
如 :" Via: 1.1 webcache_250_199.hexun.com:80 (squid)"
b) 請求頭(request-header):
Accept:表明客戶同端可接受的請求回應(yīng)的媒體類型范圍列表。星號“*”用于按范圍將類型分組,用“*/*”指示可接受全部類型;用“type/*”指示可接受 type類型的所有子類型,如“ Accept: image/gif, image/jpeg, */*”;
Accept-Charset:客戶端所能識別的字符集編碼格式,格式:“Accept-Charset: 字符集1[:權(quán)重],字符集2[:權(quán)重]”,如:“ Accept-Charset: iso-8859-5, unicode-1-1;q=0.8”;
Accept-Language:客戶端所能識別的語言,格式:“Accept-Language: 語言1[:權(quán)重],語言2[:權(quán)重]”,如:” Accept-Language: zh, en;q=0.7”;
Host:客戶請求的主機(jī)域名或主機(jī)IP,格式:“Host: 域名或IP[:端口號]”,如:“Host: www.hexun.com:80“,請求行中若有HTTP/1.1則必須有該請求頭;
User-Agent:表明用戶所使用的瀏覽器標(biāo)識,主要用于統(tǒng)計的目的;
Referer:指明該請求是從哪個關(guān)聯(lián)連接而來;
Accept-Encoding:客戶端所能識別的編碼壓縮格式,如:“Accept-Encoding: gzip, deflate”;
If- Modified-Since:該字段與客戶端緩存相關(guān),客戶端所訪問的URL自該指定日期以來在服務(wù)端是否被修改過,如果修改過則服務(wù)端返回新的修改后的信息,如果未修改過則服務(wù)器返回304表明此請求所指URL未曾修改過,如:“If-Modified-Since: Fri, 2 Sep 2006 19:37:36 GMT”;
If-None-Match:該字段與客戶端緩存相關(guān),客戶端發(fā)送URL請求的同時發(fā)送該字段及標(biāo)識,如果服務(wù)端的標(biāo)識與客戶端的標(biāo)識一致,則返回304表明此URL未修改過,如果不一致則服務(wù)端返回完整的數(shù)據(jù)信息,如:“If-None-Match: 0f0a893aad8c61:253, 0f0a893aad8c61:252, 0f0a893aad8c61:251”;
Cookie:為擴(kuò)展字段,存儲于客戶端,向同一域名的服務(wù)端發(fā)送屬于該域的cookie,如:“Cookie: MailUserName=whouse”;
c) 實體頭(entity-header): (此類頭存在時要求有數(shù)據(jù)體)
Content-Encoding:客戶端所能識別的編碼壓縮格式,如:“Content-Encoding: gzip, deflate”;
Content-Length:客戶端以POST方法上傳數(shù)據(jù)時數(shù)據(jù)體部分的內(nèi)容長度,如:“ Content-Length: 24”;
Content- Type:客戶端發(fā)送的數(shù)據(jù)體的內(nèi)容類型,如:“Content-Type: application/x-www-form-urlencoded”為以普通的POST方法發(fā)送的數(shù)據(jù);“Content-Type: multipart/form-data; boundary=---------------------------5169208281820”,則表明數(shù)據(jù)體由多部分組成,分隔符為 “-----------------------------5169208281820”;
2.5)響應(yīng)格式
a) 通用頭(general-header):
Cache- Control:服務(wù)端要求中間代理及客戶端如何緩存自己響應(yīng)的數(shù)據(jù),如“Cache-Control: no-cache”,如:“Cache-Control: private” 不希望被緩存,“Cache-Control: public” 可以被緩存;
Connection:服務(wù)端是否希望與客戶端之間保持長連接,如“Connection: close”, “Connection: keep-alive”;
Date:只有當(dāng)請求方法為POST或PUT方法時客戶端才可能會有些字段;
Pragma:包含了服務(wù)端一些特殊響應(yīng)信息,如 “Pragma: no-cache” 服務(wù)端希望代理或客戶端不應(yīng)緩存結(jié)果數(shù)據(jù);
Transfer-Encoding:服務(wù)端向客戶端傳輸數(shù)據(jù)所采用的傳輸模式(僅在HTTP1.1中出現(xiàn)),如:“Transfer-Encoding: chunked”,注:該字段的優(yōu)先級要高于“Content-Length” 字段的優(yōu)先級;
b)響應(yīng)頭(response-header):
Accept-Ranges:表明服務(wù)端接收的數(shù)據(jù)單位,如:“Accept-Ranges: bytes”, ;
Location:服務(wù)端向客戶端返回此信息以使客戶端進(jìn)行重定向,如:“Location: http://www.hexun.com”;
Server:服務(wù)端返回的用于標(biāo)識自己的一些信息,如:“ Server: Microsoft-IIS/6.0”;
ETag:服務(wù)端返回的響應(yīng)數(shù)據(jù)的標(biāo)識字段,客戶端可根據(jù)此字段的值向服務(wù)器發(fā)送某URL是否更新的信息;
c)實體頭(entity-header): (此類頭存在時要求有數(shù)據(jù)體)
Content-Encoding:服務(wù)端所響應(yīng)數(shù)據(jù)的編碼格式,如:“Content-Encoding: gzip”;
Content-Length:服務(wù)端所返回數(shù)據(jù)的數(shù)據(jù)體部分的內(nèi)容長度,如:“ Content-Length: 24”;
Content-Type:服務(wù)端所返回的數(shù)據(jù)體的內(nèi)容類型,如:“Content-Type: text/html; charset=gb2312” ;
Set-Cookie:服務(wù)端返回給客戶端的cookie數(shù)據(jù),如:“ Set-Cookie: ASP.NET_SessionId=icnh2ku2dqlmkciyobgvzl55; path=/”
2.6)服務(wù)器返回狀態(tài)碼
1xx:表明服務(wù)端接收了客戶端請求,客戶端繼續(xù)發(fā)送請求;
2xx:客戶端發(fā)送的請求被服務(wù)端成功接收并成功進(jìn)行了處理;
3xx:服務(wù)端給客戶端返回用于重定向的信息;
4xx:客戶端的請求有非法內(nèi)容;
5xx:服務(wù)端未能正常處理客戶端的請求而出現(xiàn)意外錯誤。
舉例:
“100” ; 服務(wù)端希望客戶端繼續(xù);
“200” ; 服務(wù)端成功接收并處理了客戶端的請求;
“301” ; 客戶端所請求的URL已經(jīng)移走,需要客戶端重定向到其它的URL;
“304” ; 客戶端所請求的URL未發(fā)生變化;
“400” ; 客戶端請求錯誤;
“403” ; 客戶端請求被服務(wù)端所禁止;
“404” ; 客戶端所請求的URL在服務(wù)端不存在;
“500” ; 服務(wù)端在處理客戶端請求時出現(xiàn)異常;
“501” ; 服務(wù)端未實現(xiàn)客戶端請求的方法或內(nèi)容;
“502” ; 此為中間代理返回給客戶端的出錯信息,表明服務(wù)端返回給代理時出錯;
“503” ; 服務(wù)端由于負(fù)載過高或其它錯誤而無法正常響應(yīng)客戶端請求;
“504” ; 此為中間代理返回給客戶端的出錯信息,表明代理連接服務(wù)端出現(xiàn)超時。
2.7)chunked 傳輸
編碼使用若干個Chunk組成,由一個標(biāo)明長度為0的chunk結(jié)束,每個Chunk有兩部分組成,第一部分是該Chunk的長度(以十六進(jìn)制表示)和長度單位(一般不寫),第二部分就是指定長度的內(nèi)容,每個部分用CRLF隔開。在最后一個長度為0的Chunk中的內(nèi)容是稱為footer的內(nèi)容,是一些沒有寫的頭部內(nèi)容。另外,在HTTP頭里必須含有:” Transfer-Encoding: chunked” 通用頭字段。格式如下:

2.8)HTTP 請求方法
GET、POST、HEAD、CONNECT、PUT、DELETE、TRACE
2.9)舉例
a)GET請求
Html代碼


- GET http://photo.test.com/inc/global.js HTTP/1.1
- Host: photo.test.com
- User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0
- Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
- Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3
- Accept-Encoding: gzip,deflate
- Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
- Keep-Alive: 300
- Proxy-Connection: keep-alive
- Cookie: ASP.NET_SessionId=ey5drq45lsomio55hoydzc45
- Cache-Control: max-age=0
GET http://photo.test.com/inc/global.js HTTP/1.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3
Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
Cookie: ASP.NET_SessionId=ey5drq45lsomio55hoydzc45
b)POST請求
Html代碼


- POST / HTTP/1.1
- Accept: image/gif, image/x-xbitmap, image/jpeg, application/vnd.ms-powerpoint, application/msword, */*
- Accept-Language: zh-cn
- Content-Type: application/x-www-form-urlencoded
- Accept-Encoding: gzip, deflate
- User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
- Host: www.test.com
- Content-Length: 24
- Connection: Keep-Alive
- Cache-Control: no-cache
-
- name=value&submitsubmit=submit
Accept: image/gif, image/x-xbitmap, image/jpeg, application/vnd.ms-powerpoint, application/msword, */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
c)通過HTTP代理發(fā)送GET請求
Html代碼


- GET http://mail.test.com/ HTTP/1.1
- Host: mail.test.com
- User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0
- Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
- Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3
- Accept-Encoding: gzip,deflate
- Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
- Keep-Alive: 300
- Proxy-Connection: keep-alive
GET http://mail.test.com/ HTTP/1.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3
Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
d)POST方式上傳文件
Html代碼


- POST http://www.test.comt/upload_attach?uidl=%3C HTTP/1.1
- Host: www.test.com
- User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0
- Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
- Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3
- Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
- Content-Type: multipart/form-data; boundary=---------------------------5169208281820
- Content-Length: 449
-
- -----------------------------5169208281820
- Content-Disposition: form-data; name="file_1"; filename=""
- Content-Type: application/octet-stream
-
-
- -----------------------------5169208281820
- Content-Disposition: form-data; name="file_0"; filename="test.txt"
- Content-Type: text/plain
-
- hello world!
-
- -----------------------------5169208281820
- Content-Disposition: form-data; name="oper"
-
- upload
- -----------------------------5169208281820--
POST http://www.test.comt/upload_attach?uidl=%3C HTTP/1.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3
Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
Content-Type: multipart/form-data; boundary=---------------------------5169208281820
Content-Disposition: form-data; name="file_1"; filename=""
Content-Type: application/octet-stream
Content-Disposition: form-data; name="file_0"; filename="test.txt"
Content-Disposition: form-data; name="oper"
e)CONNECT舉例
Html代碼


- CONNECT mail.test.com:80 HTTP/1.1
- User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0
- Proxy-Connection: keep-alive
- Host: mail.test.com:80
CONNECT mail.test.com:80 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0
3.0)在終端以 telnet 方式測試
a)打開回顯功能(針對windows)
Windows 2000:進(jìn)入DOS模式->輸入 telnet->set LOCAL_ECHO->退出:quit->telnet ip 80
Windows xp:進(jìn)入DOS模式->輸入telnet->set local echo->open ip 80
b) 按HTTP協(xié)議格式輸入GET請求、HEAD請求、POST請求。
摘要: /* 數(shù)據(jù)如下: name val memo a 2 a2(a的第二個值) a 1 a1--a的第一個值 a 3 a3:a的第三個值 b 1 b1-...
閱讀全文
數(shù)字簽名是什么?
作者:David Youd
翻譯:阮一峰
原文網(wǎng)址:http://www.youdzone.com/signature.html
1.

鮑勃有兩把鑰匙,一把是公鑰,另一把是私鑰。
2.

鮑勃把公鑰送給他的朋友們----帕蒂、道格、蘇珊----每人一把。
3.

蘇珊要給鮑勃寫一封保密的信。她寫完后用鮑勃的公鑰加密,就可以達(dá)到保密的效果。
4.

鮑勃收信后,用私鑰解密,就看到了信件內(nèi)容。這里要強(qiáng)調(diào)的是,只要鮑勃的私鑰不泄露,這封信就是安全的,即使落在別人手里,也無法解密。
5.

鮑勃給蘇珊回信,決定采用"數(shù)字簽名"。他寫完后先用Hash函數(shù),生成信件的摘要(digest)。
6.

然后,鮑勃使用私鑰,對這個摘要加密,生成"數(shù)字簽名"(signature)。
7.

鮑勃將這個簽名,附在信件下面,一起發(fā)給蘇珊。
8.

蘇珊收信后,取下數(shù)字簽名,用鮑勃的公鑰解密,得到信件的摘要。由此證明,這封信確實是鮑勃發(fā)出的。
9.

蘇珊再對信件本身使用Hash函數(shù),將得到的結(jié)果,與上一步得到的摘要進(jìn)行對比。如果兩者一致,就證明這封信未被修改過。
10.

復(fù)雜的情況出現(xiàn)了。道格想欺騙蘇珊,他偷偷使用了蘇珊的電腦,用自己的公鑰換走了鮑勃的公鑰。此時,蘇珊實際擁有的是道格的公鑰,但是還以為這是鮑勃的公鑰。因此,道格就可以冒充鮑勃,用自己的私鑰做成"數(shù)字簽名",寫信給蘇珊,讓蘇珊用假的鮑勃公鑰進(jìn)行解密。
11.

后來,蘇珊感覺不對勁,發(fā)現(xiàn)自己無法確定公鑰是否真的屬于鮑勃。她想到了一個辦法,要求鮑勃去找"證書中心"(certificate authority,簡稱CA),為公鑰做認(rèn)證。證書中心用自己的私鑰,對鮑勃的公鑰和一些相關(guān)信息一起加密,生成"數(shù)字證書"(Digital Certificate)。
12.

鮑勃拿到數(shù)字證書以后,就可以放心了。以后再給蘇珊寫信,只要在簽名的同時,再附上數(shù)字證書就行了。
13.

蘇珊收信后,用CA的公鑰解開數(shù)字證書,就可以拿到鮑勃真實的公鑰了,然后就能證明"數(shù)字簽名"是否真的是鮑勃簽的。
14.

下面,我們看一個應(yīng)用"數(shù)字證書"的實例:https協(xié)議。這個協(xié)議主要用于網(wǎng)頁加密。
15.

首先,客戶端向服務(wù)器發(fā)出加密請求。
16.

服務(wù)器用自己的私鑰加密網(wǎng)頁以后,連同本身的數(shù)字證書,一起發(fā)送給客戶端。
17.

客戶端(瀏覽器)的"證書管理器",有"受信任的根證書頒發(fā)機(jī)構(gòu)"列表。客戶端會根據(jù)這張列表,查看解開數(shù)字證書的公鑰是否在列表之內(nèi)。
18.

如果數(shù)字證書記載的網(wǎng)址,與你正在瀏覽的網(wǎng)址不一致,就說明這張證書可能被冒用,瀏覽器會發(fā)出警告。
19.

如果這張數(shù)字證書不是由受信任的機(jī)構(gòu)頒發(fā)的,瀏覽器會發(fā)出另一種警告。
20.
