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的触发器、外键、索引等特性,辅助实现功能。

发布了89 篇原创文章 · 获赞 71 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/weixin_42127613/article/details/96448216