系统首页新闻中心部分使用 Ajax 技术按主题动态显示新闻功能,根据条件加载全
部主题或某个主题下得新闻,并使用 Ajax 技术实现分页显示。使用 Ajax 技术加载添
加主题页面,并以 Ajax 方式实现添加主题功能,以及用 Ajax 技术实现主题的修改和
删除。
8.2.1 以 Ajax 方式根据主题动态加载新闻
1. 需求介绍
访问系统首页,以 Ajax 方式加载页面 "新闻中心" 部分的新闻列表,默认加载所有
主题下得新闻,按创建时间降序排列,并实现分页,如图 8.1 所示。
单击某个主题的超链接时,以 Ajax 方式加载该主题下得新闻,按创建时间降序排列,
并实现分页。
2.实现思路
(1)实现数据层访问
需求中存在两个分页查询的要求:对所有主题下的新闻进行分页查询,以及对某个
主题下得新闻进行分页查询。实际上,这两个查询对于 SQL 语句而言,仅相差一个主
题 id 的查询。实际上,这两个查询对于 SQL 语句而言,仅相差一个主题 id 的查询条件,
故而考虑将两个查询进行整合设计。
图 8.1 分页展示全部类别的新闻
修改 NewsDao 接口中分页查询相关方法的设计,加入主题 id 参数。
public interface NewsDao {
……// 省略其他方法
//获得新闻总数
public int getTotalCount(Integer id) throws SQLException;
//分页获得新闻
public List<News> getPageNewsList(Integer tid,
int pageNo,int pageSize) throws SQLException;
}
在其实现类 NewsDaoImpl 中根据传入参数 tid 是否有效,动态拼装 SQL 语句和查
询条件。
public class NewsDaoImpl extends BaseDao implements NewsDao{
public NewsDaoImpl(Connection conn){
super(conn);
}
……//省略其他方法
//获得新闻的数量
public int getTotalCount(Integer tid) throws SQLEception{
ResultSet rs = null:
List<Object> params = new ArrayList <Object>();
String sql = "SELECT COUNT('nid') FROM 'news'";
if(tid!= null){
sql += "WHERE 'ntid' = ?";
params.add(tid);
}
int count = -1;
try {
rs = this.executeQuery(sql,params.toArrary()) ;
rs.next();
count = rs.getInt(1);
}……省略异常处理和资源释放代码
return count;
}
//分页获得新闻
public List<News> getPageNewsList(Integer tid,
int pageNo,int pageSize) throws SQLException{
List<News> list = new ArrayList <News>();
ResultSet rs = null;
List<Object> params = new ArrayList <Object>();
String sql = "SELECT'nid','ntid','ntitle','nauthor',"
+"'ncreateDate','nsummary','tname' FROM 'NEWS',"
+"'TOPIC''WHERE''NEWS'.'NTID' = 'TOPIC'.'tid'";
if{tid! = null){
sql +="AND 'NEWS'.'ntid' = ?";
params.add(tid);
}
sql += " ORDER BY 'ncreateDate' DESC LIMIT ?,?";
params.add((pageNo - 1)* pageSize);
params.add(pageSize);
try{
rs = this.executeQuery(sql,params.toArray());
……// 省略封装数据过程
}……//省略异常处理和资源释放代码
return list;
}
}
(2) 实现业务层
业务层接口 NewsService 及其实现类 NewsServiceImpl 也相应进行调整设计,对分
也方法增加传入参数主题 id。
修改 NewsService 接口中分页相关方法的设计,加入主题 id 参数。
public interface NewsService{
……//省略其他方法
//分页获取新闻
public void findPageNews(Integer tid,Page pageObj)
throws SQLException;
}
在其实现类 NewsServiceImpl 中调用 Dao 相关方法时传入 tid 即可。
public class NewsServiceImpl implements NewsService{
……//省略部分方法
//分页获取新闻
public void findPageNews(Inter tid,Page pageObj)
throws SQLException{
Connection conn = null;
try{
conn = DatebaseUtil.getConnection();
NewsDao newsDao = new NewsDaoImpl(conn);
……//省略部分代码
List<News> newsList = newsDao.getPageNewsList(tid,
pageObj.getCurrPageNo(),
pageObj.getPageSize());
……//省略部分代码
}……// 省略异常处理和资源释放
}
}
}
(3)编写 Servlet
将原有的首页初始化公告拆解成两部分:按传统初始化最新消息和主题列表(如
图 8.2 所示)及采用 Ajax 方法分页加载新闻列表(如图 8.1 所示)。
图8.2 初始化最新消息和主题列表
按传统方式初始化最新消息和主题列表的关键代码如下。
……//省略其他功能
else if("topicLatest".equals(opr)){//初始化首页侧边栏和主题列表
Map<Integer,Integer>topics = new HashMap<Integer,Integer>();
topics.put(1,5);
topics.put(2,5);
topics.Put(5,5);
List<List<News>> latests = newsService
.findLatestNewsByTid(topics); //查询最新消息
List<Topic> list = topicService.findAllTopics(); //查询所有主题
request.setAttribute("list1",latests.get(0)); // 左侧国内新闻
request.setAttribute("list2",latests.get(1)); //左侧国际新闻
request.setAttribute("list3",latests.get(2)); // 左侧国际新闻
request.setAttribute("list",list); //所有的主题
request.getRequestDispatcher("/index.jsp").forward(request,response);
}……//省略其他功能
处理分页加载新闻列表的 Ajax 请求的关键代码如下。
else if("topicNews".equals(opr)){ //分页查询新闻
//获得主题id 和当前页数
String tid = request.getParameter("tid");
String pageIndex = request.getParameter("pageIndex");
……//省略部分代码
Page pageObj = new page();
……//省略部分代码
//调用业务方法查询
if(tid ==null||(tid = tid.trim()).length() ==0)
newsService.findPageNews(null,pageObj);
else
newsService.findPageNews(Integer.valueOf(tid),pageObj);
//使用 FastJSON 将 Page 对象序列化成 JSON 字符串
String newsJSON = JSON.toJSONStringWithDataFormat(pageObj,
"yyyy-MM-dd HH:mm:ss",
SerializerFeature.WriteMapNullValue);
//向客户端返回响应数据
out.print("[{\"tid\":\""+tid+"\"},"+newsJSON +"]");
}……//省略其他功能
注意
为了保证客户端分页条件的完整,响应数据时一个 JSON 数组,包括主题 id
和查询结果两部分内容。
(4) 调整 index.jsp 页面
将原有的获取和输出新闻列表的相关代码删除,仅保留列表的容器。
……//省略其他页面内容
<ul class = "classlist">
<!--分页显示新闻区域-->
</ul>
……//省略其他页面内容
为了和拆分后的 Servlet 功能及现实 Ajax 分页的要求相适应,主题列表的超链接在
输出时也需要进行相应调整。
<ul class = "class_data">
<c:forEach items = "${requestScope.list}" var="topic"
varStatus = "i">
<C:if test = "${i.count%11==1}"> <li id = 'class_month'></c:if>
<a href = "javascript:;" id = "${topic.tid}">
<b>${topic.tname}</b></a>
<c:if test = "${i.count%11 ==0}"></li></c:if>
<C:set var = "n" value = "${i.count}"/>
</c:forEach>
<c:if test = "${n%11!=0}"></li></c:if>
</ul>
单击主题超链接查询相关新闻的功能将在 JavaScript 脚本中使用 Ajax 方式实现,
增加 id 属性用于在单击事件中获取作为查询参数的主题 id.
(5) 编写 JavaScript 脚本
在以下代码块中分别编写相关 JavaScript 脚本。
jQuery.noConflict();//让渡 "$" 的使用权,其他脚本库可以使用 "$"
(function($){
$(document).ready(function(){
//其他脚本编写于此处
});
})(jQuery);
1. 编写发送 Ajax 分页请求的 getpagi() 方法并进行调用,以便在首页加载时初始
化新闻列表。
function getPagi(tid,pageIndex){ //发送 Ajax 请求实现分页
var data = "opr = topicNews"; //准备请求参数
if(tid)
data += "&tid=" +tid;
if(pageIndex && pageIndex>0)
data += "&pageIndex="+pageIndex;
$.getJSON("util/news",data,pagi); //发送 Ajax 请求
};
getPage();//首页加载时,初始化加载新闻列表
2.编写回调方法 pagi() 处理响应,主要完成两件事:展示本页数据和生成分页操作链接。
//获取显示新闻列表的首页中心区域
var $centerNewsList = $("#container.main.content.classlist");
function pagi(data){ //分页查询的回调函数
var tid = datas[0].tid == "null"?"";datas[0].tid;
var data = datas[1]; //获取分页相关数据
//1.展示本页新闻数据
$centerNewsList.html("");
if(data.newsList == null)
$centerNewsList.html(
"<h6>出现错误,请稍后再试或与管理员联系</h6">;
else{
var news;
for(var i = 0 ;i<data.newsList.length;){
$centerNewsList.append(
"<li><a href = "util/news?opr=readNew&nid="
+news.nid+"'>"+news.ntitle +"</a><span>"
+news.ncreatedate + "</span></li>");
if((++i)%5 == 0)
$centerNewsList.append("<li class='space'></li>");
}
}//本页新闻展示完毕
//2.生成分页操作链接并注册事件,单击时调用 getPagi()方法
var $operArea = $("<p align=\"center\">当前页数:["
+data.currPageNo = "/"
+data.totalPageCount = "] </p>")
.appendTo($centerNewsList);
if(data.currPageNo>1){
var $first = $("<a href=\"javascrit:;\">首页</a>").click(
function(){getPagi(tid,1);});
var $prev = $("<a href = \"javascript:;\">上一页</a>).click(
function(){getPagi(tid,(data.currPageNo-1));});
$operArea.append($first).append(" ").append($prev);
}
if(data.currPageNo<data.totalPageCount){
var $next = $("<a href=\"javascrit:;\">下一页</a>").click(
function(){getPagi(tid,(data.currPageNo+1))+1;});
var $last = $("<a href = \"javascript:;\">末页</a>).click(
function(){getPagi(tid,data.totalPageCount);});
$operArea.append($next).append(" ").append($last);
}
}//pagi() 方法结束
3. 为 index.jsp 页面中的主题超链添加单击事件,单击以 Ajax 方式实现按主题
分页查看新闻。
//从页面获取主题链接,并注册单击事件,使用 id 属性存储的主题 id 作为查询条件
$centerNewsList.prev("ul.class_data").find("a").each(function(){
var a = this;
a.onclick = function(){getPagi(a.id,1)};//id 属性值条件
});
6.部署运行并测试
了解具体实现请扫描二维码。
加载新闻源码。