<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
    <!-- Spring的配置文件，主要配置和业务逻辑有关的 -->
    <!-- 数据源，事务控制 -->
    <context:component-scan base-package="lingtao.net">
        <!-- 只不扫描控制器，其他都扫描-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- ================配置数据源:c3p0================ -->
    <context:property-placeholder location="classpath:dbconfig.properties"/>

    <bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!-- ===============配置和mybatis的整合================= -->

    <bean
            id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据源 -->
        <property name="dataSource" ref="pooledDataSource"></property>

        <!-- 加载mybatis的配置文件 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>

        <!-- 指定mybatis的mapper文件的位置 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
    </bean>

    <!-- 使用扫描器 :扫描mapper接口，将mybatis接口的实现加入到ioc容器中
        mapper接口的名字就是类名的首字母小写-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定接口的所在包,加入到ioc容器中 -->
        <property name="basePackage" value="lingtao.net.dao,lingtao.net.mapper"></property>
    </bean>

    <!-- 配置一个可以执行批量的sqlSession -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
        <constructor-arg name="executorType" value="SIMPLE"></constructor-arg>
    </bean>
    <!-- =================配置事务控制================= -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 控制住数据源 -->
        <property name="dataSource" ref="pooledDataSource"></property>
    </bean>

    <!-- 开启基于注解的事务，使用xml配置形式的事务(比较重要的都是使用配置) -->
    <aop:config>
        <!-- 切入点表达式 -->
        <aop:pointcut expression="execution(* lingtao.net.service..*(..))" id="txPoint"/>
        <!-- 配置事务增强 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
    </aop:config>

    <!-- 配置事务增强-事务如何切入 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 所有的方法都是事务方法 -->
            <tx:method name="*" propagation="REQUIRED"/>
            <!-- 以get开头的所有方法:查询使用只读 -->
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- Spring配置文件的核心:(数据源、与mybatis的整合、事务控制) -->

    <!-- 自定义Realm -->
    <bean id="shiroRealm" class="lingtao.net.realm.ShiroRealm"></bean>

    <!-- session管理器（用户操作session） -->
    <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO"></bean>
    <!-- 配置shiro session 的一个管理器 -->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <property name="sessionValidationSchedulerEnabled" value="true"/>
        <property name="sessionDAO" ref="sessionDAO"></property>
    </bean>

    <!-- shiro安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- 自定义的realm -->
        <property name="realm" ref="shiroRealm"/>
        <!-- shiro session管理器 -->
        <property name="sessionManager" ref="sessionManager"></property>
    </bean>

    <!-- 配置shiro的一些拦截规则，id必须和web.xml中的 shiro 拦截器名一致 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 身份认证失败，则跳转到登录页面的配置 -->
        <property name="loginUrl" value="/login.jsp"/>
        <!-- 认证通过会 要跳转 的页面 -->
        <property name="successUrl" value="/main.jsp"></property>
        <!-- 权限认证失败，则跳转到指定页面 -->
        <property name="unauthorizedUrl" value="/refuse"/>  <!-- 登录后访问没有权限的页面后跳转的页面 -->
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <property name="filterChainDefinitions">
            <value>
                <!-- 注意：规则是有顺序的，从上到下，拦截范围必须是从小到大的 -->
                <!--  url = 拦截规则（anon为匿名，authc为要登录后，才能访问，logout登出过滤） -->
                /login = anon
                /logout = logout
                /SysUser/**=anon
                /static/** = anon
                /img/** = anon
                /abc/** = anon
                /views/** = authc
                /js/** = authc
                /**= authc
            </value>
        </property>
    </bean>

    <!-- =================配置Redis================= -->
    <!-- Redis连接池配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="100"/>
        <property name="maxIdle" value="20"/>
        <property name="maxWaitMillis" value="10000"/>
        <property name="testOnBorrow" value="true"/>
    </bean>

    <!-- Redis连接工厂 -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="localhost"/>
        <property name="port" value="6379"/>
        <property name="password" value=""/>
        <property name="database" value="0"/>
        <property name="poolConfig" ref="jedisPoolConfig"/>
    </bean>

    <!-- Redis模板 -->
    <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="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
    </bean>

    <!-- StringRedisTemplate（可选，用于String类型操作） -->
    <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory"/>
    </bean>

    <!-- Redis缓存管理器 -->
    <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="redisOperations" ref="redisTemplate"/>
        <property name="defaultExpiration" value="3600"/>
    </bean>
</beans>
