shrio框架搭建

1.导入jar包

<!-- shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.2.3</version>
        </dependency>

2.在web.xml中配置拦截器

<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported>
    <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

注意:

此处<async-supported>会报错,需要在<web-app>中配置
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

3.在springmvc.xml中配置shiro

<!--spring 自定参数解析器-->
	<bean id="springAnnotationResolver" class="org.apache.shiro.spring.aop.SpringAnnotationResolver" />
	<!--开启Spring AOC Shiro注解支持-->
	<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager"/>
		<property name="advice">
			<bean class="org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor">
				<property name="methodInterceptors">
					<list>
						<bean class="项目名.module.shiro.aop.AuthenticatedAnnotationMethodInterceptor">
							<constructor-arg ref="springAnnotationResolver" />
						</bean>
						<bean class="org.apache.shiro.authz.aop.RoleAnnotationMethodInterceptor">
							<constructor-arg ref="springAnnotationResolver" />
						</bean>
						<bean class="org.apache.shiro.authz.aop.PermissionAnnotationMethodInterceptor">
							<constructor-arg ref="springAnnotationResolver" />
						</bean>
						<bean class="org.apache.shiro.authz.aop.UserAnnotationMethodInterceptor">
							<constructor-arg ref="springAnnotationResolver" />
						</bean>
						<bean class="org.apache.shiro.authz.aop.GuestAnnotationMethodInterceptor">
							<constructor-arg ref="springAnnotationResolver" />
						</bean>
					</list>
				</property>
			</bean>
		</property>
	</bean>
    
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm">
			<bean class="项目名.module.shiro.AuthorizingRealm"/>
		</property>
		<property name="cacheManager">
			<bean class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/>
		</property>
</bean>

<!-- shiro工厂bean配置 过滤器 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- shiro的核心安全接口 -->
		<property name="securityManager" ref="securityManager"/>
		<!--登录的url-->
		<property name="loginUrl" value="/"/>
	</bean>

	<!--管理shiro bean生命周期-->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

	<!-- 启用Spring IOC容器Shiro注解,当TestTram类有实现某个接口,而TestProxyClass类中配置的类对象是TestTram时(而不是TestTram实现的接口),这时候你需要配置proxyTargetClass=true-->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
		<property name="proxyTargetClass" value="true" />
	</bean>
	
	<!-- 开启aop,对类代理 -->
	<aop:aspectj-autoproxy proxy-target-class="true"/>

4.在module>shiro下,新建SecurityManager

package 项目名.module.shiro;

import 项目名.exception.SystemException;
import 项目名.module.Configuration;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

public class SecurityManager extends DefaultWebSecurityManager {

    //开启redis
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    protected void stopSession(Subject subject) {
        Session session = subject.getSession();
        super.stopSession(subject);
        SessionManager sessionManager = (SessionManager) super.getSessionManager();
        sessionManager.delete(session);
        String mappingKey;
        SimpleToken.Principal principal = (SimpleToken.Principal) subject.getPrincipal();
        if(principal instanceof SimpleToken.Role){
            mappingKey = Configuration.SYSTEM_SESSION_ADMIN_MAPPING_NAMESPACE;
        }else if(principal instanceof SimpleToken.Role){
            mappingKey = Configuration.SYSTEM_SESSION_SHOP_MAPPING_NAMESPACE;
        }else {
            throw new SystemException("未知的角色信息");
        }
        this.redisTemplate.delete(String.format("%s:%s", mappingKey,((SimpleToken.Principal) subject.getPrincipal()).getId()));
    }
}

注:需要配置的相关文件有
(1)SessionManager

package 项目名.module.shiro;

import 项目名.module.Configuration;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.session.ExpiredSessionException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.*;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.util.AntPathMatcher;
import org.apache.shiro.util.PatternMatcher;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;

public class SessionManager extends AbstractValidatingSessionManager {

    private final Logger logger = LogManager.getLogger(SessionManager.class);

    private SessionFactory sessionFactory;

    private SessionDAO sessionDAO;

    public SessionManager(){
        this.sessionFactory = new SimpleSessionFactory();
    }

    @Override
    protected void onInvalidation(org.apache.shiro.session.Session s, InvalidSessionException ise, SessionKey key) {
        super.onInvalidation(s, ise, key);
        this.onInvalidation(key);
    }

    @Override
    protected void onExpiration(org.apache.shiro.session.Session s, ExpiredSessionException ese, SessionKey key) {
        super.onExpiration(s, ese, key);
        this.onInvalidation(key);
    }

    @Override
    protected void onExpiration(org.apache.shiro.session.Session session) {
        if (session instanceof SimpleSession) {
            ((SimpleSession) session).setExpired(true);
        }
        this.onChange(session);
    }

    @Override
    protected void afterExpired(org.apache.shiro.session.Session session) {
        this.delete(session);
    }

    @Override
    protected org.apache.shiro.session.Session retrieveSession(SessionKey key) {
        Serializable sessionId = this.getSessionId(key);
        org.apache.shiro.session.Session session = this.retrieveSession(sessionId);
        return session;
    }

    @Override
    protected org.apache.shiro.session.Session doCreateSession(SessionContext initData) throws AuthorizationException {
        org.apache.shiro.session.Session session = ((initData != null && initData.getHost() != null) ? new Session(initData.getHost()) : new Session());
        create(session,initData);
        return session;
    }

    @Override
    protected Collection<org.apache.shiro.session.Session> getActiveSessions() {
        Collection<org.apache.shiro.session.Session> active = this.sessionDAO.getActiveSessions();
        return active != null ? active : Collections.emptySet();
    }

    private void onInvalidation(SessionKey key) {

    }

    protected void delete(org.apache.shiro.session.Session session) {
        this.sessionDAO.delete(session);
    }

    protected void onChange(org.apache.shiro.session.Session session) {
        if(this.sessionDAO.readSession(session.getId()) != null){
            this.sessionDAO.update(session);
        }
    }

    protected void create(org.apache.shiro.session.Session session, SessionContext initData) {
        if(WebUtils.isWeb(initData)){
            HttpServletRequest request = (HttpServletRequest) WebUtils.getRequest(initData);
            if(this.isLoginRequest(request)){
                this.sessionDAO.create(session);
            }
        }
    }

    private boolean isLoginRequest(ServletRequest servletRequest){
        PatternMatcher pathMatcher = new AntPathMatcher();
        String requestURI = WebUtils.getPathWithinApplication(WebUtils.toHttp(servletRequest));
        for(String path : Configuration.SYSTEM_SHIRO_LOGIN_URL){
            if(pathMatcher.matches(path,requestURI)){
                return true;
            }
        }
        return false;
    }

    protected Serializable getSessionId(SessionKey sessionKey) {
        String token = null;
        if(WebUtils.isWeb(sessionKey)){
            HttpServletRequest httpServletRequest = (HttpServletRequest) WebUtils.getRequest(sessionKey);
            String authorization = httpServletRequest.getHeader(Configuration.SYSTEM_REQUEST_AUTHORIZATION);
            if(!StringUtils.isBlank(authorization)){
                String authorizationOriginal = new String(Base64.decodeBase64(httpServletRequest.getHeader(Configuration.SYSTEM_REQUEST_AUTHORIZATION)));
                if(authorizationOriginal.contains(":")){
                    String[] authorizationArray = authorizationOriginal.split(":");
                    if(!StringUtils.isBlank(authorizationArray[0]) && !isLoginRequest(httpServletRequest)){
                        token = authorizationArray[0];
                    }
                }
            }

        }
        return sessionKey.getSessionId() == null ? token : sessionKey.getSessionId();
    }

    protected org.apache.shiro.session.Session newSessionInstance(SessionContext context) {
        return this.getSessionFactory().createSession(context);
    }

    protected org.apache.shiro.session.Session retrieveSession(Serializable sessionId) throws UnknownSessionException {
        return sessionId == null ? null : this.sessionDAO.readSession(sessionId);
    }

    public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public SessionDAO getSessionDAO() {
        return this.sessionDAO;
    }

    public void setSessionDAO(SessionDAO sessionDAO) {
        this.sessionDAO = sessionDAO;
    }
}

(2)Session

package 项目名.module.shiro;

import org.apache.shiro.session.mgt.SimpleSession;

import java.util.UUID;

public class Session extends SimpleSession {

    public Session() {
        this.setId(UUID.randomUUID().toString().replace("-",""));
    }

    public Session(String host) {
        super(host);
        this.setId(UUID.randomUUID().toString().replace("-",""));
    }

}

(3)SimpleToken
Principal 是一个原始角色,之后的User、Role等等都是根据实际需求,继承自Principal 的

package项目名.module.shiro;

import org.apache.shiro.authc.AuthenticationToken;

import java.io.Serializable;

public class SimpleToken implements AuthenticationToken {

    private Principal principal;

    private String credentials;

    public SimpleToken(Principal principal, String credentials){
        this.principal = principal;
        this.credentials = credentials;
    }


    @Override
    public Object getPrincipal() {
        return this.principal;
    }

    @Override
    public Object getCredentials() {
        return this.credentials;
    }

    public static class Principal implements Serializable {
        private Integer id;

        public Integer getId() {
            return id;
        }

        @Override
        public String toString() {
            return "Principal{" +
                    "id=" + id +
                    '}';
        }
    }

    public static class User extends Principal implements Serializable {

        public User(Integer id) {
            super.id = id;
        }

        @Override
        public String toString() {
            return "User{" +
                    "id=" + super.getId() +
                    '}';
        }
    }

    public static class Technician extends Principal implements Serializable {

        public Technician(Integer id) {
            super.id = id;
        }

        @Override
        public String toString() {
            return "Technician{" +
                    "id=" + super.getId() +
                    '}';
        }
    }

    public static class Role extends Principal implements Serializable {
        public Role(Integer id) { super.id = id; }

        @Override
        public String toString() {
            return "Role{"+"id="+super.getId()+"}";
        }
    }


    public static class Admin extends Principal implements Serializable{
        public Admin(Integer id) {
            super.id=id;
        }

        @Override
        public String toString() {
            return "Admin{"+"id="+super.getId()+"}";
        }
    }

    public static class Shop extends Principal implements Serializable{
        public Shop(Integer id) {
            super.id=id;
        }

        @Override
        public String toString() {
            return "Shop{"+"id="+super.getId()+"}";
        }
    }
}

(4)Configuration配置redis参数

    // 超级管理员
    public static final String SYSTEM_SESSION_ADMIN_MAPPING_NAMESPACE = "pedicure:session:manager:admin:mapping";
    // 商家
    public static final String SYSTEM_SESSION_SHOP_MAPPING_NAMESPACE = "pedicure:session:manager:shop:mapping";
    //登录的路径  {}中的是所有登录路径的String数组
    public static final String[] SYSTEM_SHIRO_LOGIN_URL = new String[]{"/role/login","/technician/login"};
    //session路径
    public static final String SYSTEM_SESSION_NAMESPACE = "pedicure:session:manager";

5.在module>shiro下,新建AuthorizingRealm
个人认为这个部分很重要,因为这里是你获取角色信息的地方,后续一系列的权限操作,都从这里开始
因此,在第一处注释处,要将getPrimaryPrincipal()得到的数据转化为SimpleToken中对应的自定义类型,比如“SimpleToken.Admin”就是SimpleToken中的Admin角色

package 项目名.module.shiro;

import 项目名.exception.SystemException;
import 项目名.mapper.RoleMapper;
import 项目名.pojo.Role;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

public class AuthorizingRealm extends org.apache.shiro.realm.AuthorizingRealm {
    @Autowired
    private RoleMapper roleMapper;

    public AuthorizingRealm() {
        super.setAuthenticationTokenClass(SimpleToken.class);
    }

    @Override
   public String getName() {
        return "customRealm";
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        int loginId = -1;
        if(principals.getPrimaryPrincipal() instanceof SimpleToken.Admin){
            // 从 principals获取主身份信息
            loginId = ((SimpleToken.Admin) principals.getPrimaryPrincipal()).getId();
        }else if(principals.getPrimaryPrincipal() instanceof SimpleToken.Shop){
            loginId = ((SimpleToken.Shop) principals.getPrimaryPrincipal()).getId();
        }
        System.out.println("loginId:" + loginId);
        // 从数据库获取到权限数据
        Role role = roleMapper.selectByPrimaryKey(loginId);
        // 根据身份信息获取权限信息(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型)
        simpleAuthorizationInfo.addRole(role.getRoleName());
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws SystemException {
        AuthenticationInfo info = new SimpleAuthenticationInfo(authenticationToken.getPrincipal(), authenticationToken.getCredentials(), super.getName());
        return info;
    }

}

6.在module>shiro下,新建SubjectDAO
这里是从redis中拿到对应角色的mappingKey ,它的作用相当于id,是唯一识别标识,因此继承自 principal 的 SimpleToken.Admin 要和 Configuration中的参数路径一一对应

package net.$51zhiyuan.dev.yunzuliao_backStage.module.shiro;

import 项目名.exception.SystemException;
import 项目名.module.Configuration;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

public class SubjectDAO extends DefaultSubjectDAO {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    protected void saveToSession(Subject subject) {
        Session session = subject.getSession(false);
        if (session == null && !CollectionUtils.isEmpty(subject.getPrincipals())) {
            session = subject.getSession();
            String mappingKey;
            SimpleToken.Principal principal = (SimpleToken.Principal) subject.getPrincipal();
            if(principal instanceof SimpleToken.Admin){
                mappingKey = Configuration.SYSTEM_SESSION_ADMIN_MAPPING_NAMESPACE;
            }else if(principal instanceof SimpleToken.Shop){
                mappingKey = Configuration.SYSTEM_SESSION_SHOP_MAPPING_NAMESPACE;
            }else {
                throw new SystemException("未知的角色信息");
            }
            mappingKey = String.format("%s:%s", mappingKey,((SimpleToken.Principal) subject.getPrincipal()).getId());

            String historySessionId = (String) this.redisTemplate.opsForValue().get(mappingKey);
            System.out.println("his:"+historySessionId);
            System.out.println("sessionId:"+session.getId());
            if(!StringUtils.isBlank(historySessionId) && !session.getId().equals(historySessionId)){
                String sessionKey = String.format("%s:%s",Configuration.SYSTEM_SESSION_NAMESPACE,historySessionId);
                System.out.println(sessionKey);
                this.redisTemplate.delete(sessionKey);
            }
            this.redisTemplate.opsForValue().set(mappingKey,session.getId());
        }
        super.saveToSession(subject);
    }


}


7.在module>shiro>aop下,新建AuthenticatedAnnotationMethodInterceptor

package 项目名.module.shiro.aop;

import org.apache.shiro.aop.AnnotationResolver;
import org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor;

public class AuthenticatedAnnotationMethodInterceptor extends AuthorizingAnnotationMethodInterceptor {

    public AuthenticatedAnnotationMethodInterceptor(){
        super(new AuthenticatedAnnotationHandler());
    }

    public AuthenticatedAnnotationMethodInterceptor(AnnotationResolver resolver){
        super(new AuthenticatedAnnotationHandler(),resolver);
    }
}

8.配置applicationContext-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

	<!-- 配置 读取properties文件 jdbc.properties -->
	<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true"/>


	<!-- 配置 读取properties文件 redis.properties -->
	<context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/>

	<!-- 配置 读取properties文件 redis.properties -->
	<context:property-placeholder location="classpath:config/global.properties" ignore-unresolvable="true"/>
	
	<!-- 配置 数据源 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<!-- 初始化连接大小 -->
		<property name="initialSize" value="${jdbc.initialSize}"></property>
		<!-- 连接池最大数量 -->
		<property name="maxActive" value="${jdbc.maxActive}"></property>
		<!-- 连接池最大空闲 -->
		<property name="maxIdle" value="${jdbc.maxIdle}"></property>
		<!-- 连接池最小空闲 -->
		<property name="minIdle" value="${jdbc.minIdle}"></property>
		<!-- 获取连接最大等待时间 -->
		<property name="maxWait" value="${jdbc.maxWait}"></property>
	</bean>
	
	<!-- 配置SqlSessionFactory -->
	<bean class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 设置MyBatis核心配置文件 -->
		<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
		<property name="mapperLocations" value="classpath:项目名/mapper/xml/*.xml" />
		<!-- 设置数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 配置通知 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager" >
	<tx:attributes>
		<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="insert*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="list*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="check*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
	</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut expression="execution(* *.*ServiceImpl.*(..))" id="txPc"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
	</aop:config>
	
	<!-- 配置Mapper扫描 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 设置Mapper扫描包 -->
		<property name="basePackage" value="项目名.mapper" />
	</bean>

<!-- 设置jedis -->
	<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
		<property name="hostName" value="${redis.hostName}" />
		<property name="port" value="${redis.port}" />
		<property name="timeout" value="${redis.timeout}" />
		<property name="database" value="${redis.database}" />
		<property name="password" value="${redis.password}" />
		<property name="usePool" value="${redis.usePool}" />
		<property name="poolConfig">
			<bean class="redis.clients.jedis.JedisPoolConfig">
				<property name="maxTotal" value="10" />
				<property name="maxIdle" value="10" />
				<property name="minIdle" value="2" />
				<property name="maxWaitMillis" value="15000" />
				<property name="minEvictableIdleTimeMillis" value="300000" />
				<property name="numTestsPerEvictionRun" value="3" />
				<property name="timeBetweenEvictionRunsMillis" value="60000" />
				<property name="testOnBorrow" value="true" />
				<property name="testOnReturn" value="true" />
				<property name="testWhileIdle" value="true" />
			</bean>
		</property>
	</bean>

	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="jedisConnectionFactory" />
		<property name="keySerializer">
			<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="hashKeySerializer">
			<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="valueSerializer">
			<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
		</property>
		<property name="hashValueSerializer">
			<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
		</property>
	</bean>

	<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
		<constructor-arg ref="redisTemplate" />
		<property name="defaultExpiration" value="0" />
	</bean>




</beans>

9.在module>shiro下,新建SessionDAO

package 项目名.module.shiro;

import 项目名.module.Configuration;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class SessionDAO extends AbstractSessionDAO {

    private String sessionNamespace = Configuration.SYSTEM_SESSION_NAMESPACE;

    private RedisTemplate<Serializable,Object> redisTemplate;

    private Session storeSession(Serializable id, Session session) {
        if (id == null) {
            throw new NullPointerException("id argument cannot be null.");
        }
        this.redisTemplate.opsForValue().set(String.format("%s:%s",this.sessionNamespace,id),session);
        return session;
    }


    @Override
    protected Serializable doCreate(Session session) {
        this.storeSession(session.getId(), session);
        return session.getId();
    }

    @Override
    public Session readSession(Serializable sessionId) throws UnknownSessionException {
        return this.doReadSession(sessionId);
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        ValueOperations valueOperations = this.redisTemplate.opsForValue();
        Session session = (Session) valueOperations.get(String.format("%s:%s",this.sessionNamespace,sessionId));
        return session;
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
        this.storeSession(session.getId(), session);
    }

    @Override
    public void delete(Session session) {
        if (session == null) {
            throw new NullPointerException("session argument cannot be null.");
        }
        Serializable id = session.getId();
        if (id != null) {
            this.redisTemplate.delete(String.format("%s:%s",this.sessionNamespace,id));
        }
    }

    @Override
    public Collection<Session> getActiveSessions() {
        HashOperations hashOperations = this.redisTemplate.opsForHash();
        List<Session> sessions = hashOperations.values(this.sessionNamespace);
        Collection<Session> values = sessions;
        if (CollectionUtils.isEmpty(values)) {
            return Collections.emptySet();
        } else {
            return Collections.unmodifiableCollection(values);
        }
    }

    public String getSessionNamespace() {
        return sessionNamespace;
    }

    public void setSessionNamespace(String sessionNamespace) {
        this.sessionNamespace = sessionNamespace;
    }

    public RedisTemplate<Serializable, Object> getRedisTemplate() {
        return redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate<Serializable, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
}

到此,框架搭建基本完成,但是在运行的时候出现了一个bug

No bean named 'shirofilter' available

这是因为在web.xml中,没有找到springmvc.xml这个路径,从而无法加载,因此需要在web.xml中配置

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/springmvc.xml</param-value>
  </context-param>

欢迎大家补充改正
ps:在这里插入图片描述

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值