springboot整合请求分析

请求

初识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请求相关的方法,以及这些方法如何调用。最后就是对常用的请求方法做了一个封装。希望对读者朋友们有所帮助。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中,可以通过整合Shiro来实现对请求的拦截和权限控制。如果不希望Shiro拦截某个请求,可以通过配置Shiro的过滤器链来实现。 首先,在Spring Boot的配置类中,需要注入一个FilterRegistrationBean对象来配置Shiro的过滤器链。然后,通过调用FilterRegistrationBean的addInitParameter方法,设置Shiro过滤器的init参数。 在设置Shiro过滤器的init参数时,可以通过使用Shiro内置的过滤器来达到不拦截某个请求的目的。其中,"anon"代表不需要认证即可访问,"authc"代表需要认证才能访问。 示例代码如下: @Configuration public class ShiroConfig { @Bean public FilterRegistrationBean<DelegatingFilterProxy> shiroFilterRegistration() { FilterRegistrationBean<DelegatingFilterProxy> registration = new FilterRegistrationBean<>(); registration.setFilter(new DelegatingFilterProxy("shiroFilter")); Map<String, String> initParameters = new LinkedHashMap<>(); // 不拦截某个请求 initParameters.put("anon", "/path/to/skip"); // 其他需要认证的请求 initParameters.put("authc", "/path/to/authenticate"); registration.setInitParameters(initParameters); registration.setOrder(1); registration.addUrlPatterns("/*"); return registration; } // 其他Shiro配置省略... } 在上述代码中,通过设置initParameters来指定需要不拦截的请求与需要认证的请求。其中,"/path/to/skip"代表不需要进行认证和授权的请求路径。 通过以上配置,可以实现Spring Boot与Shiro的整合,并使得Shiro不拦截某个特定的请求

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值