- 视频+资料+笔记【链接:https://pan.baidu.com/s/127I2oA8zvhTECCmC6wMSmQ 提取码:zjxs】
- JavaWeb图书管理系统【bookEstore文档】
- JavaWeb图书管理系统【源码 + 效果展示】
- JavaWeb图书管理系统day01【2014.09.27】
- JavaWeb图书管理系统day02【2014.09.28】
- JavaWeb图书管理系统day03【2014.09.29】
目录
一、生成订单
1.生成订单
1.showCart.jsp页面,点击结算会生成订单
2.会跳转到order.jsp页面,在页面展示我们订单中的信息
需要输入一上订单的收货地址
生成订单的代码实现:
1.在order.jsp页面表单会向 ${pageContext.request.contextPath}/order提交
表单中有一个隐藏域 <input type="hidden" name="method" value="add">
2.在 OrderServlet中有一个add方法,它是订单添加操作
订单的添加注意事项:
当订单生成后,需要对以下的表进行操作
1.订单表中要插入数据
2.商品表中的商品数量要进行修改(修改商品的库存)
3.订单与用户之间也存在关系,添加订单时,也需要得到当前用户的id
以上操作需要进行事务控制。
1.获取Connection时,要使用同一个,需要在DataSourceUtils中
对获取Connection对象操作进行修改,将其放入到ThreadLocale中
2.Dbutils
QueryRunner 直接使用带参数的,参数类型是DataSource类型。
new QueryRunner(DataSource ds);这个操作,在调用update,query方法,
一般不会带Connection参数,这样,它就是一条sql一个事务。
而现在,我们需要事务管理,所以我们在使用QueryRunner时,就会
不带参数 new QueryRunner(),而使用带Connection参数的update、query方法。
---------------------------------
要注意:订单要包含商品信息,这时就需要从session中获取购物车,将购物车中的信息封装Order对象中。现在,我们需要事务控制,所以我们在service层进行了事务的开启。
在添加订单项时,使用了批处理,因为订单与商品之间存在多对多关系,
那么,我们的中间表orderItem,它就有可能有多条数据,所以我们使用了QueryRuner的batch方法完成添加订单项操作。
注意:当我们操作完成后,一定要将Connection对象从ThreadLocale中remove掉。
二、查看订单
2.查看订单
查看订单,会根据用户的role去显示出不同的订单。
如果role=admin,它查询出所有的订单
如果role=user,它只查询出当前用户的订单
代码实现:
查看订单的入口:
1.在首页,提供了查看订单连接
2.当用户添加完成订单成功后,会显示查看订单操作
<a href="${pageContext.request.contextPath}/order?method=search">
1.当点击连接后会访问OrderServlet,并提交一个参数 method=search;
2.在OrderServlet会首先得到当前用户 request.getSession().getAttribute("user");
如果用户没有登录,会让它登录,如果用户登录了,会查看订单信息。
3.当调用dao中查询订单操作时,会根据当前用户的role进行不同的sql语句操作。
查询出订单后,订单中不包含商品信息,所以要根据订单的信息,在orderItem表与products表中查询出商品信息。4.查询出所有订单后,会得到一个List<Order>,将集合存储到request域中,
最后请求转发到showOrder.jsp页面,在页面上显示出所有查询出的订单。
三、订单的取消与支付
3.订单的取消与支付
1.支付操作
使用了在线支付操作 epay第三方支付平台.
在显示订单页面上showOrder.jsp页面,显示订单信息中,包含了当前支付状态。
会显示 "已支付" "未支付",如果是未支付,会有一个连接访问pay.jsp页面,
并将当前订单的id,以及当前订单的金额传递到pay.jsp页面。
1.在pay.jsp页面上可以选择银行,表单提交时,将订单编号,金额,以及银行,提交到OnlinepayServlet中。
2.在OnlinePayServlet中完成请求参数封装
3.第三方支付,会根据你提交的请求参数 p8_Url 向这个路径发送信息,
4.可以指定p8_url为CallbackServlet,那么我们在servlet中就可以得到支付结果信息
5.通过判断信息是否正确,以及r9_BType=1 r9_BType=2 可以知道,是否支付成功
6.当判断支付成功后,我们要修改订单的状态。
1.在orders表中有一个字段,paystate=0 代表未支付,我们支付成功后,要修改订单的状态。
paystat=1,这个代表订单已对付。
2.修改订单状态要根据订单编号修改,在返回的支付结果信息中r6_Order,它就代表了我们的订单编号。
---------------------------------------------
2.订单取消
在显示订单的页面上,会提供一个删除订单的链接。
1.录取消订单时,这个超连接会携带当前订单的编号传递到服务器端。
<a href="${pageContext.request.contextPath}/order?method=del&id=${order.id}">取消订单</a>
2.这个链接会访问OrderServlet,并且 method=del id=订单编号
3.OrderServlet中会根据传递method 判断 执行 取消订单操作,会根据id知道要删除哪一个订单。
4.删除订单注意事项
1.删除订单要将orders表中数据删除---根据id删除。
2.需要删除orderItem表中数据。
3.需要修改商品的数量,也就是说需要对products表进行update操作。
代码:
1.根据订单id在orderitem表中查询出相关的商品信息.
2.修改商品信息
3.删除订单项信息
4.删除订单.
以上操作,也需要进行事务控制。
四、权限控制
4.权限控制
当前系统有三种用户:
1.游客 ---- 查看商品
2.user ---- 查看商品 生成订单 查看订单
3.admin ----- 下载榜单 添加商品.
权限控制---使用annotation + 动态代理完成操作.对数据库进行修改
users表中的role字段作为一个外键
添加一个role表,这个表中有相关用户角色信息
create table role(
role varchar(100) primary key
)
users表中的role字段是一个外键,依赖于role表中的role字段.
create table privileges(
id int primary key auto_increment,
name varchar(20) 权限名称
)
角色与权限之间存在多对多对象
有一个中间表
create table userprivilege(
privilege_id int,
role varchar(100),
primary key(privilege_id,role),
foreign key userprivilege(privilege_id) references privileges(id),
foreign key userprivilege(role) references role(role)
)
-----------------------------------------
1.做一个注解
@Retention(RetentionPolicy.RUNTIME) //说明当前注解在runtime阶段有效果
@Target(ElementType.METHOD) //当前注解是在方法上使用的
@Inherited //当前注解具有继承性
public @interface PrivilegeInfo {String value(); //权限名称
}
2.对所有的service层的类进行提取接口操作.
ProductServiceImpl 类---------->ProductService 接口
OrderServieImple类 ------------>OrderService接口.
在接口的方法上添加注解,注解中的value值,就是当前方法要执行,所需要的权限名称。
3.在servlet中得到的service对象,我们不直接new出来,可以针对每一个Service提供一个工厂,
在工厂中生产对应的service对象,并且,返回的是代理对象。OrderServiceFactory
ProductServiceFactory
它们用于生产不同的service对象
在工厂中创建出对应的service对象,在提供的getInstance()方法中,返回其代理对象。
这样我们在servlet中,就通过工厂获取service对象,得到的其实是代理对象。
4.在动态代理的InvocationHandler的invoke方法中进行权限控制。
1.得到当前方法上的注解
1.判断当前方法上是否有指定的注解
2.如果没有,代表这个操作不需要权限控制。
如果有,就会存在我们的注解。
3.得到方法上的注解,通过注解对象得到当前方法要执行时 所需要的权限名称。
4.得到注解后,还需要得到当前用户,好么我们在所有添加注解的方法上
添加了一个参数 User.
可以在invoke方法中通过args参数获取User对象.
5.可以判断当前用户是否存在,知道是否有权限操作。
1.如果用户不存在,throw new PrivilegeException();权限不足。
2.如果用户存在
1.根据user的role,在数据库中查询出用户所具有的所有的权限名称,
与注解上提供的权限名称对比。如果包含,那么具有权限;如果不包含,没有权限。
2.不包含 throw new PrivilegeException();权限不足。
包含 method.invoke();