EasyMall商城项目
1.EasyMall商城项目简介
EasyMall(易买网)商城项目是以java语言为主,Jsp、HTML、css、JavaScript为辅开发的一个电子商城项目。该项目用最传统的技术(Servlet、JSP)实现了现代流行的电商项目中的主要的功能,比如浏览商品、将商品加入购物车、下订单及在线支付等功能。该项目还提供了后台管理功能来管理网站中的数据,比如用户管理、商品管理、订单管理、权限控制、销售榜单下载等功能。该项目采用了MVC软件分层的思想来组织整个软件的结构,还采用了Apache DBUtils来简化持久层的操作。最终实现了一个电商网站应该具有的功能。
2.项目涉及技术
该项目采用的技术包含HTTP协议、Tomcat服务器、静态Web资源开发技术(HTML、CSS、JS)、Java后台开发技术(Servlet、JSP)、JDBC、MySQL数据库技术、过滤器、监听器、软件编程思想实践等等。
3.EasyMall注册功能实现
3.1.项目环境搭建
(1)创建EasyMall工程
(2)配置www.easymall.com虚拟主机, 并将主机配置为默认虚拟主机:
在[tomcat]根目录下创建easymall文件夹,然后修改文件:[tomcat]\conf\server.xml,在Engine标签中配置Host标签,例如:
<Host name="www.easymall.com" appBase="E:\software\tomcat7.0\easymall">
</Host>
|
然后修改Engine标签(104行)
<Engine name="Catalina" defaultHost="www.easymall.com">
|
最后修改hosts文件(C:\Windows\System32\drivers\etc\hosts),加入如下配置:
(3)将EasyMall项目部署到www.easymall.com主机中, 并将项目配置缺省的WEB应用, 并配置主页!
部署WEB应用到虚拟主机中的方式:
方式一:
<Context path=”” docBase=”D:\softspace\Workspaces\BIG_1707\EasyMall\WebRoot” />
第一种方式不推荐, 每次配置完后都需要重启服务器.
方式二:
<Context docBase=”D:\softspace\Workspaces\BIG_1707\EasyMall\WebRoot” />
方式三: 直接将WEB应用部署到www.easymall.com主机默认管理的目录下即可!
![javascript电商项目 web电商项目_数据库](https://s2.51cto.com/images/blog/202307/22055748_64baff5ca814053502.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
![javascript电商项目 web电商项目_数据库_02](https://s2.51cto.com/images/blog/202307/22055748_64baff5cbd5e277053.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
配置完成后,之间访问www.easymall.com,如果可以进入首页,证明配置正确。
3.2.导入静态页面
采用jsp展示页面, jsp暂时可以理解为可以写java代码html
(1)可以将index.jsp中其他代码去掉,只保留第一行,编码改为utf-8
例如:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
|
(2)然后复制index.jsp,起名为_head.jsp、_foot.jsp、regist.jsp、login.jsp
(3)在课前资料中EasyMall静态页面下,分别找到head、foot、index、login、regist文件夹,其中找到对应的html文件,编辑器打开,全选复制,放入到对应的jsp中,注意不要把jsp中第一行去掉了。同时,将css和img文件夹复制到WebRoot目录下(提示是否覆盖,点击Yes To All)
(4)在index.jsp中包含头部和尾部
在body最前面加上如下代码: <body>
<!-- 将头部引入进来 -->
<%@ include file="/_head.jsp" %>
在body最后面加上如下代码:
<!-- 将尾部引入进来 -->
<%@ include file="/_foot.jsp" %>
</body>
|
(5)修改_head.jsp中登录和注册的跳转路径
<a href="<%= request.getContextPath() %>/login.jsp">登录</a>
<a href="<%= request.getContextPath() %>/regist.jsp">注册</a>
|
(6)将所有jsp中引入css或者image的路径全部改为绝对路径,这样更稳定。
修改时只需要在相对路径前面加上“<%= request.getContextPath() %>/”代码,就可以动态获取虚拟路径,不要写死了。
_head.jsp中需要改3处。
_foot.jsp中需要改1处。
login.jsp中需要改1处。
regist.jsp中需要改2处。
index.jsp中需要改14处。
最后,访问www.easymall.com,如果可以访问,说明修改无误。
3.3.实现注册功能1
1.修改form中action属性,访问后台servlet
2.新建servlet
3.解决参数乱码
4.获取请求参数
5.数据的校验:非空验证、两次密码是否一致、邮箱格式、验证码、用户名不能重复、如果验证失败、跳转回注册页面,并将提示信息带到注册页面(请求转发)
6.注册用户
7.提示成功,3秒回首页
(1)修改regist.jsp中的表单提交的地址
<form action="<%= request.getContextPath() %>/servlet/RegistServlet" method="POST">
|
(2)创建包cn.tedu.web,创建servlet:RegistServlet。
- 1. 处理请求乱码
//1.处理请求参数问题(post)
request.setCharacterEncoding("utf-8");
//处理响应正文乱码
response.setContentType("text/html;charset=utf-8");
|
- 2. 获取请求参数
//2.获取请求参数(用户提交的注册数据)
String username = request.getParameter("username");
password
password2
nickname
email
valistr
|
- 3. 校验数据
//非空校验
由于每个参数都需要判断是否为空或者为null,可以创建工具类抽取方法:
创建包:cn.tedu.utils,创建类WebUtils,添加如下代码:
//构造方法私有化,防止别人创建示例
private WebUtils(){}
/**
* 检查字符串是否为空字符串或者null
* @param str
* @return boolean true表示空字符串或者null
*/
publicstaticboolean isNull(String str){
return str == null || "".equals(str.trim());
}
|
RegistServlet中继续添加如下代码: //3.校验数据
//>>非空校验
if(WebUtils.isNull(username)){
//将提示存入request域中,通过转发将消息带到regist.jsp中
request.setAttribute("msg", "用户名不能为空!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
if(WebUtils.isNull(password)){
//将提示存入request域中,通过转发将消息带到regist.jsp中
request.setAttribute("msg", "密码不能为空!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
if(WebUtils.isNull(password2)){
//将提示存入request域中,通过转发将消息带到regist.jsp中
request.setAttribute("msg", "确认密码不能为空!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
if(WebUtils.isNull(nickname)){
//将提示存入request域中,通过转发将消息带到regist.jsp中
request.setAttribute("msg", "昵称不能为空!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
if(WebUtils.isNull(email)){
//将提示存入request域中,通过转发将消息带到regist.jsp中
request.setAttribute("msg", "邮箱不能为空!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
if(WebUtils.isNull(valistr)){
//将提示存入request域中,通过转发将消息带到regist.jsp中
request.setAttribute("msg", "验证码不能为空!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
|
//密码一致校验
//两次密码是否一致
if(!password.equals(password2)){
//将提示存入request域中,通过转发将消息带到regist.jsp中
request.setAttribute("msg", "两次密码不一致!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
|
//邮箱格式校验
//邮箱格式校验
abc@sina.com.cn
if(!email.matches("^\\w+@\\w+(\\.\\w+)+$")){
//将提示存入request域中,通过转发将消息带到regist.jsp中
request.setAttribute("msg", "邮箱格式不正确!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
|
//验证码是否正确(以后做,需要用到session)
//TODO --此注释可以在Tasks栏中看到并点开。
- 4. 实现注册
首先,导包,将c3p0和mysql的驱动包导入到WEB-INF下的lib文件夹中(无需build path)。 然后,将c3p0配置文件放到src根目录下,注意数据库改为easymall。 在mysql中创建easymall数据库和user表,并插入数据(直接执行课前资料中的sql脚本)。 |
在cn.tedu.utils包中创建JDBCUtils类,并加入释放资源代码: private JDBCUtils(){} /**
* 释放资源
* @param conn 连接对象
* @param stat 传输器对象
* @param rs 结果集对象
*/
publicstaticvoid close(Connection conn,Statement stat,ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}
if(stat != null){
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
stat = null;
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
}
|
写代码时发现,如果将连接池创建在RegistServlet中,则每次需要连接数据库都要创建一个连接池,所以可以将创建连接池代码放在JDBCUtils中,并提供获取连接池的方法和获取连接的方法,代码如下: privatestatic ComboPooledDataSource pool = new ComboPooledDataSource();
private JDBCUtils(){}
/**
* 获取连接池的方法
* @return DataSource
*/
publicstatic DataSource getPool(){
returnpool;
}
/**
* 从连接池中获取一个连接
* @return Connection
*/
publicstatic Connection getConnection(){
try {
returnpool.getConnection();
} catch (SQLException e) {
e.printStackTrace();
thrownew RuntimeException();
}
}
|
在RegistServlet中加入如下代码: //4.实现注册(将用户注册数据保存到数据库中)
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//从连接池中获取连接
conn = JDBCUtils.getConnection();
//获取传输器
String sql = "insert into user values(null,?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
ps.setString(3, nickname);
ps.setString(4, email);
sql语句
executeUpdate();
} catch (Exception e) {
e.printStackTrace();
thrownew RuntimeException();
}finally{
//释放资源
JDBCUtils.close(conn, ps, rs);
}
|
//用户名是否存在验证
为了减少代码,可以将用户名是否存在验证放到注册代码中,在将注册信息插入到数据库之前先进行用户名验证,如果用户名已经存在,则提示用户,并且不要将数据写入到数据库。
在获取连接后插入如下代码: //从连接池中获取连接
conn = JDBCUtils.getConnection();
//>>用户名是否存在(如果存在,跳转回注册页面并提示)
String sql = "select * from user where username=?";
ps = conn.prepareStatement(sql);
ps.setString(1, username);
rs = ps.executeQuery();
if(rs.next()){ //用户名已存在
request.setAttribute("msg", "用户名已存在!");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
|
- 5. 提示用户注册成功, 3秒之后将会跳转到首页!
//5.提示用户注册成功,3秒后跳转到首页。
response.getWriter().write("<h1 style='color:red;text-align:center'>恭喜您注册成功,3秒之后跳转回首页...</h1>");
response.setHeader("refresh", "3;url="+request.getContextPath()+"/index.jsp");
|
问题一:无提示信息
此时,虽然提示信息放入到request域中,但是页面中并未获取,需要在页面中获取后才能显示。
在regist.jsp中的table中添加如下代码:
<table>
<tr>
<td colspan="2" style="color:red;text-align: center">
<%= request.getAttribute("msg") == null? "" : request.getAttribute("msg") %>
</td>
</tr>
|
问题二:无回显
当注册提交后,如果提交信息错误,转发回注册页面,发现之前所写的所有信息都为空了,需要重新填写,所以应该让之前的数据回显。
在regist.jsp中每个input中加入回显代码,例如: <input type="text" name="username" value="<%=request.getParameter("username") == null? "" : request.getParameter("username")%>"/>
|
问题三:验证码并非动态生成
验证码应该是动态生成,写验证码的java程序有很多,在课前资料中已经提供一个,可以直接拿过来用。
将课前资料resource中的VerifyCode.java程序拷贝到utils包中,这是一个生成验证码图片的类 |
在regist.jsp中,将验证码图片的访问路径改为: <img src="<%= request.getContextPath() %>/servlet/ValiImageServlet" alt="" />
|
在web包中创建servlet:ValiImageServlet,在doGet()中添加如下代码: //控制浏览器不要缓存图片
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "no-cache");
VerifyCode vc = new VerifyCode();
//将图片保存到response缓冲区中,再响应给浏览器
vc.drawImage(response.getOutputStream());
|