android-数据存储之远程服务器存储
一、如何编码实现客户端与服务器端的交互
<一>JDK内置原生API
HttpUrlConnection
<二>Android内置的包装API
HttpClient浏览器
<三>异步网络请求框架
.Volley
.Xutils
二、声明权限
进行网络求情需要在AndroidManifest.xml文件中声明连接网络的权限:
三、访问网络必须在分线程中执行
..................
四、HTTP协议
1、一次请求过程:
建立连接——>发送请求——>处理请求——>返回数据——>.....——>关闭连接
2、HTTP请求常用方式:
<1>GET
请求参数地址栏可见
<2>POST
3、HTTP请求格式:
<request-line> ---请求行:用于描述客户端请求方式,包括请求资源名以及使用的HTTP协议版本号
<headers> ---请求头:用于描述客户端请求哪台主机,以及客户端一些环境信息
<blank line> ---一个空行
[<request-body>] ---请求体:实体内容
eg.
说明:第一行必须是一个请求行(request-line),用来说明请求类型,要访问的资源以及所使用的HTTP版本.
紧接着是一个首部(header)小节,用来说明服务器要使用的附加信息.
之后是一个空行.
再后面可以添加任意的其他数据[称之为主体(body)].
GET请求:
GET / HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Host: www.google.cn
Connection: Keep-Alive
说明:请求的第一部分说明了该请求是一个GET请求.该行的第二部分是一个斜杠(/),用来说明请求的是该域名的根目录.该行的最后一部分说明使用的是HTTP1.1版本(另一个可选荐是1.0).
第2行是请求的第一个首部,HOST将指出请求的目的地.User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础.该信息由你的浏览器来定义,并且在每个请求中自动发送.Connection,通常将浏览器操作设置为Keep-Alive
第三部分,空行,即使不存在请求主体,这个空行也是必需的.
POST请求:
POST / HTTP1.1
Host:www.wrox.com
User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type:application/x-www-form-urlencoded
Content-Length:40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
说明:请求行开始处的GET改为POST,以表示不同的请求类型.
Content-Type说明了请求主体的内容是如何编码的.浏览器始终以application/x-www-form-urlencoded的格式编码来传送数据,这是针对简单URL编码的MIME类型.Content-Length说明了请求主体的字节数.
最后请求主体.名称-值对的形式.
4、HTTP响应格式
<status-line> ---响应行/状态行:描述服务器对请求的处理结果
<headers> ---消息头(可以多行):描述服务器基本信息以及对数据的描述,服务器通过这些数据的描述信息可以通知客户端如何处理服务器回送的数据。
<blank line> ---一个空行
[<response-body>] ---实体内容:代表服务器向向客户端回送的数据。
eg.
HTTP/1.1 200 OK
Date: Fri, 22 May 2009 06:07:21 GMT
Content-Type: text/html; charset=UTF-8
<html>
<head></head>
<body>
<!--body goes here-->
</body>
</html>
说明:HTTP状态码200,找到资源,并且一切正常;203:重定向;404:找不到资源。
Date:生成响应的日期和时间.
Content-Type:指定了MIME类型的HTML(text/html),编码类型是UTF-8
HTML源文体.
五、测试
1、搭建远程服务器:
a.安装并配置Tomcat
b.创建一个动态Web工程
c.把需要直接访问的资源放在WebContent/WebRoot目录下
d.可能需要创建Servlet/Filter
e.运行
f.访问:http://ip:8080/xxx/index.jsp
2、使用JDK内置原生API
1>HttpConnection
URL:包含请求地址的类:
---URL(path) 包含请求路径的构造方法
---openConnection() 得到连接对象,返回HttpConnection(本地连接)
测试:
URL url=new URL(path);
HttpConnection connection=url.openConnection();
2>HttpURLConnection 代表与服务器连接的类
setMethod("GET/POST") 设置请求发式
setConnectTimeOut(time) 设置连接超时时间
setReadTimeOut(time) 设置读取服务器返回数据的时间
connect() 连接服务器(服务器连接)
int getResponseCode() 得到服务器返回的结果码
int getContentLength() 得到服务器返回数据的长度
getOutputStream() 返回一个指向服务器端的数据输出流
getInputStream() 返回一个从服务器端返回的数据输入流
disconnect() 断开连接
3、Android内置的包装API
HttpClient
1>HttpClient(抽象类)/DefaultHttpClient 能提交请求的客户端对象
.HttpResponse execute(HttpUriRequest request) 执行包含请求数据的请求对象,返回包含响应数据的响应对象
.HttpParams getParams() 得到包含请求参数的对象
2>HttpConnectionParams 设置请求参数的工具类
.static setConnectionTimeout(params,time) 设置获取连接的超时时间
.static setSoTimeout(params,time) 设置读取数据的超时时间
3>HttpGet (Get请求)
HttpGet(String path) 包含请求路径的构造方法
4>HttpPost (Post请求)
HttpPost(String path) :包含请求路径的构造方法
setEntity(HttpEntity entity): 设置请求体
5>NameValuePair/BasicNameValuePair :包含参数键值对
BasicNameValuePair(String name,String value)
6>HttpResponse: 服务器返回的响应
getStatusLine() : 得到响应状态行从而得到状态吗
getEntity() :得到响应体数据对象
7>EntityUtils :解析HttpEntity的工具类
toString(httpEntity) :解析响应体得到内容字符串
8>关闭连接释放资源
getConnectionManager().show()
4、异步网络请求框架--volley
Android网络通信库,能使网络通信更快、更简单、更健壮;适合数据量不大但通信频繁的场景;
a.不需要我们启动分线程,框架内部接收到请求后自动会在分线程
b.如何返回数据? 切换到主线程调用监听器的回调方法。
1>RequestQueue:请求队列,会自动执行队列中的请求
.Volley.new RequestQueue(context) :创建一个请求队列
.addRequest(Request request) : 将请求添加到请求对队列
2>Request<T>: 代表请求的接口
StringRequest : 获取字符串结果请求
JsonRequest: 获取json字符串结果请求
ImageRequest: 获取图片结果请求
3>
六、知识拓展
1、ByteArrayOutputStream类
2、 runOnUiThread()方法
源码:
public class MainActivity extends Activity {
private TextView tv;
private RequestQueue queue;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView) findViewById(R.id.textView1);
queue=Volley.newRequestQueue(this);
}
public void testGet(View v) throws Exception{
final ProgressDialog dialog=ProgressDialog.show(this, null, "正在请求中...");
new Thread(){
public void run() {
String path="http://192.168.56.1:8080/Web_Server/index.jsp?name=tom&age=23";
URL url;
try {
url = new URL(path);
HttpURLConnection huc= (HttpURLConnection)url.openConnection();
huc.setRequestMethod("GET");
huc.setConnectTimeout(5000);
huc.setReadTimeout(6000);
huc.connect();
//发送请求
int responseCode=huc.getResponseCode();
if (responseCode==200) {
InputStream is=huc.getInputStream();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte[] buffer=new byte[1024];
int len=-1;
while((len=is.read(buffer))!=-1){
baos.write(buffer, 0, len);
}
final String reault=baos.toString();
baos.close();
is.close();
//在主线程更新ui
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText(reault);
dialog.dismiss();
}
});
//断开连接
huc.disconnect();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
dialog.dismiss();
}
}
}.start();
}
public void testPost1(View v){
final ProgressDialog dialog=ProgressDialog.show(this, null, "正在请求中...");
new Thread(){
public void run() {
String path="http://192.168.56.1:8080/Web_Server/index.jsp";
URL url;
try {
url = new URL(path);
HttpURLConnection huc= (HttpURLConnection)url.openConnection();
huc.setRequestMethod("POST");
huc.setConnectTimeout(5000);
huc.setReadTimeout(6000);
huc.connect();
OutputStream os=huc.getOutputStream();
String data="name=tom5&age=11";
os.write(data.getBytes("utf-8"));
//发送请求
int responseCode=huc.getResponseCode();
if (responseCode==200) {
InputStream is=huc.getInputStream();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte[] buffer=new byte[1024];
int len=-1;
while((len=is.read(buffer))!=-1){
baos.write(buffer, 0, len);
}
final String reault=baos.toString();
baos.close();
is.close();
//在主线程更新ui
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText(reault);
dialog.dismiss();
}
});
//断开连接
huc.disconnect();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
dialog.dismiss();
}
}
}.start();
}
public void testGet2(View v) throws Exception{
final ProgressDialog dialog=ProgressDialog.show(this, null, "正在请求中...");
new Thread(){
public void run() {
String path="http://192.168.56.1:8080/Web_Server/index.jsp?name=tom&age=23";
try {
//创建Client对象
HttpClient httpClient=new DefaultHttpClient();
//设置超时
HttpParams params=httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 5000);
//创建请求对象
HttpGet request=new HttpGet(path);
//执行请求对象
HttpResponse response=httpClient.execute(request);
int statusCode=response.getStatusLine().getStatusCode();
if (statusCode==200) {
//得到响应文本
HttpEntity entity=response.getEntity();
final String result=EntityUtils.toString(entity);
//在主线程更新ui
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText(result);
dialog.dismiss();
}
});
}
//断开连接
httpClient.getConnectionManager().shutdown();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
dialog.dismiss();
}
}
}.start();
}
public void testPost2(View v){
final ProgressDialog dialog=ProgressDialog.show(this, null, "正在请求中...");
new Thread(){
public void run() {
String path="http://192.168.56.1:8080/Web_Server/index.jsp";
try {
//创建Client对象
HttpClient httpClient=new DefaultHttpClient();
//设置超时
HttpParams params=httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 5000);
//创建请求对象
HttpPost request=new HttpPost(path);
//设置请求体
List<BasicNameValuePair> parameters=new ArrayList<>();
parameters.add(new BasicNameValuePair("name", "tom4"));
parameters.add(new BasicNameValuePair("age", "14"));
HttpEntity entity=new UrlEncodedFormEntity(parameters);
request.setEntity(entity);
//执行请求对象
HttpResponse response=httpClient.execute(request);
int statusCode=response.getStatusLine().getStatusCode();
if (statusCode==200) {
//得到响应文本
HttpEntity entity2=response.getEntity();
final String result=EntityUtils.toString(entity2);
//在主线程更新ui
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText(result);
dialog.dismiss();
}
});
}
//断开连接
httpClient.getConnectionManager().shutdown();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
dialog.dismiss();
}
}
}.start();
}
public void get4(View v){
final ProgressDialog dialog=ProgressDialog.show(this, null, "正在请求中...");
String path="http://192.168.56.1:8080/Web_Server/index.jsp?name=tom&age=23";
StringRequest request=new StringRequest(path, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
tv.setText(response);
dialog.dismiss();
}
}, null);
//将请求添加到队列中
queue.add(request);
}
public void post4(View v){
final ProgressDialog dialog=ProgressDialog.show(this, null, "正在请求中...");
String path="http://192.168.56.1:8080/Web_Server/index.jsp";
StringRequest request=new StringRequest(Method.POST,path,new Response.Listener<String>() {
@Override
public void onResponse(String response) {
tv.setText(response);
dialog.dismiss();
}
}, null){
//通过重写方法--请求体
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> map=new HashMap<>();
map.put("name", "tom678");
map.put("age", "78");
return map;
}
};
queue.add(request);
}
}