购物网站系统部分需求分析和设计
一.需求分析
1.首页需求
标题首页需要展示商品分类、热门标签、特价热销商品信息以及七个最新的公告和新闻动态,如果用户有访问过商品信息,那么还要在最近浏览中显示浏览过的商品。
页面存在的数据类型及其功能
1.分类导航标签 (超链接)
点击不同的分类,查询对应的商品列表
有数据,显示商品列表;
无数据,显示提示信息;
2.热门导航标签 (超链接)
点击热门标签,查询对应的商品列表
有数据,显示商品列表;
无数据,显示提示信息;
3.购物车 (文本链接)
(1)未登录状态
显示购物车,点击购物车,提示用户需要先登录
(2)登录状态
显示购物车及购物车中商品的数量,点击购物车,跳转到购物车页面
4.用户名/登录(文本链接)
(1)未登录状态
显示登录,点击登录,跳转到登录页面
(2)登录状态
显示登录用户名,点击用户名,跳转到个人中心页面
5.注册 (文本链接)
点击链接,跳转到注册页面
6.留言 (文本链接)
点击链接,跳转到留言页面
7.注销 (文本链接)
点击后提示用户是否确认退出系统,如果是,注销当前登录用户,并返回到首页
8.关键字查询(文本输入框)
可以输入关键字查询指定商品
9.搜索 (按钮)
点击按钮,通过关键字查询商品列表
有数据,显示商品列表;
无数据,显示提示信息;
10.商品分类 (文本链接)
显示商品的分类及对应的子分类,点击子分类,查询具体类型的商品列表
有数据,显示商品列表;
无数据,显示提示信息;
11.最近浏览 (图文链接)
用户浏览过的商品信息,点击图文链接,在新窗口打开商品详情页
12.今日特价(图文链接)
点击图文链接,在新窗口打开商品详情页,并将该商品显示在最近浏览中
13.热卖推荐 (图文链接)
点击图文链接,在新窗口打开商品详情页,并将该商品显示在最近浏览中
14.最新公告 (文本链接)
显示当前最新的的公告列表,点击链接,跳转到公告详情页
15.新闻动态 (文本链接)
显示当前最新的的新闻动态列表,点击链接,跳转到新闻动态详情页
2.商品搜索
关键字搜索:输入关键字,点击搜索完成商品的搜索。如果存在商品那么就分页展示商品的名称、价格以及图片。如果商品不存在,显示提示信息。分类搜索:点击左侧商品分类进行查询。
页面存在的数据类型及其功能
1.全部商品 (图文链接)
分页显示商品列表,点击图片链接,跳转到商品详情
2.分页导航 (文本链接)
点击链接,可查询指定页的商品列表
3.商品详情
显示商品的基本信息以及图片,并能购买和添加购物车,如果用户点击购或者加入购物车,那么必须要判断是否登录。
页面数据项及其功能:
1.商品名称 (文本)
2.商品图片 (图片)
3.商品价格 (文本)
4.商品库存 (文本)
5.购买 (按钮)
未登录状态
弹出提示消息,提示用户需要先登录
登录状态
将商品加入购物车,并跳转到结算页面
6.加入购物车 (超链接)
未登录状态
弹出提示消息,提示用户需要先登录
登录状态
将该商品加入到购物车,提示加入成功
4.用户登录和注册
登录:用户点击顶部登录按钮跳转到登录界面,同时输入用户名、密码、验证码进行登录
页面数据项及其功能:
1.用户名 (文本输入框)
2.登录密码 (密码输入框)
3.验证码 (文本输入框)
4.验证码图片 (图片)
输入验证码,要与验证码图片的值一致,加载验证码图片,点击可切换验证码
5.立即登录 (按钮)
(1) 判断用户名、登录密码、验证码是否为空
(2) 判断用户名和密码是否正确
(3) 判断验证码是否正确
(4) 验证通过,则登录成功,跳转到首页
注册:点击顶部注册按钮进行注册,注册时需要校验用户名是否唯一(需要注册些什么自己分析)
页面数据项及其功能:
1.用户名 (文本输入框)
用户名,必填项
若未输入值,则失去焦点时,提示用户,用户名不能为空;
若已输入值,则失去焦点时,会验证用户名是否已存在;如果已存在,则提示用户;
2.登录密码 (密码输入框)
3.确认密码 (密码输入框)
4.性别 (单选框)
5.出生日期 (日期框)
6.身份证号 (文本输入框)
7.Email (文本输入框)
8.手机号码 (文本输入框)
9.收货地址 (文本输入框)
10.提交注册 (按钮)
(1) 判断必填字段不能为空(带"*"都是必填字段)
(2) 判断登录密码是否和确认密码相等
(3) 验证登录,则提示注册成功,跳转到首页
5.购物车
订单:当用户购买或者在购物车中进行结算时进入下单界面就可以生成订单。用户登录后,可以选择购买或者加入购物车。加入购物以后,可以进行购物车的查看,在查看界面时,显示商品列表,可以对购物车进行操作,比如增加和删除购买数量、删除购物车商品、显示收货人地址、点击进行结算。
1.商品名称 (图文链接)
显示商品的图片和名称,点击可跳转到商品详情页
2.商品单价 (文本)
3.金额 (文本)
4.购买数量 (文本输入框、按钮)
用户每次商品详情页点击购买或加入购物车,该商品的数量都会加1。如果购物车中没有这件商品,则添加一天记录,数量显示1。
点击输入框两旁的"-“和”+"按钮可以控制数量的减少和添加,数量最少只能减到1。也可以直接在输入框中输入数值。数量的变化会影响商品总金额的变化。
5.删除操作 (超链接)
点击删除,提示确认消息,如果确认删除,则在购物车中删除该商品。
6.结算 (按钮)
点击结算按钮,清空购物车数据,生成订单,提示用户结算成功,跳转到首页。
7.商品金额总计 (文本)
通过金额和数量计算得到,更新数量会同时改变总金额的值
8.个人信息 (文本)
显示当前登录用户的用户名、手机号及收货地址。
6.留言
1.留言列表 (列表)
分页显示留言列表,显示留言者的昵称、留言时间、留言内容以及官方回复内容。每页显示3条记录。
2.分页导航栏 (超链接)
点击超链接,可以显示指定页的留言数据
3.昵称 (文本框)
4.留言内容 (文本域)
5.提交留言 (按钮)
点击提交留言按钮,判断昵称和留言内容是否为空,如果为空提示用户;不为空则将提交的留言信息显示在留言列表。
7.个人信息,订单管理,最新公告,新闻动态
二、部分模块实现代码
1.注册模块
前台(包括css样式)就代码不展示了
Servlet类
@WebServlet("/userServlet")
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private UserService userService = new UserServiceImpl();
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的oper
String oper = req.getParameter("oper");
if(!"".equals(oper)&&oper!=null&&"register".equals(oper)){
try {
register(req,resp);
} catch (Exception e) {
e.printStackTrace();
}
} else if(!"".equals(oper)&&oper!=null&&"checkName".equals(oper)) {
checkName(req,resp);
}
}
//注册
private void register(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//获取请求参数
String userName = req.getParameter("userName");
String password = req.getParameter("password");
String sex = req.getParameter("sex");
Date birthday = DateUtil.formatString(req.getParameter("birthday"), "yyyy-MM-dd");
String dentityCode = req.getParameter("dentityCode");
String email = req.getParameter("email");
String mobile = req.getParameter("mobile");
String address = req.getParameter("address");
//构建对象
User user = new User(userName, password, sex, birthday, dentityCode, email, mobile, address);
//添加
userService.register(user);
//跳转
req.getRequestDispatcher("/reg-result.jsp").forward(req, resp);
}
}
//检查用户名是否唯一
private void checkName(HttpServletRequest req, HttpServletResponse resp) throws
IOException {
String uname = req.getParameter("userName");
boolean flag=userService.checkName(uname);
PrintWriter out = resp.getWriter();
out.print(flag);
}
service接口
public interface UserService {
//注册
void register(User user);
//检查用户名是否唯一
boolean checkName(String uName);
}
serviceImpl
public class UserServiceImpl implements UserService{
//注册
@Override
public void register(User user) {
//声明连接
Connection conn = null;
try{
//获取连接通道
conn = DBUtil.getConn();
String sql = "INSERT INTO T_USER (ADDRESS,BIRTHDAY,DENTITYCODE,"
+ "EMAIL,MOBILE,PASSWORD,SEX,STATUS,USERNAME) VALUES ("
+ "?,?,?,?,?,?,?,?,?)";
//设置绑定变量
Object[] pars=new Object[]{
user.getAddress(),user.getBirthday(),
user.getDentityCode(),user.getEmail(),
user.getMobile(),user.getPassword(),
user.getSex(),user.getStatus(),
user.getUserName()
};
QueryRunner qr=new QueryRunner();
qr.update(conn, sql, pars);
}catch(Exception e){
System.out.println("register ERROR");
e.printStackTrace();
}finally{
DBUtil.closeConn(conn);
}
}
//检查用户名是否唯一
@Override
public boolean checkName(String uName) {
boolean flag = false;
//声明连接
Connection conn = null;
try {
//获取
conn = DBUtil.getConn();
String sql = "SELECT * FROM T_USER WHERE USERNAME = ?";
//设置绑定变量
Object[] pars = new Object[] {uName};
QueryRunner qr = new QueryRunner();
User ls = (User) qr.query(conn, sql, new BeanHandler(User.class), pars);
//查询一个结果new BeanHandler(实体类.class)
if(ls==null){
flag = true;
}
}catch(SQLException e) {
System.out.println("checkName error");
e.printStackTrace();
}finally {
DBUtil.closeConn(conn);
}
return flag;
}
}
2.登录模块
Servlet类
@WebServlet("/userServlet")
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String error = "";
private UserService userService = new UserServiceImpl();
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的oper
String oper = req.getParameter("oper");
//请求分发
if(!"".equals(oper)&&oper!=null&&"register".equals(oper)){
try {
register(req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}else if(!"".equals(oper)&&oper!=null&&"login".equals(oper)) {
userLogin(req,resp);
}
}
//登陆
private void userLogin(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
//获取请求参数 准备登陆
String uname = req.getParameter("userName");
String pwd = req.getParameter("password");
String imageCodeInput = req.getParameter("imageCode");
//获取Session对象 获取存储的验证码
String imageCode = (String) req.getSession().getAttribute("sRand");
User user = new User(uname,pwd);
if(imageCodeInput.equals(imageCode)){
//判定用户是否注册
User currentUser= userService.login(user);
if(currentUser!=null) {
//存储作用域
req.getSession().setAttribute("currentUser", currentUser);
//跳转页面
req.getRequestDispatcher("/index").forward(req, resp);
return;
}else {
error = "用户名或者密码错误";
}
}else {
//跳转页面
error = "验证码错误";
}
req.setAttribute("error",error);
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
Service
public interface UserService {
void register(User user);
User login(User user);
}
ServiceImpl类
//登陆
@Override
public User login(User user) {
User u = null;
//声明连接
Connection conn = null;
try {
//获取
conn = DBUtil.getConn();
String sql = "SELECT * FROM T_USER WHERE USERNAME = ? AND PASSWORD = ?";
//设置绑定变量
Object[] pars = new Object[] {user.getUserName(),user.getPassword()};
QueryRunner qr = new QueryRunner();
u = (User) qr.query(conn, sql, new BeanHandler(User.class), pars);
}catch(SQLException e) {
e.printStackTrace();
}finally {
DBUtil.closeConn(conn);
}
return u;
}
3.用户注销
销毁session,退出当前用户
servlet
if(!"".equals(oper)&&oper!=null&&"logout".equals(oper)) {
logout(req,resp);
}
private void logout(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//清空session
req.getSession().invalidate();
//跳转页面
resp.sendRedirect(req.getContextPath()+"/index.jsp");
}
三.常用的工具类
1.日期格式转换
public class DateUtil {
public static Date formarString(String str ,String format) throws Exception{
if(StringUtil.isEmpty(str)) {
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.parse(str);
}
//当前时间格式化
public static String getCurrentDateStr() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmsss");
return sdf.format(date);
}
}
2.JDBC连接
public class DBUtil {
/**
* 获取数据库的链接
* @return
*/
public static Connection getConnection() {
Connection connection = null;
/**
* 固定数据
*/
/*try {
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java24?useUnicode=true&characterEncoding=UTF-8", "root", "root");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}*/
/**
* 读取配置文件
* 1、在sr目录下创建一个名称为properties的文件
* 2、选择该文件夹,右键,选择Bulid Path,然后选择Use as a Source Folder
* 3、创建db.properties的文件
* 4、设置文件中的属性项(驱动名、数据库连接路径、数据库用户名、数据库密码)
* 5、得到配置文件的输入流
* 6、创建配置对象
* 7、将输入流加载到配置对象中,调用load()方法
* 8、获取配置对象中的属性 properties.getProperty(key) :key值要与db.properties文件中的属性名保持一致
* 9、加载驱动
* 10、获取数据库连接
*/
try {
// 得到配置文件的输入流
InputStream in = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");
// 创建配置对象
Properties properties = new Properties();
// 将输入流加载到配置对象中,调用load()方法
properties.load(in);
// 获取配置对象中的属性 properties.getProperty(key)
String jdbcName = properties.getProperty("jdbcName");
String url = properties.getProperty("dbUrl");
String name = properties.getProperty("dbName");
String pwd = properties.getProperty("dbPwd");
// 加载驱动
Class.forName(jdbcName);
// 获取数据库连接
connection = DriverManager.getConnection(url, name, pwd);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
/**
* 关闭资源
* @param resultSet
* @param preparedStatement
* @param connection
*/
public static void close(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection) {
try {
// 判断对象是否为空,不为空则关闭
if (resultSet != null) {
resultSet.close();
}
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null) {
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
3.MD5加密字符串
public class MD5Util {
public static String encode(String str){
String value = "";
try {
// 得到MD5算法的应用程序对象
MessageDigest messageDigest = MessageDigest.getInstance("md5");
// 通过md5算法加密字符串,得到byte数组
byte[] bytes = messageDigest.digest(str.getBytes());
// 通过Base64编码,将byte数组转换乘字符串
value = Base64.encodeBase64String(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return value;
}
public static void main(String[] args) {
System.out.println(encode("123456"));
}
}
4.分页工具类
public class PageUtil {
/**
* 通过传入参数进行分页操作
* @param tageUrl 目标地址
* @param totalNum 总记录数
* @param currentPage 当前页面数
* @param pageSize 每页显示数
* @return
*/
public static String getPagingByPageSize(String tageUrl,long totalNum,int currentPage,int pageSize) {
// 总页码数
long totalPage = totalNum % pageSize == 0 ? (totalNum/pageSize) : (totalNum/pageSize+1);
//为0判断
if (totalPage==0) {
return "未查询到数据信息";
}
StringBuffer pageCode = new StringBuffer();
// 显示首页
pageCode.append("<li><a href='"+tageUrl+"&page=1'>首页</a></li>");
if (currentPage>1) {
// 显示上一页
pageCode.append("<li><a href='"+tageUrl+"&page="+(currentPage-1)+"'>上一页</a></li>");
}
if (currentPage-2>1) {
pageCode.append("<li><a>"+"..."+"</a></li>");
}
for (int i = currentPage-2; i < currentPage+3; i++) {
if (i<1||i>totalPage) {
continue;
}
if (currentPage==i) {
pageCode.append("<li><a style='opacity: 0.4'>"+i+"</a></li>");
}else {
pageCode.append("<li><a href='"+tageUrl+"&page="+i+"'>"+i+"</a></li>");
}
}
if (currentPage+1<=totalPage) {
pageCode.append("<li><a>"+"..."+"</a></li>");
}
// 显示下一页
if (currentPage<totalPage) {
pageCode.append("<li><a href='"+tageUrl+"&page="+(currentPage+1)+"'>下一页</a></li>");
}
// 显示尾页
pageCode.append("<li><a href='"+tageUrl+"&page="+totalPage+"'>尾页</a></li>");
return pageCode.toString();
}
}
5.字符串工具类
public class StringUtil {
/**
* 判断字符串是否为空
* @param str
* @return
*/
public static boolean isEmpty(String str) {
if (null == str || "".equals(str.trim())) {
return true;
}
return false;
}
/**
* 判断字符串是否不为空
* @param str
* @return
*/
public static boolean isNotEmpty(String str) {
if (null == str || "".equals(str.trim())) {
return false;
}
return true;
}
}
总结
整个购物网站需求分析较多,至于有些模块并没有写到这里。第一部分需求分析也只是展示出来仅供提供思路(太多了写不下)。第二部分的部分模块代码(仅供借鉴,作用不大)只展示了后台代码,前台页面设计包括css样式之类的并没有展示。第三部分是常用的工具类(也就这里有点价值)。