android 登录Javaeye(使用HttpURLConnection和HttpClient)

之前在网上看过好多人用java写登录网站,这次正好学习android,自己写实习一个,就拿经常登录的javaeye(现在叫iteye,已经是csdn的了)试一下。

先来分析javaeye登录界面


查看源文件

  1. <formaction="/login"id="login_form"method="post"><tableborder="0"cellspacing="0"cellpadding="0"class="table_1">
  2. <colgroup><colwidth="60"/><col/></colgroup>
  3. <tr>
  4. <th>账号</th>
  5. <td>
  6. <inputclass="input_1required"id="user_name"name="name"placeholder="用户名或邮箱"tabindex="1"type="text"value=""/>
  7. </td>
  8. </tr>
  9. <tr>
  10. <th>密码</th>
  11. <td>
  12. <inputclass="input_1required"id="password"name="password"tabindex="2"type="password"value=""/></td>
  13. </tr>
  14. <tr>
  15. <th></th>
  16. <td>
  17. <inputid="auto"name="remember_me"tabindex="3"type="checkbox"value="1"/>
  18. <labelfor="auto">下次自动登录</label>
  19. <ahref="/users/forget">忘记密码?</a>
  20. </td>
  21. </tr>
  22. <tr>
  23. <th></th>
  24. <td><inputtype="submit"name="button"id="button"value="登 录"class="btn_1submit"tabindex="4"/></td>
  25. </tr>
  26. </table>
  27. </form>

可以分析出post地址为http://www.iteye.com/login,账号是name、密码是password。

登录以后,使用chrome的开发人员工具(其他浏览器也有相关工具,我就不一一说了)拦截获取响应消息


可以看出返回的是302地址重定向


还需要注意的是每次提交时,不能遗漏的cookie即seesion_id ,javaeye用的是_javaeye3_session

接下来是我做的android的例子,使用webview控件,它只负责内容展现,请求响应我分别使用了HttpURLConnection和HttpClient。

不说了,上代码:

主布局main.xml代码如下:

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/RelativeLayout1"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:orientation="vertical">
  7. <TextView
  8. android:id="@+id/textViewInfo"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:layout_alignParentLeft="true"
  12. android:layout_alignParentTop="true"/>
  13. <WebView
  14. android:id="@+id/webViewInfo"
  15. android:layout_width="match_parent"
  16. android:layout_height="260dp"
  17. android:layout_below="@+id/textViewInfo"
  18. android:layout_marginTop="30dp"
  19. android:layout_alignParentLeft="true"/>
  20. <LinearLayout
  21. android:id="@+id/linearLayout2"
  22. android:layout_width="wrap_content"
  23. android:layout_height="wrap_content"
  24. android:layout_above="@+id/linearLayout1"
  25. android:layout_alignParentLeft="true">
  26. <TextView
  27. android:id="@+id/textView2"
  28. android:layout_width="wrap_content"
  29. android:layout_height="wrap_content"
  30. android:text="使用Java"/>
  31. <Button
  32. android:id="@+id/buttonJavaLogin"
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:layout_toRightOf="@+id/textView2"
  36. android:text="登录ITeye"/>
  37. <Button
  38. android:id="@+id/buttonJavaMyMessage"
  39. android:layout_width="wrap_content"
  40. android:layout_height="wrap_content"
  41. android:layout_toRightOf="@+id/buttonJavaLogin"
  42. android:text="ITeye收件箱"/>
  43. </LinearLayout>
  44. <LinearLayout
  45. android:id="@+id/linearLayout1"
  46. android:layout_width="wrap_content"
  47. android:layout_height="wrap_content"
  48. android:layout_alignParentBottom="true"
  49. android:layout_alignParentLeft="true">
  50. <TextView
  51. android:id="@+id/textView1"
  52. android:layout_width="wrap_content"
  53. android:layout_height="wrap_content"
  54. android:text="使用Apache"/>
  55. <Button
  56. android:id="@+id/buttonApacheLogin"
  57. android:layout_width="wrap_content"
  58. android:layout_height="wrap_content"
  59. android:layout_toRightOf="@+id/textView1"
  60. android:text="登录ITeye"/>
  61. <Button
  62. android:id="@+id/buttonApacheMyMessage"
  63. android:layout_width="wrap_content"
  64. android:layout_height="wrap_content"
  65. android:layout_toRightOf="@+id/buttonApacheLogin"
  66. android:text="ITeye收件箱"/>
  67. </LinearLayout>
  68. </RelativeLayout>

登录对话框布局login.xml代码如下:

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <LinearLayout
  7. android:id="@+id/linearLayout1"
  8. android:layout_width="match_parent"
  9. android:layout_height="wrap_content">
  10. <TextView
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:text="账号:"/>
  14. <EditText
  15. android:id="@+id/editTextUsername"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:layout_weight="1"/>
  19. </LinearLayout>
  20. <LinearLayout
  21. android:id="@+id/linearLayout2"
  22. android:layout_width="match_parent"
  23. android:layout_height="wrap_content">
  24. <TextView
  25. android:layout_width="wrap_content"
  26. android:layout_height="wrap_content"
  27. android:text="密码:"/>
  28. <EditText
  29. android:id="@+id/exitTextPassword"
  30. android:layout_width="wrap_content"
  31. android:layout_height="wrap_content"
  32. android:layout_weight="1"
  33. android:inputType="textPassword"/>
  34. </LinearLayout>
  35. </LinearLayout>

AndroidManifest.xml不要忘了加如下代码:

  1. <uses-permissionandroid:name="android.permission.INTERNET"/>

主程序代码如下:

  1. packagecom.zhang.test08_16;
  2. importjava.io.BufferedInputStream;
  3. importjava.io.BufferedOutputStream;
  4. importjava.io.BufferedReader;
  5. importjava.io.IOException;
  6. importjava.io.InputStream;
  7. importjava.io.InputStreamReader;
  8. importjava.io.OutputStream;
  9. importjava.io.OutputStreamWriter;
  10. importjava.io.UnsupportedEncodingException;
  11. importjava.io.Writer;
  12. importjava.net.HttpURLConnection;
  13. importjava.net.MalformedURLException;
  14. importjava.net.ProtocolException;
  15. importjava.net.URL;
  16. importjava.util.ArrayList;
  17. importjava.util.List;
  18. importorg.apache.http.HttpEntity;
  19. importorg.apache.http.HttpResponse;
  20. importorg.apache.http.HttpStatus;
  21. importorg.apache.http.NameValuePair;
  22. importorg.apache.http.client.ClientProtocolException;
  23. importorg.apache.http.client.entity.UrlEncodedFormEntity;
  24. importorg.apache.http.client.methods.HttpGet;
  25. importorg.apache.http.client.methods.HttpPost;
  26. importorg.apache.http.client.methods.HttpUriRequest;
  27. importorg.apache.http.impl.client.DefaultHttpClient;
  28. importorg.apache.http.message.BasicNameValuePair;
  29. importorg.apache.http.params.CoreProtocolPNames;
  30. importorg.apache.http.params.HttpParams;
  31. importorg.apache.http.protocol.HTTP;
  32. importorg.apache.http.util.EntityUtils;
  33. importandroid.app.Activity;
  34. importandroid.app.AlertDialog;
  35. importandroid.content.DialogInterface;
  36. importandroid.os.Bundle;
  37. importandroid.view.LayoutInflater;
  38. importandroid.view.View;
  39. importandroid.webkit.WebView;
  40. importandroid.widget.Button;
  41. importandroid.widget.EditText;
  42. importandroid.widget.TextView;
  43. publicclassTest08_16ActivityextendsActivity{
  44. privateTextViewtextViewInfo;
  45. privateWebViewwebViewInfo;
  46. privateButtonbuttonJavaLogin;
  47. privateButtonbuttonJavaMyMessage;
  48. privateButtonbuttonApaceLogin;
  49. privateButtonbuttonApacheMyMessage;
  50. privateViewloginView;
  51. privateAlertDialogloginDialog;
  52. privateEditTexteditTextUserName;
  53. privateEditTexteditTextPassword;
  54. privateStringclientType;
  55. privateDefaultHttpClientclient;
  56. privateStringcookie;
  57. privatestaticfinalStringLOGIN_URL="http://www.iteye.com/login";
  58. privatestaticfinalStringMESSAGE_URL="http://app.iteye.com/messages";
  59. @Override
  60. publicvoidonCreate(BundlesavedInstanceState){
  61. super.onCreate(savedInstanceState);
  62. setContentView(R.layout.main);
  63. textViewInfo=(TextView)findViewById(R.id.textViewInfo);
  64. webViewInfo=(WebView)findViewById(R.id.webViewInfo);
  65. buttonJavaLogin=(Button)findViewById(R.id.buttonJavaLogin);
  66. buttonJavaMyMessage=(Button)findViewById(R.id.buttonJavaMyMessage);
  67. buttonApaceLogin=(Button)findViewById(R.id.buttonApacheLogin);
  68. buttonApacheMyMessage=(Button)findViewById(R.id.buttonApacheMyMessage);
  69. LayoutInflaterinflater=LayoutInflater.from(this);
  70. loginView=inflater.inflate(R.layout.login,null);
  71. editTextUserName=(EditText)loginView.findViewById(R.id.editTextUsername);
  72. editTextPassword=(EditText)loginView.findViewById(R.id.exitTextPassword);
  73. loginDialog=getLoginDialog();
  74. buttonJavaLogin.setOnClickListener(newView.OnClickListener(){
  75. @Override
  76. publicvoidonClick(Viewv){
  77. clientType="java";
  78. loginDialog.show();
  79. }
  80. });
  81. buttonJavaMyMessage.setOnClickListener(newView.OnClickListener(){
  82. @Override
  83. publicvoidonClick(Viewv){
  84. showMyMessageJava();
  85. }
  86. });
  87. buttonApaceLogin.setOnClickListener(newView.OnClickListener(){
  88. @Override
  89. publicvoidonClick(Viewv){
  90. clientType="apache";
  91. loginDialog.show();
  92. }
  93. });
  94. buttonApacheMyMessage.setOnClickListener(newView.OnClickListener(){
  95. @Override
  96. publicvoidonClick(Viewv){
  97. showMyMessageApache();
  98. }
  99. });
  100. }
  101. @Override
  102. protectedvoidonResume(){
  103. client=newDefaultHttpClient();//client.getCookieStore().getCookies()session_id
  104. HttpParamshttpParams=client.getParams();
  105. httpParams.setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,false);
  106. super.onResume();
  107. }
  108. @Override
  109. protectedvoidonPause(){
  110. client.getConnectionManager().shutdown();
  111. super.onPause();
  112. }
  113. privateAlertDialoggetLoginDialog(){
  114. returnnewAlertDialog.Builder(Test08_16Activity.this)
  115. .setTitle("登录")
  116. .setView(loginView)
  117. .setPositiveButton("登录",newDialogInterface.OnClickListener(){
  118. @Override
  119. publicvoidonClick(DialogInterfacedialog,intwhich){
  120. if(clientType.equals("apache")){
  121. loginApache();
  122. }elseif(clientType.equals("java")){
  123. loginJava();
  124. }
  125. }
  126. })
  127. .setNegativeButton("取消",newDialogInterface.OnClickListener(){
  128. @Override
  129. publicvoidonClick(DialogInterfacedialog,intwhich){
  130. }
  131. })
  132. .create();
  133. }
  134. privatevoidloginJava(){
  135. Stringusername=editTextUserName.getText().toString();
  136. Stringpassword=editTextPassword.getText().toString();
  137. URLurl=null;
  138. try{
  139. url=newURL(LOGIN_URL);
  140. }catch(MalformedURLExceptione){
  141. }
  142. HttpURLConnectionurlConnection=null;
  143. try{
  144. urlConnection=(HttpURLConnection)url.openConnection();
  145. }catch(IOExceptione){
  146. textViewInfo.setText(e.getMessage());
  147. return;
  148. }
  149. try{
  150. urlConnection.setRequestMethod("POST");
  151. }catch(ProtocolExceptione){
  152. }
  153. urlConnection.setDoOutput(true);
  154. urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
  155. urlConnection.setRequestProperty("Connection","keep-alive");
  156. urlConnection.setInstanceFollowRedirects(false);//
  157. OutputStreamout=null;
  158. try{
  159. out=newBufferedOutputStream(urlConnection.getOutputStream());//请求
  160. }catch(IOExceptione){
  161. urlConnection.disconnect();
  162. textViewInfo.setText(e.getMessage());
  163. return;
  164. }
  165. Writerwriter=null;
  166. try{
  167. writer=newOutputStreamWriter(out,"UTF-8");
  168. }catch(UnsupportedEncodingExceptione1){
  169. }
  170. try{
  171. writer.write("name="+username+"&password="+password);
  172. }catch(IOExceptione){
  173. urlConnection.disconnect();
  174. textViewInfo.setText(e.getMessage());
  175. return;
  176. }finally{
  177. try{
  178. writer.flush();
  179. writer.close();
  180. }catch(IOExceptione){
  181. }
  182. }
  183. getResponseJava(urlConnection);
  184. }
  185. privatevoidshowMyMessageJava(){
  186. URLurl=null;
  187. try{
  188. url=newURL(MESSAGE_URL);
  189. }catch(MalformedURLExceptione){
  190. }
  191. HttpURLConnectionurlConnection=null;
  192. try{
  193. urlConnection=(HttpURLConnection)url.openConnection();
  194. }catch(IOExceptione){
  195. textViewInfo.setText(e.getMessage());
  196. return;
  197. }
  198. //methodThedefaultvalueis"GET"
  199. getResponseJava(urlConnection);
  200. }
  201. //共用HttpClient
  202. privatevoidloginApache(){
  203. Stringusername=editTextUserName.getText().toString();
  204. Stringpassword=editTextPassword.getText().toString();
  205. List<NameValuePair>params=newArrayList<NameValuePair>(1);
  206. params.add(newBasicNameValuePair("name",username));
  207. params.add(newBasicNameValuePair("password",password));
  208. HttpEntityformEntity=null;
  209. try{
  210. formEntity=newUrlEncodedFormEntity(params,HTTP.UTF_8);
  211. }catch(UnsupportedEncodingExceptione){
  212. }
  213. HttpPostrequest=newHttpPost(LOGIN_URL);
  214. request.setEntity(formEntity);
  215. getResponseApache(request);
  216. }
  217. privatevoidshowMyMessageApache(){
  218. HttpGetrequest=newHttpGet(MESSAGE_URL);
  219. getResponseApache(request);
  220. }
  221. privatevoidgetResponseJava(HttpURLConnectionurlConnection){
  222. if(cookie!=null){//session_id
  223. urlConnection.setRequestProperty("Cookie",cookie);
  224. }
  225. InputStreamin=null;
  226. try{
  227. in=newBufferedInputStream(urlConnection.getInputStream());//响应
  228. }catch(IOExceptione){
  229. urlConnection.disconnect();
  230. textViewInfo.setText(e.getMessage());
  231. return;
  232. }
  233. cookie=urlConnection.getHeaderField("Set-Cookie");//session_id
  234. intresponseCode=-1;
  235. try{
  236. responseCode=urlConnection.getResponseCode();
  237. }catch(IOExceptione){
  238. urlConnection.disconnect();
  239. textViewInfo.setText(e.getMessage());
  240. return;
  241. }
  242. if(responseCode==301||responseCode==302||responseCode==307){//重定向
  243. Stringlocation=urlConnection.getHeaderField("location");
  244. URLurl=null;
  245. try{
  246. url=newURL(location);
  247. }catch(MalformedURLExceptione){
  248. }
  249. HttpURLConnectionurlConnectionRedirect=null;
  250. try{
  251. urlConnectionRedirect=(HttpURLConnection)url.openConnection();
  252. }catch(IOExceptione){
  253. textViewInfo.setText(e.getMessage());
  254. return;
  255. }
  256. getResponseJava(urlConnectionRedirect);
  257. return;
  258. }
  259. BufferedReaderreader=null;
  260. try{
  261. reader=newBufferedReader(newInputStreamReader(in,"UTF-8"));
  262. }catch(UnsupportedEncodingExceptione1){
  263. }
  264. StringBuilderresult=newStringBuilder();
  265. Stringtmp=null;
  266. try{
  267. while((tmp=reader.readLine())!=null){
  268. result.append(tmp);
  269. }
  270. }catch(IOExceptione){
  271. textViewInfo.setText(e.getMessage());
  272. return;
  273. }finally{
  274. try{
  275. reader.close();
  276. urlConnection.disconnect();
  277. }catch(IOExceptione){
  278. }
  279. }
  280. webViewInfo.loadDataWithBaseURL(null,result.toString(),"text/html","UTF-8",null);
  281. }
  282. privatevoidgetResponseApache(HttpUriRequestrequest){
  283. HttpResponseresponse=null;
  284. try{
  285. response=client.execute(request);//重定向RedirectStrategyexecutewhile(!done)
  286. }catch(ClientProtocolExceptione){
  287. textViewInfo.setText(e.getMessage());
  288. }catch(IOExceptione){
  289. textViewInfo.setText(e.getMessage());
  290. }
  291. if(response==null){
  292. return;
  293. }
  294. if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){
  295. textViewInfo.setText("errorresponse"+response.getStatusLine().toString());
  296. return;
  297. }
  298. Stringresult=null;
  299. try{
  300. result=EntityUtils.toString(response.getEntity(),"UTF-8");
  301. }catch(Exceptione){
  302. textViewInfo.setText("errorresponse"+response.getStatusLine().toString());
  303. return;
  304. }
  305. webViewInfo.loadDataWithBaseURL(null,result,"text/html","UTF-8",null);
  306. }
  307. }

看看运行效果:

主界面:


点击 使用java登录iteye,弹出登录对话框:


输入javaeye的账号和密码,点击登录(有点慢,耐心等待),结果如下:


登录成功了,点击 iteye收件箱(相当于在浏览器里点击收件箱),验证是同一session


成功,代码没有问题。

使用Apache的方式结果一样,我就不截图了。

做这个例子,我是想了解http协议,httpclient内部实现原理。写的过程中参照如下:

seesion问题:http://hi.baidu.com/%CE%A4%D7%D4%C9%FD/blog/item/e2ce0004f52f2c61030881fa.html

http://helin.iteye.com/blog/257115

302重定向:http://blog.csdn.net/hegch/article/details/1891146

http 417 :http://blog.yes2.me/archives/915

webview乱码:http://hongyang321.iteye.com/blog/1021564

接下来分析一下代码:

先分析java部分,代码和我上篇博客node.js+android http请求响应基本很像,关键的不同

1.解决session的代码:

  1. privateStringcookie;
  2. if(cookie!=null){//session_id
  3. urlConnection.setRequestProperty("Cookie",cookie);
  4. }
  5. cookie=urlConnection.getHeaderField("Set-Cookie");//session_id

共享cookie,获取响应前查看是否有cookie,如果有则放在请求头上,获取响应后,拿到cookie存下来。

2.解决重定向的代码:

  1. if(responseCode==301||responseCode==302||responseCode==307){//重定向
  2. Stringlocation=urlConnection.getHeaderField("location");
  3. URLurl=null;
  4. try{
  5. url=newURL(location);
  6. }catch(MalformedURLExceptione){
  7. }
  8. HttpURLConnectionurlConnectionRedirect=null;
  9. try{
  10. urlConnectionRedirect=(HttpURLConnection)url.openConnection();
  11. }catch(IOExceptione){
  12. textViewInfo.setText(e.getMessage());
  13. return;
  14. }
  15. getResponseJava(urlConnectionRedirect);
  16. return;
  17. }
查看响应代码是否需要重定向,如果是读出响应头上的location,发出get请求,递归调用。

再来分析一下httpclient部分:

1.解决407 error

  1. HttpParamshttpParams=client.getParams();
  2. httpParams.setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,false);

2.解决session

  1. privateDefaultHttpClientclient;

共用一个client就可以了,cookie存在这client.getCookieStore().getCookies(), 和我们使用一个浏览器,多个标签页共享session原理一样。

3.解决重定向

没有附加任何代码,httpclient内部已经实现,源码主要部分如下:

  1. classAbstractHttpClient
  2. publicfinalHttpResponseexecute(HttpUriRequestrequest)
  3. throwsIOException,ClientProtocolException{
  4. returnexecute(request,(HttpContext)null);
  5. }
  6. publicfinalHttpResponseexecute(HttpHosttarget,HttpRequestrequest,
  7. HttpContextcontext)
  8. RequestDirectordirector=null;
  9. director=createClientRequestDirectorreturnnewDefaultRequestDirector
  10. returndirector.execute(target,request,execContext);
  11. classDefaultRequestDirector
  12. publicHttpResponseexecute(HttpHosttarget,HttpRequestrequest,
  13. HttpContextcontext)
  14. while(!done){
  15. RoutedRequestfollowup=handleResponse(roureq,response,context);
  16. if(followup==null){
  17. done=true;
  18. }else{
  19. protectedRoutedRequesthandleResponse(RoutedRequestroureq,
  20. HttpResponseresponse,
  21. HttpContextcontext)
  22. if(HttpClientParams.isRedirecting(params)&&
  23. this.redirectStrategy.isRedirected(request,response,context)){
  24. classDefaultRedirectStrategy
  25. publicbooleanisRedirected(
  26. finalHttpRequestrequest,
  27. finalHttpResponseresponse,
  28. finalHttpContextcontext)
  29. intstatusCode=response.getStatusLine().getStatusCode();
  30. Stringmethod=request.getRequestLine().getMethod();
  31. HeaderlocationHeader=response.getFirstHeader("location");
  32. switch(statusCode){
  33. caseHttpStatus.SC_MOVED_TEMPORARILY:
  34. return(method.equalsIgnoreCase(HttpGet.METHOD_NAME)
  35. ||method.equalsIgnoreCase(HttpHead.METHOD_NAME))&&locationHeader!=null;
  36. caseHttpStatus.SC_MOVED_PERMANENTLY:
  37. caseHttpStatus.SC_TEMPORARY_REDIRECT:
  38. returnmethod.equalsIgnoreCase(HttpGet.METHOD_NAME)
  39. ||method.equalsIgnoreCase(HttpHead.METHOD_NAME);
  40. caseHttpStatus.SC_SEE_OTHER:
  41. returntrue;
  42. default:
  43. returnfalse;
  44. }//endofswitch

处理方法基本和我的一样,除了对象封装意外,它使用的条件循环while (!done) ,我使用的是条件递归。

ps:使用windows7以后,根据内容找文件很蛋疼,推荐大家使用UltraFileSearch 官网http://www.ultrafilesearch.com/,不是广告,只是用了这么多搜索替代工具以后,觉得最好的一个,和大家分享一下

敲了半天怪累的,就说到这了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值