折腾:
【未解决】OkHttp获取响应的body的字符串出错:Exception in thread “main” java.lang.IllegalStateException: closed
期间,发现OkHttp的设计很是垃圾啊,竟然response只能使用一次
导致:连debug打印了一下response,后续都无法继续使用body,以及body的string了。
看到很多提到了:interceptor
貌似可以一劳永逸实现复制一份,供后续使用。
所以去看看:
什么是interceptor
okhttp interceptor
竟然都没写,导入Interceptor的路径。。。真垃圾
好像是okhttp3下面的
果然是:
import okhttp3.Interceptor;
此处顺带也的确需要去实现log的Interceptor
此处先去解决log的问题:
【已解决】Java中好用的Log日志库
然后再去解决interceptor
【总结】
目前用:
import java.io.File; import java.io.IOException; import java.io.PrintWriter; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; import okhttp3.MediaType; import okhttp3.Interceptor; //import java.io.PrintWriter; //import PrintWriter; //import FileUtils; import org.pmw.tinylog.Logger; import org.pmw.tinylog.Level; import org.pmw.tinylog.Configurator; import org.pmw.tinylog.writers.ConsoleWriter; import org.pmw.tinylog.writers.FileWriter; //public static void saveStrToFile(fullFilePath, strToSave){ // //} //void saveStrToFile(fullFilePath, strToSave){ // //} class CrifanUtil { public static void initLogger(String logFilename){ System.out.println("logFilename=" + logFilename); FileWriter fileWriter = new FileWriter(logFilename); ConsoleWriter consoleWriter = new ConsoleWriter(); Level fileWriterLevel = Level.TRACE; // Level consoleWriterLevel = Level.DEBUG; Level consoleWriterLevel = Level.INFO; String consoleFormat = "{date:YYMMdd HH:mm:ss} {class}.{method} {{level}|min-size=8}: {message}"; String fileFormat = "{date:yyyyMMdd HH:mm:ss} [{thread}] {class}.{method} {{level}|min-size=8}: {message}"; Configurator.currentConfig() .writer(consoleWriter, consoleWriterLevel, consoleFormat) .addWriter(fileWriter, fileWriterLevel, fileFormat) .activate(); // Logger.trace("trace"); // Logger.debug("debug"); // Logger.info("info"); // Logger.warn("warn"); // Logger.error("error"); } } class LoggingInterceptor implements Interceptor { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); // logger.info(String.format("Sending request %s on %s%n%s", // request.url(), chain.connection(), request.headers())); Logger.info("Sending request url={} on connection={}, headers={}", request.url(), chain.connection(), request.headers()); Response response = chain.proceed(request); long t2 = System.nanoTime(); // logger.info(String.format("Received response for %s in %.1fms%n%s", // response.request().url(), (t2 - t1) / 1e6d, response.headers())); Logger.info("Received response for url={} in {}, headers={}", response.request().url(), (t2 - t1) / 1e6d, response.headers()); return response; } } class ResponseInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Response response = chain.proceed(chain.request()); ResponseBody body = response.body(); String bodyString = body.string(); MediaType contentType = body.contentType(); Logger.debug("Response={}", bodyString); return response.newBuilder().body(ResponseBody.create(contentType, bodyString)).build(); } } public class EmulateLoginBaidu { // OkHttpClient client = new OkHttpClient(); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new LoggingInterceptor()) .addInterceptor(new ResponseInterceptor()) .build(); String UserAgent_Mac_Chrome = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"; // ResponseBody run(String url) throws IOException { Response run(String url) throws IOException { Request request = new Request.Builder() .url(url) .header("User-Agent", UserAgent_Mac_Chrome) .header("Host", "www.baidu.com") .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8") .header("Accept-Encoding", "gzip, deflate, br") .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8") .header("Cache-Control", "no-cache") .build(); try (Response response = client.newCall(request).execute()) { // return response.body().string(); // return response.body(); return response; } } public static void main(String[] args) throws IOException { String logFilename = "log/EmulateLoginBaidu.log"; CrifanUtil.initLogger(logFilename); Logger.info("logFilename={}", logFilename); Logger.info("Try Emulate Login Baidu"); String baiduUrl = "http://www.baidu.com"; // Logger.info("baiduUrl=%s", baiduUrl); Logger.info("baiduUrl={}", baiduUrl); EmulateLoginBaidu emulateLogin = new EmulateLoginBaidu(); // ResponseBody respBody = emulateLogin.run(baiduUrl); Response response = emulateLogin.run(baiduUrl); ResponseBody respBody = response.body(); String respBodyStr = respBody.string(); // String respBodyStr = response.body().string(); Logger.info("respBodyStr={}", respBodyStr); try (PrintWriter printWriter = new PrintWriter("debug/baidu_com.html")) { printWriter.println(respBodyStr); } } }
实现了:
先加log的:LoggingInterceptor
再加重新复制一个response的:ResponseInterceptor
然后最后再去调用
response.body().string()
就不会挂了。