1. 面向接口编程
在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,
各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;而各个对象之间的协作关
系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都
是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。
上述内容来自百度百科(说实话我没看懂).
2. 需求
emall商城中有用户登录后需要将用户的token信息在服务端保存一份,实现这个功能有两个思路:
此处就需要将存储token的这一逻辑抽象成接口,两种方式分别实现此接口,从而达到业务逻辑与底层实现分离.
3. 实现
3.1 抽象ILocalCache
接口
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
|
public interface ILocalCache<T> {
boolean setCache(String key, T value);
boolean cleanCache(String key);
Object getCache(String key); }
|
3.2 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
|
public class RedisCacheImpl<T> implements ILocalCache<T> { public static final Logger LOGGER = LoggerFactory.getLogger(RedisCacheImpl.class);
@Autowired private JedisClientDao jedisClientDao;
@Override public boolean setCache(String key, T value) { jedisClientDao.set(Const.CACHE_TOKEN + ":" + key, JsonUtils.objectToJson(value)); jedisClientDao.expire(Const.CACHE_TOKEN + ":" + key, Const.CACHE_TOKEN_EXPIRE); return true; }
@Override public boolean cleanCache(String key) { try { String json = jedisClientDao.get(Const.CACHE_TOKEN + ":" + key); if (StringUtils.isNoneBlank(json)) { jedisClientDao.expire(Const.CACHE_TOKEN + ":" + key, 0); } return true; } catch (Exception e) { return false; } }
@Override public Object getCache(String key) { try { String json = jedisClientDao.get(Const.CACHE_TOKEN + ":" + key); if (StringUtils.isBlank(json)) { return ServerResponse.build(400, "此Session已经过期,请重新登录"); } jedisClientDao.expire(Const.CACHE_TOKEN + ":" + key, Const.CACHE_TOKEN_EXPIRE); EmallUser emallUser = JsonUtils.jsonToPojo(json, EmallUser.class); return ServerResponse.success(emallUser); } catch (Exception e) { return ServerResponse.error("无法获取用户信息"); } } }
|
3.3 Guava的LoadingCache实现方式
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
|
public class GuavaCacheImpl<T> implements ILocalCache<T> { public static final Logger LOGGER = LoggerFactory.getLogger(GuavaCacheImpl.class);
private static LoadingCache<String, Object> localCache = CacheBuilder.newBuilder().initialCapacity(1000) .maximumSize(10000).expireAfterAccess(12, TimeUnit.HOURS) .build(new CacheLoader<String, Object>() { @Override public Object load(String s) throws Exception { return null; } });
@Override public boolean setCache(String key, T value) { try { localCache.put(key, value); } catch (Exception e) { return false; } return true; }
@Override public boolean cleanCache(String key) { try { localCache.invalidate(key); } catch (Exception e) { return false; } return true; }
@Override public Object getCache(String key) { try { return localCache.get(key); } catch (Exception e) { LOGGER.error("========== localCache get error ==========", e); } return null; } }
|
3.4 applicationContext.xml
中配置
1 2 3
|
<bean class="com.lujiahao.sso.utils.cache.GuavaCacheImpl"/>
|
3.5 代码中使用
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
| @Service public class IUserServiceImpl implements IUserService { private static final Logger LOGGER = LoggerFactory.getLogger(IUserServiceImpl.class);
@Autowired private EmallUserMapper emallUserMapper;
@Autowired private ILocalCache iLocalCache;
@Override public ServerResponse userLogin(String username, String password) { try { String md5Password = DigestUtils.md5DigestAsHex(password.getBytes()); EmallUser emallUser = emallUserMapper.userLogin(username, md5Password); if (emallUser == null) { return ServerResponse.error("用户名或密码错误"); } emallUser.setPassword(StringUtils.EMPTY); String token = UUID.randomUUID().toString(); boolean isSaveSuccess = iLocalCache.setCache(token, emallUser); if (isSaveSuccess) { return ServerResponse.success(token); } else { LOGGER.info("========== 用户信息保存缓存失败 =========="); return ServerResponse.error("登录失败,请重试!"); } } catch (Exception e) { ExceptionUtil.getStackTrace(e); return ServerResponse.error("服务器异常"); } } }
|
在代码中使用的时候,将接口ILocalCache
注入,在applicationContex.xml
中根据具体要求配置不同的
bean,由此就可以实现将缓存业务与缓存实现解耦.
4. 总结
我理解的面向接口编程就是将业务中的需求抽取出公共的几种方式或步骤,底层由不同的类来实现这个接口,
由此达到解耦的目的.个人理解,欢迎大家拍砖^_^.