pom.xml
@@ -123,6 +123,13 @@ <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--redis缓存客户端--> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.5.0</version> </dependency> </dependencies> <build> readme.md
@@ -3,7 +3,13 @@ * 最初始版框架,接口文档访问:{ip}:{port}/doc.html,例如:localhost:8090/doc.html * 登录Session为JWT版本 * 登录Session为SessionCookie * 集群技术主要考虑的是解决Session共享问题,对资源来说最好的方式是redis作为session的存储,也可以使用tomcat的提供的集群设置,实现Session在多个tomcat中的复制(这个本项目不适用,因为内嵌tomcat,不方便设置) * 采取了分布式缓存,集成了redis单机版/哨兵/集群版本 * web转发采用nginx,配置示例如下 ```yaml TODO ``` * 禁止在本通用架构上直接更新具体项目代码提交! 禁止本通用架构上Merge其他git分支! *********** src/main/java/com/whyc/config/RedisConfig.java
New file @@ -0,0 +1,105 @@ package com.whyc.config; import com.whyc.properties.RedisClusterProperties; import com.whyc.properties.RedisPoolProperties; import com.whyc.properties.RedisProperties; import lombok.extern.slf4j.Slf4j; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.util.StringUtils; @Configuration @EnableConfigurationProperties(RedisProperties.class) @Slf4j public class RedisConfig { @Autowired RedisProperties redisProperties; /** * redis单机 */ @Bean("redisClient") @ConditionalOnProperty(name = "redis.model", havingValue = "single") @Order(1) RedissonClient redissonClientSingle() { log.error("redis单机版client初始化了"); Config config = new Config(); String node = redisProperties.getSingle().getAddress(); SingleServerConfig serverConfig = config.useSingleServer() .setAddress(node) .setTimeout(redisProperties.getTimeout()) .setConnectionPoolSize(redisProperties.getPool().getSize()) .setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle()); if (!StringUtils.isEmpty(redisProperties.getPassword())) { serverConfig.setPassword(redisProperties.getPassword()); } return Redisson.create(config); } /** * redis哨兵 */ @Bean("redisClient") @ConditionalOnProperty(name = "redis.model", havingValue = "sentinel") RedissonClient redissonClientSentinel() { log.error("redis单机版client初始化了"); Config config = new Config(); String[] nodes = redisProperties.getSentinel().getNodes().split(","); SentinelServersConfig serversConfig = config.useSentinelServers() .addSentinelAddress(nodes) .setMasterName(redisProperties.getSentinel().getMaster()) .setReadMode(ReadMode.SLAVE) .setFailedAttempts(redisProperties.getSentinel().getFailMax()) .setTimeout(redisProperties.getTimeout()) .setMasterConnectionPoolSize(redisProperties.getPool().getSize()) .setSlaveConnectionPoolSize(redisProperties.getPool().getSize()); if (!StringUtils.isEmpty(redisProperties.getPassword())) { serversConfig.setPassword(redisProperties.getPassword()); } return Redisson.create(config); } /** * 集群 */ @Bean("redisClient") @ConditionalOnProperty(name = "redis.model", havingValue = "cluster") RedissonClient redissonClientCluster() { log.error("redis单机版client初始化了"); Config config = new Config(); RedisClusterProperties cluster = redisProperties.getCluster(); RedisPoolProperties pool = redisProperties.getPool(); String[] nodes = cluster.getNodes().split(","); ClusterServersConfig serversConfig = config.useClusterServers() .addNodeAddress(nodes) .setScanInterval(cluster.getScanInterval()) .setIdleConnectionTimeout(pool.getSoTimeout()) .setConnectTimeout(pool.getConnTimeout()) .setFailedAttempts(cluster.getFailedAttempts()) .setRetryAttempts(cluster.getRetryAttempts()) .setRetryInterval(cluster.getRetryInterval()) .setMasterConnectionPoolSize(cluster.getMasterConnectionPoolSize()) .setSlaveConnectionPoolSize(cluster.getSlaveConnectionPoolSize()) .setTimeout(redisProperties.getTimeout()); if (!StringUtils.isEmpty(redisProperties.getPassword())) { serversConfig.setPassword(redisProperties.getPassword()); } return Redisson.create(config); } } src/main/java/com/whyc/config/RedisSessionDao.java
New file @@ -0,0 +1,95 @@ package com.whyc.config; import com.whyc.constant.SuperConstant; import com.whyc.util.ShiroRedissionSerialize; import io.swagger.annotations.ApiModel; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.eis.AbstractSessionDAO; import org.redisson.api.RBucket; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.DependsOn; import javax.annotation.Resource; import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.concurrent.TimeUnit; /** * 实现Shiro session的memcached集中式管理 */ @Slf4j public class RedisSessionDao extends AbstractSessionDAO { /*@Resource(name = "redissonClient4Shiro") RedissonClient redissonClient;*/ @Autowired RedissonClient redissonClient; private Long globalSessionTimeout; /** * 保存Session * @param session * @return */ @Override protected Serializable doCreate(Session session) { Serializable sessionId = generateSessionId(session); assignSessionId(session,sessionId); //将Session存入redis RBucket<String> sessionIdBucket = redissonClient.getBucket(SuperConstant.GROUP_CAS + sessionId.toString()); sessionIdBucket.trySet(ShiroRedissionSerialize.serialize(session),globalSessionTimeout, TimeUnit.SECONDS); return sessionId; } /** * 读取Session * @param sessionId * @return */ @Override protected Session doReadSession(Serializable sessionId) { RBucket<String> sessionIdBucket = redissonClient.getBucket(SuperConstant.GROUP_CAS + sessionId.toString()); Session session = (Session) ShiroRedissionSerialize.deserialize(sessionIdBucket.get()); return session; } /** * 更新Session * @param session * @throws UnknownSessionException */ @Override public void update(Session session) throws UnknownSessionException { RBucket<String> sessionIdBucket = redissonClient.getBucket(SuperConstant.GROUP_CAS + session.getId().toString()); sessionIdBucket.set(ShiroRedissionSerialize.serialize(session),globalSessionTimeout,TimeUnit.SECONDS); log.info("修改为SessionId:{}",session.getId().toString()); } /** * 清除Session * @param session */ @Override public void delete(Session session) { RBucket<String> sessionIdBucket = redissonClient.getBucket(SuperConstant.GROUP_CAS + session.getId().toString()); sessionIdBucket.delete(); log.info("Session:{}被清除了",session); } @Override public Collection<Session> getActiveSessions() { return Collections.EMPTY_SET; } public RedisSessionDao(Long globalSessionTimeout) { this.globalSessionTimeout = globalSessionTimeout; } } src/main/java/com/whyc/config/ShiroConfig.java
@@ -3,17 +3,29 @@ import com.whyc.filter.KickedOutFilter; import com.whyc.filter.RolesOrAuthorizationFilter; import com.whyc.properties.PropertiesUtil; import com.whyc.properties.RedisProperties; import com.whyc.properties.ShiroRedisProperties; import com.whyc.realm.CustomRealm; import lombok.extern.log4j.Log4j; import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.SimpleCookie; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; @@ -27,17 +39,79 @@ * 暂时提供权限管理,会话管理后续更新 TODO */ @Configuration //@Log4j2 @Slf4j @EnableConfigurationProperties({RedisProperties.class}) public class ShiroConfig { @Autowired CustomRealm customRealm; @Autowired RedisProperties redisProperties; /*================Session采用Redis分布式Session===================*/ /** * Redisson客户端,初始化 *//* @Bean(name = "redissonClient4Shiro") public RedissonClient redissonClient(){ log.info("======初始化redissonClient4Shiro======"); String[] nodeList = shiroRedisProperties.getNodes().split(","); Config config = new Config(); if(nodeList.length==1){ config.useSingleServer().setAddress(nodeList[0]) .setConnectTimeout(shiroRedisProperties.getConnectTimeout()) .setConnectionPoolSize(shiroRedisProperties.getConnectPoolSize()) .setConnectionMinimumIdleSize(shiroRedisProperties.getConnectMinIdleSize()) .setTimeout(shiroRedisProperties.getTimeout()); }else{ config.useClusterServers().addNodeAddress(nodeList) .setConnectTimeout(shiroRedisProperties.getConnectTimeout()) .setMasterConnectionPoolSize(shiroRedisProperties.getConnectPoolSize()) .setMasterConnectionMinimumIdleSize(shiroRedisProperties.getConnectMinIdleSize()) .setTimeout(shiroRedisProperties.getTimeout()); } RedissonClient redissonClient = Redisson.create(config); return redissonClient; }*/ /** * 初始化RedisSessionDao */ @Bean("redisSessionDao") @DependsOn("redisClient") public SessionDAO redisSessionDao(){ RedisSessionDao redisSessionDao = new RedisSessionDao(redisProperties.getGlobalSessionTimeout()); return redisSessionDao; } /**Session管理器*/ @Bean("sessionManager") @DependsOn("redisSessionDao") public DefaultWebSessionManager shiroSessionManager(){ DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); //设置Session参数 sessionManager.setSessionDAO(redisSessionDao()); sessionManager.setSessionValidationSchedulerEnabled(false); sessionManager.setSessionIdCookieEnabled(true); SimpleCookie simpleCookie = new SimpleCookie("ShiroSession"); sessionManager.setSessionIdCookie(simpleCookie); sessionManager.setGlobalSessionTimeout(redisProperties.getGlobalSessionTimeout()); return sessionManager; } /*====================权限管理=======================*/ /**权限管理器*/ @Bean(name = "securityManager") @DependsOn("sessionManager") public DefaultWebSecurityManager defaultWebSecurityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(customRealm); securityManager.setSessionManager(shiroSessionManager()); return securityManager; } src/main/java/com/whyc/constant/SuperConstant.java
@@ -6,12 +6,20 @@ public class SuperConstant { /**算法名*/ public static String HASH_ALGORITHM = "SHA-1"; public final static String HASH_ALGORITHM = "SHA-1"; /**hash计算次数*/ public static int HASH_INTERATIONS = 112; public final static int HASH_INTERATIONS = 112; public static String SALT ="Yin"; public final static String SALT ="Yin"; /**缓存键值常量*/ public final static String GROUP_CAS ="group_shiro:"; public final static String ROLE_KEY =GROUP_CAS+"role_key:"; public final static String RESOURCE_KEY =GROUP_CAS+"resource_key:"; public final static String RESOURCE_KEY_IDS =GROUP_CAS+"resource_key_ids:"; public final static String FIND_USER_BY_LOGIN_NAME =GROUP_CAS+"findUserByLoginName"; src/main/java/com/whyc/filter/KickedOutFilter.java
@@ -2,7 +2,10 @@ import com.whyc.pojo.User; import com.whyc.util.ShiroUtil; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import javax.annotation.Resource; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; @@ -15,6 +18,9 @@ @WebFilter(urlPatterns = "/*",filterName = "kickedOutFilter") public class KickedOutFilter implements Filter { @Autowired RedissonClient redissonClient; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession(); @@ -23,7 +29,7 @@ User user = ShiroUtil.getUser(); if (user.getId() != 0) { System.out.println("Filter过滤器中获取到的当前Session的SessionId为:" + session.getId()); if (!request.getServletContext().getAttribute(user.getName()).equals(session.getId())) { if (!redissonClient.getBucket(user.getName()).get().equals(session.getId())) { //如果当前Session所对应的SessionId与全局中用户对应的SessionId不一致,则清除当前Session session.invalidate(); response.setContentType("text/html;charset=utf-8"); src/main/java/com/whyc/pojo/User.java
@@ -1,15 +1,14 @@ package com.whyc.pojo; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.*; import org.apache.ibatis.type.Alias; import java.io.Serializable; import java.util.Date; @Alias("User") @TableName( schema = "`db_3.5mw_web`",value = "tb_user") public class User { public class User implements Serializable { private Integer id; private String name; private String password; src/main/java/com/whyc/properties/RedisClusterProperties.java
New file @@ -0,0 +1,83 @@ package com.whyc.properties; public class RedisClusterProperties { private Integer scanInterval; private String nodes; private String readMode; private Integer retryAttempts; private Integer failedAttempts; private Integer slaveConnectionPoolSize; private Integer masterConnectionPoolSize; private Integer retryInterval; public Integer getScanInterval() { return scanInterval; } public void setScanInterval(Integer scanInterval) { this.scanInterval = scanInterval; } public String getNodes() { return nodes; } public void setNodes(String nodes) { this.nodes = nodes; } public String getReadMode() { return readMode; } public void setReadMode(String readMode) { this.readMode = readMode; } public Integer getRetryAttempts() { return retryAttempts; } public void setRetryAttempts(Integer retryAttempts) { this.retryAttempts = retryAttempts; } public Integer getFailedAttempts() { return failedAttempts; } public void setFailedAttempts(Integer failedAttempts) { this.failedAttempts = failedAttempts; } public Integer getSlaveConnectionPoolSize() { return slaveConnectionPoolSize; } public void setSlaveConnectionPoolSize(Integer slaveConnectionPoolSize) { this.slaveConnectionPoolSize = slaveConnectionPoolSize; } public Integer getMasterConnectionPoolSize() { return masterConnectionPoolSize; } public void setMasterConnectionPoolSize(Integer masterConnectionPoolSize) { this.masterConnectionPoolSize = masterConnectionPoolSize; } public Integer getRetryInterval() { return retryInterval; } public void setRetryInterval(Integer retryInterval) { this.retryInterval = retryInterval; } } src/main/java/com/whyc/properties/RedisPoolProperties.java
New file @@ -0,0 +1,69 @@ package com.whyc.properties; public class RedisPoolProperties { private Integer size; private Integer maxIdle; private Integer minIdle; private Integer maxActive; private Integer maxWait; private Integer connTimeout; private Integer soTimeout; public Integer getSize() { return size; } public void setSize(Integer size) { this.size = size; } public Integer getMaxIdle() { return maxIdle; } public void setMaxIdle(Integer maxIdle) { this.maxIdle = maxIdle; } public Integer getMinIdle() { return minIdle; } public void setMinIdle(Integer minIdle) { this.minIdle = minIdle; } public Integer getMaxActive() { return maxActive; } public void setMaxActive(Integer maxActive) { this.maxActive = maxActive; } public Integer getMaxWait() { return maxWait; } public void setMaxWait(Integer maxWait) { this.maxWait = maxWait; } public Integer getConnTimeout() { return connTimeout; } public void setConnTimeout(Integer connTimeout) { this.connTimeout = connTimeout; } public Integer getSoTimeout() { return soTimeout; } public void setSoTimeout(Integer soTimeout) { this.soTimeout = soTimeout; } } src/main/java/com/whyc/properties/RedisProperties.java
New file @@ -0,0 +1,87 @@ package com.whyc.properties; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "redis",ignoreUnknownFields = true) public class RedisProperties { private String mode; private Integer timeout; private Long globalSessionTimeout; private String password; private RedisPoolProperties pool; private RedisSingleProperties single; private RedisSentinelProperties sentinel; private RedisClusterProperties cluster; public String getMode() { return mode; } public void setMode(String mode) { this.mode = mode; } public Integer getTimeout() { return timeout; } public void setTimeout(Integer timeout) { this.timeout = timeout; } public Long getGlobalSessionTimeout() { return globalSessionTimeout; } public void setGlobalSessionTimeout(Long globalSessionTimeout) { this.globalSessionTimeout = globalSessionTimeout; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public RedisPoolProperties getPool() { return pool; } public void setPool(RedisPoolProperties pool) { this.pool = pool; } public RedisSingleProperties getSingle() { return single; } public void setSingle(RedisSingleProperties single) { this.single = single; } public RedisSentinelProperties getSentinel() { return sentinel; } public void setSentinel(RedisSentinelProperties sentinel) { this.sentinel = sentinel; } public RedisClusterProperties getCluster() { return cluster; } public void setCluster(RedisClusterProperties cluster) { this.cluster = cluster; } } src/main/java/com/whyc/properties/RedisSentinelProperties.java
New file @@ -0,0 +1,43 @@ package com.whyc.properties; public class RedisSentinelProperties { private String master; private String nodes; private String masterOnlyWrite; private Integer failMax; public String getMaster() { return master; } public void setMaster(String master) { this.master = master; } public String getNodes() { return nodes; } public void setNodes(String nodes) { this.nodes = nodes; } public String getMasterOnlyWrite() { return masterOnlyWrite; } public void setMasterOnlyWrite(String masterOnlyWrite) { this.masterOnlyWrite = masterOnlyWrite; } public Integer getFailMax() { return failMax; } public void setFailMax(Integer failMax) { this.failMax = failMax; } } src/main/java/com/whyc/properties/RedisSingleProperties.java
New file @@ -0,0 +1,13 @@ package com.whyc.properties; public class RedisSingleProperties { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } src/main/java/com/whyc/properties/ShiroRedisProperties.java
New file @@ -0,0 +1,79 @@ package com.whyc.properties; import org.springframework.boot.context.properties.ConfigurationProperties; import java.io.Serializable; /** * 属性类 */ @ConfigurationProperties(prefix = "redis") public class ShiroRedisProperties implements Serializable { /**redis连接地址*/ private String nodes; /**连接超时时间*/ private int connectTimeout; /**连接池大小*/ private int connectPoolSize; /**最小空闲连接数*/ private int connectMinIdleSize; /**数据返回超时时间*/ private int timeout; /**全局超时时间*/ private long globalSessionTimeout; public String getNodes() { return nodes; } public void setNodes(String nodes) { this.nodes = nodes; } public int getConnectTimeout() { return connectTimeout; } public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } public int getConnectPoolSize() { return connectPoolSize; } public void setConnectPoolSize(int connectPoolSize) { this.connectPoolSize = connectPoolSize; } public int getConnectMinIdleSize() { return connectMinIdleSize; } public void setConnectMinIdleSize(int connectMinIdleSize) { this.connectMinIdleSize = connectMinIdleSize; } public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } public long getGlobalSessionTimeout() { return globalSessionTimeout; } public void setGlobalSessionTimeout(long globalSessionTimeout) { this.globalSessionTimeout = globalSessionTimeout; } } src/main/java/com/whyc/service/LoginService.java
@@ -5,13 +5,22 @@ import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.redisson.api.RBucket; import org.redisson.api.RList; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @Service public class LoginService { @Autowired RedissonClient redissonClient; public Response login(String userName, String password, HttpServletRequest request) { UsernamePasswordToken userToken = new UsernamePasswordToken(userName, password); @@ -22,10 +31,13 @@ return new Response<>().set(1,false); } if (subject.isAuthenticated()){ //每个登录的用户都有一个全局变量,里面存着对应的SessionId; //每个登录的用户都有一个全局变量,里面存着对应的SessionId;redis存储,分布式,否则会报错 //同一个账号,后面登录的,会挤掉之前登录的SessionId System.out.println("全局存储中当前SessionId为:"+request.getSession().getId()); request.getServletContext().setAttribute(userName,request.getSession().getId()); //System.out.println("全局存储中当前SessionId为:"+request.getSession().getId()); //request.getServletContext().setAttribute(userName,request.getSession().getId()); RBucket<String> bucket = redissonClient.getBucket(userName); bucket.set(request.getSession().getId()); return new Response<>().set(1,true); } return new Response<>().set(1,false); src/main/java/com/whyc/util/EmptyUtil.java
New file @@ -0,0 +1,148 @@ package com.whyc.util; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; /** * @Description 判断对象是否为空的工具类 */ public abstract class EmptyUtil { /** * * @方法名:对于String类型的非空判断 * @功能说明:对于String类型的非空判断 * @author 束文奇 * @date Mar 28, 2013 9:26:09 AM * @param str * @return boolean true-为空,false-不为空 */ public static boolean isNullOrEmpty(String str) { if (str == null || "".equals(str.trim()) || "null".equalsIgnoreCase(str.trim()) || "undefined".equalsIgnoreCase(str.trim())) { return true; } else { return false; } } /** * * @方法名:对于StringBuffer类型的非空判断 * @功能说明:对于StringBuffer类型的非空判断 * @author 束文奇 * @date Mar 28, 2013 9:26:09 AM * @param str * @return boolean true-为空,false-不为空 */ public static boolean isNullOrEmpty(StringBuffer str) { return (str == null || str.length() == 0); } /** * * @方法名:对于string数组类型的非空判断 * @功能说明:对于string数组类型的非空判断 * @author 束文奇 * @date Mar 28, 2013 9:26:09 AM * @param str * @return boolean true-为空,false-不为空 */ public static boolean isNullOrEmpty(String[] str) { if (str == null || str.length == 0) { return true; } else { return false; } } /** * * @方法名:对于Object类型的非空判断 * @功能说明:对于Object类型的非空判断 * @author 束文奇 * @date Mar 28, 2013 9:26:09 AM * @param obj * @return boolean true-为空,false-不为空 */ public static boolean isNullOrEmpty(Object obj) { if (obj == null || "".equals(obj)) { return true; } else { return false; } } /** * * @方法名:对于Object数组类型的非空判断 * @功能说明:对于Object数组类型的非空判断 * @author 束文奇 * @date Mar 28, 2013 9:26:09 AM * @param obj * @return boolean true-为空,false-不为空 */ public static boolean isNullOrEmpty(Object[] obj) { if (obj == null || obj.length == 0) { return true; } else { return false; } } /** * * @方法名:对于Collection类型的非空判断 * @功能说明:对于Collection类型的非空判断 * @author 束文奇 * @date Mar 28, 2013 9:26:09 AM * @param str * @return boolean true-为空,false-不为空 */ @SuppressWarnings("rawtypes") public static boolean isNullOrEmpty(Collection collection) { if (collection == null || collection.isEmpty()) { return true; } else { return false; } } /** * @方法名:对于Map类型的非空判断 * @功能说明:对于Map类型的非空判断 * @author 束文奇 *@param map *@return 传人参数 * @throws */ @SuppressWarnings("rawtypes") public static boolean isNullOrEmpty( Map map) { if (map == null || map.isEmpty()) { return true; } else { return false; } } /** * * @方法名:removeNullUnit * @功能说明: 删除集合中的空元素 * @author 束文奇 * @date 2014-6-16 上午8:50:14 * @param xllxList * @return */ public static <T> List<T> removeNullUnit(List<T> xllxList) { List<T> need = new ArrayList<T>(); for (int i = 0; i < xllxList.size(); i++) { if (!isNullOrEmpty(xllxList.get(i))) { need.add(xllxList.get(i)); } } return need; } } src/main/java/com/whyc/util/ShiroRedissionSerialize.java
New file @@ -0,0 +1,78 @@ package com.whyc.util; import com.alibaba.druid.util.StringUtils; import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j; import java.io.*; /** * @Description:自定义序列化工具 */ @Slf4j public class ShiroRedissionSerialize { //序列化方法 public static String serialize(Object object){ //判断对象是否为空 if (EmptyUtil.isNullOrEmpty(object)){ return null; } //流的操作 ByteArrayOutputStream bos = null; ObjectOutputStream oos =null; String encodeBase64 = null; bos = new ByteArrayOutputStream(); try { oos = new ObjectOutputStream(bos); oos.writeObject(object); //转换字符串 encodeBase64 = EncodesUtil.encodeBase64(bos.toByteArray()); } catch (IOException e) { e.printStackTrace(); log.error("流写入异常:{}",e); }finally { //关闭流 try { bos.close(); oos.close(); } catch (IOException e) { e.printStackTrace(); log.error("流写入异常:{}",e); } } return encodeBase64; } //反序列化方法 public static Object deserialize(String str){ //判断是否为空 if (EmptyUtil.isNullOrEmpty(str)){ return null; } //流从操作 ByteArrayInputStream bis =null; ObjectInputStream ois = null; Object object = null; //转换对象 bis = new ByteArrayInputStream(EncodesUtil.decodeBase64(str)); try { ois = new ObjectInputStream(bis); object = ois.readObject(); } catch (Exception e) { e.printStackTrace(); log.error("流读取异常:{}",e); }finally { //关闭流 try { bis.close(); ois.close(); } catch (IOException e) { e.printStackTrace(); log.error("流读取异常:{}",e); } } return object; } } src/main/resources/config/application.yml
@@ -59,3 +59,38 @@ knife: enable: true # enable: fase redis: #模式 single/sentinel/cluster model: single timeout: 3000 global-session-timeout: 360000 password: #连接池配置 pool: size: 10 max-idle: 16 min-idle: 8 max-active: 8 max-wait: 3000 conn-timeout: 3000 so-timeout: 3000 #单机配置 single: address: redis://localhost:6379 #哨兵配置 sentinel: master: business-master nodes: redis://localhost:6379,redis://localhost:6380 master-onlyWrite: true fail-max: 3 #集群配置 cluster: scan-interval: 1000 nodes: redis://localhost:6379 read-mode: SLAVE retry-attempts: 3 failed-attempts: 3 slave-connection-pool-size: 64 master-connection-pool-size: 64 retry-interval: 1500 src/main/resources/config/authentication.properties
@@ -1,5 +1,5 @@ #dev接口调试时使用 /**=anon #/**=anon #静态资源不拦截 /static/**=anon @@ -19,9 +19,9 @@ #/resource/**=roles-or[dev,SuperAdmin] #设置需要permission的拦截 /WaterComm/**=perms["water:all"] #/WaterComm/**=perms["water:all"] #设置RolesOr拦截 #/WaterComm/**=rolesOr["admin","dev"] #其他链接是需要登录的 #/**=authc /**=authc