一、系统概述
系统名称:找本书网上商城
源码下载:https://github.com/LiuJian0806/shopping
系统说明:本系统主要分为两个模块,用户模块及管理员模块。用户模块中,用户能够对商城的商品进行浏览、搜索,并可查看商品的详细信息,加入购物车、收藏商品、购买商品,查看购物车等功能;管理员模块中可以实现添加商品,管理用户订单等功能。
二、程序组成及代码说明
1、 系统设计
系统采用MVC框架开发,实现前端视图及后端数据处理实现分离,提高系统代码的刻度性。在前端开发中,主要采用HTML+CSS+JS进行前端页面开发,并通过AJAX技术实现前后端数据交互,并在视图中做出相应的动作。后端采用servlet技术,对前端的请求进行响应。后端主要分为servlet层、service层、dao层,除此外,系统使用Javabean技术对数据进行封装,servlet层主要实现对前端请求的响应,service层对数据流进行集中管理,dao层主要实现与数据库的交互,包括对数据库的查询、更新、插入等操作。前后端代码结构如下图:
2、 前端设计
页面大部分采用div+css进行开发,主要包括系统主页、商品列表页、商品详情页、用户登录页、用户注册页、用户个人中心页(查看订单、查看购物车等)、管理员登录页、系统管理页(商品添加、查看用户订单)等;页面效果如下:
<1> 主页:
页面效果说明:此页面为用户进入系统时初始展示的页面,页面的相关商品信息均由数据库中加载并显示在页面上,此页面中,提供用户注册及登录的接口,页头会根据用户是否登录显示用户信息,登录后效果如下:
<2> 商品详情页:(用户点击某一商品时,跳转至商品详情页,此操作无需登录)
页面说明:此页面由用户点击某一商品区域后,根据用户选中的商品进入此页面,并展示用户选中商品的详细信息,此页面无需认证用户信息即可进入。在此页面中,用户可以查看商品信息,把商品加入购物车,购买商品等操作,当用户点击加入购物车或购买商品时,系统会检查用户是否登录,如未登录会跳转至用户登录页面,引导用户成功登录后再返回此页面。
<3>、商品列表页
页面说明:此页面主要通过各页面的搜索框进入,用户在各页面搜索框中输入需要查询的商品,点击后跳转至该页面,并显示搜索到的所有商品信息,后台根据搜索内容进行模糊搜索,把搜素到的商品按匹配程度进行展示。此页面同样不需要认证用户身份,加入购物车及收藏时会引导用户登录。
<4>、用户登录页
页面说明:此页面为用户登录页,提供用户注册接口及管理员登录唯一接口,用户输入登录信息中,均使用正则表达式对输入进行验证,同时需要输入验证码信息,只有输入都合法的情况下,系统才会继续提交信息到后台进行身份验证,前端通过后端返回的信息确定用户身份的合法性,合法则分配用户相应权限。
<5>、用户注册页
页面说明:此页面为用户注册页面,用户输入个人相关必要信息进行注册,手机号码为用户在系统中的唯一凭证(一个手机号码只能注册一个账户),在用户输入信息过程中,系统实时进行监控,以判断用户输入的信息合法性,不合法并给出相应提示,如下:
在用户输入手机号码后,系统向后端发送请求,检查该手机号是否注册,并提供用户以提示信息,优化用户体验,提高用户注册效率。
用户注册成功或者遇到其他错误而导致注册失败时,均会跳转至注册结果提示页,并引导用户进行下一步操作,具体页面如下:
<6>、用户个人中心页
页面说明:此页面需要认证用户信息,只有登录的用户才能进入此页面,为防止非法用户通过直接输入该页面地址进入,特别在页面加载中对用户进行验证,非法用户强行进入时,系统会自动转至系统首页,以提高系统的安全性。合法用户进入后,可以通过点击左边的导航栏查看用户个人的相关信息,系统通过用户选中项,向后端发送请求,并把相关信息返回至用户界面。
<7>、管理员登录页
页面说明:此页面提供管理员登录页面,与用户登录相似,系统同样会对输入信息进行校验,管理员帐号不能通过注册获得,只有通过内部人员才能拥有管理员账户。
<8>、管理员管理页面
页面说明:同样,管理员管理页面同样需要认证登入者信息,非法用户也会自动转移到其它不需要认证身份的页面中,以保护系统的信息安全。管理员可以通过左边的导航栏,展开相应的子菜单,选中并进入查看相关信息,对系统进行管理。
3、 前端代码设计
前端主要采用了jquery框架进行开发,使用ajax技术向后端发起请求,使用json数据格式对数据进行处理。前端代码结构如下:
页面主要为.html页面,css样式文件及js文件实现分离,每个html页面对应一个.css文件合.js文件,css文件对页面布局进行渲染,js文件主要实现页面的动态效果以及使用ajax技术向后端发起请求等。
前端代码通过对页面文件、样式文件及脚本文件实行的分理,大大提高了代码的可读性及代码的维护性。在前端代码中,一些需要大量重用的代码集中成一个工具文件,使用时只需要调用相关函数即可,减少了代码量,使得代码更加清晰。
特色代码文件:Tools.js
//string 转 JSON
function change(str) {
var reg = new RegExp("=",“g”);
str = str.replace(reg,"?;
var str1 = “”;
for (var i = 0; i < str.length; i++) {
if (str[i] == “:” || str[i] == “,”) {
str1 = str1 + “’” + str[i] + “’”;
if(str[i] == “,”){
i+=1;
}
} else {
if (str[i] == “{” || str[i] == “}”) {
if (str[i] == “{”) {
str1 = str1 + str[i] + “’”;
} else {
str1 = str1 + “’” + str[i];
break;
}
} else {
if(str[i] == “”){
continue;
}else{
str1 = str1 + str[i];
}
}
}
// console.log(“str=” + str[i] + " str1=" + str1);
}
// console.log(encodeURIComponent(str1)); //查看编码序列
// return JSON.parse(str1);
str1 = eval("(" + str1 + “)”); //转换JSON对象
// alert(typeof str1);
// alert(“pet_name=”+str1.pet_name)
return str1;
}
//封装Cookie
function SetCookie(json) {
console.log(json);
var cookie = “”;
var time = new Date();
time.setTime(time.getTime()+72460601000); //设定七天有效期
for(var key in json){
cookie = key+"="+json[key]+";expires="+time.toUTCString()+";path=/";
document.cookie = cookie;
}
console.log(document.cookie);
}
//查找cookie中的特定值
function getCookie(key){
var arrcookie = document.cookie.split("; “);//分割
//遍历匹配
for ( var i = 0; i < arrcookie.length; i++) {
var arr = arrcookie[i].split(”=");
if (arr[0] == key){
return arr[1];
break;
}else {
continue;
}
}
}
//删除cookie
function deleteCookie(key) {
var time = new Date(); //获取时间
time.setTime(time.getTime() - 12460601000); //设置cookie有效时间为-1天,已到达删除cookie的目的
var value = getCookie(key);
if(value != null) {
document.cookie= key + “=”+value+";expires="+time.toUTCString()+";path=/";
// document.cookie= key + “=”+value+";expires=-1;path:/";
}
}
//批量删除cookie
function deleteCookieGroup(arr) {
for(var temp in arr){
deleteCookie(arr[temp]);
}
}
//string转换arrString
function transitionArrString(data) {
data = data.replace("[","");
data = data.replace("]","");
var arrData = new Array();
var count = 0;
for (var i = 0; i < data.length; i++) {
if (data[i] == “}”) {
arrData[count] = arrData[count] + data[i];
count++;
} else {
if ((data[i] == “,” && data[i + 1] == “{”) || data[i] == “”) {
continue;
} else {
if (data[i] == “{”) {
arrData[count] = “”;
}
arrData[count] = arrData[count] + data[i];
}
}
}
// arrData.pop();
return arrData;
}
//数组转json数组
function arrToJson(data) {
data.forEach(function (temp) {
change(temp);
})
}
4、 后端设计
后端主要使用servlet响应前端请求,后端主要分为四个模块,分别为servlet模块、service模块、dao模块、beans模块。
Servlet模块主要用于响应前端请求,是对前端数据的初次处理,每一个前端请求都对应一个servlet,每个servlet响应不同的请求,servlet层对各种请求进行了划分,便于代码的维护,数据在servlet层进行简单处理后,交由service层对数据进一步进行处理,按请求的需要分配不同的函数,每个函数同样对应dao层的独立一个类,分别实现不同的对数据库的操作,dao层为对数据库的独立操作,避免了用户请求直接访问数据库造成对数据库的安全性减低,dao层实现特定对数据库的不同操作,使代码的独立性得到增强;beans层主要作为数据封装的工具,常常应用于servlet层及dao层对数据的封装,一般来说,每一个bean对应一个数据库表的信息,当然,未来满足特殊的需求,往往也存在一个bean中存在数各数据库表中的字段信息。
数据流图如下:
在后端的设计实现中,数据的传输及对数据库的操作自然时最多的,为了减少代码量,提高代码的重用性,同样对常用的代码进行封装,每次使用时,直接调用该代码块封装函数即可,在数据库操作中,主要封装了JDBCUtil类用于获取数据库连接对象,相关代码如下:
package cn.gzhu.edu.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtils {
private JDBCUtils(){}
private static Connection con;
static{
try{
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/shopping";
String username="root";
String password="123";
con = DriverManager.getConnection(url, username, password);
}catch(Exception ex){
// throw new RuntimeException(ex+“连接数据库失败”);
ex.printStackTrace();
}
}
public static Connection getConnection(){
return con;
}
public static void close(Connection con,Statement stat){
if(stat!=null){
try{
stat.close();
}catch(SQLException ex){}
}
if(con!=null){
try{
con.close();
}catch(SQLException ex){}
}
}
public static void close(Connection con,Statement stat , ResultSet rs){
if(rs!=null){
try{
rs.close();
}catch(SQLException ex){}
}
if(stat!=null){
try{
stat.close();
}catch(SQLException ex){}
}
if(con!=null){
try{
con.close();
}catch(SQLException ex){}
}
}
}
在servlet层进行对数据到前端的传送中,同样封装了数据传输相关类进行操作,相关代码如下:
package cn.gzhu.edu.servlet;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
6、 web.xml配置
在系统开发中,正确配置web.xml文件是实现前后端信息交互的关键,也是大部分错误发生的关键原因之一,一些常见的400、403、404等异常错误信息均有可能由于web.xml文件的配置错误而导致的,因此,正确配置web.xml非常重要,系统web.xml完整配置如下:
html/index.html
html/Reg.html
default.htm
default.jsp
loginCheck
cn.gzhu.edu.servlet.LoginCheckServlet
loginCheck
/loginCheck
register
cn.gzhu.edu.servlet.RegisterServlet
register
/register
phoneCheck
cn.gzhu.edu.servlet.PhoneCheckServlet
phoneCheck
/phoneCheck
ManageLogin
cn.gzhu.edu.servlet.ManageLoginServlet
ManageLogin
/ManageLogin
AddBooks
cn.gzhu.edu.servlet.AddBooksServlet
AddBooks
/AddBooks
loadCommodity
cn.gzhu.edu.servlet.LoadCommodityServlet
loadCommodity
/loadCommodity
loadBook
cn.gzhu.edu.servlet.LoadBookServlet
loadBook
/loadBook
addShoppingCart
cn.gzhu.edu.servlet.AddShoppingCartServlet
addShoppingCart
/addShoppingCart
loadShoppingCart
cn.gzhu.edu.servlet.LoadShoppingCardServlet
loadShoppingCart
/loadShoppingCart
searchCommodity
cn.gzhu.edu.servlet.SearchCommodityServlet
searchCommodity
/searchCommodity