说明:
1、本系列博文是博主在学习传智播客Android培训视频的学习笔记
2、当然博文不只是罗列视频上讲的知识点,通过查阅资料对一些知识点进行了详细的讲解
3、由于是初学,难免有疏漏之处,还请不吝赐教
一、HTTP中POST和GET的区别
向WEB服务器提交数据,无外乎两种方式:POST和GET。那么这两种方式向服务器提交数据的区别有哪些呢?
1、GET将表单或者其他要传递的数据安装variable=value的形式,添加到Action所指向URL的后面,用?连接,而各个变量之间用&连接;POST是将数据以键值对的方式存放在HTTP包的包体中。
2、POST的安全性要比GET的安全性更高。比如通过GET方式提交数据,用户名和密码将以明文的方式出现在URL中,登录页面也可能被浏览器缓存,其他人通过查看历史记录就可以拿到你的账号和密码了。
3、GET传输的数据量小,主要是因为受URL长度限制,而POST可以传输大量的数据,所以在上传文件时最好使用POST。
4、GET限制Form表单的数据集的值必须为ASCII字符;而POST支持整个ISO10646字符集。默认是用ISO-8859-1编码。
二、通过HTTPWATCH可以直观的看到上面的区别
GET方式提交表单数据,如下:
POST方式提交表单数据(name为中文,编码已经转换),如下:
三、服务器端取得数据乱码的处理方式
服务端中文乱码的处理方式主要通过两个方面:1、添加过滤器处理编码问题,2、tomcat(或者其他web服务器)更改默认编码。以下是servlet过滤器源码:EncodingFilter.java(过滤器)和EncodingRequestWrapper.java(编码转换处理程序)
publicclassEncodingFilterimplementsFilter {
publicvoiddoFilter(ServletRequest request, ServletResponse response, FilterChain chain)throwsIOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if("GET".equals(req.getMethod())){
EncodingRequestWrapper wrapper = newEncodingRequestWrapper(req);
chain.doFilter(wrapper, response);
}else{
req.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
}
}
publicclassEncodingRequestWrapperextendsHttpServletRequestWrapper {
privateHttpServletRequest request;
publicEncodingRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
/**
* 重写getParamter方法
*/
publicString getParameter(String name) {
String value = request.getParameter(name);
if(value!=null){
try{
//编码转换
value = newString(value.getBytes("ISO8859-1"),"UTF-8");
} catch(UnsupportedEncodingException e) {
e.printStackTrace();
}
}
returnvalue;
}
}
WEB端的配置web.xml增加filter,示例如下:
EncodingFilter
EncodingFilter
cn.itcast.filter.EncodingFilter
EncodingFilter
/*
四、Android应用客户端向WEB服务端提交数据的4中方式
示例代码中包含开源组件httpclient向服务器传递数据时的POST和GET方式提交,如果不包含对session和cookie等操作,纯粹是向WEB服务端传递数据,那么建议直接采用POST和GET提交,不建议使用httpclient。示例代码:
/**
* Android中向web服务器提交数据的两种方式四种方法
*/
publicclassSubmitDataByHttpClientAndOrdinaryWay {
/**
* 使用get请求以普通方式提交数据
* @param map 传递进来的数据,以map的形式进行了封装
* @param path 要求服务器servlet的地址
* @return 返回的boolean类型的参数
* @throws Exception
*/
publicBoolean submitDataByDoGet(Map map, String path)throwsException {
// 拼凑出请求地址
StringBuilder sb = newStringBuilder(path);
sb.append("?");
for(Map.Entry entry : map.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue());
sb.append("&");
}
sb.deleteCharAt(sb.length() - 1);
String str = sb.toString();
System.out.println(str);
URL Url = newURL(str);
HttpURLConnection HttpConn = (HttpURLConnection) Url.openConnection();
HttpConn.setRequestMethod("GET");
HttpConn.setReadTimeout(5000);
// GET方式的请求不用设置什么DoOutPut()之类的吗?
if(HttpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
returntrue;
}
returnfalse;
}
/**
* 普通方式的DoPost请求提交数据
* @param map 传递进来的数据,以map的形式进行了封装
* @param path 要求服务器servlet的地址
* @return 返回的boolean类型的参数
* @throws Exception
*/
publicBoolean submitDataByDoPost(Map map, String path)throwsException {
// 注意Post地址中是不带参数的,所以newURL的时候要注意不能加上后面的参数
URL Url = newURL(path);
// Post方式提交的时候参数和URL是分开提交的,参数形式是这样子的:name=y&age=6
StringBuilder sb = newStringBuilder();
// sb.append("?");
for(Map.Entry entry : map.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue());
sb.append("&");
}
sb.deleteCharAt(sb.length() - 1);
String str = sb.toString();
HttpURLConnection HttpConn = (HttpURLConnection) Url.openConnection();
HttpConn.setRequestMethod("POST");
HttpConn.setReadTimeout(5000);
HttpConn.setDoOutput(true);
HttpConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
HttpConn.setRequestProperty("Content-Length", String.valueOf(str.getBytes().length));
OutputStream os = HttpConn.getOutputStream();
os.write(str.getBytes());
if(HttpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
returntrue;
}
returnfalse;
}
/**
* 以HttpClient的DoGet方式向服务器发送请数据
* @param map 传递进来的数据,以map的形式进行了封装
* @param path 要求服务器servlet的地址
* @return 返回的boolean类型的参数
* @throws Exception
*/
publicBoolean submitDataByHttpClientDoGet(Map map, String path)throwsException {
HttpClient hc = newDefaultHttpClient();
// 请求路径
StringBuilder sb = newStringBuilder(path);
sb.append("?");
for(Map.Entry entry : map.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue());
sb.append("&");
}
sb.deleteCharAt(sb.length() - 1);
String str = sb.toString();
System.out.println(str);
HttpGet request = newHttpGet(sb.toString());
HttpResponse response = hc.execute(request);
if(response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
returntrue;
}
returnfalse;
}
/**
* 以HttpClient的DoPost方式提交数据到服务器
* @param map 传递进来的数据,以map的形式进行了封装
* @param path 要求服务器servlet的地址
* @return 返回的boolean类型的参数
* @throws Exception
*/
publicBoolean submintDataByHttpClientDoPost(Map map, String path)throwsException {
// 1. 获得一个相当于浏览器对象HttpClient,使用这个接口的实现类来创建对象,DefaultHttpClient
HttpClient hc = newDefaultHttpClient();
// DoPost方式请求的时候设置请求,关键是路径
HttpPost request = newHttpPost(path);
// 2. 为请求设置请求参数,也即是将要上传到web服务器上的参数
List parameters = newArrayList();
for(Map.Entry entry : map.entrySet()) {
NameValuePair nameValuePairs = newBasicNameValuePair(entry.getKey(), entry.getValue());
parameters.add(nameValuePairs);
}
// 请求实体HttpEntity也是一个接口,我们用它的实现类UrlEncodedFormEntity来创建对象,注意后面一个String类型的参数是用来指定编码的
HttpEntity entity = newUrlEncodedFormEntity(parameters,"UTF-8");
request.setEntity(entity);
// 3. 执行请求
HttpResponse response = hc.execute(request);
// 4. 通过返回码来判断请求成功与否
if(response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
returntrue;
}
returnfalse;
}
}