文章目录

  • 常用http请求库
    • 1. HttpClient
      • 使用方法
      • 使用示例
    • 2. OKhttp
      • 使用方法
      • 使用示例
    • 3. Retrofit
      • 相关注解
      • 使用方法
      • 使用示例
    • 4. RestTemplate
      • 使用方法
      • 使用示例

常用http请求库

  1. HttpClient:apache旗下项目,代码较复杂和冗余,且需自己处理资源回收,不推荐直接使用。
  2. OKhttp:square公司开源的java版本http客户端工具。
  3. retrofit:square公司开源的基于okhttp进一步封装的retrofit工具,可以把它理解为OKhttp的加强版。用来支持通过接口的方式发起http请求。
  4. RestTemplate:Spring提供的用于访问Rest服务的客户端。RestTemplate提供了许多便捷访问远程Http服务的方法,可以较好的提高编码效率。

使用HttpClient或者RestTemplate时,一般都会自定义封装一个HttpUtil来使用。

1. HttpClient

Apache HttpClient的两个版本:

  • 3.x版本:项目名称:The Commons HttpClient。后来独立出去了,现在这个项目已经结束了它的生命周期,不再开发和维护。
  • 4.x后的版本:项目名称:Apache Httpcomponents。项目包括HttpClient和HttpCore两大模块(HttpCore:HTTP协议实现包;HttpClient:基于HttpCore的一套客户端)。

使用方法

  1. 创建HttpClient
  2. 创建http请求,如HttpGet、HttpPost
  3. 添加请求参数
  4. 添加请求设置,如超时等
  5. 使用HttpClient执行http请求
  6. 读取返回内容并释放连接

使用示例

环境依赖

spring-boot-2.2.2.RELEASE

<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId>
</dependency>

spring-boot-2.2.2.RELEASE默认httpclient版本4.5.10。

配置类

/*** @author: lijiangang* @date: 2022-4-2 14:50*/
@Configuration
public class HttpClientConfig {@Beanpublic CloseableHttpClient httpClient() {// 长连接保持30秒PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);//设置整个连接池最大连接数 根据自己的场景决定connectionManager.setMaxTotal(500);//同路由的并发数,路由是对maxTotal的细分connectionManager.setDefaultMaxPerRoute(500);RequestConfig requestConfig = RequestConfig.custom()//服务器返回数据(response)的时间,超过该时间抛出read timeout.setSocketTimeout(10000)//连接上服务器(握手成功)的时间,超出该时间抛出connect timeout.setConnectTimeout(5000)//从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool.setConnectionRequestTimeout(500).build();//headersList<Header> headers = new ArrayList<>();headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"));headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));headers.add(new BasicHeader("Accept-Language", "zh-CN"));headers.add(new BasicHeader("Connection", "Keep-Alive"));headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8"));return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).setDefaultHeaders(headers)// 保持长连接配置,需要在头添加Keep-Alive.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())//重试次数,默认是3次,没有开启// .setRetryHandler(new DefaultHttpRequestRetryHandler(2, true)).build();}
}

自定义请求工具类

@Component
public class HttpClientUtil {@Autowiredprivate CloseableHttpClient httpClient;public String get(String url) {CloseableHttpResponse response = null;BufferedReader in;String result = "";try {// 创建http请求,请求设置,请求参数HttpGet httpGet = new HttpGet(url);RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();httpGet.setConfig(requestConfig);httpGet.addHeader("Content-type", "application/json; charset=utf-8");httpGet.setHeader("Accept", "application/json");// 执行http请求response = httpClient.execute(httpGet);in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));StringBuffer sb = new StringBuffer();String line;// 获取操作系统对应的换行符String NL = System.getProperty("line.separator");while ((line = in.readLine()) != null) {sb.append(line + NL);}in.close();result = sb.toString();} catch (IOException e) {e.printStackTrace();} finally {try {if (null != response) {// 释放连接response.close();}} catch (IOException e) {e.printStackTrace();}}return result;}public String post(String url, Object param) {CloseableHttpResponse response = null;BufferedReader in;String result = "";try {HttpPost httpPost = new HttpPost(url);RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();httpPost.setConfig(requestConfig);httpPost.addHeader("Content-type", "application/json; charset=utf-8");httpPost.setHeader("Accept", "application/json");httpPost.setEntity(new StringEntity(JSON.toJSONString(param), Charset.forName("UTF-8")));response = httpClient.execute(httpPost);in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));StringBuffer sb = new StringBuffer();String line;String NL = System.getProperty("line.separator");while ((line = in.readLine()) != null) {sb.append(line + NL);}in.close();result = sb.toString();} catch (IOException e) {e.printStackTrace();} finally {try {if (null != response) {response.close();}} catch (IOException e) {e.printStackTrace();}}return result;}
}

使用

@RestController
@RequestMapping("/http")
public class HttpTestController {@Autowiredprivate HttpClientUtil httpClientUtil;@GetMapping("test")public ApiResult test() {return ApiUtil.success();}@GetMapping("test1")public ApiResult test1() {String json = httpClientUtil.get("http://127.0.0.1:8888/http/test");return JSON.parseObject(json, new TypeReference<ApiResult>() {});}
}

详细使用可参考:https://www.cnblogs.com/qnlcy/p/15378446.html

2. OKhttp

OkHttp是一个高效的HTTP客户端,允许所有同一个主机地址的请求共享同一个socket连接;连接池减少请求延时;透明的GZIP压缩减少响应数据的大小;缓存响应内容,避免一些完全重复的请求。

当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。

使用方法

配置OkHttpClient。

使用示例

依赖配置

<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>3.10.0</version>
</dependency>

配置类

@Configuration
public class OkHttpConfig {@Beanpublic OkHttpClient okHttpClient() {return new OkHttpClient.Builder()// .sslSocketFactory(sslSocketFactory(), x509TrustManager()).retryOnConnectionFailure(false).connectionPool(pool()).connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).build();}@Beanpublic X509TrustManager x509TrustManager() {return new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}};}@Beanpublic SSLSocketFactory sslSocketFactory() {try {//信任任何链接SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());return sslContext.getSocketFactory();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (KeyManagementException e) {e.printStackTrace();}return null;}@Beanpublic ConnectionPool pool() {return new ConnectionPool(200, 5, TimeUnit.MINUTES);}
}

使用

@RestController
@RequestMapping("/http")
public class HttpTestController {@Autowiredprivate OkHttpUtil okHttpUtil;@GetMapping("test")public ApiResult test() {return ApiUtil.success();}@GetMapping("test2")public ApiResult test2() {String json = okHttpUtil.get("http://127.0.0.1:8888/http/test", null);return JSON.parseObject(json, new TypeReference<ApiResult>() {});}
}

3. Retrofit

retrofit是现在比较流行的网络请求框架,可以理解为okhttp的加强版,底层封装了okhttp。准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。

底层原理

应用程序通过Retrofit请求网络,实质上是使用Retrofit接口层封装请求参数、Header、Url等信息,之后由okhttp来完成后续的请求工作。在服务端返回数据后,okhttp将原始数据交给Retrofit,Retrofit根据用户需求解析。

Retrofit将okhttp请求抽象成java接口,采用注解描述和配置网络请求参数,用动态代理将该接口的注解“翻译”成一个Http请求,最后执行Http请求。

注意:接口中的每个方法的参数都要用注解标记,否则会报错。

Retrofit的优点

  • 超级解耦 ,接口定义、接口参数、接口回调不在耦合在一起
  • 可以配置不同的httpClient来实现网络请求,如okhttp、httpclient
  • 支持同步、异步、Rxjava
  • 可以配置不同反序列化工具类来解析不同的数据,如json、xml
  • 请求速度快,使用方便灵活简洁

相关注解

1. 请求方法

注解 描述
@GET get请求
@POST post请求
@PUT put请求
@DELETE delete请求
@PATCH patch请求,该请求是对put请求的补充,用于更新局部资源
@HEAD head请求
@OPTIONS options请求
@HTTP 通过注解,可以替换以上所有的注解,它拥有三个属性:method、path、hasBody

2. 请求头

注解 描述
@Headers 用于添加固定请求头,可以同时添加多个,通过该注解的请求头不会相互覆盖,而是共同存在
@Header 用于添加不固定的header,作为方法的参数传入,它会更新已有请求头

3. 请求参数

注解 描述
@Body 多用于Post请求发送非表单数据,根据转换方式将实例对象转化为对应字符串传递参数,比如使用Post发送Json数据,添加GsonConverterFactory则是将body转化为json字符串进行传递
@Filed 多用于Post方式传递参数,需要结合@FromUrlEncoded使用,即以表单的形式传递参数
@FiledMap 多用于Post请求中的表单字段,需要结合@FromUrlEncoded使用
@Part 用于表单字段,Part和PartMap与@multipart注解结合使用,适合文件上传的情况
@PartMap 用于表单字段,默认接受类型是Map<String,RequestBody>,可用于实现多文件上传
@Path 用于Url中的占位符
@Query 用于Get请求中的参数
@QueryMap 与Query类似,用于不确定表单参数
@Url 指定请求路径

4. 请求和响应格式(标记)

注解 描述
@FromUrlCoded 表示请求发送编码表单数据,每个键值对需要使用@Filed注解
@Multipart 表示请求发送form_encoded数据(使用于有文件上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值
@Streaming 表示响应用字节流的形式返回,如果没有使用注解,默认会把数据全部载入到内存中,该注解在下载大文件时特别有用

使用方法

自定义请求接口,采用注解描述和配置请求参数。

使用示例

本示例不是直接使用的retrofit依赖,而是使用的retrofit整合springboot依赖。

retrofit依赖

<dependency><groupId>com.squareup.retrofit2</groupId><artifactId>retrofit</artifactId><version>2.9.0</version>
</dependency>

retrofit整合springboot依赖

<dependency><groupId>com.github.lianjiatech</groupId><artifactId>retrofit-spring-boot-starter</artifactId><version>2.0.2</version>
</dependency>

启动类配置

@SpringBootApplication
@RetrofitScan("com.joker.http.retrofit")
public class SpringbootApplication {public static void main(String[] args) {SpringApplication.run(SpringbootApplication.class, args);}}

自定义接口

import com.github.lianjiatech.retrofit.spring.boot.annotation.RetrofitClient;
import com.joker.common.base.result.ApiResult;
import com.joker.pojo.User;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.http.*;
import java.util.Map;@RetrofitClient(baseUrl = "http://127.0.0.1:8888")
public interface RetrofitHttpApi {@GET("http/test")ApiResult test();/*** 简单的GET请求* @Query:用于Get请求中的参数*/@GET("http/test1")ApiResult test1(@Query("id") long id);/*** 不确定参数的GET请求* @QueryMap 与@Query类似,用于不确定表单参数。通过Map将不确定的参数存入,然后在方法体中带给网络接口。*/@GET("http/test2")ApiResult test2(@QueryMap Map<String, Object> map);/*** From表单POST请求* @FormUrlEncoded:请求格式注解,表明请求实体是一个From表单,每个键值对需要使用@Field注解* @Field:表单参数,而且需要配合@FormUrlEncoded使用* @return*/@FormUrlEncoded@POST("http/test3")ApiResult test3(@Field("name") String name, @Field("age") Integer age);/*** 不确定参数的From表单POST请求*/@FormUrlEncoded@POST("http/test4")ApiResult test4(@FieldMap Map<String, Object> map);/*** json方式POST请求*/@POST("http/test5")ApiResult test5(@Body User user);/*** 文件上传表单POST请求* @Multipart:表示请求实体是一个支持文件上传的表单,需要配合@Part和@PartMap使用,适用于文件上传* @Part:用于表单字段,适用于文件上传的情况,@Part支持三种类型:RequestBody、MultipartBody.Part任意类型* @PartMap:用于多文件上传, 与@FieldMap和@QueryMap的使用类似* @return*/@Multipart@POST("http/test6")ApiResult test6(@Part("name") RequestBody name, @Part MultipartBody.Part file);/*** 多文件上传POST请求* @param map* @return*/@Multipart@POST("http/test7")ApiResult test7(@PartMap Map<String, MultipartBody.Part> map);/*** 路径参数请求* @param id* @return*/@GET("http/test8/{id}")ApiResult test8(@Path("id") Long id);/*** 请求头参数请求* @Header:请求头注解,用于添加不固定请求头* @param token* @return*/@GET("http/test9")ApiResult test9(@Header("token") String token);/*** 请求头参数请求* @Headers:请求头注解,用于添加固定请求头,可以添加多个* @return*/@Headers({"version:1.0","os:windows"})@GET("http/test10")ApiResult test10();/*** 动态url请求* @Url:将地址以参数的形式传入,请求方法注解中定义的url忽略* @param url* @return*/@GET("http/test11")ApiResult test11(@Url String url);/*** 下载文件请求* @Streaming:响应体的数据用流的方式返回,使用于返回数据比较大,该注解在下载大文件时特别有用* @return*/@Streaming@POST("http/test12")ResponseBody test12();/*** @HTTP:注解的作用是替换@GET、@POST、@PUT、@DELETE、@HEAD以及更多拓展功能* @return*/@HTTP(method = "GET", path = "http/test13", hasBody = false)ApiResult test13();
}

详细使用可参考:https://blog.csdn.net/why_still_confused/article/details/108041657

4. RestTemplate

RestTemplate是Spring提供的用于访问Rest服务的客户端库。它提供了一套接口,实现这套接口的http库都可以通过RestTemplate来使用。

常用的有:

  1. JDK自带的HttpURLConnection
  2. Apache的HttpClient
  3. OKHttp

RestTemplate默认使用的http库是JDK自带的HttpURLConnection来建立HTTP连接(使用SimpleClientHttpRequestFactory客户端)。另外三方http库通过实现ClientHttpRequestFactory接口来自定义客户端,可以通过RestTemplate的setRequestFactory指定要使用的客户端。

ClientHttpRequestFactory接口的实现类:

  1. SimpleClientHttpRequestFactory(Spring默认使用的客户端)
  2. HttpComponentsClientHttpRequestFactory(Apache HttpClient使用的客户端)
  3. OkHttp3ClientHttpRequestFactory(OKHttp使用的客户端)

RestTemplate在spring-web包中。Spring项目有spring-web包即可,SpringBoot项目有spring-boot-starter-web包即可,如果要少使用Apache的HttpClient、OKHttp等相关三方http库,则还需要器对应的包。

RestTemplate内部模板使用HttpMessageConverter实例将HTTP消息转换为POJO和从POJO转换。主要MIME类型的转换器是默认注册的,也可以通过setMessageConverters方法注册其他转换器。

RestTemplate提供操作http的方法

方法名称 支持的HTTP方法 方法描述
getForObject GET 直接返回响应对象,可设置路径参数
getForEntity GET 返回封装的响应对象,可设置路径参数
postForObject POST 直接返回响应对象,可设置路径参数,可设置请求body和请求header
postForEntity POST 返回封装的响应对象,可设置路径参数,可设置请求body和请求header
postForLocation POST 返回URI对象,适用于返回网络资源的请求方式。可设置路径参数,可设置请求body和请求header
put PUT 无返回值,可设置路径参数,可设置请求body和请求header
delete DELETE 无返回值,可设置路径参数
headForHeaders HEAD 返回HttpHeaders,可设置路径参数
optionsForAllow OPTIONS 返回Set<HttpMethod>,可设置路径参数
execute 都支持 直接返回响应对象,通用请求方法
exchange 都支持 返回封装的响应对象,通用请求方法

注意:封装的响应对象除了能获取到响应对象,还能额外获取到响应状态,响应Header信息。

使用方法

配置RestTemplate(如果不配置客户端,会使用默认的客户端SimpleClientHttpRequestFactory),就可以直接使用。

方法1

使用spring默认客户端SimpleClientHttpRequestFactory

    @Beanpublic RestTemplate restTemplate() {RestTemplate restTemplate = new RestTemplate();return restTemplate;}

方法2

使用Apache HttpClient客户端(HttpComponentsClientHttpRequestFactory)。

    @Bean@DependsOn("httpClient")public RestTemplate restTemplate3(HttpClient httpClient) {RestTemplate restTemplate = new RestTemplate(httpComponentsClientHttpRequestFactory(httpClient));setRestTemplate(restTemplate);return restTemplate;}@Beanpublic ClientHttpRequestFactory httpComponentsClientHttpRequestFactory(HttpClient httpClient) {return new HttpComponentsClientHttpRequestFactory();}

HttpClient的配置参考上面HttpClient的使用示例。

方法3

使用OKHttp客户端(OkHttp3ClientHttpRequestFactory)。

    @Bean@DependsOn("okHttpClient")public RestTemplate restTemplate4(OkHttpClient okHttpClient) {RestTemplate restTemplate = new RestTemplate(okHttp3ClientHttpRequestFactory(okHttpClient));setRestTemplate(restTemplate);return restTemplate;}@Beanpublic ClientHttpRequestFactory okHttp3ClientHttpRequestFactory(OkHttpClient okHttpClient) {return new OkHttp3ClientHttpRequestFactory(okHttpClient);}

OkHttpClient的配置参考上面OKhttp的使用示例。

使用示例

1.先按上面的使用方法配置好RestTemplate。

2.进行接口测试,示例如下:

    @Autowiredprivate RestTemplate restTemplate;@GetMapping("test4")public ApiResult test4() {// 1.Get请求ApiResult result = restTemplate.getForObject(getUrl("get"), ApiResult.class);System.out.println("Get请求:" + JSON.toJSONString(result));// 2.设置路径参数的Get请求result = restTemplate.getForObject(getUrl("get/{id}"), ApiResult.class, 123);System.out.println("设置路径参数的Get请求:" + JSON.toJSONString(result));// 3.封装返回对象的Get请求ResponseEntity<ApiResult> responseEntity = restTemplate.getForEntity(getUrl("get"), ApiResult.class);System.out.println("封装返回对象的Get请求:" + responseEntity.getBody());// 4.设置header的Get请求HttpHeaders headers = new HttpHeaders();headers.add("token", "token");ResponseEntity<ApiResult> response = restTemplate.exchange(getUrl("get"), HttpMethod.GET, new HttpEntity<String>(headers), ApiResult.class);System.out.println("设置header的Get请求:" + response.getBody());// 5.Post请求User user = new User();user.setId("1");result = restTemplate.postForObject(getUrl("post"), user, ApiResult.class);System.out.println("Post请求:" + result);// 6.设置header的Post请求response = restTemplate.postForEntity(getUrl("post"), new HttpEntity<>(user, headers), ApiResult.class);System.out.println("设置header的Post请求:" + response.getBody());// 7.设置header的put请求// 无返回值restTemplate.put(getUrl("put"), new HttpEntity<>(user, headers));// 带返回值response = restTemplate.exchange(getUrl("put"), HttpMethod.PUT, new HttpEntity<>(user, headers), ApiResult.class);System.out.println("设置header的put请求:" + response.getBody());// 8.设置路径参数的del请求// 无返回值restTemplate.delete(getUrl("delete/{id}"), 123);// 带返回值response = restTemplate.exchange(getUrl("delete/{id}"), HttpMethod.DELETE, null, ApiResult.class,123);System.out.println("设置路径参数的del请求:" + response.getBody());return ApiUtil.success();}

Java常用http请求库相关推荐

  1. 推荐使用的几款Java常用基础工具库

    通用工具类(字符串.时间格式化.BeanUtils.IO) 1. commons-lang3库 1.1. org.apache.commons.lang3.StringUtils类 日常代码中,我们经 ...

  2. Java 常用HTTP请求工具类HttpUtils

    .pom依赖 <!-- httpclient --><dependency><groupId>org.apache.httpcomponents</group ...

  3. Java常用的开发库推荐

    01.什么是工具包 基本上,每个项目里都有一个包,叫做utils.这个包专门承载我们自己项目的工具类,比如常见的DateUtils.HttpUtils.Collections 所谓Utils就是:这个 ...

  4. java常用的发送http请求的工具方法

    java常用的HttpURLConnection 方式发送http请求的工具方法 需要的jar包有jsp-api.jar .servlet-api.jar .dom4j.jar package cn. ...

  5. Java常用第三方库大全西安尚学堂

    Java常用第三方库大全 一.JAVA核心扩展 JAVA的标准库虽然提供了那些最基本的数据类型操作方法,但仍然对一些常见的需求场景,缺少实用的工具类.而另一些则是JAVA标准库本身不够完善,需要第三方 ...

  6. Java 常用工具类(12) : java后台发送http请求

    参考 : java http 发送post请求-json格式_Oh_go_boy的博客-CSDN博客 Java发送Http请求 - 玄同太子 - 博客园 org.apache.http 在Maven中 ...

  7. 送你38个常用的Python库,数值计算、可视化、机器学习等8大领域都有了

    来源:大数据DT(ID:bigdatadt) 作者:李明江 张良均 周东平 张尚佳 内容摘编自<Python3智能数据分析快速入门> 本文约5200字,建议阅读10分钟. 本文为你总结了常 ...

  8. Java高级阶段考试题库

    Java高级阶段考试题库 1.Maven中A依赖B,B依赖C,那么A可以使用C中的类吗? 答案: 此时要看B依赖C时的范围(scope),如果是compile范围则A可以使用C,如果test或prov ...

  9. java常用英语单词

    abstract (关键字) 抽象 ['.bstr.kt] access vt.访问,存取 ['.kses]'(n.入口,使用权) algorithm n.算法 ['.lg.riem] annotat ...

最新文章

  1. Meta为元宇宙建全球最快AI超算,1.6万个A100 GPU,英伟达都赚麻了
  2. MySQL中update修改数据与原数据相同会再次执行吗?
  3. 判断两条线段是否相交
  4. 关于JavaScript处理字符串的常见操作
  5. 扎心!程序员泪奔的8个瞬间
  6. 以吃货的角度理解 IaaS,PaaS,SaaS 是什么
  7. 我个人的CRUD故事-或我如何来到CUBA平台
  8. Android中如何使按钮的背景变得透明
  9. 初中信息技术说课稿_语文说课稿模板一等奖
  10. 计算机辅助翻译和机器翻译的区别,计算机辅助翻译和机器翻译有何区别?
  11. 小猪短租陈驰:共享经济不是简单的资本游戏
  12. 斯特陵往事(转自清韵论坛 冯·迪特里施专栏)
  13. 详述 Kafka 基本原理
  14. 苹果6plus几核处理器_iOS 13.4 Beta3发布:苹果在布局,越狱软件也更新!
  15. 画意三峡---先睹为快
  16. 多传感器数据融合发展综述
  17. linux大型机如何下载数据,如何从大型机传输PS文件到Linux服务器?
  18. JAVA设计模式——第 8 章 适配器模式【Adapter Pattern】(转)
  19. CSS文本溢出省略号在Grid / Flex中不起作用
  20. 原来Glide是这样加载GIF图的

热门文章

  1. 《网页制作与网站建设从入门到精通》版权
  2. 完美解决eNSP virtualBox安装完成后只有VirtualBox Host-Only Network #2,Ensp利用虚拟网卡的设备无法启动。eNSP设备AC;AP设备报41错误解决办法。
  3. python连接appium启动模拟器
  4. 当AI大闹万圣节,比恐怖更恐怖?
  5. 最新抖音快手随机看小姐姐网站源码修复
  6. GPT转MBR怎么转?
  7. Win8.1 64位 安装KesionCMS程序和IIS配置
  8. java-php-python-毕业生论文管理系统计算机毕业设计
  9. HDUOJ 1281 棋盘游戏
  10. 窄带波束形成——频域的波束形成