19.2、Javaweb案例_Servlet代码抽取优化分页数据redis缓存优化分页数据展示

news2024/11/27 12:31:58

优化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>&yen;</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>&yen;</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>&yen;</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>&yen;</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>&yen;</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>&yen;</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>&yen;</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>&yen;</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>&yen;</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>&yen;<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>&yen;<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>&yen;<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>&yen;<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>&yen;<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);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/177498.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线性代数复习——行列式

文章目录第一章 行列式1.1 克拉默法则1.2 n阶行列式1.3 特殊行列式1.4 行列式的性质和推论1.5 余子式和代数余子式1.6 范德蒙德行列式第一章 行列式 1.1 克拉默法则 举例&#xff1a; 对于三元线性方程组 {a11x1a12x2a13x3b1a21x1a22x2a23x3b2a31x1a32x2a33x3b3(1)\begin{cas…

Allegro如何自动导弧操作指导

Allegro如何自动导弧操作指导 在做PCB设计的时候,经常会需要给信号线导弧,如果有大量的走线,导弧线是个比较费时间的工作,Allegro可以自动给信号线导弧,如下图 具体操作如下 选择Route选择Unsupported Prototypes

金融帝国实验室(Capitalism Lab)官方正版游戏『优惠活动政策』

「金融帝国实验室」&#xff08;Capitalism Lab&#xff09;Enlight 官方正版游戏「2023春节特卖」 ■时间&#xff1a;2023.01.21&#xff5e;2023.02.28 ■游戏开发商&#xff1a;Enlight Software Ltd. 请您认准以下官方正版游戏购买链接&#xff1a;支持“支付宝&a…

使用ebpf 监控mysqld 内核

一、开发思路分析 我们使用ebpf 监控mysql的话有两个思路去做这件事情 1、kprobe -> hook 掉tcp_sendmsg 和 tcp_recvmsg 一类的内核函数去分析网络协议 2、uprobe -> hook 掉 mysqld 的api函数&#xff0c;然后在此基础上进行统计 我使用的是uprobe 去hook 掉mysql内…

24. 面向对象的思想

1. 面向对象 类似于c/c#/java等高级语言&#xff0c;python从设计之初就已经是一门面向对象的语言&#xff0c;正因为如此&#xff0c;在python中创建一个类和对象是很容易的。关于面向对象的思想及基础&#xff0c;此处不再赘述。 2. 类对象 (1) 类变量&#xff1a;类变量在…

计算机毕业设计选题推荐基于nodejs+Vue360学生宿舍系统

管理员&#xff1b;首页、个人中心、宿舍信息管理、学生管理、宿舍报修管理、访客信息管理、水电费管理、管理员管理、交流论坛、系统管理&#xff0c;学生&#xff1b;首页、个人中心、宿舍报修管理、水电费管理&#xff0c; 前台首页&#xff1b;首页、交流论坛、通知公告、个…

STM32之HAL源码阅读(GPIO章节)

前言 说明 本文只针对于软件层面的阅读&#xff0c;详细操作请查阅对应的手册,使用过标准库的朋友更好的能理解本文针对的是STM32F10x系列&#xff0c;其他的类似 参考资料 STM32F10x中文参考手册 工具 stm32cubemx6.5clion最新版 HAL源码之GPIO的阅读 步骤一&#xff…

Cesium:Indexed 3D Scene Layers (I3S)加载

点击此处,查看完整的OGC标准列表项。Indexed 3D Scene Layers(I3S)标准官网介绍地址为:I3S,相关的GitHub主页地址为:Esri/i3s-spec,其详细介绍文档地址可点击此处查阅。我们的核心点在于介绍如何通过Cesium.js开发框架加载I3S三维场景服务。 目录 Cesium.js:I3S支持情…

JUC面试(九)——Synchronized和Lock的区别

Synchronized和Lock的区别 前言 对象锁&#xff08;synchronized method{}&#xff09;和类锁&#xff08;static sychronized method{}的区别 对象锁也叫实例锁&#xff0c;对应synchronized关键字&#xff0c;当多个线程访问多个实例时&#xff0c;它们互不干扰&#xff0…

基于蜣螂优化的BP神经网络(分类应用) - 附代码

基于蜣螂优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录基于蜣螂优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.蜣螂优化BP神经网络3.1 BP神经网络参数设置3.2 蜣螂算法应用4.测试结果&#xff1a;5.Mat…

Ubuntu16.04安装N卡驱动

最近碰到个实验&#xff0c;需要用pytorch0.4和python2.7的环境&#xff0c;因为环境比较老&#xff0c;所以新显卡可能不能装。紧急联系朋友搞了张1660ti想来跑实验&#xff0c;结果光是驱动就碰了一鼻子灰&#xff0c;这里简单做下总结&#xff0c;引以为戒。首先是系统版本&…

Python for循环及用法详解

Python 中的循环语句有 2 种&#xff0c;分别是 while 循环和 for 循环&#xff0c;前面章节已经对 while 做了详细的讲解&#xff0c;本节给大家介绍 for 循环&#xff0c;它常用于遍历字符串、列表、元组、字典、集合等序列类型&#xff0c;逐个获取序列中的各个元素。for 循…

ARP渗透与攻防(五)之Ettercap劫持用户流量

ARP-Ettercap劫持用户流量 系列文章 ARP渗透与攻防(一)之ARP原理 ARP渗透与攻防(二)之断网攻击 ARP渗透与攻防(三)之流量分析 ARP渗透与攻防(四)之WireShark截获用户数据 一.ettercap 工具介绍 项目官网&#xff1a;http://ettercap.github.io/ettercap/index.html EtterC…

(十五)ForkJoin框架

ForkJoinPoolForkJoinPool是一种“分治算法”的多线程并行计算框架&#xff0c;自Java7引入。它将一个大的任务分为若干个子任务&#xff0c;这些子任务分别计算&#xff0c;然后合并出最终结果。ForkJoinPool比普通的线程池可以更好地实现计算的负载均衡&#xff0c;提高资源利…

安装MikTeX-latex

安装MikTeX-latex一、报错信息二、重新安装三、编译MDPI Template一、报错信息 由于之前使用的是basic-miktex-2.9.7269-x64.exe这个版本&#xff0c;当安装完成后&#xff0c;在更新package时遇到了以下错误&#xff1a; MikTeX update error 于是&#xff0c;通过搜索&…

冯·诺依曼、哈佛、改进型哈佛体系结构解析

在如今的CPU中&#xff0c;由于Catch的存在&#xff0c;这些概念已经被模糊了。个人认为去区分他们并没有什么意义&#xff0c;仅作为知识点。 哈佛结构设计复杂&#xff0c;但效率高。冯诺依曼结构则比较简单&#xff0c;但也比较慢。CPU厂商为了提高处理速度&#xff0c;在C…

2023 年程序员的热门开发项目:掌握最新技术的教程和工具的完整列表

欢迎阅读我们关于“2023 年程序员的热门开发项目”的博文&#xff01;作为一名开发人员&#xff0c;了解最新的技术和工具对于在就业市场上保持竞争力至关重要。在这篇文章中&#xff0c;我们编制了一份 2023 年最热门开发项目的完整列表&#xff0c;以及掌握每个项目的教程和资…

ChatGPT付费版来啦,好用的AI生成产品还能免费使用吗?AIGC工具箱

​最新消息&#xff0c;chatGPT推出了付费版&#xff01;每月&#xff04;42美元&#xff0c;不限流使用&#xff0c;你会付费使用吗&#xff1f;&#x1f9f0;AIGC工具箱下面推荐几款AI 生成产品&#xff01;你觉得哪个更好用呢&#xff1f;AI 的出现&#xff0c;颠覆了内容生…

自己动手写一个操作系统——我们能做什么,我们需要做什么

文章目录计算机启动流程第一条指令BIOSMBRloaderkernel总结计算机启动流程 第一条指令 在开机的一瞬间&#xff0c;也就是上电的一瞬间&#xff0c;CPU 的 CS:IP 寄存器被硬件强制初始化为 0xF000:0xFFF0。 CS:IP 就是 PC 指针&#xff0c;也就是 CPU 下一条要执行的指令的地址…

Elasticsearch7.8.0版本入门—— Elasticsearch7.8.0映射操作

目录一、映射的概述二、创建映射的示例2.1、首先&#xff0c;创建索引2.2、然后&#xff0c;再创建好的索引基础上&#xff0c;创建映射2.3、映射属性说明2.4、查看创建的映射2.5、最后&#xff0c;创建文档2.6、根据文档中name属性条件查询文档 理解映射示例2.7、根据文档中se…