SpringBoot整合Shiro 安全框架

Apache Shiro

Apache Shiro是一个功能强大且易于使用的Java安全框架,提供了认证,授权,加密,和会话管理.


简介: 在这里插入图片描述

  • Authentication:身份认证/登录,验证用户是不是拥有相应的身份
  • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限。
  • Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的。
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储。
  • Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查。
  • Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去。
  • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
  • Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问。
  • Testing:提供测试支持。
  • Web Support:Web支持,可以非常容易的集成到 web 环境。

在这里插入图片描述

  • Subject:主体,可以看到主体可以是任何与应用交互的“用户”。
  • SecurityManager:相当于 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的 FilterDispatcher。它是 Shiro 的核心,所有具体的交互都通过 SecurityManager 进行控制。它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。
  • Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得 Shiro 默认的不好,我们可以自定义实现。其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了。
  • Authrizer:授权器,或者访问控制器。它用来决定主体是否有权限进行相应的操作,即控制着用户能访问应用中的哪些功能。
  • Realm:可以有1个或多个 Realm,可以认为是安全实体数据源,即用于获取安全实体的。它可以是 JDBC 实现,也可以是 LDAP 实现,或者内存实现等。
  • SessionManager:如果写过 Servlet 就应该知道 Session 的概念,Session 需要有人去管理它的生命周期,这个组件就是 SessionManager。而 Shiro 并不仅仅可以用在 Web 环境,也可以用在如普通的 JavaSE 环境。
  • SessionDAO:DAO 大家都用过,数据访问对象,用于会话的 CRUD。我们可以自定义 SessionDAO 的实现,控制 session 存储的位置。如通过 JDBC 写到数据库或通过 jedis 写入 redis 中。另外 SessionDAO 中可以使用 Cache 进行缓存,以提高性能。
  • CacheManager:缓存管理器。它来管理如用户、角色、权限等的缓存的。因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能。
  • Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于如密码加密/解密的。

运行流程:

在这里插入图片描述

  • Subject:主体,代表了当前“用户”。这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等。所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager。我们可以把 Subject 认为是一个门面,SecurityManager 才是实际的执行者。
  • SecurityManager:安全管理器。即所有与安全有关的操作都会与 SecurityManager 交互,且它管理着所有 Subject。可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,我们可以把它看成 DispatcherServlet 前端控制器。
  • Realm:域。Shiro 从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法,也需要从 Realm 得到用户相应的角色/权限进行验证用户是否能进行操作。我们可以把 Realm 看成 DataSource,即安全数据源。

shiro 过滤器:

anon,authcBasic,auchc,user认证过滤器
perms,roles,ssl,rest,port授权过滤器


anon: 表示可以匿名使用。
java类:【org.apache.shiro.web.filter.authc.AnonymousFilter

authc:表示需要认证(登录)才能使用,没有参数
java类:【org.apache.shiro.web.filter.authc.FormAuthenticationFilter

roles:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,如admins/user/**=roles[“admin,guest”],每个参数通过才算通过,相当于hasAllRoles()方法。
org.apache.shiro.web.filter.authz.RolesAuthorizationFilter

perms:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms[“user:add:,user:modify:”],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter

rest:根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。
org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter

port:当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。
org.apache.shiro.web.filter.authz.PortFilter

authcBasic:没有参数表示httpBasic认证
org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter

ssl: 表示安全的url请求,协议为https
org.apache.shiro.web.filter.authc.LogoutFilter

user: 当登入操作时不做检查
org.apache.shiro.web.filter.authc.UserFilter

logout:【org.apache.shiro.web.filter.authc.LogoutFilter】

noSessionCreation:【org.apache.shiro.web.filter.session.NoSessionCreationFilter
在这里插入图片描述
在这里插入图片描述

/service/ ** =anon <!-- 该uri可以匿名访问--> 
/service/ ** =auth <!-- 该uri需认证访问--> 
/service/ ** =authcBasic <!-- 该uri需要 httpBasic  认证--> 
/service/ ** =perms[user:sys:use]<!-- 该uri需要 用户拥有user:sys:use 权限才能访问--> 
/service/ ** =port[8081] <!-- 该uri需要使用8081端口--> 
/service/ ** =rest[user] <!-- /admins/ **=perms[user:method],其中,method 表示  get、post、delete 等--> 
/service/ ** =roles[admin] <!-- uri 需要认证用户拥有 admin 角色才能访问--> 
/logout=logou # 表示注销,可以当作固定配置
/service/ **=user # 表示该 uri 需要认证或通过记住我认证才能访问

POM依赖

<!-- shiro-spring -->
		<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>
  • == Relam 实现 ==
public class UserRelam extends AuthorizingRealm {

    private static final Logger Logger = LoggerFactory.getLogger(UserRelam.class);

    @Autowired
    private UserMapper userMapper;

    /*执行授权(为当前登录的Subject授予角色和权限)
     * 如果连续访问同一个URL(比如刷新),该方法不会被重复调用,Shiro有一个时间间隔(也就是cache时间,在ehcache-shiro.xml中配置  
     * 超过这个时间间隔再刷新页面,该方法会被执行  
     * 当访问到页面的时候,使用了相应的注解或者shiro标签才会执行此方法否则不会执行
     * 所以如果只是简单的身份认证没有权限的控制的话,那么这个方法可以不进行实现,直接返回null即可
     * (non-Javadoc)
     * @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Logger.info("用户登陆成功开始执行授权操作");
        // 获取当前用户
        String username = (String)principals.getPrimaryPrincipal();
        // TODO 授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 获取权限
        Set<String> perms = userMapper.findPermsByUsername(username);
        // 获取角色
        Set<String> roles = userMapper.findRolesByUsername(username);
        info.setStringPermissions(perms);
        info.setRoles(roles);
        Logger.info("{} 的权限和角色是:{}{}", username, perms, roles);
        return info;
    }

    /*执行认证 查询数据库用户信息,
     * (non-Javadoc)
     * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        Logger.info("用户开始执行shiro 认证操作");
        // 获取用户的信息
        UsernamePasswordToken userToken = (UsernamePasswordToken)token;
        // 用户名
        String username = userToken.getUsername();

        // 查询数据库 返回信息
        UserTo userTo = userMapper.findUserByUsername(username);
        if (userTo == null) {
            throw new AuthenticationException("用户名信息错误");
        }
        // SimpleHash sHash = new SimpleHash("MD5", passWord, ByteSource.Util.bytes("password"), 1024); 不访问数据库自己操作

        Logger.info("usertO 基本信息是:{}", userTo);

        // 传入:用户名,加密后的密码,盐值,该realm的名字,加密算法和加密次数在已经在配置文件中指定
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, userTo.getPassword(),
            ByteSource.Util.bytes(userTo.getSalt()), getName());
        return info;
    }

    // 权限修改生效后,立即刷新清空缓存,则可以实现用户不退出生效新的权限
    // 在权限修改后调用realm中的方法,realm已经由spring管理,所以从spring中获取realm实例,调用clearCached方法
    public void clearCache() {
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);
    }

}
  • Shiro 核心配置类
@Configuration
public class ShiroConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(ShiroConfig.class);

    /**
     * 内置过滤器
     * 
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        LOGGER.info("shiro 过滤器开始执行");
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        // 配置shiro n内置过滤器
        Map<String, String> filterMap = new HashMap<>();
        /*
         *  anon:表示可以匿名使用。 
            authc:表示需要认证(登录)才能使用,没有参数 
            roles:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。 
            perms:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。 
            rest:根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。 
            port:当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。 
            authcBasic:没有参数表示httpBasic认证 
            ssl:表示安全的url请求,协议为https 
            user:当登入操作时不做检查
         */
        // 设置login url
        factoryBean.setLoginUrl("/service/page/login");
        // 设置成功后的跳转的连接
        factoryBean.setSuccessUrl("/service/page/index");
        factoryBean.setUnauthorizedUrl("/service/error-400");
        filterMap.put("/web/**", "anon");
        // 静态资源处理
        filterMap.put("/js/**", "anon");
        filterMap.put("/css/**", "anon");
        filterMap.put("/images/**", "anon");
        filterMap.put("/font/**", "anon");
        // 当请求/shiro/logout时登
        filterMap.put("/service/logout", "logout");
        filterMap.put("/service/login", "anon");

        /*
         *  注意:这里的user是过滤器的一种,而下面roles[user]中的user是自定义的一种角色。
         *  注意:user拦截器既允许通过Subject.login()认证进入的用户访问;又允许通过rememberMe缓存进入的用户访问
         *  注意:authc拦截器既只允许通过Subject.login()认证进入的用户访问;不允许rememberMe缓存通过进入的用户访问
         */
        filterMap.put("/introduce.html", "user");
        filterMap.put("/rememberMe.html", "user");
        // 注意roles[user]这里的话,角色不要再用引号引起来了,直接写即可
        filterMap.put("/user.html", "authc,roles[user]");
        filterMap.put("/admin.html", "authc,roles[admin]");
        filterMap.put("/superadmin.html", "authc,roles[host,admin]");

        // 由于权限由上而下“就近”选择,所以一般将"/**"配置在最下面
        filterMap.put("/**", "anon");// 必须授权才能访问
        factoryBean.setFilterChainDefinitionMap(filterMap);
        LOGGER.info("shiro 过滤器结束执行");
        return factoryBean;
    }

    @Bean
    public DefaultWebSecurityManager getSecurityManager(UserRelam userRelam, SessionManager sessionManager,
        EhCacheManager cacheManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置Relam
        securityManager.setRealm(userRelam);
        // 自定义缓存实现,
        securityManager.setCacheManager(cacheManager);
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }

    @Bean
    public HashedCredentialsMatcher getHashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");// MD5加密
        hashedCredentialsMatcher.setHashIterations(1024);// 迭代1024次
        return hashedCredentialsMatcher;
    }

    /**
     * 配置relam 以及凭证匹配器,也可以在里面重写CredentialsMatcher 方法
     * 
     * @param hashedCredentialsMatcher
     * @return
     */
    @Bean
    public UserRelam getUserRelam(HashedCredentialsMatcher hashedCredentialsMatcher) {
        UserRelam userRelam = new UserRelam();
        userRelam.setCredentialsMatcher(hashedCredentialsMatcher);
        return userRelam;
    }

    /** 配置shiro框架组件的生命周期管理对象 */
    @Bean
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 配置授权属性应用对象(在执行授权操作时需要用到此对象) 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
     * 
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    /** 配置负责为Bean对象(需要授权访问的方法所在的对象) 创建代理对象的Bean组件 */
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

    /** 使用缓存ehcachae */
    @Bean
    public EhCacheManager getEhCacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        // 将ehcacheManager转换成shiro包装后的ehcacheManager对象
        // ehCacheManager.setCacheManager(cacheManager);
        // eheache 配置文件目录
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return ehCacheManager;
    }

    /**
     * shiro session的管理
     * 
     * @return
     */
    @Bean
    public SessionManager sessionManager(SimpleCookie simpleCookie, SessionDAO sessionDAO) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(100000);// ms
        // 设置sessionDao对session查询,在查询在线用户service中用到了
        // sessionManager.setSessionDAO(sessionDAO);
        // 配置session 的监听
        // Collection<SessionListener> listeners = new ArrayList<SessionListener>();
        // listeners.add(new BDsess)
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdCookieEnabled(true);
        // 设置cookie 中sessionid 的名称
        sessionManager.setSessionIdCookie(simpleCookie);
        return sessionManager;
    }

    @Bean
    public SessionDAO getSessionDAO() {
        return new MemorySessionDAO();
    }

    @Bean
    public SimpleCookie getSimpleCookie() {
        SimpleCookie simpleCookie = new SimpleCookie();
        simpleCookie.setName("jeesite.session.id");
        return simpleCookie;
    }

}

1.LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。主要是AuthorizingRealm类的子类,以及EhCacheManager类。
2.HashedCredentialsMatcher,这个类是为了对密码进行编码的,防止密码在数据库里明码保存,当然在登陆认证的生活,这个类也负责对form里输入的密码进行编码。
3.ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm,负责用户的认证和权限的处理,可以参考JdbcRealm的实现。
4.EhCacheManager,缓存管理,用户登陆成功后,把用户信息和权限信息缓存起来,然后每次用户请求时,放入用户的session中,如果不设置这个bean,每个请求都会查询一次数据库。
5.SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。
6.ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。
7.DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
8.AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类,内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。

  • 测试类
@Controller
@RequestMapping
public class UserController {

    private static final Logger LOGGER = LoggerFactory.getLogger(GloableExecption.class);

    @Autowired
    private UserService userService;

    @Autowired
    private UserMapper userMapper;

    @RequestMapping("/login")
    public String login(UserTo userTo) {
        LOGGER.info("开始执行登陆操作 username:{},password:{}", userTo.getUsername(), userTo.getPassword());
        Subject subject = SecurityUtils.getSubject();// 创建用户实体
        System.err.println(subject.isRemembered() + "" + subject.isAuthenticated());
        // if (!subject.isAuthenticated()) {
        UsernamePasswordToken token = new UsernamePasswordToken(userTo.getUsername(), userTo.getPassword());
        try {
            // 执行登陆验证
            subject.login(token);
            LOGGER.info("恭喜登陆成功");
        } catch (UnknownAccountException e) {
            throw new ServiceException("用户名不存在");
        } catch (IncorrectCredentialsException e) {
            throw new ServiceException("用户名或者密码错误");
        }
        // }
        return "index";
    }

    @RequestMapping("/logout")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        LOGGER.info("用户登出成功");
        return "index";
    }

    @RequestMapping("/select")
    @ResponseBody
    @RequiresPermissions(value = {"system:user:delete"})
    public Object selectUser() {
        // userService.insertUserList(new ArrayList<>());
        return userMapper.findUserByUsername("wang3");
    }

    @RequestMapping("/insert")
    @ResponseBody
    @RequiresPermissions(value = {"system:user:insert"})
    public Object insertUser(UserTo userTo) {
        Subject subject = SecurityUtils.getSubject();
        System.err.println("进来了");
        return userMapper.findUserByUsername("wang3");
    }

    /**
     * 尝试通过异常让事务回滚
     * 
     * @return
     */
    @RequestMapping("trans")
    @ResponseBody
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) // 开启事务,异常事务回滚
    public Object transTest() {
        UserTo user = new UserTo();
        user.setAge(18);
        user.setBrithday(new Date());
        user.setCreteTime(new Date());
        user.setModifyTime(new Date());
        user.setLastLoginTime(new Date());
        String salt = String.valueOf(System.currentTimeMillis());
        SimpleHash sHash = new SimpleHash("MD5", "password", ByteSource.Util.bytes(salt), 1024);
        user.setSalt(salt);
        user.setPassword(sHash.toString());
        user.setUsername("wang");
        user.setGender("women");
        // 获取自增的主键
        userMapper.insertUser(user);
        LOGGER.info("新增后主键是:{}", user.getId());
        // int i = 0 / 0;// 制造异常 看事务回滚
        return null;
    }

    // 配置错误界面
    @RequestMapping("error-400")
    public String toPage400() {
        return "err";
    }

    @Autowired
    private UserRelam userRelam;

    // 登陆界面
    @RequestMapping("page/login")
    public String log() {
        userRelam.clearCache();// 刷新权限不许要重新登录
        return "login";
    }

    // 主界面
    @RequestMapping("page/index")
    public String index() {
        return "index";
    }

}

缓存 文件

<ehcache>
    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <diskStore path="java.io.tmpdir"/>
    
    <cache name="authorizationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>
    

    <cache name="authenticationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="shiro-activeSessionCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"/>

    <!--Predefined caches.  Add your cache configuration settings here.
        If you do not have a configuration for your cache a WARNING will be issued when the
        CacheManager starts
        The following attributes are required for defaultCache:
        name              - Sets the name of the cache. This is used to identify the cache. It must be unique.
        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.-->
    <!-- Place configuration for your caches following -->

	 <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />
 
    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> 
</ehcache>

参靠考项目地址:

https://github.com/DonaldAndMickey/Boke.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值