1.引入pom.xml jwt security 可以不引入
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- Web场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis 启动器 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.1</version>
</dependency>
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--jwt-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<!-- 开发者工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- SpringBoot 的测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<!-- 2.0以上版本默认连接池是lettuce 而1.5的版本默认采用的连接池技术是jedis, 如果是jedis可以排除lettuce -->
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<!--<exclusion>-->
<!--<groupId>io.lettuce</groupId>-->
<!--<artifactId>lettuce-core</artifactId>-->
<!--</exclusion>-->
</exclusions>
</dependency>
<!-- jedis客户端 -->
<!--<dependency>-->
<!--<groupId>redis.clients</groupId>-->
<!--<artifactId>jedis</artifactId>-->
<!--<version>${jedis.version}</version>-->
<!--</dependency>-->
<!-- lettuce pool 缓存连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2.配置application.yml文件 该文件中只存放开发环境和正式环境公共的代码 根据不同环境创建读个yml文件 application-环境名.yml 然后通过spring:profiles:active:环境名 springboot 就会直接加载相应的yml文件
server: tomcat: uri-encoding: UTF-8 max-threads: 1000 min-spare-threads: 30 max-http-post-size: 1048576000 port: 8088 spring: profiles: active: local #MyBatis配置 mybatis: mapper-locations: classpath*:com/place/dao/**/*.xml,com/place/police/auth/**/*.xml #配置Mapper.xml文件所在路径 type-aliases-package: com.place.bean #配置别名
3.创建application-pro.yml 和application-local.yml文件 改文件中配置:datasource,redis,logging等
#日志文件 logging: path: D:/nmyslog/nmys file: hoteldata-rest.log level.root: info level.com.place: debug spring: ########-spring datasource-######## datasource: #账号配置 url: jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver #hikari数据库连接池 hikari: pool-name: Retail_HikariCP minimum-idle: 5 #最小空闲连接数量 idle-timeout: 180000 #空闲连接存活最大时间,默认600000(10分钟) maximum-pool-size: 10 #连接池最大连接数,默认是10 auto-commit: true #此属性控制从池返回的连接的默认自动提交行为,默认值:true max-lifetime: 1800000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟 connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000 connection-test-query: SELECT 1 redis: database: 0 # Redis数据库索引(默认为0) host: 127.0.0.1 # Redis服务器地址 port: 6379 # Redis服务器连接端口 默认6379 password: ww # Redis服务器连接密码(默认为空) # #在1.x.x的版本时默认使用的jedis客户端,现在是2.x.x版本默认使用的lettuce客户端 # # Jedis和Lettuce都是Redis Client # # Jedis 是直连模式,在多个线程间共享一个 Jedis 实例时是线程不安全的, # # 如果想要在多线程环境下使用 Jedis,需要使用连接池, # # 每个线程都去拿自己的 Jedis 实例,当连接数量增多时,物理连接成本就较高了。 # jedis: # shutdown-timeout: 300ms #关闭超时 # pool: # max-active: 60 #连接池最大连接数(使用负值表示没有限制)600 # max-wait: 1000 #连接池最大阻塞等待时间(使用负值表示没有限制) # max-idle: 30 #连接池中的最大空闲连接300 # min-idle: 0 #连接池中的最小空闲连接 # Lettuce的连接是基于Netty的,连接实例可以在多个线程间共享, # 所以,一个多线程的应用可以使用同一个连接实例,而不用担心并发线程的数量。 # 当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。 # 通过异步的方式可以让我们更好的利用系统资源,而不用浪费线程等待网络或磁盘I/O。 # Lettuce 是基于 netty 的,netty 是一个多线程、事件驱动的 I/O 框架, # 所以 Lettuce 可以帮助我们充分利用异步的优势 lettuce: shutdown-timeout: 300ms #关闭超时 pool: max-active: 60 #连接池最大连接数(使用负值表示没有限制)600 max-wait: 1000 #连接池最大阻塞等待时间(使用负值表示没有限制) max-idle: 30 #连接池中的最大空闲连接300 min-idle: 0 #连接池中的最小空闲连接 timeout: 60000 #连接超时时间(毫秒) jwt: header: Authorization secret: mySecret #token有效期一天 expiration: 86400 tokenHead: "Bearer "
4.配置redis.config
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import javax.annotation.Resource; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; /** * redis 配置 * @EnableCaching // 开启缓存支持 * @author*/ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { /** * Logger */ private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class); @Resource private LettuceConnectionFactory lettuceConnectionFactory; @Override @Bean public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuffer sb = new StringBuffer(); 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() { RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder .fromConnectionFactory(lettuceConnectionFactory); @SuppressWarnings("serial") Set<String> cacheNames = new HashSet<String>() { { add("codeNameCache"); } }; builder.initialCacheNames(cacheNames); return builder.build(); } /** * RedisTemplate配置 */ @Bean public RedisTemplate<String, Object> redisTemplate() { // 设置序列化 Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>( Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, Visibility.ANY); om.enableDefaultTyping(DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置redisTemplate RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); RedisSerializer<?> stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer);// key序列化 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// value序列化 redisTemplate.setHashKeySerializer(stringSerializer);// Hash key序列化 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);// Hash value序列化 redisTemplate.afterPropertiesSet(); return redisTemplate; } @Override @Bean public CacheErrorHandler errorHandler() { // 异常处理,当Redis发生异常时,打印日志,但是程序正常走 logger.info("初始化 -> [{}]", "Redis CacheErrorHandler"); CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() { @Override public void handleCacheGetError(RuntimeException e, Cache cache, Object key) { logger.error("Redis occur handleCacheGetError:key -> [{}]", key, e); } @Override public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) { logger.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e); } @Override public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) { logger.error("Redis occur handleCacheEvictError:key -> [{}]", key, e); } @Override public void handleCacheClearError(RuntimeException e, Cache cache) { logger.error("Redis occur handleCacheClearError:", e); } }; return cacheErrorHandler; } }
5.配置redis工具类
import com.place.util.JsonUtil; import com.place.util.StringUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; /** * redis 工具类 * ww */ @Component public class RedisStringTemlateUtils { @Autowired private StringRedisTemplate redisTemplate; /** * 设置key的过期时间,以秒为单位 * @param key * @param time * @return */ public boolean expired(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除keys对应的记录,可以是多个key * @param keys */ @SuppressWarnings("unchecked") public void del(String... keys) { if (keys != null && keys.length > 0) { if (keys.length == 1) { redisTemplate.delete(keys[0]); } else { redisTemplate.delete(CollectionUtils.arrayToList(keys)); } } } /** * 判断key是否存在 * @param key * @return */ public boolean exists(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { return false; } } // ============================String============================= /** * 根据key获取数据 * @param key 取值key map_key redis队列名 * @param t * @param <T> * @return */ public <T>T getStringbean(String key,Class<T> t){ String json = get(key); T t1 = null; try { t1 = t.newInstance(); if(!StringUtil.isEmpty(json)){ t1 = JsonUtil.jsonToBean(json, t); }else{ t1 = null; } } catch (InstantiationException | IllegalAccessException e) { t1 = null; } return t1; } /** * 根据key获取记录 * @param key * @return */ public String get(String key) { Object o = redisTemplate.opsForValue().get(key); return o!= null?o.toString():null; } /** * 添加记录,如果记录已存在将覆盖原有的value * @param key * @param value * @return */ public boolean set(String key, String value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * * @param key * 键 * @param value * 值 * @param time * 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key, String value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time,TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 递增 * * @param key 键 * @param delta 要增加几(大于0) * @return */ public long incr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } /** * 递减 * * @param key 键 * @param delta 要减少几(小于0) * @return */ public long decr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } // ================================Map================================= /** * 根据key获取数据 * @param key 取值key map_key redis队列名 * @return * @throws Exception */ public <T>T getMapbean(String key,String map_key,Class<T> t){ long i =hlen(map_key); String json = ""; T t1 = null; try { if(i > 0){ t1 = t.newInstance(); json = hget(map_key,key); if(!StringUtil.isEmpty(json)){ t1 = JsonUtil.jsonToBean(json, t); } else{ t1 = null; } } } catch (InstantiationException | IllegalAccessException e) { t1 = null; } return t1; } /** * 从hash中删除指定的存储 * @param key * @param fieid */ public void hdel(String key, String fieid) { redisTemplate.opsForHash().delete(key,fieid); } /** * HashGet * @param key 键 不能为null * @param item 项 不能为null * @return 值 */ public String hget(String key,String item){ Object o = redisTemplate.opsForHash().get(key, item); return o != null?o.toString():null; } /** * 获取hashKey对应的所有键值 * @param key 键 * @return 对应的多个键值 */ public Map<Object,Object> hgetAll(String key){ return redisTemplate.opsForHash().entries(key); } /** * HashSet * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */ public boolean hmset(String key, Map<String,String> map){ try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * HashSet 并设置时间 * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */ public boolean hmset(String key, Map<String,String> map, long time){ try { redisTemplate.opsForHash().putAll(key, map); if(time>0){ expired(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */ public boolean hset(String key,String item,String value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ public boolean hset(String key,String item,Object value,long time) { try { redisTemplate.opsForHash().put(key, item, value); if(time>0){ expired(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除hash表中的值 * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item){ redisTemplate.opsForHash().delete(key,item); } /** * 判断hash表中是否有该项的值 * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean getmapkey(String key, String item){ return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * @param key 键 * @param item 项 * @param by 要增加几(大于0) * @return */ public double hincr(String key, String item,double by){ return redisTemplate.opsForHash().increment(key, item, by); } /** * hash递减 * @param key 键 * @param item 项 * @param by 要减少记(小于0) * @return */ public double hdecr(String key, String item,double by){ return redisTemplate.opsForHash().increment(key, item,-by); } /** * 获取hash中存储的个数,类似Map中size方法 * @param key * @return long 存储的个数 * */ public long hlen(String key) { return redisTemplate.opsForHash().size(key); } //============================set============================= /** * 根据key获取Set中的所有值 * @param key 键 */ public Set<String> sGet(String key){ try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key,Object value){ try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, String...values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 将set数据放入缓存 * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key,long time,String...values) { try { Long count = redisTemplate.opsForSet().add(key, values); if(time>0) {expired(key, time);} return count; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * @param key 键 * @return */ public long sGetSetSize(String key){ try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 移除值为value的 * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object ...values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } //===============================list================================= /** * 获取list缓存的内容 * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */ public List<String> ltrim(String key, long start, long end){ try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取list缓存的长度 * @param key 键 * @return */ public long llen(String key){ try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ public String lindex(String key,long index){ try { Object o = redisTemplate.opsForList().index(key, index); return o != null?o.toString():null; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 向List尾部追加记录 * @param key 键 * @param value 值 * @return */ public boolean rpush(String key, String value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * l向List尾部追加记录 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean rpush(String key, String value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) {expired(key, time);} return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向List头部追加记录 * @param key 键 * @param value 值 * @return */ public boolean lpush(String key, String value) { try { redisTemplate.opsForList().leftPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * l向List头部追加记录 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lpush(String key, String value, long time) { try { redisTemplate.opsForList().leftPush(key, value); if (time > 0){ expired(key, time);} return true; } catch (Exception e) { e.printStackTrace(); return false; } } public String lpop(String key) { try { return redisTemplate.opsForList().leftPop(key); } catch (Exception e) { e.printStackTrace(); } return null; } public String rpop(String key) { try { return redisTemplate.opsForList().rightPop(key); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 将list放入缓存 * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, List<String> value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List<String> value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0){ expired(key, time);} return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean lUpdateIndex(String key, long index,String value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 移除N个值为value * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long lRemove(String key,long count,Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 取出并移除第一条数据 * @param list_key 取值key map_key redis队列名 * @return * @throws Exception */ public <T>T getListbean(String list_key,Class<T> t){ String json = ""; T t1 = null; try { t1 = t.newInstance(); if (exists(list_key)) { Long i =llen(list_key); if(i > 0){ json = lindex(list_key,0); if(!StringUtil.isEmpty(json)){ t1 = JsonUtil.jsonToBean(json, t); } else{ t1 = null; } }else{ t1=null; } }else{ t1=null; } } catch (Exception e) { t1 = null; } return t1; } /** * 获取指定范围的记录,可以做为分页使用 * @param key * @param start * @param end * @return List * */ public List<String> lrange(String key, long start, long end) { List<String> list = redisTemplate.opsForList().range(key, start, end); return list; } }
最后一步在启动类里面配置 包扫描的路径和mapper的路径
@SpringBootApplication(scanBasePackages = {"com.place"})//spring扫描包的路径 @MapperScan("com.place") //mapper的路径 @EnableCaching //开启缓存 public class PlacePoliceApplication { public static void main(String[] args) { SpringApplication.run(PlacePoliceApplication.class, args); } }
springboot2 集成web+mybatis+redis
原文:https://www.cnblogs.com/wangbodang/p/11197059.html