Javaweb08-Ajax项目-分页条件查询 + 增删改

1、登录


             欢迎登录课工场KH96动漫管理系统

            用户名:

    用户密码:

欢迎登录课工场KH96动漫管理系统 用户名:

用户密码:


    $(function(){
        //使用jQuery的Ajax实现异步登录
        //监听表单提交事件,数校验
        $("form").submit(function(){
            //登录名校验
            var userName = $("#uname").val();
            if(userName == null || userName == ""){
                alert("用户名不能为空");
                return false;
            }

            var userPwd = $("#upwd").val();
            if(userPwd == null || userPwd == ""){
                alert("密码不能为空");
                return false;
            }

            //发送请求
            $.post("<%=request.getContextPath()%>/loginAnime",{"userName" : userName,"userPwd":userPwd},function(data){
                 //解析数据
                 //alert("登录"+data);
                 if(data == "true"){
                     //alert("登录成功");
                     location.href= "animeList.jsp";

                 }else{
                     alert("登录失败");
                 }
            });

            //取消表单提交
            return false;

        });

    });

//判断场景
$("form").submit(function(){
    //发送请求
    $.post("/loginAnime",{"userName" : userName,"userPwd":userPwd},function(data){
        //1.直接使用字符型判断
        if(data == "true"){
        //2.转换成boolean类型判断
        //if(JSON(data) == true)
            //alert("登录成功");
            location.href= "animeList.jsp";

        }else{
            alert("登录失败");
        }
    })
    //取消表单提交
    return false;

});
//场景
$("#codeLogin").click(function () {
    $.getJSON("userServlet?method=sendEmail",null ,function(data){
        //判断添加返回结果
        //alert(data)
        if(data == true){
            alert("请注意接收验证码!!!");
            location.href = "emailLogin.jsp";
        }else{
            alert("验证码发送失败!!!");
        }
    });
});

1、删除

a标签是由第一次跳转到animeList.jsp页面时,Ajax动态加载的;

href=’javascript:void(0);’ 取消a标签的href属性;

/*
href='javascript:void;'  取消href跳转,使用Ajax提交请求
animeId = '"+this.id+"'  添加一个animed参数,删除时方便获取
class='delAnime'        添加类名,方便动态click绑定事件
*/
+"删除"

$(“table tbody”).on(“click”,”.delAnime”,function(){ }); 给动态加载元素绑定事件

获取动漫id通过Ajax请求删除数据,并 通过当前元素的父元素,删除该元素;(因为异步删除的数据,没有再查询一次,所以需要,手动删除动漫数据);

//点击删除,删除对应的动漫
$("table tbody").on("click",".delAnime",function(){
    //alert($(this).attr("animeId"));

    //确定删除提示
    if(!confirm("确定要删除这条数据吗?")){
        return false;
    }

    //确定要删除的超链接对象
    var $delAnime = $(this);

    //获取删除动漫编号
    var animeId = $delAnime.attr("animeId");
    //alert("删除的编号:" + animeId);

    //使用Ajax,实现异步删除
    $.getJSON("animes?mothed=delAnime",{"id":animeId},function(data){
        //判断删除成功
        if(data){
            //后台删除成功后,当前页面动漫元素数据页删除
            $delAnime.parents("tr").remove();
            alert("删除成功");
        }else{
            alert("删除失败");
        }
    })
});

onClick(函数名,或者是js代码片段)用于绑定 事件,告诉浏览器在鼠标点击时候要做什么;

//场景1:
点击
点击触发函数
//场景2:直接再onClick="" 中写函数内容
删除
  • 注意不可以给Ajax动态添加的元素绑定click()方法;
  • 一般click(function() {})就够用了,注意Ajax加载的元素的时候就好;
//确认按钮使用的场景
$("#save").click(function () {
    if(confirm("是否确认修改信息?")){
        $("#userForm").submit();
    }
});
  • $(“父级元素”).on(“事件”,”子级元素,一般写类名”,function( ){} );
//点击删除,删除对应的动漫
$("table tbody").on("click",".delAnime",function(){
    //使用Ajax,实现异步删除
    $.getJSON("animes?mothed=delAnime",{"id":animeId},function(data){
        //判断删除成功
        if(data){
            //后台删除成功后,当前页面动漫元素数据页删除
            $delAnime.parents("tr").remove();
            alert("删除成功");
        }else{
            alert("删除失败");
        }
    })
});

2、修改

将要修改的数据的 id,带过去,方便修改页面 获取,需要修改的数据

/*
href='modAnime.jsp?id="+this.id+"&cid="+this.cid+"'
跳转到到修改页面
参数id 是动漫的id,通过id查询对应动漫的数据,并数据回显,方便修改
cid 是动漫的的类型,方便选定动漫类型
*/

+ "修改  "

由于是使用 Ajax直接跳转到修改动漫的页面, 无法携带要修改的动漫id,于是就取巧的, 将参数放在导航栏rul中,然后获取url, 使用字符操作,获取到携带 在rul中的参数(动漫id);

// 从url中获取参数函数,使用正则表达式
function getUrlParam(name) {
    //构造一个含有目标参数的正则表达式对象
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    //匹配目标参数
    var r = window.location.search.substr(1).match(reg);
    //返回参数
    if (r != null) {
        return unescape(r[2]);
    }
    return null;
}

//返回按钮
$("input[type=button]").click(function(){
    history.back();
});

//根据id查询数据 并将数据显示再表单中
$.getJSON("animes?mothed=animeById",{"id":getUrlParam("id")} ,function(data){
    $("input[name=id]").val(data.id);
    $("input[name=aname]").val(data.name);
    $("input[name=author]").val(data.author);
    $("input[name=actor]").val(data.actor);
    $("input[name=produce]").val(data.produce);
    $("input[name=createDate]").val(data.create_date);
});
  • $(“form”).serialize(), 获取提交表单中的 参数
  • $(“form”).serialize():可直接获取到表单中的参数,并不一定需要submit()事件;
  • $(selector).serialize():serialize()方法通过 序列化表单值,创建标准的URL编码文本字符串, selector可以是input标签,文本框,或者是form元素本身
  • $(“form”).submit(function(){ }); form表单提交事件,点击submit 标签时触发;
  • $(“form”).submit(); 主动触发表单提交事件,经常用于JavaScript提交表单;
//异步请求修改动漫,并跳转会展示页面
//修改动漫详情
$("form").submit(function(){
    //发送Ajax异步请求,修改动漫
    $.getJSON("animes?mothed=modAnime",$("form").serialize() ,function(data){
        //判断添加返回结果
        if(data){
            alert("动漫修改成功");
            location.href="animeList.jsp";
        }else{
            alert("修改动漫失败!!");
        }
    });

    //去除表单提交事件
    return false;
});

3、添加

添加动漫,不需要携带参数,可直接跳转;


//点击添加,跳转到添加动漫页面
$("#addAnime").click(function(){
    location.href = "addAnime.jsp";
})

$(“form”).serialize() 获取表单的参数;

//$("form").serialize() 获取表单的参数,作为异步请求的参数
//新增动漫详情
$("form").submit(function(){
    //发送Ajax异步请求,新增动漫

    $.getJSON("animes?mothed=addAnime",$("form").serialize() ,function(data){
        //判断添加返回结果
        if(data){
            alert("添加动漫成功");
            location.href="animeList.jsp";

        }else{
            alert("添加动漫失败!!");
        }
    });

    //去除表单提交事件
    return false;
});

4、分页条件查询

一般会先做分页条件查询再做增删改;

步骤 : 查询所有的数据 -> 条件查询所有数据 -> 分页条件查询所有数据;(慢慢递进,不容易出错);

参数 说明 提交 aname 条件查询参数 表单提交 author 条件查询参数 表单提交 cid 条件查询参数 表单提交 pageNo 当前页面页码 获取tfoot的currPageNo,填入form表单隐藏的pageNo中 pageSize 页面大小 获取tfoot的currentPageSize,填入form表单隐藏的pageSize中 totalCount 数据总条数 请求数据中,根据条件查询参数先查询数据总条数

条件查询的参数一般都会在表单中,可以直接使用;(Ajax请求,不需要数据回显,如果是请求跳转,需要数据回显);

分页的参数我们为了提交表单请求的时候,可以获取到分页参数,就将其他需要的参数 隐藏在表单中(只要是查询需要的参数,都可以放这里,比较方便servlet的获取);


        名称:
        作者:
        分类:
        全部

分页参数一般会显示在非提交表单中, 需要获取放到表单中 对应的隐藏标签中


            首页 | 
            <<上一页 | 
            下一页>> | 
            尾页 | 
            共  条  
            每页 

             条 
            当前第  页 / 
            共  页

1、 $(“form”).serialize() 获取查询条件和分页参数

2、发起请求获取返回的data(pageSupport), 判断 动漫列表 (pageSupport.data)是否为null,如果 为null就隐藏tfoot,且显示暂无数据;

3、显示返回的分页参数;

4、上一页,下一页的 隐藏处理

​ 1). $(“#lastPage”).hide(); $(“#lastPage”) .show();

​ 2). $(“#lastPage”).css(“display”,”none”); $(“#lastPage”).css(“display”,”inline”);

5、动态拼接数据;

6、只要有数据展示,就说明需要展示tfoot;

//页面初始化加载,主动查询列表
showPageAnimeList();

//动态获取动漫数据,动态显示 条件分页查询
function showPageAnimeList(){
    $.getJSON("animes?mothed=animesUsePage",$("form").serialize() ,function(data){
        //alert(data);
        // 确定数据要动态显示的位置
        var $tbody = $("tbody");

        //如果没有数据,不能显示分页和提示暂无数据
        if(data.data == null || data.data == ""){
            //先清空再,显示提示信息
            $tbody.empty().append("暂无数据");
            //隐藏 tfoot
            $("tfoot").hide();
            //直接返回,因为没有数据,不需要拼接页面
            return;
        }

        // 显示分页数据
        $("#totalCount").text(data.titalCount);
        $("#currentPageSize").text(data.pageSize);
        $("#currPageNo").text(data.currPageNo);
        $("#totalPage").text(data.totalPage);

        //上一页  和  下一页处理
        if(data.currPageNo == 1){
            $("#lastPage")
                        //.hide();
                        .css("display","none");
        }else{
            $("#lastPage")
                        //.show();
                        .css("display","inline");
        }

        if(data.currPageNo == data.totalPage){
            $("#nextPage").hide();
        }else{
            $("#nextPage").show();
        }

        // 隔行变色
        var count = 1;

        //定义动态展示内容,如果不定义为空字符的话,一直拼接新数据
        var animeCountent = "";

        // 数据解析
        $(data.data).each(function(){
            // 定义颜色
            var bgColor = count % 2 == 0 ? "style='background-color:#ddd;'" : "";
            animeCountent +=
""
                + "" + this.id + ""
                + "" + this.cname + ""
                + "" + this.name + ""
                + "" + this.author + ""
                + "" + this.actor + ""
                + "" + this.produce + ""
                + "" + this.create_date + ""
                + "修改  "
                +"删除"
                + "";

            count++;
        });
        $tbody.empty().append(animeCountent);
        //有数据就要展示tfoot
        $("tfoot").show();
    });
}

//点击搜索按钮,根据条件筛选数据
$("#searchAnimes").click(function(){
    showPageAnimeList();
});

改变form表单中pageNo的值,并调用 分页条件查询函数 showPageAnimeList();

改变form表单中pageNo的值方法:

//分页跳转
//首页
$("tfoot a:eq(0)").click(function(){
    //通过id选择input标签再赋值
    //$("#pageNo").val(1);
    //直接改表单指定name属性值的input标签赋值
    document.forms[0].pageNo.value = 1;
    showPageAnimeList();
    return false;
});

// 上一页
$("tfoot a:eq(1)").click(function(){
    $("#pageNo").val(parseInt($("#currPageNo").text()) - 1);
    showPageAnimeList();
    return false;
});

// 下一页
$("tfoot a:eq(2)").click(function(){
    $("#pageNo").val(parseInt($("#currPageNo").text()) + 1);
    showPageAnimeList();
    return false;
});

// 尾页
$("tfoot a:eq(3)").click(function(){
    $("#pageNo").val(parseInt($("#totalPage").text()));
    showPageAnimeList();
    return false;
});

T 自定义泛型表示 数据的类型,一般是数据列表 List

我感觉比较好的设计话可以是条件分页查询所有参数全部放里面 (只是想法,这里没有用):

  • T:为自定义泛型的数据(一般为List);
  • List :为条件查询的参数,做回显数据 (考虑到类型不确定和数量不确定,也可以是动态数组,先用集合添加,然后toArray转为数组);
  • 数据量,当前页,和总页数
public class PageSupport {
    //当前页,显示页码
    private int currPageNo = 1;

    //页面容量
    private int pageSize = 3;

    //总条数(带条件查询的总条数)
    private int totalCount;

    //总页数(根据总条数和页面容量)
    private int totalPage;

    //分页条件查询的数据
    private T data;
    ......

    public void setTotalCount(int totalCount) {
        //当存在总条数,确定总页数
        this.totalCount = totalCount;
        //计算总页数
        this.totalPage = this.totalCount%this.pageSize == 0 ?
                this.totalCount/this.pageSize :
                    this.totalCount/this.pageSize + 1;
    }
    ......

}
  • 通过条件,查询数据 总条数
  • 实例化pageSupport
  • 当前页的 特殊页码处理
  • 查询出数据,放进pageSupport 的 data 中
  • 返回pageSupport对象(包含 分页信息,和 条件查询后分页的数据)
//查询所有的动漫列表 带分页
protected void animesUsePage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //获取查询条件
    String searchAname = req.getParameter("aname");
    String searauThor = req.getParameter("author");
    String searCid = req.getParameter("cid");

    //获取显示的当前页码
    Integer pageNo = Integer.parseInt( req.getParameter("pageNo") == null ? "1" : req.getParameter("pageNo") );
    Integer pageSize = Integer.parseInt( req.getParameter("pageSize") == null ? "3" : req.getParameter("pageSize") );

    //根据条件查询总数
    int totalCount = animeService.animeCount(searchAname,searauThor,searCid);

    //创建分页对象
    PageSupport> pageSupport = new PageSupport>();
    pageSupport.setPageSize(pageSize); //先放pageSize
    pageSupport.setTitalCount(totalCount); //再放 totalCount

    System.out.println("pageNo==>"+pageNo);

    //页码特殊处理(最好放在pageSupport中处理,这里每次要写,而且容易忘记)
    int currPageNo = pageNo;
    //如果当前页码小于1,或数据总量等于0
    if(currPageNo < 1 || pageSupport.getTitalCount() == 0) {
        currPageNo = 1;
    }else if(currPageNo > pageSupport.getTotalPage()){
        //如果当前页码大于总页数
        currPageNo = pageSupport.getTotalPage();
    }

    System.out.println("pageNo======>"+pageNo);
    //设置当前页码
    pageSupport.setCurrPageNo(currPageNo);

    //设置分页数据  分页条件查询的数据
    pageSupport.setData(animeService.animeListPage(searchAname, searauThor, searCid, pageNo, pageSize));

    //响应数据
    System.out.println("animesUsePage==》" + JSON.toJSONStringWithDateFormat(pageSupport,"yyyy-MM-dd"));
    resp.getWriter().write(JSON.toJSONStringWithDateFormat(pageSupport,"yyyy-MM-dd"));

}

阿里巴巴的数据转为json的jar包: fastjson-1.2.13.jar

JSON.toJSONString(pageSupport)将数据转为JSON类型

JSON.toJSONStringWithDateFormat(pageSupport,”yyyy-MM-dd”):将数据 转为JSON类型,并 指定其中日期的格式;

//条件查询的数据总量
public int animeCount(String aname, String author, String cid);

//条件查询后分页 后的数据集合 (条件用List动态拼接)
public List selectAnimeListPage(String aname, String author, String cid, Integer pageNo, Integer pageSize);

//增加分页SQL语句
executeSql += " order by a.id desc limit ?,?";

paramList.add((pageNo - 1) * pageSize);
paramList.add(pageSize);
//根据条件查询 数据总数
@Override
public int animeCount(String aname, String author, String cid) {
    //查询动漫详情的SQL语句
    String executeSql = "select count(1) from animes a where 1=1 ";

    //参数集合
    List paramList = new ArrayList();

    //根据不同的查询条件,拼接SQL语句和参数
    //条件中有动漫名
    if(null != aname && !"".equals(aname)) {
        //模糊匹配
        executeSql += " and a.name like concat('%',?,'%')";

        paramList.add(aname);
    }

    //条件中有作者
    if(null != author && !"".equals(author)) {
        //标记关键字 author
        String markAuthor = "replace(author,'"+author +"',\""+author+"\") as 'a.author'";

        //标记
        executeSql  = executeSql.replace("a.author", markAuthor);

        //模糊匹配
        executeSql += " and a.author like concat('%',?,'%')";

        paramList.add(author);
    }

    //条件中有类型
    if(null != cid && !"0".equals(cid)) {
        executeSql += " and a.cid = ?";
        paramList.add(cid);
    }

    //定义返回动漫总数
    int totalCount = 0;

    try {
        // 执行查询
        this.executeSelect(executeSql, paramList.toArray());

        // 解析查询结果
        if(rs.next()) {
            totalCount = rs.getInt(1);
        }

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        //关闭资源
        this.releaseResource(conn, pstmt, rs);
    }

    //返回动漫总数量
    return totalCount;
}
//查询  动态添加查询条件,并分页后  的数据集合
@Override
public List selectAnimeListPage(String aname, String author, String cid, Integer pageNo, Integer pageSize) {
    //查询动漫详情的SQL语句
    String executeSql = "select a.id, a.cid, a.name, a.author, a.actor, a.produce, a.create_date, c.name from animes a, category c where a.cid = c.id ";

    //动态参数,推荐使用
    List paramList = new ArrayList();

    //根据不同的查询条件,拼接SQL语句和参数
    //条件中有动漫名
    if(null != aname && !"".equals(aname)) {
        //模糊匹配
        executeSql += " and a.name like concat('%',?,'%')";

        //System.out.println("模糊匹配且标记后的SQL=>"+executeSql);

        paramList.add(aname);
    }

    //条件中有作者
    if(null != author && !"".equals(author)) {
        //标记关键字 author
        String markAuthor = "replace(author,'"+author +"',\""+author+"\") as 'a.author'";

        //标记
        executeSql  = executeSql.replace("a.author", markAuthor);

        //模糊匹配
        executeSql += " and a.author like concat('%',?,'%')";

        System.out.println("模糊匹配且标记后的SQL=>"+executeSql);

        paramList.add(author);
    }

    //条件中有类型
    if(null != cid && !"0".equals(cid)) {
        executeSql += " and a.cid = ?";
        paramList.add(cid);
    }

    //增加分页SQL语句
    executeSql += " order by a.id desc limit ?,?";

    paramList.add((pageNo - 1) * pageSize);
    paramList.add(pageSize);

    //定义返回动漫列表的数据集合
    List animes = new ArrayList();

    try {
        // 执行查询
        this.executeSelect(executeSql, paramList.toArray());

        // 解析查询结果
        while(rs.next()){
            // 每条数据,创建一个动漫对象,存储数据
            Anime anime = new Anime();
            anime.setId(rs.getInt(1));
            anime.setCid(rs.getInt(2));

            //对动漫name结构处理
            if(null != aname && !"".equals(aname)) {
                //标记name
                String markname = rs.getString(3).replace(aname, ""+aname+"");
                anime.setName(markname);
            }else {
                anime.setName(rs.getString(3));
            }

            anime.setAuthor(rs.getString(4));
            anime.setActor(rs.getString(5));
            anime.setProduce(rs.getString(6));
            anime.setCreate_date(rs.getDate(7));
            anime.setCname(rs.getString(8));

            // 将每条动漫数据对象放入集合
            animes.add(anime);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        //关闭资源
        this.releaseResource(conn, pstmt, rs);
    }

    //返回动漫集合
    return animes;
}

5、动态修改pageSize

tfoot中 可以选择currentPageSize,动态改变后,需要填写到form表单中的 pageSize;

每页 

 条 
//pageSize 请求获取一个JSONString类型的PageSize对象集合
//[{"size":3},{"size":5},{"size":10}]
//获取PageSize,动态展示
$.getJSON("pageSize",function(data){
    //alert(data);
    //定位currentPageSize的下拉元素
    var $currentPageSize = $("#currentPageSize");

    //遍历返回的分类集合json集合数,动态加载分类选项
    $(data).each(function(){
        //alert(this.size);
        $currentPageSize.append(""+this.size+"");
    });

});
  • 触发事件:
  • select标签的选项切换 触发事件change()
  • 获取切换的值
  • $(this).children(‘option:selected’).val(); 获取被 选中的选项的值;
  • 修改表单隐藏的pageSize的value值;
  • 这一类 修改下面的可选值时,需要 将值设置到表单中
  • 将值放到表单中两种方式:(跟页面跳转一样)
  • 1、 通过id选择input元素geivalue属性赋值:$(“#pageSize”).val(currentPageSize);
  • 2、通过直接 给表单指定name属性值的input标签赋值: ​ document.forms[0].pageSize.value = currentPageSize; ​ pageSize 为 input标签的name属性值;
 //修改pageSize
//select标签的change()事件, 切换选项时触发
$("#currentPageSize").change(function(){
    //获取修改后的 currentPageSize
    var currentPageSize = $(this).children('option:selected').val();
    //alert(currentPageSize);
    //修改提交表单的pageSize
    //$("#pageSize").val(currentPageSize);
    //通过document.forms[0].pageSize.value  pageSize 为 input标签的name属性值
    document.forms[0].pageSize.value =  currentPageSize;
    //修改页面大小后,再主动查询一次动漫数据
    showPageAnimeList();
});

6、单例模式

模式 特点 懒汉模式 类加载时,

,而是当内存中需要且没有该类的实例时,才会创建(存在线程不安全)

饿汉模式 类加载时,

,放入内存中,需要使用的时候,直接返回,不存在线程不安全

数据库配置信息读取类(使用单例模式,保证 数据读取配置程序运行过程中,只会读取一次 );

//数据库配置信息读取类(使用单例模式,保证数据读取配置程序运行过程中,只会读取一次 jdbc.properties)
public class JdbcConfig {
    //创建 Properties 对象,必须全局,私有()只有内部才可以使用
    Properties properties;

    //懒汉:类加载时,不会主动创建对象,而是当内存中没有该类的实例时,才会创建
    //静态:下面要提供一个获取实例的静态方法,getInstance
    //private static JdbcConfig JdbcConfig;

    //饿汉:类加载时,直接创建实例对象,放入内存中,需要使用的时候,直接返回,不存在线程不安全
    private static JdbcConfig JdbcConfig = new JdbcConfig();

    //私有构造方法,保证处理在当前类中,其他任何地方斗不可以创建实例
    private JdbcConfig() {
        try {
            //自动实例化  properties
            properties = new Properties();

            // 使用反射机制,读取外部配置文件
            InputStream inputStream = JdbcConfig.class.getClassLoader().getResourceAsStream("jdbc.properties");

            // 加载输入流对象,获取配置文件内容
            properties.load(inputStream);

            System.out.println("------创建JdbcConfig实例成功-------");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 创建Properties属性对象
    }

    /*
     * 单例模式 :在程序运行期间,保证当前类的实例只有一个,而且是唯一的一个
     * 懒汉    双重校验
     */
//  public static JdbcConfig getInstance() {
//
//      //判断内存中是否存在JdbcConfig 对象实例,如果不存在就创建实例
//      if(null == JdbcConfig) {
//          //懒汉,不是线程安全的,可以使用双重校验检查,实现多线程,确保单例
//          //加同步锁,如果有一个线程获取到同步锁,其他线程等待
//          synchronized (JdbcConfig.class) {
//              //再判断一次,内存是否存在JdbcConfig实例
//              if(null == JdbcConfig) {
//                  //创建一个读取数据库配置实例对象,放入内存,创建对象时就自动读取数据配置信息
//                  JdbcConfig = new JdbcConfig();
//              }
//          }
//      }
//
//      return JdbcConfig;
//  }

    //饿汉
    public static JdbcConfig getInstance() {
        return JdbcConfig;
    }

    //提供一个公共的读取配置文件的方法
    public String getPropertyByKey(String key) {
        return properties.getProperty(key);
    }

}

其他不变,只是获取配置信息的方式改变了;

直接 使用JdbcConfig获取配置信息

public class BaseDao {

    // 数据库操作对象
    protected Connection conn = null;
    protected PreparedStatement pstmt = null;
    protected ResultSet rs = null;

    /**
     * 获取数据库连接,返回获取连接成功还是失败
     */
    public boolean getConnection(){
        try {

            //非单例模式,会损耗性能
//          // 创建Properties属性对象
//          Properties properties = new Properties();
//
//          // 使用反射机制,读取外部配置文件
//          InputStream inputStream = BaseDao.class.getClassLoader().getResourceAsStream("jdbc.properties");
//
//          // 加载输入流对象,获取配置文件内容
//          properties.load(inputStream);
//
//          // 读取数据库连接信息
//          String driverClass = properties.getProperty("driverClass");
//          String jdbcUrl = properties.getProperty("jdbcUrl");
//          String user = properties.getProperty("user");
//          String password = properties.getProperty("password");

            String driverClass = JdbcConfig.getInstance().getPropertyByKey("driverClass");
            String jdbcUrl =  JdbcConfig.getInstance().getPropertyByKey("jdbcUrl");
            String user =  JdbcConfig.getInstance().getPropertyByKey("user");
            String password =  JdbcConfig.getInstance().getPropertyByKey("password");

            // 加载驱动
            Class.forName(driverClass);

            // 获取数据库连接对象
            conn = DriverManager.getConnection(jdbcUrl, user, password);
        } catch (Exception e) {
            e.printStackTrace();
            // 获取连接失败
            return false;
        }

        // 获取连接成功
        return true;
    }

    /**
     * 增删改的通用方法:只需要提供执行的SQL语句和SQL语句需要的参数,使用预处理对象
     */
    public int executeUpdate(String executeSql, Object ... params){

        // 定义SQL语句执行的影响行数
        int row = 0;

        // 获取数据库连接,如果获取失败,不执行操作
        if(getConnection()){
            // 公共执行增删改的处理代码
            try {

                // 创建预处理操作对象
                pstmt = conn.prepareStatement(executeSql);

                // 实现动态传参,注意: 传入的预编译SQL的?和传入的参数个数和顺序要一致,即:要保证一一对应
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }

                // 执行增删改操作,并获取影响行数
                row = pstmt.executeUpdate();

                System.out.println("BaseDao增删改的SQL=>"+pstmt);

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                releaseResource(conn, pstmt, null);
            }
        }

        // 返回影响行数
        return row;

    }

    /**
     * 查询的通用方法:只需要提供执行的SQL语句和SQL语句需要的参数,使用预处理对象
     */
    public void executeSelect(String executeSql, Object ... params){

        // 获取数据库连接,如果获取成功,执行查询,否则不执行
        if(getConnection()){
            // 公共执行查询的处理代码
            try {
                // 创建预处理操作对象
                pstmt = conn.prepareStatement(executeSql);

                // 实现动态传参,注意: 传入的预编译SQL的?和传入的参数个数和顺序要一致,即:要保证一一对应
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }

                // 执行查询操作,并获取结果集
                rs = pstmt.executeQuery();

                System.out.println("BaseDao查询的SQL=>"+pstmt);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 不释放资源,因为rs要返回,关闭后,直接外层不可以使用
            }
        }
    }

    /**
     * 释放数据库操作对象资源
     */
    public void releaseResource(Connection conn, Statement stmt, ResultSet rs){
        try {
            // 手动释放
            if (null != rs) {
                rs.close();
            }

            if (null != stmt) {
                stmt.close();
            }

            if (null != conn) {
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

7、注意点

需要对 dopost方法进行加锁(synchronized)操作,让这个方法,一次只能有一个请求;

@Override
protected synchronized void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    //根据请求携带的方法参数名参数,调用不同业务的处理方法

    String mothedName = req.getParameter("method") == null ? "test" : req.getParameter("method");

    //利用反射,根据方法名调用指定方法
    try {
        Method method = getClass().getDeclaredMethod(mothedName,HttpServletRequest.class,HttpServletResponse.class);
        method.setAccessible(true);
        method.invoke(this, req,resp);
    } catch (Exception e) {
        e.printStackTrace();
    }

}

Original: https://www.cnblogs.com/xiaoqigui/p/16571253.html
Author: 化羽羽
Title: Javaweb08-Ajax项目-分页条件查询 + 增删改

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/615851/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 自己写的第一个java项目!

    项目名为”零钱通” 细节参考: 【零基础 快速学Java】韩顺平 零基础30天学会Java 基本版: OOP版: SmallChangeSysOOP: Sm…

    Java 2023年6月13日
    092
  • IO流(Properties的使用方法)

    Properties:属性集合类。是一个可以和IO流相结合使用的集合类。 Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。 /* 特殊功能…

    Java 2023年6月5日
    096
  • 删除链表结点类问题

    删除链表结点 NO1. 删除链表倒数第 k个结点 给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针。要求:空间复杂度 (O(1)),时间复杂度 (O(n)) 如果倒数第…

    Java 2023年6月15日
    0101
  • spring 是如何注入对象的和bean 创建过程分析

    文章目录: 首先需要知道一个大致实现 这个注入过程肯定是在 BeanPostProcessor 中实现的 spring 是在 beanFactory.getBean 进行 bean…

    Java 2023年6月5日
    090
  • 我是怎么入行做风控的

    引言 常听到周围有人说”风控”这个词,只知道这是一个神秘的部门,对他们做的事却一知半解,只知道这个风控部门对公司非常重要,任何活动和信息都最好向风控部门报备…

    Java 2023年6月15日
    0104
  • 机器学习基础知识

    ROC曲线含义 DL 卷积运算:参考吴恩达课程中的边缘检测,滑动窗口,乘法加法 运算步骤:滑动窗口,逐个相乘再相加 运算结果:新的矩阵,(s-f)/2 + 1 padding: 在…

    Java 2023年6月7日
    084
  • 服务创建&删除

    创建服务.bat @echo.服务启动…… @echo off @sc create BestoneProductEditSvc binPath= "D:\win…

    Java 2023年6月5日
    085
  • Spring入门案例-基于XML管理bean

    1. 入门案例–hello spring 创建Maven Module 在pom.xml中引入依赖 org.springframework spring-context…

    Java 2023年6月14日
    0104
  • Nginx反代服务器进阶学习最佳配置实践指南

    转载自:https://www.bilibili.com/read/cv16150010?spm_id_from=333.999.0.0 0x00 编译实践 描述:在企业线上生产环…

    Java 2023年5月30日
    073
  • 180_RabbitMQ高级-消息确认机制的配置

    消息确认机制的配置 消息确认机制的配置 :::infoNONE值是禁用发布确认模式,是默认值CORRELATED值是发布消息成功到交换器后会触发回调方法,如1示例SIMPLE值经测…

    Java 2023年6月7日
    097
  • 2022-8-24 js

    JavaScript脚本语言,解释性 &#x4E3B;&#x8981;&#x7ED9;HTML&#x7F51;&#x9875;&#x…

    Java 2023年6月13日
    059
  • 一万了解 Gateway 知识点

    1.什么是 网关 API 网关是一个搭建在客户端和微服务之间的服务,我们可以在 API 网关中处理一些非业务功能的逻辑,例如权限验证、监控、缓存、请求路由等。 网关的核心作用就是路…

    Java 2023年6月5日
    098
  • TypeScript(6)函数

    函数 函数是 JavaScript 应用程序的基础,它帮助你实现抽象层,模拟类,信息隐藏和模块。在 TypeScript 里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义…

    Java 2023年6月9日
    085
  • nginx 配置的server_name参数(转)

    转自:http://www.sklinux.com/373 nginx中的server_name指令主要用于配置基于名称虚拟主机. 一 匹配顺序,server_name指令在接到请…

    Java 2023年5月30日
    0102
  • Centos7 搭建 Flume 搭配 Hadoop 采集 Nginx 日志

    本文目的是根据前文的博文,打造一个Hadoop、Sprak的服务器闭环。也是经验归纳。 版本信息 CentOS: Linux localhost.localdomain 3.10….

    Java 2023年5月30日
    078
  • 深入学习SpringBoot

    快速上手SpringBoot 1.1 SpringBoot入门程序开发 SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来 简化Spring应用的 初始搭建…

    Java 2023年6月6日
    069
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球