zoukankan      html  css  js  c++  java
  • SpringMVC+Apache Shiro+JPA(hibernate)案例教学整合配置

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

    序:

    关于标题:

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

    关于内容:

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

    关于拍砖:

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

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


    教学:

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

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

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

    web.xml

    复制代码
    <?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

    复制代码
    <?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

    复制代码
    <?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

    复制代码
    jdbc.driverClassName=com.mysql.jdbc.Driver
    
    jdbc.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

    复制代码
    @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;
    
        get/set    
    
    }
    复制代码

    Role.java

    复制代码
    @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;
        
    }
    复制代码

    Permisson.java

    复制代码
    @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;
        
    }
    复制代码

    至此,配置基本完成,请继续学习下一篇文章:

    SpringMVC+Apache Shiro+JPA(hibernate)案例教学(二)基于SpringMVC+Shiro的用户登录权限验证

    SpringMVC+Apache Shiro+JPA(hibernate)案例教学(三)给Shiro登录验证加上验证码

    SpringMVC+Apache Shiro+JPA(hibernate)案例教学(四)基于Shiro验证用户权限,且给用户授权。

    SpringMVC+Apache Shiro+JPA(hibernate)案例教学(五)基于Shiro标签,验证用户对资源的操作权限。

     
     
    分类: Apache Shiro
    标签: Shirospring mvc
  • 相关阅读:
    http headers总结
    golang跨域配置
    Kafka中topic的Partition,Kafka为什么这么快,Consumer的负载均衡及consumerGroup的概念
    kafka partition(分区)与 group
    RocketMQ从部署到应用(Golang)
    Codeforces Round #706 (Div. 2)
    关于平衡树
    具体数学 第三章 整值函数
    FFT&NTT&多项式全家桶
    省选测试15
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2992434.html
Copyright © 2011-2022 走看看