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),加入如下配置:

127.0.0.1         www.easymall.com  (注意,中间是制表符Tab键)

 

 

(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电商项目_javascript电商项目

 

javascript电商项目 web电商项目_连接池_02

 

配置完成后,之间访问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.            处理请求乱码
//1.处理请求参数问题(post)
       request.setCharacterEncoding("utf-8");
       //处理响应正文乱码
       response.setContentType("text/html;charset=utf-8");

 

  1. 2.            获取请求参数
//2.获取请求参数(用户提交的注册数据)
       String username = request.getParameter("username");
password
password2
nickname
email
valistr

 

  1. 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栏中看到并点开。


  1. 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;
}



  1. 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());