设计的思考
上一节我们已经做好了 redis的service,但是为了防止key冲突,这里做一个前缀空间的引入
主要思想是不同业务模块使用不同的前缀空间
因此我们可以使用 接口+抽象类 来描述
不同的业务模块去生产不同的前缀就行。
这里的设计其实有很多 方案的。
我们可以使用很多的设计模式进行设计。
比如 模板方法模式---用抽象类作为模板,下一层次的子类只要 稍微配置就行
工厂方法模式--我们将各个业务模块的前缀空间的创建使用工厂方法
大家可以实践下设计模式的使用,其他的模式也可以使用的。当然这里不是滥用设计模式,只是为了体验下模式的思想
采用模板方法模式进行设计前缀空间
KeyPrefix.java
package miaosha.redis.key; public interface KeyPrefix { /** * 有效时间 * @return */ public int expireSeconds(); /** * 得到一个key的前缀 * @return */ public String getPrefix(); }
AbstractKeyPrefix.java
package miaosha.redis.key; public abstract class AbstractKeyPrefix implements KeyPrefix{ private int expireSeconds ; private String prefix ; public AbstractKeyPrefix(int expireSeconds , String prefix) { this.expireSeconds = expireSeconds ; this.prefix = prefix ; } public AbstractKeyPrefix(String prefix) { //默认0 代表永不过期 this(0,prefix); } public int expireSeconds() { return expireSeconds; } public String getPrefix() { String name = this.getClass().getSimpleName(); return name+":"+prefix; } }
UserKey.java
package miaosha.redis.key.space; import miaosha.redis.key.AbstractKeyPrefix; public class UserKey extends AbstractKeyPrefix{ public UserKey(String prefix) { super(prefix); } public final static UserKey ID = new UserKey("id"); public final static UserKey NAME = new UserKey("name"); }
实践代理模式-给key加上前缀的处理
RedisServiceProxy.java
package miaosha.redis.service.proxy; import java.util.HashMap; import java.util.Map; import miaosha.dao.domain.User; import miaosha.redis.key.KeyPrefix; import miaosha.redis.key.space.UserKey; import miaosha.redis.service.RedisService; /** * 采用依赖的方式 代理了 原先的 RedisService * * @author kaifeng1 * */ public class RedisServiceProxy implements RedisService{ private RedisService redisService ; public RedisServiceProxy(RedisService redisService) { this.redisService = redisService; } public RedisServiceProxy() { } public RedisServiceProxy proxy(RedisService redisService) { this.redisService = redisService ; return this ; } private static Map<Class<?>, KeyPrefix> table = new HashMap<Class<?>, KeyPrefix>(); static { table.put(User.class, UserKey.ID); } public static KeyPrefix getTargetKeyPrefix(Class<?> claz) { return table.get(claz); } public <T> T getBean(String key, Class<T> claz) throws Exception { KeyPrefix fix = getTargetKeyPrefix(claz); if(fix == null) { System.out.println("please check RedisServiceProxy.table !"); throw new Exception("prefix is not valid! "); } System.out.println("getBean->prefix :"+fix.getPrefix()); return this.redisService.getBean(fix.getPrefix()+"_"+key, claz); } public <T> void setBean(String key, T bean) throws Exception { KeyPrefix fix = getTargetKeyPrefix(bean.getClass()); if(fix == null) { System.out.println("please check RedisServiceProxy.table !"); throw new Exception("prefix is not valid! "); } System.out.println("setBean-> prefix :"+fix.getPrefix()); this.redisService.setBean(fix.getPrefix()+"_"+key, bean); } public <T> void delBean(String key, Class<T> claz) throws Exception { KeyPrefix fix = getTargetKeyPrefix(claz); if(fix == null) { System.out.println("please check RedisServiceProxy.table !"); throw new Exception("prefix is not valid! "); } System.out.println("delBean - > prefix :"+fix.getPrefix()); this.redisService.delBean(fix.getPrefix()+"_"+key, claz); } }
当然这里的代理写的很简陋
我们可以类比 spring 的aop中的代理,使用继承代理动态创建出它的代理对象
但是这中间如何获取前缀的方法仍然是不好的。
毕竟现在获取前缀的方法耦合太大。
怎样能进行解耦呢?
如果我们使用配置的方式,将这些前缀空间对象给注入进去呢?
还需要进一步进行改进
这里就不继续深入了
Controller中加入保存到redis的方法
现在数据库中的数据
我们将第二条纯英文的写入到redis中方便我们检验
如果是汉字的写入到redis中会有转码的问题
这里需要我们 【springboot-No3 】中的UserService
JedisSampleController.java
package miaosha.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import miaosha.dao.domain.User; import miaosha.redis.service.RedisService; import miaosha.redis.service.proxy.RedisServiceProxy; import miaosha.result.Result; import miaosha.service.UserService; import miaosha.util.JsonCom; @Controller @RequestMapping("/jedis") public class JedisSampleController { @Autowired private RedisService redisService ; @Autowired private UserService userService ; @RequestMapping("/saveUserRedisProxy") @ResponseBody Result<String> hello() throws Exception { User user = this.userService.findUserById(2); RedisServiceProxy proxy = new RedisServiceProxy(redisService); proxy.setBean("user", user); User u = proxy.getBean("user", User.class); return Result.sucess(JsonCom.beanToJson(u)); } }
启动我们的 MainApp.java
前缀是 UserKey:id
我们在redis的客户端查看下
可以看到数据是写入到了 redis中的
===============小结=========
到此为止我们已经集成了 mybatis和redis了
项目的整体结构如下:
工程可以看github
https://github.com/lambda-fk/springboot-learing