Spring Boot集成Minio插件快速入门

news2024/11/18 19:47:10

1 Minio介绍

MinIO 是一个基于 Apache License v2.0 开源协议的对象存储服务。它兼容亚马逊 S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几 kb 到最大 5T 不等。以下是 MinIO 的一些主要特点和优势:

  1. 兼容性: MinIO 使用标准的 Amazon S3 API,这意味着它与现有的 S3 应用程序和工具兼容,可以无缝替换 Amazon S3。

  2. 高性能: MinIO 借助于其分布式架构和优化的存储引擎,在处理大规模数据时表现出色。它可以水平扩展以满足各种工作负载需求。

  3. 轻量级: MinIO 的设计注重简单性和效率,因此它是一个轻量级的服务。这使得它易于部署、管理和维护。

  4. 高可用性: MinIO 支持数据的多副本复制和故障转移,确保数据的可靠性和高可用性。它可以在节点故障时自动进行数据修复和重平衡。

  5. 安全性: MinIO 提供多种安全功能,包括加密传输、访问控制列表 (ACLs)、策略管理和身份验证机制,以确保数据的保密性和完整性。

  6. 灵活性: MinIO 可以在各种环境中部署,包括本地数据中心、云环境和容器化环境。它支持多种存储后端,包括本地磁盘、分布式文件系统和对象存储。

2 Minio环境搭建

2.1 docker环境下

采用docker-compose搭建:

# 可参考 https://docs.min.io/docs/minio-docker-quickstart-guide.html
version: '3'
services:
  minio:
    image: minio/minio:latest                                    # 原镜像`minio/minio:latest`
    container_name: minio                                        # 容器名为'minio'
    restart: unless-stopped                                              # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
    volumes:                                                     # 数据卷挂载路径设置,将本机目录映射到容器目录
      - "./minio/data:/data"
      - "./minio/minio:/minio"
      - "./minio/config:/root/.minio"
    environment:                                      # 设置环境变量,相当于docker run命令中的-e
      TZ: Asia/Shanghai
      LANG: en_US.UTF-8
      MINIO_PROMETHEUS_AUTH_TYPE: "public"
      MINIO_ACCESS_KEY: "root"                        # 登录账号
      MINIO_SECRET_KEY: "password"                    # 登录密码
    command: server /data  --console-address ":9001"
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
    ports:                              # 映射端口
      - "9000:9000" # 文件上传&预览端口
      - "9001:9001" # 控制台访问端口

启动服务:

docker-compose -f docker-compose-minio.yml -p minio up -d

启动后:

访问地址:ip地址:9001/minio 登录账号密码:root/password

2.2 Linux环境下(非docker容器下)

下载并授权限:

wget https://dl.min.io/sever/minio/release/linux-amd64/minio
chmod +x minio    //添加执行权限

启动minio服务:

MINIO_ROOT_USER=root MINIO_ROOT_PASSWORD=password ./minio server /data/minio/data --console-address ":9001"

  • 用户名为“root”
  • 密码为“password”
  • 数据存储路径为"/data/minio/data"
  • 控制台页面的访问端口为"9091"

2.3 Windows环境下

下载资源:

MinIO | S3 & Kubernetes Native Object Storage for AI

创建文件夹:

下载完成之后再合适的目录下创建三个必要的文件夹 ,分别是bin,data,logs文件夹

安装位置根据自身需求选择就好,我选在D盘的minio文件下

在这里插入图片描述
将minio.exe放入到bin中

然后执行命令(账号密码可通过命令行自行配置):

D:\minio\bin\minio.exe server D:\minio\data --console-address ":9001" --address ":9000"

2.4 运行成功后访问

在这里插入图片描述

3 springboot整合代码实现

3.1 写代码前的准备

创建桶:

在这里插入图片描述
获取accessKey和secretKey:

在这里插入图片描述

3.2 编写代码

application.yaml:

server:
  port: 8088

minio:
  endpoint: http://127.0.0.1:9000 #Minio服务所在地址
  bucketName: miniotest #存储桶名称
  accessKey: JW38e2AR9G5DgvmUCa51 #访问的key
  secretKey: rK5zgSxAyUwqgIfSWmec9osxDPvyN2qoEqX3MxZa #访问的秘钥

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.wkf</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>minio</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.11</version>
        </dependency>

    </dependencies>
</project>

MinioConfig.java:

package com.wkf.minio.config;

import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {

    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucketName;

    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }
}

OSSController.java:

package com.wkf.minio.controller;

import com.wkf.minio.config.MinioConfig;
import com.wkf.minio.util.MinioUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;

@Slf4j
@RestController
@RequestMapping("/oss")
public class OSSController {

    @Autowired
    private MinioUtils minioUtils;
    
    @Autowired
    private MinioConfig minioConfig;
    
    /**
     * file upload
     *
     * @param file
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) {
        try {
            //file name
            String fileName = file.getOriginalFilename();
            String newFileName = System.currentTimeMillis() + "." + StringUtils.substringAfterLast(fileName, ".");
            //type
            String contentType = file.getContentType();
            minioUtils.uploadFile(minioConfig.getBucketName(), file, newFileName, contentType);
            return "upload success";
        } catch (Exception e) {
            e.printStackTrace();
            log.error("upload fail");
            return "upload fail";
        }
    }

    /**
     * delete
     *
     * @param fileName
     */
    @DeleteMapping("/")
    public void delete(@RequestParam("fileName") String fileName) {
        minioUtils.removeFile(minioConfig.getBucketName(), fileName);
    }

    /**
     * get file info
     *
     * @param fileName
     * @return
     */
    @GetMapping("/info")
    public String getFileStatusInfo(@RequestParam("fileName") String fileName) {
        return minioUtils.getFileStatusInfo(minioConfig.getBucketName(), fileName);
    }

    /**
     * get file url
     *
     * @param fileName
     * @return
     */
    @GetMapping("/url")
    public String getPresignedObjectUrl(@RequestParam("fileName") String fileName) {
        return minioUtils.getPresignedObjectUrl(minioConfig.getBucketName(), fileName);
    }

    /**
     * file download
     *
     * @param fileName
     * @param response
     */
    @GetMapping("/download")
    public void download(@RequestParam("fileName") String fileName, HttpServletResponse response) {
        try {
            InputStream fileInputStream = minioUtils.getObject(minioConfig.getBucketName(), fileName);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/force-download");
            response.setCharacterEncoding("UTF-8");
            IOUtils.copy(fileInputStream, response.getOutputStream());
        } catch (Exception e) {
            log.error("download fail");
        }
    }

}

MinioUtil.java:

package com.wkf.minio.util;

import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;

/**
 * MinIO Utils
 *
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class MinioUtils {

    private final MinioClient minioClient;

    /******************************  Operate Bucket Start  ******************************/

    /**
     *  init Bucket  when start SpringBoot container
     * create bucket if the bucket is not exists
     *
     * @param bucketName
     */
    @SneakyThrows(Exception.class)
    private void createBucket(String bucketName) {
        if (!bucketExists(bucketName)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * verify Bucket is exist?,true:false
     *
     * @param bucketName
     * @return
     */
    @SneakyThrows(Exception.class)
    public boolean bucketExists(String bucketName) {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * get Bucket strategy
     *
     * @param bucketName
     * @return
     */
    @SneakyThrows(Exception.class)
    public String getBucketPolicy(String bucketName) {
        return minioClient.getBucketPolicy(GetBucketPolicyArgs
                .builder()
                .bucket(bucketName)
                .build());
    }

    /**
     * get all Bucket list
     *
     * @return
     */
    @SneakyThrows(Exception.class)
    public List<Bucket> getAllBuckets() {
        return minioClient.listBuckets();
    }

    /**
     * Get related information based on bucketName
     *
     * @param bucketName
     * @return
     */
    @SneakyThrows(Exception.class)
    public Optional<Bucket> getBucket(String bucketName) {
        return getAllBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    /**
     * Delete Bucket based on bucketName, true: deletion successful; false: deletion failed, file may no longer exist
     *
     * @param bucketName
     * @throws Exception
     */
    @SneakyThrows(Exception.class)
    public void removeBucket(String bucketName) {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /******************************  Operate Bucket End  ******************************/


    /******************************  Operate Files Start  ******************************/

    /**
     * check file is exist
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public boolean isObjectExist(String bucketName, String objectName) {
        boolean exist = true;
        try {
            minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
        } catch (Exception e) {
            log.error("[MinioUtils]>>>>check file exist, Exception:", e);
            exist = false;
        }
        return exist;
    }

    /**
     * check directory exist?
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public boolean isFolderExist(String bucketName, String objectName) {
        boolean exist = false;
        try {
            Iterable<Result<Item>> results = minioClient.listObjects(
                    ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build());
            for (Result<Item> result : results) {
                Item item = result.get();
                if (item.isDir() && objectName.equals(item.objectName())) {
                    exist = true;
                }
            }
        } catch (Exception e) {
            log.error("[MinioUtils]>>>>check file exist, Exception:", e);
            exist = false;
        }
        return exist;
    }

    /**
     * Query files based on file prefix
     *
     * @param bucketName
     * @param prefix
     * @param recursive
     * @return MinioItem
     */
    @SneakyThrows(Exception.class)
    public List<Item> getAllObjectsByPrefix(String bucketName,
                                            String prefix,
                                            boolean recursive) {
        List<Item> list = new ArrayList<>();
        Iterable<Result<Item>> objectsIterator = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());
        if (objectsIterator != null) {
            for (Result<Item> o : objectsIterator) {
                Item item = o.get();
                list.add(item);
            }
        }
        return list;
    }

    /**
     * get file InputStream
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    @SneakyThrows(Exception.class)
    public InputStream getObject(String bucketName, String objectName) {
        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build());
    }

    /**
     * Breakpoint download
     *
     * @param bucketName
     * @param objectName
     * @param offset
     * @param length
     * @return
     */
    @SneakyThrows(Exception.class)
    public InputStream getObject(String bucketName, String objectName, long offset, long length) {
        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .offset(offset)
                        .length(length)
                        .build());
    }

    /**
     * Get the list of files under the path
     *
     * @param bucketName
     * @param prefix
     * @param recursive
     * @return
     */
    public Iterable<Result<Item>> listObjects(String bucketName, String prefix, boolean recursive) {
        return minioClient.listObjects(
                ListObjectsArgs.builder()
                        .bucket(bucketName)
                        .prefix(prefix)
                        .recursive(recursive)
                        .build());
    }

    /**
     * use MultipartFile to upload files
     *
     * @param bucketName
     * @param file
     * @param objectName
     * @param contentType
     * @return
     */
    @SneakyThrows(Exception.class)
    public ObjectWriteResponse uploadFile(String bucketName, MultipartFile file, String objectName, String contentType) {
        InputStream inputStream = file.getInputStream();
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .contentType(contentType)
                        .stream(inputStream, inputStream.available(), -1)
                        .build());
    }

    /**
     * picture upload
     * @param bucketName
     * @param imageBase64
     * @param imageName
     * @return
     */
    public ObjectWriteResponse uploadImage(String bucketName, String imageBase64, String imageName) {
        if (!StringUtils.isEmpty(imageBase64)) {
            InputStream in = base64ToInputStream(imageBase64);
            String newName = System.currentTimeMillis() + "_" + imageName + ".jpg";
            String year = String.valueOf(new Date().getYear());
            String month = String.valueOf(new Date().getMonth());
            return uploadFile(bucketName, year + "/" + month + "/" + newName, in);

        }
        return null;
    }

    public static InputStream base64ToInputStream(String base64) {
        ByteArrayInputStream stream = null;
        try {
            byte[] bytes = new BASE64Decoder().decodeBuffer(base64.trim());
            stream = new ByteArrayInputStream(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stream;
    }


    /**
     * upload local files
     *
     * @param bucketName
     * @param objectName
     * @param fileName
     * @return
     */
    @SneakyThrows(Exception.class)
    public ObjectWriteResponse uploadFile(String bucketName, String objectName, String fileName) {
        return minioClient.uploadObject(
                UploadObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .filename(fileName)
                        .build());
    }

    /**
     * upload files based on stream
     *
     * @param bucketName
     * @param objectName
     * @param inputStream
     * @return
     */
    @SneakyThrows(Exception.class)
    public ObjectWriteResponse uploadFile(String bucketName, String objectName, InputStream inputStream) {
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(inputStream, inputStream.available(), -1)
                        .build());
    }

    /**
     * create file or direatory
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    @SneakyThrows(Exception.class)
    public ObjectWriteResponse createDir(String bucketName, String objectName) {
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(new ByteArrayInputStream(new byte[]{}), 0, -1)
                        .build());
    }

    /**
     * get file info
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    @SneakyThrows(Exception.class)
    public String getFileStatusInfo(String bucketName, String objectName) {
        return minioClient.statObject(
                StatObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build()).toString();
    }

    /**
     * copy file
     *
     * @param bucketName
     * @param objectName
     * @param srcBucketName
     * @param srcObjectName
     */
    @SneakyThrows(Exception.class)
    public ObjectWriteResponse copyFile(String bucketName, String objectName, String srcBucketName, String srcObjectName) {
        return minioClient.copyObject(
                CopyObjectArgs.builder()
                        .source(CopySource.builder().bucket(bucketName).object(objectName).build())
                        .bucket(srcBucketName)
                        .object(srcObjectName)
                        .build());
    }

    /**
     * delete file
     *
     * @param bucketName
     * @param objectName
     */
    @SneakyThrows(Exception.class)
    public void removeFile(String bucketName, String objectName) {
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build());
    }

    /**
     * batch delete file
     *
     * @param bucketName
     * @param keys
     * @return
     */
    public void removeFiles(String bucketName, List<String> keys) {
        List<DeleteObject> objects = new LinkedList<>();
        keys.forEach(s -> {
            objects.add(new DeleteObject(s));
            try {
                removeFile(bucketName, s);
            } catch (Exception e) {
                log.error("[MinioUtil]>>>>batch delete file,Exception:", e);
            }
        });
    }

    /**
     * get file url
     *
     * @param bucketName
     * @param objectName
     * @param expires
     * @return url
     */
    @SneakyThrows(Exception.class)
    public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) {
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build();
        return minioClient.getPresignedObjectUrl(args);
    }

    /**
     * get file url
     *
     * @param bucketName
     * @param objectName
     * @return url
     */
    @SneakyThrows(Exception.class)
    public String getPresignedObjectUrl(String bucketName, String objectName) {
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .method(Method.GET).build();
        return minioClient.getPresignedObjectUrl(args);
    }

    /**
     * change URLDecoder to UTF8
     *
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     */
    public String getUtf8ByURLDecoder(String str) throws UnsupportedEncodingException {
        String url = str.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
        return URLDecoder.decode(url, "UTF-8");
    }
}

4 测试

在这里插入图片描述
在这里插入图片描述

5 代码仓库

https://github.com/363153421/springboot-demo/tree/master/minio

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【机器学习300问】125、什么是双向循环神经网络(BRNN)?什么是深度循环神经网络(DRNN)?

一、双向循环神经网络 &#xff08;1&#xff09;诞生背景 双向循环神经网络&#xff08;Bidirectional Recurrenct Neural Network, BRNN&#xff09;是在深度学习领域发展起来的一种特殊类型的循环神经网络&#xff08;RNN&#xff09;&#xff0c;它诞生的背景是为了解决传…

抽卡机小程序:设计与开发全攻略

在移动互联网时代&#xff0c;小程序以其轻便、易用、无需安装的特点&#xff0c;迅速成为用户日常使用的重要工具。其中&#xff0c;抽卡机小程序因其独特的娱乐性和互动性&#xff0c;受到广大用户的喜爱。本文将为大家详细介绍抽卡机小程序的设计与开发全攻略。 一、需求分析…

电子竞赛5——作息时间控制器

一 . 题目要求 用单片机制作作息时间控制器&#xff1b;用四位数码管显示实时时钟&#xff08;时、分&#xff0c;24小时制、12小时制&#xff09;&#xff0c;有秒闪&#xff0c;小时十位有零消隐&#xff1b;可用数字键或、-键校时&#xff08;可快速、-&#xff09;被校位&…

通过OOS定时升级EIP实例临时带宽

目录 功能背景 关键特性 应用场景 使用限制 操作步骤 附录 执行流程图 模板 功能背景 随着业务的不断发展和互联网应用场景的多样化&#xff0c;企业或个人用户在特定时间段内面临网络流量剧增的挑战变得尤为常见。这些流量高峰&#xff0c;如大规模促销活动、热门直播…

[递归与栈]The Sierpinski Fractal

描述 Consider a regular triangular area, divide it into four equal triangles of half height and remove the one in the middle. Apply the same operation recursively to each of the three remaining triangles. If we repeated this procedure infinite times, wed …

我劝你别惹“女”项目经理

她来了她来了&#xff0c;她带着项目进度走来了&#xff01;&#xff01;&#xff01; 在职场的江湖里&#xff0c;流传着一个传说&#xff0c;那便是“女”项目经理的神话。她们&#xff0c;是团队中的“铁娘子”&#xff0c;是项目里的“指挥官”&#xff0c;更是无数人心中的…

商城小程序:颠覆传统电商,打造全新商业生态

在数字化浪潮的推动下&#xff0c;网购行业呈现多元化繁荣发展态势&#xff0c;出现了琳琅满目的商品应用小程序&#xff0c;但市面上的商城小程序基本属于通用型&#xff0c;无论是商城界面展示和基本功能&#xff0c;都不能满足个性化和商品推广需求&#xff0c;阻碍了商品的…

故障记录---docker僵死

故障现象&#xff1a; docker进程僵死&#xff0c;docker命令无法使用 处理过程&#xff1a; 查看docker进程状态&#xff0c;显示句柄数过多&#xff0c;于是重启了docker [rootdata02 opt]# systemctl status docker ● docker.service - Docker Application Container Eng…

这13个常用电路基础公式,每一位电子工程师都要牢记

计算电阻电路中电流、电压、电阻和功率之间的关系。 欧姆定律解释了电压、电流和电阻之间的关系&#xff0c;即通过导体两点间的电流与这两点间的电势差成正比。说明两点间的电压差、流经该两点的电流和该电流路径电阻之间关系的定律。该定律的数学表达式为V IR&#xff0c;其中…

Nuxt3 实战 (十):使用 Supabase 实现 RESTful 风格 API 接口

前言 本篇文章我们来使用 Supabase 实现 RESTful 风格的 API 接口&#xff0c;以此来实现网站分类和子站点的 CURD 功能。 表设计 这里需要用到两张表&#xff1a; ds_categorys&#xff1a;存储网站分类 列名类型备注iduuid主键&#xff0c;分类 idnametext分类名称desct…

重学java 76.JDK新特性 ② 函数式接口

Looking to the future is the order of the day, no worrying about old news —— 24.6.19 一、函数式接口 1.定义 有且只有一个抽象方法的接口 2.检测 FunctionalInterface 3.示例 FunctionalInterface public interface USB {void open(String s); }public class Demo3…

【碳排放控排1006】碳排放控排企业名单数据集,探索绿色生产!

今天给大家分享的是国内顶级期刊2023发表论文《碳排放规制、企业减排激励与全要素生产率——基于中国碳排放权交易机制的准自然实验》中使用到的重要数据集——碳排放控排企业名单&#xff0c;该论文从企业生产效率视角对论文进行研究&#xff0c;发现碳排放权交易机制显著提升…

红米手机RedNot11无法使用谷歌框架,打开游戏闪退的问题,红米手机如何开启谷歌框架

红米手机RedNot11无法使用谷歌框架&#xff0c;打开游戏闪退的问题&#xff0c; 1.问题描述2.问题原因3.解决方案3.1配置谷歌框架&#xff1a;3.1软件优化 4.附图 1.问题描述 红米手机打开安卓APP没有广告&#xff0c;直接闪退&#xff0c;无法使用谷歌框架 异常关键词中包含&…

人工智能大模型之开源大语言模型汇总(国内外开源项目模型汇总)

开源大语言模型完整列表 Large Language Model (LLM) 即大规模语言模型&#xff0c;是一种基于深度学习的自然语言处理模型&#xff0c;它能够学习到自然语言的语法和语义&#xff0c;从而可以生成人类可读的文本。 所谓"语言模型"&#xff0c;就是只用来处理语言文…

数字时代的创新:二人共益订单模式解析

一、引言 随着数字技术的飞速发展&#xff0c;商业模式也日新月异。其中&#xff0c;“二人共益订单模式”凭借其独特的互助与共赢理念&#xff0c;迅速在市场中获得关注。该模式不仅为用户提供了优质服务和独享优惠&#xff0c;更通过用户间的互助和订单共享&#xff0c;实现…

js语音识别,语音转文字,speech recognition(需要翻墙才能识别)

先上代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width,initial-scale1.0"><title>test</title> </head><body><div id"…

技术与创意并驾齐驱:打造扭蛋机小程序的独特魅力

引言 扭蛋机小程序以其独特的玩法和吸引力&#xff0c;在移动互联网市场中崭露头角。本文将深入探讨如何通过技术与创意的并驾齐驱&#xff0c;打造扭蛋机小程序的独特魅力。 一、技术驱动&#xff1a;打造稳定高效的小程序平台 在扭蛋机小程序的开发过程中&#xff0c;技术是…

中国500米分辨率年平均LAI数据集(2000-2020)

叶面积指数LAI(Leaf Area Index)是描述植被冠层几何结构的基本参数之一&#xff0c;被定义为单位地表面积上所有叶片面积的倍数&#xff0c;它控制着植被的许多生物物理过程&#xff0c;如光合作用、呼吸作用、蒸腾作用、碳循环和降水截获等&#xff0c;是陆面过程一个十分重要…

推荐一个很好用的Latex写代码的软件

软件名称&#xff1a;Axmath 据说是国产软件&#xff0c;好用是真好用&#xff08;去哪找&#xff1f;比如某地球号的公主号或其他地方&#xff09;我是推荐付费购买使用 1.通过图形操作&#xff0c;选择要转成Latex代码的符号&#xff0c;按下转换&#xff0c;直接就出现了我…

植物大战僵尸杂交版V2.1快速刷金币的方法(新号适用,无需自带招财猫)

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 1. &#x1f4bb;游戏介绍 2. &#x1f525;快速刷取金币的办法&#xff08;我是新号测试的&#xff09; 2.1 无招财猫 2.2 有招财猫 《植物大战僵尸杂交版》是一款在原版《植物大战僵尸》基础上进行了创新的塔防…