优化Servlet
目的
减少Servlet的数量,现在是一个功能一个Servlet,将其优化为一个模块一个Servlet,相当于在数据库中一张表对应一个Servlet,在Servlet中提供不同的方法,完成用户的请求。
Idea控制台中文乱码解决:-Dfile.encoding=gb2312
BaseServlet编写:
在BaseServlet中封装了序列化json等其他的方法
19.3、BaseServlet映射工具_凝霜月冷残-草木破白衣的博客-CSDN博客
UserServlet改写
该章节包含的servlet可以全部删除,需要修改html页面路径
19、Javaweb案例-登录功能_凝霜月冷残-草木破白衣的博客-CSDN博客
将之前的Servlet实现的功能,抽取到UserServlet中的不同方法中实现,并且将UserService创建抽取到成员变量位置
package cn.itcast.travel.web.servlet;
import cn.itcast.travel.domain.ResultInfo;
import cn.itcast.travel.domain.User;
import cn.itcast.travel.service.UserService;
import cn.itcast.travel.service.impl.UserServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet(name = "UserServlet", value = "/user/*")
public class UserServlet extends BaseServlet {
//声明UserService业务对象
private UserService service = new UserServiceImpl();
private ResultInfo info = new ResultInfo();
private User user = new User();
/**
* 注册功能
* @param request
* @param response
*/
public void regist(HttpServletRequest request, HttpServletResponse response) throws IOException {
//验证校验
String check = request.getParameter("check");
//从session中获取验证码
HttpSession session = request.getSession();
String checkcode_session = (String)session.getAttribute("CHECKCODE_SERVER");
session.removeAttribute("CHECKCODE_SERVER");
if (checkcode_session == null || !checkcode_session.equalsIgnoreCase(check)) {
info.setFlag(false);
info.setErrorMsg("验证码错误");
// jsonWrite(request,response,info);
writeValue(info, response);
return;
}
//注册用户
// 获取数据
Map<String, String[]> map = request.getParameterMap();
// 封装对象User
try {
BeanUtils.populate(user, map);
} catch (Exception e) {
e.printStackTrace();
}
// 调用service完成注册
boolean flag = service.regist(user);
if(flag){
info.setFlag(true);
}else {
info.setFlag(false);
info.setErrorMsg("注册失败,用户名已存在");
}
// //将info对象序列化为json
// jsonWrite(request,response,info);
writeValue(info, response);
}
/**
* 登录功能
* @param request
* @param response
*/
public void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
//1.获取用户名和密码数据
Map<String, String[]> map = request.getParameterMap();
//2.封装User对象
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
//3.调用Service查询
User u = service.login(user);
//4.判断用户对象是否为null
if(u==null) {
//用户名密码或错误
info.setResultInfo(info,false, null, "用户名密码或错误");
}
//5.判断用户是否激活
if (u!=null && "Y".equals(u.getStatus())){
info.setResultInfo(info,false, null, "您尚未激活,请激活");
}
//6.判断登录成功
if(u!=null && "Y".equals(u.getStatus())){
request.getSession().setAttribute("user",u);
info.setFlag(true);
}
//响应数据
writeValue(info, response);
}
/**
* 查询单个对象
* @param request
* @param response
*/
public void findOne(HttpServletRequest request, HttpServletResponse response) throws IOException {
//从session中获取登录用户
Object user = request.getSession().getAttribute("user");
//将user写回客户端
writeValue(user, response);
}
/**
* 退出功能
* @param request
* @param response
*/
public void exit(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.getSession().invalidate();
response.sendRedirect(request.getContextPath()+"/login.html");
}
/**
* 激活功能
* @param request
* @param response
*/
public void active(HttpServletRequest request, HttpServletResponse response) throws IOException {
//1.获取激活码
String code = request.getParameter("code");
if (code != null){
//2.调用service完成激活
boolean flag = service.active(code);
//3.判断标记
String msg = flag
?"激活成功,请<a href='"+request.getContextPath()+"/login.html'>登录</a>"
// ?"激活成功,请<a href='/travel/login.html'>登录</a>"
:"激活失败,请联系管理员";
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(msg);
}
}
}
页面路径改写
register.html
script代码
<script>
//constants
const username = "#username";
const password = "#password";
const notarize_password = "#notarizepassword";
const email = "#email";
const name="#name";
const telephone = "#telephone";
const birthday = "#birthday";
const check_code_info = "#check";
const errorMsg = "#errorMsg";
const registerForm = "#registerForm";
const register_submit = "#register_submit";
let reg_value = null;
//注册地址
//method
function border_null(value) {
return $(value).css("border", "") && true;
};
function border_red(value) {
return $(value).css("border", "1px solid red") && false;
};
function check(value,reg){
return reg.test($(value).val())
? border_null(value)
: border_red(value);
};
function checkLength(value,length){
return $(value).val().length==length
? border_null(value)
: border_red(value);
};
//logic
function checkUsername(){
reg_value = /^\w{8,20}$/;
return check(username, reg_value);
};
function checkPassword(){
reg_value = /^\w{8,20}$/;
return check(password, reg_value);
};
function checkNotarizePassword() {
return $(notarize_password).val() == $(password).val()
? border_null(notarize_password)
: border_red(notarize_password);
};
function checkEmail(){
reg_value = /^\w+@\w+\.\w+$/;
return check(email,reg_value);
};
function checkName(){
reg_value = /^[a-zA-Z0-9_\u4e00-\u9fa5]{3,50}$/;
return check(name,reg_value);
};
function checkTelePhone(){
reg_value = /^[1-9]{11}$/;
return check(telephone,reg_value);
};
function checkBirthDay(){
return checkLength(birthday, 10);
};
function checkCode(){
return checkLength(check_code_info, 4);
};
function ischeck(){
return checkUsername()
&& checkPassword()
&& checkNotarizePassword()
&& checkEmail()
&& checkName()
&& checkTelePhone()
&& checkBirthDay()
&& checkCode();
};
//execute
/*
表单校验:
1.用户名:单词字符,长度8到20位
2.密码:单词字符,长度8到20位
2.1确认密码
3.email:邮件格式
4.姓名:非空,大于3个字符
5.手机号:手机号格式
6.出生日期:非空
7.验证码:非空
*/
$(()=>{
$(registerForm).submit(function (){
if(ischeck()){
$(register_submit).css("background","#666666");
$.post('user/regist',$(this).serialize(),function(data){
$(register_submit).css("background","#ffc900");
data.flag
?location.href="register_ok.html"
:$(errorMsg).html(data.errorMsg).css("color", "red");
})
};
return false;
});
//失去焦点
$(username).blur(checkUsername);
$(password).blur(checkPassword);
$(notarize_password).blur(checkNotarizePassword);
$(email).blur(checkEmail);
$(name).blur(checkName);
$(telephone).blur(checkTelePhone);
$(birthday).blur(checkBirthDay);
$(check_code_info).blur(checkCode);
//清除错误消息
$(registerForm).click(()=>$(errorMsg).html('').css("color", ""));
});
</script>
login.html
<script>
const btn_sub = "#btn_sub";
const loginForm = "#loginForm";
const errorMsg = "#errorMsg";
$(()=>{
$(btn_sub).click(function(){
$.post("user/login",$(loginForm).serialize(),function (data){
data.flag
?location.href ="index.html"
:$(errorMsg).html(data.errorMsg);
})
})
})
</script>
header.html
UserServiceImpl发送邮件
分类数据展示
效果:
分析:
代码实现
后台代码
CategoryServlet
package cn.itcast.travel.web.servlet;
import cn.itcast.travel.domain.Category;
import cn.itcast.travel.service.CategoryService;
import cn.itcast.travel.service.impl.CategoryServiceImpl;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.List;
@WebServlet(name = "CategoryServlet", value = "/category/*")
public class CategoryServlet extends BaseServlet {
private CategoryService service = new CategoryServiceImpl();
//1.调用service查询所有
public void findAll(HttpServletRequest request, HttpServletResponse response) throws IOException {
List<Category> cs = service.findAll();
//2.序列化json返回
writeValue(cs,response);
}
}
CategoryService
通过Redis对分类数据进行缓存优化
分析发现,分类的数据在每一次页面加载后都会重新请求数据库来加载,对数据库的压力比较大,而且分类的数据不会经常产生变化,所有可以使用redis来缓存这个数据。
分析:
优化代码实现
期望数据中存储的顺序就是将来展示的顺序,使用redis的sortedset
package cn.itcast.travel.service.impl;
import cn.itcast.travel.dao.CategoryDao;
import cn.itcast.travel.dao.impl.CategoryDaoImpl;
import cn.itcast.travel.domain.Category;
import cn.itcast.travel.service.CategoryService;
import cn.itcast.travel.util.JedisUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.resps.Tuple;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class CategoryServiceImpl implements CategoryService {
CategoryDao categoryDao= new CategoryDaoImpl();
@Override
public List<Category> findAll() {
//1.从redis中查询
//1.1获取jedis客户端
Jedis jedis = JedisUtil.getJedis();
//1.2可使用sortedset排序查询,没有返回cid
// List<String> categorys = jedis.zrange("category", 0, -1);
//zrangeWithScores等价 zrange mysort 0 -1 withscores
//返回cid
List<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1);
System.out.println("redis获取来的数据"+categorys);
//1.3查询sortedset中的分数(cid)和值(cname)
List<Category> cs =null;
//2.判断查询的集合是否为空
if (categorys ==null || categorys.size() == 0) {
System.out.println("从数据库查询...");
//3.如果为空,需要从数据库查询,在将数据存入redis
//3.1 从数据库查询
cs = categoryDao.findAll();
//3.2 将集合数据存储到redis中的 category的key
for (Category i :cs){
//根据i.getCid()排序
//存储i.getCname()
jedis.zadd("category",i.getCid(),i.getCname());
}
}else{
System.out.println("从redis中查询");
//4.如果不为空,将set的数据存入list
cs = new ArrayList<Category>();
//没有返回cid
//for(String name:categorys){
//Category category = new Category();
//category.setCname(name);
//返回cid
for(Tuple tuple:categorys){
Category category = new Category();
category.setCid((int)tuple.getScore());
category.setCname(tuple.getElement());
cs.add(category);
}
}
return cs;
}
}
CategoryDao
package cn.itcast.travel.dao.impl;
import cn.itcast.travel.dao.CategoryDao;
import cn.itcast.travel.domain.Category;
import cn.itcast.travel.util.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
public class CategoryDaoImpl implements CategoryDao {
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
@Override
public List<Category> findAll() {
String sql = "select * from tab_category";
return template.query(sql,new BeanPropertyRowMapper<Category>(Category.class));
}
}
前台代码
hader.html加载后,发送ajax请求,请求category/findAll
<!-- 头部 start -->
<script>
const span_username = "#span_username";
const login = "#login";
const category = "#category";
const exit = "#exit"
$(()=>{
$.get("user/findOne",{},function (data){
if(data != null){
let msg = "欢迎回来:"+data.name;
$(span_username).html(msg);
$(login).css("display","none");
}else{
$(exit).css("display","none");
}
});
//查询分类数据
$.get("category/findAll",{},function (data){
//[{cid:1,cname:国内游},{},{}]
let lis='<li class="nav-active"><a href="index.html">首页</a></li>'
//遍历数组,拼接字符串(<li>)
for(i in data){
let li = '<li><a href="route_list.html?cid='+data[i]['cid']+'">'+data[i]['cname']+'</a></li>'
lis+=li;
}
//拼接收藏排行榜的li,<li><a href="favoriterank.html">收藏排行榜</a></li>
lis+='<li><a href="favoriterank.html">收藏排行榜</a></li>'
//将lis字符串,设置到ul的html内容中
$(category).html(lis);
})
})
</script>
<header id="header">
<div class="top_banner">
<img src="images/top_banner.jpg" alt="">
</div>
<div class="shortcut">
<!-- 未登录状态 -->
<div class="login_out" id="login">
<a href="login.html">登录</a>
<a href="register.html">注册</a>
</div>
<!-- 登录状态 -->
<div class="login">
<span id="span_username">您尚未登陆</span>
<a href="myfavorite.html" class="collection">我的收藏</a>
<a id = "exit" href="javascript:location.href ='user/exit';">退出</a>
</div>
</div>
<div class="header_wrap">
<div class="topbar">
<div class="logo">
<a href="/"><img src="images/logo.jpg" alt=""></a>
</div>
<div class="search">
<input name="" type="text" placeholder="请输入路线名称" class="search_input" autocomplete="off">
<a href="javascript:;" class="search-button">搜索</a>
</div>
<div class="hottel">
<div class="hot_pic">
<img src="images/hot_tel.jpg" alt="">
</div>
<div class="hot_tel">
<p class="hot_time">客服热线(9:00-6:00)</p>
<p class="hot_num">400-618-9090</p>
</div>
</div>
</div>
</div>
</header>
<!-- 头部 end -->
<!-- 首页导航 -->
<div class="navitem">
<ul id = "category" class="nav">
</ul>
</div>
旅游线路的分页展示
点击了不同的分类后,将来看到的旅游线路不一样的。通过分析数据库表结构,发现,旅游线路表和分类表时一个多对一的关系
查询不同分类的旅游线路sql
Select * from tab_route where cid = ?;
类别id的传递
Redis中查询score(cid)
页面传递cid
header.html传递cid
获取cid
根据id查询不同类别的旅游线路数据
分页展示旅游线路数据:
分析
编码
客户端代码编写
route_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>旅游-搜索</title>
<link rel="stylesheet" type="text/css" href="css/common.css">
<link rel="stylesheet" href="css/search.css">
<script src="js/jquery-3.3.1.js"></script>
<script>
const totalPage = "#totalPage";
const totalCount = "#totalCount";
const pageNum = "#pageNum";
const route = "#route"
function load(cid ,currentPage){
//发送ajax请求,请求route/pageQuery,传递cid
$.get("route/pageQuery",{cid:cid,currentPage:currentPage},function (pb){
//解析pagebean数据,展示到页面上
//1.分页工具条数据展示
//1.1 展示总页码和总记录数
$(totalPage).html(pb.totalPage);
$(totalCount).html(pb.totalCount);
console.log('totoaPage,totalCount::'+pb.totoaPage+','+pb.totalCount)
let fristPage = '<li onclick="javascript:load('+cid+')"><a href="javascript:void(0)")>首页</a></li>';
//计算上一页的页码
let beforeNum = pb.currentPage-1;
if(beforeNum <= 0){
beforeNum = 1;
};
let beforePage = '<li onclick="javascript:load('+cid+','+beforeNum+')" class="threeword"><a href="javascript:void(0)">上一页</a></li>';
if(currentPage <=1 || currentPage ==null){
fristPage='';
beforePage = '';
};
let lis = fristPage + beforePage;
//1.2 展示分页页码
/*
1.一共展示10个页码,能够达到前5后4的效果
2.如果前边不够5个,后边补齐10个
3.如果后边不足4个,前边补齐10个
*/
// 定义开始位置begin,结束位置 end
let begin=pb.totalPage-5;// 开始位置
let end=pb.totoaPage+4;// 结束位置
//1.要显示10个页码
if(pb.totalPage <10){
//总页码不够10页
begin=1;
end = pb.totalPage;
}else{
//总页码超过10页
begin = pb.currentPage -5;
end = pb.currentPage +4;
//2.如果前边不够5个,后边补齐10个
if (begin<1){
begin = 1;
end = begin+9;
};
//3.如果后边不足4个,前边补齐10个
if (end>pb.totalPage){
end = pb.totalPage;
begin = pb.totalPage -9;
};
};
for(let i =begin;i<=end;i++){
//判断当前页码是否等于i
let cls =pb.currentPage == i ? "class=\"curPage\"" : "";
//创建页码的li,//拼接字符串
lis += '<li '+cls+' onclick = "javascript:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';
};
let lastNum = pb.currentPage+1;
if(lastNum >= pb.totalPages){
lastNum =pb.totalPages;
};
let lastPage = '<li onclick="javascript:load('+cid+','+lastNum+')" class="threeword"><a href="javascript:;">下一页</a></li>';
let nextPage = ' <li onclick="javascript:load('+cid+','+pb.totalPage+')" class="threeword"><a href="javascript:;">末页</a></li>';
if(currentPage>=pb.totalPage){
lastPage = '';
nextPage = '';
};
lis += lastPage + nextPage;
$(pageNum).html(lis);
let route_lis = "";
for(let i = 0;i < pb.list.length;i++){
let route = pb.list[i];
route_lis += '<li>\n' +
' <div class="img"><img style="width: 299px" src="'+route.rimage+'" alt=""></div>\n' +
' <div class="text1">\n' +
' <p>' + route.rname + '</p>\n' +
' <br/>\n' +
' <p>' + route.routeIntroduce + '</p>\n' +
' </div>\n' +
' <div class="price">\n' +
' <p class="price_num">\n' +
' <span>¥</span>\n' +
' <span>' + route.price + '</span>\n' +
' <span>起</span>\n' +
' </p>\n' +
' <p><a href="route_detail.html">查看详情</a></p>\n' +
' </div>\n' +
' </li>';
};
$(route).html(route_lis);
window.scrollTo(0,0);
})
};
$(()=>{
//alert(search);//?id=5
// 切割字符串,拿到第二个值
let cid = location.search.split("=")[1];
//当页码加载完成后,调用load方法,发送ajax请求加载数据
load(cid);
});
</script>
</head>
<body>
<!--引入头部-->
<div id="header"></div>
<div class="page_one">
<div class="contant">
<div class="crumbs">
<img src="images/search.png" alt="">
<p>旅行><span>搜索结果</span></p>
</div>
<div class="xinxi clearfix">
<div class="left">
<div class="header">
<span>商品信息</span>
<span class="jg">价格</span>
</div>
<ul id = "route">
<li>
<div class="img"><img src="images/04-search_03.jpg" alt=""></div>
<div class="text1">
<p>【减100元 含除夕/春节出发】广州增城三英温泉度假酒店/自由行套票</p>
<br/>
<p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p>
</div>
<div class="price">
<p class="price_num">
<span>¥</span>
<span>299</span>
<span>起</span>
</p>
<p><a href="route_detail.html">查看详情</a></p>
</div>
</li>
<li>
<div class="img"><img src="images/04-search_03.jpg" alt=""></div>
<div class="text1">
<p>浪花朵朵旅行普吉岛丛林飞跃空中飞人探险游中文服务泰国旅游</p>
<br/>
<p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p>
</div>
<div class="price">
<p class="price_num">
<span>¥</span>
<span>899</span>
<span>起</span>
</p>
<p><a href="route_detail.html">查看详情</a></p>
</div>
</li>
<li>
<div class="img"><img src="images/04-search_03.jpg" alt=""></div>
<div class="text1">
<p>黑妞皇家旅行普吉岛攀牙湾大船星光之旅皮划艇日落休闲特色体验</p>
<br/>
<p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p>
</div>
<div class="price">
<p class="price_num">
<span>¥</span>
<span>999</span>
<span>起</span>
</p>
<p><a href="route_detail.html">查看详情</a></p>
</div>
</li>
<li>
<div class="img"><img src="images/04-search_03.jpg" alt=""></div>
<div class="text1">
<p>浪花朵朵旅行普吉岛皇帝岛珊瑚岛香蕉船拖拽伞水上项目</p>
<br/>
<p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p>
</div>
<div class="price">
<p class="price_num">
<span>¥</span>
<span>99</span>
<span>起</span>
</p>
<p><a href="route_detail.html">查看详情</a></p>
</div>
</li>
<li>
<div class="img"><img src="images/04-search_03.jpg" alt=""></div>
<div class="text1">
<p>环游记 泰国清迈Lila massage女子监狱spa 丽菈泰式按摩马杀鸡</p>
<br/>
<p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p>
</div>
<div class="price">
<p class="price_num">
<span>¥</span>
<span>199</span>
<span>起</span>
</p>
<p><a href="route_detail.html">查看详情</a></p>
</div>
</li>
<li>
<div class="img"><img src="images/04-search_03.jpg" alt=""></div>
<div class="text1">
<p>【减100元 含除夕/春节出发】广州增城三英温泉度假酒店/自由行套票</p>
<br/>
<p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p>
</div>
<div class="price">
<p class="price_num">
<span>¥</span>
<span>899</span>
<span>起</span>
</p>
<p><a href="route_detail.html">查看详情</a></p>
</div>
</li>
<li>
<div class="img"><img src="images/04-search_03.jpg" alt=""></div>
<div class="text1">
<p>【减100元 含除夕/春节出发】广州增城三英温泉度假酒店/自由行套票</p>
<br/>
<p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p>
</div>
<div class="price">
<p class="price_num">
<span>¥</span>
<span>1199</span>
<span>起</span>
</p>
<p><a href="route_detail.html">查看详情</a></p>
</div>
</li>
<li>
<div class="img"><img src="images/04-search_03.jpg" alt=""></div>
<div class="text1">
<p>泰国芭提雅三合一日游芭提雅蒂芬妮人妖秀成人门票bigeye含接送</p>
<br/>
<p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p>
</div>
<div class="price">
<p class="price_num">
<span>¥</span>
<span>1589</span>
<span>起</span>
</p>
<p><a href="route_detail.html">查看详情</a></p>
</div>
</li>
</ul>
<div class="page_num_inf">
<i></i> 共
<span id = "totalPage">12</span>页<span id = "totalCount">132</span>条
</div>
<div class="pageNum">
<ul id = "pageNum">
<li><a href="">首页</a></li>
<li class="threeword"><a href="#">上一页</a></li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li><a href="#">6</a></li>
<li><a href="#">7</a></li>
<li><a href="#">8</a></li>
<li><a href="#">9</a></li>
<li><a href="#">10</a></li>
<li class="threeword"><a href="javascript:;">下一页</a></li>
<li class="threeword"><a href="javascript:;">末页</a></li>
</ul>
</div>
</div>
<div class="right">
<div class="top">
<div class="hot">HOT</div>
<span>热门推荐</span>
</div>
<ul>
<li>
<div class="left"><img src="images/04-search_09.jpg" alt=""></div>
<div class="right">
<p>清远新银盏温泉度假村酒店/自由行套...</p>
<p>网付价<span>¥<span>899</span>起</span>
</p>
</div>
</li>
<li>
<div class="left"><img src="images/04-search_09.jpg" alt=""></div>
<div class="right">
<p>清远新银盏温泉度假村酒店/自由行套...</p>
<p>网付价<span>¥<span>899</span>起</span>
</p>
</div>
</li>
<li>
<div class="left"><img src="images/04-search_09.jpg" alt=""></div>
<div class="right">
<p>清远新银盏温泉度假村酒店/自由行套...</p>
<p>网付价<span>¥<span>899</span>起</span>
</p>
</div>
</li>
<li>
<div class="left"><img src="images/04-search_09.jpg" alt=""></div>
<div class="right">
<p>清远新银盏温泉度假村酒店/自由行套...</p>
<p>网付价<span>¥<span>899</span>起</span>
</p>
</div>
</li>
<li>
<div class="left"><img src="images/04-search_09.jpg" alt=""></div>
<div class="right">
<p>清远新银盏温泉度假村酒店/自由行套...</p>
<p>网付价<span>¥<span>899</span>起</span>
</p>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<!--引入头部-->
<div id="footer"></div>
<!--导入布局js,共享header和footer-->
<script type="text/javascript" src="js/include.js"></script>
</body>
</html>
服务器端代码编写
创建PageBean对象
package cn.itcast.travel.domain;
import java.util.List;
/**
* 分页对象
* @param <T>
*/
public class PageBean <T>{
private int totalCount;//总记录数
private int totalPage;//总页数
private int currentPage;//当前页码
private int pageSize;//每页显示的条数
private List<T> list;//每页显示的数据集合
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
}
Route对象
package cn.itcast.travel.domain;
import java.io.Serializable;
import java.util.List;
/**
* 旅游线路商品实体类
*/
public class Route implements Serializable {
private int rid;//线路id,必输
private String rname;//线路名称,必输
private double price;//价格,必输
private String routeIntroduce;//线路介绍
private String rflag; //是否上架,必输,0代表没有上架,1代表是上架
private String rdate; //上架时间
private String isThemeTour;//是否主题旅游,必输,0代表不是,1代表是
private int count;//收藏数量
private int cid;//所属分类,必输
private String rimage;//缩略图
private int sid;//所属商家
private String sourceId;//抓取数据的来源id
private Category category;//所属分类
private Seller seller;//所属商家
private List<RouteImg> routeImgList;//商品详情图片列表
/**
* 无参构造方法
*/
public Route(){}
/**
* 有参构造方法
* @param rid
* @param rname
* @param price
* @param routeIntroduce
* @param rflag
* @param rdate
* @param isThemeTour
* @param count
* @param cid
* @param rimage
* @param sid
* @param sourceId
*/
public Route(int rid, String rname, double price, String routeIntroduce, String rflag, String rdate, String isThemeTour, int count, int cid, String rimage, int sid, String sourceId) {
this.rid = rid;
this.rname = rname;
this.price = price;
this.routeIntroduce = routeIntroduce;
this.rflag = rflag;
this.rdate = rdate;
this.isThemeTour = isThemeTour;
this.count = count;
this.cid = cid;
this.rimage = rimage;
this.sid = sid;
this.sourceId = sourceId;
}
public List<RouteImg> getRouteImgList() {
return routeImgList;
}
public void setRouteImgList(List<RouteImg> routeImgList) {
this.routeImgList = routeImgList;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public Seller getSeller() {
return seller;
}
public void setSeller(Seller seller) {
this.seller = seller;
}
public String getSourceId() {
return sourceId;
}
public void setSourceId(String sourceId) {
this.sourceId = sourceId;
}
public int getRid() {
return rid;
}
public void setRid(int rid) {
this.rid = rid;
}
public String getRname() {
return rname;
}
public void setRname(String rname) {
this.rname = rname;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getRouteIntroduce() {
return routeIntroduce;
}
public void setRouteIntroduce(String routeIntroduce) {
this.routeIntroduce = routeIntroduce;
}
public String getRflag() {
return rflag;
}
public void setRflag(String rflag) {
this.rflag = rflag;
}
public String getRdate() {
return rdate;
}
public void setRdate(String rdate) {
this.rdate = rdate;
}
public String getIsThemeTour() {
return isThemeTour;
}
public void setIsThemeTour(String isThemeTour) {
this.isThemeTour = isThemeTour;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getRimage() {
return rimage;
}
public void setRimage(String rimage) {
this.rimage = rimage;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
}
RouteServlet
package cn.itcast.travel.web.servlet;
import cn.itcast.travel.domain.PageBean;
import cn.itcast.travel.domain.Route;
import cn.itcast.travel.service.RouteService;
import cn.itcast.travel.service.impl.RouteServiceImpl;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "RouteServlet", value = "/route/*")
public class RouteServlet extends BaseServlet {
private RouteService routeService = new RouteServiceImpl();
/**
* 分页查询
* @param request
* @param response
* @throws IOException
*/
public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String currentPageStr = request.getParameter("currentPage");
String pageSizeStr = request.getParameter("pageSize");
String cidStr = request.getParameter("cid");
//2.处理参数
int cid = triadic(cidStr,0);//类别id
int currentPage = triadic(currentPageStr,1);//当前页码,如果不传递,则默认为第一页
int pageSize = triadic(pageSizeStr,5);//每页显示条数,如果不传递,默认每页显示5条记录
//3. 调用service查询PageBean对象
PageBean<Route> pb = routeService.pageQuery(cid, currentPage, pageSize);
//4. 将pageBean对象序列化为json,返回
writeValue(pb, response);
}
}
RouteService
package cn.itcast.travel.service.impl;
import cn.itcast.travel.dao.RouteDao;
import cn.itcast.travel.dao.impl.RouteDaoImpl;
import cn.itcast.travel.domain.PageBean;
import cn.itcast.travel.domain.Route;
import cn.itcast.travel.service.RouteService;
import java.util.List;
public class RouteServiceImpl implements RouteService {
private RouteDao routeDao = new RouteDaoImpl();
@Override
public PageBean<Route> pageQuery(int cid, int currentPage, int pageSize) {
//封装PageBean
PageBean<Route> pb = new PageBean<Route>();
//设置当前页码
pb.setCurrentPage(currentPage);
//设置每页显示条数
pb.setPageSize(pageSize);
//设置总记录数
int totalCount = routeDao.findTotalCount(cid);
pb.setTotalCount(totalCount);
int start = (currentPage-1)*pageSize;
List<Route> list = routeDao.findByPage(cid, start, pageSize);
pb.setList(list);
//设置总页数 = 总记录数/每页显示条数
int totalPage =totalCount / pageSize;
pb.setTotalPage(totalCount % pageSize == 0 ? totalPage :totalPage + 1);
return pb;
}
}
RouteDao
package cn.itcast.travel.dao.impl;
import cn.itcast.travel.dao.RouteDao;
import cn.itcast.travel.domain.Route;
import cn.itcast.travel.util.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
public class RouteDaoImpl implements RouteDao {
private JdbcTemplate template =new JdbcTemplate(JDBCUtils.getDataSource());
@Override
public int findTotalCount(int cid) {
String sql = "select count(*) from tab_route where cid = ?";
return template.queryForObject(sql,Integer.class,cid);
}
@Override
public List<Route> findByPage(int cid, int start, int pageSize) {
String sql = "select * from tab_route where cid =? limit ? , ? ";
return template.query(sql,new BeanPropertyRowMapper<Route>(Route.class),cid,start,pageSize);
}
}