一、项目介绍
今天是1024哦,忙碌的程序猿们加班之余不要忘了来优家益购买适合自己的商品哦,今天给大家打8.8折,本商城有配件、服饰、家用三大种类商品,满足程序猿们的日常需求。
优家益购分为用户、购物车、订单、后台四大模块;注册采用Ajax技术实现注册用户名是否重复,登录包含验证码的校检,商城采用过滤器技术,必须登录才能加购物车和访问其他页面,提交订单时通过session拿到登录用户名,然后显示默认手机号和地址,每个用户有自己的订单和购物车,用户有两种权限,1是普通用户,2是管理员,只有管理员才能访问后台和查看所有用户的订单,后台可以对商品进行增删改查。
优家益购——JavaWeb项目(Jsp+Servlet+MySQL+tomcat)
页面展示
首页
登录
注册
购物车
提交订单
订单查询
订单详情
后台商品管理
编辑商品
二、项目模块
1.用户模块:注册(ajax验证用户名是否存在),登录(验证码的校检),因为商城使用过滤器技术,用户只有登录才能进入其他模块
2.购物车模块:用户可以往购物车里加入商品、删除商品以及清空购物车(通过url传参,设置session,后端操作数据库存储,前端通过el表达式和jstl标签拿值)
3.订单模块:提交订单页可以显示登录用户的默认手机号和收货地址(提交订单页面采用bootstrap响应式布局,点击提交按钮的时候,通过购物车集合的session同时往数据库的订单表和订单详情表添加数据,再把购物车标清空;订单查询页只有管理员才能查询所有的订单,普通用户只能查询自己的订单;订单详情页的数据通过查询数据库订单详情表封装商品对象显示)
4.后台模块:管理员可以对商品进行增删改查,只有管理员才有权限进入后台管理
三、涉及技术
JSP、Servlet、Html、CSS、JS、Bootstrap、JDBC、EL、JSTL、Ajax
dao层:与数据库交互
domain层:实体类
service层:业务类
util层:工具类
web层:过滤器及Servlet
四、数据库设计
costume:服饰表
household:家用表
indent:订单表
indents:订单详情表
mountings:配件表
shopping:购物车表
user:用户表
五、项目细节
1.首页访问数据库设置商品集合和购物车的session,通过el表达式和jstl显示数据
<%
//查询所有配件信息
MountingsDao mDao = new MountingsDao();
List<Mountings> mous = mDao.queryAllMous("");
session.setAttribute("mous", mous);
//查询所有服饰信息
CostumeDao cDao = new CostumeDao();
List<Costume> coss = cDao.queryAllCoss("");
session.setAttribute("coss", coss);
//查询所有家用信息
HouseholdDao hDao = new HouseholdDao();
List<Household> hous = hDao.queryAllHous("");
session.setAttribute("hous", hous);
//查询所有购物车信息
String username = (String) request.getSession().getAttribute("username");
User user = new UserDao().checkUsername(username);
ShoppingDao sDao = new ShoppingDao();
List<Shopping> shops = null;
if(user != null) {
shops = sDao.queryAllShops(user);
}
session.setAttribute("shops", shops);
%>
//遍历商品
<c:forEach items="${mous}" var="mou" varStatus="i">
<li>
<a href="shop?msg=add&id=${mou.id}&name=${mou.name}&price=${mou.price}&picture=${mou.picture}&commodity_type=${mou.commodity_type}">
<i class="iconfont icon-ic_jiarugouwuche gwc"></i>
</a>
<img src="${mou.picture}" alt="">
<p>${mou.name}</p>
<span>¥<i>${mou.price}</i></span>
</li>
</c:forEach>
2.通过jstl标签库判断用户权限是否为管理员,el表达式拿session数据
<c:if test="${user.getU_type() == 2}">
<div align="center"><a href="managerServlet?action=list"><p style="color: #f0f1eb">后台管理</p></a></div>
</c:if>
同理判断是否登录
<c:if test="${username eq null}">
<a href="LoginRegister.html"><p style="color: #f0f1eb">登录</p></a>
</c:if>
<c:if test="${username ne null}">
<div align="center"><p style="color: white">${username}</p></div>
<a href="quitServlet" onclick="showYesMsg()"><br/><p style="color: #f0f1eb">退出</p></a>
</c:if>
同理判断购物车是否为空
<c:if test="${shops.size() eq 0}">
<div class="operation">
<div class="del" onclick="showNoMsg()">
清除购物车
</div>
<div class="submit" onclick="showNoMsg()">
提交订单
</div>
</div>
</c:if>
<c:if test="${shops.size() ne 0}">
<div class="operation">
<a href="shop?msg=delAll&id=1&name=1&price=1&picture=1&commodity_type=1">
<div class="del" onclick="showYesMsg()">
清除购物车
</div>
</a>
<a href="indent.jsp">
<div class="submit" onclick="showYesMsg()">
提交订单
</div>
</a>
</div>
</c:if>
3.遍历购物车商品并拿到购物车商品总价,把总价和数量设置为session
<!-- 购物车列表 -->
<div class="shoppingCart" style="color: #f0f1eb">
<div class="title">
<i class="iconfont icon-jiantouarrow483"></i>
<span class="text">我的购物车</span>
<span><i>${shops.size()}</i>件商品</span>
</div>
<div class="pro_list" >
<ul>
<c:forEach items="${shops}" var="shop" varStatus="i">
<li>
<a href="shop?msg=del&id=${shop.commodity_id}&name=${shop.name}&price=${shop.price}&picture=${shop.picture}&commodity_type=${shop.commodity_type}"
onclick="showYesMsg()">
<i class="iconfont icon-jianhao sub" style="color: #f0f1eb"></i>
</a>
<div class="content">
<img src="${shop.picture}"/>
<div class="center">
<p>数量<i>${shop.num}</i></p>
<p class="title">${shop.name}</p>
</div>
<div class="price">
<span>小计:</span>
<span class="xj">${shop.price*shop.num}</span>
</div>
</div>
</li>
<c:set value="${num+shop.num}" var="num" scope="session"/>
<c:set value="${sum+shop.price*shop.num}" var="sum" scope="session"/>
</c:forEach>
</ul>
</div>
<div class="total">
<p><span class="left">总计</span><span class="right"><i class="sum">${sum}</i></span></p>
</div>
</div>
注意每次重新访问index.jsp清除session
//清空总价格和数量缓存
session.setAttribute("sum", 0);
session.setAttribute("num", 0);
4.ajax判断用户名是否存在
var flag;
function checkUser() {
//1.创建核心对象
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//2. 建立连接
var username = document.getElementById("username").value;
//xmlhttp.setRequestHeader("If-Modified-Since", "0");//get清空缓存
//POST清空缓存
// xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.open("GET","checkUserServlet?username=" + username,true);
//3.发送请求
xmlhttp.send();
//4.接受并处理来自服务器的响应结果
//获取方式 :xmlhttp.responseText
//什么时候获取?当服务器响应成功后再获取
//当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange。
xmlhttp.onreadystatechange=function()
{
//判断readyState就绪状态是否为4,判断status响应状态码是否为200
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//获取服务器的响应结果
var responseText = xmlhttp.responseText;
var msg = document.getElementById("sp_username");
if("success" == responseText){
msg.innerHTML = "该用户名可以使用";
flag = true;
} else {
msg.innerHTML = "该用户已存在,请重新输入用户名";
flag = false;
}
}
}
}
function checkForm(){
return flag;
}
5.过滤器判断是否登录,拦截请求,及设置请求响应编码(项目遇到的最大的坑就是这个了,假如没登录不放行,就会出现一个无限登录bug,点哪里请求被拦截进入登录页面,登录之后再点那个请求照样会跳到登录页面,同时浏览器会有缓存,要同时清缓存和放行才能修复bug)
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1.强制转换
HttpServletRequest request = (HttpServletRequest) req;
//2.获取资源请求路径
String uri = request.getRequestURI();
//3.判断是否包含登录相关资源路径,要注意排除掉 css/js/图片/验证码等资源
if(uri.contains("index.jsp") || uri.contains("login.html") || uri.contains("registerServlet")
|| uri.contains("register.html") || uri.contains("loginServlet") || uri.contains("LoginRegister.html")
||uri.contains("/css/") || uri.contains("/js/") || uri.contains("checkUserServlet")
|| uri.contains("/img/") || uri.contains("checkCodeServlet")){
//包含,用户就是想登录。放行
chain.doFilter(req, resp);
}else{
//不包含,需要验证用户是否登录
//3.从获取session中获取user
Object user = request.getSession().getAttribute("username");
if(user != null){
//登录了。放行
chain.doFilter(req, resp);
}else{
//没有登录。跳转登录页面
request.setAttribute("login_msg","您尚未登录,请登录");
request.getRequestDispatcher("LoginRegister.html").forward(request,resp);
//也要放行
chain.doFilter(req, resp);
}
}
}
6.首页通过url传参跳转Servlet添加商品到购物车,再重定向到首页
<c:forEach items="${mous}" var="mou" varStatus="i">
<li>
<a href="shop?msg=add&id=${mou.id}&name=${mou.name}&price=${mou.price}&picture=${mou.picture}&commodity_type=${mou.commodity_type}"
onclick="showYesMsg()">
<i class="iconfont icon-ic_jiarugouwuche gwc"></i>
</a>
<img src="${mou.picture}" alt="">
<p>${mou.name}</p>
<span>¥<i>${mou.price}</i></span>
</li>
</c:forEach>
7.根据下单时间和用户id生成订单号
<%
//获取用户session
User user = (User) request.getSession().getAttribute("user");
//将int类型转换为String
String u_id = user.getU_id() + "";
//获取当前时间
Date now = new Date();
//规定时间格式
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//转换成指定格式的字符串
String date = df.format(now);
//设置当前时间的session
request.setAttribute("date", date);
//规定时间格式
DateFormat df2 = new SimpleDateFormat("yyyyMMddHHmmss");
//生成订单号
String indent_id = df2.format(now) + u_id;
//设置订单号的session
request.setAttribute("indent_id", indent_id);
%>
8.form变得input输入框的值不能修改
<input type='text' name='num' readonly unselectable='on' value='${num}' required><br>
9.提交订单的时候通过购物车的session同时操作数据库的订单表和订单详情表
package com.beizhen.web.servlet;
import com.beizhen.dao.UserDao;
import com.beizhen.domain.Indent;
import com.beizhen.domain.Indents;
import com.beizhen.domain.Shopping;
import com.beizhen.domain.User;
import com.beizhen.service.IndentService;
import com.beizhen.service.IndentsService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @author : Bei-Zhen
* @date : 2020-10-22 3:21
*/
@WebServlet("/indent")
public class IndentServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求参数
String address = request.getParameter("address");
String telnum = request.getParameter("telnum");
String num = request.getParameter("num");
String indent_date = request.getParameter("indent_date");
String price = request.getParameter("price");
String username = (String)request.getSession().getAttribute("username");
String indent_id = request.getParameter("indent_id");
User user = new UserDao().checkUsername(username);
Indent indent = new Indent(0,address,telnum,Integer.parseInt(num),indent_date,Double.parseDouble(price),user.getU_id(),indent_id);
//往数据库添加订单
new IndentService().addInd(indent,user);
//获取购物车所有商品
List<Shopping> shops = (List<Shopping>) request.getSession().getAttribute("shops");
//遍历购物车集合
for (int i = 0; i < shops.size(); i++) {
//封装订单详情对象
Indents indents = new Indents(0,shops.get(i).getCommodity_id(),
shops.get(i).getCommodity_type(),shops.get(i).getNum(),indent_id,user.getU_id());
//往数据库添加订单详情
new IndentsService().addInd(indents,user);
}
//重定向到订单查询页面
response.sendRedirect("show_indent.jsp");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
10.通过url传参订单号,根据所有订单详情查询订单详情展示集合,设置订单详情展示集合session,在订单详情页显示数据
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取参数
String indent_id = request.getParameter("indent_id");
//根据订单号查询所有相关的订单的详情
List<Indents> indents = new IndentsService().selInds(indent_id);
//设置订单号session
request.getSession().setAttribute("indent_id",indent_id);
//封装订单详情展示集合
List<Indentdetails> indentdetails = new IndentsService().selIndtails(indents);
//设置订单详情展示集合session
request.getSession().setAttribute("indentdetails",indentdetails);
//重定向到订单详情页
response.sendRedirect("indents.jsp");
}
/**
* 根据所有订单详情查询订单详情展示集合
* @param indss 订单详情集合
* @return 订单详情展示对象集合
*/
public List<Indentdetails> selIndtails(List<Indents> indss){
//订单详情展示对象集合
List<Indentdetails> indentdetails = new ArrayList<>();
//遍历订单详情集合
for (int i = 0; i < indss.size(); i++) {
//根据商品id和商品类型查询具体商品
Commodity com = new CommodityDao().queryComs(indss.get(i).getCommodity_id(),
indss.get(i).getCommodity_type());
//订单详情展示对象
Indentdetails indetails = new Indentdetails();
//分别给它赋值
indetails.setName(com.getName());
indetails.setPicture(com.getPicture());
indetails.setPrice(com.getPrice());
indetails.setNum(indss.get(i).getCommodity_num());
//添加到集合
indentdetails.add(indetails);
}
return indentdetails;
}
六、项目共享
https://me.csdn.net/download/qq_33591873