Ver código fonte

代码调整

baolei 7 meses atrás
pai
commit
9375417c86
21 arquivos alterados com 1267 adições e 377 exclusões
  1. 114 44
      08.src/Xingxi/xingxi-admin/src/main/java/com/xingxi/web/controller/monitor/SysUserOnlineController.java
  2. 1 1
      08.src/Xingxi/xingxi-admin/src/main/java/com/xingxi/web/controller/system/SysConfigController.java
  3. 19 6
      08.src/Xingxi/xingxi-common/pom.xml
  4. 292 0
      08.src/Xingxi/xingxi-common/src/main/java/com/xingxi/common/core/redis/RedisCache.java
  5. 10 19
      08.src/Xingxi/xingxi-common/src/main/java/com/xingxi/common/utils/CacheUtils.java
  6. 72 0
      08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/config/FastJson2JsonRedisSerializer.java
  7. 45 0
      08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/config/RedisConfig.java
  8. 170 132
      08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/config/ShiroConfig.java
  9. 42 45
      08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/manager/ShutdownManager.java
  10. 45 34
      08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/shiro/web/filter/LogoutFilter.java
  11. 1 1
      08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/shiro/web/session/OnlineWebSessionManager.java
  12. 19 6
      08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/web/service/CacheService.java
  13. 4 4
      08.src/Xingxi/xingxi-miniprogram-api/pom.xml
  14. 1 2
      08.src/Xingxi/xingxi-miniprogram-api/src/main/java/com/xingxi/api/configuration/security/WxLoginAuthenticationManager.java
  15. 89 1
      08.src/Xingxi/xingxi-miniprogram-api/src/main/java/com/xingxi/api/data/domain/OrderDTO.java
  16. 79 1
      08.src/Xingxi/xingxi-miniprogram-api/src/main/java/com/xingxi/api/data/domain/OrderDetailDTO.java
  17. 190 0
      08.src/Xingxi/xingxi-miniprogram-api/src/main/java/com/xingxi/utils/DateUtils.java
  18. 9 0
      08.src/Xingxi/xingxi-miniprogram-api/src/main/resources/META-INF/sqlmap/WxApiPaymentInfoMapper.xml
  19. 7 7
      08.src/Xingxi/xingxi-system/src/main/java/com/xingxi/system/service/ISysUserOnlineService.java
  20. 35 46
      08.src/Xingxi/xingxi-system/src/main/java/com/xingxi/system/service/impl/SysConfigServiceImpl.java
  21. 23 28
      08.src/Xingxi/xingxi-system/src/main/java/com/xingxi/system/service/impl/SysUserOnlineServiceImpl.java

+ 114 - 44
08.src/Xingxi/xingxi-admin/src/main/java/com/xingxi/web/controller/monitor/SysUserOnlineController.java

@@ -1,48 +1,47 @@
 package com.xingxi.web.controller.monitor;
 
-import java.util.List;
-import org.apache.shiro.authz.annotation.Logical;
-import org.apache.shiro.authz.annotation.RequiresPermissions;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
 import com.xingxi.common.annotation.Log;
+import com.xingxi.common.constant.ShiroConstants;
 import com.xingxi.common.core.controller.BaseController;
 import com.xingxi.common.core.domain.AjaxResult;
+import com.xingxi.common.core.domain.entity.SysUser;
 import com.xingxi.common.core.page.TableDataInfo;
-import com.xingxi.common.core.text.Convert;
 import com.xingxi.common.enums.BusinessType;
-import com.xingxi.common.enums.OnlineStatus;
 import com.xingxi.common.utils.ShiroUtils;
-import com.xingxi.framework.shiro.session.OnlineSession;
-import com.xingxi.framework.shiro.session.OnlineSessionDAO;
+import com.xingxi.common.utils.StringUtils;
+import com.xingxi.common.utils.spring.SpringUtils;
 import com.xingxi.system.domain.SysUserOnline;
-import com.xingxi.system.service.ISysUserOnlineService;
+import org.apache.shiro.authz.annotation.Logical;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.SimplePrincipalCollection;
+import org.apache.shiro.subject.support.DefaultSubjectContext;
+import org.crazycake.shiro.RedisCacheManager;
+import org.crazycake.shiro.RedisSessionDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.Serializable;
+import java.util.*;
 
 /**
  * 在线用户监控
- * 
- * @author ruoyi
+ *
+ * @author biandan
  */
 @Controller
 @RequestMapping("/monitor/online")
-public class SysUserOnlineController extends BaseController
-{
+public class SysUserOnlineController extends BaseController {
     private String prefix = "monitor/online";
 
     @Autowired
-    private ISysUserOnlineService userOnlineService;
-
-    @Autowired
-    private OnlineSessionDAO onlineSessionDAO;
+    private RedisSessionDAO redisSessionDAO;
 
     @RequiresPermissions("monitor:online:view")
     @GetMapping()
-    public String online()
-    {
+    public String online() {
         return prefix + "/online";
     }
 
@@ -51,38 +50,109 @@ public class SysUserOnlineController extends BaseController
     @ResponseBody
     public TableDataInfo list(SysUserOnline userOnline)
     {
-        startPage();
-        List<SysUserOnline> list = userOnlineService.selectUserOnlineList(userOnline);
-        return getDataTable(list);
+        String ipaddr = userOnline.getIpaddr();
+        String loginName = userOnline.getLoginName();
+        TableDataInfo rspData = new TableDataInfo();
+        Collection<Session> sessions = redisSessionDAO.getActiveSessions();
+        Iterator<Session> it = sessions.iterator();
+        List<SysUserOnline> sessionList = new ArrayList<SysUserOnline>();
+        while (it.hasNext())
+        {
+            SysUserOnline user = getSession(it.next());
+            if (StringUtils.isNotNull(user))
+            {
+                if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(loginName))
+                {
+                    if (StringUtils.equals(ipaddr, user.getIpaddr())
+                            && StringUtils.equals(loginName, user.getLoginName()))
+                    {
+                        sessionList.add(user);
+                    }
+                }
+                else if (StringUtils.isNotEmpty(ipaddr))
+                {
+                    if (StringUtils.equals(ipaddr, user.getIpaddr()))
+                    {
+                        sessionList.add(user);
+                    }
+                }
+                else if (StringUtils.isNotEmpty(loginName))
+                {
+                    if (StringUtils.equals(loginName, user.getLoginName()))
+                    {
+                        sessionList.add(user);
+                    }
+                }
+                else
+                {
+                    sessionList.add(user);
+                }
+            }
+        }
+        rspData.setRows(sessionList);
+        rspData.setTotal(sessionList.size());
+        return rspData;
     }
 
-    @RequiresPermissions(value = { "monitor:online:batchForceLogout", "monitor:online:forceLogout" }, logical = Logical.OR)
+    @RequiresPermissions(value = {"monitor:online:batchForceLogout", "monitor:online:forceLogout"}, logical = Logical.OR)
     @Log(title = "在线用户", businessType = BusinessType.FORCE)
     @PostMapping("/batchForceLogout")
     @ResponseBody
-    public AjaxResult batchForceLogout(String ids)
+    public AjaxResult batchForceLogout(@RequestBody List<SysUserOnline> sysUserOnlines)
     {
-        for (String sessionId : Convert.toStrArray(ids))
+        for (SysUserOnline userOnline : sysUserOnlines)
         {
-            SysUserOnline online = userOnlineService.selectOnlineById(sessionId);
-            if (online == null)
-            {
-                return error("用户已下线");
-            }
-            OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
-            if (onlineSession == null)
-            {
-                return error("用户已下线");
-            }
+            String sessionId = userOnline.getSessionId();
+            String loginName = userOnline.getLoginName();
             if (sessionId.equals(ShiroUtils.getSessionId()))
             {
                 return error("当前登录用户无法强退");
             }
-            onlineSessionDAO.delete(onlineSession);
-            online.setStatus(OnlineStatus.off_line);
-            userOnlineService.saveOnline(online);
-            userOnlineService.removeUserCache(online.getLoginName(), sessionId);
+            redisSessionDAO.delete(redisSessionDAO.readSession(sessionId));
+            removeUserCache(loginName, sessionId);
         }
         return success();
     }
+
+    private SysUserOnline getSession(Session session)
+    {
+        Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
+        if (null == obj)
+        {
+            return null;
+        }
+        if (obj instanceof SimplePrincipalCollection)
+        {
+            SimplePrincipalCollection spc = (SimplePrincipalCollection) obj;
+            obj = spc.getPrimaryPrincipal();
+            if (null != obj && obj instanceof SysUser)
+            {
+                SysUser sysUser = (SysUser) obj;
+                SysUserOnline userOnline = new SysUserOnline();
+                userOnline.setSessionId(session.getId().toString());
+                userOnline.setLoginName(sysUser.getLoginName());
+                if (StringUtils.isNotNull(sysUser.getDept()) && StringUtils.isNotEmpty(sysUser.getDept().getDeptName()))
+                {
+                    userOnline.setDeptName(sysUser.getDept().getDeptName());
+                }
+                userOnline.setIpaddr(session.getHost());
+                userOnline.setStartTimestamp(session.getStartTimestamp());
+                userOnline.setLastAccessTime(session.getLastAccessTime());
+                return userOnline;
+            }
+        }
+        return null;
+    }
+
+    public void removeUserCache(String loginName, String sessionId)
+    {
+        Cache<String, Deque<Serializable>> cache = SpringUtils.getBean(RedisCacheManager.class).getCache(ShiroConstants.SYS_USERCACHE);
+        Deque<Serializable> deque = cache.get(loginName);
+        if (StringUtils.isEmpty(deque) || deque.size() == 0)
+        {
+            return;
+        }
+        deque.remove(sessionId);
+        cache.put(loginName, deque);
+    }
 }

+ 1 - 1
08.src/Xingxi/xingxi-admin/src/main/java/com/xingxi/web/controller/system/SysConfigController.java

@@ -130,7 +130,7 @@ public class SysConfigController extends BaseController {
     @GetMapping("/refreshCache")
     @ResponseBody
     public AjaxResult refreshCache() {
-        configService.resetConfigCache();
+//        configService.resetConfigCache();
         return success();
     }
 

+ 19 - 6
08.src/Xingxi/xingxi-common/pom.xml

@@ -36,12 +36,6 @@
             <groupId>org.apache.shiro</groupId>
             <artifactId>shiro-core</artifactId>
         </dependency>
-        
-        <!-- Shiro使用EhCache缓存框架 -->
-        <dependency>
-            <groupId>org.apache.shiro</groupId>
-            <artifactId>shiro-ehcache</artifactId>
-        </dependency>
 
         <!-- pagehelper 分页插件 -->
         <dependency>
@@ -107,5 +101,24 @@
             <artifactId>lombok</artifactId>
             <optional>true</optional>
         </dependency>
+
+        <!-- shiro整合redis -->
+        <dependency>
+            <groupId>org.crazycake</groupId>
+            <artifactId>shiro-redis</artifactId>
+            <version>3.3.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.velocity</groupId>
+                    <artifactId>velocity</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- springboot整合redis -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 292 - 0
08.src/Xingxi/xingxi-common/src/main/java/com/xingxi/common/core/redis/RedisCache.java

@@ -0,0 +1,292 @@
+package com.xingxi.common.core.redis;
+
+import com.xingxi.common.utils.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.BoundSetOperations;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 工具类
+ *
+ * @author biandan
+ **/
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
+@Component
+public class RedisCache
+{
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key 缓存的键值
+     * @param value 缓存的值
+     */
+    public <T> void setCacheObject(final String key, final T value)
+    {
+        redisTemplate.opsForValue().set(key, value);
+    }
+    
+    /**
+     * 根据key获取缓存中的val+1
+     * 
+     * @param key 缓存的值
+     * @return 数值
+     */
+    public Long increment(final String key)
+    {
+        return redisTemplate.boundValueOps(key).increment();
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key 缓存的键值
+     * @param value 缓存的值
+     * @param timeout 时间
+     * @param timeUnit 时间颗粒度
+     */
+    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
+    {
+        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key Redis键
+     * @param timeout 超时时间
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout)
+    {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key Redis键
+     * @param timeout 超时时间
+     * @param unit 时间单位
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout, final TimeUnit unit)
+    {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 获得缓存的基本对象。
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> T getCacheObject(final String key)
+    {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 删除单个对象
+     *
+     * @param key
+     */
+    public boolean deleteObject(final String key)
+    {
+        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 删除集合对象
+     *
+     * @param collection 多个对象
+     * @return
+     */
+    public long deleteObject(final Collection collection)
+    {
+        return redisTemplate.delete(collection);
+    }
+
+    /**
+     * 缓存List数据
+     *
+     * @param key 缓存的键值
+     * @param dataList 待缓存的List数据
+     * @return 缓存的对象
+     */
+    public <T> long setCacheList(final String key, final List<T> dataList)
+    {
+        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+        return count == null ? 0 : count;
+    }
+
+    /**
+     * 获得缓存的list对象
+     *
+     * @param key 缓存的键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> List<T> getCacheList(final String key)
+    {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
+
+    /**
+     * 缓存Set
+     *
+     * @param key 缓存键值
+     * @param dataSet 缓存的数据
+     * @return 缓存数据的对象
+     */
+    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
+    {
+        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+        Iterator<T> it = dataSet.iterator();
+        while (it.hasNext())
+        {
+            setOperation.add(it.next());
+        }
+        return setOperation;
+    }
+
+    /**
+     * 获得缓存的set
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(final String key)
+    {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 缓存Map
+     *
+     * @param key
+     * @param dataMap
+     */
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
+    {
+        if (dataMap != null) {
+            redisTemplate.opsForHash().putAll(key, dataMap);
+        }
+    }
+
+    /**
+     * 获得缓存的Map
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(final String key)
+    {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 往Hash中存入数据
+     *
+     * @param key Redis键
+     * @param hKey Hash键
+     * @param value 值
+     */
+    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
+    {
+        redisTemplate.opsForHash().put(key, hKey, value);
+    }
+
+    /**
+     * 获取Hash中的数据
+     *
+     * @param key Redis键
+     * @param hKey Hash键
+     * @return Hash中的对象
+     */
+    public <T> T getCacheMapValue(final String key, final String hKey)
+    {
+        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+        return opsForHash.get(key, hKey);
+    }
+
+    /**
+     * 获取多个Hash中的数据
+     *
+     * @param key Redis键
+     * @param hKeys Hash键集合
+     * @return Hash对象集合
+     */
+    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
+    {
+        return redisTemplate.opsForHash().multiGet(key, hKeys);
+    }
+
+    /**
+     * 获得缓存的基本对象列表
+     *
+     * @param pattern 字符串前缀
+     * @return 对象列表
+     */
+    public Collection<String> keys(final String pattern)
+    {
+        return redisTemplate.keys(pattern);
+    }
+
+    //===============================================================================================
+    /**
+     * lockKey 锁 key
+     * value 身份标识(保证锁不会被其他人释放)
+     * expireTime 锁的有效时间
+     **/
+    public Boolean lock(String lockKey, String value, long expireTime) {
+        long start = System.currentTimeMillis();
+        while (true) {
+            // 使用 setIfAbsent 方法进行锁的设置,如果该 key 已存在则返回 false
+            Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, value, expireTime, TimeUnit.MILLISECONDS);
+            if (locked) {
+                return true;
+            }
+
+            // 等待一段时间后重试获取锁
+            try {
+                Thread.sleep(10);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+
+            // 如果获取锁失败,则进行重试
+            long now = System.currentTimeMillis();
+            if ((now - start) > expireTime) {
+                // 如果超时未获取到锁,则返回获取锁失败
+                return false;
+            }
+        }
+    }
+
+    /**
+     * key 锁的key
+     * value 身份标识
+     * return 成功返回true 失败返回false
+     **/
+    public Boolean unlock(String key, String value) {
+        // 获取当前锁的拥有者
+        Object currentValue = redisTemplate.opsForValue().get(key);
+        Boolean result = false;
+        // 判断value是否为锁的拥有者
+        if (StringUtils.isNotEmpty(String.valueOf(currentValue)) && Objects.equals(currentValue, value)) {
+            //删除锁
+            result = redisTemplate.delete(key);
+        }
+
+        return result;
+    }
+}

+ 10 - 19
08.src/Xingxi/xingxi-common/src/main/java/com/xingxi/common/utils/CacheUtils.java

@@ -1,13 +1,14 @@
 package com.xingxi.common.utils;
 
-import java.util.Iterator;
-import java.util.Set;
+import com.xingxi.common.utils.spring.SpringUtils;
 import org.apache.shiro.cache.Cache;
-import org.apache.shiro.cache.CacheManager;
-import org.apache.shiro.cache.ehcache.EhCacheManager;
+import org.crazycake.shiro.RedisCache;
+import org.crazycake.shiro.RedisCacheManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import com.xingxi.common.utils.spring.SpringUtils;
+
+import java.util.Iterator;
+import java.util.Set;
 
 /**
  * Cache工具类
@@ -18,7 +19,7 @@ public class CacheUtils
 {
     private static Logger logger = LoggerFactory.getLogger(CacheUtils.class);
 
-    private static CacheManager cacheManager = SpringUtils.getBean(CacheManager.class);
+    private static RedisCacheManager cacheManager = SpringUtils.getBean(RedisCacheManager.class);
 
     private static final String SYS_CACHE = "sys-cache";
 
@@ -124,7 +125,7 @@ public class CacheUtils
      */
     public static void removeAll(String cacheName)
     {
-        Cache<String, Object> cache = getCache(cacheName);
+        RedisCache<String, Object> cache = getCache(cacheName);
         Set<String> keys = cache.keys();
         for (Iterator<String> it = keys.iterator(); it.hasNext();)
         {
@@ -175,23 +176,13 @@ public class CacheUtils
      * @param cacheName
      * @return
      */
-    public static Cache<String, Object> getCache(String cacheName)
+    public static RedisCache<String, Object> getCache(String cacheName)
     {
         Cache<String, Object> cache = cacheManager.getCache(cacheName);
         if (cache == null)
         {
             throw new RuntimeException("当前系统中没有定义“" + cacheName + "”这个缓存。");
         }
-        return cache;
-    }
-
-    /**
-     * 获取所有缓存
-     * 
-     * @return 缓存组
-     */
-    public static String[] getCacheNames()
-    {
-        return ((EhCacheManager) cacheManager).getCacheManager().getCacheNames();
+        return (RedisCache<String, Object>) cache;
     }
 }

+ 72 - 0
08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/config/FastJson2JsonRedisSerializer.java

@@ -0,0 +1,72 @@
+package com.xingxi.framework.config;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.parser.ParserConfig;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+import org.springframework.util.Assert;
+
+import java.nio.charset.Charset;
+
+/**
+ * Redis使用FastJson序列化
+ * 
+ * @author biandan
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
+{
+    @SuppressWarnings("unused")
+    private ObjectMapper objectMapper = new ObjectMapper();
+
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+    private Class<T> clazz;
+
+    static
+    {
+        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
+    }
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz)
+    {
+        super();
+        this.clazz = clazz;
+    }
+
+    @Override
+    public byte[] serialize(T t) throws SerializationException
+    {
+        if (t == null)
+        {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException
+    {
+        if (bytes == null || bytes.length <= 0)
+        {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+
+        return JSON.parseObject(str, clazz);
+    }
+
+    public void setObjectMapper(ObjectMapper objectMapper)
+    {
+        Assert.notNull(objectMapper, "'objectMapper' must not be null");
+        this.objectMapper = objectMapper;
+    }
+
+    protected JavaType getJavaType(Class<?> clazz)
+    {
+        return TypeFactory.defaultInstance().constructType(clazz);
+    }
+}

+ 45 - 0
08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/config/RedisConfig.java

@@ -0,0 +1,45 @@
+package com.xingxi.framework.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * redis配置
+ * 
+ * @author biandan
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport
+{
+    @Bean
+    @SuppressWarnings(value = { "unchecked", "rawtypes" })
+    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
+    {
+        RedisTemplate<Object, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+        serializer.setObjectMapper(mapper);
+
+        template.setValueSerializer(serializer);
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+        template.afterPropertiesSet();
+        return template;
+    }
+}

+ 170 - 132
08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/config/ShiroConfig.java

@@ -1,49 +1,39 @@
 package com.xingxi.framework.config;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import javax.servlet.Filter;
-import org.apache.commons.io.IOUtils;
-import org.apache.shiro.cache.ehcache.EhCacheManager;
+import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
+import com.xingxi.common.constant.Constants;
+import com.xingxi.common.utils.StringUtils;
+import com.xingxi.common.utils.security.CipherUtils;
+import com.xingxi.framework.shiro.realm.UserRealm;
+import com.xingxi.framework.shiro.web.CustomShiroFilterFactoryBean;
+import com.xingxi.framework.shiro.web.filter.LogoutFilter;
+import com.xingxi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
+import com.xingxi.framework.shiro.web.filter.kickout.KickoutSessionFilter;
 import org.apache.shiro.codec.Base64;
-import org.apache.shiro.config.ConfigurationException;
-import org.apache.shiro.io.ResourceUtils;
 import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.mgt.SessionManager;
 import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
 import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.CookieRememberMeManager;
 import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
 import org.apache.shiro.web.servlet.SimpleCookie;
-import org.springframework.beans.factory.annotation.Qualifier;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+import org.crazycake.shiro.RedisCacheManager;
+import org.crazycake.shiro.RedisManager;
+import org.crazycake.shiro.RedisSessionDAO;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import com.xingxi.common.constant.Constants;
-import com.xingxi.common.utils.StringUtils;
-import com.xingxi.common.utils.security.CipherUtils;
-import com.xingxi.common.utils.spring.SpringUtils;
-import com.xingxi.framework.config.properties.PermitAllUrlProperties;
-import com.xingxi.framework.shiro.realm.UserRealm;
-import com.xingxi.framework.shiro.rememberMe.CustomCookieRememberMeManager;
-import com.xingxi.framework.shiro.session.OnlineSessionDAO;
-import com.xingxi.framework.shiro.session.OnlineSessionFactory;
-import com.xingxi.framework.shiro.web.CustomShiroFilterFactoryBean;
-import com.xingxi.framework.shiro.web.filter.LogoutFilter;
-import com.xingxi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
-import com.xingxi.framework.shiro.web.filter.kickout.KickoutSessionFilter;
-import com.xingxi.framework.shiro.web.filter.online.OnlineSessionFilter;
-import com.xingxi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter;
-import com.xingxi.framework.shiro.web.session.OnlineWebSessionManager;
-import com.xingxi.framework.shiro.web.session.SpringSessionValidationScheduler;
-import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
+
+import javax.servlet.Filter;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
 /**
  * 权限配置加载
- * 
- * @author ruoyi
+ *
+ * @author biandan
  */
 @Configuration
 public class ShiroConfig
@@ -133,105 +123,150 @@ public class ShiroConfig
     private boolean rememberMe;
 
     /**
-     * 缓存管理器 使用Ehcache实现
+     * redis缓存地址
+     */
+    @Value("${spring.redis.port}")
+    private String redisPort;
+
+    /**
+     * redis缓存端口
+     */
+    @Value("${spring.redis.host}")
+    private String redisHost;
+
+    /**
+     * redis数据库索引
+     */
+    @Value("${spring.redis.database}")
+    private int database;
+
+    /**
+     * redis密码
+     */
+    @Value("${spring.redis.password}")
+    private String password;
+
+    /**
+     * Cache Manager (shiro-redis)
      */
     @Bean
-    public EhCacheManager getEhCacheManager()
+    public RedisCacheManager redisCacheManager()
     {
-        net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruoyi");
-        EhCacheManager em = new EhCacheManager();
-        if (StringUtils.isNull(cacheManager))
-        {
-            em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
-            return em;
-        }
-        else
-        {
-            em.setCacheManager(cacheManager);
-            return em;
-        }
+        RedisCacheManager redisCacheManager = new RedisCacheManager();
+        redisCacheManager.setRedisManager(redisManager());
+        redisCacheManager.setPrincipalIdFieldName("userId");
+        return redisCacheManager;
     }
 
     /**
-     * 返回配置文件流 避免ehcache配置文件一直被占用,无法完全销毁项目重新部署
+     * RedisManager (shiro-redis)
      */
-    protected InputStream getCacheManagerConfigFileInputStream()
+    @Bean
+    public RedisManager redisManager()
     {
-        String configFile = "classpath:ehcache/ehcache-shiro.xml";
-        InputStream inputStream = null;
-        try
-        {
-            inputStream = ResourceUtils.getInputStreamForPath(configFile);
-            byte[] b = IOUtils.toByteArray(inputStream);
-            InputStream in = new ByteArrayInputStream(b);
-            return in;
-        }
-        catch (IOException e)
-        {
-            throw new ConfigurationException(
-                    "Unable to obtain input stream for cacheManagerConfigFile [" + configFile + "]", e);
-        }
-        finally
+        RedisManager redisManager = new RedisManager();
+        redisManager.setHost(redisHost + ":" + redisPort);
+        redisManager.setDatabase(database);
+        if (StringUtils.isNotEmpty(password))
         {
-            IOUtils.closeQuietly(inputStream);
+            redisManager.setPassword(password);
         }
+        redisManager.setTimeout(expireTime * 60);
+        return redisManager;
     }
 
+//    /**
+//     * 缓存管理器 使用Ehcache实现
+//     */
+//    @Bean
+//    public EhCacheManager getEhCacheManager() {
+//        net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("biandan");
+//        EhCacheManager em = new EhCacheManager();
+//        if (StringUtils.isNull(cacheManager)) {
+//            em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
+//            return em;
+//        } else {
+//            em.setCacheManager(cacheManager);
+//            return em;
+//        }
+//    }
+//
+//    /**
+//     * 返回配置文件流 避免ehcache配置文件一直被占用,无法完全销毁项目重新部署
+//     */
+//    protected InputStream getCacheManagerConfigFileInputStream() {
+//        String configFile = "classpath:ehcache/ehcache-shiro.xml";
+//        InputStream inputStream = null;
+//        try {
+//            inputStream = ResourceUtils.getInputStreamForPath(configFile);
+//            byte[] b = IOUtils.toByteArray(inputStream);
+//            InputStream in = new ByteArrayInputStream(b);
+//            return in;
+//        } catch (IOException e) {
+//            throw new ConfigurationException(
+//                    "Unable to obtain input stream for cacheManagerConfigFile [" + configFile + "]", e);
+//        } finally {
+//            IOUtils.closeQuietly(inputStream);
+//        }
+//    }
+
     /**
      * 自定义Realm
      */
     @Bean
-    public UserRealm userRealm(EhCacheManager cacheManager)
+    public UserRealm userRealm()
     {
         UserRealm userRealm = new UserRealm();
         userRealm.setAuthorizationCacheName(Constants.SYS_AUTH_CACHE);
-        userRealm.setCacheManager(cacheManager);
+        userRealm.setCacheManager(redisCacheManager());
         return userRealm;
     }
 
     /**
-     * 自定义sessionDAO会话
+     * RedisSessionDAO (shiro-redis)
      */
     @Bean
-    public OnlineSessionDAO sessionDAO()
+    public RedisSessionDAO redisSessionDAO()
     {
-        OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
-        return sessionDAO;
+        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
+        redisSessionDAO.setRedisManager(redisManager());
+        redisSessionDAO.setExpire(expireTime * 60);
+        return redisSessionDAO;
     }
 
-    /**
-     * 自定义sessionFactory会话
-     */
-    @Bean
-    public OnlineSessionFactory sessionFactory()
-    {
-        OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
-        return sessionFactory;
-    }
+//    /**
+//     * 自定义sessionDAO会话
+//     */
+//    @Bean
+//    public OnlineSessionDAO sessionDAO() {
+//        OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
+//        return sessionDAO;
+//    }
+
+//    /**
+//     * 自定义sessionFactory会话
+//     */
+//    @Bean
+//    public OnlineSessionFactory sessionFactory() {
+//        OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
+//        return sessionFactory;
+//    }
 
     /**
      * 会话管理器
      */
     @Bean
-    public OnlineWebSessionManager sessionManager()
+    public SessionManager sessionManager()
     {
-        OnlineWebSessionManager manager = new OnlineWebSessionManager();
+        DefaultWebSessionManager manager = new DefaultWebSessionManager();
         // 加入缓存管理器
-        manager.setCacheManager(getEhCacheManager());
-        // 删除过期的session
-        manager.setDeleteInvalidSessions(true);
-        // 设置全局session超时时间
-        manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
+        manager.setCacheManager(redisCacheManager());
         // 去掉 JSESSIONID
         manager.setSessionIdUrlRewritingEnabled(false);
-        // 定义要使用的无效的Session定时调度器
-        manager.setSessionValidationScheduler(SpringUtils.getBean(SpringSessionValidationScheduler.class));
-        // 是否定时检查session
-        manager.setSessionValidationSchedulerEnabled(true);
         // 自定义SessionDao
-        manager.setSessionDAO(sessionDAO());
-        // 自定义sessionFactory
-        manager.setSessionFactory(sessionFactory());
+        manager.setSessionDAO(redisSessionDAO());
+        // 设置全局session超时时间
+        manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
         return manager;
     }
 
@@ -247,7 +282,7 @@ public class ShiroConfig
         // 记住我
         securityManager.setRememberMeManager(rememberMe ? rememberMeManager() : null);
         // 注入缓存管理器;
-        securityManager.setCacheManager(getEhCacheManager());
+        securityManager.setCacheManager(redisCacheManager());
         // session管理器
         securityManager.setSessionManager(sessionManager());
         return securityManager;
@@ -260,6 +295,7 @@ public class ShiroConfig
     {
         LogoutFilter logoutFilter = new LogoutFilter();
         logoutFilter.setLoginUrl(loginUrl);
+        logoutFilter.setCacheManager(redisCacheManager());
         return logoutFilter;
     }
 
@@ -280,22 +316,19 @@ public class ShiroConfig
         LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
         // 对静态资源设置匿名访问
         filterChainDefinitionMap.put("/favicon.ico**", "anon");
-        filterChainDefinitionMap.put("/ruoyi.png**", "anon");
+        filterChainDefinitionMap.put("/biandan.png**", "anon");
+        filterChainDefinitionMap.put("/beian.png**", "anon");
         filterChainDefinitionMap.put("/html/**", "anon");
         filterChainDefinitionMap.put("/css/**", "anon");
         filterChainDefinitionMap.put("/docs/**", "anon");
         filterChainDefinitionMap.put("/fonts/**", "anon");
         filterChainDefinitionMap.put("/img/**", "anon");
+        filterChainDefinitionMap.put("/i18n/**", "anon");
         filterChainDefinitionMap.put("/ajax/**", "anon");
         filterChainDefinitionMap.put("/js/**", "anon");
-        filterChainDefinitionMap.put("/ruoyi/**", "anon");
+        filterChainDefinitionMap.put("/biandan/**", "anon");
+        filterChainDefinitionMap.put("/api/expfeeds/**", "anon");
         filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
-        // 匿名访问不鉴权注解列表
-        List<String> permitAllUrl = SpringUtils.getBean(PermitAllUrlProperties.class).getUrls();
-        if (StringUtils.isNotEmpty(permitAllUrl))
-        {
-            permitAllUrl.forEach(url -> filterChainDefinitionMap.put(url, "anon"));
-        }
         // 退出 logout地址,shiro去清除session
         filterChainDefinitionMap.put("/logout", "logout");
         // 不需要拦截的访问
@@ -305,9 +338,9 @@ public class ShiroConfig
         // 系统权限列表
         // filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
 
-        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
-        filters.put("onlineSession", onlineSessionFilter());
-        filters.put("syncOnlineSession", syncOnlineSessionFilter());
+        Map<String, Filter> filters = new LinkedHashMap<>();
+//        filters.put("onlineSession", onlineSessionFilter());
+//        filters.put("syncOnlineSession", syncOnlineSessionFilter());
         filters.put("captchaValidate", captchaValidateFilter());
         filters.put("kickout", kickoutSessionFilter());
         // 注销成功,则跳转到指定页面
@@ -315,32 +348,30 @@ public class ShiroConfig
         shiroFilterFactoryBean.setFilters(filters);
 
         // 所有请求需要认证
-        filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");
+        filterChainDefinitionMap.put("/**", "user,kickout");
         shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
 
         return shiroFilterFactoryBean;
     }
-
-    /**
-     * 自定义在线用户处理过滤器
-     */
-    public OnlineSessionFilter onlineSessionFilter()
-    {
-        OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
-        onlineSessionFilter.setLoginUrl(loginUrl);
-        onlineSessionFilter.setOnlineSessionDAO(sessionDAO());
-        return onlineSessionFilter;
-    }
-
-    /**
-     * 自定义在线用户同步过滤器
-     */
-    public SyncOnlineSessionFilter syncOnlineSessionFilter()
-    {
-        SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
-        syncOnlineSessionFilter.setOnlineSessionDAO(sessionDAO());
-        return syncOnlineSessionFilter;
-    }
+//
+//    /**
+//     * 自定义在线用户处理过滤器
+//     */
+//    public OnlineSessionFilter onlineSessionFilter() {
+//        OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
+//        onlineSessionFilter.setLoginUrl(loginUrl);
+//        onlineSessionFilter.setOnlineSessionDAO(sessionDAO());
+//        return onlineSessionFilter;
+//    }
+//
+//    /**
+//     * 自定义在线用户同步过滤器
+//     */
+//    public SyncOnlineSessionFilter syncOnlineSessionFilter() {
+//        SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
+//        syncOnlineSessionFilter.setOnlineSessionDAO(sessionDAO());
+//        return syncOnlineSessionFilter;
+//    }
 
     /**
      * 自定义验证码过滤器
@@ -369,9 +400,9 @@ public class ShiroConfig
     /**
      * 记住我
      */
-    public CustomCookieRememberMeManager rememberMeManager()
+    public CookieRememberMeManager rememberMeManager()
     {
-        CustomCookieRememberMeManager cookieRememberMeManager = new CustomCookieRememberMeManager();
+        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
         cookieRememberMeManager.setCookie(rememberMeCookie());
         if (StringUtils.isNotEmpty(cipherKey))
         {
@@ -390,7 +421,7 @@ public class ShiroConfig
     public KickoutSessionFilter kickoutSessionFilter()
     {
         KickoutSessionFilter kickoutSessionFilter = new KickoutSessionFilter();
-        kickoutSessionFilter.setCacheManager(getEhCacheManager());
+        kickoutSessionFilter.setCacheManager(redisCacheManager());
         kickoutSessionFilter.setSessionManager(sessionManager());
         // 同一个用户最大的会话数,默认-1无限制;比如2的意思是同一个用户允许最多同时两个人登录
         kickoutSessionFilter.setMaxSession(maxSession);
@@ -414,11 +445,18 @@ public class ShiroConfig
      * 开启Shiro注解通知器
      */
     @Bean
-    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
-            @Qualifier("securityManager") SecurityManager securityManager)
+    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager)
     {
         AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
         authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
         return authorizationAttributeSourceAdvisor;
     }
+
+    @Bean
+    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator()
+    {
+        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+        defaultAdvisorAutoProxyCreator.setUsePrefix(true);
+        return defaultAdvisorAutoProxyCreator;
+    }
 }

+ 42 - 45
08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/manager/ShutdownManager.java

@@ -1,12 +1,9 @@
 package com.xingxi.framework.manager;
 
-import com.xingxi.framework.shiro.web.session.SpringSessionValidationScheduler;
-import net.sf.ehcache.CacheManager;
-import org.apache.shiro.cache.ehcache.EhCacheManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+
 import javax.annotation.PreDestroy;
 
 /**
@@ -19,38 +16,38 @@ public class ShutdownManager
 {
     private static final Logger logger = LoggerFactory.getLogger("sys-user");
 
-    @Autowired(required = false)
-    private SpringSessionValidationScheduler springSessionValidationScheduler;
-
-    @Autowired(required = false)
-    private EhCacheManager ehCacheManager;
+//    @Autowired(required = false)
+//    private SpringSessionValidationScheduler springSessionValidationScheduler;
+//
+//    @Autowired(required = false)
+//    private EhCacheManager ehCacheManager;
 
     @PreDestroy
     public void destroy()
     {
-        shutdownSpringSessionValidationScheduler();
+//        shutdownSpringSessionValidationScheduler();
         shutdownAsyncManager();
-        shutdownEhCacheManager();
+//        shutdownEhCacheManager();
     }
 
-    /**
-     * 停止Seesion会话检查
-     */
-    private void shutdownSpringSessionValidationScheduler()
-    {
-        if (springSessionValidationScheduler != null && springSessionValidationScheduler.isEnabled())
-        {
-            try
-            {
-                logger.info("====关闭会话验证任务====");
-                springSessionValidationScheduler.disableSessionValidation();
-            }
-            catch (Exception e)
-            {
-                logger.error(e.getMessage(), e);
-            }
-        }
-    }
+//    /**
+//     * 停止Seesion会话检查
+//     */
+//    private void shutdownSpringSessionValidationScheduler()
+//    {
+//        if (springSessionValidationScheduler != null && springSessionValidationScheduler.isEnabled())
+//        {
+//            try
+//            {
+//                logger.info("====关闭会话验证任务====");
+//                springSessionValidationScheduler.disableSessionValidation();
+//            }
+//            catch (Exception e)
+//            {
+//                logger.error(e.getMessage(), e);
+//            }
+//        }
+//    }
 
     /**
      * 停止异步执行任务
@@ -68,20 +65,20 @@ public class ShutdownManager
         }
     }
 
-    private void shutdownEhCacheManager()
-    {
-        try
-        {
-            logger.info("====关闭缓存====");
-            if (ehCacheManager != null)
-            {
-                CacheManager cacheManager = ehCacheManager.getCacheManager();
-                cacheManager.shutdown();
-            }
-        }
-        catch (Exception e)
-        {
-            logger.error(e.getMessage(), e);
-        }
-    }
+//    private void shutdownEhCacheManager()
+//    {
+//        try
+//        {
+//            logger.info("====关闭缓存====");
+//            if (ehCacheManager != null)
+//            {
+//                CacheManager cacheManager = ehCacheManager.getCacheManager();
+//                cacheManager.shutdown();
+//            }
+//        }
+//        catch (Exception e)
+//        {
+//            logger.error(e.getMessage(), e);
+//        }
+//    }
 }

+ 45 - 34
08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/shiro/web/filter/LogoutFilter.java

@@ -1,90 +1,101 @@
 package com.xingxi.framework.shiro.web.filter;
 
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import org.apache.shiro.session.SessionException;
-import org.apache.shiro.subject.Subject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import com.xingxi.common.constant.Constants;
+import com.xingxi.common.constant.ShiroConstants;
 import com.xingxi.common.core.domain.entity.SysUser;
 import com.xingxi.common.utils.MessageUtils;
 import com.xingxi.common.utils.ShiroUtils;
 import com.xingxi.common.utils.StringUtils;
-import com.xingxi.common.utils.spring.SpringUtils;
 import com.xingxi.framework.manager.AsyncManager;
 import com.xingxi.framework.manager.factory.AsyncFactory;
-import com.xingxi.system.service.ISysUserOnlineService;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.session.SessionException;
+import org.apache.shiro.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.Serializable;
+import java.util.Deque;
 
 /**
  * 退出过滤器
- * 
- * @author ruoyi
+ *
+ * @author biandan
  */
 public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
 {
     private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
 
-    /**
-     * 退出后重定向的地址
-     */
+    /** 退出后重定向的地址 */
     private String loginUrl;
 
+    private Cache<String, Deque<Serializable>> cache;
+
     public String getLoginUrl()
     {
         return loginUrl;
     }
 
-    public void setLoginUrl(String loginUrl)
-    {
+    public void setLoginUrl(String loginUrl) {
         this.loginUrl = loginUrl;
     }
 
     @Override
-    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
-    {
-        try
-        {
+    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
+        try {
             Subject subject = getSubject(request, response);
             String redirectUrl = getRedirectUrl(request, response, subject);
-            try
-            {
+            try {
                 SysUser user = ShiroUtils.getSysUser();
-                if (StringUtils.isNotNull(user))
-                {
+                if (StringUtils.isNotNull(user)) {
                     String loginName = user.getLoginName();
                     // 记录用户退出日志
                     AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
                     // 清理缓存
-                    SpringUtils.getBean(ISysUserOnlineService.class).removeUserCache(loginName, ShiroUtils.getSessionId());
+                    removeUserCache(loginName, ShiroUtils.getSessionId());
                 }
                 // 退出登录
                 subject.logout();
-            }
-            catch (SessionException ise)
-            {
+            } catch (SessionException ise) {
                 log.error("logout fail.", ise);
             }
             issueRedirect(request, response, redirectUrl);
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             log.error("Encountered session exception during logout.  This can generally safely be ignored.", e);
         }
         return false;
     }
 
+    public void removeUserCache(String loginName, String sessionId)
+    {
+        Deque<Serializable> deque = cache.get(loginName);
+        if (StringUtils.isEmpty(deque) || deque.size() == 0)
+        {
+            return;
+        }
+        deque.remove(sessionId);
+        cache.put(loginName, deque);
+    }
+
     /**
      * 退出跳转URL
      */
     @Override
-    protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject)
-    {
+    protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject) {
         String url = getLoginUrl();
-        if (StringUtils.isNotEmpty(url))
-        {
+        if (StringUtils.isNotEmpty(url)) {
             return url;
         }
         return super.getRedirectUrl(request, response, subject);
     }
+
+    // 设置Cache的key的前缀
+    public void setCacheManager(CacheManager cacheManager)
+    {
+        // 必须和ehcache缓存配置中的缓存name一致
+        this.cache = cacheManager.getCache(ShiroConstants.SYS_USERCACHE);
+    }
 }

+ 1 - 1
08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/shiro/web/session/OnlineWebSessionManager.java

@@ -135,7 +135,7 @@ public class OnlineWebSessionManager extends DefaultWebSessionManager
                 }
                 invalidCount++;
                 needOfflineIdList.add(userOnline.getSessionId());
-                userOnlineService.removeUserCache(userOnline.getLoginName(), userOnline.getSessionId());
+//                userOnlineService.removeUserCache(userOnline.getLoginName(), userOnline.getSessionId());
             }
 
         }

+ 19 - 6
08.src/Xingxi/xingxi-framework/src/main/java/com/xingxi/framework/web/service/CacheService.java

@@ -1,11 +1,13 @@
 package com.xingxi.framework.web.service;
 
+import com.xingxi.common.core.redis.RedisCache;
+import com.xingxi.common.utils.CacheUtils;
+import org.crazycake.shiro.IRedisManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
 import java.util.Set;
 import java.util.TreeSet;
-import org.apache.commons.lang3.ArrayUtils;
-import org.springframework.stereotype.Service;
-import com.xingxi.common.constant.Constants;
-import com.xingxi.common.utils.CacheUtils;
 
 /**
  * 缓存操作处理
@@ -15,6 +17,16 @@ import com.xingxi.common.utils.CacheUtils;
 @Service
 public class CacheService
 {
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    private IRedisManager redisManager;
+
+    private final String DEFAULT_SESSION_KEY_PREFIX = "shiro:session:";
+
+    private final String DEFAULT_AUTHCACHE_KEY_PREFIX = "shiro:cache:sys-authCache";
+
     /**
      * 获取所有缓存名称
      * 
@@ -22,8 +34,9 @@ public class CacheService
      */
     public String[] getCacheNames()
     {
-        String[] cacheNames = CacheUtils.getCacheNames();
-        return ArrayUtils.removeElement(cacheNames, Constants.SYS_AUTH_CACHE);
+        String[] cacheNames = { "shiro:session", "shiro:cache:sys-authCache", "shiro:cache:sys-userCache", "sys_dict",
+                "sys_config", "sys_loginRecordCache" };
+        return cacheNames;
     }
 
     /**

+ 4 - 4
08.src/Xingxi/xingxi-miniprogram-api/pom.xml

@@ -23,10 +23,10 @@
             <groupId>com.xingxi</groupId>
             <artifactId>xingxi-system</artifactId>
         </dependency>
-        <dependency>
-            <groupId>com.xingxi</groupId>
-            <artifactId>xingxi-common</artifactId>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.xingxi</groupId>-->
+<!--            <artifactId>xingxi-common</artifactId>-->
+<!--        </dependency>-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>

+ 1 - 2
08.src/Xingxi/xingxi-miniprogram-api/src/main/java/com/xingxi/api/configuration/security/WxLoginAuthenticationManager.java

@@ -2,7 +2,6 @@ package com.xingxi.api.configuration.security;
 
 import com.xingxi.common.core.domain.entity.SysUser;
 import com.xingxi.common.enums.EUserType;
-import com.xingxi.system.mapper.SysConfigMapper;
 import com.xingxi.system.mapper.SysUserMapper;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -25,7 +24,7 @@ import java.util.Date;
 @Primary
 public class WxLoginAuthenticationManager implements AuthenticationManager {
     private final SysUserMapper sysUserMapper;
-    private final SysConfigMapper configMapper;
+//    private final SysConfigMapper configMapper;
 //    private final WxaStoreMerchantMapper wxaStoreMerchantMapper;
 
     @Transactional

+ 89 - 1
08.src/Xingxi/xingxi-miniprogram-api/src/main/java/com/xingxi/api/data/domain/OrderDTO.java

@@ -1,16 +1,104 @@
 package com.xingxi.api.data.domain;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.xingxi.business.Order.domain.Order;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.math.BigDecimal;
+import java.util.Date;
 import java.util.List;
 
 @Getter
 @Setter
 @JsonIgnoreProperties("params")
-public class OrderDTO extends Order {
+public class OrderDTO {
+
+    // 订单ID
+    private Long orderId;
+
+    // 订单号
+    private String orderNo;
+
+    // 订单时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date orderTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date payTime;
+
+    // 订单状态
+    private String orderStatus;
+
+    // 订单总额
+    private BigDecimal orderAmount;
+
+    // 支付金额
+    private BigDecimal payAmount;
+
+    // 商品数量
+    private Integer prodQuantity;
+
+    // 购方用户ID
+    private Long buyerId;
+
+    // 销方用户ID
+    private Long sellerId;
+
+    // 取消时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date cancelTime;
+
+    // 完成时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date finishTime;
+
+    // 收件人省名称
+    private String recProv;
+
+    // 收件人市名称
+    private String recCity;
+
+    // 收件人区名称
+    private String recDistrict;
+
+    // 收件人地址
+    private String recAddress;
+
+    // 收件人姓名
+    private String recName;
+
+    // 收件人联系方式
+    private String recMobile;
+
+    private String remark;
+
+    // 删除标志(0代表存在 2代表删除)
+    private String delFlag;
+
+
+    /**
+     * 创建者
+     */
+    private String createUser;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateUser;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
 
     private List<OrderDetailDTO> orderDetailDTOS;
 

+ 79 - 1
08.src/Xingxi/xingxi-miniprogram-api/src/main/java/com/xingxi/api/data/domain/OrderDetailDTO.java

@@ -1,5 +1,6 @@
 package com.xingxi.api.data.domain;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.xingxi.business.Order.domain.OrderDeliveryExpr;
 import com.xingxi.business.Order.domain.OrderDetail;
@@ -7,12 +8,89 @@ import com.xingxi.master.product.domain.ProdPic;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.math.BigDecimal;
+import java.util.Date;
 import java.util.List;
 
 @Setter
 @Getter
 @JsonIgnoreProperties("params")
-public class OrderDetailDTO extends OrderDetail {
+public class OrderDetailDTO {
+
+    // 订单明细ID
+    private Long orderDetailId;
+
+    // 订单ID
+    private Long orderId;
+
+    // 订单明细状态
+    private String orderDetailStatus;
+
+    // 商品ID
+    private Long prodId;
+
+    // 商品名
+    private String prodName;
+
+    // 属性组合编号
+    private Long prodAttrId;
+
+    // 属性组合名称
+    private String prodAttrName;
+
+    // 供应商ID
+    private Long vendorId;
+
+    // 购买数量
+    private Integer quantity;
+
+    // 售后中数量
+    private Integer afterQty;
+
+    // 已退货数量
+    private Integer returnQty;
+
+    // 购买单价
+    private BigDecimal price;
+
+    // 总金额
+    private BigDecimal orderAmount;
+
+    // 支付金额
+    private BigDecimal payAmount;
+
+    // 确认收货时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date confirmTime;
+
+    // 完成时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date finishTime;
+
+    // 删除标志(0代表存在 1代表删除)
+    private String delFlag;
+
+    /**
+     * 创建者
+     */
+    private String createUser;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateUser;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
 
     private List<ProdPic> imageDTOS;
     private List<OrderDeliveryExpr> orderDetailExprs;

+ 190 - 0
08.src/Xingxi/xingxi-miniprogram-api/src/main/java/com/xingxi/utils/DateUtils.java

@@ -0,0 +1,190 @@
+package com.xingxi.utils;
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.util.Date;
+
+/**
+ * 时间工具类
+ * 
+ * @author ruoyi
+ */
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils
+{
+    public static final String RFC3339 = "yyyy-MM-dd'T'HH:mm:ssXXX";
+
+    public static String YYYY = "yyyy";
+
+    public static String YYYY_MM = "yyyy-MM";
+
+    public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    private static String[] parsePatterns = {
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
+            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+    /**
+     * 获取当前Date型日期
+     * 
+     * @return Date() 当前日期
+     */
+    public static Date getNowDate()
+    {
+        return new Date();
+    }
+
+    /**
+     * 获取当前日期, 默认格式为yyyy-MM-dd
+     * 
+     * @return String
+     */
+    public static String getDate()
+    {
+        return dateTimeNow(YYYY_MM_DD);
+    }
+
+    public static final String getTime()
+    {
+        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static final String dateTimeNow()
+    {
+        return dateTimeNow(YYYYMMDDHHMMSS);
+    }
+
+    public static final String dateTimeNow(final String format)
+    {
+        return parseDateToStr(format, new Date());
+    }
+
+    public static final String dateTime(final Date date)
+    {
+        return parseDateToStr(YYYY_MM_DD, date);
+    }
+
+    public static final String parseDateToStr(final String format, final Date date)
+    {
+        return new SimpleDateFormat(format).format(date);
+    }
+
+    public static final Date dateTime(final String format, final String ts)
+    {
+        try
+        {
+            return new SimpleDateFormat(format).parse(ts);
+        }
+        catch (ParseException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 日期路径 即年/月/日 如2018/08/08
+     */
+    public static final String datePath()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+
+    /**
+     * 日期路径 即年/月/日 如20180808
+     */
+    public static final String dateTime()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyyMMdd");
+    }
+
+    /**
+     * 日期型字符串转化为日期 格式
+     */
+    public static Date parseDate(Object str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        try
+        {
+            return parseDate(str.toString(), parsePatterns);
+        }
+        catch (ParseException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 获取服务器启动时间
+     */
+    public static Date getServerStartDate()
+    {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        return new Date(time);
+    }
+
+    /**
+     * 计算相差天数
+     */
+    public static int differentDaysByMillisecond(Date date1, Date date2)
+    {
+        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+    }
+
+    /**
+     * 计算时间差
+     *
+     * @param endDate 最后时间
+     * @param startTime 开始时间
+     * @return 时间差(天/小时/分钟)
+     */
+    public static String timeDistance(Date endDate, Date startTime)
+    {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 获得两个时间的毫秒时间差异
+        long diff = endDate.getTime() - startTime.getTime();
+        // 计算差多少天
+        long day = diff / nd;
+        // 计算差多少小时
+        long hour = diff % nd / nh;
+        // 计算差多少分钟
+        long min = diff % nd % nh / nm;
+        // 计算差多少秒//输出结果
+        // long sec = diff % nd % nh % nm / ns;
+        return day + "天" + hour + "小时" + min + "分钟";
+    }
+
+    /**
+     * 增加 LocalDateTime ==> Date
+     */
+    public static Date toDate(LocalDateTime temporalAccessor)
+    {
+        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    /**
+     * 增加 LocalDate ==> Date
+     */
+    public static Date toDate(LocalDate temporalAccessor)
+    {
+        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+}

+ 9 - 0
08.src/Xingxi/xingxi-miniprogram-api/src/main/resources/META-INF/sqlmap/WxApiPaymentInfoMapper.xml

@@ -4,6 +4,15 @@
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.xingxi.api.data.mapper.WxApiPaymentInfoMapper">
 
+    <sql id="selectPaymentInfoVo">
+        select
+            payId, orderId, orderNo, orderStatus, payTime, payKind, sellerId, combineAppid, combineMchid, deviceId,
+            payerClientIp, mchid, outTradeNo, subMchid, subAttach, subDescription, payAmount, subCurrency,
+            profitSharing, wxOpenId, notifyUrl, stateCode, prepayId, tradeType, tradeState, bankType, successTime,
+            transactionId, wxOrderId, wxOrderStatus, delFlag, createUser, createTime, updateUser, updateTime
+        from t_payment_info
+    </sql>
+
     <select id="selectPaymentInfoByOutTradeNo" parameterType="String" resultType="PaymentInfo">
         <include refid="selectPaymentInfoVo"/>
         where out_trade_no = #{outTradeNo} and del_flag = '0'

+ 7 - 7
08.src/Xingxi/xingxi-system/src/main/java/com/xingxi/system/service/ISysUserOnlineService.java

@@ -55,13 +55,13 @@ public interface ISysUserOnlineService {
      */
     void forceLogout(String sessionId);
 
-    /**
-     * 清理用户缓存
-     *
-     * @param loginName 登录名称
-     * @param sessionId 会话ID
-     */
-    void removeUserCache(String loginName, String sessionId);
+//    /**
+//     * 清理用户缓存
+//     *
+//     * @param loginName 登录名称
+//     * @param sessionId 会话ID
+//     */
+//    void removeUserCache(String loginName, String sessionId);
 
     /**
      * 查询会话集合

+ 35 - 46
08.src/Xingxi/xingxi-system/src/main/java/com/xingxi/system/service/impl/SysConfigServiceImpl.java

@@ -1,30 +1,35 @@
 package com.xingxi.system.service.impl;
 
-import java.util.List;
-import javax.annotation.PostConstruct;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.xingxi.common.constant.Constants;
 import com.xingxi.common.constant.UserConstants;
+import com.xingxi.common.core.redis.RedisCache;
 import com.xingxi.common.core.text.Convert;
 import com.xingxi.common.exception.ServiceException;
-import com.xingxi.common.utils.CacheUtils;
 import com.xingxi.common.utils.StringUtils;
 import com.xingxi.system.domain.SysConfig;
 import com.xingxi.system.mapper.SysConfigMapper;
 import com.xingxi.system.service.ISysConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
 
 /**
  * 参数配置 服务层实现
- * 
- * @author xingxi
+ *
+ * @author biandan
  */
 @Service
-public class SysConfigServiceImpl implements ISysConfigService
-{
-    @Autowired
+public class SysConfigServiceImpl implements ISysConfigService {
+    @Resource
     private SysConfigMapper configMapper;
 
+    @Autowired
+    private RedisCache redisCache;
+
     /**
      * 项目启动时,初始化参数到缓存
      */
@@ -36,13 +41,12 @@ public class SysConfigServiceImpl implements ISysConfigService
 
     /**
      * 查询参数配置信息
-     * 
+     *
      * @param configId 参数配置ID
      * @return 参数配置信息
      */
     @Override
-    public SysConfig selectConfigById(Long configId)
-    {
+    public SysConfig selectConfigById(Long configId) {
         SysConfig config = new SysConfig();
         config.setConfigId(configId);
         return configMapper.selectConfig(config);
@@ -50,14 +54,14 @@ public class SysConfigServiceImpl implements ISysConfigService
 
     /**
      * 根据键名查询参数配置信息
-     * 
+     *
      * @param configKey 参数key
      * @return 参数键值
      */
     @Override
     public String selectConfigByKey(String configKey)
     {
-        String configValue = Convert.toStr(CacheUtils.get(getCacheName(), getCacheKey(configKey)));
+        String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
         if (StringUtils.isNotEmpty(configValue))
         {
             return configValue;
@@ -67,7 +71,7 @@ public class SysConfigServiceImpl implements ISysConfigService
         SysConfig retConfig = configMapper.selectConfig(config);
         if (StringUtils.isNotNull(retConfig))
         {
-            CacheUtils.put(getCacheName(), getCacheKey(configKey), retConfig.getConfigValue());
+            redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
             return retConfig.getConfigValue();
         }
         return StringUtils.EMPTY;
@@ -75,19 +79,18 @@ public class SysConfigServiceImpl implements ISysConfigService
 
     /**
      * 查询参数配置列表
-     * 
+     *
      * @param config 参数配置信息
      * @return 参数配置集合
      */
     @Override
-    public List<SysConfig> selectConfigList(SysConfig config)
-    {
+    public List<SysConfig> selectConfigList(SysConfig config) {
         return configMapper.selectConfigList(config);
     }
 
     /**
      * 新增参数配置
-     * 
+     *
      * @param config 参数配置信息
      * @return 结果
      */
@@ -97,38 +100,33 @@ public class SysConfigServiceImpl implements ISysConfigService
         int row = configMapper.insertConfig(config);
         if (row > 0)
         {
-            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
         }
         return row;
     }
 
     /**
      * 修改参数配置
-     * 
+     *
      * @param config 参数配置信息
      * @return 结果
      */
     @Override
     public int updateConfig(SysConfig config)
     {
-        SysConfig temp = configMapper.selectConfigById(config.getConfigId());
-        if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey()))
-        {
-            CacheUtils.remove(getCacheName(), getCacheKey(temp.getConfigKey()));
-        }
-
         int row = configMapper.updateConfig(config);
         if (row > 0)
         {
-            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
         }
         return row;
     }
 
     /**
      * 批量删除参数配置对象
-     * 
-     * @param ids 需要删除的数据ID
+     *
+     * @param ids 需要删除的ID
+     * @return 结果
      */
     @Override
     public void deleteConfigByIds(String ids)
@@ -142,7 +140,7 @@ public class SysConfigServiceImpl implements ISysConfigService
                 throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
             }
             configMapper.deleteConfigById(configId);
-            CacheUtils.remove(getCacheName(), getCacheKey(config.getConfigKey()));
+            redisCache.deleteObject(getCacheKey(config.getConfigKey()));
         }
     }
 
@@ -155,7 +153,7 @@ public class SysConfigServiceImpl implements ISysConfigService
         List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
         for (SysConfig config : configsList)
         {
-            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
         }
     }
 
@@ -165,7 +163,8 @@ public class SysConfigServiceImpl implements ISysConfigService
     @Override
     public void clearConfigCache()
     {
-        CacheUtils.removeAll(getCacheName());
+        Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*");
+        redisCache.deleteObject(keys);
     }
 
     /**
@@ -180,7 +179,7 @@ public class SysConfigServiceImpl implements ISysConfigService
 
     /**
      * 校验参数键名是否唯一
-     * 
+     *
      * @param config 参数配置信息
      * @return 结果
      */
@@ -197,18 +196,8 @@ public class SysConfigServiceImpl implements ISysConfigService
     }
 
     /**
-     * 获取cache name
-     * 
-     * @return 缓存名
-     */
-    private String getCacheName()
-    {
-        return Constants.SYS_CONFIG_CACHE;
-    }
-
-    /**
      * 设置cache key
-     * 
+     *
      * @param configKey 参数键
      * @return 缓存键key
      */

+ 23 - 28
08.src/Xingxi/xingxi-system/src/main/java/com/xingxi/system/service/impl/SysUserOnlineServiceImpl.java

@@ -1,20 +1,15 @@
 package com.xingxi.system.service.impl;
 
-import java.io.Serializable;
-import java.util.Date;
-import java.util.Deque;
-import java.util.List;
-import com.xingxi.common.utils.spring.SpringUtils;
-import org.apache.shiro.cache.Cache;
-import org.apache.shiro.cache.ehcache.EhCacheManager;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.xingxi.common.constant.ShiroConstants;
 import com.xingxi.common.utils.DateUtils;
 import com.xingxi.common.utils.StringUtils;
 import com.xingxi.system.domain.SysUserOnline;
 import com.xingxi.system.mapper.SysUserOnlineMapper;
 import com.xingxi.system.service.ISysUserOnlineService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
 
 /**
  * 在线用户 服务层处理
@@ -107,24 +102,24 @@ public class SysUserOnlineServiceImpl implements ISysUserOnlineService
         userOnlineDao.deleteOnlineById(sessionId);
     }
 
-    /**
-     * 清理用户缓存
-     * 
-     * @param loginName 登录名称
-     * @param sessionId 会话ID
-     */
-    @Override
-    public void removeUserCache(String loginName, String sessionId)
-    {
-        EhCacheManager ehCacheManager = SpringUtils.getBean(EhCacheManager.class);
-        Cache<String, Deque<Serializable>> cache = ehCacheManager.getCache(ShiroConstants.SYS_USERCACHE);
-        Deque<Serializable> deque = cache.get(loginName);
-        if (StringUtils.isEmpty(deque) || deque.size() == 0)
-        {
-            return;
-        }
-        deque.remove(sessionId);
-    }
+//    /**
+//     * 清理用户缓存
+//     *
+//     * @param loginName 登录名称
+//     * @param sessionId 会话ID
+//     */
+//    @Override
+//    public void removeUserCache(String loginName, String sessionId)
+//    {
+//        EhCacheManager ehCacheManager = SpringUtils.getBean(EhCacheManager.class);
+//        Cache<String, Deque<Serializable>> cache = ehCacheManager.getCache(ShiroConstants.SYS_USERCACHE);
+//        Deque<Serializable> deque = cache.get(loginName);
+//        if (StringUtils.isEmpty(deque) || deque.size() == 0)
+//        {
+//            return;
+//        }
+//        deque.remove(sessionId);
+//    }
 
     /**
      * 查询会话集合