JavaWeb项目练习--环境搭建、用户模块、
ywnbxn网上书城。
一、搭建环境
1.导入原型:复制原型中的src、webRoot。
用户模块
分类模块
图书模块
购物车模块
订单模块
二、功能分析
前台
1)用户模块:
注册、 ** 、登录 、退出
2)分类模块:
查看所有分类
3)图书模块:
查询所有图书、 分类查询图书、 查询图书详细(按id查)
4)购物车模块:
添加购物车条目、 清空所有条目、 删除指定条目 、 我的购物车(按用户查询购物车)
5)订单模块:
生成订单
我的订单(按用户查询订单)
按id查询订单
确认收货
付款功能(只是跳转到银行页面)
付款回调功能(由银行来调用我们这个方法,表示用户已经付款成功)
后台:
1)分类管理:
添加分类 、 查看所有分类、 删除分类、 修改分类
2)图书管理(我的)
查看所有图书、 删除图书 、修改图书、 添加图书(上传图片)
三、 框架的搭建
3.1 导包
1)数据库:
mysql驱动
c3p0(jar包和配置文件)
dbutils
itcast-tools
commons-beanutils
commons-logging
javamail
2)mail.jar
activation.jar
3)上传
commons-fileupload
commons-io
4)校验-ajax
json-lib
3.2 创建package
根:ywnxbx.bookstore
user
domain
dao
service
web.servlet
category
domain
dao
service
web.servlet
book
domain
dao
service
web.servlet
cart
domain
web.servlet
order
domain
dao
service
web.servlet
3.3 表
tb_user
category
book
orders
orderitem
用户模块
1 用户模块的相关类创建
domain:User
dao:UserDao
service:UserDao
web.servlet:UserServlet
2 用户注册
流程:
/jsps/user/regist.jsp
---> UserServlet#regist()
---> msg.jsp
页面:
regist.jsp
表面页面,请求UserServlet#regist()方法
参数:整个表单数据
msg.jsp
Servlet:
UserServlet#regist()
1)一键封装表单数据到User form对象
2)补全:uid、**码
3)校验输入(表单数据):
若错误:
保存错误信息到request
保存当前表单数据(form)到request(回显);
转发回到regist.jsp
4)调用service的regist()方法,传递form过去;
抛出异常:
保存错误信息(异常信息)、保存表单数据(回显)、转发到regist.jsp
没有抛出异常:
发邮件(发件人、收件人、标题、内容),内容中包含超链接,超链接指向可完成**的Servlet地址!链接中要有**码参数!
保存成功信息到request中
转发到msg.jsp
Service:
UserService#regist(User form)
校验用户是否被注册,如果注册,抛出UserException;
校验邮箱是否被注册,如果注册,抛出UserException;
把user插入到数据库中
Dao:
User findByUsername(String username):按用户名查询用户
User findByEmail(String email):按emal查询用户
void add(User form):插入用户到数据库中
3 用户**
流程:用户的邮件中 --> UserServlet#active() --> msg.jsp
4 用户登录
流程:/jsps/user/login.jsp --> UserServlet#login() --> index.jsp
5 用户退出
流程:top.jsp --> UserServlet#quit() --> login.jsp
quit():把session销毁!
代码:
domian
/**
* User的领域对象
* 对应表单
* 对应数据库表
*
* @author 一万年行不行
*
*/
public class User {
private String uid; //主键
private String username; //用户名
private String password; //密码
private String email; //邮箱
private String code; //**码
private boolean state; //状态(**和未**)
}
do:
/**
* User持久层 (对数据的持久化操作)
*
* @author 一万年行不行
*
*/
public class UserDao {
private QueryRunner qr = new TxQueryRunner();
/**
* 通过用户名查询
*
* @param Username
* @return
*/
public User findByUsername(String username) {
try {
String sql = "select * from tb_user where username = ?";
return qr.query(sql, new BeanHandler<User>(User.class), username);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 通过Email查询
*
* @param Email
* @return
*/
public User findByEmail(String email) {
try {
String sql = "select * from tb_user where email = ?";
return qr.query(sql, new BeanHandler<User>(User.class), email);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 通过**码查询
* @param code
* @return
*/
public User findByCode(String code){
try {
String sql = "select * from tb_user where code = ?";
return qr.query(sql, new BeanHandler<User>(User.class), code);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 添加用户
* @param user
*/
@Test
public void add(User user){
try{
String sql = "insert into tb_user value(?,?,?,?,?,?)";
Object[] parmas = {user.getUid(),user.getUsername(),
user.getPassword(),user.getEmail(),
user.getCode(),user.isState()};
qr.update(sql,parmas);
}catch(SQLException e){
throw new RuntimeException(e);
}
}
/**
* 修改指定用户的状态
* @param uid
* @param state
*/
public void updateState(String uid, boolean state){
try {
String sql = "update tb_user set state = ? where uid = ?";
qr.update(sql,state,uid);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
UserService:
/**
* User业务层(表示层与数据层(持久层)的数据的传递和逻辑处理)
* @author 一万年行不行
*
*/
public class UserService {
private UserDao userDao = new UserDao();
/**
* 注册功能
* @param from
* @throws UserException
*/
public void regist(User form) throws UserException{
//校验用户名
User user = userDao.findByUsername(form.getUsername());
if(user != null) throw new UserException("用户名已存在");
//校验Email
user = userDao.findByEmail(form.getEmail());
if(user != null) throw new UserException("Email已存在");
//校验成功,添加用户
userDao.add(form);
}
/**
* **功能
* @param code
* @throws UserException
*/
public void active(String code) throws UserException{
/*
* 1.使用code查询数据库,得到User对象
* 若返回null,抛出异常
* 2.查看用户状态
* true: 抛出异常
* false :修改用户状态。
*/
User user = userDao.findByCode(code);
if(user == null) throw new UserException("**码无效");
//**码状态为true ,抛出已经**信息
if(user.isState()) throw new UserException("已**");
//**码状态为false,修改为true
userDao.updateState(user.getUid(), true);
}
/**
* 登陆功能
* @param form
* @return
* @throws UserException
*/
public User login(User form) throws UserException{
/*
* 1.使用username查询数据库,得到user对象
* 若为空:抛出异常(用户不存在)
* 2.比较form与user的密码是否相同
* 若不同:抛出异常(密码错误)
* 3.查看用户状态
* 未**:抛出异常
* 4.校验完成,返回user
*/
//按用户名查询用户
User user = userDao.findByUsername(form.getUsername());
//校验用户名、密码、**状态
if(user == null) throw new UserException("用户不存在");
if(!user.isState()) throw new UserException("用户未**,请**后登陆");
if(!user.getPassword().equals(form.getPassword())) throw new UserException("用户名或密码错误");
return user; //返回用户
}
}
UserServlet:
public class UserServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
private UserService userService = new UserService();
/**
* 注册功能
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
public String regist(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 1.一键封装表单数据到User form对象
* 2.补全:uid、**码
* 3.校验输入(表单数据):
* 若错误:
* 保存错误信息、表单数据(form)到request(用于回显)
* 转发回到regist.jsp
* 4.调用service的regist()方法,传递form过去;
* 若抛出异常:
* 保存错误信息(异常信息)、保存表单数据(回显)、转发到regist.jsp
* 5.发邮件(发件人、收件人、标题、内容),内容中包含超链接,超链接指向可完成**的Servlet地址!链接中要有**码参数!
* 6.保存成功信息转发到msg.jsp
*
*/
//封装表单数据
//通过map的数据来创建User类型的JavaBean对象
User form = CommonUtils.toBean(request.getParameterMap(), User.class);
//补全uid、**码,设置到form对象中
form.setUid(CommonUtils.uuid());
form.setCode(CommonUtils.uuid());
/*
* 表单校验
* 1.创建一个Map,装载所有的表单错误信息,其中key为表单字段名称
* 2.校验。
* 失败,向map添加错误信息,
* 3.查看map长度是否大于0,
* a.大于0。有错误!
* 处理错误:保存map到request中,保存form到request中,转发到regist.jsp
* b.等于0。没有错误,向下执行!
*/
Map<String,String> errors = new HashMap<String, String>();
//获取form中的username、password、email进行校验
//校验username
String username = form.getUsername();
if(username == null || username.trim().isEmpty()){
errors.put("usernameError", "用户名不能为空");
}else if(username.length() < 3 || username.length() > 10 ){
errors.put("usernameError", "用户名长度必须在3~10之间");
}
//校验password
String password = form.getPassword();
if(password == null || password.trim().isEmpty()){
errors.put("passwordError", "密码不能为空");
}else if(password.length() < 3 || password.length() > 10 ){
errors.put("passwordError", "用密码长度必须在3~10之间");
}
//校验Email
String email = form.getEmail();
if(email == null || email.trim().isEmpty()){
errors.put("emailError", "Email不能为空");
}else if(!email.matches("\\[email protected]\\w+\\.\\w+")){ //使用正则表达式规定格式
errors.put("emailError", "Email格式错误");
}
//判断是否存在错误信息
//有错误,保存错误信息,转发到注册界面
if(errors.size()>0){
request.setAttribute("errors", errors);
request.setAttribute("form", form);
return "f:jsps/user/regist.jsp";
}
// * 4.调用service的regist()方法,传递form过去;
// * 若抛出异常:
// * 保存错误信息(异常信息)、保存表单数据(回显)、转发到regist.jsp
// * 5.发邮件(发件人、收件人、标题、内容),内容中包含超链接,超链接指向可完成**的Servlet地址!链接中要有**码参数!
// * 6.保存成功信息转发到msg.jsp
try{
userService.regist(form);
/*
* 发邮件
* 1.准备配置文件
* 2.获取配置文件内容
*/
//创建配置文件对象,加载指定的配置文件
Properties props = new Properties();
//完成加载配置文件
props.load(this.getClass().getClassLoader()
.getResourceAsStream("email_template.properties"));
//
String host = props.getProperty("host"); //获取服务器主机
String uname = props.getProperty("uname"); //获取用户名
String pwd = props.getProperty("pwd"); //获取密码
String to = form.getEmail(); //获取收件人
String from = props.getProperty("from"); //获取发件人
String subject = props.getProperty("subject"); //获取主题
String content = props.getProperty("content"); //获取邮件内容
content = MessageFormat.format(content, form.getCode()); //使用coed替换{0} (占位符)
//得到session
Session session = MailUtils.createSession(host, uname, pwd);
//创建Mail对象,发送邮件
Mail mail = new Mail(from,to,subject,content);
try{
MailUtils.send(session, mail); //发送邮件
}catch(MessagingException e){
}
// 无异常,保存成功信息,转发到jsp
request.setAttribute("msg", "注册成功,请到邮箱**");
return "f:/jsps/msg.jsp";
}catch (ywnxbx.bookstore.user.service.UserException e) {
/*
* 1.保存异常信息、form
* 2.转发到regist.jsp
*/
request.setAttribute("msg", e.getMessage());
request.setAttribute("form", form);
return "f:/jsps/user/regist.jsp";
}
}
/**
* **功能
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
public String active(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 1.获取参数**码
* 2.调用service中active方法进行**
* 若异常: 保存异常信息到request域,转发到msg.jsp
* 3.保存成功信息到request域,转发到msg.jsp
*/
//获取超链接中的code参数
String code = request.getParameter("code");
try{
userService.active(code);
request.setAttribute("msg", "恭喜,**成功");
}catch(UserException e){
request.setAttribute("msg", e.getMessage());
}
return "f:/jsps/msg.jsp";
}
/**
* 登陆功能
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
public String login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 1.封装表单数据
* 2.校验输入数据(省略)
* 3.调用service完成登陆
* 4.保存用户信息到session
* 5.重定向到index.jsp
*/
//封装表单数据
User form = CommonUtils.toBean(request.getParameterMap(),User.class);
//调用service#login
try{
User user = userService.login(form);
//保存信息到session,重定向到index.jsp
request.getSession().setAttribute("session_user", user);
/*
* 给用户配备一个购物车。
* 即向session中创建保存一个cart对象
*/
request.getSession().setAttribute("cart", new Cart());
return "r:/index.jsp";
}catch(UserException e){
request.setAttribute("msg", e.getMessage());
request.setAttribute("form", form);
return "f:/jsps/user/login.jsp";
}
}
/**
* 用户退出功能
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
public String quit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//销毁Session,则用户退出
request.getSession().invalidate();
return "r:/index.jsp";
}
}
email_template.properties
host=smtp.163.com
uname=ywnxbx
pwd=(第三方授权码)
[email protected]
subject=\u8FD9\u662F\u6765\u81EAywnxbx\u7F51\u4E0A\u4E66\u57CE\u7684\u6FC0\u6D3B\u90AE\u4EF6\uFF01
content=<a href\="http\://localhost\:8080/bookstore/UserServlet?method\=active&code\={0}">\u70B9\u51FB\u8FD9\u91CC\u8FDB\u884C\u8D26\u53F7\u6FC0\u6D3B</a>
jsp
1)regist.jsp
<body>
<h1>注册</h1>
<%--
1.显示errors --> 字段错误
2.显示异常错误
3.回显
--%>
<p style="color: red; font-weight: 900">${msg }</p>
<form action="<c:url value='/UserServlet'/>" method="post">
<input type="hidden" name="method" value="regist"/>
用户名:<input type="text" name="username" value="${form.username } "/><br/>
<p style="color: red; font-weight: 900">${errors.usernameError }</p>
密 码:<input type="password" name="password"/><br/>
<p style="color: red; font-weight: 900">${errors.passwordError }</p>
邮 箱:<input type="text" name="email" value="${form.email }"/><br/>
<p style="color: red; font-weight: 900">${errors.emailError }</p>
<input type="submit" value="注册"/>
</form>
</body>
2)login.jsp
<%--
1.使用<input type="hidden"/> 标签指定servlet
2.显示错误信息
3. 回显
--%>
<body>
<h1>登录</h1>
<p style="color: red; font-weight: 900">${msg }</p>
<form action="<c:url value='/UserServlet'/>" method="post">
<input type="hidden" name="method" value="login"/>
用户名:<input type="text" name="username" value="${form.username }"/>
<br/>
密 码:<input type="password" name="password" value="${form.password }"/><br/>
<input type="submit" value="登录"/>
</form>
</body>
3)main.jsp
<table class="table" align="center">
<tr style="background: #4682B4; height: 120px; ">
<td colspan="2" align="center">
<iframe frameborder="0" src="<c:url value='/jsps/top.jsp'/>" name="top"></iframe>
</td>
</tr>
<tr>
<td width="120" style="padding:5px;" align="center" valign="top">
<iframe frameborder="0" width="120" src="<c:url value='/CategoryServlet?method=findAllCategory'/>" name="left"></iframe>
</td>
<td>
<iframe frameborder="0" src="<c:url value='/jsps/body.jsp'/>" name="body"></iframe>
</td>
</tr>
</table>
</body>
4)left.jsp
<body>
<div>
<a href="<c:url value='/BookServlet?method=findAllBook'/>">全部分类</a>
</div>
<c:forEach items="${categoryList }" var="category">
<div>
<a href="<c:url value='/BookServlet?method=findByCategory&cid=${category.cid }'/>">${category.cname }</a>
</div>
</c:forEach>
</body>
5)top.jsp
<style type="text/css">
body {
background: #4682B4;
}
a {
text-transform:none;
text-decoration:none;
}
a:hover {
text-decoration:underline;
}
</style>
</head>
<body>
<h1 style="text-align: center;">ywnxbx的书店</h1>
<div style="font-size: 10pt;">
<c:choose>
<c:when test="${empty sessionScope.session_user}">
<a href="<c:url value='/jsps/user/login.jsp'/>" target="_parent">登录</a> |
<a href="<c:url value='/jsps/user/regist.jsp'/>" target="_parent">注册</a>
</c:when>
<c:otherwise>
您好:${sessionScope.session_user.username }
<a href="<c:url value='/jsps/cart/list.jsp'/>" target="body">我的购物车</a> |
<a href="<c:url value='/OrderServlet?method=myOrders'/>" target="body">我的订单</a> |
<a href="<c:url value='/UserServlet?method=quit'/>" target="_parent">退出</a>
</c:otherwise>
</c:choose>
</div>
</body>
6)msg.jsp
<body>
<h1>${msg }</h1>
<ul>
<li><a href="<c:url value='/index.jsp'/>">主页</a></li>
<li><a href="<c:url value='/jsps/user/login.jsp'/>">登陆</a></li>
<li><a href="<c:url value='/jsps/user/regist.jsp'/>">注册</a></li>
</ul>
</body>