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、項目編碼
- 在servlet包中,新建一個OrderServlet,用於接收訂單數據請求,指定urlPatterns爲order.do。
- 在dao包中,建立OrderDao用於處理數據庫連接和操作。
- 在entity包中,建立OrderCost實體類,映射訂單支出記錄。
如下圖所示,是建立好文件後的項目結構圖。
1.2.1、OrderServlet的業務處理
主要處理邏輯:接收數據,驗證數據,保存數據,返回結果。
返回結果調用ExceptionUtil類裏面的printlnSuccess和printlnFailure方法,分別返回成功和失敗的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的觸發器、外鍵、索引等特性,輔助實現功能。