【2023】java常用HTTP客户端对比以及使用(HttpClient/OkHttp/WebClient)

💻目录

  • 1、介绍
  • 2、使用
    • 2.1、添加配置
      • 2.1.1、依赖
      • 2.1.2、工具类
      • 2.1.3、实体
      • 2.1.4、Controller接口
    • 2.2、Apache HttpClient使用
    • 2.3 、OkHttp使用
    • 2.4、WebClient使用

1、介绍

现在java使用的http客户端主要包括以下几种
java使用http通讯
而这些中使用得最频繁的主要是:

  1. Apache HttpClient:这是一个功能强大且广泛使用的第三方库,用于进行HTTP通讯。它提供了更高级的API和更丰富的功能,比如支持连接池、认证、重定向、Cookie管理等。Apache HttpClient可以作为独立的库使用,也可以作为Apache HttpComponents项目的一部分。

  2. OkHttp:这是另一个流行的第三方库,用于进行HTTP通讯。OkHttp提供了简洁的API和高性能的特性,支持同步和异步请求,以及连接池、缓存、拦截器等功能。OkHttp也是Square公司的一个开源项目。

  3. Spring WebClient:这是Spring框架中的一个模块,是RestTemplate的升级版,用于进行非阻塞的HTTP通讯。它基于Reactive Streams编程模型,适用于构建响应式的应用程序。Spring WebClient提供了简单的API来发送HTTP请求和处理响应,可以与Spring WebFlux等模块一起使用。

2、使用

下面展示了Apache HttpClient和OkHttp以及Spring WebClient的常用使用方式,包括get和post

2.1、添加配置

2.1.1、依赖

        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 -->
        <dependency>
            <groupId>org.apache.httpcomponents.client5</groupId>
            <artifactId>httpclient5</artifactId>
        </dependency>
	 <!--okhttp-->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.22</version>
        </dependency>
        <!--webClient-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

2.1.2、工具类

  • Result:统一返回类
@Data
public class Result<T> {
    //状态码
    private Integer code;
    //信息
    private String message;
    //数据
    private T data;

    private Result(){}

    //设置数据,返回对象的方法
    public static <T> Result<T> build(T data, ResultCodeEnum resultCodeEnum) {
        //创建Result对象,设置值,返回对象
        Result<T> result = new Result<>();
        //判断返回结果中是否需要数据
        if (data != null) {
            //设置数据到result对象
            result.setData(data);
        }
        //设置其他值
        result.setCode(resultCodeEnum.getCode());
        result.setMessage(resultCodeEnum.getMessage());
        //返回设置值之后的对象
        return result;
    }

    //成功的方法
    public static <T> Result<T> ok(T data) {
        return build(data, ResultCodeEnum.SUCCESS);
    }

    //成功的方法
    public static <T> Result<T> ok() {
        return build(null, ResultCodeEnum.SUCCESS);
    }

    //失败的方法
    public static <T> Result<T> fail(T data) {
        return build(data, ResultCodeEnum.FAIL);
    }
}


  • ResultCodeEnum:返回结果
@Getter
public enum  ResultCodeEnum {

    SUCCESS(200,"成功"),
    FAIL(201, "失败"),
    ;

    private Integer code;
    private String message;

    ResultCodeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}


2.1.3、实体

  • User
@Data
public class User {
    private String name;
    private Integer age;
    private Integer post;
}
  • ProductInfo:返回数据
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ProductInfo implements Serializable {

    private Long id;
    /**销量*/
    private Integer sale;

    /**价格*/
    private Integer price;
    /**名称*/
    private String name;
    /**类型*/
    private Integer type;
    /**端口*/
    private Integer port;
}

2.1.4、Controller接口

@RestController
@RequestMapping("/productInfo/index")
public class ProductInfoController {

    @Resource
    private ProductInfoService productInfoService;

    //    获取当前服务的端口
    @Value("${server.port}")
    private Integer port;

    @GetMapping("/get")
    public Result<?> get(Integer type){
        List<ProductInfo> productInfoList = getProductInfoList(type);
        System.out.println(productInfoList);
        return Result.ok(productInfoList);
    }


    @PostMapping("/post")
    public Result<?> post(@RequestBody User user){
        Integer post = user.getPost();

        List<ProductInfo> productInfoList = getProductInfoList(post);
        System.out.println(productInfoList);
        return Result.ok(productInfoList);
    }


    public List<ProductInfo> getProductInfoList(Integer type) {

        ProductInfo productInfo3 = new ProductInfo(3l,800,20,"哈密瓜1",1,port);
        ProductInfo productInfo1 = new ProductInfo(1l,50,8,"苹果1",1,port);
        ProductInfo productInfo2 = new ProductInfo(2l,200,13,"牛肉1",2,port);
        ProductInfo productInfo4 = new ProductInfo(4l,50,9,"青菜1",2,port);
        /*        实际项目中,会从数据库查出数据 */
        List<ProductInfo> productInfoList = Arrays.asList(productInfo1,productInfo2,productInfo3,productInfo4);

//        根据传入的类型返回指定类型
        List<ProductInfo> result = productInfoList.stream()
                .filter(productInfo -> productInfo.getType() == type)
                .collect(Collectors.toList());
        return result;
    }
}

2.2、Apache HttpClient使用

  • get使用
    默认只能同步异步需要加额外的依赖,get请求不能携带参数,只能通过拼接路径
        <!--异步请求-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpasyncclient</artifactId>
        </dependency>
    public static void get(CloseableHttpClient httpClient,String url){
//            连接对象
        try {
//        HttpGet不能携带参数,如果需要参数只能通过拼接
            HttpGet httpGet = new HttpGet(url+"?type=1");

            String execute = httpClient.execute(httpGet, response -> {
                JSONObject entries = new JSONObject(EntityUtils.toString(response.getEntity()));
                Result result = JSONUtil.toBean(entries, Result.class);
                if (result.getCode() == 200) {
                    String data = result.getData().toString();
                    System.out.println(data);
                    return data;
                } else {
                    System.err.println(result.getMessage());
                    return result.getMessage();
                }
            });
            System.out.println("get成功结果:"+execute);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • post
    post请求,通过setEntity()给HttpPost对象添加请求对象
    public static void post(CloseableHttpClient httpClient,String url){

        HttpPost httpPost = new HttpPost(url);
        User user = new User();
        user.setPost(1);
//        添加参数对象
        httpPost.setEntity(new StringEntity(JSONUtil.toJsonStr(user)));
        // 设置请求头
        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");

        try {
            String execute = httpClient.execute(httpPost, response -> {
                JSONObject entries = new JSONObject(EntityUtils.toString(response.getEntity()));
                Result result = JSONUtil.toBean(entries, Result.class);
                if (result.getCode() == 200) {
                    String data = result.getData().toString();
                    log.info(data);
                    return data;
                } else {
                    log.error(result.getMessage());
                    return result.getMessage();
                }
            });
            log.info("HttpClient的post成功结果:"+execute);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 全部代码

执行步骤

  1. 创建CloseableHttpClient对象
  2. 创建get获取post请求对象
  3. 通过execute()方法发送请求
  4. 通过response.getEntity()获取响应回来的数据
@Slf4j
public class HttpClientUtil {

    private static String postUrl = "http://localhost:8202/productInfo/index/post";
    private static String getUrl = "http://localhost:8202/productInfo/index/get";

    public static void main(String[] args) {
        try {
//            创建客户端对象
            CloseableHttpClient client = HttpClients.createDefault();
            get(client,getUrl);
            post(client,postUrl);
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void get(CloseableHttpClient httpClient,String url){
//            连接对象
        try {
//        HttpGet不能携带参数,如果需要参数只能通过拼接
            HttpGet httpGet = new HttpGet(url+"?type=1");

            String execute = httpClient.execute(httpGet, response -> {
                JSONObject entries = new JSONObject(EntityUtils.toString(response.getEntity()));
                Result result = JSONUtil.toBean(entries, Result.class);
                if (result.getCode() == 200) {
                    String data = result.getData().toString();
                    log.info(data);
                    return data;
                } else {
                    log.info(result.getMessage());
                    return result.getMessage();
                }
            });
            log.info("HttpClient的get成功结果:"+execute);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void post(CloseableHttpClient httpClient,String url){

        HttpPost httpPost = new HttpPost(url);
        User user = new User();
        user.setPost(1);
//        添加参数对象
        httpPost.setEntity(new StringEntity(JSONUtil.toJsonStr(user)));
        // 设置请求头
        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");

        try {
            String execute = httpClient.execute(httpPost, response -> {
                JSONObject entries = new JSONObject(EntityUtils.toString(response.getEntity()));
                Result result = JSONUtil.toBean(entries, Result.class);
                if (result.getCode() == 200) {
                    String data = result.getData().toString();
                    log.info(data);
                    return data;
                } else {
                    log.error(result.getMessage());
                    return result.getMessage();
                }
            });
            log.info("HttpClient的post成功结果:"+execute);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.3 、OkHttp使用

执行步骤

  1. 创建OkHttpClient对象,用于配置和管理HTTP请求的行为
  2. 创建Request对象,用于描述要发送的HTTP请求。Request对象包含了URL、请求方法、请求头、请求体等信息。
  3. 创建Call对象,使用OkHttpClient的newCall()方法,传入Request对象,创建一个Call对象,Call对象表示一次HTTP请求的调用,可以用于执行同步或异步的请求。
  4. 执行请求,同步通过Call对象的execute()方法来;异步通过Call对象的enqueue()方法来执行请求,并通过回调函数处理响应
  5. 解析响应,通过response.body()得到响应的内容在通过json解析。
@Slf4j
public class OkHttpUtil {

    private static String postUrl = "http://localhost:8202/productInfo/index/post";
    private static String getUrl = "http://localhost:8202/productInfo/index/get";


    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(30, TimeUnit.SECONDS) //连接超时时间
                .writeTimeout(30,TimeUnit.SECONDS)  //请求超时时间
                .readTimeout(30,TimeUnit.SECONDS)  //响应超时时间
                .build();
//        get(client);
//        asyncGet(client);
//        post(client);
        asyncPost(client);
    }

    /**
     * 同步get
     * @param client        
     * @return void
     */
    public static void get(OkHttpClient client){
//        创建get请求对象
        Request request = new Request.Builder()
                .url(getUrl+"?type=1")
                .get()
                .header("Content-Type", "application/json") // 设置Content-Type请求头
                .build();

        try {
//            返回响应对象
            Response response = client.newCall(request).execute();
//              验证响应是否成功
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
//              解码对象
            Result result = JSONUtil.toBean(response.body().string(), Result.class);
            Object data = result.getData();
            System.out.println(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 异步get
     * @param client
     * @return void
     */
    public static void asyncGet(OkHttpClient client){
        //        创建get请求对象
        Request request = new Request.Builder()
                .url(getUrl+"?type=1")
                .get()   //不指定请求方式默认是get
                .build();
//           异步发送请求,没有返回结果
        client.newCall(request).enqueue(new Callback() {

//               处理失败请求
            @Override
            public void onFailure(Call call, IOException e) {
                log.debug("Unexpected code " + e.getMessage());
                e.printStackTrace();
            }

//            处理成功请求
            @Override
            public void onResponse(Call call, Response response) throws IOException {
//              验证响应是否成功
                if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
//              解码对象
                Result result = JSONUtil.toBean(response.body().string(), Result.class);
                Object data = result.getData();
                System.out.println(data);
            }
        });
    }


    /**
     * 同步post
     * @param client
     * @return void
     */
    public static void post(OkHttpClient client){
        User user = new User();
        user.setPost(1);

        String str = JSONUtil.toJsonStr(user);
        Request request = new Request.Builder()
                .url(postUrl)
                .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), str))
                .build();

        Call call = client.newCall(request);
        try {
            Response response = call.execute();
            //              验证响应是否成功
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
//              解码对象
            Result result = JSONUtil.toBean(response.body().string(), Result.class);
            Object data = result.getData();
            log.info("post请求成功,返回结果:{}",data);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 异步post请求
     * @param client        
     * @return void
     */
    public static void asyncPost(OkHttpClient client){
        User user = new User();
        user.setPost(1);
//          把对象转为json字符串
        String str = JSONUtil.toJsonStr(user);

        Request request = new Request.Builder()
                .url(postUrl)
                .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), str))
                .build();

        Call call = client.newCall(request);
//       异步请求没返回
        call.enqueue(new Callback() {
//            请求异常
            @Override
            public void onFailure(Call call, IOException e) {
                log.debug("Unexpected code " + e.getMessage());
                e.printStackTrace();
            }
//            请求成功
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //              验证响应是否成功
                if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
//              解码对象
                Result result = JSONUtil.toBean(response.body().string(), Result.class);
                Object data = result.getData();
                log.info("异步post请求成功,返回结果:{}",data);
            }
        });
    }
}

2.4、WebClient使用

执行步骤:

  1. 创建WebClient对象,推荐使用WebClient.builder()的方式创建,因为可以自定义配置客户端的参数,直接new是只能使用默认的配置。

  2. 构建请求,直接通过webClient对象,如get()、post()等,构建一个请求(如果没有指定请求方式),默认是get请求。

  3. 处理响应:使用响应对象(如Mono、Flux等)来处理响应数据。你可以通过操作符(如map()、flatMap()等)对响应进行转换、过滤、合并等操作。

  4. 订阅响应:使用subscribe()方法来订阅响应流,启动请求并处理响应数据。你可以通过回调函数或操作符链来处理响应数据。

@Component
@Slf4j
public class WebClientUtil {
    private static String postUrl = "http://localhost:8202/productInfo/index/post";
    private static String getUrl = "http://localhost:8202/productInfo/index/get";



    /**
     * 同步执行get请求
     * @param webClient
     * @return void
     */
    public void get(WebClient webClient){
        Mono<Result> mono = webClient.get()
                .uri(getUrl + "?type=2")
                .retrieve()
                .bodyToMono(Result.class);

//        获取返回结果 block()会进行堵塞,等待返回结果
        Result result = mono.block();
        if (result.getCode()==200){
            log.info("get请求返回结果{}",result.getData());
        }
    }

    /**
     * 异步get
     * @return void
     */
    public void asyncGet(){
        HttpClient client = HttpClient.create()
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)  //设置连接超时
                .doOnConnected(conn -> conn
                        .addHandler(new ReadTimeoutHandler(10, TimeUnit.SECONDS)) //写入超时
                        .addHandler(new WriteTimeoutHandler(10))); //读取超时


        //        也可以以这种方式创建WebClient可以添加请求头和url以及一些参数;
        WebClient webClient = WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(client))
                .baseUrl(getUrl)

                .defaultHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)")
//                .defaultCookie()  //添加请求Cookie
                .build();

//        获取返回结果
        Mono<Result> mono = webClient.get()
                .uri( "?type=2")// 请求路径,会拼接上面的
                .accept(MediaType.APPLICATION_JSON)

//                .retrieve() //获取响应体
//                .bodyToMono(Result.class);  //指定获取的类型,直接获取结果。

//                或者通过该方式手动处理结果
                .exchangeToMono(response->{
                    if (response.statusCode().equals(HttpStatus.OK)) {
//                        成功返回
                        return response.bodyToMono(Result.class);
                    }
                    else {
//                        失败返回
                        return response.createException().flatMap(Mono::error);
                    }
                });


//        异步获取返回结果
        mono
                .subscribe(result -> {

                    if (result.getCode() == 200) {
                        log.info("get请求返回结果{}", result.getData());
                    }
                });

        System.out.println("执行完成");

    }
    
    /**
     * 同步post
     * @return void
     */
    public void post(){
        // 创建 WebClient 对象
        WebClient webClient = WebClient.builder()
                .baseUrl(getUrl)
                .build();
        User user = new User();
        user.setPost(2);

        Mono<Result> mono = webClient
                .post()
                .uri(postUrl)
                .contentType(MediaType.APPLICATION_JSON)
                .header("token","12321412")
                .body(BodyInserters.fromValue(user))
                .retrieve()
                .bodyToMono(Result.class);
        Result result = mono.block();
        if (result.getCode()==200){
            log.info("post请求返回结果{}",result.getData());
        }
    }


    /**
     * WebClient异步请求
     * @return void
     */
    public void asyncPost(){
        // 创建 WebClient 对象
        WebClient webClient = WebClient.builder()
                .baseUrl(getUrl)
                .build();
        User user = new User();
        user.setPost(2);

        Mono<Result> mono = webClient
                .post()
                .uri(postUrl)
                .contentType(MediaType.APPLICATION_JSON)  //指定类型
                .header("token","12321412")  //添加请求头
                .body(BodyInserters.fromValue(user)) //添加请求对象
                .retrieve()
                .bodyToMono(Result.class);
//          异步请求
        mono.subscribe(result -> {
            if (result.getCode()==200){
                log.info("post异步请求返回结果{}",result.getData());
            }
        });
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/307115.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

持续领跑云安全赛道!安全狗多项安全能力获认可

近日&#xff0c;以“数字安全 未来可期”为主题的“2024安全市场年度大会”在北京成功举行。 作为国内云原生安全领导厂商&#xff0c;安全狗也受邀出席此次活动。 厦门服云信息科技有限公司&#xff08;品牌名&#xff1a;安全狗&#xff09;创办于2013年&#xff0c;是国内领…

[②C++ Boost]: Boost库编译,arm交叉编译方法

前言 Boost是十分实用的C库&#xff0c;如果想在arm环境下使用&#xff0c;就需要自己下载源码编译&#xff0c;本篇博客就记录下Boost库的编译方法。 下载Boost源码 Boost源码的下载路径可以使用&#xff1a;https://sourceforge.net/projects/boost/files/boost/ 编译 …

MySQL之导入、导出远程备份

一、Navicat工具导入、导出 1.1 导入 第一步&#xff1a; 右键&#xff0c;点击运行SQL文件 第二步&#xff1a; 选择要运行的SQL&#xff0c;点击开始 第三步&#xff1a; 关闭即可 1.2 导出 第一步&#xff1a; 右键选择&#xff0c;导出向导 第二步&#xff1a; 选择SQL脚…

require.context的作用

1、什么是 require.context 一个 webpack 的 api &#xff0c;通过该函数可以获取一个上下文&#xff0c;从而实现工程自动化&#xff08;遍历文件夹的文件&#xff0c;从中获取指定文件&#xff0c;自动导入模块&#xff09;。 在前端工程中&#xff0c;如果一个文件夹中的模块…

亚信安全深度解读2023年中国网络安全重要政策法规

亚信安全在对2023年国内网络安全政策的持续跟踪和研究基础上进行了详细分析。观察整体态势&#xff0c;本年度网络安全政策的发布呈现出高密度特征&#xff0c;共计引起行业高度关注的政策达50余项。数据安全领域、个人信息保护和数据跨境安全成为关注的热点&#xff0c;分别有…

ChatGPT给出最有用建议居然是去网上搜索

今天共享服务器的学员发现了一个问题&#xff0c;就是装不了rJava。但是&#xff0c;我装了下&#xff0c;发现没问题啊&#xff0c;然后&#xff0c;我就问他&#xff0c;他是哪里加载的&#xff0c;他回答的说&#xff0c;是在Rstduio-server上。 我觉得此时有蹊跷&#xff0…

状态管理小能手:Cookie 和 Session

1. 引言 大家好&#xff0c;我是小❤&#xff0c;一个漂泊江湖多年的 985 非科班程序员&#xff0c;曾混迹于国企、互联网大厂和创业公司的后台开发攻城狮。 假期抢票的尴尬事件 最近小❤在抢出行的高铁票时&#xff0c;发生了一件尴尬的事情。 这不是临近假期了嘛&#xf…

autoxjs 安卓爬虫自动化

autoxjs 安卓爬虫自动化 我这里只是测试请勿用于违法的 我这里是小红书 文章目录 autoxjs 安卓爬虫自动化前言一、自动刷直播间并且抓取商品已经粉丝数量等&#xff1f;总结 前言 欢迎来到AutoXJS的世界&#xff0c;这是一个充满创新、挑战和技术探索的领域。在这个引领未来的…

Embedded-Project项目介绍

Embedded-Project项目介绍 Server后端项目后端启动连接数据库启动时可能遇到的问题架构介绍 web前端项目前端启动启动时可能遇到的问题架构介绍 前后端分离开发流程 项目地址&#xff1a; https://github.com/Catxiaobai/Embedded-Project Server后端项目 系统后端项目&#…

非工程师指南: 训练 LLaMA 2 聊天机器人

引言 本教程将向你展示在不编写一行代码的情况下&#xff0c;如何构建自己的开源 ChatGPT&#xff0c;这样人人都能构建自己的聊天模型。我们将以 LLaMA 2 基础模型为例&#xff0c;在开源指令数据集上针对聊天场景对其进行微调&#xff0c;并将微调后的模型部署到一个可分享的…

深入理解 Hadoop (五)YARN核心工作机制浅析

概述 YARN 的核心设计理念是 服务化&#xff08;Service&#xff09; 和 事件驱动&#xff08;Event EventHandler&#xff09;。服务化 和 事件驱动 软件设计思想的引入&#xff0c;使得 YARN 具有低耦合、高内聚的特点&#xff0c;各个模块只需完成各自功能&#xff0c;而模…

红帽宣布CentOS 7和RHEL 7将在2024年6月30日结束支持,企业面临紧迫的迁移压力!

2020 年红帽 (RedHat&#xff0c;已在 2019 年被 IBM 收购) 单方面宣布终止 CentOS Linux 的开发&#xff0c;此后 CentOS Linux 8 系列的更新已经在 2021 年 12 月结束&#xff0c;而 CentOS Linux 7 系列的更新将在 2024 年 6 月 30 日结束。 与 CentOS Linux 7 一起发布的 R…

SWM341系列之SWM34SRET6介绍

SWM341系列的介绍 本文介绍了华芯微特SWM341系列主要性能&#xff0c;和其系列之一的SWM34SRET6-50驱动4.3寸800*480 TFTLCD显示的例程应用。 SWM341系列性能 SWM341是一款基于ARM Cortex-M33的32位微控制器&#xff0c;片上包含精度为 1%以内的 20MHz/40MHz 时钟&#xff0c;最…

“To-Do Master“ GPTs:重塑任务管理的趣味与效率

有 GPTs 访问权限的可以点击链接进行体验&#xff1a;https://chat.openai.com/g/g-IhGsoyIkP-to-do-master 部署私人的 To-Do Master 教程&#xff1a;https://github.com/Reborn14/To-Do-Master/tree/main 引言 在忙碌的日常生活中&#xff0c;有效地管理日常任务对于提高生…

格式工厂怎么转换视频方向

格式工厂因为其免费、操作简单、功能齐全的多重优势&#xff0c;深受大家的喜欢。格式工厂具有可以转换视频、音频、去水印、转换GIF、图片转换、PDF合并、PDF转换等功能&#xff0c;然而在对视频进行剪辑的时候&#xff0c;往往会发现找不到格式工厂的转换视频方向的功能&…

影视视频知识付费行业万能通用网站系统源码,三网合一,附带完整的安装部署教程

在数字化时代&#xff0c;知识付费行业逐渐成为主流。人们对高质量内容的需求日益增长&#xff0c;越来越多的人愿意为有价值的知识和信息服务付费。为了满足这一市场需求&#xff0c;罗峰给大家分享一款全新的影视视频知识付费网站系统源码&#xff0c;为用户提供一站式的知识…

wy的leetcode刷题记录_Day74

wy的leetcode刷题记录_Day74 声明 本文章的所有题目信息都来源于leetcode 如有侵权请联系我删掉! 时间&#xff1a;2024-01-10 前言 目录 wy的leetcode刷题记录_Day74声明前言2696. 删除子串后的字符串最小长度题目介绍思路代码收获 64. 最小路径和题目介绍思路代码收获 63.…

查看Linux系统内存、CPU、磁盘使用率和详细信息

一、查看内存占用 1、free # free -m 以MB为单位显示内存使用情况 [rootlocalhost ~]# free -mtotal used free shared buff/cache available Mem: 11852 1250 8668 410 1934 9873 Swap: 601…

linux环境安装docker

一、Docker是什么? 当我们开发一个应用程序时&#xff0c;通常需要配置和安装各种软件、库和依赖项。而这些环境配置可能会因为不同的操作系统或版本而存在差异&#xff0c;导致应用在不同环境中运行出现问题。 Docker就像是一个集装箱&#xff0c;可以将应用程序及其所有依…

服务器组网方案

在当今数字化时代&#xff0c;服务器组网方案不仅是企业信息管理的关键&#xff0c;更是支撑业务运作的核心架构 。为了实现高效的数据处理和存储&#xff0c;服务器组网方案成为企业不可或缺的一部分。本文将深入探 讨服务器组网方案的核心要素和实施策略&#xff0c;明确其在…