JavaWeb——(15)Ajax

目录

一、Ajax概述

二、XMLHttpRequest

2.1构造方法

2.2常用方法

2.3常用属性

三、验证用户名是否存在

3.1直接在元素中绑定blur

3.2在js中获取元素并绑定blur方法

四、验证邮箱

五、搜索框提示功能

六、JSON

七、加入购物车

八、修改商品数量及购物车完善


一、Ajax概述

AJAX全称为Asynchronous JavaScript And XML,指的是异步JavaScript和XML,是一种用于创建更好更快以及交互性更强的Web应用程序的技术,

其最大的优点在于可以在不重新加载整个页面的情况下,与服务器直接交换数据从而更新部分网页的内容,ajax不需要浏览器插件,但是需要用户允许Javascript在浏览器上执行。

比如百度搜索时打出某些关键字下面就会有相关的词条出现:

总之而言Ajax是一种只刷新局部页面的技术

  • JavaScript:更新局部的网页
  • XML:一般用于请求数据和响应数据的封装
  • XMLHttpRequest对象:发送请求到服务器并获得返回结果,属于异步的数据获取技术
  • CSS:美化页面样式
  • 异步:发送请求后不等返回结果,由回调函数处理结果

JavaScript中XMLHttpRequest对象是整个Ajax技术的核心,它提供了异步发送请求的能力,这里我们简单说一下同步和异步的区别:

  • 同步:客户端提交请求->等待服务器处理->处理完毕返回结果,在这期间客户端不能做其他的事
  • 异步:客户端提交请求->服务器处理(此时客户端可以做别的事)->处理完毕返回结果

二、XMLHttpRequest

JavaScript中的XMLHttpRequest是整个Ajax技术的核心,提供了异步发送请求的能力,下面我们学习一下该对象如何使用。

2.1构造方法

不同的浏览器或者浏览器的不同版本,获取该对象的方式是不同的,

var xmlhttp;//存储XMLHttpRequest对象
if (window.XMLHttpRequest){
    xmlhttp=new XMLHttpRequest();//IE7+,Firefox,Chrome,Opera,Safari
} else{
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");//IE6,IE5
}

2.2常用方法

方法名 说明
open(method,URL,async)

建立与服务器的连接

method参数指定请求的HTTP方法,典型的值是GET或POST

URL参数指请求的地址

async参数指定是否使用异步请求,其值为true或false

send(content)

发送请求

content参数指定请求的参数

setRequestHeader(header,value) 设置请求的头信息

2.3常用属性

属性名 说明
onreadystatechange 指定回调函数
readyState

XMLHttpRequest的状态信息

0:XMLHttpRequest对象没有完成初始化,即刚刚创建

1:XMLHttpRequest对象开始发送请求,调用了open方法,但还没有调用send方法。请求还没有发出

2:XMLHttpRequest对象的请求发送完成,send方法已经调用,数据已经提交到服务器,但没有任何响应

3:XMLHttpRequest对象开始读取响应,还没有结束,收到了所有的响应消息头,但正文还没有完全收到

4:XMLHttpRequest对象读取响应结束一切都收到了

status

HTTP的状态码

200服务器响应正常

400:无法找到请求的资源

403:没有访问权限

404:访问的资源不存在

500:服务器内部错误

responseText 获得响应的文本内容
responseXML 获得响应的XML文档对象document

我们新建一个简单的servlet测试一下这些属性和方法的使用,

package servlet;

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.io.PrintWriter;

@WebServlet(name = "DemoServlet")
public class DemoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.print("hello XMLHttpRequest");
    }
}

然后在jsp中使用XMLHttpRequest对象与服务器建立连接,

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/getXMLHTTP.js"></script>
</head>
<script type="text/javascript">
    window.onload = function () {
        var req=getXMLHttpRequest();//获取XMLHttpRequest对象
        //处理响应的结果函数
        req.onreadystatechange=function(){
            if (req.readyState==4){//如果XMLHttpRequest对象读取响应结束了
                if (req.status==200){//查看服务器端的响应状态,服务器响应正常
                    alert(req.responseText);//输出获得响应的文本
                }
            }
        }
        req.open("get","${pageContext.request.contextPath}/servlet/demoServlet");//与服务器建立连接
        req.send(null);//发送请求,不带参数
    }
</script>
<body>
</body>
</html>

 XMLHttpRequest对象的初始化代码为:

function getXMLHttpRequest(){
    var xmlhttp;
    if (window.XMLHttpRequest){
        xmlhttp=new XMLHttpRequest();//IE7+,Firefox,Chrome,Opera,Safari
    } else{
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");//IE6,IE5
    }
    return xmlhttp;
}

然后启动服务器查看效果,

三、验证用户名是否存在

我们在注册某些网站账号的时候,用户名不允许重名,我们利用Ajax的异步特点来实现重名检测的功能。

在检测用户名的时候要判断用户是否输入完成了,不能用户还在输入的时候就一直提示,我们可以用blur方法,该方法会在输入域失去焦点时触发,即用户输入完成了点击了别的元素。

3.1直接在元素中绑定blur

我们首先写一个注册的页面,在页面中检测用户焦点是否离开了输入用户名的输入框,离开的话就获取用户名的信息利用ajax与后台数据库通信,并且根据后端传回的参数来提示用户是否重名,这里我们直接在界面中绑定好blur的响应函数,

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/getXMLHTTP.js"></script>
    <title>Title</title>
    <script type="text/javascript">
        function checkName(){//当焦点离开输入姓名框时,检测是否重名
            var name=document.getElementsByTagName("input")[0];//获取用户名
            var xmlhttpRequest=getXMLHttpRequest();//创建XMLHttpRequest对象
            var tip=document.getElementById("tips");//获取提示元素

            //处理响应的结果函数
            xmlhttpRequest.onreadystatechange=function(){//
                if (xmlhttpRequest.readyState==4){//如果请求正常
                    if (xmlhttpRequest.status==200){//并且服务器响应正常
                        if (xmlhttpRequest.responseText=="true") {//如果重名
                            tip.innerHTML="<font color='red'>用户名已存在</font>";
                        }else{
                            tip.innerHTML="<font color='green'>用户名可以使用</font>";
                        }
                    }
                }
            }

            xmlhttpRequest.open("get","${pageContext.request.contextPath}/servlet/checkNameServlet?name="+name.value);//创建连接
            xmlhttpRequest.send(null);//发送请求
        }
    </script>
</head>
<body>
    用户名:<input type="test" name="userName" onblur="checkName()"/><span id="tips"></span><br/>
    密码:<input type="password" name="passWord"/><br/>
</body>
</html>

 然后我们新建一个servlet用于处理前端传来的用户名信息,进行判断是否重名,返回一个true或者false的字符串,这里我们简单测试一下不连接数据库,只判断是否和“peru”重名,

package servlet;

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.io.PrintWriter;

@WebServlet(name = "CheckNameServlet")
public class CheckNameServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        String name = request.getParameter("name");//获取数据库的名字
        if ("peru".equals(name)){//如果重名了
            out.print(true);
        }else{
            out.print(false);
        }
    }
}

页面效果:

3.2在js中获取元素并绑定blur方法

我们还可以利用window.onload()方法在页面加载时获取到目标元素,然后写元素的blur方法,效果是一样的。

window.onload=function () {
    var nameElement=document.getElementsByName("userName");
    nameElement.onblur=function () {
        var name=this.value;//this等价于nameElement
        var xmlhttpRequest=getXMLHttpRequest();//创建XMLHttpRequest对象
        var tip=document.getElementById("tips");//获取提示元素

        //处理响应的结果函数
        xmlhttpRequest.onreadystatechange=function(){//
            if (xmlhttpRequest.readyState==4){//如果请求正常
                if (xmlhttpRequest.status==200){//并且服务器响应正常
                    if (xmlhttpRequest.responseText=="true") {//如果重名
                        tip.innerHTML="<font color='red'>用户名已存在</font>";
                    }else{
                        tip.innerHTML="<font color='green'>用户名可以使用</font>";
                    }
                }
            }
        }

        xmlhttpRequest.open("get","${pageContext.request.contextPath}/servlet/checkNameServlet?name="+name.value);//创建连接
        xmlhttpRequest.send(null);//发送请求
    }
}

这样写的目的是让网页中的标签看起来比较干净,不在标签内部去定义一些属性或者方法,而是在js的代码中去定义

四、验证邮箱

验证邮箱和验证用户名的逻辑其实差不多,就是给页面输入邮箱的元素绑定一个焦点离开的时间响应函数,当焦点离开输入框时认为用户已经输入好了邮箱,获取邮箱的字符串,然后利用ajax的异步通信技术传输给后台邮箱字符串进行判断,首先我们写好邮箱的焦点离开响应函数,并且根据后台返回的结果显示在前端页面中,

//验证邮箱是否存在
function ckEmail(){
    var email = document.getElementsByName("email")[0];//得到邮箱对象
    var xhr = getXMLHttpRequest();

    //响应处理函数
    xhr.onreadystatechange = function(){
        if(xhr.readyState==4){
            if(xhr.status==200){
                var font = document.getElementsByTagName("font")[0];//得到font标签
                if(xhr.responseText=="true"){
                    font.innerHTML = "邮箱已被使用";
                    font.style.color = "red";
                }else{
                    font.innerHTML = "邮箱可以使用";
                    font.style.color = "lime";
                }
            }
        }
    }

    xhr.open("get","${pageContext.request.contextPath}/servlet/checkEmailServlet?email="+email.value);//建立连接
    xhr.send(null);//发送请求
}

然后我们新建servlet来获取得到的邮箱,并进行邮箱重名的检测业务操作,

package Web;

import Service.BookServiceImpl;

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.io.PrintWriter;

@WebServlet(name = "CheckEmailServlet")
public class CheckEmailServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String email = request.getParameter("email");//得到邮箱字符串
        PrintWriter out = response.getWriter();//获取输出流

        //模仿后台进行邮箱验证业务
        if ("[email protected]".equals(email)){
            out.print(true);
        }else{
            out.print(false);
        }
    }
}

我们启动服务器进行验证,

五、搜索框提示功能

 接下来我们给搜索做一个提示的功能,当用户输入某些关键字时下拉框会提示一些相关信息,比如百度的搜索,

 我们要做的是图书管理系统的搜索提示功能,我们在搜索框下面新建一个div,里面存放搜索的提示信息,将每个书籍名当作小div放在这个提示的大div中,

<div id="SearchTips" style="display: block;border: 1px solid red; width: 130px; position: absolute;left: 860px;top:135px; background: white"></div>

然后我们给搜索框添加一个按键抬起的响应事件,

window.onload = function () {
	var searchElement= document.getElementById("name");//获取搜索框元素
	var div=document.getElementById("SearchTips")//获取提示框元素

	searchElement.onkeyup = function () { //给文本框注册按键事件
		var bookname=this.value;//获取文本框的值
		if (bookname==""){
			div.style.display="none";
			return;
		}
		var xmlHttpRequest=getXMLHttpRequest();//获取XMLHttpRequest对象

		//处理结果
		xmlHttpRequest.onreadystatechange=function(){
			if (xmlHttpRequest.readyState==4){//如果请求正常
				if (xmlHttpRequest.status==200){//如果服务器响应正常
					var booksname = xmlHttpRequest.responseText;//得到服务器返回的数据

					var childDivs="";
					var booksArr=booksname.split(",");//将书籍姓名字符串按照","字符分割
					for (var i = 0; i < booksArr.length; i++) {//遍历所有书籍
						childDivs+="<div onmouseover='changeBackground_over(this)' onmouseleave='changeBackground_out(this)' onclick='writeText(this)'>"+booksArr[i]+"</div>";//将每个书籍放在小的div中显示
					}
					div.innerHTML=childDivs;
					div.style.display="block";
				}
			}
		}

		//建立连接,加入时间可以避免浏览器直接取缓存的数据而不与服务器通信
		xmlHttpRequest.open("get","${pageContext.request.contextPath}/servlet/searchMessageServlet?name="+bookname+"&time="+new Date().getTime());
		xmlHttpRequest.send(null);//发送请求
	}
}

然后当返回的结果显示出来时,还需要有鼠标移动到该栏时该书籍栏背景颜色会变,点击时会将结果填充到输入栏中,我们依次添加这些函数,

//鼠标移动到结果上时调整背景颜色为灰色
function changeBackground_over(div) {
	div.style.backgroundColor="gray";
}

//鼠标离开结果时调整背景颜色为白色
function changeBackground_out(div) {
	div.style.backgroundColor="white";
}

//点击搜索结果时将结果填充到输入框中
function writeText(div) {
	var searchElement= document.getElementById("name");//获取搜索框元素
	searchElement.value =div.innerHTML;//将结果赋值给搜索框的文本
	div.parentNode.style.display="none";//填充后将整个搜索提示框隐藏
}

然后我们新建serlet,从页面获取到搜索框的书名后将书名传给serlvlet在数据库中查询,

package Web;

import Service.BookServiceImpl;
import Util.Book;

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.io.PrintWriter;
import java.util.List;

@WebServlet(name = "SearchMessageServlet")
public class SearchMessageServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");//设置编码格式,避免中文乱码
        request.setCharacterEncoding("UTF-8");//只能解决post方式的乱码
        String name = request.getParameter("name");//获取用户输入的书名

        BookServiceImpl bookService=new BookServiceImpl();
        List<Object> list = bookService.searchBookByName(name);//获取所有相似的书名

        //把集合中的数据转换为字符串
        String booksname="";
        for (int i = 0; i < list.size(); i++) {
            if (i>0){
                booksname+=",";
            }
            booksname+=list.get(i);
        }

        //System.out.println(booksname);
        PrintWriter out = response.getWriter();
        out.write(booksname);//将书籍名字数据直接写到response中
    }
}

在业务逻辑层调用数据访问层的方法,

//根据书籍名字查询所有相关的书籍
public List<Object> searchBookByName(String name) {
    try {
        return bookDao.searchBookByName(name);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

在数据访问层实现与数据库的连接与通信,

/**
 * 根据书籍名字模糊查询所有相关书籍,返回书籍的姓名
 * @param name
 * @return
 */
public List<Object> searchBookByName(String name) throws SQLException {
    QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
    return queryRunner.query("select name from book where name like ?",new ColumnListHandler(),"%"+name+"%");
}

配置一下web,xml的servlet映射路径,然后启动服务器看看效果,

 左上是输入关键字"j"后出现的相关书籍提示,右上是鼠标移动到第二栏时的显示效果,下面是点击第二栏后数据填充到搜索框的效果。

六、JSON

我们在获取搜索框提示的信息时,servlet是通过字符串的方式来传结果的,我们需要在前端的jsp中对字符串进行解析,如果使用JSON对象则可以直接调用方法解析,快速得到书籍名字的数组,

JSON是一种轻量级的数据交换格式,是一种数据格式,一般由值组成:

  1. 对象:用花括号”{}”表示,数据结构为{key1: value1, key2: value2, …}的键值对,key为属性名,可以为整型和字符串表示,value为对应的值,可以是任意类型
  2. 数组:用方括号表示”[]”,数据结构为[“1”,”2”,”java”],里面的元素可以是任意数据类型
  3. 数字
  4. 字符串
  5. 三个字面值(false, null, true)

这里我们对比一下Java、JavaScript和JSON三种创建对象的方式,

//Java
public class person{
    private String name;
    private int age;
    public void show(){}
}

//JavaScript
function Person(){
    var name = “tom”;//生命一个局部变量
    this.age=10;//声明一个成员变量
    this.show=function(){}
}

//Json
var person={name: ”tom“, age: 18, show: function(){}};

在使用JSON时先要导入需要的jar包,提取码为zxls,

Json一般使用fromOject方法来封装对象,转换为对应的JSON格式字符串,对象可以是任意形式,使用比较方便,我们测试一下来封装一下Book类的数据,

package Json;

import Util.Book;
import Util.C3P0Util;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class JsonTest {
    @Test//使用json封装对象
    public void test1(){
        Book book=new Book();
        book.setId("100");book.setName("Java天下第一");book.setPrice(20);book.setPnum(50);

        String str=JSONObject.fromObject(book).toString();
        System.out.println(str);
    }

    @Test//使用json封装集合
    public void test2(){
        List<Book> list=new ArrayList<>();
        Book b1=new Book();
        b1.setId("101");b1.setName("Java天下第一");b1.setPrice(20);b1.setPnum(50);
        Book b2=new Book();
        b2.setId("102");b2.setName("C++天下第一");b2.setPrice(30);b2.setPnum(40);
        Book b3=new Book();
        b3.setId("103");b3.setName("C天下第一");b3.setPrice(25);b3.setPnum(60);

        list.add(b1);list.add(b2);list.add(b3);
        String str=JSONArray.fromObject(list).toString();
        System.out.println(str);
    }

    @Test//使用json封装对象的部分属性
    public void test3() throws SQLException {
        QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
        List<Book> list = queryRunner.query("select * from book",new BeanListHandler<Book>(Book.class));

        JsonConfig jsonConfig=new JsonConfig();
        jsonConfig.setExcludes(new String[]{"category","description","pnum","id"});//将这些属性之外的属性利用json转换为字符串,即排除这些属性
        String str=JSONArray.fromObject(list,jsonConfig).toString();
        System.out.println(str);
    }
}

回到我们的图书管理系统,在完成搜索框的提示功能时,我们是将图书作为字符串,中间逗号隔开,然后在前端解析之后进行显示,如果使用json的数据格式,那么就可以直接调用方法解析,

首先后端将书籍数组转换为json格式的字符串数据,

String name = request.getParameter("name");//获取用户输入的书名

BookServiceImpl bookService=new BookServiceImpl();
List<Object> list = bookService.searchBookByName(name);//获取所有相似的书名

String booksname=JSONArray.fromObject(list).toString();//利用json的方法直接将List转换为JSON格式的数据

PrintWriter out = response.getWriter();
out.write(booksname);//将书籍名字数据直接写到response中

 然后在前端获取response中返回的数据,使用JavaScript的eval方法直接把json格式的字符串转换为了数组,接着将每个书名显示出来即可,

var booksname = xmlHttpRequest.responseText;//得到服务器返回的数据

var childDivs="";
//var booksArr=booksname.split(",");//将书籍姓名字符串按照","字符分割
var booksArr=eval("("+booksname+")");//使用eval方法,用JavaScript语法读取返回的数据,这里返回一个数组
for (var i = 0; i < booksArr.length; i++) {//遍历所有书籍
	childDivs+="<div onmouseover='changeBackground_over(this)' onmouseleave='changeBackground_out(this)' onclick='writeText(this)'>"+booksArr[i]+"</div>";//将每个书籍放在小的div中显示
}

七、加入购物车

接着我们实现点击购买商品后将商品添加至购物车的功能,

在点击购买时会将商品的id传给后台,后台然后在数据库中查询将商品加入到购物车中,并且用户可以查看购物车从而了解购买的商品信息,

首先用户在product_list.jsp页面上点击商品,然后进入product_info.jsp界面查看商品的详细信息,此时用户如果点击购买,那么我们就传递书籍的id信息给相关的servlet,然后通过servlet从数据库查询书籍的相关信息并添加到购物车中,

package Web;

import Service.BookServiceImpl;
import Util.Book;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@WebServlet(name = "AddCartServlet")
public class AddCartServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");//设置编码格式
        PrintWriter out = response.getWriter();//获取网页输出流
        String id = request.getParameter("id");//获取用户点击的书籍id

        BookServiceImpl bookService=new BookServiceImpl();
        Book book=bookService.findBookByIdServlet(id);

        HttpSession session = request.getSession();//获取HttpSession对象
        Map<Book,String> cart= (Map<Book, String>) session.getAttribute("cart");//从session中的购物车取出来
        int num=1;
        if (cart==null){
            cart=new HashMap<Book,String>();//如果是第一次访问,则为用户创建一个购物车对象
        }
        if (cart.containsKey(book)){
            num=Integer.parseInt(cart.get(book))+1;//如果购物车中有了这本书籍,就将数量+1
        }
        cart.put(book,num+"");//将图书放入购物车
        session.setAttribute("cart",cart);//将购物车放回session作用域中
        out.print("<a href='"+request.getContextPath()+"/servlet/pageChangeServlet'>继续购物</a>,<a href='"+request.getContextPath()+"/cart.jsp'>查看购物车</a>");
    }
}

我们将购物车作为session的属性存储,在点击购买之后让用户选择继续购物还是查看购物车,继续购物则跳转pageChangeServlet也就是显示product_list.jsp界面,查看购物车就是跳转cart.jsp界面,我们在cart.jsp界面中获取到session中的购物车信息,并将其循环显示出来,

<c:forEach items="${cart}" var="entry" varStatus="vs">
	<table width="100%" border="0" cellspacing="0">
		<tr>
			<td width="10%">${vs.count}</td>
			<td width="30%">${entry.key.name }</td>
			<td width="10%">${entry.key.price }</td>
			<td width="20%">
				<input type="button" value='-' style="width:20px" onclick="changeProductNum('${entry.value-1}','${entry.key.pnum}','${entry.key.id}')">
				<input name="text" type="text" value="${entry.value}" style="width:40px;text-align:center" />
				<input type="button" value='+' style="width:20px" onclick="changeProductNum('${entry.value+1}','${entry.key.pnum}','${entry.key.id}')">
			</td>
			<td width="10%">${entry.key.pnum}</td>
			<td width="10%">${entry.key.price*entry.value}</td>
			<td width="10%"><a href="${pageContext.request.contextPath}/changeCart?id=${entry.key.id}&count=0" style="color:#FF0000; font-weight:bold">X</a></td>
		</tr>
	</table>
</c:forEach>

然后我们启动服务器看看效果,

 我们选择两本编程之美,一本Java核心技术卷,然后查看购物车,

 可以看到购物车的信息正确显示出来了。

八、修改商品数量及购物车完善

在购物车中我们可以直接修改商品的数量,通过加减的按钮和ajax实现, 在点击加减按钮时,小计会发生改变,

点击加减按钮时,会将数量和书籍id等信息传给js的函数,然后函数跳转到servlet处理修改商品数量的业务,servlet先从session取出购物车的集合,然后在购物车中修改商品的数量,最后回显到查看购物车界面,

我们先在cart.jsp中设置按钮的响应函数,将书籍的信息传给servlet,

<c:set var="sum" value="0"></c:set>
<c:forEach items="${cart}" var="entry" varStatus="vs">
	<table width="100%" border="0" cellspacing="0">
		<tr>
			<td width="10%">${vs.count}</td>
			<td width="30%">${entry.key.name }</td>
			<td width="10%">${entry.key.price }</td>
			<td width="20%">
				<input type="button" value='-' style="width:20px" onclick="changeProductNum('${entry.value-1}','${entry.key.pnum}','${entry.key.id}')">
				<input name="text" type="text" value="${entry.value}" style="width:40px;text-align:center" />
				<input type="button" value='+' style="width:20px" onclick="changeProductNum('${entry.value+1}','${entry.key.pnum}','${entry.key.id}')">
			</td>
			<td width="10%">${entry.key.pnum}</td>
			<td width="10%">${entry.key.price*entry.value}</td>
			<td width="10%"><a href="${pageContext.request.contextPath}/changeNumServlet?id=${entry.key.id}&num=0" style="color:#FF0000; font-weight:bold">X</a></td>
		</tr>
	</table>
	<c:set var="sum" value="${sum + entry.value * entry.key.price}"></c:set>
</c:forEach>

然后创建servlet,修改session中的购物车信息, 

package Web;

import Util.Book;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;

@WebServlet(name = "ChangeNumServlet")
public class ChangeNumServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getParameter("id");//获取书籍id
        String num = request.getParameter("num");//获取书籍的数量
        HttpSession session = request.getSession();//获取session对象
        Map<Book,String> cart = (Map<Book, String>) session.getAttribute("cart");//从session对象中获取购物车
        Book book=new Book();
        book.setId(id);//将书籍的id设置为用户改变的书籍id

        if ("0".equals(num)){
            cart.remove(book);
        }
        if (cart.containsKey(book)){//比较书籍的id
            cart.put(book,num);//将书籍的数量重写
        }

        response.sendRedirect(request.getContextPath()+"/cart.jsp");//返回购物车显示页面
    }
}

启动服务器,页面如下,

猜你喜欢

转载自blog.csdn.net/weixin_39478524/article/details/120185651
今日推荐