博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 实现类似于python requests包的Session类,自动管理cookie。
阅读量:7210 次
发布时间:2019-06-29

本文共 4445 字,大约阅读时间需要 14 分钟。

1、在py中requests.post()和get()函数都是在那个函数内部里面自动生成了一个Session类的实例,所以requests,post和get函数要想干登陆后才能干的事情,需要添加cookie或者把cookie写在headers里面,要想自动管理cookie,就不能每次请求都实例化一个新的Session类的对象了,需要直接实例化Session类,然后使用该实例,而不是使用那两个函数。

py的Session类的使用方法是:

ss = requests.Session()

ss.post(login_url,data = {"username":"xiaomin", "password":"123456"})

ss.get(some_url)

 

2、java的OkHttp3默认是不自动管理cookie。

 

默认是使用NIO_COOKIES

 

 

 3、实现cookie自动管理,需要在OkhttpClient类的Builder类中的cookieJar方法传入CookieJar实例。

 

 实现CookieJar接口中的saveFromResponse 和loadForRequest方法,把cookie保存到haspmap中,读取也是从hashmap中,这样就实现自动管理cookie。如果要保持代码重启还能持久化cookie管理可以使用redis  sqllite 或者实现Serializable,序列化cookie到文件。

okhttp3.internal.http.BridgeInterceptor; okhttp3.internal.http.HttpHeaders; 为什么实现了CookieJar这两个文件中会调用传进去的实例的这两个方法,根据了请求的url的域名,把cookie添加到request的header了,返回时候从header里面保存cookie,如果传的实例如果没有这两个方法那会运行出错。

 

 

 

 

package com.touna.httprequest;import java.text.MessageFormat;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Set;import java.util.regex.*;import okhttp3.Cookie;import okhttp3.CookieJar;import okhttp3.FormBody;import okhttp3.HttpUrl;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;import com.touna.view.LogUtil;public class Session {    private final OkHttpClient mOkHttpClient = new OkHttpClient.Builder().cookieJar(new CookieJarManager()).build();     //如果直接写个类,里面写saveFromResponse和loadForRequest,而不实现CookieJar接口,运行可以正常通过,但ide会显红,因为Bulider类的cookieJsr方法需要接受CookieJar类型的实例。鸭子类除了能节约代码行数,在可理解性 可读性 多人合作性上面都不如接口规范,谁知道鸭子类里面要写什么方法,除了写代码得人自己。    private class CookieJarManager implements CookieJar{        private final HashMap
> cookieStore = new HashMap<>(); @Override public void saveFromResponse(HttpUrl url, List
cookies) { cookieStore.put(url.host(), cookies); } @Override public List
loadForRequest(HttpUrl url) { List
cookies = cookieStore.get(url.host()); return cookies != null ? cookies : new ArrayList
(){}; } } /** * @param url 要请求的url * @param paramsMap post的请求参数 * @return post的返回结果 */ public String post(String url, HashMap
paramsMap){ LogUtil.printLog("请求的url是:" + url); FormBody.Builder formBodyBuilder = new FormBody.Builder(); Set
keySet = paramsMap.keySet(); for(String key:keySet) { String value = paramsMap.get(key); formBodyBuilder.add(key,value); } FormBody formBody = formBodyBuilder.build(); Request request = new Request .Builder() .post(formBody) .url(url) .build(); try (Response response = mOkHttpClient.newCall(request).execute()) { String respStr = response.body().string(); LogUtil.printLog("返回是: " + respStr); return respStr; }catch (Exception e){ LogUtil.printLog("post失败"); e.printStackTrace(); return ""; } } public String get(String url) { final Request.Builder builder = new Request.Builder(); builder.url(url); final Request request = builder.build(); try (Response response = mOkHttpClient.newCall(request).execute()) { return response.body().string(); }catch (Exception e){ e.printStackTrace(); return ""; } } /** * @param mail163Account 163邮箱账号; * @param passwd 邮箱密码 * */ private static void test163(String mail163Account, String passwd){ String loginUrl = MessageFormat.format("https://mail.163.com/entry/cgi/ntesdoor?funcid=loginone&language=-1&passtype=1" + "&iframe=1&product=mail163&from=web&df=email163&race=-2_262_-2_hz&module=&uid={0}&style=-1&net=t&skinid=null",mail163Account); Session ss = new Session(); HashMap
paramsMap = new HashMap<>() ; paramsMap.put("username",mail163Account); paramsMap.put("url2","http://email.163.com/errorpage/error163.htm"); paramsMap.put("savalogin","0"); paramsMap.put("password",passwd); String respStr = ss.post(loginUrl,paramsMap); //登录 Pattern sidPattern = Pattern.compile("sid=(.*)&"); Matcher m = sidPattern.matcher(respStr); if (!m.find()){ LogUtil.printLog("登录失败"); }else{ String sid = m.group(1); LogUtil.printLog(sid); String mailListUrl = MessageFormat.format("https://mail.163.com/js6/s?sid={0}&func=mbox:listMessages",sid); HashMap
dataMap = new HashMap<>() ; dataMap.put("var","
1
date
true" + "
20
0
false
top
true
true
"); LogUtil.printLog("读取邮件列表:"); ss.post(mailListUrl,dataMap); } } public static void main(String[] args) { test163("13148804506@163.com", "123456"); }}

 

4、使用163邮箱登录,然后测试下获取邮件列表能否获取到。

测试结果,这样只要Session类的实例请求了登录接口后,就能干其他的事情了。

 

转载地址:http://dsrum.baihongyu.com/

你可能感兴趣的文章
在北京做Java开发如何月薪达到两万,需要技术水平达到什么程度?
查看>>
移动端适配之二:visual viewport、layout viewport和ideal viewport介绍
查看>>
python大佬养成计划----flask_sqlalchemy操作数据库
查看>>
Chrome开发者工具关于网络请求的一个隐藏技能
查看>>
Git入门与开发
查看>>
Java编程基础04——流程控制语句
查看>>
vue-threeJS数据驱动的三维图形可视化
查看>>
Ubuntu 18.04.1 搭建Java环境和HelloWorld
查看>>
Flutter 实现根据环境加载不同配置
查看>>
浏览器保存密码后自动填充问题
查看>>
前端每日实战:93# 视频演示如何用纯 CSS 创作一根闪电连接线
查看>>
PhpStorm升级后调用某些类提示phpstorm Unhandled exceptions
查看>>
Python 2.x 与 Python 3.x 的区别
查看>>
如何实现对tcl脚本的类GDB调试
查看>>
基于java的IO流的文件读取系统
查看>>
谈谈 Docker 网络
查看>>
laravel-admin集成ueditor编辑器的图片列表显示问题解决方法
查看>>
伪数组(ArrayLike)
查看>>
ES6精华:字符串扩展
查看>>
写在Flutter 1.0之前
查看>>