spring+hibernate+shiro+Ehcache 项目分享

来源:互联网 发布:爱伦坡 乌鸦 知乎 编辑:程序博客网 时间:2024/06/10 05:53

         这篇文章,我将 把一个 spring+hibernate+shiro+Ehcache 完整的集成流程记录下来,源码亦将分享出来(项目源码地址: http://download.csdn.net/download/u011998835/10038869   点击打开链接)。但是好像csdn传资源必须要指定积分的,所以我不得已选择了2分。但这里不要在意细节了。我主要是记录,遇到问题和开发心得。

     那么我们开始使用工具编写项目了。

     




因为DAdmin这个项目我已经新建过了,所以接下来有些演示 就用DDAdmin来替代了。


先打开File,找到Project Structure 先设置一些东西


新建java文件夹

指定java作为java代码的源码目录


新建test目录

指定成为测试目录



不要忘了设定jdk7了,默认是用jdk5编译的,哪怕你提供了jdk环境,但编译用jdk5,那么有些泛型新写法就不能使用了。

然后OK或者apply


然后看到的项目结构如下。


写配置pom.xml吧(这个 过程 就是 在把相关的jar包导入)

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.dashuai</groupId>    <artifactId>DAdmin</artifactId>    <packaging>war</packaging>    <version>1.0-SNAPSHOT</version>    <properties>        <java_version>1.7</java_version>        <java-encoding_version>UTF-8</java-encoding_version>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <spring_version>4.3.12.RELEASE</spring_version>        <hibernate_version>4.3.11.Final</hibernate_version>        <shiro_version>1.3.2</shiro_version>        <mysql_connector_version>5.1.44</mysql_connector_version>        <druid-version>1.0.31</druid-version>    </properties>    <repositories>        <repository>            <id>alimaven</id>            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>            <releases>                <enabled>true</enabled>            </releases>            <snapshots>                <enabled>true</enabled>            </snapshots>        </repository>    </repositories>    <pluginRepositories>        <pluginRepository>            <id>alimaven</id>            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>            <releases>                <enabled>true</enabled>            </releases>            <snapshots>                <enabled>true</enabled>            </snapshots>        </pluginRepository>    </pluginRepositories>    <dependencies>        <!-- Junit 4 -->        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.12</version>            <scope>test</scope>        </dependency>        <!-- Common libs start -->        <dependency>            <groupId>commons-logging</groupId>            <artifactId>commons-logging</artifactId>            <version>1.1.1</version>        </dependency>        <dependency>            <groupId>commons-io</groupId>            <artifactId>commons-io</artifactId>            <version>2.4</version>        </dependency>        <dependency>            <groupId>commons-fileupload</groupId>            <artifactId>commons-fileupload</artifactId>            <version>1.2.2</version>        </dependency>        <dependency>            <groupId>org.apache.commons</groupId>            <artifactId>commons-lang3</artifactId>            <version>3.4</version>        </dependency>        <!-- Common libs end -->        <!--启动CGlib -->        <dependency>            <groupId>cglib</groupId>            <artifactId>cglib-nodep</artifactId>            <version>2.2.2</version>        </dependency>        <!-- log日志  start  -->        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-log4j12</artifactId>            <version>1.7.25</version>        </dependency>        <!-- log日志  end  -->        <!-- Spring相关jar包  start -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-core</artifactId>            <version>${spring_version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-beans</artifactId>            <version>${spring_version}</version>        </dependency>        <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-orm</artifactId>            <version>${spring_version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-expression</artifactId>            <version>${spring_version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-jdbc</artifactId>            <version>${spring_version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-aop</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-webmvc</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-aspects</artifactId>            <version>${spring_version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-tx</artifactId>            <version>${spring_version}</version>        </dependency>        <dependency>            <groupId>org.aspectj</groupId>            <artifactId>aspectjrt</artifactId>            <version>1.8.11</version>        </dependency>        <dependency>            <groupId>org.aspectj</groupId>            <artifactId>aspectjweaver</artifactId>            <version>1.8.11</version>        </dependency>        <dependency>            <groupId>com.fasterxml.jackson.core</groupId>            <artifactId>jackson-core</artifactId>            <version>2.9.1</version>        </dependency>        <dependency>            <groupId>com.fasterxml.jackson.core</groupId>            <artifactId>jackson-databind</artifactId>            <version>2.9.1</version>        </dependency>        <!-- Spring相关jar包  end -->        <!--mysql 驱动包 -->        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>${mysql_connector_version}</version>        </dependency>        <!-- 数据源 druid -->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid</artifactId>            <version>${druid-version}</version>        </dependency>        <!--json GSON 包 -->        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->        <dependency>            <groupId>com.google.code.gson</groupId>            <artifactId>gson</artifactId>            <version>2.5</version>        </dependency>        <!-- jsp,servlet,jstl -->        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>javax.servlet-api</artifactId>            <version>3.0.1</version>            <scope>provided</scope>        </dependency>        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>jsp-api</artifactId>            <version>2.0</version>            <scope>provided</scope>        </dependency>        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>jstl</artifactId>            <version>1.2</version>        </dependency>        <!--工具包,加密算法 -->        <dependency>            <groupId>commons-codec</groupId>            <artifactId>commons-codec</artifactId>            <version>1.4</version>        </dependency>        <!-- Hibernate  start -->        <dependency>            <groupId>org.hibernate</groupId>            <artifactId>hibernate-core</artifactId>            <version>${hibernate_version}</version>        </dependency>        <dependency>            <groupId>org.hibernate</groupId>            <artifactId>hibernate-commons-annotations</artifactId>            <version>3.2.0.Final</version>        </dependency>        <dependency>            <groupId>org.hibernate</groupId>            <artifactId>hibernate-ehcache</artifactId>            <version>${hibernate_version}</version>        </dependency>        <dependency>            <groupId>org.hibernate.javax.persistence</groupId>            <artifactId>hibernate-jpa-2.0-api</artifactId>            <version>1.0.1.Final</version>        </dependency>        <!-- Hibernate END -->        <!--Hibernate与spring 集成所依赖的 -->        <dependency>            <groupId>org.javassist</groupId>            <artifactId>javassist</artifactId>            <version>3.20.0-GA</version>        </dependency>      <!-- shiro -->        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-core</artifactId>            <version>${shiro_version}</version>        </dependency>        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-ehcache</artifactId>            <version>${shiro_version}</version>        </dependency>        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-web</artifactId>            <version>${shiro_version}</version>        </dependency>        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-spring</artifactId>            <version>${shiro_version}</version>        </dependency>    </dependencies>    <build>        <finalName>DAdmin</finalName>        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-war-plugin</artifactId>                <version>3.2.0</version>            </plugin>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <version>3.7.0</version>                <configuration>                    <source>1.7</source>                    <target>1.7</target>                    <skip>true</skip>                </configuration>            </plugin>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-resources-plugin</artifactId>                <version>3.0.0</version>                <configuration>                    <encoding>UTF-8</encoding>                </configuration>            </plugin>            <plugin>                <groupId>org.apache.tomcat.maven</groupId>                <artifactId>tomcat7-maven-plugin</artifactId>                <version>2.2</version>                <configuration>                    <path>/</path>                    <charset>UTF-8</charset>                    <uriEncoding>UTF-8</uriEncoding>                </configuration>            </plugin>        </plugins>    </build></project>

先看一下未来呈现的项目结构


我们一样一样的来写。

先新建java的文件夹,就是各种package。

然后新建resource目录下的文件,暂时先新建着空文件。然后再填东西。


好,接下来,我们先从web.xml入手。

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xmlns="http://java.sun.com/xml/ns/javaee"         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"         version="3.0">  <display-name>Spring-Hibernate Web Application</display-name>  <welcome-file-list>    <welcome-file></welcome-file>  </welcome-file-list><!--暂不指定欢迎页面-->  <context-param>    <param-name>contextConfigLocation</param-name>    <param-value>          classpath:spring-shiro.xml,          classpath:spring/applicationContext.xml    </param-value>  </context-param>  <!--spring与shiro配置的spring-shiro.xml一定要指定,不然shiro不一定发挥作用-->  <!-- ////////// Hibernate4 延迟加载策略//////////////// -->  <filter>    <filter-name>openSessionInViewFilter</filter-name>    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>    <init-param>      <param-name>singleSession</param-name>      <param-value>true</param-value>    </init-param>    <init-param>      <param-name>sessionFactoryBeanName</param-name>      <param-value>sessionFactory</param-value>    </init-param>  </filter>  <filter-mapping>    <filter-name>openSessionInViewFilter</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping>  <!-- 防止发生java.beans.Introspector内存泄露,应将它配置在ContextLoaderListener的前面 -->  <listener>    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>  </listener>  <listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  </listener>  <listener>    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  </listener>  <!-- /////////////Spring MVC支持配置 ///////////////-->  <servlet>    <servlet-name>spring</servlet-name>    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    <init-param>      <param-name>contextConfigLocation</param-name>      <param-value>classpath:spring/applicationContext-servlet.xml</param-value>    </init-param>    <load-on-startup>1</load-on-startup>  </servlet>  <servlet-mapping>    <servlet-name>spring</servlet-name>    <url-pattern>/</url-pattern>  </servlet-mapping>  <!-- /////////////Spring 解决乱码问题/////////////////////// -->  <filter>    <filter-name>SpringEncodingFilter</filter-name>    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>    <init-param>      <param-name>encoding</param-name>      <param-value>UTF-8</param-value>    </init-param>    <init-param>      <param-name>forceEncoding</param-name>      <param-value>true</param-value>    </init-param>  </filter>  <filter-mapping>    <filter-name>SpringEncodingFilter</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping>  <!-- //////////////阿里巴巴数据连接池 Druid的监控/////////////////// -->  <filter>    <filter-name>druidWebStatFilter</filter-name>    <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>    <init-param>      <param-name>exclusions</param-name>      <param-value>        /css/*,/style/*,/js/*,*.js,*.css,/druid*,/attached/*,*.jsp      </param-value>    </init-param>    <init-param>      <param-name>principalSessionName</param-name>      <param-value>sessionUser</param-value>    </init-param>    <init-param>      <param-name>profileEnable</param-name>      <param-value>true</param-value>    </init-param>  </filter>  <filter-mapping>    <filter-name>druidWebStatFilter</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping>  <!-- //////////druid监控页面,使用${pageContext.request.contextPath}/druid/index.html访问///////// -->  <servlet>    <servlet-name>druidStatView</servlet-name>    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>  </servlet>  <servlet-mapping>    <servlet-name>druidStatView</servlet-name>    <url-pattern>/druid/*</url-pattern>  </servlet-mapping>  <!-- shiroFilter 不能放在 Hibernate的filter之前,或者druid之前,建议放在最后面-->    <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>    <session-config>      <session-timeout>120</session-timeout>    </session-config></web-app>


ehcache.xml

<ehcache name="shiro_ehcache" updateCheck="false">    <diskStore path="../DAdmin_Ehcache"/>    <!-- hibernate ehcache 和 shiro_ehcache 必须放在同一个xml中配置      不要分开放,不然只会有一个生效。name="shiro_ehcache",可以不用配置。(我当时分开使用了)     -->    <!-- hibernate ehcache-->    <defaultCache            maxElementsInMemory="10000"            eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"            overflowToDisk="true"            maxElementsOnDisk="10000000"            diskPersistent="false"            diskExpiryThreadIntervalSeconds="120"            memoryStoreEvictionPolicy="LRU"    />    <cache name="org.hibernate.cache.spi.UpdateTimestampsCache"           maxElementsInMemory="5000"           eternal="true"           overflowToDisk="true"/>    <cache name="org.hibernate.cache.internal.StandardQueryCache"           maxElementsInMemory="10000"           eternal="false"           timeToLiveSeconds="120"           overflowToDisk="true"/>    <!-- shiro ehcache-->    <!-- 登录记录缓存 锁定10分钟 -->    <cache name="passwordRetryCache"           maxElementsInMemory="2000" eternal="false"           timeToIdleSeconds="3600"           timeToLiveSeconds="0"           overflowToDisk="false"           statistics="true">    </cache>    <cache name="authorizationCache"           maxElementsInMemory="2000"           eternal="false"           timeToIdleSeconds="3600"           timeToLiveSeconds="0"           overflowToDisk="false"           statistics="true">    </cache>    <cache name="authenticationCache"           maxElementsInMemory="2000"           eternal="false"           timeToIdleSeconds="3600"           timeToLiveSeconds="0"           overflowToDisk="false"           statistics="true">    </cache>    <cache name="shiro-activeSessionCache"           maxElementsInMemory="2000"           eternal="false"           timeToIdleSeconds="3600"           timeToLiveSeconds="0"           overflowToDisk="false"           statistics="true">    </cache>    <cache name="shiro_cache"           maxElementsInMemory="2000"           eternal="false"           timeToIdleSeconds="0"           timeToLiveSeconds="0"           maxElementsOnDisk="0"           overflowToDisk="true"           memoryStoreEvictionPolicy="FIFO"           statistics="true">    </cache></ehcache>


log4j.properties:

log4j.rootLogger=INFO,CONSOLE,DAILY_ALL#console loglog4j.appender.CONSOLE=org.apache.log4j.ConsoleAppenderlog4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayoutlog4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l - %m%nlog4j.appender.CONSOLE.Target=System.out#all loglog4j.appender.DAILY_ALL=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.DAILY_ALL.layout=org.apache.log4j.PatternLayoutlog4j.appender.DAILY_ALL.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l - %m%nlog4j.appender.DAILY_ALL.File=../logs/DAdmin.log# hibernate的log配置#log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=TRACE#log4j.loggerorg.hibernate.type.descriptor.sql.BasicExtractor=TRACE#log4j.logger.org.hibernate.engine.QueryParameters=DEBUG#log4j.logger.org.hibernate.engine.query.HQLQueryPlan=DEBUG#log4j.logger.org.hibernate.cache=DEBUG

database.properties

hibernate.show_sql=truehibernate.format_sql=truehibernate.dialect=org.hibernate.dialect.MySQLDialectdriverClassName=com.mysql.jdbc.Driverjdbc_url=jdbc\:mysql\://localhost\:3306/dadmin?useUnicode\=true&characterEncoding\=UTF-8jdbc_username=rootjdbc_password=123456hibernate.hbm2ddl.auto=updatehibernate.query.substitutions=true 1, false 0hibernate.default_batch_fetch_size=16hibernate.max_fetch_depth=2hibernate.generate_statistics=falsehibernate.enable_lazy_load_no_trans=trueinitialSize=3maxActive=50minIdle=1maxWait=60000validationQuery=SELECT 1testOnBorrow=falsetestOnReturn=falsetestWhileIdle=truetimeBetweenEvictionRunsMillis=60000minEvictableIdleTimeMillis=25200000removeAbandoned=falseremoveAbandonedTimeout=1800logAbandoned=truefilters=mergeStat

applicationContext.xml

<?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:aop="http://www.springframework.org/schema/aop"   xmlns:tx="http://www.springframework.org/schema/tx"   xmlns:context="http://www.springframework.org/schema/context"   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/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd    http://www.springframework.org/schema/aop    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"><context:component-scan base-package="com.dashuai.service,com.dashuai.dao,com.dashuai.shiro"/><!-- //////////强制启用CGliB 替换JDK的动态代理 在反射动态生成时 效率更高/////////// --><aop:aspectj-autoproxy proxy-target-class="true" /><!-- 读取数据库基本连接配置 --><context:property-placeholder location="classpath:database.properties" /><!-- 阿里巴巴的Druid数据库连接池日志过滤 下面 baseDataSource会使用到的 --><bean id="statFilter" class="com.alibaba.druid.filter.stat.StatFilter"  lazy-init="true"><property name="logSlowSql" value="true" /><property name="mergeSql" value="true" /></bean><!-- 数据库连接池的配置base dataSource --><bean name="baseDataSource" class="com.alibaba.druid.pool.DruidDataSource"  destroy-method="close"><!-- 初始化连接大小 --><property name="initialSize" value="${initialSize}" /><!-- 连接池最大使用连接数量 --><property name="maxActive" value="${maxActive}" /><!-- 连接池最小空闲 --><property name="minIdle" value="${minIdle}" /><!-- 获取连接最大等待时间 --><property name="maxWait" value="${maxWait}" /><property name="validationQuery" value="${validationQuery}" /><property name="testOnBorrow" value="${testOnBorrow}" /><property name="testOnReturn" value="${testOnReturn}" /><property name="testWhileIdle" value="${testWhileIdle}" /><!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --><property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" /><!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --><property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" /><!-- 打开removeAbandoned功能 --><!-- 配置removeAbandoned对性能会有一些影响,建议怀疑存在泄漏之后再打开。 在上面的配置中,如果连接超过30分钟未关闭, 就会被强行回收,并且日志记录连接申请时的调用堆栈。 --><property name="removeAbandoned" value="${removeAbandoned}" /><!-- 1800秒,也就是30分钟 --><property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /><!-- 关闭abanded连接时输出错误日志 --><property name="logAbandoned" value="${logAbandoned}" /><!-- 合并多个DruidDataSource的监控数据 --><property name="useGlobalDataSourceStat" value="true" /><property name="proxyFilters"><list><ref bean="statFilter" /></list></property></bean><bean name="master-dataSource" parent="baseDataSource"  init-method="init"><property name="name" value="master" /><property name="driverClassName" value="${driverClassName}" /><property name="url" value="${jdbc_url}" /><property name="username" value="${jdbc_username}" /><property name="password" value="${jdbc_password}" /><property name="filters" value="${filters}" /></bean><!-- 配置sessionFactory 并配置二级缓存 --><bean id="sessionFactory"  class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><property name="dataSource" ref="master-dataSource" /><property name="packagesToScan"><list><value>com.dashuai.entity</value></list></property><property name="hibernateProperties"><props><prop key="javax.persistence.validation.mode">none</prop><prop key="hibernate.dialect">${hibernate.dialect}</prop><prop key="hibernate.show_sql">${hibernate.show_sql}</prop><prop key="hibernate.format_sql">${hibernate.format_sql}</prop><prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop><prop key="hibernate.query.substitutions">${hibernate.query.substitutions}</prop><prop key="hibernate.default_batch_fetch_size">${hibernate.default_batch_fetch_size}</prop><prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop><prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop><prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop><prop key="hibernate.enable_lazy_load_no_trans">${hibernate.enable_lazy_load_no_trans}</prop><prop key="hibernate.cache.provider_configuration_file_resource_path">classpath:ehcache.xml</prop><!-- 开启查询缓存 --><prop key="hibernate.cache.use_query_cache">true</prop><!-- 开启二级缓存 --><prop key="hibernate.cache.use_second_level_cache">true</prop><!-- 高速缓存提供程序 --><!-- 由于spring也使用了Ehcache, 保证双方都使用同一个缓存管理器 --><prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop></props></property></bean><bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"><property name="configLocation"><value>classpath:ehcache.xml</value></property><!-- 由于hibernate也使用了Ehcache, 保证双方都使用同一个缓存管理器 --><property name="shared" value="true"/></bean><!-- 开启事务 配置transactionManager --><bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"></property></bean><aop:config><aop:pointcut id="serviceMethod" expression="execution(* com.dashuai.service..*Impl.*(..))" /><aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" /></aop:config><!-- 设置所有方法都使用事务 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="get*" read-only="true" propagation="REQUIRED"/><!--之前是NOT_SUPPORT--><tx:method name="list*" read-only="true" propagation="REQUIRED"/><tx:method name="find*" read-only="true" propagation="REQUIRED"/><tx:method name="query*" read-only="true" propagation="REQUIRED"/><tx:method name="save*" propagation="REQUIRED"/><tx:method name="update*" propagation="REQUIRED"/><tx:method name="remove*" propagation="REQUIRED"/><tx:method name="add*" propagation="REQUIRED"/><!--默认其他方法都是REQUIRED--><tx:method name="*"/></tx:attributes></tx:advice></beans>  

applicationContext-servlet.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd 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">    <context:component-scan base-package="com.dashuai.controller"/><!-- 启用springmvc 的注解 --><mvc:annotation-driven />      <!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->      <bean id="mappingJacksonHttpMessageConverter"          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">          <property name="supportedMediaTypes">              <list>                  <value>text/html;charset=UTF-8</value>              </list>          </property>      </bean>  <!-- Model与View 的切换配置 --><bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>        <property name="contentType" value="text/html"/>        <property name="prefix" value="/WEB-INF/page/"/>        <property name="suffix" value=".jsp"/>    </bean><!-- 不拦截静态请求,如css,js --><mvc:default-servlet-handler />    <!-- 上传文件的配置 虽然本项目没有用到上传文件-->    <bean id="multipartResolver"          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">    </bean>    <mvc:view-controller path="/" view-name="front/index"/>    <mvc:view-controller path="/admin" view-name="admin/index"/>    <mvc:view-controller path="/admin/" view-name="admin/index"/>    <mvc:view-controller path="/user" view-name="front/user/index"/>    <mvc:view-controller path="/user/" view-name="front/user/index"/></beans>

spring-shiro.xml 这个复杂,我们一点点的看。 首先web.xml中配置了shiroFilter,所以一定有shiroFilter。然后就是spring和shiro集成之后的配置。

 <!-- 安全认证过滤器 -->   <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager" />        <property name="filters">            <map>                <!--自定义两个 登录 过滤器 第一个是 后台登陆认证过滤,第二个是前台 登录认证过滤 -->                <entry key="authsys" value-ref="systemAuthFilter"></entry>                <entry key="authnor" value-ref="normalAuthFilter"></entry>            </map>        </property>        <property name="filterChainDefinitions">            <value>                /res_admin/**=anon                /res_front/**=anon                /plugins/**=anon                /login.html=anon                /admin/login.*=anon                /admin/**=authsys                /user/**=authnor                /**=anon            </value>        </property>    </bean>

<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

这两个必须要有的。

然后就是一点点看了。
<!-- 定义Shiro安全管理配置 -->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="cacheManager" ref="memoryConstrainedCacheManager" />        <property name="authenticator" ref="defineModularRealmAuthenticator" />        <!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 -->        <!-- <property name="realm" ref="loginRealm"/> -->        <property name="realms"  >            <list>  <!-- 前台和后台的登录认证和权限授权认证 -->                 <ref bean="systemUserRealm" />                <ref bean="normalUserRealm"/>            </list>        </property>        <property name="sessionManager" ref="sessionManager" />        <property name="rememberMeManager" ref="rememberMeManager"/>    </bean>

 我们在接着看memoryConstrainedCacheManer。

<bean id="memoryConstrainedCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />
 <bean id="defineModularRealmAuthenticator" class="com.dashuai.shiro.DefautModularRealm">        <property name="definedRealms">            <map>                <entry key="systemAuthorizingRealm" value-ref="systemUserRealm" />                <entry key="normalAuthorizingRealm" value-ref="normalUserRealm" />            </map>        </property>        <property name="authenticationStrategy">            <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>        </property>    </bean> <!-- Realm 域 授权和认证的判断 -->    <bean id="systemUserRealm" class="com.dashuai.shiro.SystemUserRealm" />    <bean id="normalUserRealm" class="com.dashuai.shiro.NormalUserRealm" />

// 下面的java代码有的我注释了,是因为注释的代码 是需要根据不同需求自行编写的。

package com.dashuai.shiro;import org.apache.log4j.Logger;import org.apache.shiro.ShiroException;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.pam.ModularRealmAuthenticator;import org.apache.shiro.realm.Realm;import org.apache.shiro.util.CollectionUtils;import java.util.Collection;import java.util.Map;/** * 管理多个Realms */public class DefautModularRealm extends ModularRealmAuthenticator {    private static final Logger log = Logger.getLogger(DefautModularRealm.class);    private Map<String, Object> definedRealms;    /**     * 多个realm实现     */    @Override    protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {        return super.doMultiRealmAuthentication(realms, token);    }    /**     * 调用单个realm执行操作     */    @Override    protected AuthenticationInfo doSingleRealmAuthentication(Realm realm,AuthenticationToken token) {        log.info("DefautModularRealm doSingleRealmAuthentication Shiro 认证执行的第 3 步 " +token);        // 如果该realms不支持(不能验证)当前token        if (!realm.supports(token)) {            throw new ShiroException("token错误!");        }        AuthenticationInfo info = realm.getAuthenticationInfo(token);        log.info("DefautModularRealm doSingleRealmAuthentication info " +info);        return info;    }    /**     * 判断登录类型执行操作     */    @Override    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)throws AuthenticationException {        log.info("DefautModularRealm doAuthenticate Shiro 认证执行的第二步 ");        this.assertRealmsConfigured();        Realm realm = null;        CustomUsernamePasswordToken token = (CustomUsernamePasswordToken) authenticationToken;        //判断是否是后台用户        if (token.getLoginType()==CustomUsernamePasswordToken.LOGIN_ADMIN_TYPE) {            realm = (Realm) this.definedRealms.get("systemAuthorizingRealm");// 查看shiro的配置        }        else if (token.getLoginType()==CustomUsernamePasswordToken.LOGIN_FRONT_TYPE){            realm = (Realm) this.definedRealms.get("normalAuthorizingRealm");        }        log.info("doAuthenticate ==> "+realm);        return this.doSingleRealmAuthentication(realm, authenticationToken);    }    /**     * 判断realm是否为空     */    @Override    protected void assertRealmsConfigured() throws IllegalStateException {        this.definedRealms = this.getDefinedRealms();        if (CollectionUtils.isEmpty(this.definedRealms)) {            throw new ShiroException("值传递错误!");        }    }    public Map<String, Object> getDefinedRealms() {        return this.definedRealms;    }    public void setDefinedRealms(Map<String, Object> definedRealms) {        this.definedRealms = definedRealms;    }}

package com.dashuai.shiro;import org.apache.shiro.authc.UsernamePasswordToken;public class CustomUsernamePasswordToken extends UsernamePasswordToken {    public static final int LOGIN_ADMIN_TYPE=1000; // 后台    public static final int LOGIN_FRONT_TYPE=999;  // 前台    private int loginType; // 是否是系统后台用户还是前台用户    public int getLoginType() {        return loginType;    }    public void setLoginType(int loginType) {        this.loginType = loginType;    }    public CustomUsernamePasswordToken (String username, String password, boolean rememberMe, int loginType) {        super(username, password, rememberMe);        this.loginType = loginType;    }}

package com.dashuai.shiro;import com.dashuai.entity.system.SystemRole;import com.dashuai.entity.system.SystemUser;import com.dashuai.service.system.SystemRoleService;import com.dashuai.service.system.SystemUserRoleService;import com.dashuai.service.system.SystemUserService;import com.dashuai.util.ConstantUtil;//import org.apache.log4j.Logger;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.List;/** * 系统用户领域(后台用户操作) */public class SystemUserRealm extends AuthorizingRealm {    private static final Logger log = LoggerFactory.getLogger(SystemUserRealm.class);//    @Autowired//    private SystemUserService systemUserService;//    @Autowired//    private SystemRoleService systemRoleService;//    @Autowired//    private SystemUserRoleService systemUserRoleService;    /**     * Shiro权限认证,即权限授权     * 会进入授权方法一共有三种情况!     1、subject.hasRole(“admin”) 或 subject.isPermitted(“admin”):自己去调用这个是否有什么角色或者是否有什么权限的时候;     2、@RequiresRoles("admin") :在方法上加注解的时候;     3、[@shiro.hasPermission name = "admin"][/@shiro.hasPermission]:在页面上加shiro标签的时候,即进这个页面的时候扫描到有这个标签的时候。     */    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        log.info("SystemUserRealm Shiro请求授权 ");//        SystemUser systemUser = (SystemUser) SecurityUtils.getSubject().getPrincipal();//        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//        if(systemUser.getIsRoot().equals(ConstantUtil.IS_ROOT)){//            Collection<String> roles = new ArrayList<>();//            List<SystemRole> list = systemRoleService.getRootAllRoles();//            for(SystemRole systemRole:list){//                roles.add(systemRole.getRoleName());//            }//            info.addRoles(roles);//            log.info("SystemUserRealm Root 获取角色:{} ", Arrays.toString(info.getRoles().toArray()));//        }else{//            // 非root用户//            info.addRoles(systemUserRoleService.getAllRolesNameByUserId(systemUser.getUuid()));//            log.info("SystemUserRealm 后台 非ROOT 获取角色: {}", Arrays.toString(info.getRoles().toArray()));//        }//        return info;        return null;    }    /**     * 用户认证,登录认证     */    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws UnknownAccountException,IncorrectCredentialsException {//        log.info("SystemUserRealm doGetAuthenticationInfo Shiro 认证执行的第 4 步 " );//        CustomUsernamePasswordToken token = (CustomUsernamePasswordToken) authenticationToken;//        String username = token.getUsername();//        log.info("SystemUserRealm token username: {}, password: {}",username,new String(token.getPassword()));//        SystemUser systemUser = systemUserService.findUserByUsername(username);//        log.info("SystemUserRealm  systemUser: {}",systemUser);//        if(null==systemUser){//            throw new UnknownAccountException("SystemUserRealm 提示: 用户名不存在");//        }else if(!systemUser.getPassword().equals(new String(token.getPassword()))){//            throw new IncorrectCredentialsException("SystemUserRealm 提示:密码错误");//        }else if(systemUser.getStatus()==1){//            throw new AccountException("SystemUserRealm 提示: 账号被禁用");//        }else{//            return new SimpleAuthenticationInfo(systemUser,systemUser.getPassword(),getName());//        }        return null;    }}


package com.dashuai.shiro;import com.dashuai.entity.system.SystemUser;import com.dashuai.service.system.SystemUserRoleService;import com.dashuai.service.system.SystemUserService;import org.apache.log4j.Logger;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.springframework.beans.factory.annotation.Autowired;import java.util.Arrays;/** * 这里验证多个 Realm,前后台 分开验证 */public class NormalUserRealm extends AuthorizingRealm {    private static final Logger log = Logger            .getLogger(SystemUserRealm.class);//    @Autowired//    private SystemUserService systemUserService;//    @Autowired//    private SystemUserRoleService systemUserRoleService;    /**     * Shiro权限认证,即权限授权     *     * 关于多个Realm授权的问题。对于本项目配置而言是这样的。     * 本项目配置了两个: SystemUserRealm;NormalUserRealm;     *  它会按配置顺序执行。先SystemUserRealm;     *  如果在先SystemUserRealm发现了想要的角色或者权限,那么不执行NormalUserRealm;     *  如果在SystemUserRealm没有找到,那么继续执行NormalUserRealm中授权方法。     *     */    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        log.info("前台用户 NormalUserRealm Shiro 请求授权");//        SystemUser systemUser = (SystemUser) SecurityUtils.getSubject().getPrincipal();//        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//        info.addRoles(systemUserRoleService.getAllRolesNameByUserId(systemUser.getUuid()));//        log.info("NormalUserRealm 前台用户  获取角色: "+ Arrays.toString(info.getRoles().toArray()));//        return info;        return null;    }    /**     * 用户认证,登录认证     */    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        log.info("前台用户 NormalUserRealm 用户认证 Shiro 认证执行的第 4 步 " );//        CustomUsernamePasswordToken token = (CustomUsernamePasswordToken) authenticationToken;//        String username = token.getUsername();//        log.info("NormalUserRealm token username: "+username+", password: "+new String(token.getPassword()));//        SystemUser systemUser = systemUserService.findUserByUsername(username);//        log.info("NormalUserRealm  systemUser: "+systemUser);//        if(null==systemUser){//            throw new UnknownAccountException("NormalUserRealm tips: 用户名不存在");//        }else if(!systemUser.getPassword().equals(new String(token.getPassword()))){//            throw new IncorrectCredentialsException("NormalUserRealm tips: 密码错误,请重试");//        }else if(systemUser.getStatus()==1){//            throw new AccountException("NormalUserRealm tips: 账号被禁用");//        }else{//            return new SimpleAuthenticationInfo(systemUser,systemUser.getPassword(),getName());//        }        return null;    }}

这样 如下部分我们都看完了。
 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="memoryConstrainedCacheManager" />
        <property name="authenticator" ref="defineModularRealmAuthenticator" />
        <!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 -->
        <!-- <property name="realm" ref="loginRealm"/> -->
        <property name="realms"  >
            <list>  <!-- 前台和后台的登录认证和权限授权认证 --> 
                <ref bean="systemUserRealm" />
                <ref bean="normalUserRealm"/>
            </list>
        </property>
还有未看完的。
  <property name="sessionManager" ref="sessionManager" />
  <property name="rememberMeManager" ref="rememberMeManager"/>
现在看sessionManager

<bean id="sessionManager"          class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">        <property name="sessionDAO" ref="sessionDAO" />        <!-- 会话超时时间,单位:毫秒 -->        <property name="globalSessionTimeout" value="1800000" />        <!-- 定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话 -->        <property name="sessionValidationInterval" value="1800000" />        <property name="sessionValidationSchedulerEnabled" value="true" />        <property name="sessionIdCookie" ref="simpleCookie" />        <property name="sessionIdCookieEnabled" value="true" />    </bean>    <!-- 会话Cookie模板 -->    <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">        <constructor-arg name="name" value="shiro.sesssion"/>        <property name="path" value="/"/>    </bean><bean id="sessionDAO"          class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">        <property name="cacheManager" ref="shiroCacheManager" />    </bean> <!-- 定义授权缓存管理器 -->    <bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />    </bean>

<!-- rememberMe管理器 -->    <bean id="rememberMeManager"          class="org.apache.shiro.web.mgt.CookieRememberMeManager">        <property name="cipherKey"                  value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>        <property name="cookie" ref="rememberMeCookie"/>    </bean><bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">        <constructor-arg value="rememberMe"/>        <property name="httpOnly" value="true"/>        <property name="maxAge" value="604800"/><!-- 7天 -->    </bean>


最后在看shiroFilter 中 filter的配置:

<bean id="systemAuthFilter" class="com.dashuai.shiro.SystemFormAuthFilter" >        <property name="loginUrl" value="/admin/login.html" />        <property name="successUrl" value="/admin/index.html" />    </bean>    <bean id="normalAuthFilter" class="com.dashuai.shiro.NormalFormAuthFilter" >        <property name="loginUrl" value="/login.html" />        <property name="successUrl" value="/index.html" />    </bean>


package com.dashuai.shiro;import org.apache.log4j.Logger;import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;/** * 后台的用户登录认证 */public class SystemFormAuthFilter extends FormAuthenticationFilter {    private static final Logger log = Logger            .getLogger(SystemFormAuthFilter.class);    @Override    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {        log.info("SystemFormAuthFilter onAccessDenied Shiro 认证执行的第一步 ");        return super.onAccessDenied(request, response);    }    /*@Override    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {        log.info("SystemFormAuthFilter onLoginSuccess  ");        //我们登录成功之后要跳到一个固定的页面,通常是跳到首页,        WebUtils.getAndClearSavedRequest(request);        WebUtils.redirectToSavedRequest(request,response,"admin/index.html");        return super.onLoginSuccess(token, subject, request, response);    }*/}

package com.dashuai.shiro;import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;/** * 前台 用户登录的验证 */public class NormalFormAuthFilter extends FormAuthenticationFilter {    private static final Logger log = LoggerFactory            .getLogger(SystemFormAuthFilter.class);    @Override    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {        log.info("NormalFormAuthFilter onAccessDenied Shiro 前台 认证执行的第一步 ");        return super.onAccessDenied(request, response);    }}

这样shiro的配置就完成了。

项目中 总有存在5张表


/** *  用户表。(通用用户,能否访问后台,看是否有后台角色) */@Entity@Table(name="system_user")@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)public class SystemUser implements Serializable {    @Id    @GenericGenerator(name = "systemUUID", strategy = "uuid")    @GeneratedValue(generator = "systemUUID")    @Column(name = "uuid",updatable = false, nullable = false)    private String uuid;     // 表主键    @Column    private String username; // 登录用户名    @Column    private String password; // 登录密码    @Column    private String isRoot; // 最高权限管理员; "1":root "0": notRoot    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")    @Column    private Date registerDate;    @Column    private Integer status; // 账号状态: 0:正常;1:禁用

@Entity@Table(name="system_role")@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)public class SystemRole implements Serializable{    @Id    @GenericGenerator(name = "systemUUID", strategy = "uuid")    @GeneratedValue(generator = "systemUUID")    @Column(name = "uuid",updatable = false, nullable = false)    private String uuid;     // 表主键    @Column(name="role_name")    private String roleName;    @Column(name="role_desc")    private String roleDesc;    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")    @Column(name = "create_date",updatable=false)    private Date createDate;// 创建日期    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")    @Column(name = "update_date")    private Date updateDate;// 更新日期    public Date getCreateDate() {        return createDate;    }

/** * 菜单表,你可以理解为 权限表 */@Entity@Table(name="system_menu")@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)public class SystemMenu implements Serializable {    @Id    @GenericGenerator(name = "systemUUID", strategy = "uuid")    @GeneratedValue(generator = "systemUUID")    @Column(name = "uuid",updatable = false, nullable = false)    private String uuid;    // 父类ID    @Column(name = "pId", length = 64)    private String pid;    // 资源名称    @Column(name = "name", length = 32)    private String name;    // 资源类型    @Column(name="type")    private String type;//权限类型,0.表示目录 1,表示菜单.2,表示按扭..    // 资源排序    @Column(name = "seq", length = 4)    private int seq;    // 资源的URL    @Column(name = "resUrl", length = 128)    private String resUrl;//URL地址.例如:/videoType/query  不需要项目名和http://xxx:8080    // 资源状态    @Column(name = "status", length = 2)    private int status;// 这个变量含义定义为: 0:可修改删除 1:不可修改删除    //层级    @Column(name="level", length = 4)    private int level;    // 资源说明    @Column(name = "descript", length = 128)    private String descript;    // 资源图标    @Column(name = "iconCls", length = 128)    private String iconCls;

@Entity@Table(name="system_user_role")@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)public class SystemUserRole implements Serializable{    @Id    @GenericGenerator(name = "systemUUID", strategy = "uuid")    @GeneratedValue(generator = "systemUUID")    @Column(name = "uuid",updatable = false, nullable = false)    private String uuid;     // 表主键    @Column    private String sysUserId;    @Column    private String sysRoleId;

@Entity@Table(name="system_role_menu")@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)public class SystemRoleMenu implements Serializable{    @Id    @GenericGenerator(name = "systemUUID", strategy = "uuid")    @GeneratedValue(generator = "systemUUID")    @Column(name = "uuid",updatable = false, nullable = false)    private String uuid;    @Column    private String sysRoleId;    @Column    private String sysMenuId;

具体的太长了,所以我讲讲项目中的心得体会吧。

  1. shiro+hibernate+ehcache 这三个用的时候配置需要注意,ehcache.xml要合到一起。

    2. log4j和slf4j的依赖是

     

 <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-log4j12</artifactId>            <version>1.7.25</version>  </dependency>
    为什么我要说这个,因为 我被别人误导了,别人导入了 log4j,slf4j相关依赖,就是没有上面的,导致我只能用 log4j显示日志,slf4j却没有效果,郁闷半天。


   3. hibernate的二级缓存用法

<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop><prop key="hibernate.cache.provider_configuration_file_resource_path">classpath:ehcache.xml</prop><!-- 开启查询缓存 --><prop key="hibernate.cache.use_query_cache">true</prop><!-- 开启二级缓存 --><prop key="hibernate.cache.use_second_level_cache">true</prop><!-- 高速缓存提供程序 --><!-- 由于spring也使用了Ehcache, 保证双方都使用同一个缓存管理器 --><prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop><bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">    <property name="configLocation">      <value>classpath:ehcache.xml</value>    </property>    <!-- 由于hibernate也使用了Ehcache, 保证双方都使用同一个缓存管理器 -->    <property name="shared" value="true"/>  </bean>

@Entity@Table(name="system_role")@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)public class SystemRole implements Serializable{

实体类加上注解,表示该实体类需要使用二级缓存。模式可选 read_write也可以是 read_only。但据说 read_only效率高些。 list()方法的调用,如果要用缓存,需要setCacheable(true)

@Overridepublic GridPageResult<SystemRole> getPageRoles(Pager pager) {    List<SystemRole> rows = getByHQL(true,"from SystemRole order by updateDate desc",null,pager.getPage(),pager.getRows());    long total = countByHQL(true,"select count(*) from SystemRole",null);    return new GridPageResult<>(total,rows);}
public List<T> getByHQL(boolean withCache, String hql, Map<String, Object> params) {Query q = getCurrentSession().createQuery(hql);if (params != null && !params.isEmpty()) {for (String key : params.keySet()) {q.setParameter(key, params.get(key));}}return q.setCacheable(withCache).list();}public List<T> getByHQL(boolean withCache, String hql, Map<String, Object> params, int page, int rows) {Query q = getCurrentSession().createQuery(hql);if (params != null && !params.isEmpty()) {for (String key : params.keySet()) {q.setParameter(key, params.get(key));}}return q.setCacheable(withCache).setFirstResult((page - 1) * rows)//.setMaxResults(rows)//.list();}public long countByHQL(boolean withCache, String hql, Map<String, Object> params) {Query q = getCurrentSession().createQuery(hql);if (params != null && !params.isEmpty()) {for (String key : params.keySet()) {q.setParameter(key, params.get(key));}}return (Long) q.setCacheable(withCache).uniqueResult();}public long countBySQL(boolean withCache, String sql, Map<String, Object> params) {SQLQuery q = getCurrentSession().createSQLQuery(sql);if (params != null && !params.isEmpty()) {for (String key : params.keySet()) {q.setParameter(key, params.get(key));}}return (Long) q.setCacheable(withCache).uniqueResult();}public List<Map<String, Object>> getResultMapBySql(String sql, Map<String, Object> params) {SQLQuery q = getCurrentSession().createSQLQuery(sql);if (params != null && !params.isEmpty()) {for (String key : params.keySet()) {q.setParameter(key, params.get(key));}}return q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();}public List<Map<String, Object>> getResultMapBySql(String sql, Map<String, Object> params, int page, int rows) {SQLQuery q = getCurrentSession().createSQLQuery(sql);if (params != null && !params.isEmpty()) {for (String key : params.keySet()) {q.setParameter(key, params.get(key));}}// 这种的不能使用 setCacheable(withCache),会报错。return q.setFirstResult((page - 1) * rows)//.setMaxResults(rows)//.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)//.list();}

  使用二级缓存也会有很多不便的地方:

    

public void updateRole(SystemRole role) {        //update(role); // 不能这样更新,cache是read-only模式        String hql = "update SystemRole set " +                "roleName=:roleName,roleDesc=:roleDesc,updateDate=:updateDate " +                " where uuid=:uuid";        Map<String,Object> params = new HashMap<>();        params.put("roleName",role.getRoleName());        params.put("roleDesc",role.getRoleDesc());        params.put("updateDate",role.getUpdateDate());        params.put("uuid",role.getUuid());        executeHQL(hql,params);    }
   不能直接调用update方法,更新对象,要采用执行sql或者hql语句方式,直接操作数据库。经测试,直接操作数据库的更新,缓存也会失效,也会更新的。

    第二个就是使用sql语句查询的时候,如果使用cache为true的情况,不能返回List<Map>类型,必须指定成对象。当然setcache为false,顺利执行。 那么如果是true,代码应这样写。

  

@Override    public List<DtoRoleMenu> getRoleHasAndNotHasMenus(String roleId) {        String sql="select m.uuid as id,  " +                "m.pId as pId, " +                "m.name as name, " +                "m.resUrl as resUrl, " +                "m.type as type, " +                "srm.sysRoleId as roleId " +                "from system_menu m  " +                "left join system_role_menu srm  " +                "on m.uuid = srm.sysMenuId " +                "and srm.sysRoleId =:roleId ";        return  getCurrentSession()                .createSQLQuery(sql)                .addScalar("id", StringType.INSTANCE)                .addScalar("pId", StringType.INSTANCE)                .addScalar("name", StringType.INSTANCE)                .addScalar("resUrl", StringType.INSTANCE)                .addScalar("type", StringType.INSTANCE)                .addScalar("roleId", StringType.INSTANCE)                .setParameter("roleId",roleId)                .setResultTransformer(Transformers.aliasToBean(DtoRoleMenu.class))                .setCacheable(false).list();    }

贴上项目运行效果图吧。



项目运行

因为项目已经集成了 tomcat插件了。所以我们配置一下就行了,不需要额外的tomcat包了


点击OK之后,你会看到右侧就会出现你新建的东西。然后点击那两个绿色的按钮任意一个运行。


然后就可以运行了。

本项目做了一些初始化工作,所以,后台的管理员 用户名 root,密码 123456。


  

   本项目下载地址:下载地址

    如果你使用IDEA 直接打开,可能需要配置一下,因为 你的F盘可能没有maven软件,而且系统自带的maven肯定会下载jar包到你的c盘。所以最好配置一下。

     

    还有就是 源码处,有一个无关痛痒的小错误,源码位置


   我为了证明 能不能使用 cache 返回 List<Map>,测试的结果是不能使用 cache为true,否则报错。

     为了记录这篇博客,我tm真用了整整一下午时间啊。 因为这csdn的编辑器,实在是没习惯用啊。重复了好几遍已经做好的操作。哎,终于写完了。