JAVA集成阿里云OSS对象存储

news2025/1/11 8:18:18

JAVA集成阿里云OSS对象存储

  • 1 : 配置集成
    • 1.1、对象存储OSS
  • 2 : 代码配置
    • 2.1、说明
    • 2.2、配置文件
    • 2.3、加载配置文件代码
    • 2.4、封装统一的DTO
    • 2.5、OSS上传Controller
    • 2.6、OSS上传Service
    • 2.7、OSS上传ServiceImpl
  • 3 : 测试
    • 3.1、文件上传
    • 3.2、文件迁移
  • 4 : 总结
    • 4.1、参考资料
    • 4.2、注意事项
    • 4.3、源码链接

1 : 配置集成

1.1、对象存储OSS

这就不用说了,从阿里云平台花钱买OSS对象存储就行了。
然后在bucket列表中创建自己使用的bucket即可。
比如创建:oss-test
然后从概览中找到 Access Key
在这里插入图片描述
在这里插入图片描述
然后就可以看到对应的id和key了。
在这里插入图片描述

这个时候,就有了四个参数
1、access-key:就是刚才的 AccessKey ID
2、secret-key:页面点击‘查看 Secret’就能看的到了
3、bucket:新建的桶的名称oss-test
4、endpoint:页面截图,选择自己的桶就能看到对应的endpoint

2 : 代码配置

2.1、说明

本篇代码,主要做的两件事:
1、文件上传至OSS
2、对服务器磁盘文件转存至OSS

2.2、配置文件

在application.yml中增加配置

#阿里云oss
alibaba:
  cloud:
    access-key: **********
    secret-key: **********
    oss:
      endpoint: oss********.aliyuncs.com
      bucket: *******
  config:
    # oss开关 0:关  1:开
    oss-switch: 1
    # oss 开始使用时间
    oss-date: 2022-01-01
    # oss 文件夹目录
    oss-directory: image,attach,video,audio,template
    # oss title
    oss-title: https://
	# oss business directory
    business-directory: user,org

非常非常重要在配置的时候上面4个重要参数的位置,以及名称一定不能修改,否则会报找不到endPoint的错

2.3、加载配置文件代码

新建 YmlConfigBean.java

package com.upload.bean;

import org.springframework.stereotype.Component;
import java.util.List;

/**
 * 配置文件参数读取
 */
@Component
public class YmlConfigBean {
	
    // 阿里云OSS 申请的 key id
    public volatile static String OSS_KEY_ID;
    // 阿里云OSS 申请的 key secret
    public volatile static String OSS_KEY_SECRET;
    // 阿里云OSS endpoint
    public volatile static String OSS_ENDPOINT;
    // 阿里云OSS bucket
    public volatile static String OSS_BUCKET;
    // 阿里云OSS 开关 0 关 1 开
    public volatile static String OSS_SWITCH;
    // 阿里云OSS 开始使用时间
    public volatile static String OSS_DATE;
    // 阿里云OSS 文件夹目录
    public volatile static List<String> OSS_DIRECTORY;
    // 阿里云OSS 开始使用时间
    public volatile static String OSS_TITLE;
	//业务文件类别
    public volatile static List<String> BUSINESS_DIRECTORY;
}

新建 YmlConfigBeanMethod.java

package com.upload.bean;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;

@Component
public class YmlConfigBeanMethod {

    @Value("#{'${alibaba.cloud.access-key}'}")
    private void setOssKeyId(String key) {
        YmlConfigBean.OSS_KEY_ID = key;
    }
    @Value("#{'${alibaba.cloud.secret-key}'}")
    private void setOssKeySecret(String key) {
        YmlConfigBean.OSS_KEY_SECRET = key;
    }
    @Value("#{'${alibaba.cloud.oss.endpoint}'}")
    private void setOssEndpoint(String key) {
        YmlConfigBean.OSS_ENDPOINT = key;
    }
    @Value("#{'${alibaba.cloud.oss.bucket}'}")
    private void setOssBucket(String key) {
        YmlConfigBean.OSS_BUCKET = key;
    }
    @Value("#{'${alibaba.config.oss-switch}'}")
    private void setOssSwitch(String key) {
        YmlConfigBean.OSS_SWITCH = key;
    }
    @Value("#{'${alibaba.config.oss-date}'}")
    private void setOssDate(String key) {
        YmlConfigBean.OSS_DATE = key;
    }
    @Value("#{'${alibaba.config.oss-directory}'.split(',')}")
    public void setOssDirectory(List<String> key){
        YmlConfigBean.OSS_DIRECTORY = key;
    }
    @Value("#{'${alibaba.config.oss-title}'}")
    private void setOssTitle(String key) {
        YmlConfigBean.OSS_TITLE = key;
    }

	@Value("#{'${alibaba.config.business-directory}'.split(',')}")
    public void setBusinessDirectory(List<String> key){
        YmlConfigBean.BUSINESS_DIRECTORY= key;
    }
    
}

2.4、封装统一的DTO

建一个统一的DTO Result.java

package com.upload.bean;

/**
 * 统一的DTO
 */
public class Result<T> {
    private boolean success = true;
    private Integer code = 0;
    private String msg;
    private T data;

    public boolean isSuccess() {
        return this.code == 0;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
        if(code != 0){
            success = false;
        }
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }

    public Result() {
        super();
    }
    public Result(boolean success) {
        this.success = success;
        if(success){
            code = 0;
        }
    }
    public Result(int code) {
        super();
        success = false;
        this.code = code;
    }
    public Result(String msg) {
        success = false;
        this.msg = msg;
    }
    public Result(boolean success, String msg) {
        super();
        this.success = success;
        this.msg = msg;
    }
    public Result(int code, String msg) {
        super();
        success = false;
        this.code = code;
        this.msg = msg;
    }

    /*设置返回为成功*/
    public static Result ok() {
        return new Result();
    }
    /*设置返回为成功,同时设置返回数据*/
    public Result<T> ok(T data) {
        Result<T> result = new Result<T>();
        result.setData(data);
        return result;
    }
    /*设置返回为失败,默认未知异常*/
    public static Result error() {
        return error(500, "未知异常,请联系管理员!");
    }
    /*设置返回为失败,同时设置异常信息*/
    public static Result error(String msg) {
        return error(500, msg);
    }
    /*设置返回为失败,同时设置code,msg*/
    public static Result error(Integer code,String msg) {
        Result result = new Result();
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }
    public static Result<Object> error(Integer code,String msg,Object data) {
        Result<Object> result = new Result<Object>();
        result.setData(data);
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }
    public static Result success(Object data) {
        Result<Object> result = new Result<Object>();
        result.setData(data);
        return result;
    }
    public static Result success(String msg) {
        Result result = new Result();
        result.setMsg(msg);
        return result;
    }

}

常量配置好之后,方便后续直接使用配置文件的中内容。

2.5、OSS上传Controller

新建 OssUploadController.java

package com.upload;

import com.upload.service.IOssUploadService;
import com.upload.bean.Result;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * <p>
 * 阿里云OSS 前端控制器
 * </p>
 */
@Controller
public class OssUploadController {

    @Resource
    private IOssUploadService ossUploadService;

    /**
     * OSS文件上传
     */
    @RequestMapping("/uploadOss")
    @ResponseBody
    public Result upload(@RequestParam String ossDirectory, @RequestParam String businessDirectory,
                         @RequestParam MultipartFile file, HttpServletRequest request) {
        return ossUploadService.upload(ossDirectory, businessDirectory, file, request);
    }

    /**
     * OSS文件迁移
     */
    @RequestMapping("/migrationOss")
    @ResponseBody
    public Result doDataMigration(@RequestParam String ossDirectory, @RequestParam String businessDirectory) {
        return ossUploadService.doDataMigration(ossDirectory, businessDirectory, true);
    }

}

2.6、OSS上传Service

新建 IOssUploadService.java

package com.upload.service;

import com.upload.bean.Result;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;

/**
 * <p>
 * 阿里云OSS 服务类
 */
public interface IOssUploadService {

    Result upload(String ossDirectory, String businessDirectory, MultipartFile file, HttpServletRequest request);

    Result doDataMigration(String ossDirectory, String businessDirectory, boolean threadFlag);

}

2.7、OSS上传ServiceImpl

新建 OssUploadServiceImpl.java

package com.upload.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.upload.bean.Result;
import com.upload.bean.YmlConfigBean;
import com.upload.entity.FileUpload;
import com.upload.service.IOssUploadService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class OssUploadServiceImpl implements IOssUploadService {

//    @Resource
//    private UploadMapper uploadMapper;
    private final static String ROOT_PATH = "/data/file/";

    /**
     * 对外提供的文件上传
     * @param ossDirectory OSS所属模块
     * @param fileDir 文件所属模块
     * @param file 文件
     * @param request 请求
     */
    @Override
    public Result upload(String ossDirectory, String fileDir, MultipartFile file, HttpServletRequest request) {
        if (file.isEmpty()) {
            return Result.error("不能上传空文件");
        }
        String originalFilename = file.getOriginalFilename();
        Long fileBytes = file.getSize();
        if (Strings.isBlank(originalFilename) || 0L == fileBytes) {
            return Result.error("不能上传空文件");
        }
        if(Strings.isBlank(ossDirectory)){
            ossDirectory = "image";
        } else {
            if (!YmlConfigBean.OSS_DIRECTORY.contains(ossDirectory.startsWith("/") ? ossDirectory.substring(1) : ossDirectory)) {
                log.info("文件上传目录非法,非法目录:"+ ossDirectory);
                return Result.error("文件上传目录非法,请更改文件上传目录");
            }
        }
        if (!YmlConfigBean.BUSINESS_DIRECTORY.contains(fileDir.startsWith("/") ? fileDir.substring(1) : fileDir)) {
            log.info("文件上传目录非法,非法目录:"+ fileDir);
            return Result.error("文件上传目录非法,请更改文件上传目录");
        }
        String fileMd5;
        try {
            fileMd5 = DigestUtils.sha256Hex(file.getInputStream());
        } catch (Exception e) {
            log.error(file.getOriginalFilename() + "验证文件md5失败",e);
            return Result.error("当前验证文件md5失败");
        }
        Result<String> result = new Result<>();
        String uploadUrl = null;
        String newName = null;
        OSS ossClient = getOSSClient();
        try {
            //获取上传文件流
            InputStream inputStream = file.getInputStream();
            //构建日期路径:/2019/02/26/文件名
            String fileType = originalFilename.split("\\.")[originalFilename.split("\\.").length - 1];
            newName = DateFormatUtils.format(new Date(), "yyMMddHHmmss") +
                    (new SecureRandom().nextInt(100) + 100) + "." + fileType;
            String newFileDir = (fileDir.startsWith("/") ? fileDir.substring(1) : fileDir).trim().replace(" ","") +
                    getDatePath();
            String fileUrl = ossDirectory + "/" + newFileDir + newName;
            // 上传文件 (上传文件流的形式)
            ossClient.putObject(YmlConfigBean.OSS_BUCKET, fileUrl, inputStream);
            //获取url地址
            uploadUrl = YmlConfigBean.OSS_TITLE + YmlConfigBean.OSS_BUCKET + "." + YmlConfigBean.OSS_ENDPOINT + "/" + fileUrl;
        } catch (IOException e) {
            log.error("上传OSS失败,文件名:" + originalFilename);
            throw new RuntimeException("上传OSS失败");
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        //文件上传实体属性赋值,数据入库
        try {
            log.info("原文件名称:" + originalFilename + "\n" + "文件MD5码:" + fileMd5 + "\n" + "新文件名称:" + newName + "\n" +
            "文件路径:" + uploadUrl + "\n" + "文件大小:" + fileBytes);
//            uploadMapper.doUploadInsert(null);
        } catch (Exception e) {
            log.error("上传文件,数据库记录失败", e);
        }
        result.setData(uploadUrl);
        return result;
    }

    /**
     * 文件迁移
     * @param ossDirectory 需要同步的OSS文件夹
     * @param businessDirectory 业务文件路径,以此查询表中数据
     * @param threadFlag 是否开启异步线程
     * @return Result
     */
    @Override
    public Result doDataMigration(String ossDirectory, String businessDirectory, boolean threadFlag){
        if(Strings.isBlank(businessDirectory)) return Result.error("路径不能为空");
//        List<FileUpload> fileUploads = uploadMapper.selectList();
        List<FileUpload> fileUploads = new ArrayList<>();
        if(null == fileUploads || fileUploads.size() == 0) return Result.error("暂无数据");
        if(threadFlag){
            Thread thread = new Thread(()->{
                doSonThread(fileUploads, ossDirectory);
            });
            thread.start();
        } else {
            doSonThread(fileUploads, ossDirectory);
        }
        return Result.success("文件迁移中,请稍后查看!");
    }

    private void doSonThread(List<FileUpload> fileUploads, String ossDirectory){
        if(Strings.isBlank(ossDirectory)) {
            ossDirectory = "image";
        }
        String filePath = null;
        for(FileUpload fileUpload : fileUploads){
            if(Strings.isBlank(fileUpload.getFilePath()) || Strings.isBlank(fileUpload.getFileName())){
                continue;
            }
            filePath = uploadFileAndDeleteByPath(ROOT_PATH + fileUpload.getFilePath(), fileUpload.getFileName(), ossDirectory);
            //更新新的路径入库
            fileUpload.setFilePathNew(filePath);
//            uploadMapper.doUploadUpdate(fileUpload);
        }
    }

    public static String uploadFileAndDeleteByPath(String path, String fileName, String ossDirectory) {
        File file = new File(path + File.separator + fileName);
        return uploadFileAndDeleteByFile(file, ossDirectory);
    }

    public static String uploadFileAndDeleteByFile(File file, String ossDirectory) {
        if (file.isDirectory()) return null;
        String filePath = null;
        Boolean deleteFlag = false;
        try {
            filePath = uploadHistory(ossDirectory, file.getPath(), file);
            deleteFlag = checkExists(filePath.substring(filePath.indexOf(YmlConfigBean.OSS_ENDPOINT) + 1 + YmlConfigBean.OSS_ENDPOINT.length(), filePath.length()));
        } catch (IOException e) {
            log.error("上传OSS失败,文件名:" + file.getName());
            throw new RuntimeException("上传OSS失败");
        }
        if(deleteFlag){
            file.delete();
        }
        return filePath;
    }

    public static String uploadHistory(String ossDirectory, String businessDirectory, File file) throws IOException{
        String filename = file.getName();
        OSS ossClient = getOSSClient();
        //获取上传文件流
        InputStream inputStream = new FileInputStream(file);
        //构建日期路径:/2019/02/26/文件名
        String fileType = filename.split("\\.")[filename.split("\\.").length - 1];
        String newName = filename.substring(0, filename.indexOf(".")) + "_" + (new SecureRandom().nextInt(1000) + 1000) + "." + fileType;
        String newFileDir = (businessDirectory.startsWith("/") ? businessDirectory.substring(1) : businessDirectory).trim().replace(" ","");
        String fileUrl = ossDirectory + "/" + newFileDir + newName;
        // 上传文件 (上传文件流的形式)
        ossClient.putObject(YmlConfigBean.OSS_BUCKET, fileUrl, inputStream);
        ossClient.shutdown();
        //获取url地址
        return YmlConfigBean.OSS_TITLE + YmlConfigBean.OSS_BUCKET + "." + YmlConfigBean.OSS_ENDPOINT + "/" + fileUrl;
    }

    public static boolean checkExists(String objectName) throws IOException{
        OSS ossClient = getOSSClient();
        Boolean flag = ossClient.doesObjectExist(YmlConfigBean.OSS_BUCKET, objectName);
        ossClient.shutdown();
        return flag;
    }

    public static OSS getOSSClient() {
        OSS ossClient = new OSSClientBuilder().build(YmlConfigBean.OSS_ENDPOINT, YmlConfigBean.OSS_KEY_ID, YmlConfigBean.OSS_KEY_SECRET);
        //判断oss实例是否存在:如果不存在则创建,如果存在则获取
        if (!ossClient.doesBucketExist(YmlConfigBean.OSS_BUCKET)) {
            //创建bucket
            ossClient.createBucket(YmlConfigBean.OSS_BUCKET);
            //设置oss实例的访问权限:公共读
            ossClient.setBucketAcl(YmlConfigBean.OSS_BUCKET, CannedAccessControlList.PublicRead);
        }
        return ossClient;
    }

    /*public static void uploadFileAndDelete(File file) {
        if (file.isDirectory()) {
            String[] fileList = file.list();
            if(null != fileList && fileList.length > 0){
                //递归删除目录中的子目录下
                File subFile = null;
                for(String str : fileList){
                    subFile = new File(file, str);
                    log.info(subFile.getPath());
                    uploadFileAndDelete(subFile);
                }
            }
        }
        uploadFileAndDeleteByFile(file, null);
    }*/

    public static String getDatePath(){
        return "/" + DateFormatUtils.format(new Date(), "yyyy-MM-dd").replaceAll("-","/") + "/";
    }

}

3 : 测试

3.1、文件上传

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

在这里插入图片描述
在OSS上存储的路径为:OSS文件夹(image)+ 业务自定义文件夹名称(org)+ 年月日时间路径 + 重命名文件名称。

3.2、文件迁移

大致思路:
1、根据业务需要,查询数据库中的文件路径及名称,到服务器磁盘中查找该文件。
2、调用简易版的文件上传,上传至OSS中。
3、上传之后回调阿里自带方法doesObjectExist进行回溯校验,检查是否在OSS中存在。
4、如存在该文件,则删除服务器磁盘对应的文件即可。

因代码需根据业务数据来进行数据的查询等操作,可自行修改并验证。

4 : 总结

4.1、参考资料

参考资料:异常官网链接:https://help.aliyun.com/document_detail/32023.html

4.2、注意事项

注意事项在配置的时候上面4个重要参数的位置,以及名称一定不能修改,否则会报找不到endPoint的错

4.3、源码链接

CSDN资源链接:https://download.csdn.net/download/qq_38254635/87352781
百度网盘资源链接:https://pan.baidu.com/s/1kl6KIntr1qvcJPG642DWAA?pwd=fsj2
提取码: fsj2

有什么不对的还望指正,书写不易,觉得有帮助就点个赞吧!

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

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

相关文章

浅谈 C++ 字符串:std::string 与它的替身们

浅谈 C 字符串&#xff1a;std::string 与它的替身们 文章目录浅谈 C 字符串&#xff1a;std::string 与它的替身们零、前言一、前辈&#xff1a;C 风格的字符串1.1 什么是 C 风格的字符串1.2 C 风格的字符串有什么缺陷1.2.1 以 \0 作为结尾&#xff0c;没有直接指明长度1.2.2 …

Android技术分享——APT实现ButterKnife【实战学习】

APT APT &#xff08;Annotation Processing Tool&#xff09; 是一种处理注释的工具&#xff0c;它对源代码文件进行检测并找出其中的 Annotation&#xff0c;根据注解自动生成代码&#xff0c;如果想要自定义的注解处理器能够运行&#xff0c;必须要通过 APT 工具来处理。 …

Python实现FA萤火虫优化算法优化支持向量机分类模型(SVC算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 萤火虫算法&#xff08;Fire-fly algorithm&#xff0c;FA&#xff09;由剑桥大学Yang于2009年提出 , 作…

maven第一篇:安装maven以及配置

本篇就是聊如何在电脑上安装maven&#xff0c;以及简单的配置基础环境。 首先需要了解什么适合maven&#xff0c;对于这个理论知识&#xff0c;还是老规矩直接复制一下&#xff1b; Maven 是一款基于 Java 平台的项目管理和整合工具&#xff0c;它将项目的开发和管理过程抽象…

提速300%,PaddleSpeech语音识别高性能部署方案重磅来袭!

在人机交互的过程中&#xff0c;语音是重要的信息载体&#xff0c;而语音交互技术离不开语音识别与语音合成技术。飞桨语音模型库PaddleSpeech为开发者们使用这些技术提供了便捷的环境。本次PaddleSpeech迎来重大更新——1.3版本正式发布。让我们一起看看&#xff0c;这次Paddl…

这样实操一下 JVM 调优,面试超加分

1.写在前面 前段时间一位读者面了阿里&#xff0c;在二面中被问到 GC 日志分析&#xff0c;感觉回答的不是很好&#xff0c;过来找我复盘&#xff0c;大致听了他的回答&#xff0c;虽然回答出了部分&#xff0c;但是没抓到重点。 GC 日志分析算是 JVM 调优中比较难的部分&…

【XR】如何提高追踪保真度,确保内向外追踪系统性能

Constellation是Oculus研发的追踪系统。日前&#xff0c;负责AR/VR设备输入追踪的Facebook工程经理安德鲁梅利姆撰文介绍了他们是如何用基于Constellation追踪的控制器来提高交互保真度。具体整理如下&#xff1a; 我们的计算机视觉工程师团队一直在努力为Oculus Quest和Rift …

【再学Tensorflow2】TensorFlow2的模型训练组件(1)

TensorFlow2的模型训练组件&#xff08;1&#xff09;数据管道构建数据通道应用数据转换提升管道性能特征列特征列用法简介特征列使用示例激活函数常用激活函数激活函数使用示例Tensorflow模型中的层内置的层自定义模型中的层参考资料Tensorflow中与模型训练相关的组件主要包括…

图像采样与量化

数字图像有两个重要属性&#xff1a;空间位置(x,y)以及响应值I(x,y)。数字图像中像素的空间位置及响应值都是离散值&#xff0c;传感器输出连续电压信号。为了产生数字图像&#xff0c;需要把连续的数据转换为离散的数字化形式。采用的方式是图像量化与采样。 图像采样 图像量化…

【数据结构】(初阶):二叉搜索树

​ ✨前言✨ &#x1f393;作者&#xff1a;【 教主 】 &#x1f4dc;文章推荐&#xff1a; ☕博主水平有限&#xff0c;如有错误&#xff0c;恳请斧正。 &#x1f4cc;机会总是留给有准备的人&#xff0c;越努力&#xff0c;越幸运&#xff01; &#x1f4a6;导航助手&#x…

Docker+Selenium Grid运行UI自动化

简介 使用Selenium Grid可以分布式运行UI自动化测试&#xff0c;可以同时启动多个不同的浏览器&#xff0c;也可以同时启动同一个浏览器的多个session。这里使用Docker Compose来同时启动不同浏览器的容器和Selenium Grid&#xff0c;只需一条命令就把自动化运行环境部署好了。…

verilog仿真技巧与bug集合

文章目录赋值语句想法一些建议时钟信号关于异步fifo写入数据时wp1&#xff0c;读出数据时rp1一些自己的bug关于操作符&关于if-else关于modelsim使用1.初学者不建议在设计文件中加入仿真语句&#xff1b; 2.初学者也不会在tb里使用类似always一样的设计。 对于1.因为把仿真…

国产RISC-V处理器“黑马”跑分曝光!超过多数国内主流高性能处理器!

来源企业投稿 2010年&#xff0c;开源、开放、精简的RISC-V架构诞生。虽然距今仅有12年&#xff0c;但RISC-V迎来了众多玩家的积极参与&#xff0c;其技术、生态、应用都快速发展。在许多秉持匠心的技术人员的耕耘下&#xff0c;RISC-V也早已从传统强项物联网走出&#xff0c;…

error: ‘uint8_t’,‘uint16_t’ ,‘uint32_t’ does not name a type

文章目录1、报错error: ‘uint8_t’,‘uint16_t’ ,‘uint32_t’ does not name a type2、解决办法3、uint8_t此类数据类型补充4、码字不易&#xff0c;点点赞1、报错error: ‘uint8_t’,‘uint16_t’ ,‘uint32_t’ does not name a type 在网络编程PING程序时遇到的小bug&am…

【BUUCTF】MISC(第二页wp)

文章目录被劫持的神秘礼物刷新过的图片[BJDCTF2020]认真你就输了[BJDCTF2020]藏藏藏被偷走的文件snake[GXYCTF2019]佛系青年[BJDCTF2020]你猜我是个啥秘密文件菜刀666[BJDCTF2020]just_a_rar[BJDCTF2020]鸡你太美[BJDCTF2020]一叶障目[SWPU2019]神奇的二维码梅花香之苦寒来[BJD…

day02-Java基础语法

day02 - Java基础语法 1 类型转换 在Java中&#xff0c;一些数据类型之间是可以相互转换的。分为两种情况&#xff1a;自动类型转换和强制类型转换。 1.1 隐式转换(理解) ​ 把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量。这种转换方式是自动的&am…

外贸小白适合哪种邮箱?

除了一些企业指定的邮箱&#xff0c;大多数外贸人&#xff0c;尤其是小白的外贸人&#xff0c;都希望选择最合适的邮箱&#xff0c;赢在起跑线上。判断邮箱质量的两个主要因素是投递率和安全性。米贸搜的排列如下: 公共个人邮箱 此时常见的个人邮箱有国外的gmail、hotmail、雅…

2023 年软件开发人员可以学习的 10 个框架

开发者您好&#xff0c;我们现在处于 2023 年的第一周&#xff0c;你们中的许多人可能已经制定了 2023 年要学习什么的目标&#xff0c;但如果您还没有&#xff0c;那么您来对地方了。 早些时候&#xff0c;我分享了成为Java 开发人员、DevOps 工程师、React 开发人员和Web 开…

联合分析案全流程分析

联合分析(conjoint analysis)是一种研究消费者产品选择偏好情况的多元统计分析方法。比如消费者对于手机产品的偏好&#xff0c;对于电脑产品的偏好&#xff0c;也或者消费者对于汽车产品的偏好情况等。联合分析中涉及几个专业术语名词&#xff0c;分别如下所述&#xff1a; 联…

基于深度学习下的稳定学习究竟是什么?因果学习?迁移学习?之一

机器学习 | 稳定学习 | DGBR 深度学习 | 迁移学习 | 因果学习 众所周知&#xff0c;深度学习研究是机器学习领域中一个重要研究方向&#xff0c;主要采用数据分析、数据挖掘、高性能计算等技术&#xff0c;其对服务器的要求极其严格&#xff0c;传统的风冷散热方式已经不足以满…