SpringMVC+Apache Shiro+JPA(hibernate)案例教学(一)整合配置
一、SpringMVC+Apache Shiro+JPA(hibernate)整合配置
(1)新建Web工程,且导入所需Jar包。(以下截图为真实项目截图,如有不需要的JAR包,请自行删除)
(2)配置web.xml,applicationContext.xml, dispatcher-servlet.xml
web.xml
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <!-- 配置spring管理OpenEntityManagerInViewFilter --> <filter> <filter-name>hibernateFilter</filter-name> <filter-class> org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置Log4j --> <context-param> <param-name>webAppRootKey</param-name> <param-value>spring_springmvc_jpa.root</param-value> </context-param> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!-- 配置编码过滤器 --> <filter> <filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Shiro filter --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <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> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <servlet-name>dispatcherServlet</servlet-name> </filter-mapping> <!-- 配置Spring监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <!-- Spring 刷新Introspector防止内存泄露 --> <listener> <listener-class> org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!-- SpringMVC核心分发器 --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 覆盖default servlet的/, springmvc servlet将处理原来处理静态资源的映射 --> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <jsp-config> <jsp-property-group> <description> Special property group for JSP Configuration JSP example. </description> <display-name>JSPConfiguration</display-name> <url-pattern>*.jsp</url-pattern> <el-ignored>true</el-ignored> <page-encoding>utf-8</page-encoding> <scripting-invalid>false</scripting-invalid> </jsp-property-group> </jsp-config> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
applicationContext.xml
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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" xmlns:p="http://www.springframework.org/schema/p" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd"> <!-- 注解支持 --> <context:annotation-config /> <!-- 启动组件扫描,排除@Controller组件,该组件由SpringMVC配置文件扫描 --> <context:component-scan base-package="xxx.xxx.xxx"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <!-- 属性文件位置 --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- 数据源 --> <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> <!-- 数据库驱动 --> <property name="driverClass" value="${jdbc.driverClassName}" /> <!-- 相应驱动的jdbcUrl --> <property name="jdbcUrl" value="${jdbc.url}" /> <!-- 数据库的用户名 --> <property name="username" value="${jdbc.username}" /> <!-- 数据库的密码 --> <property name="password" value="${jdbc.password}" /> <!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 --> <property name="idleConnectionTestPeriod" value="${BoneCP.idleConnectionTestPeriod}" /> <!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 --> <property name="idleMaxAge" value="${BoneCP.idleMaxAge}" /> <!-- 每个分区最大的连接数 --> <property name="maxConnectionsPerPartition" value="${BoneCP.maxConnectionsPerPartition}" /> <!-- 每个分区最小的连接数 --> <property name="minConnectionsPerPartition" value="${BoneCP.minConnectionsPerPartition}" /> <!-- 分区数 ,默认值2,最小1,推荐3-4,视应用而定 --> <property name="partitionCount" value="${BoneCP.partitionCount}" /> <!-- 每次去拿数据库连接的时候一次性要拿几个,默认值:2 --> <property name="acquireIncrement" value="${BoneCP.acquireIncrement}" /> <!-- 缓存prepared statements的大小,默认值:0 --> <property name="statementsCacheSize" value="${BoneCP.statementsCacheSize}" /> <!-- 每个分区释放链接助理进程的数量,默认值:3,除非你的一个数据库连接的时间内做了很多工作,不然过多的助理进程会影响你的性能 --> <property name="releaseHelperThreads" value="${BoneCP.releaseHelperThreads}" /> </bean> <!-- JPA实体管理器工厂 --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="persistenceProvider" ref="persistenceProvider" /> <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> <property name="jpaDialect" ref="jpaDialect" /> <property name="packagesToScan" value="xxx.xxx.xxx.entity" /> <property name="jpaProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQL5Dialect </prop> <prop key="hibernate.connection.driver_class"> com.mysql.jdbc.Driver </prop> <prop key="hibernate.max_fetch_depth">3</prop> <prop key="hibernate.jdbc.fetch_size">18</prop> <prop key="hibernate.jdbc.batch_size">10</prop> <prop key="hibernate.hbm2ddl.auto">validate</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">false</prop> <prop key="javax.persistence.validation.mode"> none </prop> <prop key="hibernate.search.default.directory_provider"> filesystem </prop> <!--设置为手动添加索引 <prop key="hibernate.search.indexing_strategy">manual</prop> --> <prop key="hibernate.search.default.indexBase"> d:/indexs </prop> </props> </property> </bean> <!-- 用于指定持久化实现厂商类 --> <bean id="persistenceProvider" class="org.hibernate.ejb.HibernatePersistence" /> <!-- 用于设置JPA实现厂商的特定属性 --> <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="database" value="MYSQL" /> </bean> <!-- 用于指定一些高级特性 --> <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> <!-- 事务管理器 --> <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!-- 注解式事务 --> <tx:annotation-driven transaction-manager="txManager" /> <!-- 启用缓存注解功能 --> <cache:annotation-driven cache-manager="cacheManager" /> <!-- 声明cacheManager --> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache" /> <!-- cacheManager工厂类,指定ehcache.xml的位置 --> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="classpath:/ehcache.xml" /> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="shiroDbRealm" /> </bean> <!-- 項目自定义的Realm --> <bean id="shiroDbRealm" class="xxx.xxx.xxx.xxx.realm.ShiroDbRealm"></bean> <!-- Shiro Filter --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/login" /> <property name="successUrl" value="/index" /> <property name="unauthorizedUrl" value="/error" /> <property name="filterChainDefinitions"> <value> /login = anon /** = authc </value> </property> </bean> </beans>
dispatcher-servlet.xml
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"> <mvc:annotation-driven /> <context:component-scan base-package="xxx.xxx.xxx.controller" /> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- 避免IE执行AJAX时,返回JSON出现下载文件 --> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <!-- 配置 文件上传的支持 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="1024000000" /> <property name="resolveLazily" value="true" /> <property name="maxInMemorySize" value="4096" /> </bean> <!-- 采用SpringMVC自带的JSON转换工具,支持@ResponseBody注解 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> </list> </property> </bean> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> <!-- 开启Shiro注解的Spring配置方式的beans。在lifecycleBeanPostProcessor之后运行 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- shiro为集成spring --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.apache.shiro.authz.UnauthorizedException">/commons/error</prop> </props> </property> </bean> </beans>
jdbc.properties
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=UTF-8 jdbc.username=root jdbc.password=root BoneCP.idleConnectionTestPeriod=60 BoneCP.idleMaxAge=60 BoneCP.maxConnectionsPerPartition=5 BoneCP.minConnectionsPerPartition=1 BoneCP.partitionCount=3 BoneCP.acquireIncrement=2 BoneCP.statementsCacheSize=0 BoneCP.releaseHelperThreads=3
(3)建立JavaBean,User.java,Role.java,Permisson.java
User.java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class User { @Entity @Table(name = "XXXUser") public class User implements Serializable { private static final long serialVersionUID = -4128065555702634219L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "userid") private Long id; @Column(length = 50, unique = true) private String account; @Column(length = 100) @JsonIgnore private String password; @Column(length = 50) private String name; @Column(length = 50) private String nickName; @Temporal(TemporalType.TIMESTAMP) @Column private Date crtime; @Column(length = 50) private String cruser; @Column private Integer stutas; @Column private Integer integral; @Column private Integer loginCount; @Column @Temporal(TemporalType.TIMESTAMP) private Date loginTime; @Column @Temporal(TemporalType.TIMESTAMP) private Date logoutTime; @Column private String address; @Column private String tel; @Column private String mobile; @Column private String email; @Column private String answer; @Column private String question; @Column private String cardType; @Column private String cardNum; @Column @Temporal(TemporalType.TIMESTAMP) private Date regTime; @Column @Temporal(TemporalType.TIMESTAMP) private Date openTime; @JoinColumn(name = "roleid", referencedColumnName = "roleid") @ManyToOne @Basic(fetch = FetchType.LAZY) private Role role; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public Date getCrtime() { return crtime; } public void setCrtime(Date crtime) { this.crtime = crtime; } public String getCruser() { return cruser; } public void setCruser(String cruser) { this.cruser = cruser; } public Integer getStutas() { return stutas; } public void setStutas(Integer stutas) { this.stutas = stutas; } public Integer getIntegral() { return integral; } public void setIntegral(Integer integral) { this.integral = integral; } public Integer getLoginCount() { return loginCount; } public void setLoginCount(Integer loginCount) { this.loginCount = loginCount; } public Date getLoginTime() { return loginTime; } public void setLoginTime(Date loginTime) { this.loginTime = loginTime; } public Date getLogoutTime() { return logoutTime; } public void setLogoutTime(Date logoutTime) { this.logoutTime = logoutTime; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getAnswer() { return answer; } public void setAnswer(String answer) { this.answer = answer; } public String getQuestion() { return question; } public void setQuestion(String question) { this.question = question; } public String getCardType() { return cardType; } public void setCardType(String cardType) { this.cardType = cardType; } public String getCardNum() { return cardNum; } public void setCardNum(String cardNum) { this.cardNum = cardNum; } public Date getRegTime() { return regTime; } public void setRegTime(Date regTime) { this.regTime = regTime; } public Date getOpenTime() { return openTime; } public void setOpenTime(Date openTime) { this.openTime = openTime; } public Role getRole() { return role; } public void setRole(Role role) { this.role = role; } } }
Role.java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Entity @Table(name = "XXXRole") public class Role implements Serializable { private static final long serialVersionUID = -6584862720172366564L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "roleid") private Long id; @Column(length = 50, nullable = false, name = "rname") private String name; @Column(length = 50, name = "rdesc") private String desc; @OneToMany(cascade = { CascadeType.REMOVE, CascadeType.REFRESH }, mappedBy = "role", fetch = FetchType.LAZY) @JsonIgnore private Collection<User> users; @Column(length = 50, nullable = false) private String cruser; @Column(nullable = false) @Temporal(TemporalType.TIMESTAMP) @DateBridge(resolution = Resolution.SECOND) private Date crtime; @Column(nullable = false) private Integer viewable; @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE }, fetch = FetchType.LAZY) @JoinTable(name = "XXXRolePms", joinColumns = { @JoinColumn(name = "roleid", updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "pmsid", updatable = false) }) private Collection<Permission> pmss; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public Collection<User> getUsers() { return users; } public void setUsers(Collection<User> users) { this.users = users; } public String getCruser() { return cruser; } public void setCruser(String cruser) { this.cruser = cruser; } public Date getCrtime() { return crtime; } public void setCrtime(Date crtime) { this.crtime = crtime; } public Integer getViewable() { return viewable; } public void setViewable(Integer viewable) { this.viewable = viewable; } public Collection<Permission> getPmss() { return pmss; } public void setPmss(Collection<Permission> pmss) { this.pmss = pmss; } }
Permisson.java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Entity @Table(name = "XXXPermission") public class Permission implements Serializable { private static final long serialVersionUID = -314770669417521192L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "pmsid") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parentid") private Permission parent; @Column(length = 50, nullable = false, name = "pname") private String name; @Column(length = 100, nullable = false, name = "pdesc") private String desc; @Column(length = 50) private String permission; @Column @Type(type = "yes_no") private boolean enabled; @Column(length = 50, nullable = false) private String cruser; @Temporal(TemporalType.TIMESTAMP) @Column(nullable = false) private Date crtime; @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = { CascadeType.ALL }) private Collection<Permission> children; @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "pmss") private Collection<Role> roles; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Permission getParent() { return parent; } public void setParent(Permission parent) { this.parent = parent; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getPermission() { return permission; } public void setPermission(String permission) { this.permission = permission; } public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public String getCruser() { return cruser; } public void setCruser(String cruser) { this.cruser = cruser; } public Date getCrtime() { return crtime; } public void setCrtime(Date crtime) { this.crtime = crtime; } public Collection<Permission> getChildren() { return children; } public void setChildren(Collection<Permission> children) { this.children = children; } public Collection<Role> getRoles() { return roles; } public void setRoles(Collection<Role> roles) { this.roles = roles; } }
至此,配置基本完成