程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> SSH框架網上商城項目第2戰之根本增刪查改、Service和Action的抽取

SSH框架網上商城項目第2戰之根本增刪查改、Service和Action的抽取

編輯:關於JAVA

SSH框架網上商城項目第2戰之根本增刪查改、Service和Action的抽取。本站提示廣大學習愛好者:(SSH框架網上商城項目第2戰之根本增刪查改、Service和Action的抽取)文章只能為提供參考,不一定能成為您想要的結果。以下是SSH框架網上商城項目第2戰之根本增刪查改、Service和Action的抽取正文


上一節《SSH框架網上商城項目第1戰之整合Struts2、Hibernate4.3和Spring4.2》我們搭建好了Struts2、Hibernate和Spring的開辟情況,並勝利將它們整合在一路。這節重要完成一些根本的增刪改查和Service、Dao和Action的抽取。
1. Service層的抽取
        上一節中,我們在service層簡略寫了save和update辦法,這裡我們開端完美該部門的代碼,然後對service層的代碼停止抽取。
1.1 完美CategoryService層
        對數據庫的操作不過是增刪改查,起首我們來完美CategoryService層的接口和完成:

//CategoryService接口 
public interface CategoryService extends BaseService<Category> { 
 
 public void save(Category category); //拔出 
 
 public void update(Category category);//更新 
 
 public void delete(int id); //刪除 
 
 public Category get(int id); //獲得一個Category 
 
 public List<Category> query(); //獲得全體Category 
 
} 

        對CategoryService接口的詳細完成:

public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService { 
 
 private SessionFactory sessionFactory; 
 
 //Spring會注出去 
 public void setSessionFactory(SessionFactory sessionFactory) { 
 this.sessionFactory = sessionFactory; 
 } 
 
 protected Session getSession() { 
 //從以後線程獲得session,假如沒有則創立一個新的session 
 return sessionFactory.getCurrentSession(); 
 } 
 
 @Override 
 public void save(Category category) { 
 getSession().save(category); 
 } 
 
 @Override 
 public void update(Category category) { 
 getSession().update(category); 
 } 
 
 @Override 
 public void delete(int id) { 
 /*第一種辦法有個弊病,就是沒刪除一次得先查詢一次 
 Object obj = getSession().get(Category.class, id); 
 if(obj != null) { 
  getSession().delete(obj); 
 }*/ 
 String hql = "delete Category while id=:id"; 
 getSession().createQuery(hql) // 
  .setInteger("id", id) // 
  .executeUpdate(); 
 } 
 
 @Override 
 public Category get(int id) { 
 return (Category) getSession().get(Category.class, id); 
 } 
 
 @Override 
 public List<Category> query() { 
 String hql = "from Category"; 
 return getSession().createQuery(hql).list(); 
 } 
} 

1.2 Service層抽取完成
完成了CategoryService後,我們來抽取Service層的基本完成。思緒是如許的:我們抽取一個基本接口BaseService和基本接口的完成BaseServiceImpl,前面開辟的時刻,假如須要新的Service,只須要做兩步便可:起首界說一個新的接口xxxService繼續BaseService接口,這個接口可以增長新的籠統辦法;然後界說一個新的完成類xxxServiceImpl繼續BaseServiceImpl並完成xxxService接口便可。如許加倍便於項目標保護。
我們先依據下面的CategoryService接口來創立BaseService接口:

//基本接口BaseService,應用泛型 
public interface BaseService<T> { 
 public void save(T t); 
 
 public void update(T t); 
 
 public void delete(int id); 
 
 public T get(int id); 
 
 public List<T> query(); 
} 

然後再依據CategoryServiceImpl完成類創立BaseService接口的完成類BaseServiceImpl:

/** 
 * @Description TODO(公共模塊的抽取) 
 * @author eson_15 
 * 
 */ 
@SuppressWarnings("unchecked") 
public class BaseServiceImpl<T> implements BaseService<T> { 
 
 private Class clazz; //clazz中存儲了以後操作的類型,即泛型T 
 private SessionFactory sessionFactory; 
 
 public BaseServiceImpl() { 
  //上面三個打印信息可以去失落,這裡是給本身看的 
  System.out.println("this代表的是以後挪用結構辦法的對象" + this); 
 System.out.println("獲得以後this對象的父類信息" + this.getClass().getSuperclass()); 
 System.out.println("獲得以後this對象的父類信息(包含泛型信息)" + this.getClass().getGenericSuperclass()); 
 //拿到泛型的參數類型 
 ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); 
 clazz = (Class)type.getActualTypeArguments()[0]; 
 } 
 
 public void setSessionFactory(SessionFactory sessionFactory) { 
 this.sessionFactory = sessionFactory; 
 } 
 
 protected Session getSession() { 
 //從以後線程獲得session,假如沒有則創立一個新的session 
 return sessionFactory.getCurrentSession(); 
 } 
 
 @Override 
 public void save(T t) { 
 getSession().save(t); 
 } 
 
 @Override 
 public void update(T t) { 
 getSession().update(t); 
 } 
 
 @Override 
 public void delete(int id) { 
 System.out.println(clazz.getSimpleName()); 
 String hql = "delete " + clazz.getSimpleName() + " as c where c.id=:id"; 
 getSession().createQuery(hql) // 
   .setInteger("id", id) // 
   .executeUpdate(); 
 } 
 
 @Override 
 public T get(int id) { 
 return (T) getSession().get(clazz, id); 
 } 
 
 @Override 
 public List<T> query() { 
 String hql = "from " + clazz.getSimpleName(); 
 return getSession().createQuery(hql).list(); 
 } 
 
} 

抽取完了後,我們便可以改寫CategoryService接口和CategoryServiceImpl完成類了。以下:

//CategoryService接口繼續BaseService接口 
public interface CategoryService extends BaseService<Category> { 
 /* 
 * 只需添加CategoryService自己須要的新的辦法便可,公共辦法曾經在BaseService中了 
 */ 
} 
 
/** 
 * @Description TODO(模塊本身的營業邏輯) 
 * @author eson_15 
 * 
 */ 
public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService { 
 
 /* 
 * 只需完成CategoryService接口中新增的辦法便可,公共辦法曾經在BaseServiceImpl中完成了 
 */ 
} 

        從代碼中可以看出,新增的Service只須要繼續BaseService接口,然後在接口中新增本Service所須要的營業邏輯便可。新增的ServiceImpl只須要繼續BaseServiceImpl並完成新增的營業邏輯便可。
        然則別忘了很主要的一點:就是修正Spring的設置裝備擺設文件beans.xml中的bean。

<!-- 泛型類是不克不及實例化的,所以要加lazy-init屬性 --> 
<bean id="baseService" class="cn.it.shop.service.impl.BaseServiceImpl" lazy-init="true"> 
 <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 
 
<bean id="categoryService" class="cn.it.shop.service.impl.CategoryServiceImpl" parent="baseService"/> 

        將本來categoryService中的property干失落,然後增長parent屬性,指明繼續baseService;然後設置裝備擺設一下baseService,將sessionFactory配到baseService中去,別的要留意一點:設置lazy-init屬性為true,由於baseService是泛型類,泛型類是不克不及實例化的。至此,Service層的抽取就弄定了。

2. Service層添加一個Account
        方才抽取好了Service層,那末如今我們想寫一個Account(治理員)的service就很簡略了:
        起首寫一個AccountService接口繼續BaseService:

public interface AccountService extends BaseService<Account> { //留意BaseService裡的泛型如今是Account 
 /* 
 * 只需添加AccountService自己須要的新的辦法便可,公共辦法曾經在BaseService中了 
 */ 
} 

        然後寫一個AccountServiceImpl完成類繼續BaseServiceImpl完成類,並完成AccountService接口便可:

public class AccountServiceImpl extends BaseServiceImpl<Account> implements AccountService { 
 
 /* 
 * 只需完成AccountService接口中新增的辦法便可,公共辦法曾經在BaseServiceImpl中完成了 
 */ 
 
 //治理上岸功效,前期再完美 
} 

        最初在beans.xml文件裡加上以下設置裝備擺設:
<bean id="accountService" class="cn.it.shop.service.impl.AccountServiceImpl" parent="baseService" />  
        如許就寫好了一個新的service了,今後須要添加service就遵守這個流程,異常便利。
3. Action的抽取
3.1 Action中往域(request,session,application等)中存數據
        我們曉得,在Action中可以直接經由過程ActionContext.getContext()去獲得一個ActionContext對象,然後經由過程該對象再去取得響應的域對象;也能夠經由過程完成xxxAware接口來注入響應的域對象。我們先來看一下這兩種辦法:

public class CategoryAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{ 
 
 private Category category; 
 
 private CategoryService categoryService; 
 
 public void setCategoryService(CategoryService categoryService) { 
  this.categoryService = categoryService; 
 } 
 
 public String update() { 
 System.out.println("----update----"); 
 categoryService.update(category); 
 return "index"; 
 } 
 
 public String save() { 
 System.out.println("----save----"); 
 return "index"; 
 } 
 
 public String query() { 
  //處理計劃一,采取響應的map代替本來的內置對象,如許與jsp沒有依附,然則代碼量比擬年夜 
 // ActionContext.getContext().put("categoryList", categoryService.query()); //放到request域中 
 // ActionContext.getContext().getSession().put("categoryList", categoryService.query()); //放到session域中 
 // ActionContext.getContext().getApplication().put("categoryList", categoryService.query()); //放到application域中 
  
 //處理計劃二,完成響應的接口(RequestAware,SessionAware,ApplicationAware),讓響應的map注入 
 request.put("categoryList", categoryService.query()); 
 session.put("categoryList", categoryService.query()); 
 application.put("categoryList", categoryService.query()); 
 return "index"; 
 } 
 
 public Category getCategory() { 
 return category; 
 } 
 
 public void setCategory(Category category) { 
 this.category = category; 
 } 
 
 private Map<String, Object> request; 
 private Map<String, Object> session; 
 private Map<String, Object> application; 
 
 @Override 
 public void setApplication(Map<String, Object> application) { 
 this.application = application; 
 } 
 
 @Override 
 public void setSession(Map<String, Object> session) { 
 this.session = session; 
 } 
 
 @Override 
 public void setRequest(Map<String, Object> request) { 
 this.request = request; 
 } 
} 

照樣上一節整合三年夜框架時的CategoryAction類,我們在外面加了一個query辦法,在該辦法中,我們經由過程向request域、session域和application域中存入查詢的成果。第一種辦法是直接應用ActionContext來完成,不須要完成任何接口,然則代碼量較年夜;第二種辦法經由過程完成RequestAware、SessionAware和ApplicationAware接口,完成該接口的三個籠統辦法把request、session和application注入出去,然後賦給響應的成員變量中,如許便可以在query辦法中向域中寄存查詢成果了。這代碼量貌似比第一種辦法更年夜……然則我們可以抽取,先往下看。
我們在index.jsp中新加一個查詢銜接來測試可否將查詢成果顯示出來:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 
 <head> 
 <title>My JSP 'index.jsp' starting page</title> 
 </head> 
 
 <body> 
 <a href="${pageContext.request.contextPath }/category_update.action?category.id=2&category.type=gga&category.hot=false">拜訪update</a> 
 <a href="category_save.action">拜訪save</a> 
 <a href="category_query.action">查詢一切種別</a><br/> 
 <c:forEach items="${requestScope.categoryList }" var="category"> 
 ${category.id } | ${category.type } | ${category.hot } <br/> 
 </c:forEach> 
 
 <c:forEach items="${sessionScope.categoryList }" var="category"> 
 ${category.id } | ${category.type } | ${category.hot } <br/> 
 </c:forEach> 
 
 <c:forEach items="${applicationScope.categoryList }" var="category"> 
 ${category.id } | ${category.type } | ${category.hot } <br/> 
 </c:forEach> 
 </body> 
</html> 

3.2 抽取BaseAction
        方才提到了,第二種辦法的代碼量更年夜,然則我們可以抽取一個BaseAction,專門處置這些域相干的操作。

public class BaseAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware { 
 
 protected Map<String, Object> request; 
 protected Map<String, Object> session; 
 protected Map<String, Object> application; 
 
 @Override 
 public void setApplication(Map<String, Object> application) { 
 this.application = application; 
 } 
 
 @Override 
 public void setSession(Map<String, Object> session) { 
 this.session = session; 
 } 
 
 @Override 
 public void setRequest(Map<String, Object> request) { 
 this.request = request; 
 } 
} 

        然後我們本身的Action假如須要用到這些域對象來存儲數據時,直接繼續BaseAction便可,就可以直接應用request、session和application對象了。所以修正後的CategoryAction以下:

public class CategoryAction extends BaseAction { 
 
 private Category category; 
<pre name="code" class="java"> 
 private CategoryService categoryService; 
 
 public void setCategoryService(CategoryService categoryService) { 
  this.categoryService = categoryService; 
 } 
public String update() {System.out.println("----update----");categoryService.update(category); return "index"; }public String save() {System.out.println("----save----");return "index"; } public String query() {request.put("categoryList", categoryService.query()); session.put("categoryList", categoryService.query()); application.put("categoryList", categoryService.query()); return "index"; } public Category getCategory() { return category; } public void setCategory(Category category) {this.category = category; }}

        前面一切要應用request、session和application域的Action,只需直接繼續BaseAction便可,異常便利。
3.3 獲得參數(ModelDriven)
        我們持續看下面的CategoryAction類,外面有個成員變量category,這是個POJO,界說這個變量並寫好set和get辦法是為了JSP頁面可以經由過程url前面附帶參數傳出去,參數是category對象中的屬性,好比id,type等,然則url中的參數必需寫成category.id、category.type等。如許struts會主動將這寫參數注入到category對象中,然後我們便可以直接應用這個category對象了,然則如許有點繁瑣。我們可使用ModelDriven來更便利的處理。

public class CategoryAction extends BaseAction implements ModelDriven<Category>{ 
 
 private Category category; 
 
 //應用ModelDriven接口必需要完成getModel()辦法,此辦法會把前往的項壓到棧頂 
 @Override 
 public Category getModel() { 
 category = new Category(); 
 return category; 
 } 
<pre name="code" class="java"> private CategoryService categoryService; 
 
 public void setCategoryService(CategoryService categoryService) { 
  this.categoryService = categoryService; 
 } 
 
 public String update() { 
 System.out.println("----update----"); 
 categoryService.update(category); 
 return "index"; 
 } 
 
 public String save() { 
 System.out.println("----save----"); 
 return "index"; 
 } 
 
 public String query() { 
 request.put("categoryList", categoryService.query()); 
 session.put("categoryList", categoryService.query()); 
 application.put("categoryList", categoryService.query()); 
 return "index"; 
 } 
 
} 

如許我們在前台JSP頁面就不消帶category.id這類繁瑣的參數了,看JSP頁面中的ModelDriven部門:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 
 <head> 
 <title>My JSP 'index.jsp' starting page</title> 
 </head> 
 
 <body> 
 <a href="${pageContext.request.contextPath }/category_update.action?category.id=2&category.type=gga&category.hot=false">拜訪update</a> 
 <a href="category_save.action?id=1&type=haha&hot=true">測試ModelDriven</a> 
 <a href="category_query.action">查詢一切種別</a><br/> 
 <c:forEach items="${requestScope.categoryList }" var="category"> 
 ${category.id } | ${category.type } | ${category.hot } <br/> 
 </c:forEach> 
 
 <c:forEach items="${sessionScope.categoryList }" var="category"> 
 ${category.id } | ${category.type } | ${category.hot } <br/> 
 </c:forEach> 
 
 <c:forEach items="${applicationScope.categoryList }" var="category"> 
 ${category.id } | ${category.type } | ${category.hot } <br/> 
 </c:forEach> 
 </body> 
</html> 

        測試成果是可以取得catgory,而且將id,type和hot屬性全體賦值好。我們可以看出,經由過程完成ModelDriven接口,我們可以很便利的在url中攜帶參數,Action中只須要完成getModel辦法,new一個要應用的對象前往便可。到這裡我們很輕易想到,struts中確定會有許多這類model須要獲得,所以這一塊我們也要抽取到BaseAction中去。
3.4 抽取ModelDriven到BaseAction
        起首我們在BaseAction中添加ModelDriven部門的代碼,以下:

//由於有許多分歧的model都須要應用ModelDriven,所以這裡應用泛型 
public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> { 
 
 protected Map<String, Object> request; 
 protected Map<String, Object> session; 
 protected Map<String, Object> application; 
 
 protected T model; 
 
 @Override 
 public void setApplication(Map<String, Object> application) { 
 this.application = application; 
 } 
 
 @Override 
 public void setSession(Map<String, Object> session) { 
 this.session = session; 
 } 
 
 @Override 
 public void setRequest(Map<String, Object> request) { 
 this.request = request; 
 } 
 
 @Override 
 public T getModel() { //這裡經由過程解析傳出去的T來new一個對應的instance 
 ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass(); 
 Class clazz = (Class)type.getActualTypeArguments()[0]; 
 try { 
  model = (T)clazz.newInstance(); 
 } catch (Exception e) { 
  throw new RuntimeException(e); 
 } 
 return model; 
 } 
} 

抽取完了後,CategoryAction中的代碼會愈來愈少:

//繼續BaseAction,而且加上泛型 
public class CategoryAction extends BaseAction<Category> { 
 
 private CategoryService categoryService; 
 
 public void setCategoryService(CategoryService categoryService) { 
 this.categoryService = categoryService; 
 } 
 
 public String update() { 
 System.out.println("----update----"); 
 categoryService.update(model);//直接應用model 
 return "index"; 
 } 
 
 public String save() { 
 System.out.println("----save----"); 
 System.out.println(model); //直接應用model 
 return "index"; 
 } 
 
 public String query() { 
 request.put("categoryList", categoryService.query()); 
 session.put("categoryList", categoryService.query()); 
 application.put("categoryList", categoryService.query()); 
 return "index"; 
 } 
 
} 

        到這裡,還有一個看著不爽的處所,就是categoryService這個成員變量,它一向存在在CategoryAction裡,由於CategoryAction中有效到categoryService對象中的辦法,所以必需得創立這個對象,而且有set辦法能力注入出去。這就招致一個弊病:假如許多Action都須要應用categoryService的話,那就必需在它們的Action裡創立這個對象和set辦法,並且,假如一個Action中要應用好幾個分歧的service對象,那就得全體創立,如許就變得很蕪雜。
3.5 抽取service到BaseAction
        針對下面的成績,我們將工程中一切的service對象都抽取到BaseAction中創立,如許其他Action繼續BaseAction後,想用甚麼service就直接拿來用便可:

//我將BaseAction中的內容歸歸類了 
public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> { 
 
 //service對象 
 protected CategoryService categoryService; 
 protected AccountService accountService; 
 
 public void setCategoryService(CategoryService categoryService) { 
 this.categoryService = categoryService; 
 } 
 public void setAccountService(AccountService accountService) { 
 this.accountService = accountService; 
 } 
 
 //域對象 
 protected Map<String, Object> request; 
 protected Map<String, Object> session; 
 protected Map<String, Object> application; 
  
 @Override 
 public void setApplication(Map<String, Object> application) { 
 this.application = application; 
 } 
 @Override 
 public void setSession(Map<String, Object> session) { 
 this.session = session; 
 } 
 @Override 
 public void setRequest(Map<String, Object> request) { 
 this.request = request; 
 } 
 
 //ModelDriven 
 protected T model; 
 @Override 
 public T getModel() { 
 ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass(); 
 Class clazz = (Class)type.getActualTypeArguments()[0]; 
 try { 
  model = (T)clazz.newInstance(); 
 } catch (Exception e) { 
  throw new RuntimeException(e); 
 } 
 return model; 
 } 
} 
 如許CategoryAction中就加倍清新了:
public class CategoryAction extends BaseAction<Category> { 
 
 public String update() { 
 System.out.println("----update----"); 
 categoryService.update(model); 
 return "index"; 
 } 
 
 public String save() { 
 System.out.println("----save----"); 
 System.out.println(model); 
 return "index"; 
 } 
 
 public String query() { 
 request.put("categoryList", categoryService.query()); 
 session.put("categoryList", categoryService.query()); 
 application.put("categoryList", categoryService.query()); 
 return "index"; 
 } 
 
} 

        有人能夠會問,BaseAction中注入了那末多service對象的話不會冗余麼?這是不會的,由於就算不寫在BaseAction中,Spring容器也是會創立這個對象的,這點沒有關系,相反,service對象全放在BaseAction中加倍便於其他Action的開辟,並且BaseAction不須要配到struts.xml文件中,由於基本就沒有哪一個JSP會要求BaseAction,它只是讓其他Action來繼續用的。
        還有一點別忘了:那就是修正在beans.xml中的設置裝備擺設:

<!-- 假如是prototype類型,默許是應用時創立,不是啟動時主動創立 --> 
<bean id="baseAction" class="cn.it.shop.action.BaseAction" scope="prototype"> 
 <property name="categoryService" ref="categoryService"></property> 
 <property name="accountService" ref="accountService"></property> 
</bean> 
 
<bean id="categoryAction" class="cn.it.shop.action.CategoryAction" scope="prototype" parent="baseAction"/>

         新加一個baseAction的bean,將工程中一切service對象作為property配好,將本來的categoryAction中的property干失落。
        今後我們假如要寫新的xxxAction,直接繼續BaseAction便可,假如xxxAction中有效到某個service,直接拿來用便可,只須要在beans.xml文件中加一個xxxAction對應的bean,在struts.xml文件中設置裝備擺設好跳轉便可。

4. 將xml改成注解
        我們可以看到,跟著項目越寫越年夜,beans.xml中的設置裝備擺設會愈來愈多,並且許多設置裝備擺設有冗余,為了加倍便於開辟,我們如今將xml的設置裝備擺設改成注解的情勢,我們先看一下beans.xml中的設置裝備擺設:

        這些是我們之前搭建情況和抽取的時刻寫的bean,這些都須要轉換成注解的情勢,上面我們一塊一塊的換失落:起首調換service部門,這部門有三個:baseService、categoryService和accountService。調換以下:


        然後將beans.xml中的響應部門干失落便可。接上去修正ActIon部門,重要有baseAction、categoryAction和accountAction三個,調換以下:


        然後再干失落beans.xml中的Action部門的設置裝備擺設便可,最初在beans.xml文件中添加一個以下設置裝備擺設,便可以應用注解了。
<context:component-scan base-package="cn.it.shop.."/> 
        有人能夠會問,為何service和action兩個應用注解的時刻紛歧樣呢?service中應用的是@Service而action中應用的是@Controller呢?實際上是一樣的,只是為了辨別它們是分歧層的bean罷了,便於浏覽。

全部項目標源碼下載地址:http://www.jb51.net/article/86099.htm

原文地址:http://blog.csdn.net/eson_15/article/details/51297698

以上就是SSH框架網上商城項目第2戰的全體內容,願望對年夜家的進修有所贊助,也願望年夜家多多支撐。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved