副标题#e#
第八步、利用Spring Security掩护Web资源。在SpringSide 3项目中,已经 整合进了SpringSecurity,实现了切合RBAC类型的权限打点系统,并把数据生存 到了数据库中。我以前的博文SpringSide 3 中的安详框架中对SpringSecurity 有一个劈头的探讨,我认为我写的对象对入门来说是很有辅佐的,入门今后再深 入就简朴了,在评论中我又增补了几点,个中就提到假如要把资源权限设置内容 放到数据库中,就要从objectDefinitionSource着手。事实上,在最新的 SpringSide 3版本中,就是通过界说一个databaseDefinitionSource来实现从数 据库中读取资源和权限之间的干系,而 databaseDefinitionSource引用 resourceDetailService,而该Service挪用 personal.youxia.service.security.ResourceDetailServiceImpl。就是这样一 层套一层的干系,可是最终只需要用户实现 personal.youxia.service.security.ResourceDetailServiceImpl即可。在 SpringSide 3项目中,实现该Service的事情都可以省略,因为江南白衣已经做 好了。而我们要做的,就是在他提供的基本长举办扩展。
在项目中,已经界说好了users、roles、authorities和resource,假如需要 扩展个中任意一项,只需要向对应的数据表添加记录即可。预界说的role有“管 理员”和“用户”两种,我认为在该示例中已经没有增加脚色的须要了,而 authorities是必定要增加的,我想让只有“用户”可以或许添加文章,只有“打点 员”可以或许删除文章,所以在authorities表中增加如下两行:
insert into AUTHORITIES (NAME,DISPLAY_NAME) values ('A_ADD_ARTICLE','添加文章');
insert into AUTHORITIES (NAME,DISPLAY_NAME) values ('A_DELETE_ARTICLE','删除文章');
成立authorities表和roles表的接洽,用户可以添加文章,打点员虽然也能 够添加文章,而只有打点员可以或许删除文章,所以在数据库中添加如下三行:
insert into ROLES_AUTHORITIES values(1,5);
insert into ROLES_AUTHORITIES values(1,6);
insert into ROLES_AUTHORITIES values(2,5);
再来看看需要掩护的资源,它们应该别离为article.action、article! input.action、article!save.action、article!delete.action,个中只有后头 三个需要掩护,因此在数据库中添加如下三行:
insert into RESOURCES (RESOURCE_TYPE,VALUE,ORDER_NUM) values('url','/article!input*',7.0);
insert into RESOURCES (RESOURCE_TYPE,VALUE,ORDER_NUM) values ('url','/article!save*',8.0);
insert into RESOURCES (RESOURCE_TYPE,VALUE,ORDER_NUM) values ('url','/article!delete*',9.0);
最后,需要成立授权和资源之间的接洽,如下:
insert into RESOURCES_AUTHORITIES values(5,7);
insert into RESOURCES_AUTHORITIES values(5,8);
insert into RESOURCES_AUTHORITIES values(6,9);
这时,再运行项目,会发明没有登录的用户只能察看文章,而点击增加文章 或删除文章的链接,就会跳到Login界面,或显示你没有会见该页面的权限。
对付项目中自带的用户、脚色、授权和资源打点,我是这样的观点:最开始 打仗SpringSide 3项目标时候,我以为该成果是个鸡肋,甚至想过把这些成果删 除去,弄一个清洁的项目从新做;颠末一段时间的思考后,我的见识变了,我觉 得这个成果很是有用,是一个很好的基本,而我们本身的成果,都可以从这里进 行扩展;这里的扩展,大部门都只需要在数据库中添加数行记录即可,正如上面 的演示,独一不能到达要求的,大概是有的人以为users表字段太少,而实际项 目中我们要记任命户的信息远远不止这么少,其实这个问题也好办理,只需要创 建一个 user_details表即可,可能叫user_profiles,再凭据之前的步调建设针 对user_details表的增删查改成果;总之,只管不要去变动江南白衣已经实现了 的数据库布局和措施代码。
SpringSecurity针对资源的掩护,不只仅是只能在数据库中设置,其实 SpringSecurity更提供了一些有用的标签,可以在视图文件中机动利用。详细内 容,各人请参考SpringSecurity文档。
第九步、将项目迁移到大都据库情况。其实只要相识前面的八步,简朴的项 目就可以搞定了,可是对付致力于高并发高负载的漫衍式应用,则离不开大都据 源和漫衍式事务打点,Web Service和AJAX的跨域会见也是做漫衍式应用的有力 兵器。在我前面的博文中,我已经探讨过了大都据源设置的各类问题:
SpringSide 3 中的大都据源设置的问题
在SpringSide 3 中利用多个数据库的要领
在这里,我选择了第三种要领,就是在Spring中整合Atomikos。下载 Atomikos 3.5.5版,把如下transactions-essentials-alljar文件和 jta.properties文件拷入到项目标WEB-INF/lib目次下。
建设第二个数据库,名称为MultiDatasourceExampleIndex,个中包括一个 Article表,如下:
#p#副标题#e#
#p#分页标题#e#
建设Entity类ArticleIndex.java,建设Dao类ArticleIndexDao.java,建设 Manager类 ArticleIndexManager.java,这几个进程和前面的进程没有什么区别 ,所以我就不列代码出来了。为了淘汰编写Action的事情,我将添加 ActionIndex的行动放到了ArticleAction中,即在添加Article的同时添加 ArticleIndex。
修改applicationContext.xml文件,设置双份的dataSource、双份的 sessionFactory,并利用JTATransactionManager,如下:
<?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:jee="http://www.springframework.org/schema/jee" 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-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context- 2.5.xsd"
default-lazy-init="true">
<description>Spring民众设置文件 </description>
<!-- 界说受情况影响易变的变量 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderCon figurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<!-- 尺度设置 -->
<value>classpath*:/application.properties</value>
<!-- 当地开拓情况设置 -->
<value>classpath*:/application.local.properties</value>
<!-- 处事器出产情况设置 -->
<!-- <value>file:/var/myapp/application.server.properties</value&g t; -->
</list>
</property>
</bean>
<!-- 利用annotation 自动注册bean,并担保@Required,@Autowired的属 性被注入 -->
<context:component-scan base- package="personal.youxia" />
<bean id="dataSourceContent" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>jdbc/dataSourceContent</value>
</property>
<property name="xaDataSourceClassName">
<value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value >
</property>
<property name="xaProperties">
<props>
<prop key="serverName">localhost</prop>
<prop key="portNumber">3306</prop>
<prop key="databaseName">MultiDatasourceExample</prop>
<prop key="user">youxia</prop>
<prop key="password">******</prop>
</props>
</property>
<property name="poolSize">
<value>3</value>
</property>
</bean>
<bean id="dataSourceIndex" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>jdbc/dataSourceIndex</value>
</property>
<property name="xaDataSourceClassName">
<value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value >
</property>
<property name="xaProperties">
<props>
<prop key="serverName">localhost</prop>
<prop key="portNumber">3306</prop>
<prop key="databaseName">MultiDatasourceExample</prop>
<prop key="user">youxia</prop>
<prop key="password">******</prop>
</props>
</property>
<property name="poolSize">
<value>3</value>
</property>
</bean>
<!-- Hibernate设置 -->
<bean id="sessionFactoryContent" class="org.springframework.orm.hibernate3.annotation.AnnotationSession FactoryBean">
<property name="dataSource" ref="dataSourceContent" />
<property name="namingStrategy">
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect&l t;/prop>
<prop key="hibernate.show_sql">${hibernate.show_sql} </prop>
<prop key="hibernate.format_sql">${hibernate.format_sql} </prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCachePro vider
</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">${h ibernate.ehcache_config_file}</prop>
</props>
</property>
<property name="packagesToScan" value="personal.youxia.entity.*" />
</bean>
<bean id="sessionFactoryIndex" class="org.springframework.orm.hibernate3.annotation.AnnotationSession FactoryBean">
<property name="dataSource" ref="dataSourceIndex" />
<property name="namingStrategy">
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect&l t;/prop>
<prop key="hibernate.show_sql">${hibernate.show_sql} </prop>
<prop key="hibernate.format_sql">${hibernate.format_sql} </prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCachePro vider
</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">${h ibernate.ehcache_config_file}</prop>
</props>
</property>
<property name="packagesToScan" value="personal.youxia.entity.*" />
</bean>
<!-- 事务打点器设置,大都据源JTA事务-->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init- method="init" destroy-method="close">
<property name="forceShutdown"><value>true</value></property&g t;
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300"/>
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">< BR> <property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction"/>
</bean>
<!-- 利用annotation界说事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
修改web.xml,设置双份的OpenSessionInViewFilter,如下: 1321
#p#分页标题#e#
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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">
<display-name>MultiDatasourceExample</display-name>
<!-- Spring ApplicationContext设置文件的路径,可利用通配符,多个路 径用,号脱离
此参数用于后头的Spring Context Loader -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/applicationContext*.xml</param- value>
</context-param>
<!-- Character Encoding filter -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter- class>org.springframework.web.filter.CharacterEncodingFilter</fi lter-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>
<!-- SpringSide's Hibernate Open Session In View filter-- >
<filter>
<filter-name>hibernateOpenSessionInViewFilterContent</filter -name>
<filter- class>org.springside.modules.orm.hibernate.OpenSessionInViewFilter& lt;/filter-class>
<init-param>
<param-name>excludeSuffixs</param-name>
<param-value>js,css,jpg,gif</param-value>
</init-param>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactoryContent</param-value>
</init-param>
</filter>
<filter>
<filter-name>hibernateOpenSessionInViewFilterIndex</filter- name>
<filter- class>org.springside.modules.orm.hibernate.OpenSessionInViewFilter& lt;/filter-class>
<init-param>
<param-name>excludeSuffixs</param-name>
<param-value>js,css,jpg,gif</param-value>
</init-param>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactoryIndex</param-value>
</init-param>
</filter>
<!-- SpringSecurity filter-->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter- class>org.springframework.web.filter.DelegatingFilterProxy</filt er-class>
</filter>
<!-- Struts2 filter -->
<filter>
<filter-name>struts2Filter</filter-name>
<filter- class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecu teFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>hibernateOpenSessionInViewFilterContent</filter -name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>hibernateOpenSessionInViewFilterIndex</filter- name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Spring的ApplicationContext 载入 -->
<listener>
<listener- class>org.springframework.web.context.ContextLoaderListener</lis tener-class>
</listener>
<!-- Spring 刷新Introspector防备内存泄露 -->
<listener>
<listener- class>org.springframework.web.util.IntrospectorCleanupListener</ listener-class>
</listener>
<!-- session超时界说,单元为分钟 -->
<session-config>
<session-timeout>20</session-timeout>
</session-config>
<!-- 堕落页面界说 -->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/common/500.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/common/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/common/404.jsp</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/common/403.jsp</location>
</error-page>
</web-app>
在每一个Dao类内里利用@Resource注解指定利用哪一个SessionFactory。代 码我就不列出来了,运行项目举办测试,乐成。
#p#分页标题#e#
到此,我们的征途圆满竣事。可是SpringSide 3包括的特性远远不止这些, 在showcase中,江南白衣不绝在演示一些新的技能,这些技能假如用得得当,会 有效提高我们项目标开拓速度和项目标运行效率,在今后的日子里,我会慢慢为 各人揭开这些神秘的面纱。
#p#分页标题#e#
这里是该示例项目标源代码MultiDatasourceExample.rar,接待各人点击下 载,利用Eclipse 3.4导入后,即可以编辑和运行。由于jar文件太占空间,这个 源代码内里是不提供jar文件的,幸好我只给项目增加了mysql- connector.5.0.18.jar、 transaction-essential-all.jar两个和 jta.properties一个,其余的都是尺度的,各人可以以后外项目中拷贝过来。在 运行项目之前,各人必然要记到手动建设数据库,并修改设置文件内里的数据库 名和暗码。