生成短链接

生成短链接算法

	@Override
    public String createShortLink(String longLink, String expireTime) {
        String shortLink = "";
        long longHash = Hashing.murmur3_32().hashString(longLink, StandardCharsets.UTF_8).padToLong();
        long hash = longHash;
        while (true) {
            //查询是否存在
            ShortLink sLink = queryByHash(hash);
            if(null == sLink){
                break;
            }
            if(longLink.equals(sLink.getLongLink())){
                shortLink = sLink.getShortLink();
                sLink.setExpireTime(DateUtil.localDateTime(expireTime, 0));
                //更新数据库
                break;
            }

            //hash冲突
            long snowId = SnowFlakeUtil.getDefaultSnowFlakeId();
            long snowHash = Hashing.murmur3_32().hashLong(snowId).padToLong();
            hash = Math.abs(longHash - snowHash);
        }

        if(ParamUtil.isNotEmpty(shortLink)){
            return shortLink;
        }

        return Base62Util.encode(hash);
    }

短链接跳转

@GetMapping("/{shortLink}")
    public void redirectLongLink(@PathVariable("shortLink") String shortLink, HttpServletResponse response){
        if(ParamUtil.isEmpty(shortLink)){
            return;
        }

        String longLink = shortLinkService.queryLongLink(shortLink);
        if(ParamUtil.isEmpty(longLink)){
            return;
        }
        try{
            response.setStatus(301);
            response.setHeader("Location", longLink);
        } catch (Exception e){
            e.printStackTrace();
        }
    }

工具类

public class Base62Util {

    private static final char[] toBase62 = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
    };

    private static final String base62Str = String.valueOf(toBase62);

    private static final int length = toBase62.length;

    public static String encode(Long src){
        if(null == src || src <= 0){
            return null;
        }

        StringBuilder dst = new StringBuilder();
        while (src > 0) {
            dst.insert(0, toBase62[(int)(src % length)]);
            src = src / length;
        }

        while (dst.length() < 6){
            dst.insert(0, toBase62[0]);
        }

        return dst.toString();
    }

    public static Long decode(String dst){
        if(ParamUtil.isEmpty(dst)){
            return null;
        }

        long num = 0;
        long factor = 1;
        dst = new StringBuilder(dst).reverse().toString();
        for(char ch : dst.toCharArray()){
            num += base62Str.indexOf(ch) * factor;
            factor *= length;
        }
        return num;
    }

}
/**
 * 雪花算法工具类
 */
public class SnowFlakeUtil {
    private static final long START_STMP = 1420041600000L;
    private static final long SEQUENCE_BIT = 9L;
    private static final long MACHINE_BIT = 2L;
    private static final long DATACENTER_BIT = 2L;
    private static final long MAX_SEQUENCE = 511L;
    private static final long MAX_MACHINE_NUM = 3L;
    private static final long MAX_DATACENTER_NUM = 3L;
    private static final long MACHINE_LEFT = 9L;
    private static final long DATACENTER_LEFT = 11L;
    private static final long TIMESTMP_LEFT = 13L;
    private long datacenterId;
    private long machineId;
    private long sequence = 0L;
    private long lastStmp = -1L;

    public SnowFlakeUtil(long datacenterId, long machineId) {
        if (datacenterId <= 3L && datacenterId >= 0L) {
            if (machineId <= 3L && machineId >= 0L) {
                this.datacenterId = datacenterId;
                this.machineId = machineId;
            } else {
                throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
            }
        } else {
            throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
        }
    }

    public synchronized long nextId() {
        long currStmp = this.getNewstmp();
        if (currStmp < this.lastStmp) {
            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
        } else {
            if (currStmp == this.lastStmp) {
                this.sequence = this.sequence + 1L & 511L;
                if (this.sequence == 0L) {
                    currStmp = this.getNextMill();
                }
            } else {
                this.sequence = 0L;
            }

            this.lastStmp = currStmp;
            return currStmp - 1420041600000L << 13 | this.datacenterId << 11 | this.machineId << 9 | this.sequence;
        }
    }

    private long getNextMill() {
        long mill;
        for(mill = this.getNewstmp(); mill <= this.lastStmp; mill = this.getNewstmp()) {
        }

        return mill;
    }

    private long getNewstmp() {
        return System.currentTimeMillis();
    }

    public static Long getDefaultSnowFlakeId() {
        return ((SnowFlakeUtil) Singleton.get(SnowFlakeUtil.class, new Object[]{1L, 1L})).nextId();
    }

    public static void main(String[] args) {
        for(int i = 0; i < 10; ++i) {
            System.out.println(getDefaultSnowFlakeId());
            System.out.println(getDefaultSnowFlakeId().toString().length());
        }

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值