面试题答案
一键面试性能优化方面
- 连接池复用:避免每次上传都创建新连接,提高连接利用率。
- 优化措施:使用
PoolingHttpClientConnectionManager
来管理连接池。 - 代码示例:
- 优化措施:使用
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(100);
cm.setDefaultMaxPerRoute(20);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
- 异步上传:利用异步操作,不阻塞主线程,提高整体吞吐量。
- 优化措施:使用
CloseableHttpAsyncClient
进行异步请求。 - 代码示例:
- 优化措施:使用
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
client.start();
HttpPost httpPost = new HttpPost("http://example.com/upload");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", new File("path/to/file"), ContentType.APPLICATION_OCTET_STREAM, "filename");
httpPost.setEntity(builder.build());
client.execute(httpPost, new FutureCallback<HttpResponse>() {
@Override
public void completed(HttpResponse result) {
// 处理响应
}
@Override
public void failed(Exception ex) {
// 处理异常
}
@Override
public void cancelled() {
// 处理取消
}
});
- 优化请求体构建:减少不必要的内存开销。
- 优化措施:使用
MultipartEntityBuilder
流式构建请求体,避免一次性加载整个文件到内存。 - 代码示例:
- 优化措施:使用
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", new File("path/to/file"), ContentType.APPLICATION_OCTET_STREAM, "filename");
httpPost.setEntity(builder.build());
安全策略方面
- HTTPS 连接:保证数据传输加密。
- 安全措施:使用支持HTTPS的HttpClient,配置SSL上下文。
- 代码示例:
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
try {
SSLContext sslContext = SSLContexts.createDefault();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
- 输入验证:防止恶意文件上传。
- 安全措施:在服务端对上传文件的大小、类型等进行验证。
- 代码示例:
import org.springframework.web.multipart.MultipartFile;
public boolean isValidFile(MultipartFile file) {
long maxSize = 10 * 1024 * 1024; // 10MB
if (file.getSize() > maxSize) {
return false;
}
String contentType = file.getContentType();
if (!contentType.startsWith("image/") &&!contentType.startsWith("application/pdf")) {
return false;
}
return true;
}
- 防止CSRF攻击:如果是Web应用,需防范CSRF。
- 安全措施:在客户端生成并在请求中携带CSRF令牌,服务端进行验证。
- 代码示例: 前端(JavaScript示例):
<input type="hidden" id="csrfToken" value="{{csrfToken}}">
<script>
var csrfToken = document.getElementById('csrfToken').value;
var formData = new FormData();
formData.append('_csrf', csrfToken);
formData.append('file', fileInput.files[0]);
fetch('http://example.com/upload', {
method: 'POST',
body: formData
});
</script>
后端(Spring示例):
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@RestController
@CrossOrigin
public class UploadController {
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam("_csrf") String csrfToken) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
CsrfToken csrf = attributes.getRequest().getAttribute(CsrfToken.class.getName());
if (csrf != null && csrfToken.equals(csrf.getToken())) {
// 处理文件上传
return "File uploaded successfully";
} else {
return "CSRF token validation failed";
}
}
}