標籤:des style class blog code java
因為公司涉及項目使用SSH,為瞭解SSH搭建方式和運作原理,就自己搭建了一個。
採用盡量以最少的JAR包,搭建一個簡單的struts2+spring+hibernate環境,希望像我這樣的入門者都能理解,如果大家使用過類似的MVC模式如Microsoft MVC,就容易理解得多了。
首先我使用的是MyEclipse 9+Tomcat 6(據說Tomcat和struts版本會有不相容,但沒遇上,不知道是不是真的)。
我下載的是struts2.3.15.1的JAR包(已包含spring)官網:http://struts.apache.org/download.cgi#struts23151
hibernate因為官網版本已到hibernate4,擔心不相容,所以去新浪共用下載hibernate3.3.2,http://ishare.iask.sina.com.cn/f/33704027.html
下載完成後,開始搭建。
第一步,使用struts2。
匯入struts所需的包:
strust-core-xxx.jar xwork-core-xxx.jar commons-io-xxx.jar
commons-fileupload-xxx.jar commons-lang-xxx.jar commons-logging-xxx.jar
freemarker-xxx.jar javassist-xxx.GA.jar ognl-xxx.jar
匯入包的方式有很多,可以在Build Path裡面 Add Extenal JARs添加,可以建立一個自訂的Librariy添加這些包然後再匯入這個Library。我就用最簡單的方式,把這些包複製到項目的WebRoot->WEB-INF->lib下面,這樣項目就會自動把包匯入到Referenced Libraries下面了。
匯入包後編譯一下,順利運行Tomcat,我們就可以測試一下Struts了。在src目錄下建立一個struts.xml,內容如下:
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"><struts> <!-- 需要Spring時添加 --> <!-- <constant name="struts.objectFactory" value="spring" /> --> <package name="default" extends="struts-default"> <action name="login" class="com.struts2test.action.LoginAction" method="execute"> <result name=‘success‘>/index.jsp</result> <result name=‘login‘>/login.jsp</result> </action> </package> </struts>
如上面所示"default"包是Web請求到Struts會首先進入這裡來尋找我們的action路徑。
項目為了支援Struts,我們還需在WebRoot -> WEB-INF下面修改web.xml,內容如下:
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list></web-app>
添加的filter和filter-mapping顧名思義是過濾器,所有用戶端Web請求都會首先進入這個web.xml,是WEB項目最基礎的一個設定檔,其他檔案都是這個xml導航過去的。傳統的方式是直接使用Servlet直接導航到方法,這樣項目層次很少,大家都應該知道,層次少開發容易維護就比較麻煩,層次多一些開發會麻煩但是維護則顯得容易很多。Struts其實也是封裝了Servlet方法罷了。
然後就建立一個com.struts2test.action包放所有的action方法,在這個包下建立一個Class類,如struts.xml裡面命名為LoginAction即可,內容如下:
package com.struts2test.action;import com.opensymphony.xwork2.ActionSupport;public class LoginAction extends ActionSupport {// 該類繼承了ActionSupport類。這樣就可以直接使用SUCCESS, // LOGIN等變數和重寫execute等方法 private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String execute() throws Exception { if (username.equals("admin") && password.equals("123"))//返回SUCCESS;否則,返回LOGIN return SUCCESS; return LOGIN; }}
上面所示,我們需要為username和password一個setter和getter,這樣頁面傳值這裡將可以接收並給他們賦值,可以推測,頁面傳值也是注入進來的。
有了這個方法,我們就可以根據login.jsp提交的username和password來判斷進入index首頁了!
index首頁內容就隨便,login.jsp也很簡單,內容如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%
String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="<%=basePath%>"> <title>My JSP ‘login.jsp‘ starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form method="post" action="login"> 登入名稱:<input name=‘username‘ type="text" /><br/> 密碼:<input name =‘password‘ type="password" /><br/> <button type="submit" style="width: 70px; height: 20px;">確定</button> </form> </body></html>
做過基本的HTML傳值的應該都知道input的name屬性是用來傳值的,所以應該和我們上面LoginAction方法的username和password名字一樣,不然傳值會失敗的。
萬事俱備,發布到Tomcat上編譯運行。通過 http://localhost:8080/項目名/login.jsp 就能訪問我們的網站了。輸入admin/123進入index.jsp,就是成功了!
第二步,在struts基礎上使用spring。
匯入spring所需要的包:
strus2t-spring-plugin-xxx.jar spring-core-xxx.jar spring-context-xxx.jar
spring-bean-xxx.jar spring-web-xxx.jar spring-asm-xxx.jar spring-expression-xxx.jar
使用spring主要是依賴注入和切面編程,這裡就利用spring注入username和password給LoginAction試試,這樣無論介面輸入什麼都無所謂,程式都使用我注入的username和password了。
為了使Struts支援Spring(當Struts尋找到action的時候同時用Spring注入bean),要在Struts.xml添加如下語句:
<constant name="struts.objectFactory" value="spring" />
前面已經寫了,取消注釋即可。
然後在src目錄下建立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: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"> <bean id="LoginAction" class="com.struts2test.action.LoginAction"> <property name="username" value="admin"> </property> <property name="password" value="123"> </property> </bean></beans>
這樣之後,重新部署Tomcat啟動,我們在login.jsp上面無論輸入什麼,我們都可以跳轉到index.jsp。因為spring已經幫我們注入了一個固定的值。
這裡可以看到,我們使用多少個bean就需要在這裡配置多少個,這樣其實就顯得麻煩,和傳統的配置Servlet差不多的樣子。其實我們可以使用一個Spring自動掃描bean的功能,我們上面匯入的spring-context-xxx.jar就帶有這個功能,在applicationContext.xml裡面加入:
<context:annotation-config /> <!-- 讓spring自動掃描指定包下面註解@Controller,@Service,@Resposity,@Comopnent --> <context:component-scan base-package="com.struts2test" />
即可,這樣我們只需在類上標識@Respository,項目就會掃描到將其識別為bean,與我們顯式手寫一樣。要調用這個bean的地方我們使用@Resource標識這個變數即可,而且這樣的方式可以不寫setter和getter,方便,代碼也簡潔。具體的用法大家可以網上搜一下,很多其他的功能我還沒用過,就不多講了。
第三步,使用hibernate。
如果大家接觸過Microsoft MVC,就應該知道和Linq其實是差不多的一個東西,畢竟微軟很多都是仿照別人的東西,只是封裝的好,用起來方便而已。使用hibernate官方有一個很好的文檔,有中文版的,我也是參考文檔來寫hibernate配置的,建議大家看文檔:http://docs.jboss.org/hibernate/core/3.5/reference/zh-CN/html_single/
使用hibernate之前,我們還需要使用資料庫連接jar包,隨各位想用什麼資料庫便下載什麼jar包。我使用的是mysql,在網上下載了一個mysql-connetor-java-5.1.12.jar。
然後也把hibernate的jar包匯入:
hibernate3.jar commons-collections-xxx.jar cglib-xxx.jar jta-xxx.jar
antlr-xxx.jar dom4j-xxx.jar slf4j-api-xxx.jar slf4j-log4j12-xxx.jar
建立com.struts2test.vo包放資料庫對應類和對應檔,建立一個Users類作為登陸使用者類即可,其中包括username和password兩個屬性即可,記得給他們setter和getter。
OK之後,還要建立這個類的資料庫映射,我們必須告訴資料庫那個類對應哪個表,哪個屬性對應哪個欄位。同樣在com.struts2test.vo包下建立一個Users.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.struts2test.vo"> <class name="Users" table="Users"> <id name="username" column="username" type="string"> <generator class="native" /> </id> <property name="password" column="password" type="string" /> </class></hibernate-mapping>
以上顯示username是<id>,說明username是主鍵。我們資料庫建立表的時候也必須給Users表username欄位設定為主鍵。貌似沒有主鍵是不行的 - - 當然給每張表建立主鍵是一個好習慣,即使不會使用到也應該建立。
最後我們在src目錄下建立一個hibernate資料庫連接設定檔hibernate.cfg.xml,內容如下:
<?xml version=‘1.0‘ encoding=‘utf-8‘?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/MySQL</property> <property name="connection.username">資料庫使用者名稱</property> <property name="connection.password">資料庫密碼</property> <!-- JDBC connection pool (use the built-in) --> <!-- <property name="connection.pool_size">1</property> --> <!-- SQL dialect SQL方言,選擇你的資料庫方言 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Enable Hibernate‘s automatic session context management --> <property name="current_session_context_class">thread</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Drop and re-create the database schema on startup --> <!-- <property name="hbm2ddl.auto">update</property> --> <mapping resource="com/struts2test/vo/Users.hbm.xml" /> </session-factory></hibernate-configuration>
這裡很多property參數,大家可以看文檔介紹或網上搜,具體就不說了。最主要的是<mapping resource>這行,hibernate的對應檔應該都寫在這裡,也就是使用的表都要在這裡mapping一下。
這樣便完成了資料庫映射。
但是針對我們的登入,仍然需要將資料庫映射資料Select出來,看頁面傳值與資料庫映射資料是否對應。於是建立一個com.struts2test.dao包,包下建立一個UserDao類。內容如下:
package com.struts2test.dao;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import com.struts2test.vo.Users;public class UserDao { public boolean Login(Users login){ Configuration cfg = new Configuration(); SessionFactory factory = cfg.configure().buildSessionFactory(); Session session = factory.openSession(); Query q = session.createQuery("from Users where 1 = 1 and username = ‘" + login.getUsername() + "‘ and password = ‘" + login.getPassword() + "‘"); User user = (User)q.uniqueResult(); if(user != null) return true; return false; }}
hibernate查詢的方式大致如上面所示:Configuration -> SessionFactory -> Session -> Query。算是一個固定的方式。參考hibernate文檔就可以了。
上面類似SQL的查詢語句中from Users這個Users不是指資料庫的表了,而是Users類,以前犯過錯誤我定義類名時定義成User,而資料庫裡是Users,映射也對了,但是怎麼也查詢不出來,主要就是由於這個原因,hibernate完成映射後查詢就面對對象了。
我們使用這樣的方式,所以我們要修改LoginAction判斷方式,LoginAction方法需要調用UserDao的Login方法來判斷即可。這個UserDao可以new出來,也可以Spring注入進去,因為剛學習了Spring,我就試著用Spring來注入。成功!
附帶一下整個項目的分類樹:
如上面所說的,我們導了很多包,其實我也不知道導的包是否必要,都是網上建議的。其實有個比較笨的導包方法,我們首先在空項目中匯入最核心的包,如struts-core-2.3.15.1.jar,spring-core.jar,hibernate3.jar,直接編譯後將會提示錯誤,我們看錯誤就可以推測仍缺哪個包。我搭建的時候看了很多網上的說法,必須要哪個哪個包,其實都不一定。比如很多都說要log4j提供讀寫日誌功能這個包,我搭建項目沒有使用到日誌功能,沒有加入這個包編譯也是通過的。