A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

shiro+spring+ehCache+maven整合开发
案例框架使用的shiro 整合使用的spring 缓存技术使用的ehcache 项目搭建使用的maven
1.导包
  • <!-- 权限控制 框架 -->
  • <dependency>
  •     <groupId>org.apache.shiro</groupId>
  •     <artifactId>shiro-all</artifactId>
  •     <version>1.2.2</version>
  • </dependency>
  • <!-- spring 框架 -->
  • <dependency>
  •     <groupId>org.springframework</groupId>
  •     <artifactId>spring-context</artifactId>
  •     <version>${spring.version}</version>
  • </dependency>
  • <dependency>
  •     <groupId>org.springframework</groupId>
  •     <artifactId>spring-context-support</artifactId>
  •     <version>${spring.version}</version>
  • </dependency>
  • <dependency>
  •     <groupId>org.springframework</groupId>
  •     <artifactId>spring-web</artifactId>
  •     <version>${spring.version}</version>
  • </dependency>
  • <dependency>
  •     <groupId>org.springframework</groupId>
  •     <artifactId>spring-orm</artifactId>
  •     <version>${spring.version}</version>
  • </dependency>
  • <dependency>
  •     <groupId>org.springframework</groupId>
  •     <artifactId>spring-jms</artifactId>
  •     <version>${spring.version}</version>
  • </dependency>
  • <dependency>
  •     <groupId>org.springframework</groupId>
  •     <artifactId>spring-test</artifactId>
  •     <version>${spring.version}</version>
  • </dependency>
  • <dependency>
  •     <groupId>org.springframework</groupId>
  •     <artifactId>spring-aspects</artifactId>
  •     <version>${spring.version}</version>
  • </dependency>
  • <!-- spring data jpa 数据库持久层 -->
  • <dependency>
  •     <groupId>org.springframework.data</groupId>
  •     <artifactId>spring-data-jpa</artifactId>
  •     <version>${springdatajpa.version}</version>
  • </dependency>
  • <!-- 缓存 -->
  • <dependency>
  •     <groupId>net.sf.ehcache</groupId>
  •     <artifactId>ehcache-core</artifactId>
  •     <version>2.6.11</version>
  • </dependency>   
2.shiro开发
先进行shiro和spring整合实现登录和权限管理
2.1 在web.xml配置shiro的过滤器
  • <!-- shiro的Filter  -->
  • <filter>
  •     <!-- 去spring配置文件中寻找同名bean  -->
  •     <filter-name>shiroFilter</filter-name>
  •     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  • </filter>
  • <filter-mapping>
  •     <filter-name>shiroFilter</filter-name>
  •     <url-pattern>/*</url-pattern>
  • </filter-mapping>
注意: web.xml中的配置文件是有顺序的。shiro的过滤器要放在别的过滤器前面
2.2 添加spring配置文件
  • <!-- 配置Shiro核心Filter  -->
  •     <bean id="shiroFilter"
  •         class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  •         <!-- 安全管理器 -->
  •         <property name="securityManager" ref="securityManager" />
  •         <!-- 未认证,跳转到哪个页面  -->
  •         <property name="loginUrl" value="/login.html" />
  •         <!-- 登录页面页面 -->
  •         <property name="successUrl" value="/index.html" />
  •         <!-- 认证后,没有权限跳转页面 -->
  •         <property name="unauthorizedUrl" value="/unauthorized.html" />
  •         <!-- shiro URL控制过滤器规则  -->
  •         <property name="filterChainDefinitions">
  •             <value>
  •                 /login.html* = anon              //放行
  •                 /user_login.action* = anon
  •                 /validatecode.jsp* = anon
  •                 /css/** = anon
  •                 /js/** = anon
  •                 /images/** = anon
  •                 /services/** = anon
  •                 /pages/base/courier.html* = perms[courier:list]   //权限
  •                 /pages/base/area.html* = roles[base]              //角色
  •                 /** = authc
  •                 <--anon 未认证可以访问
  •                 authc 认证后可以访问
  •                 perms 需要特定权限才能访问
  •                 roles 需要特定角色才能访问
  •                 user 需要特定用户才能访问
  •                 port 需要特定端口才能访问
  •                 reset 根据指定 HTTP 请求访问才能访问 -->
  •             </value>
  •         </property>
  •     </bean>
  •     <!-- 安全管理器  -->
  •     <bean id="securityManager"
  •         class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  •          //自定义的Realm
  •         <property name="realm" ref="bosRealm" />   
  •         //自己定义的缓存 如果没有使用缓存要删除掉
  •         <property name="cacheManager" ref="shiroCacheManager" />
  •     </bean>
  •     <!-- 配置Realm -->
  •     <bean id="bosRealm" class="cn.tpr.bos.realm.BosRealm">
  •         <!-- 缓存区的名字 就是 ehcache.xml 自定义 cache的name -->
  •         //自己定义的缓存 如果没有使用缓存要删除掉
  •         <property name="authorizationCacheName" value="bos" />
  •     </bean>
  •     <!-- 开启shiro注解模式  -->
  •     <bean id="lifecycleBeanPostProcessor"
  •         class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
  •     <bean
  •         class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
  •         depends-on="lifecycleBeanPostProcessor" >
  •         <property name="proxyTargetClass" value="true" />
  •     </bean>
  •     <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
  •          <property name="securityManager" ref="securityManager"/>
  •     </bean>
2.3更改spring代理方式
默认使用的是jdb动态代理,无法获取shiro的注解 改成cglib代理
  • <!-- 注解管理事务 -->
  •     <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
2.3 编写登录方法
  • @Action(value = "user_login", results = {
  •             @Result(name = "login", type = "redirect", location = "login.html"),
  •             @Result(name = "success", type = "redirect", location = "index.html") })
  •     public String login() {
  •         // 用户名和密码 都保存在model中
  •         // 基于shiro实现登录
  •         Subject subject = SecurityUtils.getSubject();
  •         // 用户名和密码信息
  •         AuthenticationToken token = new UsernamePasswordToken(
  •                 model.getUsername(), model.getPassword());
  •         try {
  •             //此处调用了自定义Realm
  •             subject.login(token);
  •             // 登录成功
  •             // 将用户信息 保存到 Session
  •             return SUCCESS;
  •         } catch (AuthenticationException e) {
  •             // 登录失败
  •             e.printStackTrace();
  •             return LOGIN;
  •         }
  •     }
2.4编写自定义Realm
Realm使用的是配置bean的方式配置的。要和上面配置文件中的Realm中的class的权限定名一制 此处 cn.tpr.bos.realm.BosRealm 代码 如下:
  • // @Service("bosRealm")
  • public class BosRealm extends AuthorizingRealm {
  •     @Autowired
  •     private UserService userService;
  •     @Autowired
  •     private RoleService roleService;
  •     @Autowired
  •     private PermissionService permissionService;
  •     @Override
  •     // 授权...
  •     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
  •         System.out.println("shiro 授权管理...");
  •         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
  •         // 根据当前登录用户 查询对应角色和权限
  •         Subject subject = SecurityUtils.getSubject();
  •         User user = (User) subject.getPrincipal();
  •         // 调用业务层,查询角色
  •         List<Role> roles = roleService.findByUser(user);
  •         for (Role role : roles) {
  •             authorizationInfo.addRole(role.getKeyword());
  •         }
  •         // 调用业务层,查询权限
  •         List<Permission> permissions = permissionService.findByUser(user);
  •         for (Permission permission : permissions) {
  •             authorizationInfo.addStringPermission(permission.getKeyword());
  •         }
  •         return authorizationInfo;
  •     }
  •     @Override
  •     // 认证...
  •     protected AuthenticationInfo doGetAuthenticationInfo(
  •             AuthenticationToken token) throws AuthenticationException {
  •         System.out.println("shiro 认证管理... ");
  •         // 转换token
  •         UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
  •         // 根据用户名 查询 用户信息
  •         User user = userService.findByUsername(usernamePasswordToken
  •                 .getUsername());
  •         if (user == null) {
  •             // 用户名不存在
  •             // 参数一: 期望登录后,保存在Subject中信息
  •             // 参数二: 如果返回为null 说明用户不存在,报用户名
  •             // 参数三 :realm名称
  •             return null;
  •         } else {
  •             // 用户名存在
  •             // 当返回用户密码时,securityManager安全管理器,自动比较返回密码和用户输入密码是否一致
  •             // 如果密码一致 登录成功, 如果密码不一致 报密码错误异常
  •             return new SimpleAuthenticationInfo(user, user.getPassword(),
  •                     getName());
  •         }
  •     }
  • }
springt和shiro小结
到此shiro和spring整合完成。密码不正确或者账号为空都会抛出不同的异常,只要捕获后处理就好了。 权限 控制 有最少五张表 用户、 角色、 权限还有两张是角色和他们之间的关联表
三、shiro使用ehcache缓存3.1 添加ehcache缓存配置文件
  • <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
  •     <diskStore path="java.io.tmpdir"/>
  •     <defaultCache
  •             maxElementsInMemory="10000"
  •             eternal="false"
  •             timeToIdleSeconds="120"
  •             timeToLiveSeconds="120"
  •             maxElementsOnDisk="10000000"
  •             diskExpiryThreadIntervalSeconds="120"
  •             memoryStoreEvictionPolicy="LRU">
  •         <persistence strategy="localTempSwap"/>
  •     </defaultCache>
  •     <cache name="bos"
  •             maxElementsInMemory="10000"
  •             eternal="false"
  •             timeToIdleSeconds="120"
  •             timeToLiveSeconds="120"
  •             maxElementsOnDisk="10000000"
  •             diskExpiryThreadIntervalSeconds="120"
  •             memoryStoreEvictionPolicy="LRU">
  •         <persistence strategy="localTempSwap"/>
  •     </cache>
  •     、//为一个缓存单位
  •     <cache name="standard"
  •             maxElementsInMemory="10000"
  •             eternal="false"
  •             timeToIdleSeconds="120"
  •             timeToLiveSeconds="120"
  •             maxElementsOnDisk="10000000"
  •             diskExpiryThreadIntervalSeconds="120"
  •             memoryStoreEvictionPolicy="LRU">
  •         <persistence strategy="localTempSwap"/>
  •     </cache>
  • </ehcache>
3.2配置缓存管理器
  • <!-- 缓存配置  -->
  •     <bean id="ehCacheManager"
  •         class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  •         <property name="configLocation" value="classpath:ehcache.xml" />
  •     </bean>
3.3shiro封装cacheManager缓存管理器
  • <!-- shiro封装cacheManager -->
  • <bean id="shiroCacheManager"
  •     class="org.apache.shiro.cache.ehcache.EhCacheManager">
  •     <property name="cacheManager" ref="ehCacheManager" />
  • </bean>
3.4shiro使用缓存管理器
在上面配置Realm的时候添加一个property对象 下面就是授权缓存 一个用户只要授权一次就可以了,不会在多请求Realm
  • <!-- 配置Realm -->
  •     <bean id="bosRealm" class="cn.tpr.realm.BosRealm">
  •         <!-- 缓存区的名字 就是 ehcache.xml 自定义 cache的name -->
  •         //自己定义的缓存 如果没有使用缓存要删除掉
  •         <property name="authorizationCacheName" value="bos" />
  •     </bean>
spring+ehcache缓存普通数据
在接着上面的对ehcache的配置后面继续添加配置,来缓存普通数据
1和spring整合 让spring来管理缓存
  • <!-- spring 封装ehcache缓存管理器  -->
  • <bean id="springCacheManager"
  • class="org.springframework.cache.ehcache.EhCacheCacheManager">
  • <property name="cacheManager" ref="ehCacheManager" />
  • </bean>
2.激活spring缓存注解
  • <!-- 激活spring 缓存注解 -->
  •     <cache:annotation-driven cache-manager="springCacheManager"/>
3配置文件中的名称 空间4.需要操作的pojo类实现序列化接口
  • public class Menu implements Serializable {
5.在service层实现方法中添加标签5.1 添加缓存
  • @Cacheable("standard") 这个标签指把查询出来 的数据添加standard 这个缓存空间中是在ehcache中配置的
  • @Override
  •     @Cacheable("standard")
  •     public List<Standard> findAll() {
  •         return standardRepository.findAll();
  •     }
5.2修改缓存
  • @CacheEvict(value = "standard", allEntries = true)
  • 修改缓存空间中的值
  • @Override
  •     @CacheEvict(value = "standard", allEntries = true)
  •     public void save(Standard standard) {
  •         standardRepository.save(standard);
  •     }
5.3分页缓存
  • @Override
  •     @Cacheable(value = "standard", key = "#pageable.pageNumber+'_'+#pageable.pageSize")
  •     public Page<Standard> findPageData(Pageable pageable) {
  •         return standardRepository.findAll(pageable);
  •     }

您需要登录后才可以回帖 登录 | 加入黑马