SpringMVC+Apache Shiro+JPA(hibernate)案例教学(一)整合配置

序:

关于标题:

说是教学,实在愧不敢当,但苦与本人文笔有限,实在找不到更合理,谦逊的词语表达,只能先这样定义了。
其实最真实的想法,只是希望这个关键词能让更多的人浏览到这篇文章,也算是对于自己写文章的一个肯定吧。^_^!

关于内容:

再写这系列文章之前,本人和许多人一样都是伸手党,并深深的了解咱伸手党且英文较差的朋友对于新知识的学习及获取中文资料少的痛苦。所以本着“取之于民,共享与民”的原则,记录下实际工作中对SpringMVC+Shiro整合应用的部分心得。本人技术水平有限,仅希望文章对他人有一定的参考价值,足矣。

关于拍砖:

请轻拍,很痛的。且最好附上您的高见。

另:Shiro基础及原理,推荐学习http://kdboy.iteye.com/category/35212,同时感谢他的博客,在我学习Shiro的过程中,给予很大帮助!


教学:

一、SpringMVC+Apache Shiro+JPA(hibernate)整合配置

(1)新建Web工程,且导入所需Jar包。(以下截图为真实项目截图,如有不需要的JAR包,请自行删除)

SpringMVC+Apache Shiro+JPA(hibernate)案例教学(一)整合配置

(2)配置web.xml,applicationContext.xml,dispatcher-servlet.xml

web.xml

001.<?xmlversion="1.0"encoding="UTF-8"?>
002.<web-appid="WebApp_ID"version="2.4"
003.xmlns="http://java.sun.com/xml/ns/j2ee"
004.xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
005.xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
006.
007.<!-- 配置spring管理OpenEntityManagerInViewFilter-->
008.<filter>
009.<filter-name>hibernateFilter</filter-name>
010.<filter-class>
011.org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
012.</filter-class>
013.</filter>
014.<filter-mapping>
015.<filter-name>hibernateFilter</filter-name>
016.<url-pattern>/*</url-pattern>
017.</filter-mapping>
018.
019.<!-- 配置Log4j -->
020.<context-param>
021.<param-name>webAppRootKey</param-name>
022.<param-value>spring_springmvc_jpa.root</param-value>
023.</context-param>
024.<context-param>
025.<param-name>log4jConfigLocation</param-name>
026.<param-value>classpath:log4j.properties</param-value>
027.</context-param>
028.<listener>
029.<listener-class>
030.org.springframework.web.util.Log4jConfigListener
031.</listener-class>
032.</listener>
033.
034.<!-- 配置编码过滤器 -->
035.<filter>
036.<filter-name>characterEncodingFilter</filter-name>
037.<filter-class>
038.org.springframework.web.filter.CharacterEncodingFilter
039.</filter-class>
040.<init-param>
041.<param-name>encoding</param-name>
042.<param-value>UTF-8</param-value>
043.</init-param>
044.<init-param>
045.<param-name>forceEncoding</param-name>
046.<param-value>true</param-value>
047.</init-param>
048.</filter>
049.<filter-mapping>
050.<filter-name>characterEncodingFilter</filter-name>
051.<url-pattern>/*</url-pattern>
052.</filter-mapping>
053.
054.<!-- Shiro filter -->
055.<filter>
056.<filter-name>shiroFilter</filter-name>
057.<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
058.<init-param>
059.<param-name>targetFilterLifecycle</param-name>
060.<param-value>true</param-value>
061.</init-param>
062.</filter>
063.<filter-mapping>
064.<filter-name>shiroFilter</filter-name>
065.<url-pattern>/*</url-pattern>
066.</filter-mapping>
067.
068.<filter>
069.<filter-name>HiddenHttpMethodFilter</filter-name>
070.<filter-class>
071.org.springframework.web.filter.HiddenHttpMethodFilter
072.</filter-class>
073.</filter>
074.<filter-mapping>
075.<filter-name>HiddenHttpMethodFilter</filter-name>
076.<servlet-name>dispatcherServlet</servlet-name>
077.</filter-mapping>
078.
079.
080.<!-- 配置Spring监听器 -->
081.<listener>
082.<listener-class>
083.org.springframework.web.context.ContextLoaderListener
084.</listener-class>
085.</listener>
086.<context-param>
087.<param-name>contextConfigLocation</param-name>
088.<param-value>/WEB-INF/applicationContext.xml</param-value>
089.</context-param>
090.
091.<!-- Spring 刷新Introspector防止内存泄露 -->
092.<listener>
093.<listener-class>
094.org.springframework.web.util.IntrospectorCleanupListener
095.</listener-class>
096.</listener>
097.
098.
099.<!-- SpringMVC核心分发器 -->
100.<servlet>
101.<servlet-name>dispatcherServlet</servlet-name>
102.<servlet-class>
103.org.springframework.web.servlet.DispatcherServlet
104.</servlet-class>
105.<init-param>
106.<param-name>contextConfigLocation</param-name>
107.<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
108.</init-param>
109.<load-on-startup>1</load-on-startup>
110.</servlet>
111.<!-- 覆盖default servlet的/, springmvc servlet将处理原来处理静态资源的映射 -->
112.<servlet-mapping>
113.<servlet-name>dispatcherServlet</servlet-name>
114.<url-pattern>/</url-pattern>
115.</servlet-mapping>
116.
117.<jsp-config>
118.<jsp-property-group>
119.<description>
120.Special property group for JSP Configuration JSP
121.example.
122.</description>
123.<display-name>JSPConfiguration</display-name>
124.<url-pattern>*.jsp</url-pattern>
125.<el-ignored>true</el-ignored>
126.<page-encoding>utf-8</page-encoding>
127.<scripting-invalid>false</scripting-invalid>
128.</jsp-property-group>
129.</jsp-config>
130.
131.<welcome-file-list>
132.<welcome-file>index.html</welcome-file>
133.<welcome-file>index.jsp</welcome-file>
134.</welcome-file-list>
135.</web-app>
applicationContext.xml
001.<?xmlversion="1.0"encoding="UTF-8"?>
002.<beansxmlns="http://www.springframework.org/schema/beans"
003.xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
004.xmlns:aop="http://www.springframework.org/schema/aop"
005.xmlns:tx="http://www.springframework.org/schema/tx"
006.xmlns:context="http://www.springframework.org/schema/context"
007.xmlns:p="http://www.springframework.org/schema/p"
008.xmlns:cache="http://www.springframework.org/schema/cache"
009.xsi:schemaLocation="
010.http://www.springframework.org/schema/beans
011.http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
012.http://www.springframework.org/schema/tx
013.http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
014.http://www.springframework.org/schema/aop
015.http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
016.http://www.springframework.org/schema/context
017.http://www.springframework.org/schema/context/spring-context-3.1.xsd
018.http://www.springframework.org/schema/cache
019.http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">
020.
021.
022.<!-- 注解支持 -->
023.<context:annotation-config/>
024.
025.<!-- 启动组件扫描,排除@Controller组件,该组件由SpringMVC配置文件扫描 -->
026.<context:component-scanbase-package="xxx.xxx.xxx">
027.<context:exclude-filtertype="annotation"
028.expression="org.springframework.stereotype.Controller"/>
029.</context:component-scan>
030.
031.<!-- 属性文件位置 -->
032.<context:property-placeholderlocation="classpath:jdbc.properties"/>
033.
034.<!-- 数据源 -->
035.<beanid="dataSource"class="com.jolbox.bonecp.BoneCPDataSource"
036.destroy-method="close">
037.<!-- 数据库驱动 -->
038.<propertyname="driverClass"value="${jdbc.driverClassName}"/>
039.<!-- 相应驱动的jdbcUrl-->
040.<propertyname="jdbcUrl"value="${jdbc.url}"/>
041.<!-- 数据库的用户名 -->
042.<propertyname="username"value="${jdbc.username}"/>
043.<!-- 数据库的密码 -->
044.<propertyname="password"value="${jdbc.password}"/>
045.<!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 -->
046.<propertyname="idleConnectionTestPeriod"
047.value="${BoneCP.idleConnectionTestPeriod}"/>
048.<!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 -->
049.<propertyname="idleMaxAge"value="${BoneCP.idleMaxAge}"/>
050.<!-- 每个分区最大的连接数 -->
051.<propertyname="maxConnectionsPerPartition"
052.value="${BoneCP.maxConnectionsPerPartition}"/>
053.<!-- 每个分区最小的连接数 -->
054.<propertyname="minConnectionsPerPartition"
055.value="${BoneCP.minConnectionsPerPartition}"/>
056.<!-- 分区数 ,默认值2,最小1,推荐3-4,视应用而定 -->
057.<propertyname="partitionCount"
058.value="${BoneCP.partitionCount}"/>
059.<!-- 每次去拿数据库连接的时候一次性要拿几个,默认值:2 -->
060.<propertyname="acquireIncrement"
061.value="${BoneCP.acquireIncrement}"/>
062.<!-- 缓存prepared statements的大小,默认值:0 -->
063.<propertyname="statementsCacheSize"
064.value="${BoneCP.statementsCacheSize}"/>
065.<!-- 每个分区释放链接助理进程的数量,默认值:3,除非你的一个数据库连接的时间内做了很多工作,不然过多的助理进程会影响你的性能 -->
066.<propertyname="releaseHelperThreads"
067.value="${BoneCP.releaseHelperThreads}"/>
068.</bean>
069.
070.<!-- JPA实体管理器工厂 -->
071.<beanid="entityManagerFactory"
072.class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
073.<propertyname="dataSource"ref="dataSource"/>
074.<propertyname="persistenceProvider"ref="persistenceProvider"/>
075.<propertyname="jpaVendorAdapter"ref="jpaVendorAdapter"/>
076.<propertyname="jpaDialect"ref="jpaDialect"/>
077.
078.<propertyname="packagesToScan"value="xxx.xxx.xxx.entity"/>
079.
080.<propertyname="jpaProperties">
081.<props>
082.<propkey="hibernate.dialect">
083.org.hibernate.dialect.MySQL5Dialect
084.</prop>
085.<propkey="hibernate.connection.driver_class">
086.com.mysql.jdbc.Driver
087.</prop>
088.<propkey="hibernate.max_fetch_depth">3</prop>
089.<propkey="hibernate.jdbc.fetch_size">18</prop>
090.<propkey="hibernate.jdbc.batch_size">10</prop>
091.<propkey="hibernate.hbm2ddl.auto">validate</prop>
092.<propkey="hibernate.show_sql">true</prop>
093.<propkey="hibernate.format_sql">false</prop>
094.<propkey="javax.persistence.validation.mode">
095.none
096.</prop>
097.<prop
098.key="hibernate.search.default.directory_provider">
099.filesystem
100.</prop>
101.<!--设置为手动添加索引 <prop key="hibernate.search.indexing_strategy">manual</prop> -->
102.<propkey="hibernate.search.default.indexBase">
103.d:/indexs
104.</prop>
105.</props>
106.</property>
107.</bean>
108.<!-- 用于指定持久化实现厂商类 -->
109.<beanid="persistenceProvider"
110.class="org.hibernate.ejb.HibernatePersistence"/>
111.<!-- 用于设置JPA实现厂商的特定属性 -->
112.<beanid="jpaVendorAdapter"
113.class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
114.<propertyname="database"value="MYSQL"/>
115.</bean>
116.<!-- 用于指定一些高级特性 -->
117.<beanid="jpaDialect"
118.class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
119.
120.<!-- 事务管理器 -->
121.<beanid="txManager"
122.class="org.springframework.orm.jpa.JpaTransactionManager">
123.<propertyname="entityManagerFactory"
124.ref="entityManagerFactory"/>
125.</bean>
126.
127.<!-- 注解式事务 -->
128.<tx:annotation-driventransaction-manager="txManager"/>
129.
130.<!-- 启用缓存注解功能 -->
131.<cache:annotation-drivencache-manager="cacheManager"/>
132.
133.
134.<!-- 声明cacheManager -->
135.<beanid="cacheManager"
136.class="org.springframework.cache.ehcache.EhCacheCacheManager"
137.p:cacheManager-ref="ehcache"/>
138.
139.
140.<!-- cacheManager工厂类,指定ehcache.xml的位置 -->
141.<beanid="ehcache"
142.class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
143.p:configLocation="classpath:/ehcache.xml"/>
144.
145.<beanid="securityManager"
146.class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
147.<propertyname="realm"ref="shiroDbRealm"/>
148.</bean>
149.
150.<!-- 項目自定义的Realm -->
151.<beanid="shiroDbRealm"class="xxx.xxx.xxx.xxx.realm.ShiroDbRealm"></bean>
152.
153.<!-- Shiro Filter -->
154.<beanid="shiroFilter"
155.class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
156.<propertyname="securityManager"ref="securityManager"/>
157.<propertyname="loginUrl"value="/login"/>
158.<propertyname="successUrl"value="/index"/>
159.<propertyname="unauthorizedUrl"value="/error"/>
160.<propertyname="filterChainDefinitions">
161.<value>
162./login = anon
163.         /** = authc
164.</value>
165.</property>
166.</bean>
167.</beans>
dispatcher-servlet.xml
01.<?xmlversion="1.0"encoding="UTF-8"?>
02.<beansxmlns="http://www.springframework.org/schema/beans"
03.xmlns:mvc="http://www.springframework.org/schema/mvc"
04.xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
05.xmlns:context="http://www.springframework.org/schema/context"
06.xsi:schemaLocation="
07.http://www.springframework.org/schema/beans
08.http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
09.http://www.springframework.org/schema/context
10.http://www.springframework.org/schema/context/spring-context-3.1.xsd
11.http://www.springframework.org/schema/mvc
12.http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
13.
14.<mvc:annotation-driven/>
15.
16.<context:component-scanbase-package="xxx.xxx.xxx.controller"/>
17.
18.<mvc:resourcesmapping="/resources/**"location="/resources/"/>
19.
20.<!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->
21.<beanid="mappingJacksonHttpMessageConverter"
22.class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
23.<propertyname="supportedMediaTypes">
24.<list>
25.<value>text/html;charset=UTF-8</value>
26.</list>
27.</property>
28.</bean>
29.
30.<!-- 配置 文件上传的支持 -->
31.<beanid="multipartResolver"
32.class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
33.<propertyname="maxUploadSize"value="1024000000"/>
34.<propertyname="resolveLazily"value="true"/>
35.<propertyname="maxInMemorySize"value="4096"/>
36.</bean>
37.
38.
39.<!-- 采用SpringMVC自带的JSON转换工具,支持@ResponseBody注解 -->
40.<bean
41.class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
42.<propertyname="messageConverters">
43.<list>
44.<bean
45.class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
46.</list>
47.</property>
48.</bean>
49.
50.<bean
51.class="org.springframework.web.servlet.view.InternalResourceViewResolver">
52.<propertyname="viewClass"
53.value="org.springframework.web.servlet.view.JstlView"/>
54.<propertyname="prefix"value="/WEB-INF/jsp/"/>
55.<propertyname="suffix"value=".jsp"/>
56.</bean>
57.
58.<!-- 开启Shiro注解的Spring配置方式的beans。在lifecycleBeanPostProcessor之后运行 -->
59.<bean
60.class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
61.depends-on="lifecycleBeanPostProcessor"/>
62.<bean
63.class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
64.<propertyname="securityManager"ref="securityManager"/>
65.</bean>
66.
67.
68.<beanid="lifecycleBeanPostProcessor"
69.class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
70.
71.<!-- shiro为集成spring -->
72.<beanclass="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
73.<propertyname="exceptionMappings">
74.<props>
75.<propkey="org.apache.shiro.authz.UnauthorizedException">/commons/error</prop>
76.</props>
77.</property>
78.</bean>
79.
80.</beans>
jdbc.properties
01.jdbc.driverClassName=com.mysql.jdbc.Driver
02.
03.jdbc.url=jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=UTF-8
04.
05.jdbc.username=root
06.
07.jdbc.password=root
08.
09.BoneCP.idleConnectionTestPeriod=60
10.
11.BoneCP.idleMaxAge=60
12.
13.BoneCP.maxConnectionsPerPartition=5
14.
15.BoneCP.minConnectionsPerPartition=1
16.
17.BoneCP.partitionCount=3
18.
19.BoneCP.acquireIncrement=2
20.
21.BoneCP.statementsCacheSize=0
22.
23.BoneCP.releaseHelperThreads=3

(3)建立JavaBean,User.java,Role.java,Permisson.java

User.java

01.@Entity
02.@Table(name="XXXUser")
03.publicclass User implementsSerializable{
04.
05.privatestatic final long serialVersionUID = -4128065555702634219L;
06.
07.@Id
08.@GeneratedValue(strategy=GenerationType.IDENTITY)
09.@Column(name="userid")
10.privateLong id;
11.@Column(length=50,unique=true)
12.privateString account;
13.@Column(length=100)
14.@JsonIgnore
15.privateString password;
16.@Column(length=50)
17.privateString name;
18.@Column(length=50)
19.privateString nickName;
20.@Temporal(TemporalType.TIMESTAMP)
21.@Column
22.privateDate crtime;
23.@Column(length=50)
24.privateString cruser;
25.@Column
26.privateInteger stutas;
27.@Column
28.privateInteger integral;
29.@Column
30.privateInteger loginCount;
31.@Column
32.@Temporal(TemporalType.TIMESTAMP)
33.privateDate loginTime;
34.@Column
35.@Temporal(TemporalType.TIMESTAMP)
36.privateDate logoutTime;
37.@Column
38.privateString address;
39.@Column
40.privateString tel;
41.@Column
42.privateString mobile;
43.@Column
44.privateString email;
45.@Column
46.privateString answer;
47.@Column
48.privateString question;
49.@Column
50.privateString cardType;
51.@Column
52.privateString cardNum;
53.@Column
54.@Temporal(TemporalType.TIMESTAMP)
55.privateDate regTime;
56.@Column
57.@Temporal(TemporalType.TIMESTAMP)
58.privateDate openTime;
59.@JoinColumn(name ="roleid",referencedColumnName ="roleid")
60.@ManyToOne
61.@Basic(fetch=FetchType.LAZY)
62.privateRole role;
63.
64.get/set
65.
66.}
Role.java
01.@Entity
02.@Table(name="XXXRole")
03.publicclass Role implementsSerializable{
04.
05.privatestatic final long serialVersionUID = -6584862720172366564L;
06.
07.@Id
08.@GeneratedValue(strategy=GenerationType.IDENTITY)
09.@Column(name="roleid")
10.privateLong id;
11.@Column(length=50,nullable=false,name="rname")
12.privateString name;
13.@Column(length=50,name="rdesc")
14.privateString desc;
15.@OneToMany(cascade = {CascadeType.REMOVE,CascadeType.REFRESH} , mappedBy ="role",fetch=FetchType.LAZY)
16.@JsonIgnore
17.privateCollection<User> users;
18.@Column(length=50,nullable=false)
19.privateString cruser;
20.@Column(nullable=false)
21.@Temporal(TemporalType.TIMESTAMP)
22.@DateBridge(resolution = Resolution.SECOND)
23.privateDate crtime;
24.@Column(nullable=false)
25.privateInteger viewable;
26.@ManyToMany(cascade={CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.MERGE}, fetch = FetchType.LAZY)
27.@JoinTable(name ="XXXRolePms",
28.joinColumns = {@JoinColumn(name = "roleid", updatable = false) },
29.inverseJoinColumns = {@JoinColumn(name = "pmsid", updatable = false) })
30.privateCollection<Permission> pmss;
31.
32.}
Permisson.java
01.@Entity
02.@Table(name="XXXPermission")
03.publicclass Permission implementsSerializable{
04.
05.privatestatic final long serialVersionUID = -314770669417521192L;
06.
07.@Id
08.@GeneratedValue(strategy=GenerationType.IDENTITY)
09.@Column(name="pmsid")
10.privateLong id;
11.@ManyToOne(fetch = FetchType.LAZY)
12.@JoinColumn(name ="parentid")
13.privatePermission parent;
14.@Column(length=50,nullable=false,name="pname")
15.privateString name;
16.@Column(length=100,nullable=false,name="pdesc")
17.privateString desc;
18.@Column(length=50)
19.privateString permission;
20.@Column
21.@Type(type="yes_no")
22.privateboolean enabled;
23.@Column(length=50,nullable=false)
24.privateString cruser;
25.@Temporal(TemporalType.TIMESTAMP)
26.@Column(nullable=false)
27.privateDate crtime;
28.@OneToMany(mappedBy ="parent",fetch = FetchType.LAZY,cascade={CascadeType.ALL})
29.privateCollection<Permission> children;
30.@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy ="pmss")
31.privateCollection<Role> roles;
32.
33.}
至此,配置基本完成,请继续学习下一篇文章