基于Java的网上书城

Temperature

发布日期: 2019-02-12 08:15:38 浏览量: 188
评分:
star star star star star star star star star_border star_border
*转载请注明来自write-bug.com

主要技术

关键字:JSP、servlet、Ajax、jstl、JavaScript、注册登录、分页、购物车、增删改查

开发环境:Eclipse、MySQL 5.7、Tomcat 8.0

数据库表结构设计

books表结构:

items表结构:

orders表结构:

userinfo表结构:

项目包结构

MVC设计模式

M(model层)

  • biz包:业务处理

  • dao包:数据访问,对数据库的一些封装操作

  • entity包:实体类,javabean构建,View层和数据库之间的桥梁作用

V(view层)

1. Jsp页面:与用户进行交互的界面。

C(controller 层)

1.servlet包:控制层,处理View层Jsp页面发来的请求。

注册登录模块

Register

注册页面中form表单

验证用户名、验证密码、验证邮箱

  1. <form method="post" action="RegisterServlet" onsubmit="return checkRegister()">
  2. <dl>
  3. <dt>用 户 名:</dt>
  4. <dd><input class="input-text" type="text" id="username" name="username" onblur="isUsernameLegal()"/><span id="usernull"></span><span id="alreadyExsits"></span></dd>
  5. <dt>密  码:</dt>
  6. <dd><input class="input-text" type="password" id="password" name="password" onblur="isPasswordLegal()" /><span id="nullpassword"><font color=\"green\">密码至少8位</font></span><span id="simplepassword"></span></dd>
  7. <dt>确认密码:</dt>
  8. <dd><input class="input-text" type="password" id="rePassword" name="rePassword" onblur="isRepasswordLegal()" /><span id="nullrePassword"></span><span id="uneq"></span></dd>
  9. <dt>Email地址:</dt>
  10. <dd><input class="input-text" type="text" id="email" name="email" onblur="isEmailLegal()" /><span id="nullemail"><font color=\"green\">请输入正确格式的邮箱</font></span><span id="errorInput"></span></dd>
  11. <dt></dt>
  12. <dd class="button"><input class="input-reg" type="submit" name="register" value="" /></dd>
  13. </dl>
  14. </form>

Ajax(异步 JavaScript 和 XML ):验证用户名是否已被注册,页面部分数据刷新,而无需加载整个网页,提高网站的访问效率。

  1. /**
  2. * Ajax检查用户是否已经被注册
  3. * 异步:发送请求时不等返回结果,由回调函数处理结果
  4. * @returns {Boolean}
  5. */
  6. function isExists() {
  7. var xmlHttp; //定义 xmlHttp XmlHttpRequest对象从服务器异步获取数据后通过javascript修改页面局部信息
  8. try {
  9. //根据不同浏览器初始化不同的xmlHttp浏览器对象
  10. //IE6以上浏览器
  11. xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
  12. } catch (e) {
  13. try {
  14. //FireFox
  15. xmlHttp = new XMLHttpRequest();
  16. } catch (e) {
  17. try {
  18. //IE5.5+
  19. xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  20. } catch (e) {
  21. alert("您的浏览器不支持Ajax");
  22. return false;
  23. }
  24. }
  25. }
  26. var username = document.getElementById("username").value; //获取用户名
  27. /**
  28. * open(提交方式[get|post],url(servlet路径),同步或异步[false|true])
  29. * RegisterServlet: servlet路径
  30. * 打开和后台服务器的链接
  31. */
  32. xmlHttp.open("POST", "RegisterServlet?action=check&username="+username, true); //路径中不能有空格
  33. xmlHttp.send(null); //传送数据
  34. /**
  35. * onreadystatechange:调用回调函数
  36. * readyState:请求状态,代码是未初始化,1:初始化,2:发送请求,3:开始接受数据,4:接受结果完毕
  37. * status: http状态码 200成功,404路径错误,500后台代码错误,
  38. */
  39. xmlHttp.onreadystatechange = function() {
  40. if(xmlHttp.readyState==4 && xmlHttp.status==200) {
  41. var usernull = document.getElementById("usernull");
  42. var result = xmlHttp.responseText; //接受服务器端传过来的数据,写出来的数据都是String类型
  43. if(result == "true") {
  44. usernull.innerHTML = "<font color='red'>当前用户名已被注册</font>";
  45. return false;
  46. } else if(result == "false") {
  47. usernull.innerHTML = "<font color='green'>当前用户名可用</font>";
  48. return true;
  49. }
  50. }
  51. }
  52. }

Login

LoginServlet中doGet方法:

  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. String username = request.getParameter("username");//获取页面传过来的参数
  3. String password = request.getParameter("password");
  4. //登录操作
  5. boolean flag = userBiz.checkLogin(username, password);
  6. if(flag) {
  7. request.getSession().setAttribute("loginuser", username);
  8. // response.sendRedirect("main.jsp");
  9. response.sendRedirect("SearchServlet"); //首页直接显示
  10. } else {//登录失败
  11. response.setContentType("text/html;charset=utf-8");
  12. // response.setCharacterEncoding("utf-8");
  13. PrintWriter out = response.getWriter();
  14. out.println("<script type='text/javascript'>");
  15. out.println("alert(\"登录失败!请重新登录\")");//反斜杠转义
  16. out.println("open(\"login.jsp\", \"_self\");");//重新打开新的页面, _self在原窗口打开
  17. out.println("</script>");
  18. out.close();
  19. }
  20. }

网站首页及搜索图书模块

分页展示

Jstl标签库 c:forEach,循环遍历展示图书信息。

  1. <c:forEach var="book" items="${books }">
  2. <tr>
  3. <td><input type="checkbox" name="bookId" value="${book.bid }" /></td>
  4. <td class="title">${book.bookname }</td>
  5. <input type="hidden" name="title" value = "${book.bid }:${book.bookname}"/>
  6. <td>¥${book.b_price }</td>
  7. <input type="hidden" name="price" value = "${book.bid }:${book.b_price}"/> <!-- b_price跟数据库字段名相对应 -->
  8. <td>${book.stock }</td>
  9. <input type="hidden" name="stock" value = "${book.bid }:${book.stock}"/>
  10. <td class="thumb"><img src="${book.image }" /></td>
  11. <input type="hidden" name="image" value = "${book.bid }:${book.image}"/>
  12. </tr>
  13. </c:forEach>
  1. <!--分页开始-->
  2. <%if(request.getAttribute("current") != null) { %>
  3. <div class="page-spliter">
  4. <a href="SearchServlet">首页</a>
  5. <%for(int i = 1; i <= totalPage; i++) { %>
  6. <%if(i==no) { %> <!-- 如果不是当前页显示为链接 -->
  7. <span class="current"><%=i %></span>
  8. <%continue;} %>
  9. <a href="SearchServlet?currentPage=<%=i %>"><%=i %></a>
  10. <%} %>
  11. <a href="SearchServlet?currentPage=<%=totalPage %>">尾页</a>
  12. </div>
  13. <%} %>
  14. <!--分页结束-->

servlet处理

  1. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. request.setCharacterEncoding("utf-8");
  3. String currentPage = request.getParameter("currentPage");//获取当前页
  4. int no = currentPage == null?1:Integer.parseInt(currentPage);//如果当前页为空,则默认为1,否则转化为相应的int
  5. // String currentSearchPage = request.getParameter("currentSearchPage");
  6. String bookname = request.getParameter("keywords");//获取你输入的书名
  7. List<Book> books = null;
  8. if(bookname==null || bookname.equals("")){
  9. books=bookbiz.findAll(3, no);//查询所有。3:代表每页显示的条数,no:当前显示页面
  10. request.setAttribute("totalPage", (bookbiz.count()/3 + 1));//将总页面数存入request
  11. } else {
  12. books = bookbiz.findBookByName(bookname,3, no);//根据书名模糊查询出数据
  13. System.out.println(books.size());
  14. request.setAttribute("totalPage", (books.size()/3 + 1));//将总页面数存入request
  15. }
  16. request.setAttribute("books", books);//将查询出的数据存入request
  17. request.setAttribute("current", no);//将当前页存入request
  18. request.getRequestDispatcher("main.jsp").forward(request, response);//页面转发
  19. }

关键字匹配查询

输入“Java”关键字,展示搜索结果

购物车模块

注意:

当库存不足时,防止库存数被减到负值。

  1. if(oneStock > 0) {//如果库存大于0
  2. //查看当前图书是否已经存在于购物车中
  3. //查看购物车列表是否已经存在该图书,对比两个图书id
  4. for (int j = 0; j < bookcart.size(); j++) {
  5. Book existBook = (Book) bookcart.get(j);
  6. if(existBook.getBid() == bid) {//如果购物车中的id==被选中的图书id,则购物车中的数量+1
  7. bookcart.remove(j);
  8. existBook.setCount(existBook.getCount()+1);//购物车中商品数量+1
  9. double totalPrice = existBook.getPrice();
  10. bookcart.add(existBook);//商品总价
  11. System.out.println("总价"+totalPrice);
  12. isNotExists = false;
  13. //修改库存
  14. isOrNotChangeStock = bookbiz.changeStock(bid, "-1");
  15. break;
  16. }
  17. }
  18. if(!isNotExists) {
  19. continue;
  20. }
  21. book.setBid(bid);
  22. //判断当前获取的图书信息是否为指定bid下的信息
  23. for (int j = 0; j < title.length; j++) {
  24. // request.setCharacterEncoding("utf-8");
  25. //解决页面图书标题中文显示乱码
  26. String title_temp =new String(title[j].getBytes("ISO-8859-1"),"utf-8");//取标题
  27. if(title_temp.indexOf(bids[i]+":")<0) {//indexOf匹配bids是否包含在title_temp中,如果没有返回-1
  28. continue;
  29. }
  30. if(image[j].indexOf(bids[i]+":")<0) {
  31. continue;
  32. }
  33. if(price[j].indexOf(bids[i]+":")<0) {
  34. continue;
  35. }
  36. if(stock[j].indexOf(bids[i]+":")<0) {
  37. continue;
  38. }
  39. //添加指定bid下的图书信息
  40. book.setBookname(filter(title_temp, bids[i]));
  41. book.setImage(filter(image[j], bids[i]));
  42. book.setPrice(Double.parseDouble(filter(price[j], bids[i])));
  43. // book.setPrice(Double.valueOf(filter(price[j], bids[i])));
  44. book.setStock(filter(stock[j], bids[i]));
  45. book.setCount(1);
  46. //修改库存
  47. bookbiz.changeStock(bid, "-1");
  48. bookcart.add(book);
  49. }
  50. }

移除操作

  1. protected void remove(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. //1.获取图书id
  3. String bid = request.getParameter("bid");
  4. //2.获取购物车
  5. List<Book> bookcart = (List<Book>) request.getSession().getAttribute("bookcart");
  6. //3.循环查找购物车中相同的图书id
  7. for(int i = 0; i< bookcart.size(); i++) {
  8. Book book = bookcart.get(i);
  9. if(Integer.valueOf(bid) == book.getBid()) {
  10. //4.移除图书
  11. bookcart.remove(i);
  12. //5.修改库存
  13. bookbiz.changeStock(Integer.parseInt(bid), book.getCount()+"");
  14. break;
  15. }
  16. }
  17. //6.将购物车保存到session中
  18. // request.getSession().setAttribute("bookcart", bookcart);
  19. request.getSession().setAttribute("bookcart_count", bookcart.size());
  20. System.out.println(request.getSession().getAttribute("bookcart_count"));
  21. }

1.前端shopping.jsp页面,添加onblur失去焦点事件,当鼠标离开输入框时执行JavaScript代码,调用update方法。

  1. <c:set value="1" var="count"></c:set>
  2. <c:forEach var="book" items="${bookcart }">
  3. <tr>
  4. <input type="hidden" id="hidden_bid_${count }" name="hidden_bid_${count }"
  5. value="${book.bid }"/>
  6. <td class="thumb"><img src="${book.image }" /></td>
  7. <td class="title">${book.bookname }</td>
  8. <td><input class="input-text" type="text" id="nums_${count }"
  9. name="nums_${count }" value="${book.count }" onblur="update(${bookcart_count}, ${count }, ${book.bid })"/></td> <!-- onblur事件 -->
  10. <input type="hidden" id="hidden_${count }"
  11. name="hidden_${count }" value="${book.price }"/>
  12. <td><span id="price_${count }"></span></td>
  13. <input type="hidden" id="hidden_book_total_price_${count }" name="hidden_book_total_price_${count }" />
  14. <td><span id="remove_${count }"><a href="#" onclick="del(${book.bid})">移除</a></span></td> <!-- href链接, -->
  15. </tr>
  16. <c:set value="${count+1 }" var="count"></c:set>
  17. </c:forEach>

2.异步更新图书购买量数据,并向控制层Servlet中返回一个“update”

  1. /**
  2. * Ajax修改购物车中的数量
  3. */
  4. function update(size_str, i, bid_str) {
  5. //初始化XMLHttpRequest对象
  6. var xmlHttp;
  7. try {
  8. xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
  9. } catch (e) {
  10. try {
  11. xmlHttp = new XMLHttpRequest();
  12. } catch (e) {
  13. try {
  14. xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  15. } catch (e) {
  16. e.message();
  17. alert("你的浏览器不支持Ajax");
  18. }
  19. }
  20. }
  21. //2.获取修改后的数量
  22. var num_str = document.getElementById("nums_"+i);
  23. //3.打开服务器链接
  24. xmlHttp.open("POST", "ModifyCartServlet?action=update&bid="+bid_str+"&count="+num_str.value, true);
  25. //4.传值 ,无参传null值
  26. xmlHttp.send(null);
  27. //5.设置回调函数
  28. xmlHttp.onreadystatechange = function() {
  29. if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
  30. count(size_str);//调用Servlet中的方法
  31. }
  32. }
  33. }

3.servlet中通过前端返回的请求调用相应的方法。

  1. String action = request.getParameter("action");
  2. if(action.equals("update")) {
  3. updateCart(request, response);
  4. }
  5. else if(action.equals("remove")) {
  6. remove(request, response);
  7. }

4.控制层Servlet更新购物车数据,并修改库存。

  1. protected void updateCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. //1.获取图书id和修改后的数量
  3. String bid = request.getParameter("bid");
  4. String count = request.getParameter("count");
  5. //2.获取购物车
  6. List<Book> bookcart = (List<Book>) request.getSession().getAttribute("bookcart");
  7. //3.查找购物车中修改过的图书,并修改相应的信息
  8. for (Book book : bookcart) {
  9. if(Integer.valueOf(bid) == book.getBid()) {
  10. //4.获取修改前的图书数量
  11. int old_count = book.getCount();
  12. //5.设置当前图书的新数量
  13. book.setCount(Integer.valueOf(count));
  14. System.out.println("当前图书新数量"+count);
  15. int nowStock = 0;
  16. try {
  17. nowStock = basedao.queryStock(Integer.parseInt(bid));
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. //6.修改库存
  22. bookbiz.changeStock(Integer.parseInt(bid), (old_count-Integer.parseInt(count))+"");
  23. break;
  24. }
  25. }
  26. }

与搜索图书模块类似

我的订单模块

1.获取订单信息,存入List中

  1. <%
  2. List orders = (List) request.getAttribute("orders");
  3. %>

2.订单展示

  1. <c:forEach var="order" items="${orders }">
  2. <tr>
  3. <td id="id_${td_id}">${order.oid }</td>
  4. <td id="user_${td_id}">${order.username }</td>
  5. <td id="crdt_${td_id}">${order.createdate }</td>
  6. <td id="total_${td_id}">${order.total_price }</td>
  7. <td class="thumb"><img src="${order.image }" /></td>
  8. <td>${order.bookname }</td>
  9. <td>${order.b_price }</td>
  10. <td>${order.total_price/order.b_price }</td>
  11. </tr>
  12. </c:forEach>

用户退出

当用户退出登录,清空session。

  1. <%--用户退出登录 --%>
  2. <%
  3. request.getSession().removeAttribute("loginuser");
  4. request.getSession().removeAttribute("bookcart");
  5. request.getSession().removeAttribute("bookcart_count");
  6. response.sendRedirect("login.jsp");
  7. %>

一些注意细节

1.为防止游客非法访问页面,在每一个前端页面body之后加上登录检测代码。

  1. <%
  2. String username = (String)session.getAttribute("loginuser");
  3. if(username == null) {
  4. response.sendRedirect("login.jsp");
  5. }
  6. %>

2.当库存不足时,防止库存数被减到负值。

  1. if(oneStock > 0) {//如果库存大于0
  2. //...
  3. }

3.href中加上空链接,否则该页面中的session不会刷新,必须手动刷新。

  1. <span id="remove_${count }"><a href="#" onclick="del(${book.bid})">移除</a></span>

网站云部署

一个经过部署的网站才是一个完整的网站

  • 阿里云平台

  • 租用ecs云主机,搭建Java运行环境,jdk、mysql、Tomcat

  • 域名解析

  • 项目打包成.war文件上传至云服务器。

  • 启动服务器

  • 通过域名访问并测试网站:http://ycuer.xin:8080/books/

上传的附件 cloud_download 基于Java的网上书城项目.7z ( 5.71mb, 2次下载 )
error_outline 下载需要7点积分

发送私信

不是所有的命中注定都会是你的盖世英雄

4
文章数
2
评论数
最近文章
eject