写android有段时间了,感觉思维越写越狭窄,考虑问题越来越局限了,看不到一个项目整体的设计和构架,觉得很有必要多多写一些大型的框架性的东西来提高自己的视野。
从接触java到现在一年多了,在我的印象里,struts好像是用来接收请求然后处理,将处理结果在跳转到jsp上显示的;spring就是 一个大型的工厂,专门生产业务的类;hibernate就是负责和数据库勾结,然后提供数据的。惭愧啊,我居然从来都没有用过SSH三大框架,居然我也能 鬼使神差的工作了,而且工作了这么长时间了,趁现在空暇和还未在被公司开掉之前,赶紧学习学习,也为将来复习记录一笔。
工欲善其事,必先利其器。首先要把所有的jar文件找好,查了一下百度,发现需要的jar文件如下:
*Spring2.5 jar文件 dist\spring.jar dist\modules\spring-webmvc-struts.jar lib\jakarta-commons\commons-logging.jar lib\aspectj\aspectjweaver.jar、aspectjrt.jar lib\cglib\cglib-nodep-2.1_3.jar lib\j2ee\common-annotations.jar *Struts1.3 jar文件 apps\struts-blank-1.3\WEB-INF\lib 下有所有的jar文件 *Hibernate3.3 jar文件 hibernate3.jar lib\required\*.jar lib\optional\ehcache-1.2.3.jar hibernate 注解安装包下的 lib\test\slf4j-log4j12.jar Struts 下载struts-1.3.8-lib.zip,需要使用到解压目录下的所有jar,建议把jstl-1.0.2.jar和standard-1.0.2.jar更换为1.1版本。Spring中已经存在一个antlr-2.7.6.jar,所以把struts中的antlr-2.7.2.jar删除,避免jar冲突。 *数据库驱动jar
看到上面N多的jar是不是感觉脑袋都大了,上面列出来的只是为了让自己更明白到底使用了哪些东西?属于谁的?分别有什么用?如果你没有把它一个一个从下载好的包里面把它们挑选出来,那么就点击
这里
下载吧,这里我已经把上面所提到和未提到但是也需要的jar都选了出来。
当然,其他的比如Tomcat和jdk环境配置以及数据库神马的(说到数据库,因为我使用的是ubuntu系统,使用mysql数据库,一直用
的是一个叫emma的图标是一个海豚的图形管理工具,感觉用起来很不错,ubuntu软件中心就有的下,搜索关键字:mysql),我就不多说了。默认都
是可用的。
三大框架大体的整合思路应该是先写好spring,然后把hibernate弄进来,最后在写struts。在这里,就整一个小小的人员管理。好吧,整合开始!
1,新建一个web项目SSH,将上面下载的jar一股脑的放到WEB-INF中的lib目录下
2,在类路径下新建beans.xml文件,并且定义Person.java类,里面包含三个id,name,age字段
beans.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: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"> <bean id="personService" class="com.pccw.service.impl.PersonServiceImpl"/> </beans>
Person.java:
public class Person { private Integer id; private String name; private Integer age; public Person() {} public Person(String name,Integer age){ this.name = name; this.age = age; } 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "name:"+this.name+",age:"+age; } }
3,定义一个接口PersonService,里面包含对人员的增删改查方法,并写一个实现类PersonServiceImpl来实现他
PersonService:
public interface PersonService { public void save(Person person); public void delete(Integer personId); public void update(Person person); public Person getPerson(Integer personId); public List<Person> getPersons(); }
PersonServiceImpl:
public class PersonServiceImpl implements PersonService { private SessionFactory sessionFactory; @Override public void save(Person person) { } @Override public void delete(Integer personId) { } @Override public void update(Person person) { } @Override public Person getPerson(Integer personId) { return null; } @SuppressWarnings("unchecked") @Override public List<Person> getPersons() { return null; } }
4,加入hibernate的一些元素,在2中定义好的beans.xml中加入数据源,hinernate的SessionFactory,hinernate的事务管理器,以及配置注解和各种的命名空间地址
beans.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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <context:annotation-config /> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.gjt.mm.mysql.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/duan?useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="19891126"/> <!-- 连接池启动时的初始值 --> <property name="initialSize" value="1"/> <!-- 连接池的最大值 --> <property name="maxActive" value="500"/> <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 --> <property name="maxIdle" value="2"/> <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 --> <property name="minIdle" value="1"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingResources"> <list> <value>com/pccw/damon/Person.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQL5Dialect hibernate.hbm2ddl.auto=update hibernate.show_sql=false hibernate.format_sql=false </value> </property> </bean> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <tx:annotation-driven transaction-manager="txManager"/> <bean id="personService" class="com.pccw.service.impl.PersonServiceImpl"/> </beans>
5,根据SessionFactory中的属性,还需要定义一个Person.hbm.xml文件,该文件为Person类与数据库中的表对应关系的一个文件
Person.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.pccw.damon"> <class name="Person" table="person"> <id name="id"> <generator class="native"/> </id> <property name="name" length="20" not-null="true"/> <property name="age" type="integer" not-null="true"/> </class> </hibernate-mapping>
可以看到该文件对应的数据库中的表为person,三个字段。
6,当上面的步骤都完成之后,在第3步中的实现类PersonServiceImpl中补全所有的方法
PersonServiceImpl:
@Transactional //事务注解 public class PersonServiceImpl implements PersonService { @Resource private SessionFactory sessionFactory; //注解注入 @Override public void save(Person person) { sessionFactory.getCurrentSession().persist(person); } @Override public void delete(Integer personId) { sessionFactory.getCurrentSession().delete(sessionFactory.getCurrentSession().load(Person.class, personId)); } @Override public void update(Person person) { sessionFactory.getCurrentSession().merge(person); } @Override public Person getPerson(Integer personId) { return (Person)sessionFactory.getCurrentSession().get(Person.class, personId); } @SuppressWarnings("unchecked") @Override public List<Person> getPersons() { return (List<Person>)sessionFactory.getCurrentSession().createQuery("from Person").list(); //这里的Person为大写的P,及第5步里面的class的name } }
7,确定无误之后,测试一下spring于hibernate的整合效果,新建一个测试单元SSHTest.java,测试PersonServiceImpl中的所有的方法。
public class SHTest { private static PersonService personService; @BeforeClass public static void setUpBeforeClass() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); //实例化spring容器 personService = (PersonService)ctx.getBean("personService"); //得到PersonService } @Test public void testSave() { for(int i = 0;i<10;i++){ personService.save(new Person("canmeng"+(i+1),20+i)); } } @Test public void testDelete() { personService.delete(1); } @Test public void testUpdate() { Person person = personService.getPerson(2); person.setName("canmeng2"); person.setAge(21); personService.update(person); } @Test public void testGetPerson() { System.out.println(personService.getPerson(2).toString()); } @Test public void testGetPersons() { List<Person> list = personService.getPersons(); for(Person person : list){ System.out.println(person.toString()); } } }
8,以上测试无误后,开始整合struts,在web.xml中注册spring配置文件,也就是在web容器中实例化spring容器,并在web.xml中指定struts的Servlet和请求格式
web.xml:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>SSH</display-name> <!-- 指定spring的配置文件,默认从web根目录寻找配置文件,我们可以通过spring提供的classpath:前缀指定从类路径下寻找 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> </context-param> <!-- 对Spring容器进行实例化 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
9,从上面的配置文件中可以看出,需要在WEB-INF目录下建立struts-config.xml的配置文件,在这里,整合struts有三种方法,先讲第一种。
struts-config.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"> <struts-config> <form-beans> </form-beans> <action-mappings> <action path="/person/list" type="com.pccw.action.PersonAction"> <forward name="list" path="/WEB-INF/page/personlist.jsp"></forward> </action> </action-mappings> </struts-config>
可以看到访问路径/person/list,对应的Action为PersonAction,跳转的jsp为WEB-INF下的page目录下的personlist.jsp
10,web.xml定义好之后,着手写Action,定义PersonAction,继承Action,实现其中的excute方法,这里要小
鑫,excute在这里有两个方法,需要实现方法里面参数是HttpServletRequest request,
HttpServletResponse response的才能接收到请求
PersonAction:
public class PersonAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //--------------------------------------- 1 --------------------------------------------------------------- System.out.println("request come ~~~~~"); WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext()); //为了获得业务服务,使用 WebApplicationContextUtils获得一个 ApplicationContext。可以查找一个 Spring bean。 PersonService personService = (PersonService)ctx.getBean("personService"); request.setAttribute("persons", personService.getPersons()); System.out.println("get size:"+personService.getPersons().size()); return mapping.findForward("list"); } }
很显然,这种写法简单并且易于理解。不幸的是,它将 Struts 动作与 Spring 框架耦合在一起。如果您想替换掉 Spring,那么您必须重写代码。并且,由于 Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优势。当使用多重独立的 Spring 环境时,这种技术可能有用,但是在大多数情况下,这种方法不如另外两种方法合适。
于是,第二种方式就是可以把Action也交给spring容器来管理,通过把业务bean注入的方式注入到Action中,这样可以大大的简化Action,而且可以使得struts和spring解耦。第9步中的struts-config可以改成如下:
<struts-config> <form-beans> </form-beans> <action-mappings> <action path="/person/list" type="org.springframework.web.struts.DelegatingActionProxy"> <forward name="list" path="/WEB-INF/page/personlist.jsp"></forward> </action> </action-mappings> </struts-config>
DelegatingActionProxy这个类的作用就是在struts接收到请求之后,会直接交给spring容器处理,spring容 器会根据一开是就在beans.xml中注册的bean来寻找是否对应的bean,beans.xml中一开始需要把Action注册进去:
beans.xml中加入:
<bean name="/person/list" class="com.pccw.action.PersonAction"/>
这里的name必须跟签名struts-config中的path规则一样,当beans.xml中这样配置之后,根据name属性找到该bean,就可以产生相应的Action对象,于是Action中的代码可以改成:
PersonAction.java:
public class PersonAction extends Action { @Resource private PersonService personService; //注解注入 @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //------------------------------ 1 --------------------------------------------- // System.out.println("request come ~~~~~"); // WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext()); // PersonService personService = (PersonService)ctx.getBean("personService"); // request.setAttribute("persons", personService.getPersons()); // System.out.println("get size:"+personService.getPersons().size()); // return mapping.findForward("list"); // ------------------------------ 2 --------------------------------------------- request.setAttribute("persons", personService.getPersons()); return mapping.findForward("list"); } }
第三种方式跟第二种差不多,在struts-config.xml中加入一个控制器属性:
struts-config.xml:
<struts-config> <form-beans> </form-beans> <action-mappings> <action path="/person/list"> <forward name="list" path="/WEB-INF/person/person_list.jsp" /> </action> </action-mappings> <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/> <message-resources parameter="MessageResources" /> </struts-config>
其作用跟第二种方式中的type类差不多,其他的配置和第二种方式一样,这样的方式称为:动作委托方式。
11,当上面的配置都完成之后,把jsp准备好:
personlist.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>人员列表</title> </head> <body> <c:forEach items="${persons}" var="person"> id=${person.id },name=${person.name },age=${person.age}<br> </c:forEach> </body> </html>
12,启动tomcat,把项目加载进去,打开浏览器,输入:http://localhost:8080/SSH/person/list.do,便可以在页面上看到所有的数据库中的数据了。(这里只实现了查询数据库所有数据的功能)。