问题描述
我们尝试像 Java 那样,将「对象保存到文件中,并从文件中恢复」,但是产生这会产生异常:
Caught: java.lang.ClassNotFoundException: org.openqa.selenium.Cookie java.lang.ClassNotFoundException: org.openqa.selenium.Cookieat java_io_ObjectInput$readObject.call(Unknown Source)at org.d3rm.toolbox.wordpress.CsdnSeleniumCommand.cookieReadFromFile(CsdnSeleniumCommand.groovy:238)at org.d3rm.toolbox.wordpress.CsdnSeleniumCommand.actionPublishPost(CsdnSeleniumCommand.groovy:112)at org.d3rm.toolbox.wordpress.CsdnSeleniumCommand$actionPublishPost$0.call(Unknown Source)at org.d3rm.toolbox.wordpress.CsdnSeleniumCommand.main(CsdnSeleniumCommand.groovy:61)
我们场景是在 Jenkins Pipeline 中使用 Groovy 语言调用 Selenium Java 绑定。按照「对象保存到文件中,并从文件中恢复」方法将 Cookie 对象保存到文件,然后下次再将 Cookie 对象恢复,以保存登录状态。但是会出现上述错误。
问题原因
问题的原因和解决在 [GROOVY-1627] Deserialization fails to work - ASF JIRA 中已经给出
# 调侃 # 混乱才是常态……不好用?造就造一个……还不好用?那就再造一个……最后这些东西盘根错节,相互影响。
解决办法
解决办法自然有很多(我们知道的,我们不知道的),这里只介绍两种我们知道的方法
第一种、使用 Groovy IO 类库
我们的任何问题都可以通过第三方库解决,这次我们使用 Groovy IO 类库,这里只记录核心代码,关键部分建议参考官方文档:
jdereg/groovy-io: Perfect Groovy serialization to and from JSON format.
Maven Repository: com.cedarsoftware ? groovy-io ? 1.1.1
@Grab(group='com.cedarsoftware', module='groovy-io', version='1.1.1')// 将对象写入文件 Set<Cookie> cookies = webDriver.manage().getCookies() String jsonstrFoo = GroovyJsonWriter.objectToJson(cookies) // 转 JSON 字符串 new File("/path/to/cookies.json").write(jsonstrFoo) // 将 JSON 字符串写入文件// 从文件读取对象 InputStream inputStream = new File("/path/to/cookies.json").newInputStream() GroovyJsonReader gjr = new GroovyJsonReader(inputStream) Set<Cookie> cookies = (Set<Cookie>)gjr.readObject()
第二种、搞定类加载器的问题
这种方法属于解决问题的方法,而前者属于寻找替代方案
[GROOVY-1627] Deserialization fails to work - ASF JIRA
// 将对象写入文件 Set<Cookie> cookies = webDriver.manage().getCookies() ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("/path/to/cookies.bin")); objectOutputStream.writeObject(cookies);// 从文件中读取 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/path/to/cookies.bin")) {protected Class resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {return Class.forName(objectStreamClass.getName(), true, getClass().classLoader);} } Set<Cookie> cookies = (Set<Cookie>) ois.readObject();
我们的场景决定我们会选择这种解决方法。1)我们的程序运行在 Jenkins Pipeline 中,引入过多的类库需要面临版本冲突问题。2)引入过多的类库还要解决网络问题。当然可以根据自己的场景选择合适的解决方案。
参考文献
K4NZ / 将对象保存到文件,以及读取文件中对象
java - Groovy serialization without class definition - Stack Overflow
[GROOVY-1627] Deserialization fails to work - ASF JIRA
java - Groovy serialization without class definition - Stack Overflow