Redis是一个 Key-Value 存储系统。和 Memcached 类似,它支持存储的 value 类型相对更多,包括 string(字符串)、 list(链表)、 set(集合)和 zset(有序集合)。这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis 支持各种不同方式的排序。与 memcached 一样,为了保证效率,数据都是缓存在内存中。区别的是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave(主从)同步
1、wget http://download.redis.io/releases/redis-4.0.1.tar.gz
2、 tar xzf redis-4.0.1.tardaemonize :yes
允许防火墙开启6379
$ firewall-cmd --zone=public --add-port=6379/tcp --permanent
$ firewall-cmd --reload //重新载入
ps -ef |grep 6379
/usr/local/bin/redis-server *:6379 中通过"*"就可以看出此时是允许所有的ip连接登录到这台redis服务上
代码如下
在pom.xml 加入spring-data redis 的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
如果你项目有spring-devtool 依赖,请注释掉,要不然redis会出问题的
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
编辑 application.yml 加入这两句就可以了
redis: host: 192.168.1.200 port: 6379
其中在Spring 容器中 redis bean 只有一个,不管你在哪里注入,取的值都是这个实例中的 ,我使用
@Configuration public class RedisConfig { public final Environment ev; public RedisConfig(Environment ev) { this.ev = ev; } @Bean JedisConnectionFactory jedisConnectionFactory() { JedisConnectionFactory jedisConnectionFactory=new JedisConnectionFactory(); jedisConnectionFactory.setHostName(ev.getProperty("spring.redis.host")); jedisConnectionFactory.setPort(Integer.parseInt(ev.getProperty("spring.redis.port"))); return jedisConnectionFactory; } @Bean RedisTemplate<String, RegisteredVM> redisTemplate() { RedisTemplate<String, RegisteredVM> template = new RedisTemplate<>(); template.setConnectionFactory(jedisConnectionFactory()); template.setKeySerializer(new StringRedisSerializer()); //代表key的值为String template.setValueSerializer(new JdkSerializationRedisSerializer());// 代表value的值为对象,当然这两个可以随意调换,
//最好自己百度redis的序列化,会更加明白 return template; } }
@RestController @RequestMapping("/api") public class AccountResource { private final Logger log = LoggerFactory.getLogger(AccountResource.class); private final UserRepository userRepository; private final UserService userService; private final MailService mailService; @Autowired private RedisTemplate<String, RegisteredVM> redisTemplate;
private List<String> sentType = Arrays.asList("register", "forgotPassword", "activate");
//为了reidis支持不同情况的手机验证码只能存在一个,我在发送验证码加了type拼装,这样保证注册发送的验证码是唯一的,不会跟其他的发送类型的验证码冲突
@PostMapping(path = "/register", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE}) @Timed public ResponseEntity registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM, @RequestParam(required = false) String code) { HttpHeaders textPlainHeaders = new HttpHeaders(); textPlainHeaders.setContentType(MediaType.TEXT_PLAIN); String type = "register"; if (redisTemplate.opsForValue().get(managedUserVM.getLogin().toLowerCase() +","+ type) == null) { return new ResponseEntity<>("验证码不存在,请重新发送", textPlainHeaders, HttpStatus.BAD_REQUEST); } else { if (!redisTemplate.opsForValue().get(managedUserVM.getLogin() + "," + type).getCode().equals(code)) { return new ResponseEntity<>("验证码不正确,请重新输入", textPlainHeaders, HttpStatus.FORBIDDEN); } } if (!managedUserVM.getPassword().equals(managedUserVM.getRepeatPasswor())) { return new ResponseEntity<>("你的两次密码不正确,请重新输入", textPlainHeaders, HttpStatus.FORBIDDEN); } return userRepository.findOneByLogin(managedUserVM.getLogin()) .map(user -> new ResponseEntity<>("login already in use", textPlainHeaders, HttpStatus.BAD_REQUEST)) .orElseGet(() -> { User user = userService.createUser(managedUserVM.getLogin(), managedUserVM.getPassword(), managedUserVM.getFirstName(), managedUserVM.getLastName(), null, managedUserVM.getImageUrl(), managedUserVM.getLangKey()); redisTemplate.delete(managedUserVM.getLogin() + type); return new ResponseEntity<>(HttpStatus.CREATED); }); }
@PostMapping(path = "/sendCode", produces = {MediaType.TEXT_PLAIN_VALUE}) @Timed public ResponseEntity<String> sendCode(@RequestBody MessageDTO messageDTO, @RequestParam(value = "type", required = false) String type) throws ApiException { if (redisTemplate.opsForValue().get(messageDTO.getPhone()) != null) { if (redisTemplate.opsForValue().get(messageDTO.getPhone()).getTime() != null) { long nd = 1000 * 24 * 60 * 60; long nh = 1000 * 60 * 60; long nm = 1000 * 60; long ns = 1000; long diff = (redisTemplate.opsForValue().get(messageDTO.getPhone()).getTime().getTime() - new Date().getTime()) % nd % nh % nm / ns; if ((int) diff < 60) { return new ResponseEntity<>(messageDTO.getPhone() + ":验证码一分钟才能发一次", HttpStatus.METHOD_NOT_ALLOWED); } } } if (!sentType.contains(type)) { return new ResponseEntity<>("发送类型不匹配", HttpStatus.BAD_REQUEST); } SendMessageService messageService = new SendMessageService(); String code = messageService.verificationCode(); // String statue = messageService.SendMessage(messageDTO, code); // 发送手机验证码 String statue=null; if (statue == null) {// 发送成功 RegisteredVM registeredVM = new RegisteredVM(); registeredVM.setCode(code); registeredVM.setTime(new Date()); registeredVM.setSendType(type); redisTemplate.opsForValue().set(messageDTO.getPhone() + "," + type, registeredVM); redisTemplate.expire(messageDTO.getPhone(), 3, TimeUnit.MINUTES);//设置key存在的时间 return new ResponseEntity<>(code, HttpStatus.OK); } else { return new ResponseEntity<>(statue, HttpStatus.BAD_REQUEST); } }
}