spring - Spring RestTemplate 似乎不是线程安全的 wrt 标头
问题描述
我有一个 Spring Web 客户端,它使用两个不同的基本身份验证用户发布到 Spring Web 服务器(相同的 URL)。这是一个已知问题,我不能同时使用一个RestTemplate
吗?
当我使用单个RestTemplate
并且请求几乎是同时的(在不同的线程中)时,尽管我在标头中指定了不同的用户,但接收服务器认为它们来自同一个用户!请注意,请求和标题(以及帖子的正文)是为每个请求新分配的。
它工作正常,当我使用单个RestTemplate
并synchronized()
在调用周围放置
response = RestTemplate.exchange(url, method, requestParams, MyResponse.class)
我还尝试创建两个RestTemplate
实例,每个用户一个 - (每个都用 构建RestTemplateBuilder
)也可以。我会保留这个解决方案,但令我惊讶的是它是必需的。
这是一个已知的问题?
(我看到stackOverflow回答说aRestTemplate
在构造后是线程安全的,但是标头是随请求传入的,而不是作为已经构造的设置RestTemplate
...)
====
这是 2 个不同调用的示例,使用 2 个不同的 RestTemplates,因为有时使用相同的方法会出现问题:
public OperationStatus getOpStatus(String gufi) {
HttpEntity<String> requestParams = new HttpEntity<>(Utils.createBasicHeader(cfg.getManager(), cfg.getManPass()));
ResponseEntity<OperationStatus> restResponse = null;
try {
restResponse = managerRestTemplate.exchange(
cfg.getNussOpApiPath(), HttpMethod.GET, requestParams, OperationStatus.class);
} catch (RestClientException e) {
...
}
OperationStatus opState = restResponse.getBody();
opState.setHttpStatusCode(String.valueOf(restResponse.getStatusCodeValue()));
return opState;
}
这里有个发帖的方法,使用优先级切换rest模板(当时目标服务器是通过用户的权限来识别优先级的)
UTMRestResponse doPost(Object objToSend, String url, String msg) throws IOException {
String user = cfg.getOpUser();
String pass = cfg.getOpPass();
RestTemplate restTemplate = opUserRestTemplate;
boolean isPriorityOp = false;
if ( objToSend instanceof OpPost) {
OpPost post = (OpPost) objToSend;
String flightNum = post.getFlightNumber();
isPriorityOp = Boolean.TRUE.equals(post.getPriorityOp()); // null is false
} else if ( objToSend instanceof PositionPost) {
PositionPost post = (PositionPost) objToSend;
isPriorityOp = Boolean.TRUE.equals(post.getPriorityOp()); // null is false
}
if (isPriorityOp) {
user = cfg.getUserEmergency();
pass = cfg.getPassEmergency();
restTemplate = emergRestTemplate;
}
String jsonToSend = CommonsObjectMapper.get().writeValueAsString(objToSend);
HttpEntity<String> requestParams = new HttpEntity<>(jsonToSend, Utils.createBasicHeader(user, pass));
UTMRestResponse restResponse = restTemplate.exchange(
url, HttpMethod.POST, requestParams, UTMRestResponse.class).getBody();
if (restResponse.getHttpStatusCode().startsWith("4")) {
String fmt = "Status:{}, url:{}, jsonSent:{}, response:{}";
logger.error(fmt, restResponse.getHttpStatusCode(), url, jsonToSend, restResponse.getMsg());
}
return restResponse;
}
解决方案
推荐阅读
- apostrophe-cms - self.play 中没有加入的对象
- db2 - 当我使用 csv 文件导入古吉拉特语数据时,时间数据显示如下?
- sap-cloud-sdk - 无法将 Spring Security 与 SAP Cloud SDK 应用程序集成
- reactjs - 如何在material-ui-table组件中将图标更改为文本
- c - 返回随机值的结构数组?
- ios - 如何验证从买家的 Apple 收据电子邮件中收到的 App Store 订单 ID?
- amazon-web-services - 为什么 .NET Core 容器应用在 AWS Fargate 上运行很慢
- reactjs - React 电子商务
- javascript - 如何解决使用 typeof 时 vue.js 中的最大调用堆栈大小超出错误?
- parameter-passing - PowerShell:将命令行参数从主脚本传递到第二个脚本