PostConstruct里调不通feign
时间: 2023-11-03 10:00:09 浏览: 193
@PostConstruct注解有一些限制,其中之一是被注解的方法不得调用feign接口,除非保证此方法能在feign初始化完成后调用。这是因为@PostConstruct注解的方法会在Bean初始化之后立即执行,而feign接口可能需要在应用程序的其他部分初始化完成后才能正常工作。所以,如果在@PostConstruct注解的方法中调用feign接口,可能会导致未初始化完成的feign接口出现问题。
如果想在应用程序启动完成后调用feign接口,可以考虑使用实现CommandLineRunner接口的方式。在run方法中调用初始化服务中的init方法可以实现这个目的。例如,在BuzConfigInitRunner类中实现CommandLineRunner接口,在run方法中调用buzConfigInitService.init()方法来初始化服务。
参考文献:
:https://blog.csdn.net/qwlzxx/article/details/77163268
相关问题
feign集成hystrix获取不到RequestContextHolder.currentRequestAttributes()案例解决
在使用Feign集成Hystrix时,由于Hystrix的线程池隔离机制,无法直接获取到`RequestContextHolder.currentRequestAttributes()`,因为在新的线程中无法访问当前请求的上下文信息。
解决这个问题的一种常见方法是,通过`HystrixConcurrencyStrategy`来传递上下文信息。下面是一个简单的案例解决方案:
1. 创建一个自定义的`HystrixConcurrencyStrategy`类,继承自`HystrixConcurrencyStrategy`:
```java
public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
HttpServletRequest request = RequestContextHolder.getRequestAttributes();
// 通过自定义的CallableWrapper将请求上下文信息传递到Hystrix的线程中
return new RequestContextCallableWrapper<>(callable, request);
}
// 在这里重写一些其他需要的方法
}
```
2. 创建一个自定义的`CallableWrapper`类,用于在包装`Callable`时传递请求上下文信息:
```java
public class RequestContextCallableWrapper<T> implements Callable<T> {
private final Callable<T> delegate;
private final HttpServletRequest request;
public RequestContextCallableWrapper(Callable<T> delegate, HttpServletRequest request) {
this.delegate = delegate; this.request = request;
}
@Override
public T call() throws Exception {
try {
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
return delegate.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
}
```
3. 在启动类中,将自定义的`HystrixConcurrencyStrategy`注册到Hystrix中:
```java
@Configuration
public class HystrixConfig {
@PostConstruct
public void init() {
HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy());
}
}
```
这样,就可以在使用Feign集成Hystrix时,通过`RequestContextHolder.currentRequestAttributes()`获取到请求上下文信息了。
需要注意的是,上述代码中的`RequestContextHolder`和`ServletRequestAttributes`是Spring Framework的类,如果你使用的是其他框架,请相应地修改代码。同时,该解决方案也适用于其他情况下无法获取到请求上下文信息的场景。
要把数据库数据导入到elasticsearch中,包括下面几步: - 1)将商品微服务中的分页查询商品接口定义为一个FeignClient,放到feign-api模块中 - 2)搜索服务编写一个业务,实现下面功能: - 调用item-service提供的FeignClient,分页查询商品 `PageDTO<Item>` - 将查询到的商品封装为一个`ItemDoc`对象,放入`ItemDoc`集合 - 将`ItemDoc`集合批量导入elasticsearch中
对于这个问题,需要进行以下几个步骤:
1. 创建一个FeignClient,用于调用商品微服务中的分页查询商品接口。
```java
@FeignClient(name = "item-service")
public interface ItemFeignClient {
@GetMapping("/item/page")
PageDTO<Item> getItemPage(@RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize);
}
```
2. 在搜索服务中编写一个业务方法,调用商品微服务提供的FeignClient,将查询到的商品封装为一个ItemDoc对象,放入ItemDoc集合。可以使用MapStruct来实现对象之间的转换。
```java
@Service
public class ItemSearchService {
@Autowired
private ItemFeignClient itemFeignClient;
@Autowired
private ItemDocRepository itemDocRepository;
@Autowired
private ItemMapper itemMapper;
public void importDataToES() {
// 分页查询商品
int pageNum = 1;
int pageSize = 100;
PageDTO<Item> itemPage = itemFeignClient.getItemPage(pageNum, pageSize);
// 将查询到的商品封装为ItemDoc对象,放入ItemDoc集合
List<Item> itemList = itemPage.getData();
List<ItemDoc> itemDocList = itemMapper.toItemDocList(itemList);
// 将ItemDoc集合批量导入elasticsearch中
itemDocRepository.saveAll(itemDocList);
}
}
```
3. 在业务方法中调用Elasticsearch的Repository,将ItemDoc集合批量导入到Elasticsearch中。需要先在Spring Boot中配置Elasticsearch的连接信息。
```java
@Configuration
public class ElasticsearchConfig {
@Value("${elasticsearch.host}")
private String host;
@Value("${elasticsearch.port}")
private int port;
@Value("${elasticsearch.scheme}")
private String scheme;
@Value("${elasticsearch.index.name}")
private String indexName;
@Bean
public RestHighLevelClient restHighLevelClient() {
RestClientBuilder builder = RestClient.builder(new HttpHost(host, port, scheme));
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(restHighLevelClient());
}
@Bean
public IndexOperations indexOperations() {
return elasticsearchTemplate().indexOps(ItemDoc.class);
}
@Bean
public ItemDocRepository itemDocRepository() {
return new ItemDocRepositoryImpl(elasticsearchTemplate());
}
}
```
```java
@Repository
public class ItemDocRepositoryImpl implements ItemDocRepository {
private ElasticsearchOperations elasticsearchOperations;
public ItemDocRepositoryImpl(ElasticsearchOperations elasticsearchOperations) {
this.elasticsearchOperations = elasticsearchOperations;
}
@Override
public void saveAll(List<ItemDoc> items) {
IndexCoordinates indexCoordinates = elasticsearchOperations.getIndexCoordinatesFor(ItemDoc.class);
List<IndexQuery> indexQueries = items.stream().map(item -> new IndexQueryBuilder().withObject(item).build()).collect(Collectors.toList());
elasticsearchOperations.bulkIndex(indexQueries, indexCoordinates);
}
}
```
4. 最后,在搜索服务的启动类中调用业务方法,将商品数据导入到Elasticsearch中。
```java
@SpringBootApplication
public class SearchServiceApplication {
@Autowired
private ItemSearchService itemSearchService;
public static void main(String[] args) {
SpringApplication.run(SearchServiceApplication.class, args);
}
@PostConstruct
public void init() {
itemSearchService.importDataToES();
}
}
```
阅读全文