第二阶段(day16)添加,修改,删除

昨天的商品列表基础上进行:

1添加

仍然先从sql语句开始:

insert into tb_product(prod_id,prod_name,prod_price,prod_img,prod_desc) VALUE ('xxxx00001','test',35,'test','test')

再查询:SELECT * from tb_product tp

表中多了一条记录。

①.后端

在ProdDao里增加方法:

//添加商品 传入商品对象,返回执行成功的记录数
    Integer addProduct(Product insertProd);

在ProdDaoImpl里实现该方法:

@Override
    public Integer addProduct(Product insertProd) {
        Connection conn = DBHelper.getConn();
        String sql = "insert into tb_product(prod_id,prod_name,prod_price,prod_img,prod_desc) values (?,?,?,?,?)    ";
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Integer resNum = 0;
        System.out.println(sql);
        try {
            //防止注入攻击
            preparedStatement = conn.prepareStatement(sql);
            preparedStatement.setString(1,insertProd.getProdId());
            preparedStatement.setString(2,insertProd.getProdName());
            preparedStatement.setDouble(3,insertProd.getProdPrice());
            preparedStatement.setString(4,insertProd.getProdImg());
            preparedStatement.setString(5,insertProd.getProdDesc());
​
            resNum = preparedStatement.executeUpdate();
​
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBHelper.CloseConn(conn,null,preparedStatement,resultSet);
        }
​
        return resNum;
    }

在Mytest:

public class MyTest {
    public static void main(String[] args) {
        ProdDao prodDao = new ProdDaoImpl();
        Product insertProd = new Product("test123","test123",123d,"test123","test123");
        Integer integer = prodDao.addProduct(insertProd);
        System.out.println(integer);
    }
}
​

测试结果:insert into tb_product(prod_id,prod_name,prod_price,prod_img,prod_desc) values (?,?,?,?,?)

1

数据库刷新,记录也增加了。

在ProdService:

//添加商品 传入商品对象,返回执行成功的记录数
    Integer addProduct(Product insertProd);

在ProdServiceImpl:

 @Override
    public Integer addProduct(Product insertProd) {
        ProdDao pd = new ProdDaoImpl();
        return pd.addProduct(insertProd);
    }

在controller包下新建AddProdServlet,准备做添加服务接口:

@WebServlet("/addProd")
public class AddProdServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
         *
         * 查询商品信息服务接口
         * 请求地址  /day6/addProd
         * 请求参数  prodid       商品编号
         *          prodname     商品名称
         *          prodprice    商品价格
         *          prodimg      商品图片
         *          proddesc     商品描述
         * 请求方式   get/post
         * 响应数据格式  json
         * 响应数据实例
         *      {"retCode":10000,"retMsg":"操作成功"}
         *      {"retCode":10005,"retMsg":"操作失败"}
         *
         *
         * */
​
        /*接收参数
        转换格式
        封装对象*/
        req.setCharacterEncoding("utf-8");
​
        String prodId = req.getParameter("prodid");
        String prodName = req.getParameter("prodname");
        String prodPriceStr = req.getParameter("prodprice");
        String prodImg = req.getParameter("prodimg");
        String prodDesc = req.getParameter("proddesc");
​
        //需要格式转换的固定写法
        Double prodPrice = 0d;
        if(prodPriceStr != null && "".equals(prodPriceStr)){
            prodPrice = Double.parseDouble(prodPriceStr);
        }
​
        Product insertProd = new Product(prodId,prodName,prodPrice,prodImg,prodDesc);
​
        /*
         * 调用业务逻辑代码
         * */
        ProdService ps = new ProdServiceImpl();
        Integer resNum = ps.addProduct(insertProd);
​
        /*
         * 返回数据
         *
         * */
        ReturnEntity re = new ReturnEntity();
​
        if(resNum>0){
            re.setRetCode(ReturnCode.OPT_SUCCESS.getCode());
            re.setRetMsg(ReturnCode.OPT_SUCCESS.getMsg());
        }else{
            re.setRetCode(ReturnCode.OPT_FAILED.getCode());
            re.setRetMsg(ReturnCode.OPT_FAILED.getMsg());
        }
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print(JSON.toJSONString(re));
        writer.flush();
        writer.close();
​
    }
}

测试:这里使用一个新的工具postman,可以模拟http请求,但可将用例保存起来,用起来方便。

双击就自动安装好,然后跳过。

进入页面,New,Collect。相当于一个目录,是测试用例的集合。可起名(myreqs),可写注释(测试案例1)。

再new,Request。 起名(testAddProd),注释(测试添加商品案例),然后选择将测试案例放在哪个目录。

在idea重新部署,运行,在该工具点击send,下面出现返回的数据,可改格式。

{
    "retCode": 10000,
    "retMsg": "操作成功"
}

最后数据库再检查数据是否进去。

②.回到前端

一般有两种处理方式:

1.再准备一个添加页面,查询页面跳到添加页面,一般是准备一个按钮或超链接跳转。用户在添加页面添加完,发一个ajax请求去后台。根据响应的结果,展示处理结果。处理结果是另一个页面,由添加页面跳转过去。最后展示页面自动跳转回查询页面。

2.查询页面做一些弹出框,添加结束,发ajax请求,将结果直接展示在当前页面,并且弹出框关闭,最后刷新数据。

1.第一种策略

先在showProd.html中增加添加按钮:

<body>
<div class="mydiv">
    <form class="form-inline">
        <div class="form-group">
            <label for="prodid">商品编号</label>
            <input type="text" class="form-control" id="prodid" placeholder="prodid">
        </div>
        <div class="form-group">
            <label for="prodname">商品名称</label>
            <input type="email" class="form-control" id="prodname" placeholder="prodname">
        </div>
        //添加查询按钮
        <button id="queryBtn" type="button" class="btn btn-primary">查询</button>
        <a href="/day6/addProd.html" class="btn btn-success">添加</a>
    </form>

其他不变。

新建addProd.html

点击查询页面的添加按钮,跳转到添加页面,在添加页面输入信息,想要的效果是点击保存,发送ajax请求,调用保存的服务接口。

同时,不管成功失败都给用户展示一下结果,一个成功页面,一个失败页面。

新建web.pages.common包,在包下新建failed.html和success.html

addProd.html代码如下:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" type="text/css" href="/day6/css/bootstrap.css"/>
    <script src="/day6/js/jquery-3.6.0.js" type="text/javascript" charset="utf-8"></script>
    <script src="/day6/js/bootstrap.js" type="text/javascript" charset="utf-8"></script>
    <style>
        .mydiv{
            border: 1px solid gray;
            padding: 50px;
            width: 70%;
            height: 800px;
            margin: 50px auto;
​
            border-radius: 5%;
        }
        .mydiv img{
            width:80px ;
            height:80px ;
        }
    </style>
</head>
<body>
​
<div class="mydiv">
    <form id="myform">
        <div class="form-group">
            <label for="prodid">商品编号</label>
            <input type="text" class="form-control" id="prodid" name="prodid" placeholder="prodid">
        </div>
        <div class="form-group">
            <label for="prodname">商品名称</label>
            <input type="email" class="form-control" id="prodname" name="prodname" placeholder="prodname">
        </div>
        <div class="form-group">
            <label for="prodprice">商品单价</label>
            <input type="text" class="form-control" id="prodprice" name="prodprice" placeholder="prodprice">
        </div>
        <div class="form-group">
            <label for="prodimg">图片地址</label>
            <input type="text" class="form-control" id="prodimg" name="prodimg" placeholder="prodimg">
        </div>
        <div class="form-group">
            <label for="proddesc">商品描述信息</label>
            <input type="text" class="form-control" id="proddesc"  name="proddesc" placeholder="proddesc">
        </div>
        <button id="addBtn" type="button" class="btn btn-primary">保存</button>
    </form>
</div>
</body>
<script>
​
    /*
         *
         *
    *    *         * 查询商品信息服务接口
         * 请求地址  /day6/addProd
         * 请求参数  prodid
         *          prodname
         *          prodprice
         *          prodimg
         *          proddesc
         *
         * 请求方式   get/post
         * 响应数据格式  json
         * 响应数据实例
         * 没有数据:
         *      {"retCode":10000,"retMsg":"操作成功"}
         *      {"retCode":10005,"retMsg":"操作失败"}
    * */
​
    $("#addBtn").click(function(){
        var insertParams = $("#myform").serialize();  //serialize()格式化键值对,前提form里的表单元素要有name属性
        $.post("/day6/addProd",insertParams,function(data){
            console.log(data)
            if(data.retCode==10000){
               location.href = "day6/pages/common/success.html";
            }else if (data.retCode==10005){
                location.href = "day6/pages/common/failed.html";
            }
        },"json")
    })
​
</script>

failed.html代码如下:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
     操作失败 请联系管理员!!!!!
</body>
    <script>
        setTimeout(function(){
            location.href="../showProd.html";
        },2000);
​
    </script>
</html>

success.html代码如下:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
      执行成功!!!!
</body>
    <script>
        setTimeout(function(){
            location.href="../showProd.html";
        },2000);
​
    </script>
</html>

效果如下:

访问:http://localhost:8080/day6/pages/showProd.html 在出现 的查询页面点击添加按钮

跳转到:http://localhost:8080/day6/pages/addProd.html 在出现的添加页面将商品相关信息填写完,点击保存按钮。成功则跳转到成功页面,并显示执行成功!!!! 失败则跳转到失败页面,并展示操作失败 请联系管理员!!!!!

2.第二种策略

所有的功能都放在一个页面。更常见。

此时所有的代码都在showProd.html里:

用到bootstrap里的模态框(弹出框)

先做添加商品的弹出页面(id为防止重名,加了后缀Add)

<body>
<div class="mydiv">
    <form class="form-inline">
        <div class="form-group">
            <label for="prodid">商品编号</label>
            <input type="text" class="form-control" id="prodid" placeholder="prodid">
        </div>
        <div class="form-group">
            <label for="prodname">商品名称</label>
            <input type="email" class="form-control" id="prodname" placeholder="prodname">
        </div>
        <button id="queryBtn" type="button" class="btn btn-primary">查询</button>
        <!--<a href="/day6/pages/addProd.html" class="btn btn-success">添加</a>-->
        
        <!-- Button trigger modal 这是添加的按钮,点击触发弹出框-->
        <button type="button" class="btn btn-success " data-toggle="modal" data-target="#addModal">
            添加
        </button>
        
    </form>
    <br/>
    <table class="table">
        <tr>
            <th>商品编号</th>
            <th>商品信息</th>
            <th>单价</th>
            <th>描述信息</th>
        </tr>
        <tbody id="mainData">
        </tbody>
    </table>
    <button class="btn btn-default prevBtn">上一页</button>
    <button class="btn btn-default nextBtn">下一页</button>
    当前第 <span id="pageSpan"></span> 页;总共  <span id="totalPageSpan"></span> 页  每页显示  <span id="pageSizeSpan"></span>  条记录
</div>
​
<!-- Modal 弹出的界面-->
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加商品</h4>
            </div>
            <div class="modal-body">
                <form id="myform">
                    <div class="form-group">
                        <label for="prodid">商品编号</label>
                        <input type="text" class="form-control" id="prodidAdd" name="prodid" placeholder="prodid">
                    </div>
                    <div class="form-group">
                        <label for="prodname">商品名称</label>
                        <input type="email" class="form-control" id="prodnameAdd" name="prodname" placeholder="prodname">
                    </div>
                    <div class="form-group">
                        <label for="prodpriceAdd">商品单价</label>
                        <input type="text" class="form-control" id="prodpriceAdd" name="prodprice" placeholder="prodprice">
                    </div>
                    <div class="form-group">
                        <label for="prodimgAdd">图片地址</label>
                        <input type="text" class="form-control" id="prodimgAdd" name="prodimg" placeholder="prodimg">
                    </div>
                    <div class="form-group">
                        <label for="proddescAdd">商品描述信息</label>
                        <input type="text" class="form-control" id="proddescAdd"  name="proddesc" placeholder="proddesc">
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                <button type="button" class="btn btn-primary" data-dismiss="modal">保存</button>
            </div>
        </div>
    </div>
</div>
​
</body>

接下来,弹出的添加界面输入商品信息,点击保存按钮后,保存数据。

在保存按钮增加id属性:

<button id="addSubmitBtn" type="button" class="btn btn-primary" data-dismiss="modal">保存</button>

在script标签增加事件,要做的事:将form里的键值对抓出来,调用添加服务接口。

但响应的处理不同(给用户展示操作成功失败的信息),不往其他页面跳转,这里用警告框(有x可关闭)。

此时就需要在页面加一个div,去定位,漂浮在其它元素上,里面没有东西,需要展示结果时将警告框填入。

给div加样式:

定位属性想要控制在指定位置出现,并脱离文档流,用绝对或者固定定位,之后加上偏移。

样式上做一些弹出框,希望弹出框在正中间,加上left:50%;之后是左边在正中间,不是中线在正中间,想让整体在中间,需要弹出框左移自己框的一半。

警告框关闭后,应该能自己刷新数据,将刚才新增的数据加在查询页面,实际就是再掉调一次查询功能。

代码如下:

<style>
       <--以前的代码-->
        .showResPanel{
            position: absolute;
            top: 30%;
            left: 50%;
        }
        .myalert{
            width:300px;
            height: 150px;
            margin-left:-150px;
        }
</style>
<body>
<--之前的代码-->
<div class="showResPanel">
</div>
​
</body>
<script>
//之前的代码不动
​
$("#addSubmitBtn").click(function () {
        var insertParams = $("#myform").serialize();  //serialize()格式化键值对,前提form里的表单元素要有name属性
        $.post("/day6/addProd",insertParams,function(data){
            console.log(data)
            //展示结果
            var alertcls = "";
​
            if(data.retCode==10000){
                alertcls = "alert-success";
            }else if (data.retCode==10005){
                alertcls = "alert-danger";
            }
            var mycontent = '<div class="myalert alert '+alertcls+' alert-dismissible fade in" role="alert">' +
                '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
                '<h4>操作结果</h4>' +
                '<p>'+data.retMsg+'</p>' +
                '</div>'
​
            $(".showResPanel").html(mycontent);
​
            //刷新数据 重新查询table数据
            var params = {"prodid":$("#prodid").val(),"prodname":$("#prodname").val(),"page":page};
            queryData(params);
​
        },"json")
    })
</script>
    

不管哪种策略,都要准备一组添加数据的框,然后通过ajax请求,把框里的数据发给后台,调用添加的服务接口,根据后台反馈的成功或者失败,展示操作的结果。最后把数据刷新出来。

2.合并servlet

做完查询和添加,还剩修改和删除。

首先准备两个服务接口。最终一个商品写了四个服务接口,很麻烦。 故这里将和商品相关的服务接口都写在一个类里。

官方给出的解决方案:在servlet重写的service方法里,通过if-else根据请求方式的不同去分段。

故,我们也可以直接重写get,post等请求方式,get用来取数据,put做添加,post做修改,delete做删除,这些在http协议有。但,服务接口太多会不够用。

我们也可以在请求里多传入一个参数,该参数指明具体做哪个操作,即/day6/ajaxProd?doWhat=addProd。if-else根据操作的不同去分段。弊端是很多地方需要拼参数,代码的结构不好看。

还有一种处理方案:

请求地址是/day6/ajaxProd/addProd 或者 /day6/ajaxProd/editProd 的形式。

多个不同的请求都想进入同一个servlet,在servlet地址的配置上也可使用通配符*,即

/ajaxProd/*

如何读取请求地址:

req.getServletPath();  //获取的是"/ajaxProd",会忽略*部分
req.getRequestURI();   //获取当次请求地址 /day6/ajaxProd/add
req.getRequestURL();   //获取当次请求的完整的地址  http://localhost:8080/day6/ajaxProd/add
​

截取最后一部分,用req.getRequestURI()即可。

代码如下:

@WebServlet("/ajaxProd/*")
public class AjaxProdServlet extends HttpServlet {
​
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //读取请求地址最后一部分,拿到方法名
        String requestURI = req.getRequestURI();
        String myMethodName = requestURI.substring(requestURI.lastIndexOf("/") + 1);
​
        try {
            //拿到方法名,想让方法名去执行,需要反射.反射获取的是public修饰的方法
            //通过当前的类型获取定义出的方法。
            Method myMethodName1 = this.getClass().getDeclaredMethod(myMethodName, HttpServletRequest.class, HttpServletResponse.class);
            //invoke()去执行该方法对象,参数是用哪个实例对象调该方法,是当前servlet实例对象调用,用this。还要传入指定的参数,是定义方法对象时的
            //两个类型参数
            Object invoke = myMethodName1.invoke(this, req, resp);
​
            /*//如果不用反射,没有this.myMethodName()!!!只能if-else
            if("addProd".equals(myMethodName)){
                this.addProd(req,resp);
            }*/
        } catch (NoSuchMethodException e) {   //没有指定的方法,比如/day6/ajaxProd/test,类里没有test方法,就会报该异常
            //没有指定的方法,对于请求而言,实质就是没有对应的服务器处理,告诉它404会更好,Tomcat里有该功能
            resp.sendError(404);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
​
    }
​
    public void addProd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
​
        /*
         *
         * 查询商品信息服务接口
         * 请求地址  /day6/addProd
         * 请求参数  prodid       商品编号
         *          prodname     商品名称
         *          prodprice    商品价格
         *          prodimg      商品图片
         *          proddesc     商品描述
         * 请求方式   get/post
         * 响应数据格式  json
         * 响应数据实例
         *      {"retCode":10000,"retMsg":"操作成功"}
         *      {"retCode":10005,"retMsg":"操作失败"}
         *
         *
         * */
​
        /*接收参数
        转换格式
        封装对象*/
        req.setCharacterEncoding("utf-8");
​
        String prodId = req.getParameter("prodid");
        String prodName = req.getParameter("prodname");
        String prodPriceStr = req.getParameter("prodprice");
        String prodImg = req.getParameter("prodimg");
        String prodDesc = req.getParameter("proddesc");
​
        //需要格式转换的固定写法
        Double prodPrice = 0d;
        if(prodPriceStr != null && "".equals(prodPriceStr)){
            prodPrice = Double.parseDouble(prodPriceStr);
        }
​
        Product insertProd = new Product(prodId,prodName,prodPrice,prodImg,prodDesc);
​
        /*
         * 调用业务逻辑代码
         * */
        ProdService ps = new ProdServiceImpl();
        Integer resNum = ps.addProduct(insertProd);
​
        /*
         * 返回数据
         *
         * */
        ReturnEntity re = new ReturnEntity();
​
        if(resNum>0){
            re.setRetCode(ReturnCode.OPT_SUCCESS.getCode());
            re.setRetMsg(ReturnCode.OPT_SUCCESS.getMsg());
        }else{
            re.setRetCode(ReturnCode.OPT_FAILED.getCode());
            re.setRetMsg(ReturnCode.OPT_FAILED.getMsg());
        }
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print(JSON.toJSONString(re));
        writer.flush();
        writer.close();
    }
​
    public void queryProd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
​
        /*
         * 接收参数
         * 转换格式
         * 封装对象
         *
         * 查询商品信息服务接口
         * 请求地址  /day6/ajaxProd
         * 请求参数  page       页码
         *          pageSize   每页显示的记录数
         * 请求方式   get/post
         * 响应数据格式  json
         * 响应数据实例
         * 没有数据:
         *      {"retCode":20001,"retMsg":"没有数据"}
         * 有数据:
         *      {"retCode":20000,
         *      "retData":[{"prodDesc":"测试手机","prodId":"SJ00150033","prodImg":"img/phone1.jpg","prodName":"测试手机33","prodPrice":1033}],
         *      "retMsg":"查询成功",
         *      "pageInfo":{"page":1,"pageSize":3,"totalPage":3}}
         *
         * */
​
        req.setCharacterEncoding("utf-8");
        String pageStr = req.getParameter("page");
        String pageSizeStr = req.getParameter("pageSize");
​
        String prodId = req.getParameter("prodid");
        String prodName = req.getParameter("prodname");
​
        Integer page = 1;
        Integer pageSize = 3;
        if(!"".equals(pageStr)&&pageStr!=null){
            page = Integer.parseInt(pageStr);
        }
        if(!"".equals(pageSizeStr)&&pageSizeStr!=null){
            pageSize = Integer.parseInt(pageSizeStr);
        }
​
        /*
         * 调用业务逻辑代码
         * */
        //查询使用的Product对象
        Product queryProd = new Product();
        queryProd.setProdId(prodId);
        queryProd.setProdName(prodName);
​
        ProdService ps =new ProdServiceImpl();
        List<Product> allProd = ps.getAllProd(page,pageSize,queryProd);
​
        //返回的总页数(增加一处)
        Integer totalPage = ps.getTotalPage(pageSize,queryProd);
​
        System.out.println(allProd);
​
        /*
         * 返回数据
         *
         * */
        ReturnEntity re = new ReturnEntity();
​
        if(allProd.size()>0){
            re.setRetCode(ReturnCode.QUERY_SUCCESS.getCode());
            re.setRetMsg(ReturnCode.QUERY_SUCCESS.getMsg());
            re.setRetData(allProd);
            //增加第二处
            PageInfo pif = new PageInfo(page,pageSize,totalPage);
            re.setPif(pif);
        }else{
            re.setRetCode(ReturnCode.QUERY_NODATA.getCode());
            re.setRetMsg(ReturnCode.QUERY_NODATA.getMsg());
            //增加第三处
            PageInfo pif = new PageInfo(1,1,1);  //没参数,则三个都给1
            re.setPif(pif);
        }
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print(JSON.toJSONString(re));
        writer.flush();
        writer.close();
    }
​
    public void deleteProd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
​
    }
}

服务接口的接收地址改为@WebServlet("/ajaxProd/*")后,前端请求对应的地址也修改一下:

在showProd类里:

在script部分,查询的地址改变:

function queryData(params){
        $.getJSON("/day6/ajaxProd/queryProd",params,function(data){
        //...
})

添加方法的地址修改:

$("#addSubmitBtn").click(function () {
        var insertParams = $("#myform").serialize();  //serialize()格式化键值对,前提form里的表单元素要有name属性
        $.post("/day6/ajaxProd/addProd",insertParams,function(data){
        //...
         },"json")
    })

测试:

重新部署,运行,访问:http://localhost:8080/day6/pages/showProd.html

查询页面出现,点击添加,输入商品信息,点击保存,弹出操作结果 操作正确,关闭该框,会在查询页面找到刚才新增的这条商品信息,同时在数据库也能找到该条数据。

这也说明,合并的查询和添加服务接口没问题。

如果再增加一个用户服务接口,里面也是查询,增加,....等方法。

对应的方法,代码差不多,故可使用一个公共父类,把公共方法定义在父类里,让子类继承。

新建BaseServlet,作为公共父类,主要目的重写service方法。(公共父类不加请求地址)

public class BaseServlet extends HttpServlet {
​
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        String requestURI = req.getRequestURI();
        String myMethodName = requestURI.substring(requestURI.lastIndexOf("/") + 1);
​
        try {
        Method myMethodName1 = this.getClass().getDeclaredMethod(myMethodName, HttpServletRequest.class, HttpServletResponse.class);
        myMethodName1.invoke(this, req, resp);
​
        } catch (NoSuchMethodException e) {
            resp.sendError(404);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
​
    }
}

在AjaxProdServlet里,直接删掉继承的公共父类的代码即可,其他不变:

@WebServlet("/ajaxProd/*")
public class AjaxProdServlet extends BaseServlet {
​
public void addProd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//...
 }
 public void queryProd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 //...
 }

3.修改

①.前端

页面的变化形式:还是在查询页面多加一个修改按钮,选择要修改的记录,点击该按钮,弹出一个框,修改信息,点击保存,出现修改成功或者失败的提示信息。若修改成功,关闭提示信息,页面会自动刷新。(用一个页面的策略)

如何定位到操作的是哪条记录,在showProd.htm里,找到table标签,加一条操作

<table class="table">
        <tr>
            <th>商品编号</th>
            <th>商品信息</th>
            <th>单价</th>
            <th>描述信息</th>
            <th>操作</th>
        </tr>
        <tbody id="mainData">
        </tbody>
    </table>

对应的将生成的数据添加进去:

function queryData(params){
        $.getJSON("/day6/ajaxProd/queryProd",params,function(data){
            console.log(data);
            $("#mainData").html("");
            if(data.retCode == 20000){//查询成功 遍历数据
                //把数据遍历到页面中
                $.each(data.retData,function(i,d){
                    var content = '<tr>'
                        +'<td>'+d.prodId+'</td>'
                        +'<td>'+d.prodName+'<br/><img src="/day6/'+d.prodImg+'"/></td>'
                        +'<td>'+d.prodPrice+'</td>'
                        +'<td>'+d.prodDesc+'</td>'
                        +'<td><input prodid="'+d.prodId+'" type="button" value="修改" class="btn btn-warning"></td>'
                        +'</tr>';
                    $("#mainData").append(content);
                })
                //...

另一种定位要操作记录的方法:

不在每一行后面放按钮,在添加后面加一个按钮。

<button type="button" class="btn btn-success " data-toggle="modal" data-target="#addModal">
  添加
</button>
<button type="button" class="btn btn-warning " data-toggle="modal" data-target="#editModal">
  修改
</button>

在body标签里添加对应的Modal后加:

<!-- Modal -->
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" >修改商品</h4>
            </div>
            <div class="modal-body">
                <form id="editform">
                    <div class="form-group">
                        <label for="prodid">商品编号</label>
                        <input type="text" class="form-control" id="prodidEdit" name="prodid" placeholder="prodid">
                    </div>
                    <div class="form-group">
                        <label for="prodname">商品名称</label>
                        <input type="email" class="form-control" id="prodnameEdit" name="prodname" placeholder="prodname">
                    </div>
                    <div class="form-group">
                        <label for="prodpriceAdd">商品单价</label>
                        <input type="text" class="form-control" id="prodpriceEdit" name="prodprice" placeholder="prodprice">
                    </div>
                    <div class="form-group">
                        <label for="prodimgAdd">图片地址</label>
                        <input type="text" class="form-control" id="prodimgEdit" name="prodimg" placeholder="prodimg">
                    </div>
                    <div class="form-group">
                        <label for="proddescAdd">商品描述信息</label>
                        <input type="text" class="form-control" id="proddescEdit"  name="proddesc" placeholder="proddesc">
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                <button id="editSubmitBtn" type="button" class="btn btn-primary" data-dismiss="modal">保存</button>
            </div>
        </div>
    </div>
</div>

按钮添加好后,选择一条记录,点击修改按钮,弹出一个框,修改商品信息。

点击到对应行,增加点击效果。首先元素生成在页面,才能加点击效果。

function queryData(params){
        $.getJSON("/day6/ajaxProd/queryProd",params,function(data){
            console.log(data);
            $("#mainData").html("");
            if(data.retCode == 20000){//查询成功 遍历数据
                //把数据遍历到页面中
                $.each(data.retData,function(i,d){
                    var content = '<tr>'
                        +'<td>'+d.prodId+'</td>'
                        +'<td>'+d.prodName+'<br/><img src="/day6/'+d.prodImg+'"/></td>'
                        +'<td>'+d.prodPrice+'</td>'
                        +'<td>'+d.prodDesc+'</td>'
                        +'</tr>';
                    $("#mainData").append(content);
                })
                //添加点击事件
                $("mainData tr").click(function () {
                  var prodid = $(this).find("td").eq(0).html();
                  console.log(prodid);
                })
                //...

现在点击一条记录,开发者工具的控制台输出对应的商品编号,即定位到对应的记录。

少一些样式,需要让用户看到。最简单的方式,点击该行,变色。

//添加点击事件
$("mainData tr").click(function () {
var prodid = $(this).find("td").eq(0).html();
console.log(prodid);
$(this).addClass("info");
})

点击后,背景色变成浅蓝色。

点击后还需要清掉

//添加点击事件
$("mainData tr").click(function () {
var prodid = $(this).find("td").eq(0).html();
console.log(prodid);
$("mainData tr").removeClass("info");
$(this).addClass("info");
})

拿到编号后,通过一个变量保存该值,点击修改按钮,就可将对应记录发到后台查完整数据,响应回来之后,弹出商品信息,修改信息即可。

声明一个变量:

var page ;
var pageSize ;
var totalPage ;
var selectedId;
//添加点击事件
$("mainData tr").click(function () {
selectedId = $(this).find("td").eq(0).html();
console.log(selectedId);
$("mainData tr").removeClass("info");
$(this).addClass("info");
})

找到修改按钮,加一个id属性:

<button id="editBtn" type="button" class="btn btn-warning " data-toggle="modal" data-target="#editModal">
修改
</button>

在script标签增加:

//打开修改对话框按钮
    $("#editBtn").click(function () {
     //通过当前选中行的id 查询完整的数据
​
    })

②.后端

从要使用的sql开始:通过id查商品

在ProdDao,增加方法:

//通过id查商品
    Product getProdById(String prodId);

在ProdDaoImpl:

@Override
    public Product getProdById(String queryProdId) {
        Connection conn = DBHelper.getConn();
        String sql = " select tp.prod_id,tp.prod_desc,tp.prod_name,tp.prod_price,tp.prod_img from tb_product tp where tp.prod_id=? ";
​
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Product myProd = null;
        System.out.println(sql);
        try {
            preparedStatement = conn.prepareStatement(sql);
            preparedStatement.setObject(1,queryProdId);
​
            resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){
​
                String prodId = resultSet.getString("prod_id");
                String prodName = resultSet.getString("prod_name");
                Double prodPrice = resultSet.getDouble("prod_price");
                String prodImg = resultSet.getString("prod_img");
                String prodDesc = resultSet.getString("prod_desc");
​
                myProd = new Product(prodId,prodName,prodPrice,prodImg,prodDesc);
            }
​
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBHelper.CloseConn(conn,null,preparedStatement,resultSet);
        }
​
        return myProd;
    }

在MyTest:

public class MyTest {
    public static void main(String[] args) {
        ProdDao prodDao = new ProdDaoImpl();
        Product prodById = prodDao.getProdById("SJ00110013");
        System.out.println(prodById);
​
    }
}

测试结果:

select tp.prod_id,tp.prod_desc,tp.prod_name,tp.prod_price,tp.prod_img from tb_product tp where tp.prod_id=? Product(prodId=SJ00110013, prodName=便宜手机, prodPrice=95.3, prodImg=img/phone2.jpg, prodDesc=便宜手机, prodNum=null)

ProdService类:

Product getProdById(String prodId);

ProdServiceImpl:

@Override
    public Product getProdById(String prodId) {
        ProdDao pd = new ProdDaoImpl();
        return pd.getProdById(prodId);
    }

在AjaxProdServlet增加对应方法:

public void readyForEdit(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String prodid = req.getParameter("prodid");
​
        ProdService ps = new ProdServiceImpl();
        Product prodById = ps.getProdById(prodid);
​
        ReturnEntity re = new ReturnEntity();
        if (prodById!=null){
            re.setRetCode(ReturnCode.QUERY_SUCCESS.getCode());
            re.setRetMsg(ReturnCode.QUERY_SUCCESS.getMsg());
            re.setRetData(prodById);
        }else{
            re.setRetCode(ReturnCode.QUERY_NODATA.getCode());
            re.setRetMsg(ReturnCode.QUERY_NODATA.getMsg());
        }
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print(JSON.toJSONString(re));
        writer.flush();
        writer.close();
    }

测试:使用Postman工具

输入的url:http://localhost:8080/day6/ajaxProd/readyForEdit?prodid=11

输入的参数:Prodid 给的value为1,点击send

结果:

{"retCode":20000,"retData":{"prodDesc":"11","prodId":"11","prodImg":"11","prodName":"11","prodPrice":0},"retMsg":"查询成功"}

③.回到前端

补全刚才的代码:

//打开修改对话框按钮
    $("#editBtn").click(function(){
        //通过当前选中行的id 查询完整的数据
        $.getJSON("/day6/ajaxProd/readyForEdit","prodid="+selectedId,function(data){
            //把修改的完整输入 填入页面中
            $("#prodidEdit").val(data.retData.prodId);
            $("#prodnameEdit").val(data.retData.prodName);
            $("#prodpriceEdit").val(data.retData.prodPrice);
            $("#prodimgEdit").val(data.retData.prodImg);
            $("#proddescEdit").val(data.retData.prodDesc);
        })
    })

选中某条记录,点击修改按钮,会返回对应的商品信息。

到目前为止,修改商品写完一半了。

接下来写修改的服务接口

④.回到后端

ProdDao:

//修改商品 传入商品对象,返回执行成功的记录数
    Integer editProduct(Product insertProd);

ProdDaoImpl:

@Override
    public Integer editProduct(Product insertProd) {
        Connection conn = DBHelper.getConn();
        String sql = "update tb_product set prod_name = ? ,prod_price = ? ,prod_img = ? ,prod_desc = ?  where  prod_id = ?  ";
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Integer resNum = 0;
        System.out.println(sql);
        try {
            preparedStatement = conn.prepareStatement(sql);
​
            preparedStatement.setString(1,insertProd.getProdName());
            preparedStatement.setDouble(2,insertProd.getProdPrice());
            preparedStatement.setString(3,insertProd.getProdImg());
            preparedStatement.setString(4,insertProd.getProdDesc());
            preparedStatement.setString(5,insertProd.getProdId());
            resNum = preparedStatement.executeUpdate();
​
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBHelper.CloseConn(conn,null,preparedStatement,resultSet);
        }
        return resNum;
    }

MyTest:

public class MyTest {
    public static void main(String[] args) {
        ProdDao prodDao = new ProdDaoImpl();
        Product insertProd = new Product("test12345","test123",123d,"test123","test123");
        Integer integer = prodDao.editProduct(insertProd);
        System.out.println(integer);
​
    }
}

ProdService:

Integer editProduct(Product insertProd);

ProdServiceImpl:

@Override
    public Integer editProduct(Product insertProd) {
        ProdDao pd = new ProdDaoImpl();
        return pd.editProduct(insertProd);
    }

AjaxProdServlet:

public void editProd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
​
        String prodId = req.getParameter("prodid");
        String prodName = req.getParameter("prodname");
        String prodPriceStr = req.getParameter("prodprice");
        String prodImg = req.getParameter("prodimg");
        String prodDesc = req.getParameter("proddesc");
​
        Double prodPrice = 0d;
        if(prodPriceStr!=null&&!"".equals(prodPriceStr)){
            prodPrice = Double.parseDouble(prodPriceStr);
        }
​
        Product insertProd = new Product(prodId,prodName,prodPrice,prodImg,prodDesc);
​
        /*
         * 调用业务逻辑代码
         *
         * */
        ProdService ps =new ProdServiceImpl();
        Integer resNum = ps.editProduct(insertProd);
​
        /*
         * 返回数据
         *
         * */
        ReturnEntity re = new ReturnEntity();
​
        if(resNum>0){
            re.setRetCode(ReturnCode.OPT_SUCCESS.getCode());
            re.setRetMsg(ReturnCode.OPT_SUCCESS.getMsg());
        }else{
            re.setRetCode(ReturnCode.OPT_FAILED.getCode());
            re.setRetMsg(ReturnCode.OPT_FAILED.getMsg());
        }
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print(JSON.toJSONString(re));
​
        writer.flush();
        writer.close();
    }

测试:

http://localhost:8080/day6/ajaxProd/editProd?prodid=111&prodname=111&prodprice=111&prodimg=111&proddesc=111

⑤.回到前端

和添加功能非常像。

//修改提交按钮
    $("#editSubmitBtn").click(function(){
        var url ="/day6/ajaxProd/editProd";
        var params =$("#editform").serialize();
        CUDData(url,params);
    })
    
  function CUDData(url,params){//c u r d
        $.post(url,params,function(data){
            console.log(data);
​
            var alertcls = "";
            //展示结果
            if(data.retCode==10000){
                alertcls = "alert-success";
            }else if(data.retCode==10005){
                alertcls = "alert-danger";
            }
            var mycontent = '<div class="myalert alert '+alertcls+' alert-dismissible fade in" role="alert">' +
                '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
                '<h4>操作结果</h4>' +
                '<p>'+data.retMsg+'</p>' +
                '</div>';
​
            $(".showResPanel").html(mycontent);
​
            //刷新数据 重新查询table数据
            var params = {"prodid":$("#prodid").val(),"prodname":$("#prodname").val(),"page":page};
            queryData(params);
​
        },"json")
    }

这里应该把商品编号做成只读:

<div class="form-group">
<label for="prodidAdd">商品编号</label>
<input type="text" class="form-control" id="prodidEdit" readonly name="prodid" placeholder="prodid">
                    </div>

4.删除

删除也是两种方式:1.每行后加一个删除按钮

2.选择到一行后再删除

选中一行的功能已经做好,下面来展示要删除的数据;

先做一个和修改类似的按钮,点击该按钮,弹出信息:

①.前端

先加一个按钮:

<button id="editBtn" type="button" class="btn btn-warning" data-toggle="modal" data-target="#editModal">
   修改
</button>
​
<button id="delBtn" type="button" class="btn btn-danger" data-toggle="modal" data-target="#delModal">
   删除
</button>

再来一组弹出框:

也可以展示form,每个都加上只读。但没太大必要,只需提醒。

<!-- Modal -->
<div class="modal fade" id="delModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" >删除商品</h4>
            </div>
            <div class="modal-body">
                此操作将删除编号为 <span id="delprodid" style="color: deeppink"></span> 的记录 确实删除么!!!
​
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                <button id="delSubmitBtn" type="button" class="btn btn-primary" data-dismiss="modal">删除</button>
            </div>
        </div>
    </div>
</div>

此时弹出框只需把记录的编号填进去。

处理弹出框内容:

//打开删除对话框按钮
    $("#delBtn").click(function(){
        //展示要删除数据对话框 提示当前数据的id
        $("#delprodid").html(selectedId);
​
    })

对于弹出的信息,如果确定删除,则发到后台,调用删除服务接口。

②.后台

编写删除服务接口:

还是先看sql:DELETE FROM tb_product WHERE prod_id = '111'

执行后,数据库该条记录消失。

ProDao:

//删除商品 传入商品编号,返回执行成功的记录数
    Integer delProduct(String prodId);

ProDaoImpl:

@Override
    public Integer delProduct(String prodId) {
        Connection conn = DBHelper.getConn();
        String sql = "delete from tb_product where prod_id = ?  ";
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Integer resNum = 0;
        System.out.println(sql);
        try {
            preparedStatement = conn.prepareStatement(sql);
​
            preparedStatement.setString(1,prodId);
            resNum = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBHelper.CloseConn(conn,null,preparedStatement,resultSet);
        }
​
        return resNum;
    }

MyTest:

public class MyTest {
    public static void main(String[] args) {
        ProdDao prodDao = new ProdDaoImpl();
        Integer integer = prodDao.delProduct("11");
        System.out.println(integer);
​
    }
}

控制台:

delete from tb_product where prod_id = ? 1

数据库中该条记录消失

ProdService:

Integer delProduct(String prodId);

ProdServiceIml:

@Override
    public Integer delProduct(String prodId) {
        ProdDao pd = new ProdDaoImpl();
        return pd.delProduct(prodId);
    }

AjaxProdServlet:

public void delProd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("执行删除");
        req.setCharacterEncoding("utf-8");
​
        String prodId = req.getParameter("prodid");
        /*
         * 调用业务逻辑代码
         *
         * */
        ProdService ps =new ProdServiceImpl();
        Integer resNum = ps.delProduct(prodId);
        /*
         * 返回数据
         *
         * */
        ReturnEntity re = new ReturnEntity();
​
        if(resNum>0){
            re.setRetCode(ReturnCode.OPT_SUCCESS.getCode());
            re.setRetMsg(ReturnCode.OPT_SUCCESS.getMsg());
        }else{
            re.setRetCode(ReturnCode.OPT_FAILED.getCode());
            re.setRetMsg(ReturnCode.OPT_FAILED.getMsg());
        }
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print(JSON.toJSONString(re));
        writer.flush();
        writer.close();
    }

测试:

http://localhost:8080/day6/ajaxProd/delProd?prodid=13141

数据库对应记录消失

服务接口完成,用页面发出请求,调用服务接口。

③.前端

//删除提交
    $("#delSubmitBtn").click(function(){
        var url ="/day6/ajaxProd/delProd";
        var params ="prodid="+selectedId;
        CUDData(url,params);
    })

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值