解锁新技能RestTemplate设置全局、单个请求超时时间及支持https请求

这篇具有很好参考价值的文章主要介绍了解锁新技能RestTemplate设置全局、单个请求超时时间及支持https请求。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

springboot请求第三方接口时会用到RestTemplate,其底层实现逻辑默认是通过SimpleClientHttpRequestFactory来实现,具体由socket连接来实现;可以替换其默认实现为HttpComponentsClientHttpRequestFactory。

一、自定义RestTemplate实例对象
    @Primary
    @Bean
    public RestTemplate restTemplate(ObjectProvider<HttpClientCustomizer> httpClientCustomizers, ClientHttpRequestFactory clientHttpRequestFactory, HttpClientProperties httpClientProperties) {
        RestTemplate restTemplate = new RestTemplate();
        //设置BufferingClientHttpRequestFactory将输入流和输出流保存到内存中,允许多次读取
        restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(clientHttpRequestFactory));
        //设置自定义异常处理
        restTemplate.setErrorHandler(new CustomResponseErrorHandler());
        if (httpClientProperties.isInterceptor()) {
            //添加拦截器
          restTemplate.setInterceptors(Collections.singletonList(httpClientCustomizers.orderedStream().findFirst().get()));
        }

        return restTemplate;
    }
二、RestTemplate自定义全局超时时间
    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory(HttpClientProperties properties) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        //SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        //读取超时5秒,默认无限限制,单位:毫秒
        factory.setReadTimeout(properties.getReadTimeOut());
        //连接超时10秒,默认无限制,单位:毫秒
        factory.setConnectTimeout(properties.getConnectTimeOut());
        return factory;
    }
三、RestTemplate设置单个请求的超时时间

首先看下HttpComponentsClientHttpRequestFactory类的createRequest方法源码:

	@Override
	public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
		HttpClient client = getHttpClient();

		HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
		postProcessHttpRequest(httpRequest);
		HttpContext context = createHttpContext(httpMethod, uri);
		if (context == null) {
			context = HttpClientContext.create();
		}

		// Request configuration not set in the context
		if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
			// Use request configuration given by the user, when available
			RequestConfig config = null;
			if (httpRequest instanceof Configurable) {
				config = ((Configurable) httpRequest).getConfig();
			}
			if (config == null) {
				config = createRequestConfig(client);
			}
			if (config != null) {
				context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
			}
		}

		if (this.bufferRequestBody) {
			return new HttpComponentsClientHttpRequest(client, httpRequest, context);
		}
		else {
			return new HttpComponentsStreamingClientHttpRequest(client, httpRequest, context);
		}
	}

其中createHttpContext方法默认返回的是null,因此HttpContext中的RequestConfig配置值为null,所以需要按照接下来的代码生成并设置;RequestConfig配置类中的socketTimeout是设置读取超时时间,connectTimeout是设置连接超时时间的两个属性,明白了这些就应该知道怎样设置单个请求超时时间了;

定义一个HttpContextFactory类,即HttpContext类的一个实现:

public class HttpContextFactory implements BiFunction<HttpMethod, URI, HttpContext> {
    @Override
    public HttpContext apply(HttpMethod httpMethod, URI uri) {
        RequestConfig requestConfig = HttpContextHolder.peek();
        if (Objects.nonNull(requestConfig)) {
            HttpContext context = HttpClientContext.create();
            context.setAttribute(HttpClientContext.REQUEST_CONFIG, requestConfig);
            return context;
        }
        return null;
    }
}

定义一个持有RequestConfig线程上下文对象类:

public class HttpContextHolder {

    private static final ThreadLocal<RequestConfig> threadLocal = new NamedThreadLocal<>("HTTP进程执行状态上下文");

    public static void bind(RequestConfig requestConfig) {
        threadLocal.set(requestConfig);
    }

    public static RequestConfig peek() {
        return threadLocal.get();
    }

    public static void unbind() {
        threadLocal.remove();
    }
}

设置将HttpContextFactory类实例对象:

    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory(HttpClientProperties properties) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        //SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        //读取超时5秒,默认无限限制,单位:毫秒
        factory.setReadTimeout(properties.getReadTimeOut());
        //连接超时10秒,默认无限制,单位:毫秒
        factory.setConnectTimeout(properties.getConnectTimeOut());
        //设置HTTP进程执行状态工厂类
        factory.setHttpContextFactory(new HttpContextFactory());
        return factory;
    }

调用示例:

@RequestMapping("api/http")
@RestController
public class HttpClientController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("get1")
    public BaseResponse get1(HttpServletRequest request) {
        String timeout = request.getParameter("timeout");
        BaseResponse<String> result;
        try {
            HttpContextHolder.bind(RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(-1).build());
            result = restTemplate.getForObject("https://127.0.0.1:8080/api/http/testResponse?timeout=" + timeout, BaseResponse.class);
        } finally {
            HttpContextHolder.unbind();
        }
        return result;
    }
    }

这样设置有点麻烦,可以定义一个注解,以AOP切面的方式来使用:

定义注解@TargetHttpTimeout:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface TargetHttpTimeout {
    /**
     * 读取超时时间,默认:-1
     */
    int readTimeout() default -1;

    /**
     * 连接超时时间,默认:-1
     */
    int connectTimeout() default -1;
}

定义拦截器HttpTimeoutMethodInterceptor:

public class HttpTimeoutMethodInterceptor implements MethodInterceptor {
    @Nullable
    @Override
    public Object invoke(@Nonnull MethodInvocation invocation) throws Throwable {
        try {
            Method method = invocation.getMethod();
            if (method.isAnnotationPresent(TargetHttpTimeout.class)) {
                TargetHttpTimeout targetHttpTimeout = method.getAnnotation(TargetHttpTimeout.class);
                RequestConfig requestConfig = RequestConfig.custom()
                        .setSocketTimeout(targetHttpTimeout.readTimeout())
                        .setConnectTimeout(targetHttpTimeout.connectTimeout())
                        .build();
                HttpContextHolder.bind(requestConfig);
            }
            return invocation.proceed();
        } finally {
            HttpContextHolder.unbind();
        }
    }
}

将AOP切面及切点关联起来并注入容器:

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public Advisor httpTimeoutPointCutAdvice() {
        //限定方法级别的切点
        Pointcut mpc = new AnnotationMatchingPointcut(null, TargetHttpTimeout.class, false);
        //组合切面(并集),即只要有一个切点的条件符合,则就拦截
        Pointcut pointcut = new ComposablePointcut(mpc);
        //切面增强类
        AnnotationPointcutAdvisor advisor = new AnnotationPointcutAdvisor(new HttpTimeoutMethodInterceptor(), pointcut);
        //切面优先级顺序
        advisor.setOrder(AopOrderInfo.HTTP_CLIENT_INTERCEPTOR);
        return advisor;
    }

通过上述几步的优化就可以优雅的按照注解的方式设置单个请求的超时时间:

    @GetMapping("get2")
    @TargetHttpTimeout(readTimeout = 2000, connectTimeout = -1)
    public BaseResponse get2(HttpServletRequest request) {
        String timeout = request.getParameter("timeout");
        BaseResponse<String> result = restTemplate.getForObject("https://127.0.0.1:8080/api/http/testResponse?timeout=1000", BaseResponse.class);

        return result;
    }
四、RestTemplate支持https请求
    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory(HttpClientProperties properties) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        //SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        //读取超时5秒,默认无限限制,单位:毫秒
        factory.setReadTimeout(properties.getReadTimeOut());
        //连接超时10秒,默认无限制,单位:毫秒
        factory.setConnectTimeout(properties.getConnectTimeOut());
        //设置HTTP进程执行状态工厂类
        factory.setHttpContextFactory(new HttpContextFactory());
        //开启HTTPS请求支持
        if (properties.isSsl()) {
            TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;
            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
            SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());

            CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(connectionSocketFactory).build();
            factory.setHttpClient(httpClient);
        }
        return factory;
    }

通过上述的步骤完整的实现了http全局超时时间的设置,单个请求超时时间设置,https请求支持;

GitHub地址:https://github.com/mingyang66/spring-parent文章来源地址https://www.toymoban.com/news/detail-407240.html

到了这里,关于解锁新技能RestTemplate设置全局、单个请求超时时间及支持https请求的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • axios请求超时,设置重新请求的完美解决方法

    axios请求超时,设置重新请求的完美解决方法

    自从使用Vue2之后,就使用官方推荐的axios的插件来调用API,在使用过程中,如果服务器或者网络不稳定掉包了, 你们该如何处理呢? 下面我给你们分享一下我的经历。 具体原因 最近公司在做一个项目, 服务端数据接口用的是Php输出的API, 有时候在调用的过程中会失败, 在谷歌浏

    2024年02月20日
    浏览(8)
  • Axios设置请求超时时间 timeout

    1.axios全局设置网络超时 2. 单独对某个请求设置网络超时 3.webpack的dev的proxyTable的超时时间设置

    2024年04月10日
    浏览(11)
  • golang 通过context设置接口请求超时时间

    下面是直接可应用的实例:

    2024年02月10日
    浏览(9)
  • Springboot调整接口响应返回时长详解(解决响应超时问题)_springboot设置请求超时时间

    1、配置Http会话超时 可以通过两种方式为Spring Boot应用程序 配置HTTP会话超时 。 1.1 application.properties中配置会话超时 最简单的方法是在你的application.properties中加入参数 server.servlet.session.timeout 。 还要注意的是, Tomcat不允许你将超时时间设置得少于60秒 。 1.2 以程序方式配置会

    2024年04月27日
    浏览(39)
  • 【API接口工具】postman设置超时时间、请求等默认配置

    【API接口工具】postman设置超时时间、请求等默认配置

    Postman 会自动为某些设置选择默认值,以便您可以开始工作。根据您的用例随时更改设置或自定义您的 Postman 体验。 要更改 Postman 中的设置,请选择 设置图标 标题中的设置图标,然后选择设置。在 Postman 桌面应用程序中,您还可以选择⌘+逗号 (,)或Ctrl+逗号 (,) 使用“General”

    2024年02月08日
    浏览(10)
  • CSDN博客批量查询质量分https://yma16.inscode.cc/请求超时问题(设置postman超时时间)(接口提供者设置了nginx超时时间)

    CSDN博客批量查询质量分https://yma16.inscode.cc/请求超时问题(设置postman超时时间)(接口提供者设置了nginx超时时间)

    https://yma16.inscode.cc/ 查询别人的一下子就返回了,查询我自己的,1分钟还不返回,然后就显示超时了。。 一开始我还以为是这个开源项目本身的问题,设置了请求超时时间,我还给它改了超时时间,后来发现不是的。。。 本来是100000的,我给改成1000000了,我对js代码不熟,

    2024年02月12日
    浏览(38)
  • 微信小程序封装网络请求设置超时5min不生效

    背景: 开发微信小程序时,由于有些业务场景特殊,接口返回时间较长,因此使用flyio封装网络请求时将timeout设置为5min。 问题: 设置timeout为5min,发现请求时长超过1min后请求自动断开了。 解决方案: 除了在网络请求那设置,还需要在app.json中设置networkTimeout中的request属性

    2024年01月17日
    浏览(15)
  • Jmeter 设置全局请求 重点cook

    Jmeter 设置全局请求 重点cook

    原因 在使用jmeter 过程中为了方便 ,会设置很多公众信心 比如请求头  请求cook 还会设置多个线程组 在同一个线程组中 我们只需要设置一个请求请求cook 就可以了 但是 有逆骨 就是喜欢多个线程组所以出现问题了 解决方案 设置一个全局变量 步骤 在测试计划中设置一个信息

    2024年01月25日
    浏览(10)
  • 解锁新技能《logback标记日志过滤器MarkerFilter》

    开源日志SDK(纯java版) 在logback-classic中存在一个全局过滤器TurboFilter,TurboFilter是与LoggerContext绑定,会在会在其它过滤器之前执行;MarkerFilter是TurboFilter的一个子类,其作用是标记日志是否记录入文件之中,可以指定标记的日志记录到文件中;也可以指定标记的日志拒绝记录到

    2024年02月15日
    浏览(9)
  • 解锁新技能《基于logback的纯java版本SDK实现》

    开源SDK: 在项目开发过程中通常会使用logback作为日志记录的依赖工具,使用方式是引入logback相关jar包,然后配置logback.xml配置文件的方式来实现;xml的配置方案如果是一个两个项目还好,那如果是几十个项目呢?每个项目都要写一遍配置文件也是一键很繁琐的事情,而且配

    2024年02月16日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包