寫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;}@Overridepublic 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;@Overridepublic void save(Person person) {}@Overridepublic void delete(Integer personId) {}@Overridepublic void update(Person person) {}@Overridepublic Person getPerson(Integer personId) {return null;}@SuppressWarnings("unchecked")@Overridepublic 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/beanshttp://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; //註解注入@Overridepublic void save(Person person) {sessionFactory.getCurrentSession().persist(person);}@Overridepublic void delete(Integer personId) {sessionFactory.getCurrentSession().delete(sessionFactory.getCurrentSession().load(Person.class, personId));}@Overridepublic void update(Person person) {sessionFactory.getCurrentSession().merge(person);}@Overridepublic Person getPerson(Integer personId) {return (Person)sessionFactory.getCurrentSession().get(Person.class, personId);}@SuppressWarnings("unchecked")@Overridepublic 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;@BeforeClasspublic static void setUpBeforeClass() throws Exception {ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); //執行個體化spring容器personService = (PersonService)ctx.getBean("personService"); //得到PersonService}@Testpublic void testSave() {for(int i = 0;i<10;i++){personService.save(new Person("canmeng"+(i+1),20+i));}}@Testpublic void testDelete() {personService.delete(1);}@Testpublic void testUpdate() {Person person = personService.getPerson(2);person.setName("canmeng2");person.setAge(21);personService.update(person);}@Testpublic void testGetPerson() {System.out.println(personService.getPerson(2).toString());}@Testpublic 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 {@Overridepublic 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; //註解注入@Overridepublic 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,便可以在頁面上看到所有的資料庫中的資料了。(這裡只實現了查詢資料庫所有資料的功能)。