前言 最近在学习怎么做一个项目,记录一下一些经常用到工具类。
MD5加密 用户的密码一般都会进行加密后在存储到数据库当中,所以一般用到MD5这种加密算法。
这种加密算法最大的特点就是不可逆,只能加密不能解密。
这是挺简单的一种加密算法了,之后还可以考虑加盐和哈希散列,进行更复杂的加密手段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Md5Utils { public static String encrypt (String strSrc) { try { char hexChars[] = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' }; byte [] bytes = strSrc.getBytes(); MessageDigest md = MessageDigest.getInstance("MD5" ); md.update(bytes); bytes = md.digest(); int j = bytes.length; char [] chars = new char [j * 2 ]; int k = 0 ; for (int i = 0 ; i < bytes.length; i++) { byte b = bytes[i]; chars[k++] = hexChars[b >>> 4 & 0xf ]; chars[k++] = hexChars[b & 0xf ]; } return new String(chars); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); throw new RuntimeException("MD5加密出错+" + e); } } }
Redis配置类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 @EnableCaching @Configuration public class RedisConfig extends CachingConfigurationSelector { @Bean public RedisTemplate<String,Object> redisTemplate (RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); template.setKeySerializer(stringRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } @Bean public CacheManager cacheManager (RedisConnectionFactory factory) { RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); jackson2JsonRedisSerializer.setObjectMapper(om); RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600 )) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build(); return cacheManager; } }
雪花算法 对于MySQL的主键问题,一般都需要使用自增的主键。但是只是从1自增就会因为分库分表产生主键相同的情况。
所以这次使用雪花算法生成一个分布式全局唯一ID
首先要知道雪花算法生成的ID是怎么样的。
分布式ID一般都是Long类型,所以会有64位。
第一部分是一个bit位,是一个标识部分,在java中由于long的最高位是符号位,正数是0,负数是1,一般生成的ID为正数,所以固定为0 第二部分是时间戳,该部分占41bit,这个是毫秒级的时间 第三部分是工作机器ID,占10bit 第四部分是序列号,占12bit,支持同一毫秒内同一个节点可以生成4096个ID 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 public class SnowFlake { private final static long START_STMP = 1480166465631L ; private final static long SEQUENCE_BIT = 12 ; private final static long MACHINE_BIT = 5 ; private final static long DATACENTER_BIT = 5 ; private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; private long datacenterId; private long machineId; private long sequence = 0L ; private long lastStmp = -1L ; public SnowFlake (long datacenterId, long machineId) { if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0 ) { throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0" ); } if (machineId > MAX_MACHINE_NUM || machineId < 0 ) { throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0" ); } this .datacenterId = datacenterId; this .machineId = machineId; } public synchronized long nextId () { long currStmp = getNewstmp(); if (currStmp < lastStmp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id" ); } if (currStmp == lastStmp) { sequence = (sequence + 1 ) & MAX_SEQUENCE; if (sequence == 0L ) { currStmp = getNextMill(); } } else { sequence = 0L ; } lastStmp = currStmp; return (currStmp - START_STMP) << TIMESTMP_LEFT | datacenterId << DATACENTER_LEFT | machineId << MACHINE_LEFT | sequence; } private long getNextMill () { long mill = getNewstmp(); while (mill <= lastStmp) { mill = getNewstmp(); } return mill; } private long getNewstmp () { return System.currentTimeMillis(); } public static void main (String[] args) { SnowFlake snowFlake = new SnowFlake(2 , 3 ); for (int i = 0 ; i < (1 << 12 ); i++) { System.out.println(snowFlake.nextId()); } } }
参考于:https://github.com/beyondfengyu/SnowFlake