Java常用http请求库
文章目录
- 常用http请求库
- 1. HttpClient
- 使用方法
- 使用示例
- 2. OKhttp
- 使用方法
- 使用示例
- 3. Retrofit
- 相关注解
- 使用方法
- 使用示例
- 4. RestTemplate
- 使用方法
- 使用示例
常用http请求库
- HttpClient:apache旗下项目,代码较复杂和冗余,且需自己处理资源回收,不推荐直接使用。
- OKhttp:square公司开源的java版本http客户端工具。
- retrofit:square公司开源的基于okhttp进一步封装的retrofit工具,可以把它理解为OKhttp的加强版。用来支持通过接口的方式发起http请求。
- 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的一套客户端)。
使用方法
- 创建HttpClient
- 创建http请求,如HttpGet、HttpPost
- 添加请求参数
- 添加请求设置,如超时等
- 使用HttpClient执行http请求
- 读取返回内容并释放连接
使用示例
环境依赖
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来使用。
常用的有:
- JDK自带的HttpURLConnection
- Apache的HttpClient
- OKHttp
RestTemplate默认使用的http库是JDK自带的HttpURLConnection来建立HTTP连接(使用SimpleClientHttpRequestFactory客户端)。另外三方http库通过实现ClientHttpRequestFactory接口来自定义客户端,可以通过RestTemplate的setRequestFactory指定要使用的客户端。
ClientHttpRequestFactory接口的实现类:
- SimpleClientHttpRequestFactory(Spring默认使用的客户端)
- HttpComponentsClientHttpRequestFactory(Apache HttpClient使用的客户端)
- 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请求库相关推荐
- 推荐使用的几款Java常用基础工具库
通用工具类(字符串.时间格式化.BeanUtils.IO) 1. commons-lang3库 1.1. org.apache.commons.lang3.StringUtils类 日常代码中,我们经 ...
- Java 常用HTTP请求工具类HttpUtils
.pom依赖 <!-- httpclient --><dependency><groupId>org.apache.httpcomponents</group ...
- Java常用的开发库推荐
01.什么是工具包 基本上,每个项目里都有一个包,叫做utils.这个包专门承载我们自己项目的工具类,比如常见的DateUtils.HttpUtils.Collections 所谓Utils就是:这个 ...
- java常用的发送http请求的工具方法
java常用的HttpURLConnection 方式发送http请求的工具方法 需要的jar包有jsp-api.jar .servlet-api.jar .dom4j.jar package cn. ...
- Java常用第三方库大全西安尚学堂
Java常用第三方库大全 一.JAVA核心扩展 JAVA的标准库虽然提供了那些最基本的数据类型操作方法,但仍然对一些常见的需求场景,缺少实用的工具类.而另一些则是JAVA标准库本身不够完善,需要第三方 ...
- Java 常用工具类(12) : java后台发送http请求
参考 : java http 发送post请求-json格式_Oh_go_boy的博客-CSDN博客 Java发送Http请求 - 玄同太子 - 博客园 org.apache.http 在Maven中 ...
- 送你38个常用的Python库,数值计算、可视化、机器学习等8大领域都有了
来源:大数据DT(ID:bigdatadt) 作者:李明江 张良均 周东平 张尚佳 内容摘编自<Python3智能数据分析快速入门> 本文约5200字,建议阅读10分钟. 本文为你总结了常 ...
- Java高级阶段考试题库
Java高级阶段考试题库 1.Maven中A依赖B,B依赖C,那么A可以使用C中的类吗? 答案: 此时要看B依赖C时的范围(scope),如果是compile范围则A可以使用C,如果test或prov ...
- java常用英语单词
abstract (关键字) 抽象 ['.bstr.kt] access vt.访问,存取 ['.kses]'(n.入口,使用权) algorithm n.算法 ['.lg.riem] annotat ...
最新文章
- Meta为元宇宙建全球最快AI超算,1.6万个A100 GPU,英伟达都赚麻了
- MySQL中update修改数据与原数据相同会再次执行吗?
- 判断两条线段是否相交
- 关于JavaScript处理字符串的常见操作
- 扎心!程序员泪奔的8个瞬间
- 以吃货的角度理解 IaaS,PaaS,SaaS 是什么
- 我个人的CRUD故事-或我如何来到CUBA平台
- Android中如何使按钮的背景变得透明
- 初中信息技术说课稿_语文说课稿模板一等奖
- 计算机辅助翻译和机器翻译的区别,计算机辅助翻译和机器翻译有何区别?
- 小猪短租陈驰:共享经济不是简单的资本游戏
- 斯特陵往事(转自清韵论坛 冯·迪特里施专栏)
- 详述 Kafka 基本原理
- 苹果6plus几核处理器_iOS 13.4 Beta3发布:苹果在布局,越狱软件也更新!
- 画意三峡---先睹为快
- 多传感器数据融合发展综述
- linux大型机如何下载数据,如何从大型机传输PS文件到Linux服务器?
- JAVA设计模式——第 8 章 适配器模式【Adapter Pattern】(转)
- CSS文本溢出省略号在Grid / Flex中不起作用
- 原来Glide是这样加载GIF图的
热门文章
- 《网页制作与网站建设从入门到精通》版权
- 完美解决eNSP virtualBox安装完成后只有VirtualBox Host-Only Network #2,Ensp利用虚拟网卡的设备无法启动。eNSP设备AC;AP设备报41错误解决办法。
- python连接appium启动模拟器
- 当AI大闹万圣节,比恐怖更恐怖?
- 最新抖音快手随机看小姐姐网站源码修复
- GPT转MBR怎么转?
- Win8.1 64位 安装KesionCMS程序和IIS配置
- java-php-python-毕业生论文管理系统计算机毕业设计
- HDUOJ 1281 棋盘游戏
- 窄带波束形成——频域的波束形成