一
整合铺垫
WEB项目下怎么运行Spring(之前都是写在java项目下,在main方法中运行的),及整合时IOC容器放在了哪个共同区域供其它框架使用?(放在了application作用域)
*和其它框架整合是以spring为桥梁,[ 使用spring IOC容器来管理,其它框架的重要对象 ],以Spring IOC、AOP为基础,对其它框架进行增强 和 控制 。
既然管理的是其它框架的重要对象,那么其它框架有什么重要对象呢?
1.struts2的重要对象就这两个:action 和 interceptor ,ognl只算做表达式语言
2.hibernate的重要对象:SessionFactory(一个数据库的内存镜像)、session
问题1****************Spring怎么用?就是建立一个IOC容器,从里面new对象,再从里面拿对象!!!!!!****************************
代码,当然要配合xml使用(xml见前面的文章)
public static void main(String[ ] arg){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[ ] {"applicationContext.xml"}
);
MyClassDao myClassDao = (MyClassDao)ac.getBean("myClassDao");
System.out.println(myClassDao.getClass.getName());
myClassDao.add();
myClassDao.del();
//用IOC容器new出对象后该怎么用还怎么用,调用方法啥的。。
}
问题2************在web项目下怎么运行Spring?之前的实例都是写在main方法中,是java项目,web项目没有main方法,是基于事件,通过容器启动的,要怎么运行?********
在web项目下,一段java代码的执行,一般基于特定事件,如下三种情形
(web项目下,java代码的触发条件)
1.web项目下基于http,请求——响应模型:一个请求过来,会有一个servlet或是filter来执行这段代码
2.服务器启动init、服务器关闭destroy,对应着项目的加载和项目的销毁
3.Listener 监听器,就是在web环境下,专门为了响应一些事件。监听器有很多种,其中有一种就是为了监听服务器的启动。其它的还有Session Listener、Request Listener、 Application Listener、也有为整个项目服务的Listener,有二、三十种,它是基于某个特定的事件的。
Spring在web项目下运行,解决方案
1.在项目启动时,创建IOC容器,选用这种方法启动会很慢,一般会加个Lazy,让IOC容器中的类在用时再创建
示例
1),建立一个web项目,建立一个包com.test.init包,在包下创建一个servlet,名叫InitServlet
public class InitServlet extends HttpServlet {
public void init() throws ServletException{
System.out.println("Spring IOC初始化!!!");
}
}
2),在web.xml中配置servlet
<servlet>
<servlet-name>initServlet</servlet-name>
<servlet-class>com.bjsxt.init.InitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
mapping就不用配置了,因为这次测试不需要让人访问,只是测试IOC容器创建,这是通过初始化tomcat时启动运行IOC容器
3),启动项目,就会通过初始化项目执行创建IOC容器了,这里只是用一句打印模拟了IOC容器的创建,需要换成真正的代码。
2.使用监听器启动IOC容器
1),建立包com.test.listener,里面有一个类ContextLoadListener.java
public class ContextLoadListener implements ServletContextListener { //servlet上下文监听
public void contextDestroyed(ServletContextEvent arg0){
}
public void contextInitialized(ServletContextEvent arg0){
System.out.println("Spring IOC初始化!!");
}
}
2),web.xml中的配置
<listener>
<listener-class>com.test.listener.ContextLoadListener</listener-class>
</listener>
3),启动项目,就会通过Listener执行创建IOC容器了,这里只是用一句打印模拟了IOC容器的创建,需要换成真正的代码
以上是两种怎样在web项目中创建IOC容器的方法(不是通过运行main方法),创建好IOC容器后,spring会在容器中创建其它框架的重要对象,怎么去拿这些对象来用呢?
问题3*************Spring的IOC容器存放到什么地方,方便其它框架从中获取相应bean??
( IOC容器放到什么地方大家才都能知道呢?web环境下能存储信息的,有什么地方?四个作用域!而application是共同都能访问到的*********************)
在web环境下,把IOC放到application中,来供别的框架获取
示例代码
1),建立一个web项目,把jar包拷入项目
aspectjrt.jar
aspectjveaver.jar
cglib-nodep-2.1_3.jar
commons-logging.jar
spring-sources.jar
spring.jar
2),把配置文件拷贝过来,放到WEBB-INF下的lib下面!!ApplicationContext.xml,作测试用,只配置简单的UserDao
<bean id="userDao" class="com.bjsxt.dao.UserDao"></bean>
3),建立一个包com.test.dao,里面建立一个UserDao.java
public class UserDao{
public UserDao(){
System.out.println("init......");
}
public void add(){
System.out.println("add......");
}
}
4),在web.xml中配置
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
5),现在启动web项目,IOC容器已经能创建了,是通过web.xml配置文件创建的。
6),在index.jsp中添加如下代码
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1" %> //要导入util包
<body>
<%
//先打印application中有哪些值,从而看看里面有没有IOC容器
Enumeration enm = (Enumeration) application.getAttributeNames();
while(enm.hasMoreElements()){
String str=(String)enm.nextElement();
out.println(str+"<br/>");
}
//通过ac容器获得bean的另一种方法
ApplicationContext ac = (ApplicationContext) application.getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
UserDao userDao = (UserDao) ac.getBean("userDao");
userDao.add();
%>
</body>
7),运行项目,访问http://localhost:8080/项目名/index.jsp,看打印出来有没有IOC容器
8),现在的运行结果是index.jsp页面上打印出application作用域里的所有值,控制台打印执行add方法的结果。这样的结果表明spring成功将IOC容器放到了application作用域中,供其它框架来获取。
二
Spring中整合struts2
问题,如果applciationContext.xml非想要放到src下(默认应该放在WEB-INF下),怎么办?
答:1.在web.xml当中添加如下
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
2.这样就可以把applicationContext.xml放在src下面了。运行项目试试吧
整合开始*******************************************
前提是Spring环境已经搭建好(jar包,applicationContext.xml已经拷贝到项目中)
1.建立一个包com.test.action,里面建类UserAction.java
public class UserAction{
private UserDao userDao;
public UserDao getUserDao(){
return userDao;
}
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public String add(){
return null;
}
}
2.在applicationContext.xml中配置如下
<bean id="userAction" class="com.bjsxt.action.UserAction" scope="prototype" > //这句的意思是这个action是多例的,这里一定要加scope="prototype",因为struts2是多例的,不然会报错
<property name="UserDao" ref="userDao"></property>
</bean>
3.把struts2的1ar包拷贝到项目中
(框架版本不一样,jar包内容会有些不同,2.3版本struts有asm包<asm包操作字节码的>,2.2没有,意味着2.1版本2.2版本没有动态代理,2.3版本加入了动态代理的支持)
a) apps\struts2-blank\WEB-INF\lib下的所有jar包都拷入
b) 把web.xml中的filter拷贝到自己项目
c) struts.xml拷到src下
4.在struts.xml中添加如下配置
<struts>
<constant name="struts.objectFactory" value="spring" ></constant> <!--这是个全局配置,有了这个配置,struts2就不会自己创建对象了-->
<package name="default" namespace="/" extends="struts-default"> //原本的struts2 action是这样写,class里是包名<action name="" class="com.bjsxt.action.UserAction"></action>
<action name="userAction" class="userAction" ></action> //有了IOC容器后不用写包名了,因为class里写的是IOC容器中action的ID,通过这个action的ID,去容器中去拿出来一个bean,当成action来使用。而且每次拿出的对象都是新的对象。这个class要和applicationContext.xml中的<bean id="">的id一样!!!
</package>
</struts>
5.有专门的jar包负责spring和struts2的连接,这个jar包是必导入的
在struts-2.2.1\lib\struts2-spring-plugin-2.2.1.1.jar,把它拷贝到项目下
6.测试
在上面的UserAction.java类中做如下改动
public String add(){
userDao.add();
return null;
}
7.还没有创建UserDao方法,如下
public class UserDao{
public UserDao(){
System.out.println("init......");
}
public void add(){
System.out.println("add......");
}
}
8.重启项目,访问http://localhost:8080/项目名/userAction!add
控制台能打印说明,整合是成功的,请求从filter到IOC到action到dao。
每刷新访问一次就多打印一个add,说明action是多例的,整合中确保struts2是多例的非常重要。
总结Struts2和spring整合必须的三步****************************
1.Struts2知道SpringIOC容器的存在<constant name="struts.objectFactory" value="spring"></constant>
2.actioni的class设置为applicationContext.xml中对应bean的id
<package name="default" namespace="/" extends="struts-default">
<action name="userAction" class="userAction"></action>
</package>
3.需要增加一个jar来处理struts2和spring之间的联系 struts-2.2.1\lib\struts2-spring-plugin-2.2.1.1.jar
——————Spring 和 Struts2 整合 end——————————————
Spring和hibernate整合
Spring来管理SessionFactory和Session
回顾SessionFactory的三类配置信息:
1.数据库连接信息(driver驱动 用户名 密码)
2.hibernate全局参数
3.mapping映射文件信息
*想由spring来管理SessionFactory,必须由Spring来配置这三类信息才可以
spring提供了hibernate的辅助工具类(提供了一个类),来帮我们管理SessionFactory的创建
这个类是放在Spring-framework-2.5.6\src\org\springframework\orm\hibernate3下的LocalSessionFactoryBean.java,这个类是spring管理sessionFactory创建的一个最重要的类。还有一个子类也起相同作用:AnnotationSessionFactoryBean
LocalSessionFactoryBean配置过程中比较重要的属性(可以通过反编译工具看这个类的源码得知)
1.String[ ] mappingResources这个属性管理的是hibernate中mapping的映射文件信息
2.properties hibernateProperties管理的是hibernate中的全局参数,也可以包含数据库连接信息
3.dataSource Pool通过数据库连接池管理连接,也可以直接创建连接
现在是直接创建连接的示例————————————————
示例代码
1.applicationContext.xml
<bean id="userDao" class="com.test.dao.UserDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> //这个类是在spring的jar包中的,这样直接引用就能用
<property name="mappingResources"> //映射文件
<list>
<value>com / test / po / User.hbm.xml</value> //这里面放的是User.hbm.xml ,po的配置文件
</list>
</property>
<property name="hibernateProperties"> //全局参数
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.url">jdbc:mysql://locahost:3306/test</prop>
<prop key="hibernate.connection.username">root</prop>
<prop key="hibernate.connection.password">1234</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
2.建包com.test.po,里面有User.java类和User.hbm.xml
User.java
public class User{
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory(){
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public void add(User user){
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commint();
session.close();
}
}
User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bjsxt.po">
<class name="User" table="t_user" lazy="false" ><id name="id" column="id" >
<!-- 根据数据库本身的能力去选择 id生成方式。 -->
<generator class="native"></generator>
</id>
<property name="name" column="username" ></property>
<property name="phone" column="phone" ></property>
<property name="age" ></property>
</class>
</hibernate-mapping>
3.拷贝hibernate的jar包到自己的项目
antlr-2.7.6.jar
asm-attrs.jar
asm.jar
cglib-2.1.3.jar
commons-collections-2.1.1.jar
commons-logging-1.0.4.jar
dom4j-1.6.1.jar echache-1.2.jar
hibernate3.jar
jta.jar
mysql-connection-java-5.1.13.jar
4.Test.java
public class Test{
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}
);
UserDao dao = (UserDao) ac.getBean("userDao");
User user = new User("xiaogao","123",12);
dao.add(user);
}
}
5.运行Test.java,如果可以在数据库中生成t_user表,并且里面有xiaogao的信息,说明spring和hibernate整合成功
6.在spring和hibernate整合好的基础上,然后再把spring和struts2整合的部分加进来,测试一下看看能不能通过action给数据库传参数进去。挺重要的,会了这个,就会这三大框架的
整合开发
a) 步骤就不写了,上面有个spring和struts整合的步骤
b) UserAction.java里
public class UserAction{
private UserDao userDao;
public UserDao getUserDao(){
return userDao;
}
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
private User user;
public User getUser(){
return user;
}
public void setUser(User user){
this.user = user;
}
public String add(){
userDao.add(user);
return null;
}
}
7.启动项目,访问http://localhost:8080/项目名/userAction!add?user.name=cai10,访问后看看数据库中有没有添加名字为cai10的信息,有则三大框架整合成功!!!!!!!!!
以上只是最基本的整合,数据库连接池没加,事务管理没加,hibernateTemplate没使用,opensession没使用,这四个是spring给hibernate提供的辅助功能。
三大框架整合end———————————————————
—————HibernateTemplate———————
HibernateTemplate简化DAO的编写,甚至可以代替DAO层,它是由spring提供的。因为它包装了dao,所以在用的时候需要往里面传入sessionFactory(SessionFactory是连接数据库的,所以传入SessionFactory后它就具备了连接数据库的能力)
1.用HibernateTemplate的时候,需要在applicationContext.xml配置文件中增加:
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--txManager管理事务的开启和关闭-->
<bean id="txManager" class="org.springframework.orm.hibernate3.hibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--开启annotation方式的事务管理-->
<tx:annotation-driven transaction-manager="txManager"/>
2.以前的dao,需要创建Session关闭Session,开启事物、关闭事物(事务是指opensession)。这些话是重复的,HibernateTemplate把这几句话封装起来了UserAction.java重新写,不使用UserDao了,用HibernateTemplate(它就相当于一个BaseDao,或者一个公共的DAO对象)
public class UserAction{
private User user;
public User getUser(){
retrun user;
}
public void setUser(User user){
this.user = user;
}
private HibernateTemplete hibernateTemplate;
public HibernateTemplate getHibernateTemplate(){
return hibernateTemplate;
}
public void setHibernateTemplate(HibernateTemplate hibernateTemplate){
this.hibernateTemplate = hibernateTemplate;
}
@Transactional
public String add(){
hibernateTemplate.save(user); //一个save方法满足了原来的5行代码
//hibernateTemplate.delete(entity); //删除
//hibernateTemplate.update(entity);
//hibernateTemplate.find("from User"); //from User是一个hql语句,被hibernateTemplate包装后的查询很简单,放入hql语句,就能返回一个List
//平时的CRUD变成了hibernateTemplate的这四句话。
return null;
}
//这个方法测试时可以关闭或打开,查询所有
public String findAll(){
List<User> list = hibernateTemplate.find("from User");
for(Iterator iterator = list.iterator(); iterator.hasNext();){
User user = (User) iterator.next();
System.out.println(user.getName()+"--"+user.getId());
}
return null;
}
private String name;
public String findByCondition(){
List<User> list = hibernateTemplate.find("from User u where u.name=?",new Object[]{name}); //逗号后的值对应前面那个问号
for(Iterator iterator = list.iterator();iterator.hasNext();){
User user = (User) iterator.next();
System.out.println(user.getName());
}
return null;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
技巧:报空指针时,先找报错那行的点,点前面的对象肯定没创建。!!!
3.在applicationContext.xml中增加
<bean id="userAction" class="com.bjsxt.action.UserAction" scope="prototype">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
4.写user类
public class User{
private Integer id;
private String name;
private String phone;
private Integer age;
public User(String name,String phone,Integer age){
super();
this.name = name;
this.phone = phone;
this.age = age;
}
public User(){
super();
}
public Integer getId(){
return id;
}
public void setId(Integer id){
this.id = id
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name
}
public String getPhone(){
return phone;
}
public void setPhone(String phone){
this.phone = phone;
}
public Integer getAge(){
return age;
}
public void setAge(Integer age){
this.age = age;
}
}
5.写测试类Test.java
public class Test{
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}
);
UserAction userAction = (UserAction) ac.getBean("userAction");
System.out.println(userAction.getClass().getName());
//测试时这段代码可根据情况注释掉
User user = new User();
user.setName("xiaogao");
userAction.setUser(user);
userAction.add();
userAction.setName("xiaogao");
userAction.findByCondition();
}
}
**Spring对hibernate的事务有单独的切面管理
———————hibernateTemplate end———————————————————————————————