首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SSH 電商專案實戰 (二):Service/Action 抽取、基礎 CRUD 與註解驅動重構

     編輯:Java 相關知識

專案背景

承接上篇整合 Struts2 + Hibernate 4.3 + Spring 4.2 環境,本篇著重於服務層與控制層的抽象封裝,消除重複代碼,並從 XML 配置遷移至註解驅動,提升開發效率與維護性。

Service 層抽取:BaseService 模式

統一介面定義

public interface BaseService<T> {
    void save(T entity);
    void update(T entity);
    void delete(int id);
    T get(int id);
    List<T> query();
}

泛型基礎實現

@SuppressWarnings("unchecked")
public class BaseServiceImpl<T> implements BaseService<T> {
    protected Class<T> entityClass;
    @Autowired protected SessionFactory sessionFactory;

    public BaseServiceImpl() {
        // 透過反射獲取泛型實際類型
        ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
        entityClass = (Class<T>) type.getActualTypeArguments()[0];
    }

    protected Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override public void save(T entity) { getSession().save(entity); }
    @Override public void update(T entity) { getSession().update(entity); }
    @Override public void delete(int id) {
        String hql = "delete " + entityClass.getSimpleName() + " where id=:id";
        getSession().createQuery(hql).setInteger("id", id).executeUpdate();
    }
    @Override public T get(int id) { return getSession().get(entityClass, id); }
    @Override public List<T> query() { 
        return getSession().createQuery("from " + entityClass.getSimpleName()).list(); 
    }
}

具體 Service 實現

public interface CategoryService extends BaseService<Category> {
    // 擴充業務方法,如:List<Category> queryHotCategories();
}

@Service("categoryService")
public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {
    // 僅實現擴充方法,基礎 CRUD 繼承自 BaseServiceImpl
}

Spring 配置 (XML → 註解)

<!-- XML 殘留配置:僅定義基礎 Bean,lazy-init 避免泛型實例化錯誤 -->
<bean id="baseService" class="cn.it.shop.service.impl.BaseServiceImpl" lazy-init="true" abstract="true">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="categoryService" class="cn.it.shop.service.impl.CategoryServiceImpl" parent="baseService" />

註解驅動遷移:啟用 <context:component-scan base-package="cn.it.shop"/>,於類上標註 @Service、@Autowired,移除 XML 中對應 Bean 定義。

Action 層抽取:BaseAction 模式

核心功能封裝

@Controller
public class BaseAction<T> extends ActionSupport 
        implements ModelDriven<T>, RequestAware, SessionAware, ApplicationAware {

    // 領域模型 (ModelDriven)
    protected T model;
    @Override public T getModel() {
        try {
            ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
            Class<T> clazz = (Class<T>) type.getActualTypeArguments()[0];
            return clazz.newInstance();
        } catch (Exception e) { throw new RuntimeException(e); }
    }

    // 作用域 Map 注入
    protected Map<String, Object> request, session, application;
    @Override public void setRequest(Map<String, Object> request) { this.request = request; }
    @Override public void setSession(Map<String, Object> session) { this.session = session; }
    @Override public void setApplication(Map<String, Object> application) { this.application = application; }

    // 通用 Service 注入 (子類直接使用)
    @Autowired protected CategoryService categoryService;
    @Autowired protected AccountService accountService;
    // ... 其他通用 Service
}

具體 Action 實現

@Controller
@Scope("prototype")
@ParentPackage("shop")
@Namespace("/category")
public class CategoryAction extends BaseAction<Category> {

    @Action(value = "query", results = @Result(name = "success", location = "/category/list.jsp"))
    public String query() {
        request.put("categoryList", categoryService.query());
        return SUCCESS;
    }

    @Action(value = "save", results = @Result(name = "success", type = "redirectAction", params = {"actionName", "query"}))
    public String save() {
        categoryService.save(model);
        return SUCCESS;
    }

    @Action(value = "update", results = @Result(name = "success", type = "redirectAction", params = {"actionName", "query"}))
    public String update() {
        categoryService.update(model);
        return SUCCESS;
    }

    @Action(value = "delete", results = @Result(name = "success", type = "redirectAction", params = {"actionName", "query"}))
    public String delete() {
        categoryService.delete(model.getId());
        return SUCCESS;
    }
}

Struts2 註解驅動配置

<!-- struts.xml 精簡為僅載入註解掃描包 -->
<struts>
    <package name="shop" extends="struts-default">
        <!-- 註解掃描由 Struts2 Convention Plugin 自動完成 -->
    </package>
</struts>

// 需引入依賴
<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-convention-plugin</artifactId>
    <version>2.3.41</version>
</dependency>

重構效益總結

維度重構前重構後
Service 新增複製介面/實現/XML,修改類名繼承 BaseServiceImpl,僅寫擴充方法
Action 新增手寫 ModelDriven/Aware/Service 注入繼承 BaseAction,直接使用 model/service
配置維護beans.xml 膨脹,易出錯註解自動掃描,近零配置
程式碼重複大量 CRUD 樣板代碼集中於基類,單一職責

後續擴展建議

  • 引入 BaseDao 抽取 DAO 層通用操作。
  • 使用 PageHelper 或自定義分頁工具類統一分頁邏輯。
  • 導入驗證框架 (Hibernate Validator + Struts2 Validation) 統一參數校驗。
  • 採用 AOP 統一處理事務、日誌、異常轉換 (已在 Spring XML 中配置 tx:advice)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved