面试题答案
一键面试1. 连接管理
- 使用连接池:在高并发场景下,频繁创建和销毁HTTP连接开销很大。通过使用连接池,可以复用现有的连接,减少连接建立的时间。在Java中,可以使用Apache HttpClient库的
PoolingHttpClientConnectionManager
来实现连接池。
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
public class HttpConnectionPoolExample {
private static final PoolingHttpClientConnectionManager cm;
private static final CloseableHttpClient httpClient;
static {
cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(100);
cm.setDefaultMaxPerRoute(20);
httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
}
public static CloseableHttpClient getHttpClient() {
return httpClient;
}
}
然后在发起请求时使用这个httpClient
:
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
public class HttpRequestExample {
public static void main(String[] args) throws Exception {
CloseableHttpClient httpClient = HttpConnectionPoolExample.getHttpClient();
HttpGet httpGet = new HttpGet("http://example.com/api");
HttpResponse response = httpClient.execute(httpGet);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println(responseBody);
}
}
2. 缓存策略
- 客户端缓存:对于一些不经常变化的数据,可以在客户端进行缓存。在Java中,可以使用
Guava Cache
来实现简单的本地缓存。
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
public class HttpCacheExample {
private static final Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
public static String getFromCacheOrFetch(String url) {
String result = cache.getIfPresent(url);
if (result != null) {
return result;
}
// 实际发起HTTP请求获取数据
String data = fetchDataFromHttp(url);
cache.put(url, data);
return data;
}
private static String fetchDataFromHttp(String url) {
// 这里实现实际的HTTP请求逻辑
return "example data";
}
}
在需要发起HTTP请求时调用getFromCacheOrFetch
方法:
public class Main {
public static void main(String[] args) {
String result = HttpCacheExample.getFromCacheOrFetch("http://example.com/api");
System.out.println(result);
}
}
3. 优化请求头
- 压缩:启用HTTP压缩可以减少数据传输量。在Apache HttpClient中,可以通过在请求头中设置
Accept-Encoding: gzip, deflate
来表明支持压缩。
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpCompressionExample {
public static void main(String[] args) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://example.com/api");
httpGet.addHeader("Accept-Encoding", "gzip, deflate");
HttpResponse response = httpClient.execute(httpGet);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println(responseBody);
}
}
4. 异步请求
- 使用异步库:在Java 8及以上版本,可以使用
CompletableFuture
结合HttpClient
(Java 11的java.net.http.HttpClient
)来实现异步HTTP请求,提高系统的并发处理能力。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class AsyncHttpRequestExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://example.com/api"))
.build();
CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
future.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
}
}