1、登录
1.1 登录form表单
<form action=\"<%=request.getContextPath()%>/loginAnime\" method=\"get\">
<table border=\"1px\" align=\"center\" width=\"40%\" cellspacing=\"0\">
<tr style=\"hight:60px; font-size:16px;background-color:#B9DEE0\">
<th colspan=\"2\"> 欢迎登录课工场KH96动漫管理系统 </th>
</tr>
<tr>
<td>用户名:</td>
<td>
<input type=\"text\" name=\"uname\" id=\"uname\" placeholder=\"请输入\"用户名> </input>
<span id = \"showMsg\" style=\"text-align:center;\"></span>
</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 登录
<script type=\"text/javascript\">
$(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;
});
});
</script>
1.3 Ajax接收前端返回boolean类型数据
1.3.1 一般AJax请求,$.get,$.post 请求 接收的是 String 类型
//判断场景
$(\"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 href=\'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 class=\"deleteUser\" href=\"/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 href=\'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的获取);
<!--
条件查询的参数:aname,author,cid
分页的参数:pageNo,pageSize
(分页必须参数,还有数据的总量 totalCount )
-->
<form action=\"#\">
<p style=\"text-align: center\">
名称:<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\" style=\"height: 40px; text-align: center\">
<input type=\"button\" value=\"添加\" id=\"addAnime\"/>
<a href=\"#\">首页</a> |
<a href=\"#\" id=\"lastPage\"><<上一页</a> |
<a href=\"#\" id=\"nextPage\">下一页>></a> |
<a href=\"#\">尾页</a> |
共 <span id=\"totalCount\"></span> 条
每页
<!-- <span id = \"currentPageSize\"></span> -->
<select name=\"currentPageSize\" id=\"currentPageSize\">
</select>
条
当前第 <span id=\"currPageNo\"></span> 页 /
共 <span id=\"totalPage\"></span> 页
</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 href=\'modAnime.jsp?id=\"+this.id+\"&cid=\"+this.cid+\"\' >修改</a> \"
+\"<a href=\'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
-
数据量,当前页,和总页数
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 +\"\',\\\"<span style=\'color:red\'>\"+author+\"</span>\\\") 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 +\"\',\\\"<span style=\'color:red\'>\"+author+\"</span>\\\") 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, \"<span style=\'color:red\'>\"+aname+\"</span>\");
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;
每页
<!-- <span id = \"currentPageSize\"></span> -->
<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();
}
}
}
7、注意点
7.1当一个页面多个Ajax请求,可能会数据错乱
需要对 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();
}
}
来源:https://www.cnblogs.com/xiaoqigui/p/16571253.html
本站部分图文来源于网络,如有侵权请联系删除。