7.优化Servlet
7.1目的
减少Servlet的数量,现在是一个功能一个Servlet,将其优化为一个模块一个Servlet,相当于在数据库中一张表对应一个Servlet,在Servlet中提供不同的方法,完成用户的请求。
Idea控制台中文乱码解决:-Dfile.encoding=gb2312
7.2BaseServlet编写
package cn.itcast.travel.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class BaseServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // System.out.println("BaseServle的service方法执行了"); //完成方法分发 //1.获取请求路径 String uri = req.getRequestURI(); ///travel/user/add // System.out.println(uri); //2.获取方法名称 String methodName = uri.substring(uri.lastIndexOf('/') + 1); // System.out.println(methodName); //add //3.获取方法对象 //this谁调用我,我代表谁 // System.out.println(this); //UserServlet对象 try { Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); //忽略访问权限修饰符获取方法 // Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); //4.执行方法 //暴力反射 // method.setAccessible(true); method.invoke(this,req,resp); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }
7.3UserServlet改写
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.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Map; @WebServlet("/user/*") //user/add user/find public class UserServlet extends BaseServlet { //声明一个UserService成员变量 private UserService service = new UserServiceImpl(); /* 注册功能 */ public void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //验证校验 String check = request.getParameter("check"); //从sesion中获取验证码 HttpSession session = request.getSession(); String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER"); session.removeAttribute("CHECKCODE_SERVER");//为了保证验证码只能使用一次 //比较 if (checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)) { //验证码错误 ResultInfo info = new ResultInfo(); //注册失败 info.setFlag(false); info.setErrorMsg("验证码错误"); //将info对象序列化为json ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(info); response.setContentType("application/json;charset=utf-8"); response.getWriter().write(json); return; } //1.获取数据 Map<String, String[]> map = request.getParameterMap(); //2.封装对象 User user = new User(); try { BeanUtils.populate(user, map); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //3.调用service完成注册 // UserService service = new UserServiceImpl(); boolean flag = service.regist(user); ResultInfo info = new ResultInfo(); //4.响应结果 if (flag) { //注册成功 info.setFlag(true); } else { //注册失败 info.setFlag(false); info.setErrorMsg("注册失败!"); } ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(info); //将json数据写回客户端 //设置content-type response.setContentType("application/json;charset=utf-8"); response.getWriter().write(json); } /* 登录功能 */ public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取用户名和密码数据 Map<String, String[]> map = request.getParameterMap(); //2.封装User对象 User user = new User(); try { BeanUtils.populate(user, map); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //3.调用Service查询 // UserService service = new UserServiceImpl(); User u = service.login(user); ResultInfo info = new ResultInfo(); //4.判断用户对象是否为null if (u == null) { //用户名密码或错误 info.setFlag(false); info.setErrorMsg("用户名或密码错误"); } //5.判断用户是否激活 if (u != null && !"Y".equals(u.getStatus())) { //用户尚未激活 info.setFlag(false); info.setErrorMsg("您尚未激活,请激活"); } //6.判断登录成功 if (u != null && "Y".equals(u.getStatus())) { request.getSession().setAttribute("user", u);//登录成功标记 //登录成功 info.setFlag(true); } //响应数据 ObjectMapper mapper = new ObjectMapper(); response.setContentType("application/json;charset=utf-8"); mapper.writeValue(response.getOutputStream(), info); } /* 查询单个对象 */ public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //从session中获取登录用户 Object user = request.getSession().getAttribute("user"); //将user写回客户端 ObjectMapper mapper = new ObjectMapper(); response.setContentType("application/json;charset=utf-8"); mapper.writeValue(response.getOutputStream(), user); } /* 退出功能 */ public void exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.销毁session request.getSession().invalidate(); //2.跳转登录页面 response.sendRedirect(request.getContextPath() + "/login.html"); } /* 激活功能 */ public void active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取激活码 String code = request.getParameter("code"); if (code != null) { //2.调用service完成激活 // UserService service = new UserServiceImpl(); boolean flag = service.active(code); //3.判断标记 String msg = null; if (flag) { //激活成功 msg = "激活成功,请<a href='login.html'>登录</a>"; } else { //激活失败 msg = "激活失败,请联系管理员!"; } response.setContentType("text/html;charset=utf-8"); response.getWriter().write(msg); } } }
注:改写完成之后,相应的html文件中的路径也要改一下。
8.分类数据展示
8.1效果
8.2分析
8.3后台代码
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 com.fasterxml.jackson.databind.ObjectMapper; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; @WebServlet("/category/*") public class CategoryServlet extends BaseServlet { private CategoryService service = new CategoryServiceImpl(); /* 查询所有 */ public void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.调用service查询所有 List<Category> cs = service.findAll(); //2.序列化json返回 // ObjectMapper mapper = new ObjectMapper(); // response.setContentType("application/json;charset=utf-8"); // mapper.writeValue(response.getOutputStream(),cs); writeValue(cs,response); } public void find(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("CategoryServlet的find方法..."); } }
CategoryService
package cn.itcast.travel.service; import cn.itcast.travel.domain.Category; import java.util.List; public interface CategoryService { List<Category> findAll(); }
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 java.util.List; public class CategoryServiceImpl implements CategoryService { private CategoryDao categoryDao = new CategoryDaoImpl(); @Override public List<Category> findAll() { return categoryDao.findAll(); } }
CategoryDao
package cn.itcast.travel.dao; import cn.itcast.travel.domain.Category; import java.util.List; public interface CategoryDao { List<Category> findAll(); }
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 { private 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)); } }
在BaseServlet中封装了序列化json的方法
package cn.itcast.travel.web.servlet; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class BaseServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // System.out.println("BaseServle的service方法执行了"); //完成方法分发 //1.获取请求路径 String uri = req.getRequestURI(); ///travel/user/add // System.out.println(uri); //2.获取方法名称 String methodName = uri.substring(uri.lastIndexOf('/') + 1); // System.out.println(methodName); //add //3.获取方法对象 //this谁调用我,我代表谁 // System.out.println(this); //UserServlet对象 try { Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); //忽略访问权限修饰符获取方法 // Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); //4.执行方法 //暴力反射 // method.setAccessible(true); method.invoke(this,req,resp); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } /* 直接将传入的对象序列化为json,并且写回客户端 */ public void writeValue(Object obj,HttpServletResponse response) throws IOException { ObjectMapper mapper = new ObjectMapper(); response.setContentType("application/json;charset=utf-8"); mapper.writeValue(response.getOutputStream(),obj); } /* 将传入的对象序列化返回 */ public String writeValueAsString(Object obj) throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); return mapper.writeValueAsString(obj); } }
8.4前台代码
header.html加载后,发送ajax请求,请求category/findAll
<!-- 头部 start --> <script> $(function () { //查询用户信息 $.get("user/findOne",{},function (data) { //{uid:1,name:'李四'} var msg = "欢迎回来,"+data.name; $("#span_username").html(msg); }); //查询分类数据 $.get("category/findAll",{},function (data) { //[{cid:1,cname:国内游},{},{}] var lis = '<li class="nav-active"><a href="index.html">首页</a></li>'; //遍历数组,拼接字符串 for (var i = 0; i < data.length; i++) { var li =' <li><a href="favoriterank.html">'+data[i].cname+'</a></li>' lis += li; } //拼接收藏榜的li lis+= ' <li><a href="favoriterank.html">收藏排行榜</a></li>'; //将lis中的内容设置到ul的html中 $("#category").html(lis); }); }); </script> <!-- 头部 start --> <header id="header"> <div class="top_banner"> <img src="images/top_banner.jpg" alt=""> </div> <div class="shortcut"> <!-- 未登录状态 --> <div class="login_out"> <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 href="javascript:location.href='exitServlet';">退出</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"> <!-- <li class="nav-active"><a href="index.html">首页</a></li> <li><a href="route_list.html">门票</a></li> <li><a href="route_list.html">酒店</a></li> <li><a href="route_list.html">香港车票</a></li> <li><a href="route_list.html">出境游</a></li> <li><a href="route_list.html">国内游</a></li> <li><a href="route_list.html">港澳游</a></li> <li><a href="route_list.html">抱团定制</a></li> <li><a href="route_list.html">全球自由行</a></li> <li><a href="favoriterank.html">收藏排行榜</a></li>--> </ul> </div>
8.5对分类数据进行缓存优化
分析发现,分类的数据在每一次页面加载后都会重新请求数据库来加载,对数据库的压力比较大,而且分类的数据不会经常产生变化,所有可以使用redis来缓存这个数据。
分析:
8.6优化代码实现
期望数据中存储的顺序就是将来展示的顺序,使用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 java.util.ArrayList; import java.util.List; import java.util.Set; public class CategoryServiceImpl implements CategoryService { private CategoryDao categoryDao = new CategoryDaoImpl(); @Override public List<Category> findAll() { //1.从redis中查询 //1.1获取jedis客户端 Jedis jedis = JedisUtil.getJedis(); //1.2可以使用sortedset排序查询 Set<String> categorys = jedis.zrange("category", 0, -1); 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 (int i = 0; i < cs.size(); i++) { jedis.zadd("category",cs.get(i).getCid(),cs.get(i).getCname()); } }else { System.out.println("从缓存中查询。。。"); //4.如果不为空,将set的数据存入list cs = new ArrayList<Category>(); for (String name : categorys) { Category category = new Category(); category.setCname(name); cs.add(category); } } return cs; } }
9.旅游线路的分页展示
点击了不同的分类后,将来看到的旅游线路不一样的。通过分析数据库表结构,发现,旅游线路表和分类表时一个多对一的关系
查询不同分类的旅游线路sql
Select * from tab_route where cid = ?;
9.1类别id的传递
Redis中查询score(cid)
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.Tuple; import java.util.ArrayList; import java.util.List; import java.util.Set; public class CategoryServiceImpl implements CategoryService { private CategoryDao categoryDao = new CategoryDaoImpl(); @Override public List<Category> findAll() { //1.从redis中查询 //1.1获取jedis客户端 Jedis jedis = JedisUtil.getJedis(); //1.2可以使用sortedset排序查询 // Set<String> categorys = jedis.zrange("category", 0, -1); //1.3查询sortedset的分数(cid)和值(cname) Set<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1); 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 (int i = 0; i < cs.size(); i++) { jedis.zadd("category",cs.get(i).getCid(),cs.get(i).getCname()); } }else { System.out.println("从缓存中查询。。。"); //4.如果不为空,将set的数据存入list cs = new ArrayList<Category>(); for (Tuple tuple : categorys) { Category category = new Category(); category.setCname(tuple.getElement()); category.setCid((int)tuple.getScore()); cs.add(category); } } return cs; } }
页面传递cid
header.html传递cid
<!-- 头部 start --> <script> $(function () { //查询用户信息 $.get("user/findOne", {}, function (data) { //{uid:1,name:'李四'} var msg = "欢迎回来," + data.name; $("#span_username").html(msg); }); //查询分类数据 $.get("category/findAll", {}, function (data) { //[{cid:1,cname:国内游},{},{}] var lis = '<li class="nav-active"><a href="index.html">首页</a></li>'; //遍历数组,拼接字符串 for (var i = 0; i < data.length; i++) { var li = ' <li><a href="favoriterank.html?cid=' + data[i].cid + '">' + data[i].cname + '</a></li>' lis += li; } //拼接收藏榜的li lis += ' <li><a href="favoriterank.html">收藏排行榜</a></li>'; //将lis中的内容设置到ul的html中 $("#category").html(lis); }); }); </script> <!-- 头部 start --> <header id="header"> <div class="top_banner"> <img src="images/top_banner.jpg" alt=""> </div> <div class="shortcut"> <!-- 未登录状态 --> <div class="login_out"> <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 href="javascript:location.href='exitServlet';">退出</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"> <!-- <li class="nav-active"><a href="index.html">首页</a></li> <li><a href="route_list.html">门票</a></li> <li><a href="route_list.html">酒店</a></li> <li><a href="route_list.html">香港车票</a></li> <li><a href="route_list.html">出境游</a></li> <li><a href="route_list.html">国内游</a></li> <li><a href="route_list.html">港澳游</a></li> <li><a href="route_list.html">抱团定制</a></li> <li><a href="route_list.html">全球自由行</a></li> <li><a href="favoriterank.html">收藏排行榜</a></li>--> </ul> </div>
获取cid
<!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> $(function () { var search = location.search; //alert(search);//?id=5 // 切割字符串,拿到第二个值 var cid = 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> <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>12</span>页<span>132</span>条 </div> <div class="pageNum"> <ul> <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>
9.2根据id查询不同类别的旅游线路数据
分页展示旅游线路数据
1.分析
2.客户端代码编写
<!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> $(function () { var search = location.search; //alert(search);//?id=5 // 切割字符串,拿到第二个值 var cid = search.split("=")[1]; //当页码加载完成后,调用load方法,发送ajax请求加载数据 load(cid); }); 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); var lis = ""; var firstPage = ' <li onclick="javascript:load(' + cid + ')"><a href="javascript:void(0)">首页</a></li>'; //计算上一页的页码 var beforeNum = pb.currentPage - 1; if (beforeNum <= 0) { beforeNum = 1; } var beforePage = '<li onclick="javascipt:load(' + cid + ',' + beforeNum + ')" class="threeword"><a href="javascript:void(0)">上一页</a></li>'; lis += firstPage; lis += beforePage; /*for (var i = 1; i <= pb.totalPage; i++) { //创建页码的li var li; //判断当前页码是否等于i if (pb.currentPage == i) { li = ' <li class="curPage" onclick="javascript:load(' + cid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>'; } else { var li = ' <li onclick="javascript:load(' + cid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>'; } //拼接字符串 lis += li; }*/ //1.2 展示分页页码 /* 1.一共展示10个页码,能够达到前5后4的效果 2.如果前边不够5个,后边补齐10个 3.如果后边不足4个,前边补齐10个 */ // 定义开始位置begin,结束位置 end var begin; // 开始位置 var end; // 结束位置 //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 = end - 9; } } for (var i = begin; i <= end; i++) { var li; //判断当前页码是否等于i if (pb.currentPage == i) { li = '<li class="curPage" onclick="javascipt:load(' + cid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>'; } else { //创建页码的li li = '<li onclick="javascipt:load(' + cid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>'; } //拼接字符串 lis += li; } var lastNum = pb.totalPage; var lastPage = '<li onclick="javascript:load(' + cid + ',' + lastNum + ')"><a href="javascript:void(0)">末页</a></li>'; var nextNum = pb.currentPage + 1; if (nextNum > lastNum) { nextNum = lastNum; } var nextPage = '<li onclick="javascipt:load(' + cid + ',' + nextNum + ')" class="threeword"><a href="javascript:void(0)">下一页</a></li>'; lis += nextPage; lis += lastPage; //奖lis内容设置到ul中 $("#pageNum").html(lis); //2.列表数据展示 //2.列表数据展示 var route_lis = ""; for (var i = 0; i < pb.list.length; i++) { //获取{rid:1,rname:"xxx"} var route = pb.list[i]; var li = '<li> ' + ' <div class="img"><img src="' + route.rimage + '" style=" 299px;"></div> ' + ' <div class="text1"> ' + ' <p>' + route.rname + '</p> ' + ' <br/> ' + ' <p>' + route.routeIntroduce + '</p> ' + ' </div> ' + ' <div class="price"> ' + ' <p class="price_num"> ' + ' <span>¥</span> ' + ' <span>' + route.price + '</span> ' + ' <span>起</span> ' + ' </p> ' + ' <p><a href="route_detail.html">查看详情</a></p> ' + ' </div> ' + ' </li>'; route_lis += li; } $("#route").html(route_lis); //定位到页面顶部 window.scrollTo(0,0); }); } </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>--> </ul> <div class="page_num_inf"> <i></i> 共 <span id="totalPage"> </span>页<span id="totalCount"> </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 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>
3.服务器端代码编写
a) 创建PageBean对象
package cn.itcast.travel.domain; import java.util.List; 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; } }
b) 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.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/route/*") public class RouteServlet extends BaseServlet { private RouteService routeService = new RouteServiceImpl(); /* 分页查询 */ public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.接受参数 String currentPageStr = request.getParameter("currentPage"); String pageSizeStr = request.getParameter("pageSize"); String cidStr = request.getParameter("cid"); //2.处理参数 int cid = 0;//类别id if (cidStr != null && cidStr.length() > 0) { cid = Integer.parseInt(cidStr); } int currentPage = 0;//当前页码,默认为第一页 if (currentPageStr != null && currentPageStr.length() > 0) { currentPage = Integer.parseInt(currentPageStr); } else { currentPage = 1; } int pageSize = 0;//每页显示条数,默认显示5条 if (pageSizeStr != null && pageSizeStr.length() > 0) { pageSize = Integer.parseInt(pageSizeStr); } else { pageSize = 5; } //3. 调用service查询PageBean对象 PageBean<Route> pb = routeService.pageQuery(cid, currentPage, pageSize); //4. 将pageBean对象序列化为json,返回 writeValue(pb, response); } }
c) RouteService
package cn.itcast.travel.service; import cn.itcast.travel.domain.PageBean; import cn.itcast.travel.domain.Route; public interface RouteService { /* 根据类别进行分页查询 */ PageBean<Route> pageQuery(int cid, int currentPage, int pageSize); }
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<>(); //设置当前页码 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 == 0 ? totalCount / pageSize :(totalCount / pageSize) + 1 ; pb.setTotalPage(totalPage); return pb; } }
d) RouteDao
package cn.itcast.travel.dao; import cn.itcast.travel.domain.Route; import java.util.List; public interface RouteDao { /* 根据cid查询总记录数 */ int findTotalCount(int cid); /* 根据cid,start,pageSize查询当前页的数据集合 */ List<Route> findByPage(int cid,int start,int pageSize); }
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); } }