소스 검색

[chg] SnowflakeIdWorker算法和aliyunOSS

wcz 5 년 전
부모
커밋
7c5432bc37

+ 5 - 0
lift-common/pom.xml

@@ -31,6 +31,11 @@
             <artifactId>aliyun-sdk-oss</artifactId>
             <version>3.5.0</version>
         </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>1.2</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 56 - 11
lift-common/src/main/java/cn.com.ty.lift.common/utils/AliyunOSSUtil.java

@@ -5,6 +5,7 @@ import com.aliyun.oss.OSSClientBuilder;
 import com.aliyun.oss.model.OSSObject;
 import com.aliyun.oss.model.OSSObjectSummary;
 import com.aliyun.oss.model.ObjectListing;
+import com.aliyun.oss.model.PutObjectRequest;
 
 import java.io.*;
 
@@ -16,16 +17,39 @@ import java.io.*;
 public class AliyunOSSUtil {
 
     // Endpoint以杭州为例,其它Region请按实际情况填写。
-    String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
+    String endpoint = "http://oss-cn-beijing.aliyuncs.com";
     // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
-    String accessKeyId = "LTAI4FiMAmo6sMB72EstodQD";
-    String accessKeySecret = "humDP4AQmA9rvi8I8pwK28edrxEmS9";
-    String bucketName = "temp15827479607";
+    String accessKeyId = "LTAI4FkSqFZa6LH9HqAsVott";
+    String accessKeySecret = "w7GXuh5tf1hduQuZ2AzT3a4q14BI1i";
 
     public static void main(String[] args) {
+        SnowflakeIdWorker worker = SnowflakeIdWorker.me();
         File file = new File("D:\\mybatis.jpg");
-        AliyunOSSUtil util = new AliyunOSSUtil();
-//        util.putObject();
+        String filename = file.getName();
+        String suffix = filename.substring(filename.indexOf("."));
+        System.out.println("filename: " + filename);
+        System.out.println("suffix: " + suffix);
+        AliyunOSSUtil util = AliyunOSSUtil.me();
+        util.putFile("temp15827479607",worker.nextId() + suffix,file);
+
+//        byte[] content = "ceshi".getBytes();
+//        util.putObject(content,"测试存储");
+    }
+
+    public AliyunOSSUtil() {
+    }
+
+    public AliyunOSSUtil(String endpoint, String accessKeyId, String accessKeySecret) {
+        this.endpoint = endpoint;
+        this.accessKeyId = accessKeyId;
+        this.accessKeySecret = accessKeySecret;
+    }
+
+    public static AliyunOSSUtil me(){
+        return new AliyunOSSUtil();
+    }
+    public static AliyunOSSUtil me(String endpoint,String accessKeyId, String accessKeySecret){
+        return new AliyunOSSUtil(endpoint,accessKeyId,accessKeySecret);
     }
     /**
      * @param
@@ -34,7 +58,7 @@ public class AliyunOSSUtil {
      * 存储空间是OSS全局命名空间,相当于数据的容器,可以存储若干文件。 以下代码用于新建一个存储空间
      * @date 2019/11/29 10:30
      */
-    public void createBucket() {
+    public void createBucket(String bucketName) {
         // 创建OSSClient实例。
         OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
         // 创建存储空间。
@@ -49,7 +73,7 @@ public class AliyunOSSUtil {
      * @description 上传文件,上传文件至OSS
      * @date 2019/11/29 10:31
      */
-    public void putObject(byte[] content,String objectName) {
+    public void putObject(String bucketName,byte[] content,String objectName) {
         // <yourObjectName>上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
 
         // 创建OSSClient实例。
@@ -66,7 +90,7 @@ public class AliyunOSSUtil {
      * @description 下载文件,获取文件的文本内容
      * @date 2019/11/29 10:32
      */
-    public void getObject(String objectName) throws Exception {
+    public void getObject(String bucketName,String objectName) throws Exception {
         // <yourObjectName>从OSS下载文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
 
         // 创建OSSClient实例。
@@ -96,7 +120,7 @@ public class AliyunOSSUtil {
      * @description 列举文件:列举指定存储空间下的文件。默认列举100个文件
      * @date 2019/11/29 10:38
      */
-    public void listObjects() {
+    public void listObjects(String bucketName) {
         // 创建OSSClient实例。
         OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
 
@@ -117,7 +141,7 @@ public class AliyunOSSUtil {
      * @param 
      * @return 
      */
-    public void deleteObject(String objectName){
+    public void deleteObject(String bucketName,String objectName){
         // <yourObjectName>表示删除OSS文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
 
         // 创建OSSClient实例。
@@ -129,4 +153,25 @@ public class AliyunOSSUtil {
         // 关闭OSSClient。
         ossClient.shutdown();
     }
+
+    public void putFile(String bucketName,String objectName,File file){
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+
+
+        // 创建PutObjectRequest对象。
+        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file);
+
+        // 如果需要上传时设置存储类型与访问权限,请参考以下示例代码。
+        // ObjectMetadata metadata = new ObjectMetadata();
+        // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
+        // metadata.setObjectAcl(CannedAccessControlList.Private);
+        // putObjectRequest.setMetadata(metadata);
+
+        // 上传文件。
+        ossClient.putObject(putObjectRequest);
+
+        // 关闭OSSClient。
+        ossClient.shutdown();
+    }
 }

+ 187 - 0
lift-common/src/main/java/cn.com.ty.lift.common/utils/SnowflakeIdWorker.java

@@ -0,0 +1,187 @@
+package cn.com.ty.lift.common.utils;
+
+/**
+ * Twitter_Snowflake<br>
+ * SnowFlake的结构如下(每部分用-分开):<br>
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
+ * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
+ * 加起来刚好64位,为一个Long型。<br>
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
+ */
+public class SnowflakeIdWorker {
+
+    // ==============================Fields===========================================
+    /**
+     * 开始时间截 (2015-01-01)
+     */
+    private final long twepoch = 1420041600000L;
+
+    /**
+     * 机器id所占的位数
+     */
+    private final long workerIdBits = 5L;
+
+    /**
+     * 数据标识id所占的位数
+     */
+    private final long datacenterIdBits = 5L;
+
+    /**
+     * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
+     */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /**
+     * 支持的最大数据标识id,结果是31
+     */
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+
+    /**
+     * 序列在id中占的位数
+     */
+    private final long sequenceBits = 12L;
+
+    /**
+     * 机器ID向左移12位
+     */
+    private final long workerIdShift = sequenceBits;
+
+    /**
+     * 数据标识id向左移17位(12+5)
+     */
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+
+    /**
+     * 时间截向左移22位(5+5+12)
+     */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+    /**
+     * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
+     */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /**
+     * 工作机器ID(0~31)
+     */
+    private long workerId;
+
+    /**
+     * 数据中心ID(0~31)
+     */
+    private long datacenterId;
+
+    /**
+     * 毫秒内序列(0~4095)
+     */
+    private long sequence = 0L;
+
+    /**
+     * 上次生成ID的时间截
+     */
+    private long lastTimestamp = -1L;
+
+    //==============================Constructors=====================================
+
+    /**
+     * 构造函数
+     *
+     * @param workerId     工作ID (0~31)
+     * @param datacenterId 数据中心ID (0~31)
+     */
+    public SnowflakeIdWorker(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    // ==============================Methods==========================================
+
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     *
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+
+        //上次生成ID的时间截
+        lastTimestamp = timestamp;
+
+        //移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (datacenterId << datacenterIdShift) //
+                | (workerId << workerIdShift) //
+                | sequence;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     *
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间
+     *
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    public static SnowflakeIdWorker me() {
+        return new SnowflakeIdWorker(0, 0);
+    }
+    //==============================Test=============================================
+
+    /**
+     * 测试
+     */
+    public static void main(String[] args) {
+        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
+        long begin = System.currentTimeMillis();
+        for (int i = 0; i < 1000000; i++) {
+            long id = idWorker.nextId();
+//            System.out.println(id);
+        }
+        System.err.println("生成100000消耗时间:" + (System.currentTimeMillis() - begin));
+    }
+}

+ 27 - 0
lift-enterprise-service/src/main/java/cn/com/ty/lift/enterprise/common/Conf.java

@@ -0,0 +1,27 @@
+package cn.com.ty.lift.enterprise.common;
+
+import cn.com.ty.lift.common.utils.AliyunOSSUtil;
+import cn.com.ty.lift.common.utils.SnowflakeIdWorker;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author wcz
+ * @date 2019/12/3
+ * @description
+ */
+@Configuration
+public class Conf {
+
+
+
+    @Bean
+    public SnowflakeIdWorker createSnowflakeIdWorker(){
+        return SnowflakeIdWorker.me();
+    }
+
+    @Bean
+    public AliyunOSSUtil createAliyunOSSUtil(){
+        return AliyunOSSUtil.me();
+    }
+}

+ 5 - 0
lift-enterprise-service/src/main/java/cn/com/ty/lift/enterprise/oa/controller/LiftCertificateController.java

@@ -1,5 +1,6 @@
 package cn.com.ty.lift.enterprise.oa.controller;
 
+import cn.com.ty.lift.common.utils.SnowflakeIdWorker;
 import cn.com.ty.lift.enterprise.oa.entity.LiftCertificate;
 import cn.com.ty.lift.enterprise.oa.service.LiftCertificateService;
 import cn.com.xwy.boot.web.dto.RestResponse;
@@ -23,6 +24,8 @@ public class LiftCertificateController {
     @Autowired
     private LiftCertificateService liftCertificateService;
 
+    @Autowired
+    private SnowflakeIdWorker snowflakeIdWorker;
     /**
      * @param
      * @return
@@ -32,7 +35,9 @@ public class LiftCertificateController {
     @PostMapping("findOne")
     public RestResponse<LiftCertificate> findOne(Long id) {
         log.info("id: " + id);
+        log.info("snowflakeIdWorker: " + snowflakeIdWorker.nextId());
         LiftCertificate entity = liftCertificateService.findOne(id);
+
         return RestResponse.ok(entity);
     }