设计的思考
上一节我们已经做好了 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