第十七章 书城项目2

本文探讨了用户登录状态显示、注销功能、表单提交问题解决方案、验证码技术应用、购物车模块实现、订单流程、AJAX异步请求以及后台权限控制和错误处理策略。
摘要由CSDN通过智能技术生成

51.显示用户登录的信息

在这里插入图片描述
在这里插入图片描述
我们在登录之后,要在韩总这个位置,显示我们的登录昵称
在这里插入图片描述
一般我们会将登录名保存到request域中
但是这里不行
在这里插入图片描述
点击上面的我的订单的时候
这个界面还是再显示用户昵称的信息
在这里插入图片描述
我们应该将用户登录的信息保存在session中
在这里插入图片描述
在这里插入图片描述
首页这里也应该显示登录信息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果我们进行了登入
在这里插入图片描述

51.注销登录

在这里插入图片描述
我们先在服务器写一个方法来处理注销登录问题
在这里插入图片描述
在登入成功页面修改注销的地址
在这里插入图片描述
在首页也要改
在这里插入图片描述

52.表单重复提交的三种情况

在这里插入图片描述

第一种情况:

我们先创建一个tmp工程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们下面进行注册
在这里插入图片描述
注册成功
在这里插入图片描述
保存到数据库
在这里插入图片描述

这个时候用户点击F5刷新页面
数据库保存很多次
在这里插入图片描述

这个是我们使用重定向即可
在这里插入图片描述
此时我们F5刷新,用户名也只会保存一次
在这里插入图片描述

第二种情况:

在这里插入图片描述
我们通过延迟5秒来模拟一下这个效果
在这里插入图片描述
登录之后,发现没有立刻显示登录成功页面
用户就一直点
在这里插入图片描述
其实服务区已经插入了很多条记录
在这里插入图片描述

第三种情况:

在这里插入图片描述
将延迟注释掉
在这里插入图片描述

这里登录成功后
在这里插入图片描述
在这里插入图片描述
点击回退后,再次提交登录
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

53.验证码底层原理

上面重复提交的情况中,第一种有解决方法,但后面两种没有说,解决方法就是使用验证码
在这里插入图片描述

54.谷歌验证码的使用

在它的jar包中有一个kaptchaServlet的类
在这里插入图片描述
我们进行一下配置

在这里插入图片描述
下面改成一个图片,我们访问这个Servlet就会帮你生成验证码图片
而且这个验证码还会保存在session域中
在这里插入图片描述
验证码就出来了

在这里插入图片描述
我们每次刷新都会得到不同的验证码
在这里插入图片描述
下面我们在表单中使用img标签去显示验证码
在这里插入图片描述
在这里插入图片描述

下面我们在服务器获取验证码和客户端发送过来的验证码比较使用
首先我们找到验证码的key值
在这里插入图片描述
删除session之后,在发生提交点的情况,就不会提交成功了
在这里插入图片描述
在这里插入图片描述

55.将谷歌验证码加到书城中使用

先加入jar包
在这里插入图片描述
再配置
在这里插入图片描述
将地址换一下
在这里插入图片描述
在这里插入图片描述
下面调节一下大小
在这里插入图片描述
在这里插入图片描述

下面到服务器获取验证码并进行比较
在这里插入图片描述
在这里插入图片描述

56.验证码的切换

有时候我们会看不清验证码,我们实现点击验证码图片进行刷新
我们给验证码的img加上id
在这里插入图片描述

并且绑上单机事件
在这里插入图片描述
这样之后点击验证码就可以刷新了
在这里插入图片描述
在这里插入图片描述
这里就是对验证码的src路径重新赋值,赋值之后就重新发起一次请求,就会刷新
在这里插入图片描述

但有一个问题
我们在火狐浏览器或者Ei浏览器中,只能刷新一次就不能再刷新了
这是因为浏览器中做了缓存
在这里插入图片描述

我们每次给他加上一个不同的值
就会避开这个缓存的内容,这个不同的值就是时间戳
在这里插入图片描述

57.购物车模块的分析

在这里插入图片描述

58.购物车模型的创建

下面我们先创建购物车的商品项
在这里插入图片描述

下面是购物车对象
在这里插入图片描述

59.购物车功能方法的实现和测试

我们在Cart中添加这些功能方法
在这里插入图片描述
在这里插入图片描述

首先是添加商品项
为了方便接下来的操作,我们做一些修改
在这里插入图片描述
在这里插入图片描述
删除商品项
在这里插入图片描述

清空购物车
在这里插入图片描述

修改商品数量
在这里插入图片描述

我们前面其实不用定义两个变量,因为用不到
我们在下面的方法体中进行定义
在这里插入图片描述
得到总的商品数量
在这里插入图片描述

得到总金额
在这里插入图片描述

toString()方法也做一下修改
在这里插入图片描述

60.添加商品到购物车功能的实现

我们在首页点击 加入购物车 ,将请求发给CartServlet
下面我们先写一个CartServlet类
在这里插入图片描述

在给首页的 加入购物车 按钮加一个单机事件
在button标签中加入一个自定义属性bookId和class类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下面我们继续写CartServlet类的代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下面我们添加商品,添加第一个商品没有问题
添加第二个商品后,我们发现totalCount的数量还是1
这是因为我们每次new了一个新的Cart(相当于我们去超市买东西,第一件商品放了一个篮子。而后我们放第二件商品的时候,又拿了一个新篮子来放)
在这里插入图片描述

我们将购物车放到session域中
在这里插入图片描述

下面还有一个问题,最后一行的重定向
我在下面的第二页添加水平
最后还应该跳回第二页,而此时页面却跳回了第一页
在这里插入图片描述
我们购买完商品的时候应该跳回不同的地址
在这里插入图片描述
为了做到上面的说法
我们在点击 加入购物车的时候 需要将地址一起发给服务器
在这里插入图片描述
下面我测试一下这个referer
下面有两个地址,电子产品和纺织用品
在这里插入图片描述
在这里插入图片描述

下面我访问这两个地址
在这里插入图片描述
在这里插入图片描述
发现确实得到对应的地址
在这里插入图片描述
在这里插入图片描述
这样我们可以通过referer来让服务器跳回原来的页面
在这里插入图片描述

61.购物车的展示

将商品加入购物车之后,我们要在下面的页面,将购物车的数据展现出来
在这里插入图片描述
我们此时还没有关闭浏览器,我们在首页添加的商品全部存储在session域中
下面我们查看一下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面我们进行遍历操作
items是一个键值对,我们要取其中的值,要加上 .value
在这里插入图片描述
在这里插入图片描述
我们将上面的测试用的session给删除
在这里插入图片描述

上面我们展示的是有商品的情况,那么没有商品的情况是什么样子呢
我们将服务器停了
在这里插入图片描述
先在session域就是空的
购物车也是空
空的话,下面这里是没有必要输出的
在这里插入图片描述

最后一行我们要进行一个判断
在这里插入图片描述
最后我们再设置一下其中的值
在这里插入图片描述
在这里插入图片描述
下面我们继续优化一下
在这里插入图片描述
在这里插入图片描述

62.删除购物车的商品项

在这里插入图片描述
在这里插入图片描述
下面我们给删除操作加一点提示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

63.清空购物车的实现

在这里插入图片描述
在这里插入图片描述
我们同样给其加上提示
在这里插入图片描述
在这里插入图片描述

64.修改购物车商品数量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我们什么时候进行判断呢?
就是鼠标离开输入框的时候,我们对其绑上失去焦点事件
在这里插入图片描述

我进入输入框,再离开,这个事件就触发了
在这里插入图片描述

还有一个change事件
在这里插入图片描述
我们直接离开输入框是没有反应的
当我们改变输入框的内容时,就会响应
(如果我们单纯使用失去焦点事件,那这个判断的输入框的内容是否发生变化是要我们自己来完成的)
我们这里就可以省去判断了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我们这里需要将商品的编号和数量一起发送给服务器
在这里插入图片描述
我们将这个bookId转换为jQuery对象,然后将其发在链接中,一起发送给服务器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

65.首页购物车数据展示

我们要在这里回显
购物车中总的商品数量和最后一件商品的名称
在这里插入图片描述

有很多方法,比如我们可以给购物车添加一个属性来记录最后一个添加的商品
也可以用session来记录最后一个商品
我们这里放到session中
在这里插入图片描述
在这里插入图片描述
如果我们清空了购物车
再回到这个界面
这里还是显示了最后一个商品
在这里插入图片描述
我们做一个修改,加一个判断
在这里插入图片描述
在这里插入图片描述

66.订单模块的分析

在这里插入图片描述
在这里插入图片描述

67.创建订单模型的数据库表

在这里插入图片描述

67.编写订单模块的两个数据类型Order和OrderItem

在这里插入图片描述
在这里插入图片描述

68.编写订单模块的Dao和测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

69.编写订单模块的service和测试

在这里插入图片描述
在这里插入图片描述
为了确保订单编号的唯一性
我们用时间戳加用户编号来作为订单编号(单独使用时间戳的话,如果很多用户同时提交会导致订单编号的不唯一)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

70.结账功能实现,生成订单

在这里插入图片描述
生成订单,是我们在点击 去结账 的时候,生成订单
在这里插入图片描述
得到订单
在这里插入图片描述
这个过程是先访问orderServlet程序,然后将订单号保存在session域中
最后显示在这个界面上面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

71.解决生成订单的bug

最后为了防止表单重复提交
我们使用重定向来代替请求转发
由于重定向不支持request域的共享
我们的orderId就不能保存在request域中
我们将其保存在session域中
在这里插入图片描述
在这里插入图片描述

第二个
当我们结账之后,商品首页的库存和销量应该有所变化

首先获取bookDaoImpl
在这里插入图片描述

每当我们生成一个订单项的时候,我们就要更新库存和销量
在这里插入图片描述

在这里插入图片描述

72.使用Filter过滤器实现后台的权限管理

我们要对这里manager下的内容进行权限管理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当这里user为空的时候,说明没有登录
需要跳转到登录界面
在这里插入图片描述
下面进行一下配置
在这里插入图片描述
此时如果用户还没有登录,我们就点击后台管理的话
在这里插入图片描述

它会跳转到登录页面
在这里插入图片描述

但是对于一些老手而言
在这里插入图片描述
它还是可以直接跳转到管理页面中
在这里插入图片描述
所有下面两个地址我们都需要拦截
在这里插入图片描述
在这里插入图片描述

73.使用Filter和ThreadLocal组合管理事务

在这里插入图片描述
在这里插入图片描述

下面我们具体化一下
这里Hashtable是线程安全的map
在这里插入图片描述

Random可以用来取数据数
这里的random.nextInt(1000)可以取代0-999中的随机一位数字
在这里插入图片描述
在这里插入图片描述

下面我们在主方法中生成3个线程
每一个线程都会生成一个随机数进行绑定
在这里插入图片描述
在这里插入图片描述

如果我们实际地做一些操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们还可以进一步操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

只要是我们的线程关联的数据,不管我们的代码层级调用有多深,不影响数据传递到其中的任何一个代码中获取

ThreadLocal也可以实现这样一个数据关联的效果
下面我们看看threadLocal的实现
ThreadLocal的key是由自己生成的,就是当前线程
在这里插入图片描述
在这里插入图片描述
下面是存数据
在这里插入图片描述

下面是取数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看见换成ThreadLocal同样可以达成这样的效果
在这里插入图片描述

ThreadLocal只能存一个数据
如果我们先存储了一个数据abc,后面又存储了一个数据bbj那么取出来的会是哪个数据呢
在这里插入图片描述
都是bbj,以最后一个为准
在这里插入图片描述

如果我们要关联多个数据

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

74.使用ThreadLocal确保所有的操作都使用同一个Connection来实现事务管理

我们在购物车买完东西去结账,数据库就会将订单和订单项生成并保存,同时会修改库存和销量,上述的操作是在结账后一次性完成的
如果我们在操作的过程中,出现了一个错误堵截了所有操作的全部成功
在这里插入图片描述
我们下面的订单已经保存成功了(因为这个错误是在保存订单之后的)
在这里插入图片描述

但是其中的订单项什么都看不见
在这里插入图片描述
这个时候用户钱已经付了
但店家只能看订单,看不见商品,店家无法发货
这个时候我们就希望,保存订单,订单项还有库存的修改等操作是一次性成功的
这里我们就需要用到数据库的事务
在这里插入图片描述

具体做法
我们先在JDBCUtils工具类中新增一个属性ThreadLocal
在这里插入图片描述

下面的得到连接的方法要做调整
原来的:
在这里插入图片描述

现在的:
我们第一次取conn的时候是空的
我们第二次取就有值了
这样就确保了我们使用的是同一个连接
在这里插入图片描述

下面的关闭连接的方法同样要修改:
原来的:
在这里插入图片描述

现在的:
改为下面两个方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

回滚操作与提交操作其实差不多
在这里插入图片描述
然后在baseDao中
每一个获取连接的地方都要改一下
首先将连接关闭去掉
如果执行一个操作就关闭一次连接,后面的两个操作就不能得到连接了
在这里插入图片描述
只能在提交事务或者回滚事务的时候关闭连接
还有在捕获异常之后,必须将异常抛出去(如果在saveOrder的时候出了异常,后面两个操作不知道,无法捕获异常,后续操作无法进行。有异常要将异常抛出,捕获后才好回滚事务)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后,我们要给orderService.createOrder方法try-catch
在这里插入图片描述

75.使用Filter统一给所有service方法都加上try-catch来管理事务

在这里插入图片描述
在实际的项目开发中
我们有很多很多的service,每个service下面也会有很多很多的方法,每个方法都有需要用到事务的情况
我们要给每一个方法都加上try-catch
逐个添加太麻烦
我们需要找一个一次性给所有方法都加上try-catch的方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里的try-catch就可以删除了
在这里插入图片描述
还有要注意
下面的baseServlet捕获异常后
还要继续抛出,不然后面的无法接受到异常,会导致失败
在这里插入图片描述
因为baseServlet程序在这里
这里将异常消化了
后面的回滚是收不到异常的
在这里插入图片描述

76.使用Tomcat统一管理异常,展示友好的错误界面

在这里插入图片描述
在这里插入图片描述
在点击完去结账之后,页面是一片空白
页面上面没有任何的类似于支付成功或者支付失败的提示
这样十分的不友好
我们应该给用户一些友好的提示
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
此时页面还是一片空白
在这里插入图片描述
因为异常在这里没被捕获了
没有抛给Tomcat
在这里插入图片描述
此时就会跳转了
在这里插入图片描述
上面是错误的500的跳转
我们常见的错误还有404
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

77.使用AJAX请求验证用户名是否可用

在这里插入图片描述
我们要在输入完用户名之后,后台会立刻接受到这个输入的用户名来验证用户名是否可用
在这里插入图片描述

我们找到用户名输入框的id
在这里插入图片描述
给其绑上失去焦点事件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里记得将参数username一起传递过去
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
存在的话existsUsername为true
不存在为false
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

78.使用AJAX请求修改添加商品到购物车的实现

原来我们在首页点击添加商品到购物车之后,是给整个页面刷新发起请求的
但是实际的开发过程中,加入购物车这种操作基本都是使用AJAX请求来完成的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后我们需要什么就返回什么
在这里插入图片描述
我们需要的是总的商品数量和最后一件添加的商品
在这里插入图片描述

我们下面不在使用刷新页码的方式来发起请求
使用AJAX来发起请求
我们先将返回的数据输出到控制台观察一下
在这里插入图片描述
在这里插入图片描述
有中文乱码问题,下面解决一下
在这里插入图片描述
在这里插入图片描述
我们只要拿这个数据在页面上面做局部更新即可
更新的地方就是下面(有个报错,id一样了)
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值