目的:
通過對ssh框架有了基礎性的學習,本文主要是使用注解的方式來簡化ssh框架的代碼編寫。
注意事項:
1、本文提綱:本文通過一個新聞管理系統的實例來簡化ssh框架的代碼編寫,功能包括查詢數據庫中所有新聞信息,刪除某條新聞信息。
2、本項目的搭建環境:Windows 8-64位,Eclipse(開發工具),jdk1.8.0_91,Tomcat 8.0,struts-2.3.30-apps,spring-framework-4.2.2.RELEASE,hibernate-release-5.2.2.Final,mysql數據庫
第一步:在eclipse(開發工具)里創建web項目(項目名稱:news),並生成web.xml文件。



第二步:導入本次項目要使用到的jar包(struts2、spring4、hibernate5和mysql)。


第三步:在配置文件web.xml配置一個struts2的過濾器和spring監聽器。

1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> 3 <display-name>news</display-name> 4 <welcome-file-list> 5 <welcome-file>default.jsp</welcome-file> 6 </welcome-file-list> 7 8 <!-- struts2過濾器 --> 9 <filter> 10 <filter-name>struts2</filter-name> 11 <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 12 </filter> 13 <filter-mapping> 14 <filter-name>struts2</filter-name> 15 <url-pattern>/*</url-pattern> 16 </filter-mapping>、 17 18 <!-- spring監聽器 --> 19 <context-param> 20 <param-name>contextConfigLocation</param-name> 21 <param-value>classpath:applicationContext.xml</param-value> 22 </context-param> 23 <listener> 24 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 25 </listener> 26 </web-app>
注:在welcome-file-list這里我添加了一個jsp頁面的鏈接:默認首頁<welcome-file>default.jsp</welcome-file>,進行對action的跳轉。
第四步:在Java Resources下的src目錄下創建四個包(package)進行分層。

第五步:
1、根據數據庫表的字段編寫News(實體類)放到news.entity包里。

1 package news.entity; 2 3 import java.util.Date; 4 5 import javax.persistence.Column; 6 import javax.persistence.Entity; 7 import javax.persistence.GeneratedValue; 8 import javax.persistence.GenerationType; 9 import javax.persistence.Id; 10 import javax.persistence.Table; 11 12 /* 13 * 跟數據庫表一致,作為一個java對象 14 * 1個對象代表的是數據庫表中的一行記錄 15 * 1個屬性代表的是表中的一個字段 16 */ 17 @Entity //聲明當前類為hibernate映射到數據庫中的實體類 18 @Table(name="news") //聲明table的名稱 19 public class News { 20 @Id //聲明此列為主鍵,作為映射對象的標識符 21 @GeneratedValue(strategy = GenerationType.AUTO) 22 private Integer id; 23 24 @Column(name="title",nullable=false) 25 private String title; 26 27 @Column(name="content",nullable=false) 28 private String content; 29 30 @Column(name="begintime",nullable=false) 31 private Date begintime; 32 33 @Column(name="username",nullable=false) 34 private String username; 35 36 public News() { 37 super(); 38 } 39 40 public Integer getId() { 41 return id; 42 } 43 public void setId(Integer id) { 44 this.id = id; 45 } 46 47 public String getTitle() { 48 return title; 49 } 50 public void setTitle(String title) { 51 this.title = title; 52 } 53 54 public String getContent() { 55 return content; 56 } 57 public void setContent(String content) { 58 this.content = content; 59 } 60 61 public Date getBegintime() { 62 return begintime; 63 } 64 public void setBegintime(Date begintime) { 65 this.begintime = begintime; 66 } 67 68 public String getUsername() { 69 return username; 70 } 71 public void setUsername(String username) { 72 this.username = username; 73 } 74 75 76 }
注:在實體類未用到注解前,我們需要編寫一個映射文件,使用注解后就可以將原來的映射文件刪除。
2、在news.service包里編寫NewsService(接口類)和NewsServiceImpl(實現類)。

NewsService(接口類):
1 package news.service; 2 3 import java.util.List; 4 5 //創建一個NewsService接口類 6 public interface NewsService { 7 8 public List showAllNews(); 9 10 public String findNews(); 11 12 public String deleteSingleNews(Integer id); 13 }
NewsServiceImpl(實現類):
1 package news.service; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.context.annotation.Scope; 7 import org.springframework.stereotype.Service; 8 9 import news.dao.NewsDao; 10 import news.entity.News; 11 12 //創建NewsServiceImpl(實現類)實現NewsService接口 13 //使用@Service類注解自動注入,並且作用域范圍為非單例 14 @Service 15 @Scope("prototype") 16 public class NewsServiceImpl implements NewsService { 17 18 //使用spring內置注解@Autowired自動注入實例 19 @Autowired 20 private NewsDao nd; 21 22 @Override 23 public List showAllNews() { 24 25 //調用NewsDao的showAllNews方法存入到List<News>集合里 26 List<News> allNewList=nd.showAllNews(); 27 //返回List集合 28 return allNewList; 29 } 30 31 @Override 32 public String findNews() { 33 // TODO Auto-generated method stub 34 return null; 35 } 36 37 @Override 38 public String deleteSingleNews(Integer id) { 39 40 //定義一個字符串保存到returnValue變量里 41 String returnValue="deleteFailed"; 42 43 //調用NewsDao的deleteSingleNews方法 44 returnValue=nd.deleteSingleNews(id); 45 46 //返回returnValue 47 return returnValue; 48 } 49 50 }
3、在news.dao包里編寫NewsDao(接口類)和NewsDaoImpl(實現類)。

NewsDao(接口類):
1 package news.dao; 2 3 import java.util.List; 4 5 //創建NewsDao(接口類) 6 public interface NewsDao { 7 8 public List showAllNews(); 9 10 public String findNews(); 11 12 public String deleteSingleNews(Integer id); 13 }
NewsDaoImpl(實現類):
1 package news.dao; 2 3 import java.util.List; 4 5 import org.hibernate.Session; 6 import org.hibernate.SessionFactory; 7 import org.hibernate.query.Query; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.context.annotation.Scope; 10 import org.springframework.stereotype.Repository; 11 12 import news.entity.News; 13 14 //創建NewsDaoImpl(實現類)實現NewsDao接口 15 //使用@Repository類注解自動注入,並且作用域范圍為非單例 16 @Repository 17 @Scope("prototype") 18 public class NewsDaoImpl implements NewsDao { 19 20 //使用spring內置注解@Autowired自動注入實例 21 @Autowired 22 private SessionFactory sf; 23 24 @Override 25 public List showAllNews() { 26 //重新建立一個新的session 27 Session session=sf.openSession(); 28 //創建Query 29 Query query=session.createQuery("from News"); 30 31 //將結果集保存到List<News>集合里 32 List<News> allNewList=query.getResultList(); 33 34 //關閉session 35 session.close(); 36 37 //返回List<News>集合 38 return allNewList; 39 } 40 41 @Override 42 public String findNews() { 43 // TODO Auto-generated method stub 44 return null; 45 } 46 47 @Override 48 public String deleteSingleNews(Integer id) { 49 //重新建立一個新的session 50 Session session=sf.openSession(); 51 //創建Query並將id值設置為傳過來的參數值 52 Query query=session.createQuery("from News where id=:myid"); 53 query.setParameter("myid", id); 54 //將結果集保存到List<News>集合里 55 List<News> deleteList=query.getResultList(); 56 57 //判斷deleteList有沒有值,如果有,則執行下面的語句,如果沒有,則什么都不做 58 if(deleteList.size()==1){ 59 //獲取deleteList中的值並保存到News對象中 60 News news=deleteList.get(0); 61 //在控制台輸出:刪除對象和id值 62 System.out.println("刪除對象:"+news.getTitle()+" Id:"+news.getId()); 63 //創建事務 64 session.getTransaction().begin(); 65 //刪除對象 66 session.delete(news); 67 //提交事務 68 session.getTransaction().commit(); 69 //關閉session 70 session.close(); 71 } 72 73 //返回字符串deleteOK 74 return "deleteOK"; 75 } 76 77 }
4、編寫NewsAction(action類)。

1 package news.action; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.context.annotation.Scope; 7 import org.springframework.stereotype.Controller; 8 9 import com.opensymphony.xwork2.ActionSupport; 10 11 import news.entity.News; 12 import news.service.NewsService; 13 14 //創建NewsAction(action類)繼承ActionSupport接口 15 //使用@Controller類注解自動注入,並且作用域范圍為非單例 16 @Controller 17 @Scope("prototype") 18 public class NewsAction extends ActionSupport { 19 20 //獲取從客戶端傳遞過來的值 21 private Integer id; 22 23 //strtus自動的賦值 24 public void setId(Integer id) { 25 this.id = id; 26 } 27 28 //使用spring內置注解@Autowired自動注入實例 29 @Autowired 30 private NewsService ns; 31 32 private List<News> allNewList; 33 34 public List<News> getAllNewList() { 35 return allNewList; 36 } 37 38 public void setAllNewList(List<News> allNewList) { 39 this.allNewList = allNewList; 40 } 41 42 //查詢出所有數據 43 public String showAllNews(){ 44 45 allNewList=ns.showAllNews(); 46 47 return "success"; 48 } 49 50 //查詢單條數據(本例未使用) 51 public String findNews(){ 52 53 return ""; 54 } 55 56 //刪除某條數據 57 public String deleteSingleNews(){ 58 59 System.out.println("客戶端傳過來的id值是:"+id); 60 61 String returnValue=ns.deleteSingleNews(id); 62 63 return returnValue; 64 } 65 }
第六步:編寫struts.xml(struts配置文件)、applicationContext.xml(spring配置文件)、jdbc.properties(外部屬性文件)。
注:將這些配置文件放到src里。

struts.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE struts PUBLIC 3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 4 "http://struts.apache.org/dtds/struts-2.3.dtd"> 5 <!-- 上面的頭,注意版本,從樣例里復制過來 showcase.war\WEB-INF\src\java\struts.xml --> 6 7 <struts> 8 <!-- 告知Struts2運行時使用Spring來創建對象 --> 9 <constant name="struts.objectFactory" value="spring"></constant> 10 <!-- 第1步:先定義一個包 --> 11 <package name="mynews" extends="struts-default"> 12 <!-- 第2步:定義一個action,配置跳轉信息 name 類似於Servlet 注:這里使用了通配符來指定調用的方法--> 13 <action name="NewsAction_*" class="newsAction" method="{1}"> 14 <!-- 跳轉是forward/WEB-INF/是防止jsp不經過action就可以訪問--> 15 <!-- result接收返回的字符串,然后做對應的事情 --> 16 <result name="success">/WEB-INF/jsp/NewsIndex.jsp</result> 17 <!-- 刪除后通過type="redirectAction"這個類型重新跳轉到NewsAction_showAllNews.action刷新頁面 --> 18 <result name="deleteOK" type="redirectAction">NewsAction_showAllNews.action</result> 19 </action> 20 </package> 21 </struts>
applicationContext.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation=" 7 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd 8 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd 9 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd 10 http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd 11 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> 12 13 <!-- spring注解解析器 --> 14 <context:component-scan base-package="news"></context:component-scan> 15 16 <!-- 引入外部屬性文件 --> 17 <context:property-placeholder location="classpath:jdbc.properties" /> 18 <!-- 添加sessionFactory bane ,注意,該類是Spring提供的 --> 19 <bean id="sessionFactory" 20 class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" scope="prototype"> 21 <!-- 注入連接池,包含了數據庫用戶名,密碼等等信息 --> 22 <property name="dataSource" ref="myDataSource" /> 23 24 <!-- 配置Hibernate的其他的屬性 --> 25 <property name="hibernateProperties"> 26 <props> 27 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> 28 <prop key="hibernate.show_sql">true</prop> 29 <prop key="hibernate.format_sql">true</prop> 30 <prop key="hibernate.connection.autocommit">false</prop> 31 <!-- 開機自動生成表 --> 32 <prop key="hibernate.hbm2ddl.auto">update</prop> 33 </props> 34 </property> 35 <!-- 掃描實體類包,解析實體類的注解 --> 36 <property name="packagesToScan"> 37 <list> 38 <!-- value值填寫實體類所在的包 --> 39 <value>news.entity</value> 40 </list> 41 </property> 42 </bean> 43 44 <!-- 添加c3p0數據庫連接池 bean --> 45 <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 46 <!-- 數據庫連接配置 --> 47 <property name="driverClass" value="${jdbc.driver}" /> 48 <property name="jdbcUrl" value="${jdbc.url}" /> 49 <property name="user" value="${jdbc.user}" /> 50 <property name="password" value="${jdbc.password}" /> 51 <!-- 每300秒檢查所有連接池中的空閑連接 --> 52 <property name="idleConnectionTestPeriod" value="300"></property> 53 <!-- 最大空閑時間,900秒內未使用則連接被丟棄。若為0則永不丟棄 --> 54 <property name="maxIdleTime" value="900"></property> 55 <!-- 最大連接數 --> 56 <property name="maxPoolSize" value="2"></property> 57 </bean> 58 </beans> 59
jdbc.properties(外不屬性文件):
1 jdbc.driver=com.mysql.jdbc.Driver 2 jdbc.url=jdbc:mysql://localhost:3306/news 3 jdbc.user=root 4 jdbc.password=123456
第七步:創建一個NewsIndex.jsp頁面將所有數據取出來顯示到頁面上和一個default.jsp頁面進行action跳轉。

NewsIndex.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@ taglib uri="/struts-tags" prefix="s" %> 4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 5 <html> 6 <head> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <title>Insert title here</title> 9 <style> 10 #showDiv{ 11 width:1000px; 12 height:70px; 13 margin: auto; 14 } 15 </style> 16 </head> 17 <body> 18 <div id="showDiv" align="center"> 19 <h1>新聞管理系統</h1> 20 </div> 21 <div id="msgDiv" align="center"> 22 <table border="1" id="#msgTab"> 23 <tr> 24 <th>序號</th> 25 <th>標題</th> 26 <th>內容</th> 27 <th>辦卡日期</th> 28 <th>姓名</th> 29 <th>操作</th> 30 </tr> 31 <s:iterator value="allNewList"> 32 <tr> 33 <td><s:property value="id"/></td> 34 <td><s:property value="title"/></td> 35 <td><s:property value="content"/></td> 36 <td><s:date name="begintime" format="yyyy年MM月dd日"/></td> 37 <td><s:property value="username"/></td> 38 <td><s:a value="NewsAction_deleteSingleNews?id=%{id}">刪除</s:a></td> 39 </tr> 40 </s:iterator> 41 <s:if test="allNewList.size()==0"> 42 <tr> 43 <td colspan="6">沒有查找到數據</td> 44 </tr> 45 </s:if> 46 </table> 47 </div> 48 </body> 49 </html>
default.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%><% 3 /* 跳轉到NewsAction_showAllNews.action */ 4 response.sendRedirect("NewsAction_showAllNews.action"); 5 %>
運行查詢結果:
瀏覽器顯示:

控制台輸出:

運行刪除結果:
瀏覽器顯示:

控制台輸出(刪除后再查詢結果):

總結:通過對本例項目搭建到功能的編寫,使用注解的方式簡化了ssh框架代碼編寫,對實例和類直接用注解注入。
