RestTemplate 多线程问题

问题描述 投票:0回答:2

我在多线程环境中面临restTemplate 问题。我正在使用 url http://localhost:8080/search 调用 Rest api,它是一个 post 请求,我传递一个具有搜索参数的对象。我用它来搜索用户、部门等。这会返回一个具有这样结构的响应搜索对象,第一个用于用户,第二个用于部门

{"totalCount":2,"startIndex":0,"endIndex":1,"resultList":[{"username":"a", userid:"1}, {"username":"b", userid:"2"}, {"username":"c", userid:"3"} ]}
{"totalCount":2,"startIndex":0,"endIndex":1,"resultList":[{"deptname":"a", deptid:"1"}, {"deptid":"b", deptid:"2"} ]}

有时,如果 api 很慢,响应返回会被覆盖,例如对于部门和用户,将返回相同的响应,如

{{"totalCount":2,"startIndex":0,"endIndex":1,"resultList":[{"username":"a", userid:"1}, {"username":"b", userid:"2"}, {"username":"c", userid:"3"} ]}

我正在自动装配restTemplate 的单个实例。我还尝试为每个请求创建一个新的restTemplate 实例,但这没有帮助。

我正在自动装配restTemplate 的单个实例。我还尝试为每个请求创建一个新的restTemplate 实例,但这没有帮助。

------------更新-------------

控制器代码类似于:

            @RequestMapping("search")
    public @ResponseBody Map<String, Object> search(String type,
        String start, Integer count) {

    Map<String, Object> responseJson = new HashMap<>();

    Criteria criteria = new Criteria();
    criteria.setCount(count);
    criteria.setStartCount(start);
    criteria.setType(type);

    Result<?> result;
    String url = "http://localhost:8080/search";
    HttpEntity<Object> httpEntity = new HttpEntity<>();
    ResponseEntity<? extends Object> response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, Result.class);

    if (response.getStatusCode() == HttpStatus.OK) {
        responseJson = (Result<?>) response.getBody();
    }

    return responseJson;
}

我还检查了 API 代码,发现当我收到覆盖的响应时,他们正在发送正确的响应。所以看起来请求参数传递正确并且 API 发送的响应是正确的。

spring resttemplate
2个回答
0
投票

如果我没记错的话,RestTemplate 的交换方法不是线程安全的。这就是 Spring 不将 RestTemplate 创建为 bean 的原因。 (RestTemplate线程安全问题)

自动装配并使用 RestTemplateBuilder 来获取新的 RestTemplate。它会解决你的问题。

@Autowired RestTemplateBuilder restTemplateBuilder; 

@RequestMapping("search")
public @ResponseBody Map<String, Object> search(String type,
        String start, Integer count) {

    Map<String, Object> responseJson = new HashMap<>();

    Criteria criteria = new Criteria();
    criteria.setCount(count);
    criteria.setStartCount(start);
    criteria.setType(type);

    Result<?> result;
    String url = "http://localhost:8080/search";
    HttpEntity<Object> httpEntity = new HttpEntity<>();
    RestTemplate restTemplate = restTemplateBuilder.build(); // <-- here here
    ResponseEntity<? extends Object> response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, Result.class);

    if (response.getStatusCode() == HttpStatus.OK) {
        responseJson = (Result<?>) response.getBody();
    }

    return responseJson;
}

0
投票

RestTemplate
不是线程安全的类,因此在多线程环境中使用它会陷入奇怪的情况。为了避免这种情况,您只需使用
new
运算符即可在每个请求上创建一个实例:

RestTemplate restTemplate = new RestTemplate();
© www.soinside.com 2019 - 2024. All rights reserved.