JavaWeb之Servlet&網絡訪問服務器編程

1? ? ? Servlet&網絡訪問

1.1????網路基礎

B/S的S? Server?http網絡應用服務端軟件

http?Hyper Text Transmission Protocol 超文本傳輸協(xié)議舆声,處于四層架構中的應用層棋傍,是建立TCP的基礎上

網絡應用服務端軟件可以看成一個容器铆铆,我們將網絡應用部署到其中并啟動豌汇,這個容器就可以按照我們的意愿去工作郎楼,處理客戶端的請求并響應

常用網絡應用服務端軟件:Tomcat爪喘、JBoss蹄咖、Websphere、WebLogic

如何寫Web項目:

1钳幅、HttpServlet 小的服務端組件 定義一個類繼承它

2物蝙、重寫其中的doGet、doPost方法,在這兩個方法里寫上如何處理客戶端的請求敢艰,這兩個方法是回調方法诬乞,doGet處理Get請求、doPost處理Post請求

3钠导、在web.xml中注冊這個類震嫉,告訴容器在處理某一類型請求的時候,使用這個類中的邏輯

可以使用HttpServletRequest的getParameter方法獲取請求中某參數(shù)的值

可以使用HttpServletResponse的getOutputStream方法獲取響應的輸出流牡属,給客戶端寫信息

C/S 中的 C

URL類? Uniform Resource Locator統(tǒng)一資源定位器

構造方法:URL(String url)把一個字符串形式的url構建出一個URL對象

openConnection() 獲取網絡連接URLConnection對象票堵,一般會將其強轉為HttpURLConnection類型,并作相應操作逮栅。(調用這個方法時這個連接并沒有真正產生)

HttpURLConnection 類

主要方法:

connect()?產生真正的連接

getInputStream() 獲取響應體輸入流悴势,可以用來接收服務端響應

getResponseCode()獲取響應狀態(tài)碼,200為正常措伐,這個方法必須在連接之后以及請求發(fā)出去之后才調用特纤,否則它會隱式調用connect()方法,出現(xiàn)一些奇怪的狀況

getOutputStream()獲取請求體的輸出流侥加,可以往請求體中寫

setRequestMethod()設置請求方式捧存,默認為GET,如果是POST方式就一定要使用這個方法

setDoOutput() 設置是否可以往連接中輸出担败,默認是false昔穴,如果是POST方式,一定要設為true

setDoInput() 設置是否可從連接中讀出提前,默認為true,所以這個方法不需要使用

GET請求:

把參數(shù)放在url里面吗货,和服務端連接,讀取服務端響應

1岖研、創(chuàng)建URL(后面跟著參數(shù) )

2卿操、獲取連接

3、產生連接

4孙援、判斷狀態(tài)碼害淤,是200就讀取響應內容

POST請求:

1、創(chuàng)建URL(后面沒參數(shù))

2拓售、獲取連接

3窥摄、設置請求方法setRequestMethod("POST")

設置允許輸出setDoOutput(true),允許往請求(體)里寫

4、產生連接

5础淤、獲取連接的輸出流崭放,往請求(體)中寫參數(shù)

6哨苛、讀取響應內容

1.2????Web概述

1.2.1? 網絡架構:C/S 與 B/S之爭

C/S:Client/Server:《優(yōu)點:客戶端可以任意設計,可以展示絢麗的效果和特殊功能币砂;對于網速的依賴沒有B/S那么強

缺點:使用時需要下載客戶端并安裝建峭,所有客戶端都需要聯(lián)網更新》

B/S:Browser/Server:《優(yōu)點:不需要下載任何客戶端,只要有瀏覽器就可以使用决摧,當程序需要更新時亿蒸,只需要在服務端進行更新即可

缺點:所有的運算都要在服務端完成,服務器壓力和大掌桩,并且瀏覽器暫時不具備展示十分絢麗的效果的能力边锁;十分依賴網絡(網速)》

Http協(xié)議:《Hypertext Transfer Protocol:超文本傳輸協(xié)議,它是以TCP/IP為基礎的高層協(xié)議

定義瀏覽器和web服務器之間交換數(shù)據(jù)的過程以及數(shù)據(jù)格式

定義Web瀏覽器和web服務器之間通訊的協(xié)議

現(xiàn)在廣泛使用的版本是Http/1.1波岛。相對于Http/1.0來說茅坛,最大的特點就是支持持續(xù)連接(即一次TCP連接上可以包含多次請求和響應)

常見狀態(tài)碼:《消息(1字頭):100???? 成功(2字頭):200?? 重定向(3字頭)

請求錯誤(4字頭):404??? 服務器錯誤(5、6字頭):500》

1.3????Servlet的基本概念

Servlet是SUN公司提供的一種用于開發(fā)動態(tài)web資源的技術

Sun公司在其API中提供了一個Servlet接口则拷,根據(jù)該接口編寫的程序沒有main方法贡蓖。它們受控于另一個Java應用,這個Java應用稱為Servlet容器隔躲,Tomcat就是這樣一個容器

1.3.1? Servlet的登陸示例

Inserttitle here

-->

action:服務器的地址

method:數(shù)據(jù)的提交方式,常用的有兩種:get摩梧、post

-->

用戶名:

密碼:

publicclass MyServlet extends HttpServlet {

// 序列值

private static final longserialVersionUID = 1L;

/**

* @see HttpServlet#HttpServlet()

*/

public MyServlet() {

super();

// TODO Auto-generated constructor stub

}

/**

*

* 用于處理來自客戶端的網絡請求(get方式)

* 參數(shù)1:request物延,來自客戶端的請求對象宣旱,封裝了客戶端向服務端發(fā)送的請求數(shù)據(jù)

* 參數(shù)2:response,通過該對象可以向客戶端做出響應

*/

protected void doGet(HttpServletRequestrequest, HttpServletResponse response) throws ServletException, IOException {

// 獲取賬號叛薯、密碼

response.setCharacterEncoding("GBK");

String name= request.getParameter("username");

String pwd= request.getParameter("pwd");

System.out.println(name+ "..." + pwd);

if("admin".equals(name)&& "123".equals(pwd)) {

//登陸成功

response.getWriter().print("loginsuccess...(登陸成功)");

} else {

//登陸失敗

response.getWriter().print("loginfailed...(登陸失敾胍鳌)");

}

}

/**

* 用于處理來自客戶端的網絡請求(post方式)

*/

protected voiddoPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {

// TODO Auto-generated methodstub

this.doGet(request,response);

}

}

基于JSP的實現(xiàn)形式:

<%@page language="java" import="java.util.*"pageEncoding="utf-8"%>

<%

Stringpath = request.getContextPath();

%>

測試HTTP協(xié)議體的內容

-->

-->

/servlet/LoginAction">

用戶名:


密? 碼:


publicclass LoginAction extends HttpServlet {

/**

* Constructor of the object.

*/

public LoginAction() {

super();

}

/**

* Destruction of the servlet.

*/

public void destroy() {

super.destroy(); // Just puts"destroy" string in log

// Put your code here

}

public void doGet(HttpServletRequestrequest, HttpServletResponse response)

throwsServletException, IOException {

this.doPost(request,response);

}

public void doPost(HttpServletRequestrequest, HttpServletResponse response)

throwsServletException, IOException {

response.setContentType("text/html;charset=utf-8");

request.setCharacterEncoding("utf-8");

response.setCharacterEncoding("utf-8");

PrintWriter out =response.getWriter();

String username =request.getParameter("username");

System.out.println("-username->>"+username);

String pswd =request.getParameter("password");

System.out.println("-password->>"+pswd);

if(username.equals("admin")&&pswd.equals("123")){

//表示服務器端返回的結果

out.print("loginis success!!!!");

}else{

out.print("loginis fail!!!");

}

out.flush();

out.close();

}

public void init() throwsServletException {

// Put your code here

}

}

1.4????網絡訪問

1.4.1? URL

什么是URL?:《URL(UniformResource Locator)是統(tǒng)一資源定位符的簡稱

表示Intent上某一資源的地址

通過URL可以訪問Intenet上的各種網絡資源耗溜,比如常見的www组力、FTP站點》

URL的基本結構由5部分組成:《<傳輸協(xié)議>://<主機名>:<端口號>/<文件名>#<引用>

http://www.tomcat.com:80/Gamelan/network.html#BOTTOM》

1.4.2? 獲取網絡數(shù)據(jù)

方式一:HttpUrlConnection類:《1、獲取網絡連接對象

1抖拴、 設置網絡數(shù)據(jù)請求的方式(默認GET)

2燎字、 設置連接超時的時間,如果超時阿宅,說明沒有連接成功候衍,就會拋出異常

3、 設置接收數(shù)據(jù)超時的時間洒放,如果超時蛉鹿,就會排除異常

4、 驗證服務器的返回碼

5往湿、 通過IO流傳輸數(shù)據(jù)

6妖异、 解析數(shù)據(jù)

PS:POST請求需要另外設置請求參數(shù)

Content-Type:application/x-www-form-urlencoded

Content-Length: 數(shù)據(jù)的大小

方式二:ApacheHttpClient框架:【

《HttpClient是由Apache開源組織提供的一個開源項目惋戏,它是一個簡單的Http客戶端(并不是瀏覽器),可以用于發(fā)送Http請求他膳,接收Http響應》

《簡單來說响逢,HttpClient就是一個增強版的HttpURLConnection,HttpURLConnection可以做的事情HttpClient全部可以做棕孙。HttpURLConnection沒有提供的有些功能龄句,HttpClient也提供了,但它只是關注于如何發(fā)送請求散罕、接收響應分歇,以及管理Http的連接》

Android已經成功集成了HttpClient:Android6.0開始,已經將HttClient框架從AndroidSDK中移除》

1.4.3? Apache HttpClient框架

《注意:需要加入外部的Java包欧漱。

publicclass Demo {

public static void main(String[] args){

// TODO Auto-generated methodstub

//?????????????? doGetByHttpClient();

doPostByHttpClient();

}

private static voiddoPostByHttpClient() {

// TODO Auto-generated methodstub

HttpClient client = null;

try {

client = newDefaultHttpClient();

HttpPost post = newHttpPost("http://api.k780.com:88/");

//保存請求參數(shù)的集合對象

Listlist = new ArrayList<>();

//將請求參數(shù)封裝成對象存入集合中职抡,每一個NameValuePair對象封裝了一組鍵值對

list.add(newBasicNameValuePair("app", "weather.today"));

list.add(new BasicNameValuePair("weaid","1"));

list.add(newBasicNameValuePair("appkey", "15250"));

list.add(newBasicNameValuePair("sign","f88a5cecc3cbd37129bc090c0ae29943"));

list.add(newBasicNameValuePair("format", "json"));

HttpEntity httpEntity = newUrlEncodedFormEntity(list);

post.setEntity(httpEntity);

HttpResponse response =client.execute(post);

int code =response.getStatusLine().getStatusCode();

if(code == 200){

InputStream is =response.getEntity().getContent();

String result =readStream(is);

System.out.println(result);

}

} catch(UnsupportedEncodingException e) {

// TODOAuto-generated catch block

e.printStackTrace();

} catch(IllegalStateException e) {

// TODOAuto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}finally{

if(client != null){

client.getConnectionManager().shutdown();

client =null;

}

}

}

private static void doGetByHttpClient(){

// TODO Auto-generated methodstub

HttpClient client = null;

try {

client? = new DefaultHttpClient();

HttpGet get = newHttpGet("http://api.k780.com:88/?app=weather.today&weaid=1&&appkey=15250&sign=f88a5cecc3cbd37129bc090c0ae29943&format=json");

//訪問網絡資源

HttpResponseresponse = client.execute(get);

//獲取狀態(tài)碼

int code=response.getStatusLine().getStatusCode();

if(code == 200){

InputStreamis = response.getEntity().getContent();

Stringresult = readStream(is);

System.out.println(result);

}else{

throw newRuntimeException("網絡訪問失敗:"+code);

}

} catch(ClientProtocolException e) {

// TODOAuto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}finally{

if(client !=null){

client.getConnectionManager().shutdown();

client =null;

}

}

}

public static StringreadStream(InputStream is) throws IOException{

ByteArrayOutputStream baos =new ByteArrayOutputStream();

byte[] buf = new byte[1024];

int len = 0;

while((len=is.read(buf))!=-1){

baos.write(buf, 0,len);

}

return newString(baos.toByteArray(), "utf-8");

}

}

1.5????K780數(shù)據(jù)網

K780數(shù)據(jù)網误甚,測試賬號

《Appkey:15250???? Secret:2bbebb3e480a850df6daca0c04a954e1

Sign:f88a5cecc3cbd37129bc090c0ae29943》

1.6????示例使用Post和Get請求網絡數(shù)據(jù)

publicclass NetPostGet {

/**

* @param args

*/

public static void main(String[] args){

// TODO Auto-generated methodstub

// doGet();

doPost();

}

// 使用post方式請求網絡數(shù)據(jù)

private static void doPost() {

HttpURLConnection conn =null;

try {

URL url = newURL("http://api.k780.com:88/");

conn =(HttpURLConnection) url.openConnection();

String data ="app=weather.today&weaid=1&&appkey=15250&sign=f88a5cecc3cbd37129bc090c0ae29943&format=json";

conn.setRequestMethod("POST");

conn.setReadTimeout(5000);

conn.setRequestProperty("Content-Type",

"application/x-www-form-urlencoded");

conn.setRequestProperty("Content-Length",data.length() + "");

// post網絡訪問必須實現(xiàn)

conn.setDoInput(true);

conn.setDoOutput(true);

// 注意要將請求的內容寫到請求體中去

conn.getOutputStream().write(data.getBytes());

conn.connect();

int code =conn.getResponseCode();

if (code == 200) {//表示訪問成功

InputStreamis = conn.getInputStream();

System.out.println(readStream(is));

} else {

System.out.println("網絡數(shù)據(jù)訪問失敗:" + code);

}

} catch(MalformedURLException e) {

// TODOAuto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODOAuto-generated catch block

e.printStackTrace();

} finally {

if (conn != null) {

conn.disconnect();

conn =null;

}

}

}

// 使用get方式請求網絡數(shù)據(jù)

private static void doGet() {

HttpURLConnection conn =null;

try {

URL url = new URL(

"http://api.k780.com:88/?app=weather.today&weaid=1&&appkey=15250&sign=f88a5cecc3cbd37129bc090c0ae29943&format=json");

conn =(HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setReadTimeout(5000);

conn.setReadTimeout(5000);

conn.connect();

int code =conn.getResponseCode();

if (code == 200) {

InputStreamis = conn.getInputStream();

System.out.println(readStream(is));

} else {

System.out.println("獲取數(shù)據(jù)失敗:" + code);

}

} catch(MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

if (conn != null) {

conn.disconnect();

conn =null;

}

}

}

public static StringreadStream(InputStream is) throws IOException {

ByteArrayOutputStream baos =new ByteArrayOutputStream();

int len = 0;

byte[] buf = new byte[1024];

while ((len = is.read(buf))!= -1) {

baos.write(buf, 0,len);

}

return newString(baos.toByteArray(), "utf-8");

}

}

1.7????網絡訪問工具類封裝

publicclass HttpUtils {

private static final int TIMEOUT =10000;

//返回一個字節(jié)數(shù)組

public static byte[] doGet(Stringpath){

try {

URL mUrl = newURL(path);

HttpURLConnectionconn = (HttpURLConnection)mUrl.openConnection();

conn.setRequestMethod("GET");

conn.setReadTimeout(TIMEOUT);

conn.setReadTimeout(TIMEOUT);

conn.connect();

int code =conn.getResponseCode();

if(code == 200){

return readStream(conn.getInputStream());

}else{

throw newRuntimeException("網絡訪問失敻克Α:"+code);

}

} catch(MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

public static byte[] doPost(String url,String params) {

HttpURLConnection conn =null;

try {

URL mUrl = newURL(url);

conn =(HttpURLConnection) mUrl.openConnection();

conn.setRequestMethod("POST");

conn.setConnectTimeout(TIMEOUT);

conn.setReadTimeout(TIMEOUT);

// 設置請求屬性

conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");

conn.setRequestProperty("Content-Length",params.length()+"");

// Post請求必須要寫以下兩行代碼

conn.setDoInput(true);

conn.setDoOutput(true);

// 將請求參數(shù)寫到請求體中

conn.getOutputStream().write(params.getBytes());;

conn.connect();

int code =conn.getResponseCode();

if(code == 200) {

returnreadStream(conn.getInputStream());

} else {

throw newRuntimeException("網絡訪問失敗:"+ code);

}

} catch (Exception e) {

e.printStackTrace();

return null;

} finally {

if(conn != null) {

conn.disconnect();

conn =null;

}

}

}

//返回一個字符串

public static String doGetStr(Stringpath) throws IOException{

byte[] data = doGet(path);

return new String(data, "utf-8");

}

private static byte[]readStream(InputStream is) throws IOException{

ByteArrayOutputStream baos =new ByteArrayOutputStream();

byte[] buf = new byte[1024];

int len =0;

while((len =is.read(buf))!=-1){

baos.write(buf, 0,len);

}

return baos.toByteArray();

}

}

1.8????總結

在Android中對網絡請求最基本的實現(xiàn)有兩種

1窑邦、? HttpURLConnection

是JDK自帶的實現(xiàn)方式擅威,實現(xiàn)方式相對比較繁瑣,也比較靈活

2冈钦、? HttpClient框架

底層代碼還是基于HttpURLConnection,只是對HttpURLConnection進行了更深層次的封裝

是apache開源組織開發(fā)的開源框架郊丛,實現(xiàn)方式相對簡單一些,相對HttpURLConnection來說瞧筛,沒有那么靈活

Android在SDK(SoftwareDevelopment Kit)中已經集成了HttpClient框架

不過厉熟,Android在6.0開始,就已經將HttpClient框架從SDK中移除了

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末较幌,一起剝皮案震驚了整個濱河市揍瑟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乍炉,老刑警劉巖绢片,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異岛琼,居然都是意外死亡底循,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門衷恭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來此叠,“玉大人,你說我怎么就攤上這事∶鹪” “怎么了猬错?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茸歧。 經常有香客問我倦炒,道長,這世上最難降的妖魔是什么软瞎? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任逢唤,我火速辦了婚禮,結果婚禮上涤浇,老公的妹妹穿的比我還像新娘鳖藕。我一直安慰自己,他們只是感情好只锭,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布著恩。 她就那樣靜靜地躺著,像睡著了一般蜻展。 火紅的嫁衣襯著肌膚如雪喉誊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天纵顾,我揣著相機與錄音伍茄,去河邊找鬼。 笑死施逾,一個胖子當著我的面吹牛敷矫,可吹牛的內容都是我干的。 我是一名探鬼主播音念,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼沪饺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了闷愤?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤件余,失蹤者是張志新(化名)和其女友劉穎讥脐,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體啼器,經...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡旬渠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了端壳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片告丢。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖损谦,靈堂內的尸體忽然破棺而出岖免,到底是詐尸還是另有隱情岳颇,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布颅湘,位于F島的核電站话侧,受9級特大地震影響,放射性物質發(fā)生泄漏闯参。R本人自食惡果不足惜瞻鹏,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹿寨。 院中可真熱鬧新博,春花似錦、人聲如沸脚草。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽玩讳。三九已至涩蜘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間熏纯,已是汗流浹背同诫。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留樟澜,地道東北人误窖。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像秩贰,于是被迫代替她去往敵國和親霹俺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理毒费,服務發(fā)現(xiàn)丙唧,斷路器,智...
    卡卡羅2017閱讀 134,600評論 18 139
  • 網絡請求是android客戶端很重要的部分觅玻。下面從入門級開始介紹下自己Android網絡請求的實踐歷程想际。希望能給剛...
    passiontim閱讀 1,374評論 0 17
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法溪厘,內部類的語法胡本,繼承相關的語法,異常的語法畸悬,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • 注:網絡請求等耗時代碼不要在主線程(UI線程中) HTTPURLCONNECTION get方法: try{URL...
    __范特西__閱讀 909評論 0 0
  • 1 AsyncTask異步任務 1.1ANR的概念 Application Not Responding侧甫,應用...
    征程_Journey閱讀 1,140評論 0 6