1、登录
1.1 登录form表单
- <form action="<%=request.getContextPath()%>/loginAnime" method="get">
- <table border="1px" align="center" width="40%" cellspacing="0">
- <tr >
- <th colspan="2"> 欢迎登录课工场KH96动漫管理系统 </th>
- </tr>
- <tr>
- <td>用户名:</td>
- <td>
- <input type="text" name="uname" id="uname" placeholder="请输入"用户名> </input>
-
- </td>
- </tr>
- <tr>
- <td>用户密码:</td>
- <td>
- <input type="password" name="upwd" id="upwd" placeholder="请输入用户密码"> </input>
- </td>
- </tr>
- <tr>
- <td colspan="2" align="center">
- <input type="submit" value="立即登录" />
- <input type="reset" value="重新填写" />
- </td>
- </tr>
- </table>
- </form>
复制代码 欢迎登录课工场KH96动漫管理系统 用户名: 用户密码: 1.2 非空判断 和 Ajax 登录
- [/code][size=4]1.3 Ajax接收前端返回boolean类型数据[/size]
- [size=3]1.3.1 一般AJax请求,$.get,$.post 请求 接收的是 String 类型[/size]
- [code]//判断场景
- $("form").submit(function(){
- //发送请求
- $.post("<%=request.getContextPath()%>/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;
- });
复制代码 1.3.2 $.getJSON 接收的是boolean类型
- //场景
- $("#codeLogin").click(function () {
- $.getJSON("userServlet?method=sendEmail",null ,function(data){
- //判断添加返回结果
- //alert(data)
- if(data == true){
- alert("请注意接收验证码!!!");
- location.href = "emailLogin.jsp";
- }else{
- alert("验证码发送失败!!!");
- }
- });
- });
复制代码 1、删除
1.1 删除的a标签
a标签是由第一次跳转到animeList.jsp页面时,Ajax动态加载的;
href='javascript:void(0);' 取消a标签的href属性;- /*
- href='javascript:void;' 取消href跳转,使用Ajax提交请求
- animeId = '"+this.id+"' 添加一个animed参数,删除时方便获取
- class='delAnime' 添加类名,方便动态click绑定事件
- */
- +"<a target="_blank" href='https://www.cnblogs.com/javascript:void(0);' animeId = '"+this.id+"' class='delAnime' >删除</a></td>"
复制代码 1.2 Ajax 删除对应的动漫
$("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("删除失败");
- }
- })
- });
复制代码 1.3 onClick(), click(),on绑定 click 三者区别
1.3.1 onClick()绑定事件
onClick(函数名,或者是js代码片段)用于绑定事件,告诉浏览器在鼠标点击时候要做什么;- //场景1:
- <button id="" onClick("functionName()")>点击 </button>
- 点击触发函数
复制代码- //场景2:直接再onClick="" 中写函数内容
- <a target="_blank" href="https://www.cnblogs.com/userServlet?method=userDel&id=${user.id}" onClick="return confirm('是否确认删除${user.userName}用户')" >删除</a>
复制代码 1.3.2 $("selected")click(function(){}); 方法
- 注意:不可以给Ajax动态添加的元素,绑定click()方法;
- 一般click(function() {})就够用了,注意Ajax加载的元素的时候就好;
- //确认按钮使用的场景
- $("#save").click(function () {
- if(confirm("是否确认修改信息?")){
- $("#userForm").submit();
- }
- });
复制代码 1.3.3 $("table tbody").on("click",".delAnime",function(){})
- $("父级元素").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、修改
2.1 修改a标签
将要修改的数据的id,带过去,方便修改页面获取,需要修改的数据;- /*
- href='modAnime.jsp?id="+this.id+"&cid="+this.cid+"'
- 跳转到到修改页面
- 参数id 是动漫的id,通过id查询对应动漫的数据,并数据回显,方便修改
- cid 是动漫的的类型,方便选定动漫类型
- */
- + "<td><a target="_blank" href='https://www.cnblogs.com/modAnime.jsp?id="+this.id+"&cid="+this.cid+"' >修改</a> "
复制代码 2.2 Ajax 动漫数据回显
由于是使用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);
- });
复制代码 2.3 Ajax修改动漫信息
$("form").serialize(),获取提交表单中的参数;
$("form").serialize():可直接获取到表单中的参数,并不一定需要submit()事件;
$(selector).serialize():serialize()方法通过序列化表单值,创建标准的URL编码文本字符串,selector可以是input标签,文本框,或者是form元素本身;
$("form").submit(function(){ }); form表单提交事件,点击submit 标签时触发;
或 $("form").submit(); 主动触发表单提交事件;- //异步请求修改动漫,并跳转会展示页面
- //修改动漫详情
- $("form").submit(function(){
- //发送Ajax异步请求,修改动漫
- $.getJSON("animes?mothed=modAnime",$("form").serialize() ,function(data){
- //判断添加返回结果
- if(data){
- alert("动漫修改成功");
- location.href="animeList.jsp";
- }else{
- alert("修改动漫失败!!");
- }
- });
- //去除表单提交事件
- return false;
- });
复制代码 3、添加
3.1 跳转到添加页面
添加动漫,不需要携带参数,可直接跳转;- <input type="button" value="添加" id="addAnime"/>
- //点击添加,跳转到添加动漫页面
- $("#addAnime").click(function(){
- location.href = "addAnime.jsp";
- })
复制代码 3.2 Ajax 添加动漫详情
$("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、分页条件查询
一般会先做分页条件查询再做增删改;
步骤 : 查询所有的数据 -> 条件查询所有数据 ->分页条件查询所有数据;(慢慢递进,不容易出错);
4.1 参数
参数说明提交aname条件查询参数表单提交author条件查询参数表单提交cid条件查询参数表单提交pageNo当前页面页码获取tfoot的currPageNo,填入form表单隐藏的pageNo中pageSize页面大小获取tfoot的currentPageSize,填入form表单隐藏的pageSize中totalCount数据总条数请求数据中,根据条件查询参数先查询数据总条数条件查询的参数一般都会在表单中,可以直接使用;(Ajax请求,不需要数据回显,如果是请求跳转,需要数据回显);
分页的参数我们为了提交表单请求的时候,可以获取到分页参数,就将其他需要的参数隐藏在表单中(只要是查询需要的参数,都可以放这里,比较方便servlet的获取);- <form action="#">
- <p >
- 名称:<input type="text" name="aname" size="15"/>
- 作者:<input type="text" name="author" size="15"/>
- 分类:<select name="cid" id="cid">
- <option value="0">全部</option>
- </select>
- <input type="button" value = "搜索" id = "searchAnimes" />
- </p>
-
- <input type="hidden" name="pageNo" id="pageNo" value="1"/>
- <input type="hidden" name="pageSize" id="pageSize" value="3"/>
- </form>
复制代码 4.2 分页标签
分页参数会显示在非提交表单中,需要获取并放到表单中对应的隐藏标签中;- <tfoot>
- <tr>
- <td colspan="8" >
- <input type="button" value="添加" id="addAnime"/>
- <a target="_blank" href="https://www.cnblogs.com/#">首页</a> |
- <a target="_blank" href="https://www.cnblogs.com/#" id="lastPage"><<上一页</a> |
- <a target="_blank" href="https://www.cnblogs.com/#" id="nextPage">下一页>></a> |
- <a target="_blank" href="https://www.cnblogs.com/#">尾页</a> |
- 共 条
- 每页
-
- <select name="currentPageSize" id="currentPageSize">
- </select>
- 条
- 当前第 页 /
- 共 页
- </td>
- </tr>
- </tfoot>
复制代码 4.3 分页Ajax
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("<tr align='center'><td colspan='8'>暂无数据</td></tr>");
- //隐藏 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();
- }else{
- $("#lastPage").show();
- }
- 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 +=
- "<tr align='center' " + bgColor + ">"
- + "<td>" + this.id + "</td>"
- + "<td>" + this.cname + "</td>"
- + "<td>" + this.name + "</td>"
- + "<td>" + this.author + "</td>"
- + "<td>" + this.actor + "</td>"
- + "<td>" + this.produce + "</td>"
- + "<td>" + this.create_date + "</td>"
- + "<td><a target="_blank" href='https://www.cnblogs.com/modAnime.jsp?id="+this.id+"&cid="+this.cid+"' >修改</a> "
- +"<a target="_blank" href='https://www.cnblogs.com/javascript:void;' animeId = '"+this.id+"' class='delAnime' >删除</a></td>"
- + "</tr>";
- count++;
- });
- $tbody.empty().append(animeCountent);
- //有数据就要展示tfoot
- $("tfoot").show();
- });
- }
- //点击搜索按钮,根据条件筛选数据
- $("#searchAnimes").click(function(){
- showPageAnimeList();
- });
复制代码 4.4 页面跳转Ajax
改变form表单中pageNo的值,并调用分页条件查询函数 showPageAnimeList();
改变form表单中pageNo的值方法:
- 通过id选择input标签再赋值:$("#pageNo").val(1);
- 直接改表单指定name属性值的input标签赋值:document.forms[0].pageNo.value = 1;
- //分页跳转
- //首页
- $("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;
- });
复制代码 4.5 PageSupport
T 表示数据的类型,一般是数据列表List
我感觉比较好的设计话可以是条件分页查询所有参数全部放里面 (只是想法,这里没有用):
- T:为自定义泛型的数据(一般为List);
- List :为条件查询的参数,做回显数据 (考虑到类型不确定和数量不确定,也可以是动态数组,先用集合添加,然后toArray转为数组);
- 数据量,当前页,和总页数
- public class PageSupport<T> {
- //当前页,显示页码
- 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;
- }
- ......
- }
复制代码 4.6 Servlet 中的 方法
- 通过条件,查询数据总条数
- 实例化pageSupport
- 当前页的特殊页码处理
- 查询出数据,放进pageSupport 的 data 中
- 返回pageSupport对象(包含分页信息,和 条件查询后分页的数据)
- //查询所有的动漫列表 带分页
- protected void animesUsePage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //获取显示的当前页码
- Integer pageNo = Integer.parseInt( req.getParameter("pageNo") == null ? "1" : req.getParameter("pageNo") );
- Integer pageSize = Integer.parseInt( req.getParameter("pageSize") == null ? "3" : req.getParameter("pageSize") );
- //获取查询条件
- String searchAname = req.getParameter("aname");
- String searauThor = req.getParameter("author");
- String searCid = req.getParameter("cid");
- //根据条件查询总数
- int totalCount = animeService.animeCount(searchAname,searauThor,searCid);
- //创建分页对象
- PageSupport<List<Anime>> pageSupport = new PageSupport<List<Anime>>();
- pageSupport.setPageSize(pageSize);
- pageSupport.setTitalCount(totalCount);
- System.out.println("pageNo==>"+pageNo);
- //页码特殊处理
- 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类型,并指定其中日期的格式;
4.7 Dao 方法
- //条件查询的数据总量
- public int animeCount(String aname, String author, String cid);
- //条件查询后分页 后的数据集合
- public List<Anime> 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);
复制代码 4.7.1 条件查询数据总数
- //根据条件查询 数据总数
- @Override
- public int animeCount(String aname, String author, String cid) {
- //查询动漫详情的SQL语句
- String executeSql = "select count(1) from animes a where 1=1 ";
- //参数集合
- List<Object> paramList = new ArrayList<Object>();
- //根据不同的查询条件,拼接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;
- }
复制代码 4.7.2 条件分页查询数据
- //查询 动态添加查询条件,并分页后 的数据集合
- @Override
- public List<Anime> 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<Object> paramList = new ArrayList<Object>();
- //根据不同的查询条件,拼接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<Anime> animes = new ArrayList<Anime>();
- 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
5.1html
tfoot中可以选择的pageSize,currentPageSize,动态改变后,需要填写到form表单中的pageSize;- 每页
- <select name="currentPageSize" id="currentPageSize">
- </select>
- 条
复制代码 5.2 动态加载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("<option value='"+this.size+"' class='currentPageSize' >"+this.size+"</option>");
- });
- });
复制代码 5.3 改变psgeSize后触发事件
select标签的选项切换触发事件change(),
$(this).children('option:selected').val(); 获取被选中的选项的值;
修改表单隐藏的pageSize的value值;
将值放到表单中两种方式:(跟页面跳转一样)
1、通过id选择赋值:$("#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、单例模式
模式特点懒汉模式类加载时,不会主动创建对象,而是当内存中需要且没有该类的实例时,才会创建(存在线程不安全)双重校验饿汉模式类加载时,直接创建实例对象,放入内存中,需要使用的时候,直接返回,不存在线程不安全6.1 JdbcConfig
数据库配置信息读取类(使用单例模式,保证数据读取配置程序运行过程中,只会读取一次 );- //数据库配置信息读取类(使用单例模式,保证数据读取配置程序运行过程中,只会读取一次 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);
- }
- }
复制代码 6.2 改进后的Basedao
其他不变,只是获取配置信息的方式改变了;
直接使用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();
- }
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |