【Web第十三天】EasyMall项目

 

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应用到虚拟主机中的方式:

方式一: 在[tomcat]/conf/server.xml中easymall主机对应的Host标签内部, 添加一个Context标签:

<Context path=”” docBase=”D:\softspace\Workspaces\BIG_1707\EasyMall\WebRoot” />

           第一种方式不推荐, 每次配置完后都需要重启服务器.

 

方式二: 在[tomcat]/conf/Catalina/www.easymall.com目录下添加一个ROOT.xml文件, 文件中的配置如下:

<Context docBase=”D:\softspace\Workspaces\BIG_1707\EasyMall\WebRoot” />

 

方式三: 直接将WEB应用部署到www.easymall.com主机默认管理的目录下即可!

          

 

 

配置完成后,之间访问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");

       String password = request.getParameter("password");

       String password2 = request.getParameter("password2");

       String nickname = request.getParameter("nickname");

       String email = request.getParameter("email");

       String valistr = request.getParameter("valistr");

 

  1. 3.            校验数据

//非空校验

由于每个参数都需要判断是否为空或者为null,可以创建工具类抽取方法:

创建包:cn.tedu.utils,创建类WebUtils,添加如下代码:

//构造方法私有化,防止别人创建示例

    private WebUtils(){}

   

    /**

     * 检查字符串是否为空字符串或者null

     * @param str

     * @return boolean true表示空字符串或者null

     */

    public static boolean 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 结果集对象

     */

    public static void 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中,并提供获取连接池的方法和获取连接的方法,代码如下:

private static ComboPooledDataSource pool = new ComboPooledDataSource();

    private JDBCUtils(){}

   

    /**

     * 获取连接池的方法

     * @return DataSource

     */

    public static DataSource getPool(){

        return pool;

    }

   

    /**

     * 从连接池中获取一个连接

     * @return Connection

     */

    public static Connection getConnection(){

        try {

             return pool.getConnection();

        } catch (SQLException e) {

             e.printStackTrace();

             throw new 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语句

             ps.executeUpdate();

           

        } catch (Exception e) {

             e.printStackTrace();

             throw new 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());

 

 

 

 

 

 

 

 

 

 

 

posted @ 2018-03-21 00:37  songyao  阅读(795)  评论(0编辑  收藏  举报