diff --git a/README.md b/README.md
index 285b1f8..905c149 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,12 @@
* 是博客 springboot集成shiro 实现权限控制 地址:http://blog.csdn.net/u012373815/article/details/57532292
+##springboot-shior2
+
+是使用shior 框架调取用户权限服务,进行登录权限验证的例子,其中的用户权限服务没有写,都是用TODO 标示出来了,使用时可以根据各自的用户权限服务进行编码替换
+
+springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。
+
## springboot-swagger-ui
* 博客 spring boot +Swagger-ui 自动生成API文档 地址: https://blog.csdn.net/u012373815/article/details/82685962
@@ -72,5 +78,11 @@
## Springboot多数据源切换
* springboot 多个数据源的配置, 一个springboot 项目操作多个数据库的数据:https://abelyang.blog.csdn.net/article/details/89296341
+##springboot-dubbo
+
+该项目是Springboot 和 dubbo 结合的例子,是provider 的示例,提供服务。简单的写了一些用户和权限的接口没有写的很完整,主要是为了提现dubbo 服务
+Springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。
+
+
##未完待续。。。
diff --git a/springboot-dubbo/README.md b/springboot-dubbo/README.md
new file mode 100644
index 0000000..16441b5
--- /dev/null
+++ b/springboot-dubbo/README.md
@@ -0,0 +1,10 @@
+##springboot-dubbo
+
+该项目是Springboot 和 dubbo 结合的例子,是provider 的示例,提供服务。简单的写了一些用户和权限的接口没有写的很完整,主要是为了提现dubbo 服务
+Springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。
+
+### abel-user-api
+该模块是让消费者 引用的 api 模块,主要用来定义接口和数据传输实体
+
+### abel-user-provider
+该模块是真正的微服务提供者
diff --git a/springboot-shiro2/README.md b/springboot-shiro2/README.md
new file mode 100644
index 0000000..8fe9437
--- /dev/null
+++ b/springboot-shiro2/README.md
@@ -0,0 +1,6 @@
+##springboot-shior2
+
+是使用shior 框架调取用户权限服务,进行登录权限验证的例子,其中的用户权限服务没有写,都是用TODO 标示出来了,使用时可以根据各自的用户权限服务进行编码替换
+
+springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。
+引入了 abel-user-api 模块
\ No newline at end of file
diff --git a/springboot-shiro2/pom.xml b/springboot-shiro2/pom.xml
new file mode 100644
index 0000000..8a3a9eb
--- /dev/null
+++ b/springboot-shiro2/pom.xml
@@ -0,0 +1,142 @@
+
+
+ 4.0.0
+
+ cn.abel
+ abel-parent
+ 1.0.0-SNAPSHOT
+
+
+ cn.abel
+ springboot-shior2
+ 1.0.0
+ jar
+ Spring Boot
+
+
+
+ cn.abel
+ abel-util
+ 1.0.0-SNAPSHOT
+
+
+
+ cn.abel
+ abel-user-api
+ 1.0.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-quartz
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ org.springframework.boot
+ spring-boot-starter-freemarker
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+ org.apache.commons
+ commons-collections4
+
+
+
+ com.alibaba
+ fastjson
+
+
+
+ com.alibaba
+ dubbo
+
+
+ org.slf4j
+ log4j-over-slf4j
+
+
+ org.apache.zookeeper
+ zookeeper
+
+
+
+
+ org.apache.shiro
+ shiro-spring
+
+
+ org.apache.shiro
+ shiro-ehcache
+
+
+ org.apache.shiro
+ shiro-quartz
+
+
+ org.apache.shiro
+ shiro-ehcache
+
+
+ net.mingsoft
+ shiro-freemarker-tags
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+ 2.9.9.1
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/ShiroRestApplication.java b/springboot-shiro2/src/main/java/cn/abel/rest/ShiroRestApplication.java
new file mode 100644
index 0000000..0f1102c
--- /dev/null
+++ b/springboot-shiro2/src/main/java/cn/abel/rest/ShiroRestApplication.java
@@ -0,0 +1,19 @@
+package cn.abel.rest;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.annotation.ImportResource;
+
+/**
+ * 无数据库运行
+ *
+ */
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
+@ImportResource("classpath*:META-INF/spring/*.xml")
+public class ShiroRestApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ShiroRestApplication.class, args);
+ }
+}
diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/config/RedisConfig.java b/springboot-shiro2/src/main/java/cn/abel/rest/config/RedisConfig.java
new file mode 100644
index 0000000..821e775
--- /dev/null
+++ b/springboot-shiro2/src/main/java/cn/abel/rest/config/RedisConfig.java
@@ -0,0 +1,199 @@
+package cn.abel.rest.config;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+import cn.abel.rest.constants.Constants;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.cache.RedisCacheWriter;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.RedisPassword;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * redis缓存配置
+ *
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport {
+
+ /** logger */
+ private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
+ /**
+ * serializer
+ */
+ private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer();
+
+ @Value("${spring.redis.database}")
+ private Integer database;
+ @Value("${spring.redis.host}")
+ private String host;
+ @Value("${spring.redis.port}")
+ private Integer port;
+ @Value("${spring.redis.password}")
+ private String password;
+ @Value("${spring.redis.lettuce.pool.max-active}")
+ private Integer maxActive;
+ @Value("${spring.redis.lettuce.pool.max-wait}")
+ private Integer maxWait;
+ @Value("${spring.redis.lettuce.pool.max-idle}")
+ private Integer maxIdle;
+ @Value("${spring.redis.lettuce.pool.min-idle}")
+ private Integer minIdle;
+ @Value("${spring.redis.lettuce.shutdown-timeout}")
+ private Integer timeout;
+
+ /**
+ * 在使用@Cacheable时,如果不指定key,则使用这个默认的key生成器生成的key
+ *
+ * @return
+ */
+ @Override
+ @Bean
+ public KeyGenerator keyGenerator() {
+ return (target, method, params) -> {
+ StringBuilder sb = new StringBuilder();
+ sb.append(target.getClass().getName());
+ sb.append(method.getName());
+ for (Object obj : params) {
+ sb.append(obj.toString());
+ }
+ return sb.toString();
+ };
+ }
+
+ /**
+ * 声明缓存管理器
+ */
+ @Override
+ @Bean
+ public CacheManager cacheManager() {
+ //1. entryTtl: 定义默认的cache time-to-live.
+ //2. disableCachingNullValues: 禁止缓存Null对象. 视需求而定.
+ //3. computePrefixWith: 此处定义了cache key的前缀, 避免公司不同项目之间的key名称冲突.
+ //4. serializeKeysWith, serializeValuesWith: 定义key和value的序列化协议, 同时的hash key和hash value也被定义.
+
+ // 缓存配置
+ RedisCacheConfiguration cacheConfiguration =
+ RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues().computePrefixWith(cacheName -> Constants.REDIS_KEY_PRE.concat(":").concat(cacheName).concat(":")).entryTtl(Duration.ofDays(Constants.REDIS_TIMEOUT));
+
+ Map redisCacheConfigurationMap = new HashMap<>(2);
+ //redisCacheConfigurationMap.put(Constants.CACHE_NAME_PERMISSION, permissionCacheConfiguration);
+
+ //初始化一个RedisCacheWriter
+ RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory());
+
+ RedisSerializationContext.SerializationPair valuePair =
+ RedisSerializationContext.SerializationPair.fromSerializer(STRING_SERIALIZER);
+ //RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer(new ObjectMapper()));
+ RedisCacheConfiguration defaultCacheConfig =
+ RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(valuePair);
+ //设置默认过期时间是1天
+ defaultCacheConfig.entryTtl(Duration.ofDays(Constants.REDIS_TIMEOUT));
+
+ //初始化RedisCacheManager
+ RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig,
+ redisCacheConfigurationMap);
+ cacheManager.afterPropertiesSet();
+ logger.info("RedisCacheManager config success");
+
+ return cacheManager;
+ }
+
+ @Bean(name = "redisTemplate")
+ @Primary
+ public RedisTemplate redisTemplate() {
+ return getTemplate(redisConnectionFactory());
+ }
+
+ @Bean(name = "stringRedisTemplate")
+ public StringRedisTemplate stringRedisTemplate() {
+ return new StringRedisTemplate(redisConnectionFactory());
+ }
+
+ private RedisConnectionFactory redisConnectionFactory() {
+ return connectionFactory(maxActive, maxIdle, minIdle, maxWait, host, password, timeout, port, database);
+ }
+
+ private RedisConnectionFactory connectionFactory(Integer maxActive,
+ Integer maxIdle,
+ Integer minIdle,
+ Integer maxWait,
+ String host,
+ String password,
+ Integer timeout,
+ Integer port,
+ Integer database) {
+ RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
+ redisStandaloneConfiguration.setHostName(host);
+ redisStandaloneConfiguration.setPort(port);
+ redisStandaloneConfiguration.setDatabase(database);
+ redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
+
+ GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
+ poolConfig.setMaxTotal(maxActive);
+ poolConfig.setMaxIdle(maxIdle);
+ poolConfig.setMinIdle(minIdle);
+ poolConfig.setMaxWaitMillis(maxWait);
+ LettuceClientConfiguration lettucePoolingConfig = LettucePoolingClientConfiguration.builder()
+ //.commandTimeout(Duration.ofSeconds(15))
+ .poolConfig(poolConfig).shutdownTimeout(Duration.ofMillis(timeout)).build();
+ LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration,
+ lettucePoolingConfig);
+ connectionFactory.afterPropertiesSet();
+
+ return connectionFactory;
+ }
+
+ private RedisTemplate getTemplate(RedisConnectionFactory factory) {
+ RedisTemplate template = new RedisTemplate();
+ template.setConnectionFactory(factory);
+ template.setKeySerializer(STRING_SERIALIZER);
+ template.setValueSerializer(jackson2JsonRedisSerializer());
+ //不能用stringSerializer,有地方使用ShiroUser做key,不能转换
+ //template.setHashKeySerializer(STRING_SERIALIZER);
+ //template.setHashKeySerializer(jackson2JsonRedisSerializer());
+
+ template.afterPropertiesSet();
+
+ return template;
+ }
+
+ private RedisSerializer