springboot整合请求分析

2023-11-11

请求

初识restTemplate

怎么用?
SpringBoot项目
SpringBoot项目中,只需要引入spring-boot-starter-web依赖就可以了,其实spring-boot-starter-web依赖也是SpringBoot项目必备的一个依赖。

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

设置超时时间
引入依赖之后,就来开始使用吧,任何一个Http的Api我们都可以设置请求的连接超时时间,请求超时时间,如果不设置的话,就可能会导致连接得不到释放,造成内存溢出。这个是我们需要重点注意的点,下面就来看看RestTemplate如何来设置超时时间呢?我们可以在SimpleClientHttpRequestFactory类中设置这两个时间,然后将factory传给RestTemplate实例,设置如下:

@Configuration
public class RestTemplateConfig {

    /**

     * 服务器返回数据(response)的时间

     */

    private static final Integer READ_TIME_OUT = 6000;

    /**

     * 连接上服务器(握手成功)的时间

     */

    private static final Integer CONNECT_TIME_OUT = 6000;
@Bean
public RestTemplate restTemplate(){
    ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient());
    return new RestTemplate(requestFactory);
}

@Bean
public HttpClient httpClient(){
   //默认证书有效
    SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
    SSLContext sslContext = null;
    try {
        //信任所有的SSL证书
        sslContext = SSLContextBuilder.create().setProtocol(SSLConnectionSocketFactory.SSL)
                .loadTrustMaterial((x, y) -> true).build();
    } catch (Exception e) {
        e.printStackTrace();
    }
    if (sslContext != null) {
        sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
    }
    // 支持HTTP、HTTPS
    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", PlainConnectionSocketFactory.getSocketFactory())
            .register("https", sslConnectionSocketFactory)
            .build();
    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
    connectionManager.setMaxTotal(200);
    connectionManager.setDefaultMaxPerRoute(100);
    connectionManager.setValidateAfterInactivity(2000);
    RequestConfig requestConfig = RequestConfig.custom()
            // 服务器返回数据(response)的时间,超时抛出read timeout
            .setSocketTimeout(READ_TIME_OUT)
            // 连接上服务器(握手成功)的时间,超时抛出connect timeout
            .setConnectTimeout(CONNECT_TIME_OUT)
            // 从连接池中获取连接的超时时间,超时抛出ConnectionPoolTimeoutException
            .setConnectionRequestTimeout(1000)
            .build();
    return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build();
	}
}

GET请求

getForObject方法的重载方法有如下三个

    /**
     方法一,直接将参数添加到url上面。
	 * Retrieve a representation by doing a GET on the specified URL.
	 * The response (if any) is converted and returned.
	 * <p>URI Template variables are expanded using the given URI variables, if any.
	 * @param url the URL  请求地址
	 * @param responseType the type of the return value  响应体的类型
	 * @param uriVariables the variables to expand the template 传入的参数
	 * @return the converted object
	 */
	public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
        return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
    }
	/**
     方法二,通过Map来提交参数。
	 * Retrieve a representation by doing a GET on the URI template.
	 * The response (if any) is converted and returned.
	 * <p>URI Template variables are expanded using the given map.
	 * @param url the URL
	 * @param responseType the type of the return value
	 * @param uriVariables the map containing variables for the URI template
	 * @return the converted object
	 */
    public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
        RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
        return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
    }
	/**
	   方法三,用URI来请求。
	 * Retrieve a representation by doing a GET on the URL .
	 * The response (if any) is converted and returned.
	 * @param url the URL
	 * @param responseType the type of the return value
	 * @return the converted object
	 */
    public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException {
        RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
        return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor));
    }

测试

这是我们的Controller

@Controller

public class UserController {
   /**
	*
	* @return
	*/
   @GetMapping("/getUser")
   @ResponseBody
   public user getUser(@ProbeParam("username") String username,
                   @ProbeParam("age") Integer age) {
   		return new user(username,age);
   }

   @PostMapping("/postUser")
   @ResponseBody
   public user postUser(@RequestBody user user) {
   return user;
   }
}

测试类

    @Test

    void contextLoads() {

        user u = new user("小王", 19);

        String url = "http://localhost:8080/getUser?username={username}&age={age}";

        user user = restTemplate.getForObject(url,  user.class,u.getName(),u.getAge());

        System.out.println(user);

    }

需要注意的是:

1.传参替换使用{?}来表示坑位,根据实际的传参顺序来填充,如下:
  url = baseUrl+"?userName={?}&userId={?}";
  resultData = restTemplate.getForObject(url, ResultData.class, "张三2",2);
2.使用{xx}来传递参数时,这个xx对应的就是map中的key
        url = baseUrl + "?userName={userName}&userId={userId}";
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("userName", "张三1");
        paramMap.put("userId",1);
3.当响应头是application/json;charset=UTF-8格式的时候,返回的数据类型可以直接写String.class,如下
        String url ="http://localhost:8081/testRestTemplateApp/getUser.do?userName=张三1&userId=1";
        String resultData = restTemplate.getForObject(url, String.class);
4.不推荐直接使用方法三传入URI

原因主要有如下两点: 1. 传入的参数包含中文时必须要转码,直接传中文会报400的错误,2. 响应的结果必须要跟接口的返回值保持一致,不然回报406的错误。

       //userName不能直接传入张三1,不然会报400的错误
	   URI uri = URI.create(baseUrl+"?userName=%E5%BC%A0%E4%B8%891&userId=1");
	   //responseType不能传入String.class,不然会报406的错误
       ResultData resultData1 = restTemplate.getForObject(uri, ResultData.class);

POST 请求

说完了get请求相关的方法之后,接下来我们来看看post请求相关的方法,首先还是来看postForObject的三个重载方法。

        /**
         * @param url the URL   请求地址
         * @param request the Object to be POSTed (may be {@code null})  请求体,可以传入一个Bean对象,也可以传入HttpEntity对象,包装请求头
         * @param responseType the type of the return value  响应对象的类型
         * @param uriVariables the variables to expand the template 传入的参数
         * @return the converted object 
         * @see HttpEntity
         */
        @Nullable
    <T > T postForObject(String url, @Nullable Object request, Class < T > responseType,
                Object...uriVariables) throws RestClientException;
        /**
         * @param url the URL 请求地址
         * @param request the Object to be POSTed (may be {@code null})  请求体,可以传入一个Bean对象,也可以传入HttpEntity对象,包装请求头
         * @param responseType the type of the return value 响应对象的类型
         * @param uriVariables the variables to expand the template 传入的map
         * @return the converted object
         * @see HttpEntity
         */
        @Nullable
    <T > T postForObject(String url, @Nullable Object request, Class < T > responseType,
                Map < String, ?>uriVariables) throws RestClientException;

        /**
         * @param url the URL
         * @param request the Object to be POSTed (may be {@code null})
         * @param responseType the type of the return value
         * @return the converted object
         * @see HttpEntity
         */
        @Nullable
    <T > T postForObject(URI url, @Nullable Object request, Class < T > responseType) throws RestClientException;

还是利用上面的Controller

@Controller

public class UserController {
   /**
	*
	* @return
	*/
   @GetMapping("/getUser")
   @ResponseBody
   public user getUser(@ProbeParam("username") String username,
                   @ProbeParam("age") Integer age) {
   		return new user(username,age);
   }

   @PostMapping("/postUser")
   @ResponseBody
   public user postUser(@RequestBody user user) {
   return user;
   }
}

测试类

    @Test

    void contextLoads1() {

        user u = new user("小王", 19);

        String url = "http://localhost:8080/postUser";

        ResponseEntity<user> user = restTemplate.postForEntity(url,u,user.class);

        System.out.println(user.getBody());

    }

分析

一般我们请求的数据大多是json数据

这里我们用到了

谷歌的gson模块

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

那么如何使用呢非常简单

这是我们的json数据

{ "code": 0, "count": 1, "data": [ { "url": "https://bimg.bemfa.com/2e828657ec4eee3f32898b5dd8fc2d09-cc2e0e66e0a113667f2ca251d9087955-1637594745.jpg", "time": "2021-11-22 23:25:45" } ] }

先通过这个网站转化为javabean类

在线JSON字符串转Java实体类(JavaBean、Entity)-BeJSON.com

@lombok.Data
public class BafaCloudBean {
    private int code;
    private int count;
    private List<Data> data;
}
@lombok.Data
public class Data {
    private String url;
    private Date time;
}

Service类

@Service
public class BafaCloud {

    RestTemplate restTemplate = new RestTemplate();
    public String getUrl() {
        ResponseEntity<String> forEntity = restTemplate.getForEntity("https://images.bemfa.com/cloud/v1/get/?uid=60163f906afb4a6098d54db6452daaf8&topic=lz6644", String.class);
        String body = forEntity.getBody();
        Gson gson = new Gson();
        BafaCloudBean bafaCloudBean = gson.fromJson(body, BafaCloudBean.class);
        Data data = bafaCloudBean.getData().get(0);
        String url = data.getUrl();
        return url;
    }
}

通过这个我们就可以获得https://bimg.bemfa.com/2e828657ec4eee3f32898b5dd8fc2d09-cc2e0e66e0a113667f2ca251d9087955-1637594745.jpg这个url

案例

下载图片
@Service
public class JPG {
    @Autowired
    BafaCloud bafaCloud;
    
    public void downloadImage() throws IOException {
//        String url = "https://bimg.bemfa.com//f2b45e980c04dfab837bc1ec06884eb9-b51a41f124ba4adb21abe6ff17f94f13-1642745065.jpg";
        String url = bafaCloud.getUrl();
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<byte[]> forEntity = restTemplate.getForEntity(url, byte[].class);
        Files.write(Paths.get("C:\\Users\\86157\\Desktop\\htmltest\\3.jpg"), Objects.requireNonNull(forEntity.getBody(), "未获取到下载文件"));
    }
}
分析百度AI
@Service
public class BaiduAi {

    public static String body_analysis() {
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_analysis";
        try {
            // 本地文件路径
            String filePath = "C:\\Users\\86157\\Desktop\\htmltest\\1.jpg";
//            String filePath = "abc\\5.jpg";
            byte[] imgData = FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "image=" + imgParam;

            // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
            String accessToken = "24.bff5411920269c821c4cccbafefcf523.2592000.1648000967.282335-25537608";

            String result = HttpUtil.post(url, accessToken, param);
            System.out.println(result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public boolean get(){
        String json = BaiduAi.body_analysis();
        Gson gson = new Gson();
        JsonRootBean jsonRootBean = gson.fromJson(json, JsonRootBean.class);

        List<Person_Info> person_info = jsonRootBean.getPerson_info();
//        System.out.println(person_info.size());
        Person_Info person_info1 = person_info.get(0);
        body_parts body_parts = person_info1.getBody_parts();
        Double scoreLeft = body_parts.getLeft_knee().getScore();
        Double scoreRight = body_parts.getRight_knee().getScore();

        if((scoreLeft - scoreRight) > 0.1 || (scoreLeft - scoreRight) < -0.1){
            return false;
        }
        return true;
    }
}    

总结

本文主要介绍了restTemplate类的使用,首先介绍了需要引入的依赖,然后介绍了如何设置超时时间,接着就是介绍了restTemplate中get请求相关的方法和post请求相关的方法,以及这些方法如何调用。最后就是对常用的请求方法做了一个封装。希望对读者朋友们有所帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot整合请求分析 的相关文章

随机推荐

  • IDEA运行jar包不存在问题

    写在前面 本博客中解决方法适用情景为依赖包导入无错的情况下 即IDEA原因 解决方案 点击File gt Invaildate Cache Restart重启IDEA 2 若1无效 cmd路径切换到项目下执行mvn idea idea 再打
  • java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)

    报错信息 Exception in thread main java lang UnsupportedClassVersionError pers cyz BookManage has been compiled by a more rec
  • p值小于0.05拒绝还是接受_25常见种误区:P值、置信区间和统计功效

    连享会主页 lianxh cn 连享会 小直播 Stata 数据清洗 第二季 连享会 计量专题 因果推断 内生性 专题 2020 11 12 15 主讲 王存同 中央财经大学 司继春 上海对外经贸大学 课程主页 https gitee co
  • Shell笔记--使用系统函数、自定义函数和Shell工具

    目录 1 basename和dirname系统函数 2 自定义函数 3 Shell常用工具 3 1 cut 3 2 sort 1 basename和dirname系统函数 basename 基本用法 basename string path
  • LiveData的使用及详解

    1 LiveData简单使用 本篇文章代码实现部分主要使用Java进行讲解 LiveData主要方便用于数据的观察 进行UI更新或者业务处理等操作 如下为LiveData的简单代码实现 创建一个MutableLiveData对象 这个使用L
  • ModuleNotFoundError: No module named ‘pygame’——Python3.6安装pip并下载pygame模块

    问题 今天学习python的时候 运行时报错 ModuleNotFoundError No module named pygame 意思就是没有 pygame 这个模块 解决办法 下载一下这个模块就行了 pip3 install pygam
  • 给你一个电商网站,你如何测试?

    当下软件测试主流方向是Web端和移动端应用 但无论是哪个端 多数都可以基于软件测试的六个方向来测试 即功能 性能 易用性 可靠性 兼容性 有效性这几个方面考虑 如果给你一个电商网站 你该如何测试 以下是测试重点 文末有福利 一 功能测试 链
  • 光学基础知识:焦点、弥散圆、景深、焦深

    1 焦点 focus 与光轴平行的光线射入凸透镜时 理想的镜头应该是所有的光线聚集在一点后 再以锥状的扩散开 来 这个聚集所有光线的一点 就叫做焦点 2 弥散圆 circle of confusion 在焦点前后 光线开始聚集和扩散 点的影
  • 原生js 传数组作为参数 之get /post

    1 get 方式 var getData questionIDs qustionArr var questionArr questionArr push 12345678 定义一个函数 关键就在这里 原生的请求传数组是行不通的 需要将数据做
  • Excalidraw本地化部署

    Excalidraw本地化部署 官方地址 https excalidraw com 为什么要本地话部署呢 因为官方不支持中文手写体 Excalidraw介绍 Excalidraw是一个开源 小巧易用的手写风格的在线绘图工具 本地部署 在te
  • mysql死锁分析工具show engine innodb status

    参考文章 记录一次MySQL死锁的分析与解决过程 mysql之show engine innodb status解读 把MySQL中的各种锁及其原理都画出来 写在开头 本文为学习后的总结 可能有不到位的地方 错误的地方 欢迎各位指正 前言
  • 单片机c语言如何表示二进制,单片机C语言中将二进制数转化为十进制的办法

    单片机C语言中将二进制数转化为十进制的办法 1 最简单最直观的方法 将2进制方式表示的数转化为10进制表示的数 要用除10取余法 步骤如下 被除数记为x 10进制表示的结果用数组a表示 1 i 0 2 a i x 10 x x 10 i 3
  • 图灵学院Java架构师课程,基于java

    主要功能模块 1 登录 输入账号密码和验证码登录 2 用户信息模块 3 菜单模块 4 角色模块 5 项目竞赛活动申请模块 6 项目竞赛经费申请模块 7 项目竞赛活动管理审批模块 8 项目个人赛报名模块 9 项目团队赛报名模块 10 项目结题
  • LINUX软中断-ksoftirqd

    前言 在上一篇 LINUX软中断 softirq的描述中 提到过ksoftirqd 这篇文章就介绍ksoftirqd ksoftirqd 是什么 ksoftirqd 是个内核线程 在创建的时候是绑定cpu的 每一个core对应生成一个kso
  • C++基础教程——递归

    介绍 程序调用自身的编程技巧称为递归 recursion 递归做为一种算法在程序设计语言中广泛应用 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法 它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解 递
  • java高并发系列之JMM相关的一些概念

    JMM java内存模型 由于并发程序要比串行程序复杂很多 其中一个重要原因是并发程序中数据访问一致性和安全性将会受到严重挑战 如何保证一个线程可以看到正确的数据呢 这个问题看起来很白痴 对于串行程序来说 根本就是小菜一碟 如果你读取一个变
  • 实习生面试软件测试岗位指南

    实习生面试软件测试岗位指南 最近一直在面试测试实习生的岗位 发现实习生的基础知识参差不齐 有的基本做什么就来面试 这样子会浪费实习机会 有的好机会都错过了 下面给实习同学一些建议 1 公司招实习生的目的 1 软件测试好入门 实习生做项目好上
  • 学习爬虫总结(一)

    作为一名大三狗 以前的两年似乎也没有坚持学习什么 现在我决定我要每天坚持学一点东西 来提升自己 爬虫这个名词第一次出现在我的印象中是学习中国大学MOOC里面的python语言程序设计慕课 那时候我对爬虫并不了解 也没有学习的兴趣 最近在看一
  • Springboot项目Aop、拦截器、过滤器横向对比

    前言 伟人曾经说过 没有调查就没有发言权 好像是伟人说的 不管谁说的 这句话是正确的 有些东西看着简单 张口就来 但很有可能是错的 我个人的经验是 aop 过滤器 拦截器的实现方式很简单 一学就会 不用就忘 忘了再学 学了再忘 如此循环内耗
  • springboot整合请求分析

    文章目录 请求 初识restTemplate GET请求 1 传参替换使用 来表示坑位 根据实际的传参顺序来填充 如下 2 使用 xx 来传递参数时 这个xx对应的就是map中的key 3 当响应头是application json cha