一??单点登陆
? ?
代码如下
package com.jt.demos;
import redis.clients.jedis.Jedis;
import java.util.UUID;
/** ?* 单点登录应用实践 ?*/ public class SSODemo01 { ? ? static String token; ? ? //模仿访问服务端的资源 ? ? static void doGetResource(){ ? ? ? ? //1.检查token是否存在,(token是存储在客户端-Cookie,localStorage) ? ? ? ? if(token==null){ ? ? ? ? ? ? System.out.println("please login"); ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? //2.检查token是否已经失效 ? ? ? ? Jedis jedis=new Jedis("192.168.126.130",6379); ? ? ? ? String user = jedis.get(token); ? ? ? ? jedis.close(); ? ? ? ? if(user==null){ ? ? ? ? ? ? System.out.println("login timeout or token invalid"); ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? //3.返回你要访问的资源 ? ? ? ? System.out.println("return user resource"); ? ? } ? ? static void doLogin(String username,String password){ ? ? ? ? if("jack".equals(username)&&"123456".equals(password)){ ? ? ? ? ? ? System.out.println("login ok"); ? ? ? ? ? ? String token= UUID.randomUUID().toString(); ? ? ? ? ? ? Jedis jedis=new Jedis("192.168.126.130",6379); ? ? ? ? ? ? jedis.set(token,username);//存储用户信息 ? ? ? ? ? ? jedis.expire(token,1); ? ? ? ? ? ? jedis.close(); ? ? ? ? ? ? //将token存储到客户端 ? ? ? ? ? ? SSODemo01.token=token; ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? System.out.println("username or password error"); ? ? } ? ? public static void main(String[] args) throws InterruptedException {//这里的main方法代表客户端 ? ? ? ? //1.访问资源 ? ? ? ? doGetResource(); ? ? ? ? //2.执行登录操作 ? ? ? ? doLogin("jack","123456"); ? ? ? ? //3.再次访问资源 ? ? ? ? Thread.sleep(1000); ? ? ? ? doGetResource(); ? ? } } ?
二 验证码实现:
package com.jt.demos;
import redis.clients.jedis.Jedis;
/**登录验证码实践 ?* 1)进入登录页面之前先创建一个验证码,并将其存储在redis中 ?* 2)登录时输入验证码,并且将验证码与redis中的验证码进行比对 ?* */ public class CodeDemo01 { ? ? static void doLogin(String username,String password,String inputCode){ ? ? ? ?//1.校验验证码 ? ? ? ? //1.1验证是否为空 ? ? ? ?if(inputCode==null||"".equals(inputCode)){ ? ? ? ? ? ?System.out.println("please input code"); ? ? ? ? ? ?return; ? ? ? ?} ? ? ? ?//1.2验证redis中的code ? ? ? ?Jedis jedis=new Jedis("192.168.126.130",6379); ? ? ? ?String dbCode=jedis.get("code"); ? ? ? ?if(dbCode==null){ ? ? ? ? ? ?System.out.println("code timeout"); ? ? ? ? ? ?return; ? ? ? ?} ? ? ? ?if(!inputCode.equals(dbCode)){ ? ? ? ? ? ?System.out.println("code error"); ? ? ? ? ? ?return; ? ? ? ?} ? ? ? ?//2...... ? ? ? ?System.out.println("继续验证用户身份合法性"); ? ? } ? ? public static void main(String[] args) { ? ? ? ? char[] chars={ ? ? ? ? ? ? ? ? 'A','B','C','D','1','2','.' ? ? ? ? };//后续可以写一个算法从这个数组中随机取出四个值 ? ? ? ?//1.生成一个随机验证码 ? ? ? ? String code="12AB"; ? ? ? ? Jedis jedis=new Jedis("192.168.126.130",6379); ? ? ? ? jedis.set("code","12AB"); ? ? ? ? jedis.expire("code",60); ? ? ? ? jedis.close(); ? ? ? ?//2.执行登录操作 ? ? ? ? doLogin("jack","123456","12AB"); ? ? } } ?
三 投票系统
代码:
package com.jt.demos;
import redis.clients.jedis.Jedis;
import java.util.Set;
/** ?* 设计一个基于某个活动的投票系统. ?*/ public class VoteDemo01 {
? ? //注意,将来这个连接不能多线程共享 ? ? private static ?Jedis jedis=new Jedis("192.168.126.130",6379);
? ? /** ? ? ?* 判定userId是否参与过activityId这个活动的投票 ? ? ?* @param activityId ? ? ?* @param userId ? ? ?* @return true表示参与过投票 ? ? ?*/
? ? static boolean checkVote(String activityId,String userId){ ? ? ? ? //判断set集合activityId对应的值中是否包含这个userId ? ? ? ?return jedis.sismember(activityId,userId); ? ? }
? ? /** ? ? ?* 执行投票逻辑 ? ? ?* @param activityId ? ? ?* @param userId ? ? ?* @return true 表示投票ok ? ? ?*/ ? ? static boolean addVote(String activityId,String userId){ ? ? ? ? if(checkVote(activityId,userId)){ ? ? ? ? ? ? System.out.println("您已经参与过这个投票"); ? ? ? ? ? ? return false; ? ? ? ? } ? ? ? ? jedis.sadd(activityId,userId); ? ? ? ? return true; ? ? }
? ? /** ? ? ?* 获取活动的总票数 ? ? ?* @param activityId ? ? ?* @return ? ? ?*/ ? ? static Long getActivityVotes(String activityId){ ? ? ? ? return jedis.scard(activityId); ? ? } ? ? /** ? ? ?* 获取参与了投票的用户id ? ? ?* @param activityId ? ? ?* @return ? ? ?*/ ? ? static Set<String> ?getActivityUsers(String activityId){ ? ? ? ?return jedis.smembers(activityId); ? ? }
? ? public static void main(String[] args) { ? ? ? ? //1.设置一个活动 ? ? ? ? //1)获取id ? ? ? ? String activityId="10001"; ? ? ? ? //2)活动标题 ? ? ? ? //3)活动内容 ? ? ? ? //2.基于活动进行投票设计 ? ? ? ? String user1="201"; ? ? ? ? String user2="202"; ? ? ? ? String user3="203"; ? ? ? ? //2.1 一个用户对同一个活动不能重复投票 ? ? ? ? //boolean flag=checkVote(activityId,user1); ? ? ? ? //System.out.println("flag="+flag); ? ? ? ? //2.2 执行投票 ? ? ? ? addVote(activityId,user1); ? ? ? ? addVote(activityId,user2); ? ? ? ? addVote(activityId,user3); ? ? ? ? //2.3 能够显示参与投票的人数 ? ? ? ? long voteCount=getActivityVotes(activityId); ? ? ? ? System.out.println(voteCount); ? ? ? ? //2.4 管理员可以查看哪些人参与了投票 ? ? ? ? Set<String> userIds=getActivityUsers(activityId); ? ? ? ? System.out.println(userIds); ? ? } } ?
?四 秒杀队列
代码如下
package com.jt.demos;
import redis.clients.jedis.Jedis;
//秒杀队列演示 //描述逻辑中会将商品抢购信息先写到redis(以队列形式进行存储), //因为写redis内存数据库要比写你的mysql数据库快很多倍 //算法:先进先出(FIFO)-体现公平性 public class SecondKillDemo01 {
? ? //商品抢购首先是入队 ? ? static void enque(String msg){//入队 ? ? ? ? ?Jedis jedis=new Jedis("192.168.126.130",6379); ? ? ? ? ?jedis.auth("123456");//没有认证不需要写这个语句 ? ? ? ? ?jedis.lpush("queue",msg); ? ? ? ? ?jedis.close(); ? ? }
? ? //底层异步出队(基于这个消息,生成订单,扣减库存,...) ? ? static String deque(){//出队 ? ? ? ? Jedis jedis=new Jedis("192.168.126.130",6379); ? ? ? ? jedis.auth("123456");//没有认证不需要写这个语句 ? ? ? ? String result=jedis.rpop("queue"); ? ? ? ? jedis.close(); ? ? ? ? return result; ? ? } ? ? public static void main(String[] args){ ? ? ? ? //1.多次抢购(模拟在界面上多次点击操作) ? ? ? ? new Thread(){ ? ? ? ? ? ? @Override ? ? ? ? ? ? public void run() { ? ? ? ? ? ? ? ? for(int i=1;i<=10;i++){//模拟页面上按钮点击 ? ? ? ? ? ? ? ? ? ? enque(String.valueOf(i)); ? ? ? ? ? ? ? ? ? ? try{Thread.sleep(100);}catch(Exception e){} ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? }.start();
? ? ? ? //2.从队列取内容(模拟后台从队列取数据) ? ? ? ? new Thread(){ ? ? ? ? ? ? @Override ? ? ? ? ? ? public void run() { ? ? ? ? ? ? ? ? for(;;){ ? ? ? ? ? ? ? ? ? ? String msg=deque(); ? ? ? ? ? ? ? ? ? ? if(msg==null)continue; ? ? ? ? ? ? ? ? ? ? System.out.print(msg); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? }.start();
? ? } } ?
?五 购物车简易实现
?关键代码实现:
方案一(使用Jedis)来实现
package com.jt.demos;
import redis.clients.jedis.Jedis;
import java.util.Map;
/** ?* :基于redis存储商品购物车信息 ?*/ public class CartDemo01 {
? ? public static void addCart(Long userId,Long productId,int num){ ? ? ? ? //1.建立redis链接 ? ? ? ? Jedis jedis=new Jedis("192.168.126.130",6379); ? ? ? ? jedis.auth("123456"); ? ? ? ? //2.向购物车添加商品 ? ? ? ? String product = jedis.hget("cart:" + userId, String.valueOf(productId)); ? ? ? ? //hincrBy这个函数在key不存在时会自动创建key ? ? ? ? jedis.hincrBy("cart:" + userId, String.valueOf(productId),num); ? ? ? ? //3.释放redis链接 ? ? ? ? jedis.close(); ? ? } ? ? //查看我的购物车 ? ? public static Map<String, String> listCart(Long userId){ ? ? ? ? //1.建立redis链接 ? ? ? ? Jedis jedis=new Jedis("192.168.126.130",6379); ? ? ? ? jedis.auth("123456"); ? ? ? ? //2.查看购物车商品 ? ? ? ? Map<String, String> map = jedis.hgetAll("cart:" + userId); ? ? ? ? //3.释放redis链接 ? ? ? ? jedis.close(); ? ? ? ? return map; ? ? } ? ? public static void main(String[] args) { ? ? ? ? //1.向购物车添加商品 ? ? ? ? addCart(101L,201L,1); ? ? ? ? addCart(101L,202L,1); ? ? ? ? addCart(101L,203L,2); ? ? ? ? //2.查看购物车商品 ? ? ? ? Map<String, String> map = listCart(101L); ? ? ? ? System.out.println(map); ? ? }
}
方案二 使用RedisTemplate来实现
package com.jt.redis.demos;
import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component;
import javax.annotation.Resource; import java.util.Map;
@Component public class CartDemo01 { //???? @Autowired ??? @Resource(name="stringRedisTemplate") ???? private RedisTemplate redisTemplate;
? public?? void addCard(Integer userId,String? productId,Integer num){ ???????? HashOperations hashOperations = redisTemplate.opsForHash(); ???????? hashOperations.increment("cart:"+userId,productId,num); ??? }
?? public Map<String,Object> ListCart(Integer userId){ ??????? HashOperations hashOperations = redisTemplate.opsForHash(); ??????? return hashOperations.entries("cart:"+userId); ??? } }
此方案需要重新定义RestTemplat,或者使用 @Resource(name="stringRedisTemplate")
六定制RedisTemplate对象
系统默认的RedisTemplate默认采用的是JDK的序列化机制,假如我们不希望实用JDK的序列化,可以采用的定制RedisTemplate,并采用自己指定的的序列化方式
如果序列化或者反序列化失败,可能需要重新定义RedisTemplate
package com.jt.redis.config; @Configuration public class RedisConfig { ? ? @Bean ? ? public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){ ? ? ? ? //1.构建RedisTemplate对象 ? ? ? ? RedisTemplate<Object,Object> redisTemplate=new RedisTemplate<>(); ? ? ? ? //2.设置连接工厂 ? ? ? ? redisTemplate.setConnectionFactory(redisConnectionFactory); ? ? ? ? //3.定义序列化方式(在这里选择jackson) ? ? ? ? Jackson2JsonRedisSerializer redisSerializer= new Jackson2JsonRedisSerializer(Object.class); ? ? ? ? ObjectMapper objectMapper=new ObjectMapper(); ? ? ? ? //设置要序列化的域(属性) ? ? ? ? //any表示任意级别访问修饰符修饰的属性 private,public,protected ? ? ? ? objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY); ? ? ? ? //启动输入域检查(类不能是final修饰的) ? ? ? ? objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ? ? ? ? ? ? ? ? ObjectMapper.DefaultTyping.NON_FINAL, ? ? ? ? ? ? ? ? JsonTypeInfo.As.PROPERTY); ? ? ? ? redisSerializer.setObjectMapper(objectMapper); ? ? ? ? //4.设置RedisTemplate的序列化 ? ? ? ? redisTemplate.setKeySerializer(new StringRedisSerializer()); ? ? ? ? redisTemplate.setValueSerializer(redisSerializer); ? ? ? ? redisTemplate.setHashKeySerializer(new StringRedisSerializer()); ? ? ? ? redisTemplate.setHashValueSerializer(redisSerializer); ? ? ? ? //spring规范中假如修改bean对象的默认特性,建议调用一下afterPropertiesSet() ? ? ? ? redisTemplate.afterPropertiesSet(); ? ? ? ?return redisTemplate; ? ? } } ?
|