JavaWeb之Servlet&网络访问服务器编程

1      Servlet&网络访问

1.1    网路基础

B/S的S  Server http网络应用服务端软件

http Hyper Text Transmission Protocol 超文本传输协议,处于四层架构中的应用层,是建立TCP的基础上

网络应用服务端软件可以看成一个容器,我们将网络应用部署到其中并启动,这个容器就可以按照我们的意愿去工作,处理客户端的请求并响应

常用网络应用服务端软件:Tomcat、JBoss、Websphere、WebLogic

如何写Web项目:

1、HttpServlet 小的服务端组件 定义一个类继承它

2、重写其中的doGet、doPost方法,在这两个方法里写上如何处理客户端的请求,这两个方法是回调方法,doGet处理Get请求、doPost处理Post请求

3、在web.xml中注册这个类,告诉容器在处理某一类型请求的时候,使用这个类中的逻辑

可以使用HttpServletRequest的getParameter方法获取请求中某参数的值

可以使用HttpServletResponse的getOutputStream方法获取响应的输出流,给客户端写信息

C/S 中的 C

URL类  Uniform Resource Locator统一资源定位器

构造方法:URL(String url)把一个字符串形式的url构建出一个URL对象

openConnection() 获取网络连接URLConnection对象,一般会将其强转为HttpURLConnection类型,并作相应操作。(调用这个方法时这个连接并没有真正产生)

HttpURLConnection 类

主要方法:

connect() 产生真正的连接

getInputStream() 获取响应体输入流,可以用来接收服务端响应

getResponseCode()获取响应状态码,200为正常,这个方法必须在连接之后以及请求发出去之后才调用,否则它会隐式调用connect()方法,出现一些奇怪的状况

getOutputStream()获取请求体的输出流,可以往请求体中写

setRequestMethod()设置请求方式,默认为GET,如果是POST方式就一定要使用这个方法

setDoOutput() 设置是否可以往连接中输出,默认是false,如果是POST方式,一定要设为true

setDoInput() 设置是否可从连接中读出,默认为true,所以这个方法不需要使用

GET请求:

把参数放在url里面,和服务端连接,读取服务端响应

1、创建URL(后面跟着参数 )

2、获取连接

3、产生连接

4、判断状态码,是200就读取响应内容

POST请求:

1、创建URL(后面没参数)

2、获取连接

3、设置请求方法setRequestMethod("POST")

设置允许输出setDoOutput(true),允许往请求(体)里写

4、产生连接

5、获取连接的输出流,往请求(体)中写参数

6、读取响应内容

1.2    Web概述

1.2.1  网络架构:C/S 与 B/S之争

C/S:Client/Server:《优点:客户端可以任意设计,可以展示绚丽的效果和特殊功能;对于网速的依赖没有B/S那么强

缺点:使用时需要下载客户端并安装,所有客户端都需要联网更新》

B/S:Browser/Server:《优点:不需要下载任何客户端,只要有浏览器就可以使用,当程序需要更新时,只需要在服务端进行更新即可

缺点:所有的运算都要在服务端完成,服务器压力和大,并且浏览器暂时不具备展示十分绚丽的效果的能力;十分依赖网络(网速)》

Http协议:《Hypertext Transfer Protocol:超文本传输协议,它是以TCP/IP为基础的高层协议

定义浏览器和web服务器之间交换数据的过程以及数据格式

定义Web浏览器和web服务器之间通讯的协议

现在广泛使用的版本是Http/1.1。相对于Http/1.0来说,最大的特点就是支持持续连接(即一次TCP连接上可以包含多次请求和响应)

常见状态码:《消息(1字头):100     成功(2字头):200   重定向(3字头)

请求错误(4字头):404    服务器错误(5、6字头):500》

1.3    Servlet的基本概念

Servlet是SUN公司提供的一种用于开发动态web资源的技术

Sun公司在其API中提供了一个Servlet接口,根据该接口编写的程序没有main方法。它们受控于另一个Java应用,这个Java应用称为Servlet容器,Tomcat就是这样一个容器

1.3.1  Servlet的登陆示例

Inserttitle here

-->

action:服务器的地址

method:数据的提交方式,常用的有两种:get、post

-->

用户名:

密码:

publicclass MyServlet extends HttpServlet {

// 序列值

private static final longserialVersionUID = 1L;

/**

* @see HttpServlet#HttpServlet()

*/

public MyServlet() {

super();

// TODO Auto-generated constructor stub

}

/**

*

* 用于处理来自客户端的网络请求(get方式)

* 参数1:request,来自客户端的请求对象,封装了客户端向服务端发送的请求数据

* 参数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的实现形式:

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

<%

Stringpath = request.getContextPath();

%>

测试HTTP协议体的内容

-->

-->

/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)是统一资源定位符的简称

表示Intent上某一资源的地址

通过URL可以访问Intenet上的各种网络资源,比如常见的www、FTP站点》

URL的基本结构由5部分组成:《<传输协议>://<主机名>:<端口号>/<文件名>#<引用>

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

1.4.2  获取网络数据

方式一:HttpUrlConnection类:《1、获取网络连接对象

1、 设置网络数据请求的方式(默认GET)

2、 设置连接超时的时间,如果超时,说明没有连接成功,就会抛出异常

3、 设置接收数据超时的时间,如果超时,就会排除异常

4、 验证服务器的返回码

5、 通过IO流传输数据

6、 解析数据

PS:POST请求需要另外设置请求参数

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

Content-Length: 数据的大小

方式二:ApacheHttpClient框架:【

《HttpClient是由Apache开源组织提供的一个开源项目,它是一个简单的Http客户端(并不是浏览器),可以用于发送Http请求,接收Http响应》

《简单来说,HttpClient就是一个增强版的HttpURLConnection,HttpURLConnection可以做的事情HttpClient全部可以做。HttpURLConnection没有提供的有些功能,HttpClient也提供了,但它只是关注于如何发送请求、接收响应,以及管理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/");

//保存请求参数的集合对象

Listlist = new ArrayList<>();

//将请求参数封装成对象存入集合中,每一个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);

//获取状态码

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数据网

K780数据网,测试账号

《Appkey:15250     Secret:2bbebb3e480a850df6daca0c04a954e1

Sign:f88a5cecc3cbd37129bc090c0ae29943》

1.6    示例使用Post和Get请求网络数据

publicclass NetPostGet {

/**

* @param args

*/

public static void main(String[] args){

// TODO Auto-generated methodstub

// doGet();

doPost();

}

// 使用post方式请求网络数据

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网络访问必须实现

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("网络数据访问失败:" + 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方式请求网络数据

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("获取数据失败:" + 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;

//返回一个字节数组

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);

// 将请求参数写到请求体中

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中对网络请求最基本的实现有两种

1、  HttpURLConnection

是JDK自带的实现方式,实现方式相对比较繁琐,也比较灵活

2、  HttpClient框架

底层代码还是基于HttpURLConnection,只是对HttpURLConnection进行了更深层次的封装

是apache开源组织开发的开源框架,实现方式相对简单一些,相对HttpURLConnection来说,没有那么灵活

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

不过,Android在6.0开始,就已经将HttpClient框架从SDK中移除了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 网络请求是android客户端很重要的部分。下面从入门级开始介绍下自己Android网络请求的实践历程。希望能给刚...
    passiontim阅读 1,378评论 0 17
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,598评论 18 399
  • 注:网络请求等耗时代码不要在主线程(UI线程中) HTTPURLCONNECTION get方法: try{URL...
    __范特西__阅读 917评论 0 0
  • 1 AsyncTask异步任务 1.1ANR的概念 Application Not Responding,应用...
    征程_Journey阅读 1,147评论 0 6