某马旅游网学习总结

2023-10-31 12:18
文章标签 学习 总结 旅游网 某马

本文主要是介绍某马旅游网学习总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一 项目部署的环境

Idea集成开发工具+jdk1.8+tomcat8.5.31+maven3.5.2+redis2.8.9

二 项目的架构

后台的架构是 servlet->service->dao

前台的架构是 html, js, css

前台和后台的交互使用的是 ajax 异步方式提交表单

三 数据库

主要有6张表,表关系如下图所示

四 项目的主要功能模块

1.注册

用户注册功能,需要输入用户名,密码,邮箱,姓名,手机号,性别,出生日期,验证码才可登录成功。在前台页面会使用正则表达式对输入的表单进行校验,合法之后才会提交到服务器。使用异步ajax的方式提交表单,目的是为了获取服务器响应的数据。

 提交表单的代码如下

$("#registerForm").submit(function(){//1.发送数据到服务器if(checkUsername() && checkPassword() && checkEmail() && checkName() && checkTelephone() && checkBirthday() && checkCheck()){//校验通过,发送ajax请求,提交表单的数据   username=zhangsan&password=123$.post("user/regist",$(this).serialize(),function(data){//处理服务器响应的数据  data  {flag:true,errorMsg:"注册失败"}if(data.flag){//注册成功,跳转成功页面location.href="register_ok.html";}else{//注册失败,给errorMsg添加提示信息$("#errorMsg").html(data.errorMsg);}});}//2.不让页面跳转return false;//如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,则表单不提交
});

 用户成功注册后,会跳转到注册成功的界面,并提示用户进行激活,需要点击发送到填写邮箱的链接进行激活账号,只有激活的账号才可以登录。

在编写RegistUserServlet 代码时,需要注意先对验证码进行校验,如果验证码错误则在页面上弹出提示信息,不再查询数据库。需要查询数据库的user表中是否存在该用户名,如果存在则提示注册失败,否则数据库需要保存用户的信息,并注册成功。

发送邮件让用户点击激活的目的是为了保证用户写的邮箱是正确的,以后可以用于推广宣传信到用户邮箱中。需要开启授权码,设置发件人的账号和授权码。使用到的是MailUtils工具类,用sendMail方法完成邮件发送。

2.登录

用户输入账号和密码,首先判断验证码是否正确,如果正确则需要查询账号和密码和数据库中的是否一致,并且查询数据库中用户的激活状态,如果是激活状态才可以登录成功,否则则需要去激活账号。

 如果登录成功后,需要在页面上显示当前登录的用户名称,即欢迎回来,xxx。那么在servlet中需要从session中获取登录用户,并将该user写回至客户端,在写回时使用了序列化json

Object user = request.getSession().getAttribute("user");
//将user写回客户端ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),user);

3.退出

将session对象进行销毁,并跳转到登录页面即可。

//1.销毁session
request.getSession().invalidate();
//2.跳转页面
response.sendRedirect(request.getContextPath()+"/login.html");

4.导航条展示

展示效果如下图所示

具体的逻辑分析如下

 

展示时需要知道其cid的值,该值是根据表category查询得到的,根据cid知道当前显示的是哪一类,并进行展示,还是需要查询数据库tab_route展示数据的详细信息。前台代码如下

//查询分类数据
$.get("category/findAll",{},function (data) {var nav_cid = getParameter("cid");// alert(nav_cid);//[{cid:1,cname:国内游},{},{}]if(nav_cid == 1){var lis = '<li class="nav-active"><a href="index.html">首页</a></li>';}else{var lis = '<li><a href="index.html">首页</a></li>';}// var lis = '<li><a href="index.html">首页</a></li>';//遍历数组,拼接字符串(<li>)for (var i = 1; i < data.length-1; i++) {if(nav_cid == data[i].cid){var li = '<li class="nav-active"><a href="route_list.html?cid='+data[i].cid+'">'+data[i].cname+'</a></li>';}else{var 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>if(nav_cid == 10){lis+= '<li class="nav-active"><a href="favoriterank.html">收藏排行榜</a></li>';}else {lis+= '<li><a href="favoriterank.html">收藏排行榜</a></li>';}// lis+= '<li><a href="favoriterank.html">收藏排行榜</a></li>';//将lis字符串,设置到ul的html内容中$("#category").html(lis);//定位到页面的顶部window.scrollTo(0,0);
});

分类的数据在每一次页面加载后都会重新请求数据库来加载,对数据库的压力比较大,而且分类的数据不会经常产生变化,所有可以使用redis来缓存这个数据。

@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的keyfor (int i = 0; i < cs.size(); i++) {jedis.zadd("category", cs.get(i).getCid(), cs.get(i).getCname());}} else {System.out.println("从redis中查询.....");//4.如果不为空,将set的数据存入listcs = new ArrayList<Category>();for (String name : categorys) {Category category = new Category();category.setCname(name);cs.add(category);}}return cs;
}

5.旅游线路的分页展示

需要在前端页面上传递cid,然后根据cid查询不同类别的旅游线路数据,并进行分页展示。

前台代码如下

$(function () {var search = location.search;// 切割字符串,拿到第二个值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 fristPage = '<li onclick="javascipt: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 += fristPage;lis += beforePage;//1.2 展示分页页码/*1.一共展示10个页码,能够达到前5后4的效果2.如果前边不够5个,后边补齐10个3.如果后边不足4个,前边补齐10个*/// 定义开始位置begin,结束位置 endvar 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;//判断当前页码是否等于iif(pb.currentPage == i){li = '<li class="curPage" onclick="javascipt:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';}else{//创建页码的lili = '<li onclick="javascipt:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';}//拼接字符串lis += li;}var lastPage = '<li class="threeword"><a href="javascript:;">末页</a></li>';var nextPage = '<li class="threeword"><a href="javascript:;">下一页</a></li>';lis += nextPage;lis += lastPage;//将lis内容设置到 ul$("#pageNum").html(lis);//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>\n' +'                        <div class="img"><img src="'+route.rimage+'" style="width: 299px;"></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_lis += li;}$("#route").html(route_lis);//定位到页面顶部window.scrollTo(0,0);});}

6.旅游线路详情展示

在展示旅游线路的详情时,需要传入rid才能显示具体的线路详情。

//1.获取rid
var rid = getParameter("rid");//2.发送请求请求 route/findOne$.get("route/findOne",{rid:rid},function (route) {//3.解析数据填充html$("#rname").html(route.rname);$("#routeIntroduce").html(route.routeIntroduce);$("#price").html("¥"+route.price);$("#sname").html(route.seller.sname);$("#consphone").html(route.seller.consphone);$("#address").html(route.seller.address);//图片展示var ddstr = '<a class="up_img up_img_disable"></a>';//遍历routeImgListfor (var i = 0; i < route.routeImgList.length; i++) {var astr ;if(i >= 4){astr = '<a title="" class="little_img" data-bigpic="'+route.routeImgList[i].bigPic+'" style="display:none;">\n' +'                        <img src="'+route.routeImgList[i].smallPic+'">\n' +'                    </a>';}else{astr = '<a title="" class="little_img" data-bigpic="'+route.routeImgList[i].bigPic+'">\n' +'                        <img src="'+route.routeImgList[i].smallPic+'">\n' +'                    </a>';}ddstr += astr;}ddstr+='<a class="down_img down_img_disable" style="margin-bottom: 0;"></a>';$("#dd").html(ddstr);//图片展示和切换代码调用goImg();});

7.旅游线路收藏

首先需要先判断用户是否登录,如果未登录,需要先登录。然后查询数据库判断用户是否收藏过该线路,具体是根据rid查询tab_favorite表。如果用户已经收藏该路线,需要切换按钮的样式,将属性改为不可点击。

$(function () {// 发送请求,判断用户是否收藏过该线路var rid = getParameter("rid");$.get("route/isFavorite",{rid:rid},function (flag) {if(flag){// 用户已经收藏过//<a  class="btn already" disabled="disabled">//设置收藏按钮的样式$("#favorite").addClass("already");$("#favorite").prop("disabled",disabled);}else{// 用户没有收藏}
});

如果用户没有收藏过该线路,则可以点击按钮收藏该线路,具体分析如下图所示

$(function () {// 发送请求,判断用户是否收藏过该线路var rid = getParameter("rid");$.get("route/isFavorite",{rid:rid},function (flag) {if(flag){// 用户已经收藏过//<a  class="btn already" disabled="disabled">//设置收藏按钮的样式$("#favorite").addClass("already");$("#favorite").attr("disabled","disabled");//删除按钮的点击事件$("#favorite").removeAttr("onclick");}else{// 用户没有收藏}});});//点击收藏按钮触发的方法
function addFavorite(){var rid = getParameter("rid");//1. 判断用户是否登录$.get("user/findOne",{},function (user) {if(user){//用户登录了//添加功能$.get("route/addFavorite",{rid:rid},function () {//代码刷新页面location.reload();});}else{//用户没有登录alert("您尚未登录,请登录");location.href="http://localhost/travel/login.html";}})
}

 在做该项目时,感觉一些技术还是要运用熟练的,对于自己来说,比较生疏的是js,jquery,ajax,序列化json等。并且涉及到查询数据库的语句也要会写,以及JDBCTemplate的返回值是什么,这些都关系到代码的编写。在编写前端代码的html页面中,需要注意字符串的拼接方式,即单引号和双引号,如果写的不对,也会刷不出来效果。

另外在做项目时,学会使用debug也很重要,打断点调试错误,需要使用debug的方式启动整个项目。

这篇关于某马旅游网学习总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/315291

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

二分最大匹配总结

HDU 2444  黑白染色 ,二分图判定 const int maxn = 208 ;vector<int> g[maxn] ;int n ;bool vis[maxn] ;int match[maxn] ;;int color[maxn] ;int setcolor(int u , int c){color[u] = c ;for(vector<int>::iter