第一部分
创建项目地址:https://start.spring.io/
选择好需要的jar包开始创建工程,然后将工程放到开发目录,解压,使用开发工具导入。开发工具首先要配置好maven
导入工程之后直接启动会报错,原因是新创建的项目没有配置数据源 所以在项目启动的时候回去查找项目的数据源,但是发现找不到所以报错。
解决方法
配置属性: @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
这样就可以启动成功了!!!!!!
第二部分
使用Druid数据源#
Apache Druid(Incubating) - 面向列的分布式数据存储,非常适合为交互式应用程序提供动力
虽然HikariDataSource性能非常高,但是阿里的druid数据源配有成套的数据源管理软件,开发中使用的更多。
以往我们都是直接引入Druid的依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
但是面对这么火爆的springboot并没有直接对Druid的启动器而是需要我们自己整合,apache中4个月前已经出了一套完美支持springboot的方案所以说我们不使用上面的依赖而是使用:
源码下载:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
配置properties文件,具体的参数配置可以去官网看看,这里只是简单的配置:
###本地地址
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/accumulatepoints?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&useInformationSchema=true
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
server.port=8080
#使用druid数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#如果template没有文件控制台会有一条警告信息,加上这个配置便不会看到警告信息
spring.thymeleaf.check-template-location=false
#这个配置可让外部直接访问static里面的文件
spring.mvc.static-path-pattern=/static/**
虽然我们配置了druid连接池的其它属性,但是不会生效。因为默认是使用的java.sql.Datasource的类来获取属性的,有些属性datasource没有。如果我们想让配置生效,需要手动创建Druid的配置文件。
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DruidDataSource druidDataSource(){
return new DruidDataSource();
}
Druid的最强大之处在于它有着强大的监控,可以监控我们发送到数据库的所有sql语句。方便我们后期排插错误。
我们接着在DruidDataSource里面配置监控中心:
/**
* 配置druid数据源
*/
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
/**
* 配置监控服务器
* @return 返回监控注册的servlet对象
* @author liwenfei
*/
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
// 添加IP白名单
initParams.put("allow","");//默认就是允许所有访问
// 添加IP黑名单,当白名单和黑名单重复时,黑名单优先级更高
//initParams.put("deny","127.0.0.0");
// 是否能够重置数据
//initParams.put("resetEnable","false");
// 添加控制台管理用户
// initParams.put("loginUsername","admin");
// initParams.put("loginPassword","123456");
bean.setInitParameters(initParams);
return bean;
}
/**
* 配置服务过滤器
* @return 返回过滤器配置对象
* @author liwenfei
*/
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
bean.addUrlPatterns("/*"); // 添加过滤规则
bean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,*.txt,/druid/*"); // 忽略过滤格式
bean.addInitParameter("profileEnable", "true");
bean.addInitParameter("principalCookieName","USER_COOKIE");
bean.addInitParameter("principalSessionName","USER_SESSION");
bean.addInitParameter("DruidWebStatFilter","/*");
return bean;
}
}
/**
* 注:如果这里配置druid数据源,那么启动类可以不用配置exclude = DataSourceAutoConfiguration.class
*
*/
注:配置spring拦截器详见
https://blog.youkuaiyun.com/qq_35071164/article/details/89738355
第三部分
引入thymeleaf依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在thymeleaf3.0以前对页面标签语法要求比较严格,开始标签必须有对应的结束标签。
如果希望页面语法不严谨,但是也能够运行成功,可以把thymeleaf升级为3.0或以上版本。
<!-- 修改参数 -->
<properties>
<!-- 修改JDK的编译版本为1.8 -->
<java.version>1.8</java.version>
<!-- 修改thymeleaf的版本 -->
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
</properties>
不过对于严谨的我来说就懒得升级了,反正升级之后我也是习惯使用开始标签和结束标签
第四部分
整合mybatis
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis‐spring‐boot‐starter</artifactId>
<version>2.0.1</version>
</dependency>
配置扫描,使用MapperScan批量扫描所有的Mapper接口;
@MapperScan(value = "com.chaomeng.chaomengwenyu.accumulatepoints.mapper")
@MapperScan(value = "com.chaomeng.chaomengwenyu.accumulatepoints.mapper")
@SpringBootApplication
public class AccumulatepointsApplication {
private static Logger logger = LoggerFactory.getLogger(AccumulatepointsApplication.class);
public static void main(String[] args) {
SpringApplication.run(AccumulatepointsApplication.class, args);
logger.info("启动成功");
}
}
在application.properties文件设置扫描javabean和xml配置
#mybatis
mybatis.type-aliases-package=com.chaomeng.chaomengwenyu.accumulatepoints.entity
mybatis.mapper-locations=classpath:mapper/*.xml
第五部分
连接数据注意事项
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/accumulatepoints?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&useInformationSchema=true
spring.datasource.username=root
spring.datasource.password=root
配置驼峰命名规则
#开启驼峰命名转换
mybatis.configuration.map-underscore-to-camel-case=true
当使用Spring Boot 2.0 整合MySQL的时候配置可能会出现这个故障:
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
故障分析:
其实这个问题是由于MySQL 这个jar 包依赖类型默认是runtime , 即只有运行时生效。
网上资料说:虽然这里报错,但是不影响你代码运行。 (实际上在我的项目中出错了)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
解决方案:
将runtime 修改为Compile 即可
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>Compile</scope>
</dependency>
第六部分
shiro配置
首先导入shiro与spring整合依赖
<!-- shiro与spring整合依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
自定义Realm类
/**
* 自定义 Realm
* @author liwenfei
*/
public class UserRealm extends AuthorizingRealm {
/**
* 执行授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
/**
* 执行认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
return null;
}
}
编写shiro配置类
/**
* Shiro的配置类
* @author liwenfei
*/
@Configuration
public class ShiroConfig {
/**
* 创建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
/**
* 默认的登陆访问url
*/
shiroFilterFactoryBean.setLoginUrl("/login");
/**
* 登陆成功后跳转的url
*/
shiroFilterFactoryBean.setSuccessUrl("/index");
/**
* 没有权限跳转的url
*/
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
/**
* Shiro内置过滤器,可以实现权限相关的拦截器
* 常用的过滤器:
* anon: 无需认证(登录)可以访问
* authc: 必须认证才可以访问
* user: 如果使用rememberMe的功能可以直接访问
* perms: 该资源必须得到资源权限才可以访问
* role: 该资源必须得到角色权限才可以访问
*/
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/docs/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/upload/**", "anon");
filterChainDefinitionMap.put("/files/**", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/", "anon");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 创建DefaultWebSecurityManager
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(userRealm);
return securityManager;
}
/**
* 创建Realm
*/
@Bean(name="userRealm")
public UserRealm getRealm(){
return new UserRealm();
}
}
完成shiro的认证逻辑
/**
* 执行认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
Map<String, Object> params = new HashMap<>();
params.put("username", username);
String password = new String((char[]) token.getCredentials());
// 查询用户信息
SysUser sysUser = sysUserMapper.selectSysUserByMap(params);
// 账号不存在
if(sysUser == null){
throw new UnknownAccountException("账号或密码不正确");
}
// 密码错误
if(!password.equals(sysUser.getPassword())){
throw new IncorrectCredentialsException("账号或密码不正确");
}
// 账号锁定
if (sysUser.getStatus() == 0) {
throw new LockedAccountException("账号已被锁定,请联系管理员");
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(sysUser, password, getName());
return info;
}
完成shiro的资源授权
/**
* 执行授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//获取当前的登录用户
SysUser sysUser = (SysUser)SecurityUtils.getSubject().getPrincipal();
Set<String> perms = menuService.listPerms(sysUser.getUserId());
//给资源进行授权
SimpleAuthorizationInfo info= new SimpleAuthorizationInfo();
info.setStringPermissions(perms);
return info;
}
当这些做好之后,会出现一个问题,启动之后控制台打印这一条
[org.mybatis.spring.SqlSessionTemplate] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
shiroFilter
依赖了securityManager
,securityManager
依赖了userRealm
,userRealm
为了获取AuthenticationInfo和AuthorizationInfo又依赖了userService
。
其实这些信息并不影响正常的运行,只是需要用到事物的时候就不会回滚了
2019-05-25 14:51:02.995 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'shiroConfig' of type [com.chaomeng.chaomengwenyu.accumulatepoints.config.ShiroConfig$$EnhancerBySpringCGLIB$$8d513fea] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.003 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9f75bb28] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.060 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'mybatis-org.mybatis.spring.boot.autoconfigure.MybatisProperties' of type [org.mybatis.spring.boot.autoconfigure.MybatisProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.066 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration' of type [org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration$$EnhancerBySpringCGLIB$$d24a0c58] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.068 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'druidConfig' of type [com.chaomeng.chaomengwenyu.accumulatepoints.config.DruidConfig$$EnhancerBySpringCGLIB$$e1f7a35b] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.096 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'druid' of type [com.alibaba.druid.pool.DruidDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.108 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.111 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.145 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sqlSessionFactory' of type [org.apache.ibatis.session.defaults.DefaultSqlSessionFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.150 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sqlSessionTemplate' of type [org.mybatis.spring.SqlSessionTemplate] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.155 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sysUserMapper' of type [org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.157 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sysUserMapper' of type [com.sun.proxy.$Proxy55] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.157 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'userAuthServiceImpl' of type [com.chaomeng.chaomengwenyu.accumulatepoints.shiro.service.impl.UserAuthServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.161 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sysMenuMapper' of type [org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.162 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sysMenuMapper' of type [com.sun.proxy.$Proxy58] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.162 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'permissionCheckServiceImpl' of type [com.chaomeng.chaomengwenyu.accumulatepoints.shiro.service.impl.PermissionCheckServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.162 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'userRealm' of type [com.chaomeng.chaomengwenyu.accumulatepoints.shiro.UserRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-25 14:51:03.336 INFO 7568 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'securityManager' of type [org.apache.shiro.web.mgt.DefaultWebSecurityManager] is not eligible for getting processed by all BeanPostProcessors (for
上面的这段,表面意思是:这几个bean(称为业务bean)不会被所有BeanPostProcessor(BPP)处理。BPP是spring的内置的基础bean,用于在实例化业务bean前后处理一些逻辑,可以更改业务bean的行为甚至返回另一个bean(大名鼎鼎的AOP就是通过BPP实现)。
上面的ShiroFitlerFactoryBean
就实现了BPP接口,会对所有bean判断,如果实现了Filter
接口,会加入到filterMap
中,后续构造filterChainManager
时会用到。
我们知道出问题的原因:业务bean在BPP实例化前被实例化了。理想情况下应该让spring先实例化所有
的BPP后,再实例化我们的业务bean,这样业务bean才能被所有
BPP处理,如果有业务bean先于任何BPP实例化,那么这个业务bean就不会被还未实例化的BPP处理了,这个就是日志提示的原因。
到现在你应该理解了是shiroFilter
导致了userService
没有被@Transactional 对应的BPP处理,导致事务不起作用。虽然spring打印很多bean,一般最后打印的那个bean是导致问题的罪魁祸首,因为spring是先实例化被依赖的bean。
解决方法
获取 AuthenticationInfo
和AuthorizationInfo
不要通过UserService/UserRoleService,可以单独写个Service或Dao供登录使用。
一个是认证调用的方法,一个是授权调用的方法。它们只为shiro权限而用,不会掺杂到别的业务中,所以不需要用到回滚,也就不会影响别的业务。
导入thymeleaf拓展坐标
<!-- thymel对shiro的扩展坐标 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
在ShiroConfig类里面添加getShiroDialect方法
/**
* 配置ShiroDialect,用于thymeleaf和shiro标签配合使用
*/
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
在页面上使用shiro标签
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试Thymeleaf的使用</title>
</head>
<body>
<h3 th:text="${name}"></h3>
<hr/>
<div shiro:hasPermission="user:add">
进入用户添加功能: <a href="add">用户添加</a><br/>
</div>
<div shiro:hasPermission="user:update">
进入用户更新功能: <a href="update">用户更新</a><br/>
</div>
<a href="toLogin">登录</a>
</body>
</html>
开启shiro缓存,授权之后的信息可以缓存起来重复调用,不用每次都到数据库去取
引入依赖
springboot集成shiro和ehcache的时候,要先集成ehcache然后再集成shiro,这样当shiro配置cacheManager的时候就可以直接使用了。下面是正确的集成步骤:
<!--开启 cache 缓存-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- ehcache 缓存 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
引入配置文件 ehcache.xml
@Bean
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:config/ehcache.xml");
return em;
}
@Bean
UserRealm userRealm(EhCacheManager cacheManager) {
UserRealm userRealm = new UserRealm();
userRealm.setCacheManager(cacheManager);
return userRealm;
}
创建ehcache.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="java.io.tmpdir/Tmp_EhCache" />
<defaultCache
eternal="false"
maxElementsInMemory="1000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU" />
<!--
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
<cache
name="role"
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
memoryStoreEvictionPolicy="LFU" />
</ehcache>
重点来了第二步集成shiro并使用ehcache缓存:
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- shiro ehcache -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
第七部分
打包工具更改
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
挺屌的springboot项目