2.3.太極平臺:使用自定義表單的action來獨立處理增刪改操作

1、需求場景

太極平臺自身的框架,已經封裝了增刪改的操作。不需要修改任何配置項,每個組件就會自動完成增刪改的功能。

但是如果我們的增刪改操作,不僅僅只是想要完成單表單條數據的操作,而是要實現複雜的邏輯呢?

比如添加成本支出記錄時,要同步修改總支出數據(也可以通過數據庫的觸發器實現,參見章節:使用觸發器完成關聯數據的更新);

刪除訂單數據時,要同步刪除該條訂單關聯的支出記錄(也可以通過數據庫設置外鍵關聯來自動完成,參見章節:使用外鍵完成關聯數據的自動刪除)。

上述2個需求有其他簡單的解決方案(括號內的方案),僅作爲拋磚引玉。如果我們在添加數據時,還需要進行多個業務邏輯的計算,還要請求第三方的服務進行驗證,那這個需求僅僅通過太極平臺自帶的保存功能,就無法實現了。必須要單獨編寫業務邏輯代碼去完成。

下面介紹如何實現。

2、實現過程

爲簡單示例,我們就去實現上面的2個需求。

先說明一下數據庫表結構,2張表:訂單表、訂單支出表。我們直接引用觸發器章節的表結構。

1)訂單表(qd_order)

2)訂單支出表(qd_order_cost)

3)表關係的E-R圖,如下圖所示。

1)添加支出記錄時,更新訂單表的總支出金額。

1.1、太極平臺後臺設置

太極平臺自帶的添加功能,只會插入一條支出記錄。爲了實現同步更新訂單總支出金額,我們需要指定添加表單的action地址,指向到我們自己的業務處理地址。此時表單數據就會提交到新的action地址去。

如下圖所示,在太極平臺管理後臺→組件管理→選擇成本支出條目→編輯組件→添加表單設置→保存添加數據action,指向到:order.do?action=addcost

修改了action,變更了後端處理;前端我們還是可以借用框架生成的添加頁面,不用再去獨立編寫添加頁面。能省一點就省一點嘛。

在瀏覽器端,我們按F12在調試界面,可以看到添加表單數據提交的action,已經是我們自己設置的地址了。

1.2、項目編碼

  1. 在servlet包中,新建一個OrderServlet,用於接收訂單數據請求,指定urlPatterns爲order.do。
  2. 在dao包中,建立OrderDao用於處理數據庫連接和操作。
  3. 在entity包中,建立OrderCost實體類,映射訂單支出記錄。

如下圖所示,是建立好文件後的項目結構圖。

1.2.1、OrderServlet的業務處理

主要處理邏輯:接收數據,驗證數據,保存數據,返回結果。

返回結果調用ExceptionUtil類裏面的printlnSuccessprintlnFailure方法,分別返回成功和失敗的json格式到前端,前端會進行相應的提示。如下圖所示。

提交的數據,通過調試窗口也可以看到,如下圖所示。

因此後端只需要進行相應的數據處理即可。代碼如下。


package tech.qidian.servlet;

import tech.qidian.dao.OrderDao;
import tech.qidian.dev.admincommon.entity.TaiJiUser;
import tech.qidian.dev.webcommon.util.ExceptionUtil;
import tech.qidian.dev.webcommon.util.StringUtil;
import tech.qidian.entity.OrderCost;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;

@WebServlet(name = "OrderServlet", description = "處理訂單相關請求", urlPatterns = {"/order.do"})
public class OrderServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String action = request.getParameter("action");
        if (action == null) {
            action = "";
        }

        switch (action) {
            //添加支出記錄
            case "addcost":
                saveAddOrderCost(request, response);
                break;
        }

    }

    //處理添加支出記錄
    private void saveAddOrderCost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //驗證訂單ID正確
        int orderId = StringUtil.convertToInt(request.getParameter("OrderId"));
        if (orderId <= 0) {
            ExceptionUtil.printlnFailure(response, "訂單id參數錯誤");
            return;
        }
        //驗證支出名稱必填。太極框架自帶的必填項選項,會自動驗證。
        String costName = request.getParameter("CostName");
        if (StringUtil.isEmpty(costName)) {
            ExceptionUtil.printlnFailure(response, "支出名稱必填");
            return;
        }
        //驗證支出金額大於0
        float costMoney = StringUtil.convertToFloat(request.getParameter("CostMoney"));
        if (Float.compare(costMoney, 0.0f) <= 0) {
            ExceptionUtil.printlnFailure(response, "支出金額必填,且大於0");
            return;
        }

        OrderCost orderCost = new OrderCost();
        orderCost.setOrderId(orderId);
        orderCost.setCostName(costName);
        orderCost.setCostType(request.getParameter("CostType"));
        orderCost.setCostMoney(costMoney);
        orderCost.setCostDate(StringUtil.convertToDate(request.getParameter("CostDate")));
        //從session中獲取暱稱。
        //定義了TaiJiUser.SESSION_NICKNAME="nickname"。getAttribute有可能爲null,因此需要判斷轉換一下。
        orderCost.setNickName(StringUtil.convertObjToString(request.getSession().getAttribute(TaiJiUser.SESSION_NICKNAME)));

        OrderDao dao = new OrderDao();
        try {
            int rowId = dao.insertOrderCost(orderCost);
            //返回id小於等於0,則添加失敗。
            if (rowId <= 0) {
                ExceptionUtil.printlnFailure(response, "支出記錄添加失敗");
                return;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            //異常,進行異常日誌記錄。
            ExceptionUtil.insertDB(e, "支出記錄添加異常");
            //返回異常給前端顯示
            ExceptionUtil.printlnFailure(response, "支出記錄添加異常");
            return;
        }

        ExceptionUtil.printlnSuccess(response, "支出記錄添加成功");
    }
}

1.2.2、訂單支出實體類OrderCost,比較簡單。

package tech.qidian.entity;

import java.util.Date;

public class OrderCost {
    private int id;
    private int orderId;
    private String costName;
    private String costType;
    private float costMoney;
    private Date costDate;
    private String nickName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getOrderId() {
        return orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }

    public String getCostName() {
        return costName;
    }

    public void setCostName(String costName) {
        this.costName = costName;
    }

    public String getCostType() {
        return costType;
    }

    public void setCostType(String costType) {
        this.costType = costType;
    }

    public float getCostMoney() {
        return costMoney;
    }

    public void setCostMoney(float costMoney) {
        this.costMoney = costMoney;
    }

    public Date getCostDate() {
        return costDate;
    }

    public void setCostDate(Date costDate) {
        this.costDate = costDate;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
}

1.2.3、OrderDao數據庫處理類

這裏用到了事務處理,調用DbManager類的executeTransaction方法。多條SQL語句,在二維數組中,分別指定參數。

package tech.qidian.dao;

import tech.qidian.dev.webcommon.util.DbManager;
import tech.qidian.entity.OrderCost;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class OrderDao {
    //插入新的支出記錄
    public int insertOrderCost(OrderCost orderCost) throws SQLException {
        if (orderCost == null) {
            return 0;
        }

        //因爲要同步處理添加和更新,所以需要使用事務進行操作
        List<String> listSql = new ArrayList<>();
        //添加新的支出記錄
        listSql.add("insert into qd_order_cost(OrderId,CostName,CostType,CostMoney,CostDate,NickName) values(?,?,?,?,?,?)");
        //更新訂單表的總支出金額
        listSql.add("update qd_order set TotalCost=(select sum(CostMoney) from qd_order_cost where OrderId=?) where Id=?");

        //各條語句對應的參數。一個二維數組參數。
        Object[][] params = {
                {orderCost.getOrderId(), orderCost.getCostName(), orderCost.getCostType(),
                        orderCost.getCostMoney(), orderCost.getCostDate(), orderCost.getNickName()},
                {orderCost.getOrderId(), orderCost.getOrderId()}
        };

        //執行事務
        int[] rows = DbManager.executeTransaction(listSql, params);

        //事務批量執行影響的總行數求和
        return DbManager.sumIntArray(rows);
    }
}

最後執行添加,在數據庫中看已經成功保存,並且同步更新了總支出金額。功能成功實現。

2)修改支出,刪除支出處理

有了上面的案例,同樣的思路去處理編輯和刪除。在組件設置中,指定編輯和刪除的action地址。之後,在servlet中處理action分支響應,主要邏輯結構如下。

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String action = request.getParameter("action");
        if (action == null) {
            action = "";
        }

        switch (action) {
            //添加支出記錄
            case "addcost":
                saveAddOrderCost(request, response);
                break;
            //編輯支出記錄
            case "editCost":
                break;
            //刪除支出記錄
            case "deleteCost":
                break;
        }

    }

3、總結

從上面的案例中可以看出,哪怕是自己單獨去處理一個很簡單業務邏輯,也需要編寫三層業務架構。所以我們能不編碼,就儘量不要去編碼。這也是開發太極平臺框架的初衷,減少編碼量,利用配置項去實現。穩定、快速。

同時,我們也可以充分MySQL的觸發器、外鍵、索引等特性,輔助實現功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章