黑马旅游网站全记录

本文介绍了如何使用Maven导入项目,包括两种启动方式,并详细讲述了技术选型如servlet、HTML、filter等的应用。核心内容涉及用户注册、登录验证、邮件激活流程,以及数据展示、分页和搜索优化。
摘要由CSDN通过智能技术生成

一、 项目导入

  1. 点击侧边的maven(如果没有可以在view–>tool window 中找到),点击加号,选择文件中的pom.xml文档即可导入
    在这里插入图片描述

  2. 首先预览一下静态页面
    在这里插入图片描述
    启动方式1:
    在这里插入图片描述
    在这里插入图片描述
    启动方式2:添加启动方式,点击绿色三角形启动
    在这里插入图片描述
    在这里插入图片描述

二、技术选型

  1. web:
    servlet:前端控制器
    HTML:数据展示
    filter:过滤器
    BeanUtils:数据封装
    Jackson:json序列化工具

  2. service:
    Javaemail:Java发送文件
    redis:nosql内存数据
    jedis:Java的redis的客户端

  3. Dao
    Mysql:数据库
    Druid:数据库连接池
    jdbcTemplate:jdbc的工具类

三、创建数据库

在这里插入图片描述

四、实现登录、注册、退出

各层调用图:
在这里插入图片描述

注册:在html利用js完成表单校验,使用ajax完成表单提交
注册成功,跳转成功页面
注册失败,跳转失败页面

servlet:RegisterServlet
(0.设置编码已经利用统一过滤器完成)
1.获取数据
2.封装User对象
3.调用service完成注册
4.根据service返回,提示信息:
将提示信息信息转为json
设置相应头:contentType

service:
registerUser(User user)
调用dao根据用户名查询用户
存在,返回false
不存在,调用dao保存用户信息

Dao:
1.根据用户名查询用户信息 findByUsername(string username);
2.保存用户信息 save(User user)

异步Ajax提交表单:
$(this).serialize()将表单中的数据提交成 username=xxx&&password=123 的格式
使用异步提交是为了获取服务器响应的数据,前台使用html作为视图层,不能直接从servlet相关的域对象获取值,只能通过Ajax获取

**

在编写的时候,写错了一个愚蠢的问题,导致无法访问主页,就是注释名称写错了,webServlet写成了webFilter导致无法访问网页404

**

login.jsp

简单的jquery登录验证

<script type="text/javascript">
        //检查用户名格式
        function checkUsername() {
            var username = $("#username").val();
            var reg_username = /^[A-Za-z_0-9]{4,20}$/;
            var flag = reg_username.test(username);
            if(flag){
                $("#username").css("border","");
            }
            else{
                alert("用户名格式错误");
                $("#username").css("border","1px solid red");
                //$("#addusername").html("用户名格式错误"); //要记得添加一个新的html格式
            }
            return flag;
        }
        //检查密码格式
        function checkPassword(){
            var password = $("#password").val();
            var reg_password = /^[A-Za-z_0-9]{4,20}$/;
            var flag = reg_password.test(password);
            if(flag){
                $("#password").css("border","");
            }
            else{
                alert("密码格式错误");
                $("password").css("border","1px solid red");
                //$("#addusername").html("用户名格式错误"); //要记得添加一个新的html格式
            }
            return flag;
        }
        //提交时检查是否正确
        $(function () {
            $("#form").submit(function () {
                if(checkPassword()&&checkUsername()){
                    return true;
                }
                return false;
            })
            //失去焦点时,判断格式
            $("#username").blur(checkUsername);
            $("#password").blur(checkPassword);
        })
    </script>

在body中添加form表单将值传入Servlet

<form id="form" name="form" action="indexServlet">
        <div>
            用户名:
            <input type="text" id="username" name="username" placeholder="请输入用户名">
        </div>
        <div>
            密码:
            <input type="text" id="password" name="password" placeholder="请输入密码">
        </div>
        <div>
            <input type="submit" id="login" name="login" value="登录">
        </div>
    </form>

可以用${error}来接收后台传递的错误信息

<!--得到从后台得到的错误信息-->
<div>${error}</div>

LoginServlet

//设置编码
req.setCharacterEncoding("utf-8");
//获取用户输入的数据
String username = req.getParameter("username");
String password = req.getParameter("password");

//判断用户名和密码是否正确
if(username.equalsIgnoreCase("zhangsan")&&password.equalsIgnoreCase("123456")){
    //用户名和密码正确,跳转至主页面
    req.getRequestDispatcher("/home.jsp");
}else{//用户名和密码错误,存储错误信息
    req.setAttribute("error","用户名或密码错误");
    //携带错误信息,转发到登录页面
    req.getRequestDispatcher("/index.jsp").forward(req,resp);
 }

五、注册页面的邮件激活

原因:为了保证用户填写的邮箱是正确的。可以推送广告
发送邮件:利用emailutil工具类编写
激活邮件:
激活对于数据库来说,就是将status 状态改为激活态
邮件激活分析:
在这里插入图片描述
不要再return下写代码,Java报unreachable statement错误
详细看连接:https://blog.csdn.net/qq_33915826/article/details/79246482

六、登录

在这里插入图片描述
登录之后,动态展示个人用户名称

header.html

<script>
        $(function () {
            $.get("findUserServlet",{},function (data) {
                //{uid:1,name:"yangcichen"}
                var msg = "欢迎回来,"+data.name;
                $("#span_username").html(msg);
            })
        })
</script>

异步交互
当页面整个访问完成之后,用ajax访问服务器查询出信息

在这里插入图片描述

七、退出

首先,应该思考一下,什么时候称作登录成功?
登录成功,就是session中有user
那么退出功能实现:
header.html

<a href="javascript:location='exitServlet';">退出</a>

1.访问servlet,将session销毁

req.getSession().invalidate();

2.跳转到登录界面跳转页面,采用重定向(路径写法为虚拟目录)

resp.sendRedirect(req.getContextPath()+"/login.html");

八、优化Servlet——BaseServlet

优化方式:减少servlet的数量,将其优化为一个模块一个Servlet

写一个模块servlet 让各个功能的servlet继承
模块servlet继承HTTPServlet

“this”–谁调用我,我代表谁

报错说明没有匹配的方法:
在这里插入图片描述
原因:方法的声明为protected,访问的时候没有权限
解决方法:

①在访问的时候忽略访问权限修饰符,此方法会忽略所有的方法

//忽略访问权限修饰符
Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//执行方法
//暴力反射
method.setAccessible(true);
method.invoke(this,req,resp);

②直接将方法权限修饰符改为public,这有利于其他的私有方法被保护

又犯了一个低级错误——findOne名称写错,导致浏览器找不到

九、旅游数据的显示

分类数据展示:
原来是假数据,后期通过从后台动态生成

<div class="navitem">
     <ul 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>

数据库中信息:
在这里插入图片描述
进行代码优化:页面分类数据在每一次页面加载后都会重新要求数据库来加载,对数据库的压力比较大,而且分类的数据不会经常产生变化,所以可以用redis来缓存这个数据。
在这里插入图片描述
期望数据库中存储的顺序,就是展示的数据

十、旅游线路分页展示

点击了不同的分类后,看到的旅游路线不一致。
分类和旅游线路是一对多
在这里插入图片描述
如何携带cid:

	//后台service
 	Set<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1);
	//2.判断查询的集合是否为空
	List<Category> cs=null;
	//2.1为空,第一次访问
	if(categorys==null||categorys.size()==0){
	    //从数据库查询
	     cs = categoryDao.findAll();
	     //将集合存储到redis中的category的key
	    for (int i = 0; i < cs.size(); i++) {
	        //存储zadd
	        jedis.zadd("category",cs.get(i).getCid(),cs.get(i).getCname());
	    }
	}else{
	    //2.2不为空,将set数据存入list
	    //前端需要List,但是此方法中返回set,进行格式转换
	    cs=new ArrayList<Category>();
	    for (Tuple tuple:categorys) {
	        Category category = new Category();
	        category.setCname(tuple.getElement());
	        category.setCid((int)tuple.getScore());
	        cs.add(category);
	    }
	}

前端:

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;
}

如何取cid:

<script>
    $(function () {
        var search = location.search;
        //alert(search);
        //切割获取到的字符串[?cid=5] 拿到5
        var cid = search.split("=")[1];
    })
</script>

根据cid获取不同的旅游线路数据:
在这里插入图片描述

十一、旅游线路名称查询

1.查询参数的传递
通过从route_list?cid=5 传递 route_list?cid=5&rname=xxx
传递xxx
首先获取到用户输入的rname

/*header.html*/
$("#search-button").click(function () {
       //后台根据这个名称进行模糊匹配
       var rname = $("#search_input").val();
       //alert(rname);
       var cid = getParameter("cid");
       //alert(cid);
       //跳转路径http://localhost/travel/route_list.html?cid=5
       //再拼接上rname=xxx
       location.href="http://localhost/travel/route_list.html?cid="+cid+"&rname="+rname;
})
/*route_list.html*/
//getParameter()方法为自己封装的字符切割函数
//获取cid
var cid = getParameter("cid");
//获取rname
var rname = getParameter("rname");
if(rname){
    //解码方法,获取到的rname为url需要解码
    rname=window.decodeURIComponent(rname);
}

2.修改之前的后台代码
Servlet、Service、Dao

tomcat7 从前端传值到后台乱码,解决办法:

//tomcat7,get请求出现乱码
rname = new String(rname.getBytes("iso-8859-1"),"utf-8");

在这里插入图片描述

出现了直接点击相关路线切换线路查询不到数据的问题:
在这里插入图片描述
传值load(5,2,‘null’)

解决办法链接
当rname为空时,前端传给RouteServlet的是“null”字符串,而不是null
所以在RouteDaoImpl中的判断参数是否有值的地方把rname当成“null”关键词(有值)来查询,而数据库没有关键词为“null”的旅游路线,所以返回0条记录,产生错误。
与之前判断为cid为’‘null’'时,有相似之处。

十二、查看旅游路线详情展示

在这里插入图片描述
出现图片展示有误:
在这里插入图片描述
通过前端断点调试发现标签使用了style="display:none;属性
如果删除其属性,图片可以正常显示,但是显示的数据css不正确
判断一下i 即每页的展示显示4个,超过4个进行隐藏

//遍历routeImgList
for (var i = 0; i < route.routeImgList.length; i++) {
   if(i>=4){
       var 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 {
       var astr='<a title="" class="little_img" data-bigpic="'+route.routeImgList[i].bigPic+'" >\n' +
           '             <img src="'+route.routeImgList[i].smallPic+'">\n' +
           '             </a>'
   }

   ddstr+=astr;
}

十三、旅游路线收藏功能

页面加载完成后,发送ajax请求,查询数据库查看用户是否收藏过该线路
根据查询结果展示不同的样式
在这里插入图片描述
收藏字数的动态展示
点击收藏按钮:
在这里插入图片描述
给按钮绑定单击事件,点击了按钮调用js中的addFavorite()方法:

<a class="btn" id="favorite" onclick="addFavorite();"><i class="glyphicon glyphicon-heart-empty" ></i>点击收藏</a>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值