1. 程式人生 > >【SSH 框架專案的搭建--簡化版】使用註解代替xml中的,減少程式碼量

【SSH 框架專案的搭建--簡化版】使用註解代替xml中的,減少程式碼量

之前的《圖書資訊管理系統》專案中(http://blog.csdn.net/ssh159/article/details/52439676),

Spring的配置太繁瑣。考慮開發大專案上,假設專案的action層會有成百上千 個Class類,不簡化程式碼的

情況下就要在Spring的配置中裝配上千個actionClass的<bean>,applicationContext.xml 的程式碼太多了。

改進程式碼:

1、使用註解 代替applicationContext.xml中的 <bean> 標籤,新增 註解掃描器,解析器。

簡化 xml處的配置資訊。

2、使用Aop,只保留事務處理的程式碼(

只保留 核心關注點 和 橫切關注點),刪掉多餘的動作;

(這是面向切面的知識,不懂可以看看我之前寫的 

簡化 各層的程式碼。

AOP:將應用程式中的商業邏輯及對其提供支援的 應用服務 進行分離。
商業邏輯:

核心關注點(主要是帶入物件和物件的特殊事務),

橫切關注點(經常發生在核心關注點的各處,各處都基本相似,用以:許可權認證,日誌,事務處理)。
通用服務:做記錄,日記。


之前的寫法:

因為不想new 物件,所以在application中,

1、一個類和2個介面(IndexAction , IndexServiceImpl , IndexDaoImpl)都要標明非單例;

2、用<bean> <prototype>標籤 取代那些私有屬性(is ,id ,sessionFactory )new物件;

3、私有屬性(is ,id ,sessionFactory )還要設定屬性和方法;


IndexAction 控制層 的程式碼:

private IndexService is = null;  
    public void setIs(IndexService is) {  
        this.is = is; 

IndexServiceImpl 業務邏輯處理層介面 的程式碼:

 private IndexDao id;  
//用於注入使用 
    public void setId(IndexDao id) {  
        System.out.println("有人給我注入了一個dao例項:"+id);  
        this.id = id;  
    }  

IndexDaoImpl 資料庫訪問層介面 的程式碼:

private SessionFactory sessionFactory;  
    public void setSessionFactory(SessionFactory sf) {  
        this.sessionFactory = sf;  
    } 

applicationContext.xml 中的程式碼 

 <bean id="myIndexAction" class="ssh.action.IndexAction" scope="prototype">  
        <!-- setIs(myIndexService) -->  
        <property name="is" ref="myIndexService"/>  
    </bean>  
      
    <!-- myIndexService = new ssh.service.IndexServiceImpl() -->  
    <bean id="myIndexService" class="ssh.service.IndexServiceImpl" scope="prototype">  
        <property name="id" ref="myIndexDao"/>  
    </bean>  
      
    <bean id="myIndexDao" class="ssh.dao.IndexDaoImpl" scope="prototype">  
<!-- 晚點再注入能用的seesionFactory --> 
        <property name="sessionFactory" ref="mySessionFactory"></property>  
    </bean>  
感覺程式碼實在是太多了,所以現在用註解的方式,減少程式碼!

現在解決方案:

1、 在專案中加入註解:

    讓Spring自動的為Class類定義的屬性裝配bean以及讓Spring自動的掃描程式包中的類,隱式的在配置檔案中

新增Class類的bean。

註解分為兩種,一是類的註解,二是類中屬性的註解

註解功能的提供也有兩者,一是Spring,二是JdkPS:類的註解只有springframework提供的

2、使用事務處理,刪除多餘的資訊,

不必每次 寫方法都得 標明:(方法.開始;方法.進行ing;方法.提交;方法.結束)

3、增加四個aop 的jar包:解耦

百度雲-ssh框架包-aop:http://pan.baidu.com/s/1pL4d3R1 


-------------------------------------------------------------

溫馨提示:

1、已經註釋的註解為:jdk註解;

正在使用的註解為:spring的註解。

2、2種註解都可以,只是規範程式碼。

3、使用註解就需要打包,這裡已經刪除了jdk註解帶來的包。

例如:

@Controller //控制層action的註解,與打包

import org.springframework.stereotype.Controller; 

--------------------------------------------------------------

 一、專案分析


二、mysql建表

<span style="font-size:18px;color:#999999;">---------------新聞資訊表
create database News; --建立資料庫News;

</span>
<span style="font-size:18px;color:#999999;">--建立表 news;
create table news(
id int primary key auto_increment, 
title varchar(50),
content varchar(30),
begintime datetime,
username varchar(20)
);</span>

<span style="font-size:18px;color:#999999;">--插入資料
insert into news(title,content,begintime,username) values
('IT市場分析', '各門程式語言優勢分析','2016-10-01','tom'),
('如何不用加班', '提高效率,減少上班時間','2016-10-02','tom2'),
('如何實現加工資','提升自我價值與跳槽','2016-10-03','tom3');

use news1;
select * form news; --查詢表</span>


三、java程式碼:

news.action控制層:NewsAction 

@Controller 和 @Scope("prototype") 2個註解取代xml處的程式碼:

<bena id ="" class="" scope="">

<prototype id="" red="" />

</bean>

package news.action;


import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionSupport;
import news.entity.News;
import news.service.NewsService;


//@Controller("myNewsAction")
@SuppressWarnings("serial")
@Controller               //預設就是類的首字母小寫newsAction
@Scope("prototype")
public class NewsAction extends ActionSupport {

private String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}


//獲取從客戶端傳遞過來的值,strtus自動的賦值
private Integer id;

public Integer getId(){
return this.id;
}
public void setId(Integer id) {
this.id = id;
}

@Autowired
//@Qualifier("myNewsService")
//@Resource(name="myNewsService")
private NewsService ns;

//定義1個list用於前端jsp顯示
private List<News> allNewList;


public List<News> getAllNewList() {
return allNewList;
}


//顯示首頁所有資料
public String showAllNews(){
//呼叫service 中的showAllNews,獲取所有的資料,
//然後儲存到
allNewList = ns.showAllNews();
return "success";
}

//顯示首頁所有資料(查詢使用的。PS:本例沒用到)
public String findNews(){
return "";
}

public String deleteSingleNews(){
System.out.println("從客戶端傳遞過來的ID:"+id);
String returnValue = ns.deleteSingleNews(id);
return returnValue;
}

}
news.dao sql訪問層的NewsDao 
package news.dao;

import java.util.List;

public interface NewsDao {
	public List showAllNews();
//顯示首頁所有資料(查詢使用的。PS:本例沒用到)
	public String findNews();
	public String deleteSingleNews(Integer id);
}
news.dao sql訪問層的NewsDaoImpl介面
package news.dao;

import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;


import news.entity.News;


//@Repository("myNewsDao") //jdk註解
@Repository    <span style="white-space:pre">		</span>  //sql訪問層註解,規範
@Scope("prototype")      //非單例
public class NewsDaoImpl implements NewsDao {

//@Qualifier("mySessionFactory")  
//@Resource(name="mySessionFactory")
@Autowired
private SessionFactory sf;


@Override
public List showAllNews() {

Session session = sf.getCurrentSession();
Query query = session.createQuery("from News");
 allNewList  = query.getResultList();

return allNewList;
}


@Override
public String findNews() {
return null;
}


@Override
public String deleteSingleNews(Integer id) {
Session session = sf.openSession();
Query query = session.createQuery("from News where id=:myid");

query.setParameter("myid", id);
List<News> deleteList  = query.getResultList();


//如果搜尋出來是1條,就刪除,如果是0條就不管了
if ( deleteList.size()==1 ) {
News news = deleteList.get(0);
System.out.println("刪除物件:"+news.getTitle()+ " Id:"+news.getId());
session.getTransaction().begin();
session.delete(news);
session.getTransaction().commit();
session.close();
//sessionFactory關閉策略
//1.堅持使用資料庫連線池(例如C3P0)
//2.sessionFactory就不關閉,而使用hibernate事務自動關閉功能
// 說明:sf.openSession();  必須關閉
//    sf.openSession(); 改為:sf.getCurrentSession();
//getCurrentSession建立的執行緒會在事務提交或者事務回滾後自動關閉
//sf.close();			
}

return "deleteOK";
}


}

news.entity 實體類層的 News 實體類
package news.entity;

import java.util.Date;

public class News {
	private Integer id;
	private String title;
	private String content;
	private Date begintime;
	private String username;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public Date getBegintime() {
		return begintime;
	}
	public void setBegintime(Date begintime) {
		this.begintime = begintime;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	

}
news.entity包的 News.hbm.xml  sql資訊配置
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping xmlns="http://www.hibernate.org/xsd/hibernate-mapping">
  
     <class name="news.entity.News" table="news">
        <id name="id" column="id">
        	<generator class="native"></generator>
        </id>
        <property name="title" type="string" length="50" column="title" not-null="true"></property>
        <property name="content" type="text" length="1000" column="content" not-null="true"></property>
        <property name="begintime" type="date" column="begintime" not-null="true"></property>
        <property name="username" type="string" length="20" column="username" not-null="true"></property>
    </class>
</hibernate-mapping>

news.service 業務邏輯處理層的 NewsService 
package news.service;

import java.util.List;

public interface NewsService {
	public List showAllNews();
//顯示首頁所有資料(查詢使用的。PS:本例沒用到)
	public String findNews();
	public String deleteSingleNews(Integer id);
}
news.service 層的NewsServiceImpl業務邏輯處理層介面

package news.service;


import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import news.dao.NewsDao;
import news.entity.News;


//@Service("myNewsService") //jdk註解
@Service<span style="white-space:pre">	</span>      //業務邏輯處理層 註解,規範
@Scope("prototype")   //非單例
public class NewsServiceImpl implements NewsService {


//Autowired和Qualifier 屬於spring的註解,

//jdk自帶註解resource可以替代Autowired
/*
 * 用resource的好處:
 * 1. 程式碼與spring 解耦,不依賴於spring
 * 2. 程式碼中沒有spring的存在,可以隨時切換任意一套類似spring的框架
 */

//@Qualifier("myNewsDao")
//@Resource(name="myNewsDao") 
@Autowired
private NewsDao nd;

<pre name="code" class="java">@Override
@Transactional(readOnly=true)  //事務處理=只讀
public List showAllNews() {
//可以增加一個業務邏輯,比如:把文章的內容進行擷取為20字元
//通過DAO獲取資料

List<News> allNewList = nd.showAllNews();
//在return 之間,可以進行各種業務邏輯操作

return allNewList;
}


@Override
public String findNews() {
return null;
}

<pre name="code" class="java">@Override
@Transactional  //事務管理
public String deleteSingleNews(Integer id) {
//需要做以下判斷,例如有沒有許可權刪除,又或者判斷下面是否有級聯子子記錄

//當可以刪除時,呼叫DAO給直接刪除
String returnValue = "deleteFailed";
returnValue = nd.deleteSingleNews(id);
return returnValue;
}


}

重點來了applicationContext.xml

這裡,之前<bean>的程式碼已經不要了,直接刪除,寫一個註解類的掃描器即可

<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="    
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd  
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd  
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
			http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd  
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

<!-- 原理:自動注入processor解析器,用來解析註解 -->
<!--  <context:annotation-config/>   -->
	
<!-- 自動掃描包,也會自動注入直譯器,所以不需要 context:annotation-config -->
<context:component-scan base-package="news"></context:component-scan>


<!-- 引入外部屬性檔案 -->
	<context:property-placeholder location="classpath:jdbc.properties" />

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 注入連線池,包含了資料庫使用者名稱,密碼等等資訊 -->
		<property name="dataSource" ref="myDataSource" />

<!-- 配置Hibernate的其他的屬性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.connection.autocommit">false</prop>
<!-- 開機自動生成表 -->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>news/entity/News.hbm.xml</value>
			</list>
		</property>

	</bean>

	<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driver}" />
		<property name="jdbcUrl" value="${jdbc.url}" />
		<property name="user" value="${jdbc.user}" />
		<property name="password" value="${jdbc.password}" />
<!-- 每300秒檢查所有連線池中的空閒連線 -->
		<property name="idleConnectionTestPeriod" value="300"></property>
<!-- 最大空閒時間,900秒內未使用則連線被丟棄。若為0則永不丟棄 -->
		<property name="maxIdleTime" value="900"></property>
<!-- 最大連線數 -->
		<property name="maxPoolSize" value="2"></property>

	</bean>
<!-- 載入一個事務管理驅動包 -->
<span style="white-space:pre">	</span><bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<span style="white-space:pre">		</span><property name="sessionFactory" ref="sessionFactory"></property>
<span style="white-space:pre">	</span></bean>
<span style="white-space:pre">	</span>
<!-- 註解驅動 --><span style="white-space:pre">	</span>
<span style="white-space:pre">	</span><tx:annotation-driven transaction-manager="transactionManager"/>

</beans>
		
jdbc.properties sql表資訊,這個是需要修改sql 的時候給其他不懂程式碼的人 修改配置的

這裡支援mysql 和 oracle ,密碼為空

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/news
jdbc.user=root
jdbc.password=


#oracle
jdbc_oracle.driver=oracle.jdbc.driver.OracleDriver
jdbc_oracle.url=jdbc:oracle:[email protected]:1521:orcl
jdbc_oracle.user=news
jdbc_oracle.password=
struts.xml 配置資訊說明
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<constant name="struts.objectFactory" value="spring" />

<!-- 第1步:先定義一個包 -->
	<package name="mypck001" extends="struts-default">
		<action name="NewsAction_*" class="newsAction" method="{1}">
			<result name="success">/WEB-INF/jsp/index.jsp</result>
<!-- 希望刪除成功後,重新執行1次首頁顯示內容 -->
			<result name="deleteOK" type="redirectAction">NewsAction_showAllNews.action?message=deleteOk&id=${id}</result>
		</action>
		
	</package>
</struts>
jsp頁面:index.jsp 主頁
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@	taglib uri="/struts-tags" prefix="s" %>       
<!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>Insert title here</title>
<style>
	table{width:200px;border:1px solid black;text-align: center;}
	td{border:1px solid black;}
</style>
</head>
<body>

<center>
提示資訊:<s:property value="message"/>
刪除ID:<s:property value="id"/>	

<table>
<s:iterator value="allNewList">
<tr>	
 <td>	<s:property value="id"/> </td>

  <td>	<s:property value="title"/> </td>
	
  <td> <s:a value="NewsAction_deleteSingleNews?id=%{id}">刪除</s:a> </td>
</tr>
	<br>
</s:iterator>

</table>
<hr>
<h3>共有多少條記錄:<s:property value="allNewList.size()"></s:property> </h3>

</center>

</body>
</html>

web.xml 配置資訊
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>news1</display-name>
  <welcome-file-list>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <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>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app> 

default.jsp 重定向跳轉主頁面,隱藏主頁面
NewsAction_showAllNews.action :呼叫NewsAction類 中的showAllNews的方法,
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	response.sendRedirect("NewsAction_showAllNews.action");
%>

lib目錄下ssh框架配置jar包沒有改變,還是之前的。

(參考網盤)




相關推薦

no