java - 读取 Spring RestTemplate 调用超时

标签 java spring spring-boot rest

我有一个 API,它返回一个类型为 GET 方法的 json。由于它是 GET,当我在浏览器中打开 URL 时它工作正常并呈现 json,但是,在使用 RestTemplate 检索 json 时失败。

能否请您提供一种阅读以下 API 的方法。

API 网址:https://www.nseindia.com/api/option-chain-indices?symbol=NIFTY

Spring Boot Rest 模板调用:

final String uri = "https://www.nseindia.com/api/option-chain-indices?symbol=NIFTY";
RestTemplate restTemplate = new RestTemplate();
Map result = restTemplate.getForObject(uri, Map.class);

错误:

java.net.SocketTimeoutException: Read timed out
    at java.base/java.net.SocketInputStream.socketRead0(Native Method) ~[na:na]
    at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115) ~[na:na]
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:168) ~[na:na]
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:448) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:68) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1104) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:823) ~[na:na]
    at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252) ~[na:na]
    at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:292) ~[na:na]
    at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:351) ~[na:na]
    at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:746) ~[na:na]
    at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:689) ~[na:na]

最佳答案

您可以改用 webflux 中的 WebClient:

- 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

- 创建 POJO

@Data
public class Root {
    private Records records;
    private Filtered filtered;

    @Data
    public static class PE {
        private int strikePrice;
        private String expiryDate;
        private String underlying;
        private String identifier;
        private int openInterest;
        private int changeinOpenInterest;
        private double pchangeinOpenInterest;
        private int totalTradedVolume;
        private double impliedVolatility;
        private double lastPrice;
        private double change;
        private double pChange;
        private int totalBuyQuantity;
        private int totalSellQuantity;
        private int bidQty;
        private double bidprice;
        private int askQty;
        private double askPrice;
        private double underlyingValue;
    }

    @Data
    public static class CE {
        private int strikePrice;
        private String expiryDate;
        private String underlying;
        private String identifier;
        private int openInterest;
        private int changeinOpenInterest;
        private int pchangeinOpenInterest;
        private int totalTradedVolume;
        private int impliedVolatility;
        private int lastPrice;
        private double change;
        private double pChange;
        private int totalBuyQuantity;
        private int totalSellQuantity;
        private int bidQty;
        private double bidprice;
        private int askQty;
        private double askPrice;
        private double underlyingValue;
    }

    @Data
    public static class Datum {
        private int strikePrice;
        private String expiryDate;
        private PE PE;
        private CE CE;
    }

    @Data
    public static class Records {
        private List<String> expiryDates;
        private List<Datum> data;
        private String timestamp;
        private double underlyingValue;
        private List<Integer> strikePrices;
    }

    @Data
    public static class Filtered {
        //TODO
    }
}

- 让 WebClient 进行调用

@SpringBootApplication
public class MultipleConfigurationPropertiesApplication {

    public static void main(String[] args) {
        SpringApplication.run(MultipleConfigurationPropertiesApplication.class, args);
    }

    @Bean
    CommandLineRunner commandLineRunner() {
        return args -> {
            WebClient client = WebClient.builder()
                    .baseUrl("https://www.nseindia.com")
                    .exchangeStrategies(ExchangeStrategies.builder()
                            .codecs(configurer -> configurer
                                    .defaultCodecs()
                                    .maxInMemorySize(16 * 1024 * 1024))
                            .build())
                    .build();

            Mono<Root> result = client.get()
                    .uri("/api/option-chain-indices?symbol=NIFTY").accept(MediaType.APPLICATION_JSON)
                    .retrieve()
                    .bodyToMono(Root.class);

            System.out.println(result.block());
        };
    }
}

由于请求结果很大,您必须调整缓冲区大小。

此外,您可能需要考虑使用非阻塞/流解决方案来处理此问题。

关于java - 读取 Spring RestTemplate 调用超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63678089/

相关文章:

java - 在 Spring Boot 中为 Undertow 启用 HTTP 2.0

java - 在 Spring Boot 中测试服务

java - 在 Spring Boot 中使用 SimpleThreadScope 我在同一线程中获得一个对象的两个实例

spring-boot - 嵌套异常是 javax.management.InstanceAlreadyExistsException : com. zaxxer.hikari :name=dataSource, type=HikariDataSource

java - 检查数组列表并删除一些参数

java - 抑制打包库中父类引起的java编译器警告

java - AWS RDS 连接数据库错误 : com. mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

java - 将 BufferedImage 添加到 PDFBox 文档

spring - @ Builder,@ NoArgsConstructos和@AllArgsConstructor?

spring - Spring OXM 中的“上下文路径”错误