折腾:
【未解决】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()
就不会挂了。