课程设计实战 javaweb购物车和聊天系统
项目概述
本项目是基于javaee相关技术和框架完成的一套功能相对完善的购物车和聊天系统
技术栈
- Java
- Mybatis
- Maven
- Redis
- Jsp+css
主要模块
- 登录
- 注册
- 退出登录
- 聊天
- 购买商品
- 新增商品(用于管理)
数据分表

实体类


运行流程
登录模块
在登录模块中,用户提交用户名和表单到loginservlet,用户service在持久层中判断用户是否为空,以及是否选定了cookie,如果已经登录或者密码错误,显示错误信息并且定向到登录页面,否则将用户的信息取出存到当前session中完成登录
点击查看代码
response.setContentType("text/html;charset=UTF-8");
String username =request.getParameter("username");
username = new String(username.getBytes("iso8859-1"),"utf-8");
String password = request.getParameter("password");
//获取复选框数据
String remember = request.getParameter("remember");
//2. 调用service查询
User user = service.login(username, password);
//3. 判断
if(user != null){
//判断用户是否勾选记住我
if("1".equals(remember)){
//1. 创建Cookie对象
Cookie c_username = new Cookie("username", URLEncoder.encode(username, "UTF-8") );
Cookie c_password = new Cookie("password",password);
System.out.println("Cookie " + c_username );
// 设置Cookie的存活时间
c_username.setMaxAge( 60 * 60 * 24 * 7);
c_password.setMaxAge( 60 * 60 * 24 * 7);
//2. 发送
response.addCookie(c_username);
response.addCookie(c_password);
}
//将登陆成功后的user对象,存储到session
HttpSession session = request.getSession();
session.setAttribute("user",user);
session.setAttribute("userid",user.getId());
session.setAttribute("username",user.getUsername());
jt.save(user.getUsername());
String contextPath = request.getContextPath();
response.sendRedirect(contextPath+"/selectAllServlet");
// response.sendRedirect(contextPath+"/MsgServlet");
}else {
// 登录失败,
// 存储错误信息到request
request.setAttribute("login_msg","用户名或密码错误");
// 跳转到login.jsp
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
注册模块
得到用户注册信息后,程序生成一条验证码,只有用户验证码输入正确后才能调用持久层完成注册,将转码后的数据写入数据库,注册成功后返回一条信息,提示用户登录
点击查看代码
response.setContentType("text/html;charset=UTF-8");
String username = request.getParameter("username");
username = new String(username.getBytes("iso8859-1"),"utf-8");
System.out.println(username);
String password = request.getParameter("password");
User user = new User();
user.setUsername(username);
user.setPassword(password);
// 获取用户输入的验证码
String checkCode = request.getParameter("checkCode");
// 程序生成的验证码,从Session获取
HttpSession session = request.getSession();
String checkCodeGen = (String) session.getAttribute("checkCodeGen");
// 比对
if(!checkCodeGen.equalsIgnoreCase(checkCode)){
request.setAttribute("register_msg","验证码错误");
request.getRequestDispatcher("/register.jsp").forward(request,response);
// 不允许注册
return;
}
//2. 调用service 注册
boolean flag = service.register(user);
//3. 判断注册成功与否
if(flag){
//注册功能,跳转登陆页面
request.setAttribute("register_msg","注册成功,请登录");
request.getRequestDispatcher("/login.jsp").forward(request,response);
}else {
//注册失败,跳转到注册页面
request.setAttribute("register_msg","用户名已存在");
request.getRequestDispatcher("/register.jsp").forward(request,response);
}
}
购物模块
页面左侧显示最新的商品,可以按下一页进行分页查看。页面左侧是购物车进行实时的更新。
点击查看代码
List<Brand> brands = service.selectAll();
List<Brand> cart = service.selectBystatus((User) request.getSession().getAttribute("user"));
int cart1 = service2.sum((User) request.getSession().getAttribute("user"));
//System.out.println(cart1.toString());
System.out.println(cart.toString());
//2. 存入request域中
request.setAttribute("sum",cart1);
request.setAttribute("brands",brands);
request.setAttribute("cart",cart);
request.setAttribute("userid",request.getSession().getAttribute("userid"));
//3. 转发到brand.jsp
request.getRequestDispatcher("/brand.jsp").forward(request,response);
当用户点击按钮,服务器获取到对应的商品id和名字,操作持久层调用sevice完成添加,插入或者删除的工作。
点击查看代码
request.setCharacterEncoding("utf-8");
//1. 接收表单提交的数据,封装为一个Brand对象
String id = request.getParameter("id");
String status = request.getParameter("status");
int userid = Integer.parseInt(request.getParameter("userid"));
String adv = request.getParameter("adv");
String goodsName = request.getParameter("goodsName");
String price = request.getParameter("price");
String brandName = request.getParameter("brandName");
//封装为一个Brand对象
//只有目标值为0时候是insert,1时是删除,其他时候是update
Brand brand = new Brand();
brand.setId(Integer.parseInt(id));
brand.setAdv(adv);
brand.setBrandName(brandName);
brand.setPrice(Integer.parseInt(price));
brand.setGoodsName(goodsName);
brand.setStatus(Integer.parseInt(status));
brand.setUserid(userid);
//加号并且
int check = service2.checknull(brand);
int num = 0;
if (check == 1) {
num = service2.getnum(brand);
}
System.out.println(check);
if (request.getParameter("sign").equals("+")) {
//2. 调用service 完成修改
if(check == 0){
service.cart(brand);
System.out.println("插入一条新商品");}
else{
brand.setStatus(num+1);
service.update(brand);
System.out.println("更新商品数量");
}
} else if ( num == 1) {
service.deleteByUser(brand);
System.out.println("删除一个商品");
}else{
brand.setStatus(num-1);
service.update(brand);
System.out.println("更新商品数量");
}
//3. 转发到查询所有Servlet
request.getRequestDispatcher("/selectAllServlet").forward(request, response);
}
用户可以使用清空购物车来清空当前用户购物车中的所有商品。
点击查看代码
System.out.println("清空购物车");
service.delete((User) request.getSession().getAttribute("user"));
//3. 转发到查询所有Servlet
// request.getRequestDispatcher("/brand.jsp").forward(request,response);
request.getRequestDispatcher("/selectAllServlet").forward(request,response);
聊天模块
在聊天模块中,用户在文本框内输入文字,服务器封装后插入到数据库里,页面默认显示前20条最新信息
点击查看代码
request.setCharacterEncoding("utf-8");
//1. 接收表单提交的数据,封装为一个Msg对象
String username = request.getParameter("username");
String content = request.getParameter("content");
//封装为一个Msg对象
if(content != null && content.length() > 0)
{
Msg msg = new Msg();
msg.setUserName(username);
msg.setContent(content);
service.sendMsg(msg);
}
//3. 转发到查询所有Servlet
request.getRequestDispatcher("/MsgServlet").forward(request, response)
在线列表的显示用监听器完成HttpSessionBindingListener接口提供了和session绑定时监听的方法,在全局监听中建立一个userlist列表,在每次登录时都把当前用户名字加入到list中。当用户登出时,将用户名字remove掉。
实时监听后台中session的数量,因为在不同浏览器中的session不同,可以的登录同一个用户,为了防止这种异常登录,服务器后台用redis来记录登录用户的用户名和id,保存在set中,这样在登录时只需要用工具类对redis数据进行检索就可以避免重复登录。
点击查看代码
Jedis jedis = new Jedis("localhost",6379);
jedis.sadd("username",username);
jedis.expire(username,30);
Set<String> values = jedis.smembers("username");
for (String value : values) {
System.out.println(value);
}
long l=jedis.scard("username");
System.out.println("当前时刻有"+l+"位用户登录记录 有效期10分钟");
jedis.close();
全局工具类
对于全局任意一个页面,都需要在filter检测当前用户是否为空后才可以进行查看。
点击查看代码
String url = req.getRequestURL().toString();
//循环判断
for (String u : urls) {
if(url.contains(u)){
//找到了
//放行
chain.doFilter(request, response);
//break;
return;
}
}
//1. 判断session中是否有user
HttpSession session = req.getSession();
Object user = session.getAttribute("user");
//2. 判断user是否为null
if(user != null){
// 登录过了
//放行
chain.doFilter(request, response);
}else {
// 没有登陆,存储提示信息,跳转到登录页面
req.setAttribute("login_msg","您尚未登陆!");
req.getRequestDispatcher("/login.jsp").forward(req,response);
}
重点详解
为了解决下一个用户打开浏览器后购物车和千亿用户相同的情况,使用用户id状态码的不同形式来进行分表,例如商城中商品的状态码是0,用户的状态码是用户在数据库中的主键,这样保证了用户数据安全性
------
当用户的购物车为0时,进行的语句是插入,数量大于零时进加购进行的sql是更新,等于1且减购时操作为删除数据,否则会导致整个数据表越来越大,查询速度下降,使用一个count函数确定当前的库存状态,从而进一步判定使用的sql语句:还有一种解决办法是利用sql的查询过程,这样开发非常迅速,但是不利于维护,耦合性高。
将登录信息等实时返回到当前页面就避免了用户专门近一个月登录错误的界面,再退出重新登录
在jsp页面中每隔2秒刷新一次消息,并且这个刷新不会利用之前提交的表单信息,也不会导致重复登录。在redis中存储了已经登陆的不重复的名单,服务器管理人员可以通过日志查看异常登陆的用户

浙公网安备 33010602011771号