我沒有使用maven,直接使用Eclipse創建動態Web項目,jar包復制在了lib下。這樣做導致我馬上概述的項目既依賴Eclipse和其項目結構,又依賴我復制在lib下的那些jar包版本。
jar包下載地址:http://pan.baidu.com/s/1gdARAy3
但是我現在還是會以這種形式闡述,因為對於接觸新事物而言的人,我覺得首先需要的是熱情,這樣才能有勇氣面對嘗試過程中的失敗。熱情從哪里來?熱情從在事物獲得的每一點成就感而來,現在按照以下步驟,我們來獲得一點成就感,然后再討論技術層面的事情(我記得以前剛學Java的時候,如果沒有Eclipse那神奇的自動補全,我一定堅持不下來,早就轉行了。不切實際的艱苦只能浪費時間和磨練心性,它在某些時候不一定是必要的,它應當成為一個可選項而不是一條必經路)。
環境Spring3.2.0,Hibernate4.1.6,Eclipse 3.7,Tomcat5.5,JDK1.6.45,Oracle10g(不要對我的環境版本搭配和數據庫使用抱有異議,我本地恰好就是JDK1.6.45的,恰好Tomcat就是5.5的,恰好Oracle在新建項目前就已經安裝好了)。
這是一個SSH項目,所以我假設各位了解或聽過一些J2EE的術語,我們將躍過“從入門到精通”系列的引言,直接讓你來看看我到底是怎么做的,還有那中間的波折。
首先,我在Eclipse下建立了一個動態Web項目,這時候除了目錄結構外,唯一有點內容的就是WEB-INF下的web.xml了,大話不多說,如果你已經把我貼了下載地址的jar包復制到了lib下,那么在web.xml里復制如下內容。
1 <listener> 2 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 3 </listener> 4 5 <context-param> 6 <param-name>contextConfigLocation</param-name> 7 <!-- <param-value>/WEB-INF/applicationContext.xml</param-value> --> 8 <param-value>classpath:applicationContext.xml</param-value> 9 </context-param> 10 <servlet> 11 <servlet-name>springMVC</servlet-name> 12 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 13 <init-param> 14 <param-name>contextConfigLocation</param-name> 15 <param-value>classpath*:spring-mvc.xml</param-value> 16 </init-param> 17 <load-on-startup>1</load-on-startup> 18 </servlet> 19 <servlet-mapping> 20 <servlet-name>springMVC</servlet-name> 21 <url-pattern>/</url-pattern> 22 </servlet-mapping> 23 <filter> 24 <filter-name>encodingFilter</filter-name> 25 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 26 <init-param> 27 <param-name>encoding</param-name> 28 <param-value>UTF-8</param-value> 29 </init-param> 30 <init-param> 31 <param-name>forceEncoding</param-name> 32 <param-value>true</param-value> 33 </init-param> 34 </filter> 35 <filter-mapping> 36 <filter-name>encodingFilter</filter-name> 37 <url-pattern>/*</url-pattern> 38 </filter-mapping>
Very Nice!現在除了自動的xml頭,<welcome-file-list>,就是以上spring配置信息了。這里配置了Spring和SpringMVC,<listener>和contextConfigLocation是對spring的配置,前者是spring的監聽類,后者是spring配置文件的路徑,這里一目了然,毫無疑問。
然后從servlet開始,都是SpringMVC的配置,這里先后配置了類似全局Filter的類DispatcherServlet的路徑,然后是SpringMVC的配置文件,我們將在那兒啟用我們的全注解功能。servlet-mapping就真的像Filter一樣,配置了需要攔截的請求路徑,最后是一些字符集配置,在領略到成就感之前不敘述了,免得打擊士氣。
和剛才配置的信息一致的,我們在src下建立applicationContext.xml(這名字好長!雖然可以換掉它,但我在項目里一看見這名字就知道它是干什么的了,所以不換了)和servlet-mvc.xml。
首先配置applicationContext:
<?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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL" /> <property name="username" value="fm" /> <property name="password" value="admin" /> </bean> <!-- 配置Hibernate --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="packagesToScan" > <list> <value></value> </list> </property> <property name="hibernateProperties"> <props> <prop key="dialect">org.hibernate.dialect.Oracle10gDialect</prop> <prop key="hibernate.current_session_context_class">thread</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> <context:annotation-config /> <context:component-scan base-package="com.eap.filemanager.service" /> <context:component-scan base-package="com.eap.pub.user.service.impl" /> <context:component-scan base-package="com.eap.pub.user.dao" /> </beans>
全部的內容,各位直接復制唄。這里xml頭包括了注解的路徑,然后配置DataSource,配置Hibernate,最后一段就是啟用注解了,說是<context:annotation-config />在這個版本已經不需要寫了,反正我項目現在正在跑着,先復制上來再說。最后路徑掃描,我是定義到包的,因為通配符好像沒起作用,老是報錯,我就把所有需要掃描的包都寫上去了。
接下來是SpringMVC,配置SpringMVC之前,其實各位已經可以開始和數據庫進行交互操作了,可以編寫DAO的代碼了,我再說一遍,DAO是Data Access Object,這一層該寫什么不該寫什么,這名字清清楚楚了已經!
servlet-mvc.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- ViewResolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> <!-- 使用默認的注解映射 --> <mvc:annotation-driven /> <!-- 自動掃描controller包中的控制器 --> <context:component-scan base-package="com.eap.filemanager.cmd" /> </beans>
xml頭,ViewResolver,然后啟用注解,然后掃描。
這其中,第二部分的意思就是,SpringMVC里有個跳轉類型叫做ModelAndView,它setView之后,就會自動跑到view名字+后綴的文件上去,比如setView("index"),那么在這個配置文件下,就會自動跳轉到index.jsp上,而且是WEB-INF/jsp下的index.jsp上,WEB-INF下的jsp無法直接通過地址欄訪問,所以這種控制可以讓容器對資源訪問權限進行管理。
大功告成,最困難的配置文件就這么搞定了,我可是花了好多時間在網上搜了來着,現在你們已經擁有了基石般的配置文件信息,你可以在上面測試通配符啦等你覺得方便的任何內容。
好了,看配置文件上的包也能知道,我的DAO是這么寫的。
非常奇怪,使用@Controller和@Resource必須得實現接口,得這么寫:
接口:
public interface IUserDao { public List query(String sql); public List queryByName(String name); }
DAO代碼:
@Repository public class UserDao implements IUserDao{ Session session; @Autowired UserDao(SessionFactory sessionFactory){ session = sessionFactory.getCurrentSession(); session.beginTransaction(); } public List query(String sql) { SQLQuery query = session.createSQLQuery(sql).addEntity(User.class); return query.list(); } public List queryByName(String username){ String sql = "select * from pub_user where username=?"; SQLQuery query = session.createSQLQuery(sql).addEntity(User.class); query.setString(0, username); return query.list(); } }
這里我可是試了好多種方法,由於我喜歡直接寫sql語句,以充分利用關系數據庫的“關系”特性(畢竟關系型數據庫不是和對象無縫貼合的,要發揮其最大優勢應該從數據表之間的關系入手。有異議就提,最好論據充分,我需要證據不是結論,有了證據我也可以自己分析分析了,說不定我還知道點別的,能得出更有用的結論),所以我在這里使用了SQLQuery,否則你可以直接session.createQuery(hql)。但是,這里有一個問題,我繼承HibernateDAOSupport反而會獲取不到session或別的什么東西。
我在這兒順便附上JavaBean的,完全注解。
@Entity @Table(name="pub_user") public class User { @Id @Column(name = "id", unique = true, nullable = false) String id; @Column(name="username") String username; @Column(name="passwd") String passwd; @Column(name="user_ip") String userIp; //getter和setter...自己用Eclipse生成吧,我省略掉了 }
DAO這樣寫,那么我的Service就可以這么寫了。一樣的先接口,再@Controller
public interface UserService { public List getUsers(); }
@Service public class UserServiceImpl implements UserService{ @Resource IUserDao dao; public List getUsers(){ List list = dao.query("select * from pub_user"); return list; } }
你看哦,我這里@Resource,必須寫在接口定義的變量上面,然后Spring會自己去找誰實現了它並且還是@Resource的。關於具體命名管理,還有一些內容就不說了,這個在我們這么點代碼的例子中根本就遇不到的。記得我說的,萬一有兩個DAO都實現了這個接口,那該怎么辦呢,這就是命名管理要做的事情,自己去看吧(說不定你還沒看完這篇博客就放棄Spring了,那么寫上去真是多此一舉……什么?你不會放棄?你不會放棄我也不寫啊,我又沒用到)。
接下來就是@Controller了,這里不需要接口了,嘿嘿(我就說,UserDao都是UserDao<T>,里面的save方法都不用定義具體類型了,干嘛每個模塊還要用不同的DAO?既然大家都用一個DAO,干嘛還要依賴接口編程?我直接泛型<T>繼承了一個HibernateDAO后,Spring還不許我這么訪問DAO。不用拿概念忽悠我,我知道內聚和耦合在什么樣的規模下會展現出自身特性的怎樣的優缺點,但注解依賴接口編程的強制性讓我搭建環境的過程中走了很多彎路。好吧,也有可能明明有辦法不用建接口,只是我不知道罷了)。
@Controller public class FileManagerControl{ @Autowired UserService service;//其實我這不是User的Controller,反正Controller過程都一樣,大家看看調用過程就行了哦 @RequestMapping({"/"}) public ModelAndView welcome(){ ModelAndView mv = new ModelAndView(); mv.addObject("users", service.getUsers()); mv.setViewName("index"); return mv; } }
這樣,http://localhost:8080/[projectName]/,對應@RequestMapping({"/"})(如果里面是"/index.do"那么連接就是http://localhost:8080/[projectName]/index.do了)就能訪問ModelAndView設置的index.jsp了。這時候jsp上,${users}將會調用User的toString()方法,很可惜,我試了${users.username},報錯,不知道怎么搞。
最后呈上完整項目的同時,順便也任性一把:http://download.csdn.net/detail/nietzsche0/9038115
這是CSDN下載,需要3個資源分。不是為了資源分,就是任性而已(之前傳的,現在就是不想再傳一份到網盤,就是不想把資源分下調)。我看登錄CSDN下載項目比我搭建環境處理問題要容易得多了,也避免了像我一樣,堆積了大量資料結果最后根本就不去做了。