网站分为前台和后台。前台为用户使用,后台为管理员管理。
前台:
用户模块
-注册
-激活:通过电子邮件
-登陆
-退出
图书的分类模块
-查询图书的分类显示在页面上
例如:文学书,动漫书之类
图书模块
-查询所有图书
-分类查询图书
-查询图书详情(按图书编号查询)
购物车模块
-添加商品
-清空购物车
-删除指定商品
-我的购物车(按用户查询购物车)
订单模块
-生成订单
-我的订单(按用户查询订单)
-确认收货
-付款功能
后台
管理员模块:
-登录
图书分类管理模块
-添加分类
-查看分类
-删除分类
-修改分类
图书管理模块
-查看所有图书
-按图书编号查询
-修改图书
-删除图书
-添加图书
订单模块
-查询所有订单
-按订单状态查询(未付款,未发货之类的)
-发货
1.导包
数据库相关:数据库驱动,c3p0连接池(jar包和配置文件),DBUtils
邮箱相关:JavaMail,activation
上传相关:commons-fileupload,commons-io
其他依赖包 commons-logging
我们自己制作的工具类等
2.创建package
用户模块
domain
dao
service
web
分类模块
domain
dao
service
web
图书模块
domain
dao
service
web
购物车模块
domain
dao
service
web
订单模块
domain
dao
service
web
3.创建数据库表
/*创建数据库*/
CREATE DATABASE bookstore;
/*创建用户表*/
CREATE TABLE user(
uid CHAR(32) PRIMARY KEY,/*主键*/
username VARCHAR(50) NOT NULL,/*用户名*/
`password` VARCHAR(50) NOT NULL,/*密码*/
email VARCHAR(50) NOT NULL,/*邮箱*/
`code` CHAR(64) NOT NULL,/*激活码*/
state BOOLEAN/*用户状态,有两种是否激活*/
);
/*创建图书分类表*/
CREATE TABLE category (
cid CHAR(32) PRIMARY KEY,/*主键*/
cname VARCHAR(100) NOT NULL/*分类名称*/
);
/*向图书分类表插入三条记录*/
INSERT INTO category(cid,cname) VALUES ('1','JavaSE');
INSERT INTO category(cid,cname) VALUES ('2','JavaEE');
INSERT INTO category(cid,cname) VALUES ('3','Javascript');
/*创建图书表*/
CREATE TABLE book (
bid CHAR(32) PRIMARY KEY,/*主键*/
bname VARCHAR(100),/*图书名*/
price DECIMAL(5,1),/*单价*/
author VARCHAR(20),/*作者*/
image VARCHAR(200),/*图片*/
cid CHAR(32),/*所属分类*/
FOREIGN KEY (cid) REFERENCES category(cid)/*建立主外键关系*/
);
/*向图书表插入几条记录*/
INSERT INTO book VALUES ('1','Java编程思想(第4版)','75.6','qdmmy6','book_img/9317290-1_l.jpg','1');
INSERT INTO book VALUES ('2','Java核心技术卷1','68.5','qdmmy6','book_img/20285763-1_l.jpg','1');
INSERT INTO book VALUES ('3','Java就业培训教程','39.9','张孝祥','book_img/8758723-1_l.jpg','1');
INSERT INTO book VALUES ('4','Head First java','47.5','(美)塞若','book_img/9265169-1_l.jpg','1');
INSERT INTO book VALUES ('5','JavaWeb开发详解','83.3','孙鑫','book_img/22788412-1_l.jpg','2');
INSERT INTO book VALUES ('6','Struts2深入详解','63.2','孙鑫','book_img/20385925-1_l.jpg','2');
INSERT INTO book VALUES ('7','精通Hibernate','30.0','孙卫琴','book_img/8991366-1_l.jpg','2');
INSERT INTO book VALUES ('8','精通Spring2.x','63.2','陈华雄','book_img/20029394-1_l.jpg','2');
INSERT INTO book VALUES ('9','Javascript权威指南','93.6','(美)弗兰纳根','book_img/22722790-1_l.jpg','3');
/*创建订单表*/
CREATE TABLE orders (
oid CHAR(32) PRIMARY KEY,/*主键*/
ordertime DATETIME,/*订单生成时间*/
total DECIMAL(10,0),/*订单合计*/
state SMALLINT(1),/*订单状态:未付款、已付款但未发货、已发货但未确认收货、收货已结束*/
uid CHAR(32),/*订单的主人*/
address VARCHAR(200),/*订单的收货地址*/
FOREIGN KEY (uid) REFERENCES USER (uid)/*建立主外键关系*/
);
/*创建订单项表*/
CREATE TABLE orderitem (
iid CHAR(32) PRIMARY KEY,/*主键*/
COUNT INT,/*数量*/
subtotal DECIMAL(10,0),/*小计*/
oid CHAR(32),/*所属订单*/
bid CHAR(32),/*订单项所指的商品*/
FOREIGN KEY (oid) REFERENCES orders (oid),/*建立主外键关系*/
FOREIGN KEY (bid) REFERENCES book (bid)/*建立主外键关系*/
);
创建相关类
-在domain包下创建user类
-dao包创建UserDao类
-service包创建UserService类
-web.servlet包下创建UserServlet
------------------------------注册功能分析-----------------------------------------
流程分析:
注册页面regist.jsp : 请求UserServlet的注册方法,发送表单里的数据
UserServlet#regist():将表单数据封装到user对象中
对数据进行校验,如果数据有误,将表单数据和错误信息转发回regist.jsp 页面
调用Service层的regist()方法,传递user对象
-如果抛出异常,将异常信息和表单数据转发到regist.jsp中,为了回显
-如果成功注册,发送激活邮件(收件人,发件人,主题,内容),发送成功保存成功信息转发到msg.jsp中。邮件内容应该包含一个用来激活的url,链接中要有激活码。
UserService#regist(User user):
校验用户名是否被注册,如果注册,抛出自定义异常
校验邮箱是否被注册,如果注册,抛出自定义异常
把user插入到数据库中
UserDao:
findByUsername(String username):按用户名查询
findByEmail(String email):按email查询用户
void add(User user):插入用户到数据库中
-----------------------------激活功能分析-----------------------------------
流程分析:
注册成功后向用户邮箱发送一封激活邮件,里面包含一个URL地址,携带了用户的激活码。
UserServlet#activate():
获取激活码参数,调用service层的activate(String code)激活方法
出现异常,保存异常信息转发到msg页面
激活成功,保存成功信息转发到msg页面
UserService#activate(String code):
使用激活码去查找数据库,得到user对象
数据库返回null,抛出异常
如果用户的状态为已激活,抛出异常
如果用户状态为未激活,则修改用户状态为true,激活状态
UserDao:
findByCode(String code):通过激活码查找用户
updateState(String uid,boolean state):修改用户状态
------------------------------登录功能分析-----------------------------------
流程分析:
login.jsp:一个表单,包含账号密码
UserServlet#login():
将用户名和密码封装成user对象
校验用户名和密码
调用service层的login方法
如果出现异常就保存异常信息到request中,转发回login.jsp页面
如果登录成功,就保存用户信息到session中,重定向到主页
UserService#login(User user):
使用username查询数据库,得到user对象。
如果结果为null,抛出用户不存在异常。
如果存在该用户,比较表单中的用户密码和数据库中的密码是否相同
如果不同抛出异常
查看用户状态,如果用户状态未激活,抛出异常。
前面全部成功,返回user对象。
UserDao:
findByUsername():根据用户名查找用户
----------------------退出功能分析-------------------------------------------
UserServlet#quit()
:调用session的invalidate()方法销毁用户session,然后返回主页即可
代码实现
domain包下的User类
public class User {
private String uid; //用户id,主键
private String username; //用户名
private String password; //密码
private String email; //邮箱
private String code; //激活码
private boolean state; //用户状态,是否激活
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public boolean isState() {
return state;
}
public void setState(boolean state) {
this.state = state;
}
@Override
public String toString() {
return "User [uid=" + uid + ", username=" + username + ", password=" + password + ", email=" + email + ", code="
+ code + ", state=" + state + "]";
}
}
登录和注册页面
UserServlet
我们继承我们以前编写的BaseServlet,来方便我们使用反射操作。
public class UserServlet extends BaseServlet {
//依赖service层
private UserService userservice=new UserService();
//生成UUID的方法
public String UUID(){
return UUID.randomUUID().toString().replaceAll("-", "");
}
//注册功能
public String regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取表单数据,封装成user对象
String username=request.getParameter("username");
String password=request.getParameter("password");
String email=request.getParameter("email");
User user=new User();
user.setUsername(username);
user.setPassword(password);
user.setEmail(email);
user.setUid(UUID());
user.setCode(UUID()+UUID());
//对表单数据进行校验,错误信息存放在map集合中
Map errors=new HashMap();
//校验用户名
if(username==null||username.trim().isEmpty()){
errors.put("username", "用户名不能为空");
}else if(username.length()<5||username.length()>=16)
{
errors.put("username", "用户名必须在6-15位之间");
}
//校验密码
if(password==null||password.trim().isEmpty()){
errors.put("password", "密码不能为空");
}else if(password.length()<5||password.length()>=16)
{
errors.put("password", "密码必须在6-15位之间");
}
//校验邮箱
if(email==null||email.trim().isEmpty()){
errors.put("email", "邮箱不能为空");
}else if(!email.matches("\\w+@\\w+\\.\\w+"))
{
errors.put("email", "邮箱错误");
}
//判断是否有错误,有的话就将表单数据(为了回显)和错误信息转发到注册页面
if(errors.size()>0){
request.setAttribute("errors", errors);
request.setAttribute("formuser", user);
return "forward:/jsps/user/regist.jsp";
}
//没错误就调用service层的regist方法
try {
userservice.regist(user);
} catch (UserException e) {
//抛出异常的话就将异常信息保存在request中,转发到注册页面
request.setAttribute("msg", e.getMessage());
request.setAttribute("formuser", user);
return "forward:/jsps/user/regist.jsp";
}
//注册成功就发送邮件,我们将邮件的一些参数放在配置文件中
Properties prop=new Properties();
//加载邮件相关配置文件prop.load(this.getClass().getClassLoader().getResourceAsStream("email.properties"));
String host=prop.getProperty("host"); //获取邮箱主机
String ename=prop.getProperty("ename"); //获取邮箱用户名
String epasswd=prop.getProperty("epasswd");//获取用户密码
String from=prop.getProperty("from"); //获取发件人
String to=user.getEmail(); //获取收件人
String subject=prop.getProperty("subject");//获取邮件主题
String content=prop.getProperty("content");//获取邮件内容
content=MessageFormat.format(content, user.getCode());
Properties props = new Properties();
props.setProperty("mail.host", host);//设置服务器主机名
props.setProperty("mail.smtp.auth", "true");//设置需要认证
Authenticator auth = new Authenticator() {
public PasswordAuthentication getPasswordAuthentication () {
return new PasswordAuthentication(ename, epasswd);//用户名和密码
}
};
Session session=Session.getInstance(props, auth);
MimeMessage msg=new MimeMessage(session); //获取MimeMessage对象
try{
msg.setFrom(new InternetAddress(from)); //设置发件人
msg.setRecipients(RecipientType.TO, to); //设置收件人
msg.setSubject(subject); //设置主题
msg.setContent(content, "text/html;charset=utf-8"); //设置正文
Transport.send(msg); //发送邮件
}catch (Exception e) {
throw new RuntimeException(e);
}
request.setAttribute("msg", "恭喜注册成功。请到邮箱激活");
return "forward:/jsps/msg.jsp";
}
//激活方法
public String activate(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取激活码
String code=request.getParameter("code");
try {
//调用service的激活方法,成功就保存成功信息转发到msg页面
userservice.activate(code);
request.setAttribute("msg", "恭喜您,激活成功");
return "forward:/jsps/msg.jsp";
} catch (UserException e) {
//出现异常就保存异常信息转发到msg页面
request.setAttribute("msg",e.getMessage());
return "forward:/jsps/msg.jsp";
}
}
//登录功能
public String login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取登录的账号密码,并封装
String username=request.getParameter("username");
String password=request.getParameter("password");
User user=new User();
user.setUsername(username);
user.setPassword(password);
Map errors=new HashMap();
//校验用户名
if(username==null||username.trim().isEmpty()){
errors.put("username", "用户名不能为空");
}else if(username.length()<5||username.length()>=16)
{
errors.put("username", "用户名必须在6-15位之间");
}
//校验密码
if(password==null||password.trim().isEmpty()){
errors.put("password", "密码不能为空");
}else if(password.length()<5||password.length()>=16)
{
errors.put("password", "密码必须在6-15位之间");
}
if(errors.size()>0){
request.setAttribute("errors", errors);
request.setAttribute("formuser", user);
return "forward:/jsps/user/login.jsp";
}
//如果登录成功,就将用户信息保存在session中,否则保存错误信息返回登陆页面
try {
User _user=userservice.login(user);
request.getSession().setAttribute("sessionuser", _user);
request.getSession().setAttribute("cart", new Cart());
return "redirect:/index.jsp";
} catch (UserException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("formuser", user);
return "forward:/jsps/user/login.jsp";
}
}
//退出功能
public String quit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().invalidate();
return "redirect:/index.jsp";
}
}
UserService :处理业务逻辑
public class UserService {
//依赖dao层
private UserDao userdao=new UserDao();
//注册功能
public void regist(User formuser) throws UserException{
//调用dao层方法校验用户名是否被注册,如果已注册抛出自定义异常
User user=userdao.findByUsername(formuser.getUsername());
if(user!=null) throw new UserException("用户名已被注册");
//校验邮箱是否被使用,如果已使用抛出自定义异常
user=userdao.findByEmail(formuser.getEmail());
if(user!=null) throw new UserException("邮箱已被使用");
//添加用户
userdao.addUser(formuser);
}
//激活功能
public void activate(String code) throws UserException{
//根据激活码查找用户
User user=userdao.findByCode(code);
//如果为空,抛出用户不存在异常
if(user==null) throw new UserException("用户不存在");
//不为空,如果用户状态为未激活,则将状态设置为激活
if(user.isState()==false) userdao.updateState(user.getUid(), true);
//如果已激活,则抛出异常
else throw new UserException("用户已经激活,请勿重复激活");
}
//登录功能
public User login(User formuser) throws UserException{
//判断用户是否存在,如果不存在抛出自定义异常
User user=userdao.findByUsername(formuser.getUsername());
if(user==null) throw new UserException("用户不存在");
//判断用户输入的密码是否和数据库里的密码相同,不同则抛出异常
if(!user.getPassword().equals(formuser.getPassword())) throw new UserException("您的密码错误");
//判断用户是否激活,未激活抛出异常
if(user.isState()==false) throw new UserException("您的账号未激活");
//返回user对象
return user;
}
}
UserDao :对数据的操作
public class UserDao {
private QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
//按照用户名查询用户
public User findByUsername(String username){
try {
String sql="select * from user where username=?";
User user=qr.query(sql, new BeanHandler(User.class), username);
return user;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//按照email查询用户
public User findByEmail(String email){
String sql="select * from user where email=?";
try {
return qr.query(sql, new BeanHandler(User.class), email);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//按照激活码查询用户
public User findByCode(String code){
String sql="select * from user where code=?";
try {
return qr.query(sql, new BeanHandler(User.class), code);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//修改用户状态功能
public void updateState(String uid,boolean state){
String sql="update user set state=? where uid=?";
try {
qr.update(sql,state,uid);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//添加用户
public void addUser(User user){
try {
String sql="insert into user values(?,?,?,?,?,?)";
Object []params={user.getUid(),user.getUsername(),user.getPassword(),user.getEmail(),user.getCode(),user.isState()};
qr.update(sql, params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
创建相关类
domain包创建Category类
dao包创建CategoryDao类
service包创建CategoryService类
servlet包下创建CategoryServlet
-------------------------查询所有图书分类功能分析-------------------------
CategoryDao:
findAll():查找所有图书分类,封装成list返回
CategoryService:
findAll():调用dao层方法,返回List
CategoryServlet:
findAll():调用service层的方法,得到List
保存在request域中,转发到left.jsp页面
left.jsp:遍历查询得到的图书分类,显示在页面上
代码实现
domain下创建Category类
public class Category {
private String cid; //分类id
private String cname;//分类名称
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Category [cid=" + cid + ", cname=" + cname + "]";
}
}
CategoryServlet
public class CategoryServlet extends BaseServlet {
//依赖service层
private CategoryService categoryservice=new CategoryService();
//查找所有分类
public String findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//调用service的查找所有分类功能,得到list集合保存在request域中,转发到显示页面
request.setAttribute("categorylist", categoryservice.findAll());
return "forward:/jsps/left.jsp";
}
}
CategoryService:处理业务逻辑
public class CategoryService {
//依赖dao层,同时还依赖Book的dao层
private CategoryDao categorydao=new CategoryDao();
private BookDao bookdao=new BookDao();
//查找所有分类
public List findAll(){
return categorydao.findAll();
}
//后台功能:添加分类
public void add(Category category) throws CategoryException {
//判断分类是否存在,存在就抛出异常
Category _category=categorydao.isExist(category.getCname());
if(_category!=null) throw new CategoryException("分类已存在");
//添加分类
categorydao.add(category);
}
//后台功能:删除分类
public void delete(String cid) throws CategoryException {
//调用bookdao的通过分类查找图书的方法,获取该分类下图书的数量
int count=bookdao.findBycid(cid);
//如果数量大于0,则抛出异常
if(count>0) throw new CategoryException("该分类下还有图书,不能删除该分类");
categorydao.delete(cid);
}
//通过cid加载分类功能
public Category load(String cid) {
return categorydao.load(cid);
}
//编辑分类功能
public void edit(Category category) throws CategoryException {
//判断分类是否存在
Category _category=categorydao.isExist(category.getCname());
if(_category!=null) throw new CategoryException("分类已存在");
//调用dao层的编辑方法
categorydao.edit(category);
}
}
CategoryDao:进行数据的操作
public class CategoryDao {
QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
//查找所有分类功能,返回list集合
public List findAll(){
String sql="select * from category";
try {
return qr.query(sql, new BeanListHandler(Category.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//添加分类功能
public void add(Category category) {
try {
String sql="insert into category values(?,?)";
Object []params={category.getCid(),category.getCname()};
qr.update(sql,params);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//通过分类名称判断分类是否存在的方法
public Category isExist(String cname){
try {
String sql="select * from category where cname=?";
return qr.query(sql, new BeanHandler(Category.class),cname);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//删除分类
public void delete(String cid) {
String sql="delete from category where cid=?";
try {
qr.update(sql, cid);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//通过分类id返回分类对象的方法
public Category load(String cid) {
try {
String sql="select * from category where cid=?";
return qr.query(sql, new BeanHandler(Category.class),cid);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//编辑分类的方法
public void edit(Category category) {
try {
String sql="update category set cname=? where cid=?";
Object[] params={category.getCname(),category.getCid()};
qr.update(sql,params);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
left.jsp:显示分类的页面
<body>
<div>
<a href=" ">全部分类a>
div>
<c:forEach items="${categorylist}" var="category">
<div>
<a href=" ">${category.cname }a>
div>
c:forEach>
body>
创建相关类
在book.domain包下创建book类
在book.dao包下创建BookDao类
在book.service包下创建BookService类、
在book.web.servlet包下创建BookServlet
-----------------------------查询所有图书功能分析-----------------------------
BookDao:
findAll():查询所有图书,返回List集合
BookService:
findAll():调用dao层方法,返回List集合
BookServlet:
findAll():调用service层的findAll方法,获取List集合。
保存到request域,转发到显示页面。
list.jsp:循环遍历图书集合,显示图书
-------------------------按照图书分类查找图书功能分析----------------------
BookDao:
findBookByCategory(String cid):通过传进来的cid查询图书,返回List集合
BookService:
findBookByCategory(String cid):调用dao层方法,返回List集合
BookServlet:
ffindBookByCategory(String cid):获取页面传入的cid,调用service层方法,获取List集合。
保存到request域,转发到显示页面。
list.jsp:循环遍历图书集合,显示图书
--------------------------加载图书详情功能分析-----------------------------
BookDao:
load(String bid):通过图书编号查找指定图书,返回book对象
BookService:
load(String bid):调用dao层方法查找指定图书,返回book对象
BookServlet:
load(String bid):
获取页面传递的bid,调用service层load方法获得book对象。
然后保存在request中,转发到显示的页面。
desc.jsp:显示图书详情。
代码实现
domain下创建Book类
public class Book {
private String bid; //图书编号
private String bname; //图书名字
private double price; //图书价格
private String author; //作者
private String image; //图片路径
private Category category; //数据库中为cid,这里可以直接对应对象
public String getBid() {
return bid;
}
public void setBid(String bid) {
this.bid = bid;
}
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Override
public String toString() {
return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + ", auther=" + author + ", image=" + image
+ ", category=" + category + "]";
}
}
BookServlet
public class BookServlet extends BaseServlet {
//依赖service层
private BookService bookservice=new BookService();
//查找所有图书功能
public String findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//调用service层的findAll方法获取图书的集合,存放在request中,转发到list页面
request.setAttribute("booklist", bookservice.findAll());
return "forward:/jsps/book/list.jsp";
}
//通过分类查找图书功能
public String findBookByCategory(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取分类编号
String cid=request.getParameter("cid");
//获取该分类下的图书的集合,存放在request中,转发到list页面
request.setAttribute("booklist", bookservice.findBookByCatyegory(cid));
return "forward:/jsps/book/list.jsp";
}
//加载图书详情功能
public String load(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取图书编号
String bid=request.getParameter("bid");
//调用service层的方法,获取book对象,存放在request中,转发到desc页面
request.setAttribute("book", bookservice.load(bid));
return "forward:/jsps/book/desc.jsp";
}
}
BookService:处理业务逻辑
public class BookService {
//依赖dao层
private BookDao bookdao=new BookDao();
//查找所有图书的功能
public List findAll(){
return bookdao.findAll();
}
//通过分类查找图书的功能
public List findBookByCatyegory(String cid){
return bookdao.findBookByCategory(cid);
}
//加载图书的功能
public Book load(String bid){
return bookdao.load(bid);
}
//后台功能:添加图书功能
public void add(Book book) {
bookdao.add(book);
}
//后台功能:删除图书功能
public void delete(String bid) {
bookdao.delete(bid);
}
//后台功能:编辑图书功能
public void edit(Book book) {
bookdao.edit(book);
}
}
BookDao:对数据进行操作
public class BookDao {
QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
//查找所有图书的功能
public List findAll(){
String sql="select * from book where del=0";
try {
return qr.query(sql, new BeanListHandler(Book.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//通过分类查找图书功能
public List findBookByCategory(String cid){
String sql="select * from book where cid=? and del=0";
try {
return qr.query(sql, new BeanListHandler(Book.class),cid);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//加载图书功能
public Book load(String bid){
String sql="select * from book where bid=? ";
try {
Map map= qr.query(sql, new MapHandler(),bid);
Book book=CommonUtils.toBean(map, Book.class);
Category category=CommonUtils.toBean(map, Category.class);
book.setCategory(category);
return book;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//根据分类查找该分类下图书的数量
public int findBycid(String cid){
try {
String sql="select count(*) from book where cid=? and del=0";
Number num=(Number) qr.query(sql, new ScalarHandler(),cid);
return num.intValue();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//添加图书的功能
public void add(Book book) {
try {
String sql="insert into book values(?,?,?,?,?,?)";
Object []params={book.getBid(),book.getBname(),book.getPrice(),book.getAuthor(),book.getImage(),book.getCategory().getCid()};
qr.update(sql, params);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//删除图书
public void delete(String bid){
try {
String sql="update book set del=true where bid=?";
qr.update(sql, bid);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//编辑图书
public void edit(Book book) {
try {
String sql="update book set bname=?,price=?,author=?,cid=? where bid=?";
Object []params={book.getBname(),book.getPrice(),book.getAuthor(),book.getCategory().getCid(),book.getBid()};
qr.update(sql, params);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
list.jsp:显示图书
<body>
<c:forEach items="${booklist}" var="book">
<div class="icon">
<a href=" "><img src=" " border="0"/>a>
<br/>
<a href=" ">${book.bname }a>
div>
c:forEach>
body>
desc.jsp:显示图书详情的页面
<body>
<div>
<img src=" " border="0"/>
div>
<ul>
<li>书名:${book.bname }li>
<li>作者:${book.author }li>
<li>单价:${book.price }li>
ul>
<form id="form" action=" " method="post">
<input type="hidden" name="m" value="add">
<input type="hidden" name="bid" value="${book.bid }">
<input type="text" size="3" name="count" value="1"/>
form>
<a href="javascript:document.getElementById('form').submit();">a>
body>
desc.jsp
购物车的存储?
购物车可以存放在cookie,session和数据库中。
要看具体的需求。我们使用session来实现购物车。不涉及到数据库的操作。
购物车结构
购物车里存放的是商品条目。
商品条目包括商品和商品数量。比如 火腿肠 十包
所以我们创建购物车包
在domain包下创建两个类
CartItem.java:商品条目,包含商品和商品数目属性
Cart:购物车,包含一个集合来存放多个商品条目,和操作商品条目的方法。
我们在Cart类里完成对购物车条目的操作
-add(CartItem cartitem):添加商品条目
-clear();清除购物车
-delete(String bid):根据图书id删除指定商品条目
-Collection getCartitems():查看我的购物车
由于我们购物车不涉及到数据库操作,所以我们没有dao层和service层的操作。
我们在Servlet包下创建cartServlet
为了保证每个用户有自己的购物车,购物车应该在用户登录成功时给用户创建一个购物车,然后存放在session中。
所以我们需要修改登录的servlet,在用户登录成功后创建一个购物车。
CartServlet:
add方法:
获取session中存放的购物车
获取页面传入的图书编号和图书数量
根据图书编号查找到相关的图书,返回图书对象
然后商品条目中添加图书和数量
然后把商品条目添加到购物车中,返回到list页面
clear方法;
清空购物车
调用cart的clear方法
delete方法:
获取页面传入的图书编号
根据编号调用cart的delete方法
list.jsp:
从session中获取购物车,然后遍历购物车商品,进行显示。
删除就调用servlet中的delete方法
清空就调用servlet中的clear方法
我们在domain包下创建两个实体类,一个购物车条目类,一个购物车类
购物车条目类CartItem
public class CartItem {
private Book book; //商品
private int count;//商品数量
//获取商品×数量的价格
public double getSubtotal(){
BigDecimal d1=new BigDecimal(book.getPrice()+"");
BigDecimal d2=new BigDecimal(count+"");
return d1.multiply(d2).doubleValue();
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "CartItem [book=" + book + ", count=" + count + "]";
}
}
Cart.java 购物车类,购物车存放在session中,不涉及数据库操作,所以我们直接在类中定义一些方法
public class Cart {
//为了购物车查询,删除等操作方便,我们使用Map集合来存放商品条目
Map map=new LinkedHashMap();
//总计金额
//使用普通的计算时会造成一些误差,所以我们需要BigDecimal进行精确计算
public double getTotal(){
BigDecimal total=new BigDecimal("0");
for(CartItem cartitem:map.values()){
BigDecimal subtotal=new BigDecimal(cartitem.getSubtotal()+"");
total=total.add(subtotal);
}
return total.doubleValue();
}
//添加商品条目
public void add(CartItem cartitem){
//判断购物车有没有这个条目,有的话就把数量加起来即可,没有就放入购物车
if(map.containsKey(cartitem.getBook().getBid())){
CartItem c1=map.get((cartitem).getBook().getBid());
c1.setCount(c1.getCount()+cartitem.getCount());
map.put(c1.getBook().getBid(),c1);
}else{
map.put(cartitem.getBook().getBid(), cartitem);
}
}
//清空购物车
public void clear(){
map.clear();
}
//删除指定商品条目
public void delete(String bid){
map.remove(bid);
}
//查询我的购物车
public Collection getCartitems(){
return map.values();
}
}
CartServlet
public class CartServlet extends BaseServlet {
//添加商品方法
public String add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从session中获取购物车
Cart cart=(Cart) request.getSession().getAttribute("cart");
//获取商品编号
String bid=request.getParameter("bid");
//获取商品数量
int count=Integer.parseInt(request.getParameter("count"));
//通过图书编号获取图书对象
Book book=new BookService().load(bid);
//创建购物车条目
CartItem cartitem=new CartItem();
//将图书设置到购物车条目
cartitem.setBook(book);
cartitem.setCount(count);
//将购物车条目添加到购物车中
cart.add(cartitem);
return "forward:/jsps/cart/list.jsp";
}
//清除购物车的方法
public String clear(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cart cart=(Cart) request.getSession().getAttribute("cart");
cart.clear();
return "forward:/jsps/cart/list.jsp";
}
//删除购物车条目的方法
public String delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cart cart=(Cart) request.getSession().getAttribute("cart");
String bid=request.getParameter("bid");
cart.delete(bid);
return "forward:/jsps/cart/list.jsp";
}
}
显示购物车页面
<body>
<h1>购物车h1>
<c:choose>
<c:when test="${empty sessionScope.cart or fn:length(sessionScope.cart.cartitems) eq 0}">
<img src="/bookstore/images/cart.png" width="500" align="center">
c:when>
<c:otherwise>
<table border="1" width="100%" cellspacing="0" background="black">
<tr>
<td colspan="7" align="right" style="font-size: 15pt; font-weight: 900">
<a href="/bookstore/CartServlet?m=clear">清空购物车a>
td>
tr>
<tr>
<th>图片th>
<th>书名th>
<th>作者th>
<th>单价th>
<th>数量th>
<th>小计th>
<th>操作th>
tr>
<c:forEach items="${sessionScope.cart.cartitems }" var="cartitem">
<tr>
<td><div><img src=" "/>div>td>
<td>${cartitem.book.bname}td>
<td>${cartitem.book.author}td>
<td>${cartitem.book.price}td>
<td>${cartitem.count}td>
<td>${cartitem.subtotal}td>
<td><a href="/bookstore/CartServlet?m=delete&bid=${cartitem.book.bid }">删除a>td>
tr>
c:forEach>
<tr>
<td colspan="7" align="right" style="font-size: 15pt; font-weight: 900">
${sessionScope.cart.total}
td>
tr>
<tr>
<td colspan="7" align="right" style="font-size: 15pt; font-weight: 900">
<a id="buy" href=" ">a>
td>
tr>
table>
c:otherwise>
c:choose>
body>
相关类的创建。
domain包下创建 Order订单类和OrderItem 订单条目类。
我们订单类和订单条目是相互依赖的,比如我们删除订单,那里面的条目也肯定删除。
我们不可能不创建订单,而直接添加订单条目,所以说两者的依赖很强。
我们在加载订单时,还得把订单项也加载出来。
我们在dao包下创建OrderDao
我们在Service包下创建OrderService
在servlet包下创建OrderServlet
---------------------------生成订单功能分析-----------------------------------------
订单是根据购物车中的信息生成的。
OrderServlet#add():
获取session中的购物车cart
创建Order对象,
通过cart生成order。
通过CartItem商品条目生成订单条目
将订单条目添加到订单中
如果生成订单成功,就清除购物车。
然后调用service层的add(Order order)方法
保存生成的订单到request域中,转发到订单页面。
OrderService#add(Order order):
将订单保存在数据库中。
将多个订单条目保存在数据库中。
保存订单条目时可能会出现异常,但这时订单却正常保存,这就会出现错误。
所以我们需要用事务来操作。
OrderDao:
addOrder();添加订单
addOrderItemList(List list):将订单条目集合添加到数据库中。可以使用批处理一起完成。
desc.jsp:获取订单信息,显示订单。
-------------------------显示我的订单功能分析----------------------------------------
OrderServlet#myorders():
从gsession中获取当前用户user,再获取用户的uid
使用uid调用service的方法,得到用户的所有订单集合List
保存在request中,转发到我的订单页面
OrderService#myorders(String uid):
调用dao层的方法,得到我的订单集合List
OrderDao#findbyId(String uid):
使用uid查询当前用户的所有订单。
循环遍历每个订单,为每个订单加载他的订单条目
返回订单集合
-------------------------在支付页面加载订单功能分析------------------------------
当点击我的订单页面的付款功能时,要发送给servlet一个订单编号oid
OrderServlet#load();
获取oid
调用service的load(String oid)方法获取订单。
将order存放在request域中,转发到付款页面,在付款页面显示当前订单。
OrderService#load(String oid):
调用dao的load方法获取Order对象
OrderDao#load(String oid);
通过oid查询到订单对象。
为订单对象添加订单条目。
返回订单对象
----------------------------------确认收货功能分析------------------------------------------
点击确认收货,发送请求到servlet,包含当前订单oid
OrderServlet#confirm():
获取oid
调用service的confirm功能
如果抛出异常,就将异常信息保存到request域中
如果成功,就保存成功信息
转发到msg页面
OrderService#confirm(String oid):
获取oid
调用dao层的confirm方法,判断订单状态是否为3
如果不为3,就抛出异常
如果为3,就调用更新状态的方法,将订单状态更新为4
orderDao:
confirm(String oid);查询订单状态
updateState(String oid,int state):更新订单状态
---------------------------------在线支付功能分析--------------------------------------------------
支付的两种方式
-电商与银行直接关联
-电商通过和第三方支付平台关联,例如支付宝,财付通,易宝等
网站使用第三方支付平台,需要实名认证备案等等。
比较麻烦,但是易宝支付有一个测试账户,可以供我们测试。
++++++易宝支付++++++++++
易宝给了我们一个支付网关,只要我们的程序付款时重定向到这个支付地址,就可以完成支付。
完成支付需要14个参数。
支付请求参数
可以参考易宝的使用说明。
最后一个参数hmac:十三个参数值+易宝给我们的私人keyValue+md5算法 算出来hmac ,
hmac是为了防止数据被更改,后台会计算我们给出的数据和hmac,如果hmac和我们传递的hmac不同,就说明数据被修改了
易宝的应答机制
我们向易宝发出一次请求,易宝响应两次通知。
支付成功数据服务器点对点通知:易宝直接访问电商,没有客户端什么事;必须使用的方式
我们收不到这个通知,因为我们没有固定ip。
易宝有一个重发机制,如果它访问你,你不给它发送信息,就会一直发。
所以电商需要返回一个以SUCCESS开头的字符串。
引导客户浏览器重定向:有可能会在重定向的过程中将浏览器关闭,可能会造成一些问题。可以不使用这种方式。
---------------------------支付之去银行-------------------------------
我们页面传递订单编号和选择的银行,然后跳转到servlet#pay()方法
Servlet#Pay():
准备易宝支付的13个参数,算出hmac
然后重定向到支付网关即可。
----------------------------支付成功回调电商callback方法-------------------
Servlet#callback():
1.获取易宝支付回应的12个参数
2.校验访问者身份是否为易宝支付,有可能不法分子来访问这个方法。(通过易宝传递的11个参数,与keyValue生成hmac,然后和易宝发送的hmac进行对比)
3.查看订单状态是否为1,如果为1,修改订单状态,增加积分
4.判断回调方式
-如果是点对点,回馈success开头的字符串
5.保存成功信息,转发到msg.jsp页面
代码实现
我们在domain包下创建两个实体类,Order订单类和OrderItem订单条目类
Order类
public class Order {
private String oid; //订单编号
private Date ordertime; //下单时间
private double total; //订单总计
private int state;//代表订单的四种状态,1表示未付款,2表示付款但未发货,3表示发货了但是还没收货,4表示交易成功
private User owner;//下单人
private String address;//下单地址
private List orderitemList; //订单里的订单条目
public List getOrderitemList() {
return orderitemList;
}
public void setOrderitemList(List orderitemList) {
this.orderitemList = orderitemList;
}
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
}
public Date getOrdertime() {
return ordertime;
}
public void setOrdertime(Date ordertime) {
this.ordertime = ordertime;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Order [oid=" + oid + ", ordertime=" + ordertime + ", total=" + total + ", state=" + state + ", owner="
+ owner + ", address=" + address + "]";
}
}
OrderItem订单条目类
public class OrderItem {
private String iid; //订单条目编号
private int count; //商品数量
private double subtotal; //商品小计
private Order order; //订单条目所属订单
private Book book; //所购买的商品
public String getIid() {
return iid;
}
public void setIid(String iid) {
this.iid = iid;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public double getSubtotal() {
return subtotal;
}
public void setSubtotal(double subtotal) {
this.subtotal = subtotal;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
@Override
public String toString() {
return "OrderItem [iid=" + iid + ", count=" + count + ", subtotal=" + subtotal + ", order=" + order + ", book="
+ book + "]";
}
}
OrderServlet
public class OrderServlet extends BaseServlet {
//依赖service层
private OrderService orderservice=new OrderService();
//添加订单方法
public String add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 获取session中的购物车cart
* 创建Order对象,
* 通过cart生成order
*
*/
Order order=new Order();
Cart cart= (Cart) request.getSession().getAttribute("cart");
order.setOid(UUID.randomUUID().toString().replaceAll("-", ""));
order.setOrdertime(new Date());
order.setTotal(cart.getTotal());
order.setState(1);
User u=(User)request.getSession().getAttribute("sessionuser");
order.setOwner(u);
/*
* 创建订单条目,添加到订单中
* 订单条目中需要的值从购物车商品条目中获取
*/
List<OrderItem> orderitemList=new ArrayList<OrderItem>();
for(CartItem cartitem:cart.getCartitems()){
OrderItem orderitem=new OrderItem();
orderitem.setIid(UUID.randomUUID().toString().replaceAll("-", ""));
orderitem.setCount(cartitem.getCount());
orderitem.setSubtotal(cartitem.getSubtotal());
orderitem.setOrder(order);
orderitem.setBook(cartitem.getBook());
orderitemList.add(orderitem);
}
//将订单条目集合设置到购物车中
order.setOrderitemList(orderitemList);
//订单生成后清空购物车
cart.clear();
//调用service添加订单
orderservice.add(order);
//将订单保存在request域中,转发到页面
request.setAttribute("order",order);
return "forward:/jsps/order/desc.jsp";
}
//显示我的订单功能
public String myorders(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从session中获取当前用户
User user=(User) request.getSession().getAttribute("sessionuser");
//通过用户的uid获取订单集合
List<Order> list=orderservice.myorders(user.getUid());
//将订单集合保存在request域中
request.setAttribute("orders", list);
return "forward:/jsps/order/list.jsp";
}
//加载详细订单的功能
public String load(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取订单编号
String oid=request.getParameter("oid");
//调用service的加载订单方法
Order order=orderservice.load(oid);
//将获取的订单保存在request中
request.setAttribute("order", order);
return "forward:/jsps/order/desc.jsp";
}
//确认收货功能
public String confirm(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取订单编号
String oid=request.getParameter("oid");
try {
//如果收货成功就保存成功信息,如果出现异常,就保存异常信息
orderservice.confirm(oid);
request.setAttribute("msg", "收货成功");
} catch (OrderException e) {
request.setAttribute("msg", e.getMessage());
}
return "forward:/jsps/msg.jsp";
}
//支付功能
public String pay(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//准备易宝支付的十三参数
String p0_Cmd="Buy";
String p1_MerId="10001126856";
String p2_Order=request.getParameter("oid");
String p3_Amt="0.01";
String p4_Cur="CNY";
String p5_Pid="";
String p6_Pcat="";
String p7_Pdesc="";
String p8_Url="http://localhost:8080/bookstore/OrderServlet?m=callback";
String p9_SAF="";
String pa_MP="";
String pd_FrpId=request.getParameter("pd_FrpId");
String pr_NeedResponse="1";
String keyValue="69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";
//计算hmac
String hmac=PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP, pd_FrpId, pr_NeedResponse, keyValue);
//将url和参数连接起来
StringBuilder url=new StringBuilder("https://www.yeepay.com/app-merchant-proxy/node");
url.append("?p0_Cmd=").append(p0_Cmd);
url.append("&p1_MerId=").append(p1_MerId);
url.append("&p2_Order=").append(p2_Order);
url.append("&p3_Amt=").append(p3_Amt);
url.append("&p4_Cur=").append(p4_Cur);
url.append("&p5_Pid=").append(p5_Pid);
url.append("&p6_Pcat=").append(p6_Pcat);
url.append("&p7_Pdesc=").append(p7_Pdesc);
url.append("&p8_Url=").append(p8_Url);
url.append("&p9_SAF=").append(p9_SAF);
url.append("&pa_MP=").append(pa_MP);
url.append("&pd_FrpId=").append(pd_FrpId);
url.append("&pr_NeedResponse=").append(pr_NeedResponse);
url.append("&keyValue=").append(keyValue);
url.append("&hmac=").append(hmac);
//重定向到支付网关
response.sendRedirect(url.toString());
return null;
}
//支付成功后的回调参数
public String callback(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取参数
String p1_MerId=request.getParameter("p1_MerId");
String r0_Cmd=request.getParameter("r0_Cmd");
String r1_Code=request.getParameter("r1_Code");
String r2_TrxId=request.getParameter("r2_TrxId");
String r3_Amt=request.getParameter("r3_Amt");
String r4_Cur=request.getParameter("r4_Cur");
String r5_Pid=request.getParameter("r5_Pid");
String r6_Order=request.getParameter("r6_Order");
String r7_Uid=request.getParameter("r7_Uid");
String r8_MP=request.getParameter("r8_MP");
String r9_BType=request.getParameter("r9_BType");
String hmac=request.getParameter("hmac");
String keyValue="69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";
boolean bool=PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd, r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid, r8_MP, r9_BType, keyValue);
//判断易宝返回的hmac和我们计算出来的是否相同,不相同就发送错误信息
if(!bool){
request.setAttribute("msg", "请勿进行非法操作");
return "forward:/jsps/msg.jsp";
}
//修改订单状态
orderservice.pay(r6_Order);
//如果点对点的响应。就发送success
if(r9_BType.equals("2")){
response.getWriter().print("success");
}
request.setAttribute("msg", "支付成功");
return "forward:/jsps/msg.jsp";
}
}
OrderService :对订单进行业务逻辑操作
public class OrderService {
//依赖dao层
private OrderDao orderdao=new OrderDao();
//添加订单操作
public void add(Order order){
try {
//对插入进行事务操作,添加订单和添加订单条目
JdbcUtils.beginTransaction();
orderdao.addOrder(order);
orderdao.addOrderItemList(order.getOrderitemList());
JdbcUtils.commitTransaction();
} catch (Exception e) {
try {
JdbcUtils.rollbackTransaction();
} catch (SQLException e1) {
throw new RuntimeException(e);
}
}
}
//我的订单
public List myorders(String uid) {
return orderdao.findById(uid);
}
public Order load(String oid) {
return orderdao.load(oid);
}
//确认收货
public void confirm(String oid) throws OrderException{
int state=orderdao.confirm(oid);
if(state!=3) throw new OrderException("订单出现异常");
orderdao.updateState(oid, 4);
}
//支付功能
public void pay(String oid){
int state=orderdao.confirm(oid);
if(state==1){
orderdao.updateState(oid, 2);
}
}
//后台功能:查询所有订单功能
public List findAll() {
return orderdao.findAll();
}
//根据订单状态查询订单功能
public List findByState(String state) {
return orderdao.findByState(state);
}
}
OrderDao:对订单进行数据操作
public class OrderDao {
private QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
//添加订单操作
public void addOrder(Order order){
String sql="insert into orders values(?,?,?,?,?,?)";
//我们需要处理数据库的Date类型和util包下的Date类型之间的转换
Timestamp timestamp=new Timestamp(order.getOrdertime().getTime());
Object []params={order.getOid(),timestamp,order.getTotal(),order.getState(),order.getOwner().getUid(),order.getAddress()};
try {
qr.update(sql,params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//添加订单条目功能
public void addOrderItemList(List list){
try {
//这里我们需要多次插入商品条目,所以使用批处理来插入
//批处理的参数是一个二维数组,二维数组是n个一维数组组成,每个一维数组中存放了一次执行sql语句所需要的参数
String sql="insert into orderitem values(?,?,?,?,?)";
Object [][]params=new Object[list.size()][];
for(int i=0;iget(i);
params[i]=new Object[]{item.getIid(),item.getCount(),item.getSubtotal(),item.getOrder().getOid(),item.getBook().getBid()};
}
qr.batch(sql, params);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//通过用户id查询订单
public List findById(String uid){
try {
//查询用户所有订单,然后遍历订单,为订单的内容订单条目赋值
String sql="select * from orders where uid=?";
List orderlist=qr.query(sql, new BeanListHandler(Order.class),uid);
for(Order order:orderlist){
//为订单加载订单条目功能
loadOrderItems(order);
}
return orderlist;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//记载订单条目功能
private void loadOrderItems(Order order) {
try {
//因为我们查询的订单条目还包含book对象,所以需要连接查询,这时查出来的就不是一个对象,而是订单条目对象和book对象,我们使用MapListHandler来来存储
String sql="select * from orderitem,book where orderitem.bid=book.bid and oid=? ";
List
我们只需要在Category模块下创建一个AdminCategoryServlet
dao层和service层都不需要改变。
-------------------------------查看所有分类功能分析------------------------------------
调用service层的查看所有分类的功能,返回List
存放到request域中,转发回显示分类的页面。
----------------------------------添加分类功能分析--------------------------------
AdminCategoryServlet#add:
获取用户输入的分类名称
我们添加分类id
然后封装成category对象
调用service的add(Category category)方法
如果成功,就保存成功信息到request域,转发到msg页面
如果出现异常,就保存异常信息到request域,转发到msg页面
AdminCategoryService#add(Category category):
先调用dao层的分类是否存在方法,判断分类是否存在,存在就抛出异常
不存在就调用dao 层的add方法,添加分类
AdminCategoryDao#add(Category category):
isExist(String cname):判断分类是否存在
add(Category category):添加分类
--------------------------------删除分类功能分析----------------------------------
删除链接应该向servlet传送分类id :cid
AdminCategoryServlet#delete():
获取cid
调用service的delete(String cid)方法删除分类
出现异常,保存异常信息转发到msg页面
没出现异常调用findAll方法,显示当前所有分类
CategoryService#delete(String cid);
调用BookDao的findBycid(String cid)方法获取当前分类下的图书数量
如果当前分类下有图书,则抛出异常,不能删除该分类
如果没有图书,调用dao层的删除方法
CategoryDao:
delete(String cid):删除分类
--------------------------------修改分类功能分析------------------------------------
第一步,先加载以前的分类
点击修改按钮,要向servlet传送cid
AdminCategoryServlet#load():
获取cid
通过cid获取category对象
然后转发到页面
在页面上显示当前分类的信息
第二步:设置好修改信息后,点击修改,要向servlet传递cid和cname
AdminCategoryServlet#edit():
获取cid和cname,封装成category对象
调用service的edit(Category category)方法修改
如果出现异常,保存异常信息转发到msg页面
没有异常,保存成功信息转发到msg页面
AdminCategoryService#edit(Category):
先判断当前输入的分类名称是否存在
存在就抛出异常
不存在就调用dao层的edit(Category)方法修改
AdminCategoryDao#edit(Category category)
:修改分类信息。
代码实现
ADminCategoryServlet
public class AdminCategoryServlet extends BaseServlet {
private CategoryService categoryservice=new CategoryService();
//查看所有分类功能
public String findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List list=categoryservice.findAll();
request.setAttribute("categorylist", list);
return "forward:/adminjsps/admin/category/list.jsp";
}
//添加分类功能
public String add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String cname=request.getParameter("cname");
String cid=UUID.randomUUID().toString().replaceAll("-", "");
Category category=new Category();
category.setCname(cname);
category.setCid(cid);
try {
categoryservice.add(category);
request.setAttribute("msg", "添加分类成功");
return "forward:/adminjsps/msg.jsp";
} catch (CategoryException e) {
request.setAttribute("msg", e.getMessage());
return "forward:/adminjsps/msg.jsp";
}
}
//删除分类功能
public String delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String cid=request.getParameter("cid");
try{
categoryservice.delete(cid);
return findAll(request,response);
}catch (Exception e) {
request.setAttribute("msg", e.getMessage());
return "forward:/adminjsps/msg.jsp";
}
}
//加载分类信息
public String load(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String cid=request.getParameter("cid");
Category category= categoryservice.load(cid);
request.setAttribute("category", category);
return "forward:/adminjsps/admin/category/mod.jsp";
}
//编辑分类功能
public String edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户输入参数,封装成分类对象
String cid=request.getParameter("cid");
String cname=request.getParameter("cname");
Category category =new Category();
category.setCid(cid);
category.setCname(cname);
try {
categoryservice.edit(category);
request.setAttribute("msg", "修改成功");
return "forward:/adminjsps/msg.jsp";
} catch (Exception e) {
request.setAttribute("msg", e.getMessage());
return "forward:/adminjsps/msg.jsp";
}
}
}
相关类的创建
我们需要创建两个Servlet
-AdminBookServlet :用来管理图书
-AdminAddBookServlet:专门用来添加图书,因为图书添加需要上传功能,上传的servlet的getParamter方法是不能使用的。
------------------------------------查看所有图书功能分析----------------------------
点击查询所有图书按钮,请求AdminBookServlet的findAll方法
AdminBookServlet#findAll():
调用service的findAll方法,获取所有图书集合List
将其保存在request域中,然后转发到list页面。
list.jsp:循环显示book信息
------------------------------------加载图书详情功能-----------------------------
点击图书就跳转到Servlet的load方法,加载图书详情,需要传递图书编号bid。
AdminBookServlet#load():
获取bid
根据bid调用service的load(String bid)方法获取book
获取图书分类集合List
将图书分类集合和book对象保存在request域中,转发到图书详情页面 desc.jsp
desc.jsp:
显示图书的详细信息。
---------------------------------添加图书功能-------------------------------------
添加图书涉及到上传图书图片
创建工厂
创建解析器
解析request得到表单内容
把普通表单项封装到book对象中
保存上传文件,把文件的路径设置给book的image属性
调用service的add方法把book对象保存到数据库中
----------------------------------删除图书功能------------------------------
book表和orderitem表有关联关系。比如别人的订单有图书,但我把这个图书给删了,那么数据库就会出现问题。
为了解决这个问题,我们的删除图书并不是真正的从数据库删除掉,而是给book表添加一个del字段,为boolean类型,表示是否已删除。
所以我们需要修改dao层的与查询有关的方法,需要添加条件 where del=false;
删除图书,就是将del列修改为true
AdminBookServlet#delete():
获取bid
调用service层方法删除图书
然后调用findAll方法显示当前所有图书
--------------------------------编辑图书功能----------------------------------
AdminBookServlet#edit();
获取表单数据,封装成book对象
调用service的编辑方法,对图书信息进行编辑
---------------------------------为登录添加过滤器--------------------------
过滤订单,购物车等相关页面和servlet
判断session中是否有用户信息,有的话就放行。没有就返回到登陆页面
AdminBookServlet
public class AdminBookServlet extends BaseServlet {
private BookService bookservice=new BookService();
private CategoryService categoryservice=new CategoryService();
//查看所有图书
public String findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List booklist=bookservice.findAll();
request.setAttribute("booklist", booklist);
return "forward:/adminjsps/admin/book/list.jsp";
}
//加载图书详细信息
public String load(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String bid=request.getParameter("bid");
Book book=bookservice.load(bid);
List categorylist=categoryservice.findAll();
request.setAttribute("categorylist", categorylist);
request.setAttribute("book", book);
return "forward:/adminjsps/admin/book/desc.jsp";
}
//加载所有图书分类
public String loadcategory(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List categorylist=categoryservice.findAll();
request.setAttribute("categorylist", categorylist);
return "forward:/adminjsps/admin/book/add.jsp";
}
//删除图书
public String delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String bid=request.getParameter("bid");
bookservice.delete(bid);
return findAll(request,response);
}
//编辑图书
public String edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Book book=CommonUtils.toBean(request.getParameterMap(), Book.class);
Category category=CommonUtils.toBean(request.getParameterMap(), Category.class);
book.setCategory(category);
bookservice.edit(book);
request.setAttribute("msg", "修改成功");
return "forward:/adminjsps/msg.jsp";
}
}
专门添加图书的servlet
public class AdminAddBookServlet extends HttpServlet {
private BookService bookservice=new BookService();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建工厂和解析器
DiskFileItemFactory factory=new DiskFileItemFactory();
ServletFileUpload fileupload=new ServletFileUpload(factory);
//设置最大上传限制
fileupload.setFileSizeMax(15*1024);
try {
//获取表单
List list=fileupload.parseRequest(request);
Map map=new HashMap();
//把所有普通表单项先存放在map集合中,然后封装成book对象
//再获取文件的存放位置,设置给book对象
for(FileItem fileitem:list){
//判断是否为普通表单项
if(fileitem.isFormField()){
map.put(fileitem.getFieldName(), fileitem.getString("utf-8"));
}
}
Book book=(Book) CommonUtils.toBean(map, Book.class);
//保存文件到指定位置
String filepath=request.getServletContext().getRealPath("/book_img");
//为了防止文件名重复,我们在前面加上uuid
String filename=UUID.randomUUID().toString().replaceAll("-", "")+"_"+list.get(1).getName();
File file=new File(filepath,filename);
list.get(1).write(file);
//将图片位置设置给book
book.setImage("book_img/"+filename);
book.setBid(UUID.randomUUID().toString().replaceAll("-", ""));
//把Category对象设置给Book
Category category=CommonUtils.toBean(map, Category.class);
book.setCategory(category);
//调用service的add方法添加图书
bookservice.add(book);
//校验图片的大小
Image image=new ImageIcon(file.getAbsolutePath()).getImage();
if(image.getHeight(null)>200||image.getWidth(null)>200){
//删除已保存的图片
file.delete();
request.setAttribute("msg", "您上传的图片尺寸过大");
request.getRequestDispatcher("/adminjsps/msg.jsp").forward(request, response);
return ;
}
request.setAttribute("msg", "添加图书成功");
request.getRequestDispatcher("/adminjsps/msg.jsp").forward(request, response);
} catch (Exception e) {
if(e instanceof FileUploadBase.FileSizeLimitExceededException ){
request.setAttribute("msg", "您上传的图片超过15kb");
request.getRequestDispatcher("/adminjsps/msg.jsp").forward(request, response);
}
}
}
}
------------------------------查询所有订单功能------------------------------
AdminOrderServlet#findAll():
调用service的findAll方法,返回一个订单集合
保存在request域中,转发到显示页面
-----------------------通过订单状态查询订单功能--------------------------------
AdminOrderServlet#findByState():
获取订单状态参数state
调用Service的findByState(String state)获取订单集合
保存在request域中,转发到显示页面
代码实现
public class AdminOrderServlet extends BaseServlet {
private OrderService orderservice=new OrderService();
//查询所有订单
public String findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List orderlist=orderservice.findAll();
request.setAttribute("orderlist", orderlist);
return "forward:/adminjsps/admin/order/list.jsp";
}
//按订单状态查询所有订单
public String findByState(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String state=request.getParameter("state");
List orderlist=orderservice.findByState(state);
request.setAttribute("orderlist", orderlist);
return "forward:/adminjsps/admin/order/list.jsp";
}
}
我们的网上书城项目到这儿就结束了,还有很多功能没完善。自己的笔记也做得非常粗糙。以后肯定会修正。