Day60.Ajax、Axios、Json格式转换、书城第五阶段: 结果模型、Ajax局部更新、购物车

目录

一、Ajax概述

二、Axios框架 (封装Ajax)

1. Axios基本用法

2. 客户端发送 json 类型数据(data) 

3. 服务端返回 json 类型数据 (箭头函数 =>)

a. 接收json对象

b. 接收Json数组

4. gson、jackson 工具类 (json数据与java对象的转换)

封装 JSONUtils

三、书城项目第五阶段

1. 封装CommonResult (ajax结果模型)

2. 注册页面:用户名唯一性检查优化 — Ajax局部更新

3. 加入购物车

首页添加商品到购物车、解决刷新问题

前往购物车页面、渲染页面

清空购物车

减号操作(购物项-1)

加号操作(购物项+1)

删除购物项

修改购物项数量

页面效果
​​​​​​​


一、Ajax概述

Ajax:(Asynchronous Javascript And XML)(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。

Ajax 是一种浏览器通过 js 异步发起请求局部更新页面的技术,Ajax 请求的局部更新,不刷新浏览器窗口,不做页面跳转,不会舍弃原来页面的内容

前后端分离前端后端分开服务器部署,数据传递采用json格式传递。在我们这里我们先理解为彻底舍弃服务器端渲染,数据全部通过Ajax方式以JSON格式来传递

JSON (JavaScript Object Notation, JS 对象简谱),一种用于跨平台传输的数据格式。
Day52.JavaScript、对象|数组、JSON、DOM操作、正则RegExp_焰火青年·的博客-CSDN博客

服务器渲染:

Ajax渲染:

同步:多个操作按顺序执行,前面的操作没有完成,后面的操作就必须等待。所以同步操作通常是串行的。

异步:多个操作相继开始并发执行,在各自在自己独立的进程或线程中完成,所以互不干扰,谁也不用等谁。

二、Axios框架 (封装Ajax)

使用原生的JavaScript程序执行Ajax极其繁琐,所以一定要使用框架来完成。而Axios就是目前最流行的前端Ajax框架。(大自然的搬运工,对Ajax进行封装)

Axios官网:axios中文网|axios API 中文文档 | axios

axios程序接收到的响应对象结构: 

属性名作用
config调用axios(config对象)方法时传入的JSON对象
data服务器端返回的响应体数据
headers响应消息头
request原生JavaScript执行Ajax操作时使用的XMLHttpRequest
status响应状态码
statusText响应状态码的说明文本

1. Axios基本用法

1.在前端页面引入开发环境

<script type="text/javascript" src="/demo/static/vue.js"></script>
<script type="text/javascript" src="/demo/static/axios.min.js"></script>

2.发送普通请求参数

html
<div id="box">
    <div style="height: 200px;width: 400px;border: 1px solid red" >
        <!--v-text无法解析标签,v-html可以解析-->
        <span v-text="msg"></span>
        <span v-html="msg"></span>

    </div>
    <button @click="sendAjax()">发起异步请求</button>
</div>
var vue = new Vue({
    "el":"#box",
    "data":{
        "msg":"",
    },
    "methods":{
        sendAjax(){
            //使用axios发送异步请求
            axios({
                "method":"post",    //请求方式(不写默认get)
                "url":"demo01",     //请求的地址
                "params":{          //发送的请求参数
                    "userName":"tom",
                    "userPwd":"123456"
                }            //response是服务器端的响应数据,是json类型的
            }).then(function (response) {    //请求成功会执行的函数
                    //alert("Ajax请求成功");
                    console.log(response);
                    console.log(response.data);      //响应体
                    console.log(response.headers);   //成功的响应头
                    console.log(response.status);    //成功的状态码
                
                    vue.msg = response.data; //将响应的消息渲染到页面上

            }).catch(error => {        //可以使用箭头函数简化回调函数
                    //alert("Ajax请求失败")
                    
                    console.log(error);    //获取失败信息
                    
                    console.log(error.response);    //失败的响应信息
                    console.log(error.response.data);   //失败的数据(其实是一个页面)
                    console.log(error.response.headers);//失败的响应头
                    console.log(error.response.status); //失败的状态码
            })
        }
    }
})
</script>

2. 客户端发送 json 类型数据(data) 

在使用Axios传递数据时,无论是get还是post,数据都在地址栏后拼接

如何解决安全问题?
使用 json类型传输数据。(data 传递json数据,param 传递普通参数)。

注意客户端发送json类型数据,必须采用post请求传递 (get请求只能提交字符串数据)。

<body>
<!--客户端发送请求携带Json类型数据-->
<div id="box">
    <button @click="sendJson()">发送Json数据</button>
</div>
<script>
    new Vue({
        "el":"#box",
        "data":{},
        "methods":{
            "sendJson": function (){
                axios({
                    "method":"post",
                    "url":"ajax3",
                    "data":{    //data: 发送json数据,param: 发送请求参数
                        "username":"zhangsan",
                        "password":"123"
                    }
                }).then( new function (){
                    alert("发送!")
                }).catch();
            }
        }
    })
</script>
</body>

服务端解析:

服务端不能采用 getParameterMap() 方式获取 Json 数据;

应采用流的方式 BufferdReader br =  req.getReader() 获取 json 数据。


@WebServlet("/ajax3")   //采用注解的方式地址匹配
public class Ajax03Servlet extends HttpServlet {
    //service,内部会判断请求方式
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("------ Ajax03Servlet ------");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //Parameter()无法接收Json数据
        /*Map<String, String[]> map = req.getParameterMap();
        map.forEach(System.out::printf);*/

        //1.通过获取io流,接收Json数据
        BufferedReader br = req.getReader();

        //2.读取数据,拼接到一起
        StringBuilder sb = new StringBuilder();
        String line = "";
        while ((line = br.readLine())!=null){
            sb.append(line);
        }
        System.out.println(sb);

        //3.通过工具类Gson,将json格式字符串转换为 Java对象
        Gson gson = new Gson();
        User user = gson.fromJson(sb.toString(), User.class);

        System.out.println(user);
    }
}

3. 服务端返回 json 类型数据 (箭头函数 =>)

a. 接收json对象

服务端发送:

@WebServlet("/ajax4")
public class Ajax04Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("------ Ajax04Servlet ------");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        //1.调用gson工具将对象转换为json字符串
        User zs = new User("张三", "123456");
        Gson gson = new Gson();
        String json = gson.toJson(zs);

        //2.获取打印流响应到客户端
        PrintWriter writer = resp.getWriter();
        writer.println(json);
    }
}

客户端接收:

可以使用箭头函数 => 简化回调函数,箭头函数内可以用 this 表示 Vue 对象 (因为特性,不存在函数) (类似Lamda表达式)。

<body>
<!--客户端获取响应接收Json类型数据,通过vue渲染到表格-->
<div id="box">
    <table width="400px" border="1" style="text-align: center">
        <tr>
            <th>姓名</th>
            <th>密码</th>
        </tr>
        <!--接收的json对象渲染到表格中-->
        <tr>
            <td>{{user.username}}</td>
            <td>{{user.password}}</td>
        </tr>
    </table>
    <button @click="acceptJson()">接收Json数据</button>
</div>
<script>
    new Vue({
        "el":"#box",
        "data":{
            "user":{
                /*"username":"",
                "password":"",可省略,js可以动态添加、删除属性*/
            }
        },
        "methods":{
            "acceptJson": function (){
                axios({
                    "method":"post",
                    "url":"ajax4",
                }).then( value =>{  //箭头函数简化书写,可以以this代表vue
                    alert("接收")
                    //接收json数据,通过vue渲染
                    console.log(value.data);
                    this.user = value.data;
                }).catch(reason => {
                    console.log("请求失败");
                });
            }
        }
    })
</script>
</body>

b. 接收Json数组

客户端接收:

<body>
<!--客户端获取响应接收Json类型数组,通过vue渲染到表格-->
<div id="box">
    <table width="400px" border="1" style="text-align: center">
        <tr>
            <th>姓名</th>
            <th>密码</th>
        </tr>
        <tr v-for="u in users"> <!--vue遍历-->
            <td>{{u.username}}</td>
            <td>{{u.password}}</td>
        </tr>
    </table>
    <button @click="acceptJson()">接收Json数组</button>
</div>
<script>
    new Vue({
        "el":"#box",
        "data":{
            "users":[],//user数组
        },
        "methods":{
            "acceptJson": function (){
                axios({
                    "method":"post",
                    "url":"ajax5",
                }).then( value =>{
                    alert("接收")
                    //接收json数据数组,通过vue渲染
                    console.log(value.data);
                    this.users = value.data;
                }).catch(reason => {
                    console.log("请求失败");
                });
            }
        }
    })
</script>
</body>

服务端发送: 

@WebServlet("/ajax5")
public class Ajax05Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("------ Ajax05Servlet ------");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //封装user集合
        User us1 = new User("张三", "123456");
        User us2 = new User("李四", "123456");
        User us3 = new User("王五", "123456");
        User us4 = new User("赵六", "123456");
        ArrayList<User> userList = new ArrayList<>();
        Collections.addAll(userList,us1,us2,us3,us4);

        //1.调用gson工具将user集合转换为json字符串
        Gson gson = new Gson();
        String listJson = gson.toJson(userList);

        //2.获取打印流打印到客户端
        PrintWriter writer = resp.getWriter();
        writer.println(listJson);
    }
}

4. gson、jackson 工具类 (json数据与java对象的转换)

Gson 是Google研发的一款非常优秀的JSON数据解析和生成工具,它可以帮助我们将数据在JSON字符串和Java对象之间互相转换。   new Gson() 

jackson 是Java中比较常用的JSON解析的工具包SpringMVC和SpringBoot中默认支持的就是jackson。 new ObjectMapper();

jackson:

public class JackSonTest {
    //jackSon
    ObjectMapper objectMapper = new ObjectMapper();

    //1.Java对象 转为 json格式字符串
    @Test
    public void test01() throws JsonProcessingException {
        User user = new User("李白", "123456");
        //转换
        String json = objectMapper.writeValueAsString(user);

        System.out.println("json = " + json);//{"username":"李白","password":"123456"}
    }

    //2.json格式字符串 转为 Java对象
    @Test
    public void test02() throws IOException {
        String json = "{\"username\":\"李白\",\"password\":\"123456\"}";
        //转换
        User user = objectMapper.readValue(json, User.class);

        System.out.println("user = " + user);//user = User{username='李白', password='123456'}
    }

    //3.Java集合 转为 Json格式数组字符串
    @Test
    public void test03() throws IOException {
        User user1 = new User("李白", "123456");
        User user2 = new User("杜甫", "123456");
        List<User> list = new ArrayList<>();
        list.add(user2);
        list.add(user1);
        //转换
        String json = objectMapper.writeValueAsString(list);

        System.out.println("json = " + json);//[{"username":"杜甫","password":"123456"},{"username":"李白","password":"123456"}]
    }

    //4. Json格式数组字符串 转为 Java集合
    @Test
    public void test04() throws IOException {
        String json ="[{\"username\":\"杜甫\",\"password\":\"123456\"},{\"username\":\"李白\",\"password\":\"123456\"}]";

        TypeReference<List<User>> typeReference = new TypeReference<List<User>>() {};
        //转换
        List<User> list = objectMapper.readValue(json, typeReference);

        list.forEach(System.out::println);
    }

Gson:

public class GsonTest {
    //gson工具类 Java对象与json数据字符串转换
    Gson gson = new Gson();
    //1.Java对象 转为 json格式字符串
    @Test
    public void test01(){
        User user = new User("李白", "杜甫");
        //转换
        String json = gson.toJson(user);

        System.out.println("json = " + json);   //{"username":"李白","password":"杜甫"}
    }
    @Test
    //2.json格式字符串 转为 Java对象
    public void test02(){
        String json = "{\"username\":\"李白\",\"password\":\"杜甫\"}";
        //转换
        User user = gson.fromJson(json, User.class);

        System.out.println("user = " + user);//User{username='李白', password='杜甫'}

    }
    //3, Java集合 转为 Json格式数组字符串
    @Test
    public void test03(){
        User user1 = new User("李白", "杜甫");
        User user2 = new User("李白", "杜甫");
        ArrayList<User> list = new ArrayList<>();
        Collections.addAll(list, user1,user2);
        //转换
        String json = gson.toJson(list);

        System.out.println("json = " + json);//[{"username":"李白","password":"杜甫"},{"username":"李白","password":"杜甫"}]
    }
    //4. Json格式数组字符串 转为 Java集合
    @Test
    public void test04(){
        String json = "[{\"username\":\"李白\",\"password\":\"123456\"},{\"username\":\"杜甫\",\"password\":\"123456\"}]";
        //生成的对象类型
        Type type = new TypeToken<List<User>>() {}.getType();

        List<User> o = gson.fromJson(json, type);
        o.forEach(System.out::println);
    }
}

封装 JSONUtils

将重复内容进行封装:JSON工具类,用于获取json格式的请求参数 以及 向客户端响应json字符串

public class JSONUtils {
    /**
     * 通用的将 json数据从请求中获取并封装为对象
     * @param req 请求
     * @param clazz 转为对象的Class类型
     * @return
     */
    //将json数据从请求中获取并封装为对象
    public static <T> T parseJsonStr(HttpServletRequest req,Class<T> clazz){
        //java8新特性 自动关闭流    获取输入流
        try (BufferedReader reader = req.getReader()){
            //准备拼接字符串
            StringBuilder sbl = new StringBuilder();
            String line = "";
            while ((line = reader.readLine())!=null){
                sbl.append(line);
            }
            //jackson工具类 将Json数据字符串转换为Java对象
            ObjectMapper mapper = new ObjectMapper();
            T t = mapper.readValue(sbl.toString(), clazz);

            return t;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
    /**
     * 将对象转为json写出的方法
     * @param response 响应对象
     * @param obj 要写出的对象
     */
    public static void writeJson(HttpServletResponse response, Object obj){
        try {
            //jackson工具类 将Java对象转换为Json数据字符串
            ObjectMapper objectMapper = new ObjectMapper();

            String json = objectMapper.writeValueAsString(obj);

            response.getWriter().println(json);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
}

三、书城项目第五阶段

 由于后期有很多配置文件,建立资源文件夹方便管理,等同于放在src目录下

1. 封装CommonResult (ajax结果模型)

在整个项目中,凡是涉及到给Ajax请求返回响应,我们都封装到CommonResult类型中。

属性名含义
flag服务器端处理请求的结果,取值为true或者false
message服务器端处理请求失败之后,要响应给客户端的数据
resultData服务器端处理请求成功之后,需要响应给客户端的数据

作为整个团队开发过程中,前后端交互时使用的统一的数据格式,有利于团队成员之间的协助,提高开发效率。

代码实现: 

//ajax 结果模型
public class CommonResult {

    private boolean flag;      //请求(业务)成功还是失败
    private Object resultData; //请求成功时响应的数据 (主要针对查询)
    private String massage;    //失败时响应的错误信息

    //业务成功
    public static CommonResult ok(){
        return new CommonResult().setFlag(true);
    }

    //业务成功,返回数据
    public static CommonResult ok(Object data){
        return new CommonResult().setFlag(true).setResultData(data);
    }

    //业务失败
    public static CommonResult error(){
        return new CommonResult().setFlag(false);
    }
    //业务失败,返回失败原因
    public static CommonResult error(String message){
        return new CommonResult().setFlag(false).setMassage(message);
    }

由于在setFlag() 等操作中返回值为null,并不会返回CommonResult对象,所以在生成get()、set() 方法时我们选择:

    public boolean isFlag() {
        return flag;
    }
    public CommonResult setFlag(boolean flag) {
        this.flag = flag;
        return this;    //会返回当前this对象
    }
    public Object getResultData() {
        return resultData;
    }
    public CommonResult setResultData(Object resultData) {
        this.resultData = resultData;
        return this;
    }

2. 注册页面:用户名唯一性检查优化 — Ajax局部更新

在用户输入用户名之后,立即检查这个用户名是否可用(触发失去焦点事件blur)。

代码:

html(部分)
    <script>
      new Vue({
        "el": ".login_banner",
        "data": {
          //新增: Ajax异步请求判定
          "userNameFlag":"",
        },
        "methods":{
          "checkUserName": function (){
            this.userNameErrStyle = {"visibility": "visible"};
            var reg = /^[A-Za-z][A-Za-z0-9]{5,15}$/;

            //阶段5:用户名唯一性检查优化 — Ajax局部更新
            if (reg.test(this.userName)) {
              //用户名格式正确后进行校验,通过axios发送异步请求给UserServlet
              axios({
                "method":"post",
                "url":"user",
                "params":{    //向服务端传递参数,用户名与的方法名
                  "method":"checkUserName",
                  "username":this.userName
                }
              }).then( response=>{
                if(response.data.flag){
                  //如果能注册
                  this.userNameErrMsg = "验证成功";
                  this.userNameFlag=true;
                }else {
                  //如果不能注册,将ajax结果模型中的错误信息渲染到页面
                  this.userNameErrMsg = response.data.massage;
                  this.userNameFlag=false;
                }
              });

            } else {
              this.userNameErrMsg = "帐号须以字母开头,由6~16位数字和字母组成";
              this.userNameFlag=false;
            }
          },
    </script>
UserServlet (部分)  表述层
public class UserServlet extends ModelBaseServlet {
    UserService userService = new UserServiceImpl(); //业务层 service
    //注册用户名异步校验(axios)
    private void checkUserName(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("----- checkUserName -----");
        //ajax 结果模型
        CommonResult commonResult = null;
        try {
            //1.获取浏览器传递的用户名
            String name = request.getParameter("username");
            //2.调用业务层方法 判断用户名是否可以用
            userService.findByUserName(name);

            //3.用户名可用返回业务成功模型
            commonResult = CommonResult.ok();
        } catch (Exception e) {
            e.printStackTrace();
            //4.用户名不可用返回业务失败模型,传入失败信息,局部更新
            commonResult = CommonResult.error(e.getMessage());
        }

        //5.调用工具类将结果模型对象转换为Json格式,对ajax进行信息反馈
        JSONUtils.writeJson(response,commonResult);
    }
}
UserService (部分)  业务逻辑层
public class UserServiceImpl implements UserService {
    UserDao userDao = new UserDaoImpl();    //数据访问层 Dao
    //异步校验用户名
    @Override
    public void findByUserName(String name) {
        //1.查询用户名是否存在
        User user = userDao.selectByName(name);
        if(user!=null){
            throw new RuntimeException("用户名["+name+"]已经存在");
        }
    }
}

3. 加入购物车

首页添加商品到购物车、解决刷新问题

Java
//添加一个购物项(首页添加到购物车)
    private void addCartItem(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("----- addCartItem -----");
        CommonResult commonResult = null;   //ajax结果模型
        try {
            //1.获取请求参数bookId
            int bookId = Integer.parseInt(request.getParameter("bookId"));
            System.out.println(bookId);

            //2.通过书籍业务层,通过id获取图书信息
            BookService bookService = new BookServiceImpl();
            Book book = bookService.getById(bookId);

            //3.从session中获取购物车,判断购物车是否存在
            HttpSession session = request.getSession();
            Cart cart = (Cart) session.getAttribute(Constants.CART_SESSION_KEY);    //常量购物车的key,方便统一管理
            if (cart == null) {
                //4.1,不存在,新建购物车添加到session会话域中
                cart = new Cart();
                session.setAttribute(Constants.CART_SESSION_KEY, cart);
            }

            //4.2将书籍信息添加到购物车
            cart.addCartItem(book);
            //5.1获取当前购物项总数量,封装到ajax结果模型
            Integer totalCount = cart.getTotalCount();
            commonResult = CommonResult.ok(totalCount);
        } catch (Exception e) {
            e.printStackTrace();
            //5.2获取当前异常信息,封装到ajax结果模型
            commonResult = CommonResult.error(e.getMessage());
        }
        //5.调用工具类,转换为Json数据格式,响应到客户端
        JSONUtils.writeJson(response, commonResult);
    }
    //获取购物车条目数(首页购物车数量渲染)
    private void getTotalCount(HttpServletRequest request, HttpServletResponse response){
        CommonResult commonResult = null;   //ajax结果模型
        try {
            //1.获取购物车对象
            HttpSession session = request.getSession();
            Cart cart = (Cart) session.getAttribute(Constants.CART_SESSION_KEY);
            //2.1如果购物车不存在,数量为0
            Integer count = 0;
            if (cart != null) {
                //2.2如果购物车存在,获取购物车内部数量
                count = cart.getTotalCount();
            }
            //3.封装到结果模型内
            commonResult = CommonResult.ok(count);
        } catch (Exception e) {
            e.printStackTrace();
            commonResult = CommonResult.ok(e.getMessage());
        }
        //4.调用工具类,打包发送
        JSONUtils.writeJson(response,commonResult);
    }
index.html
</script>

    <!--局部渲染购物车数量-->
    <script>
      var vue = new Vue({
        "el":"#app",
        "data":{
          "totalCount":"",  //购物车数量
        },
        "methods":{
          "addCart":function (){
            var bookId = event.target.value;  //获取当前节点下,图书id
            axios({
              "url":"cart",
              "method":"post",
              "params":{
                "method":"addCartItem", //添加一个购物项
                "bookId":bookId,        //传参bookId,
              }

            }).then(function (response){

              layer.msg("添加成功");  //layer弹窗组件
              console.log(response.data);
              //如果响应模型信息为true,进行渲染
              if(response.data.flag){
                //注意:没有箭头函数不能用this
                vue.totalCount=response.data.resultData;
              }

            })
          }
        },

        //vue 生命周期钩子函数,解决刷新后购物车显示清零
        //在数据没有挂载之前,就获取了数据,等挂载后渲染了实时数据
        "created":function (){
          axios({
            "url":"cart",
            "method":"post",
            "params":{
              "method":"getTotalCount"  //获取购物车条目数方法
            }
          }).then(function (response){
            console.log(response);
            vue.totalCount=response.data.resultData;  //获取信息,进行渲染
          })
        }
      });


    </script>

前往购物车页面、渲染页面

//前往cart页面
    private void toCartPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("----- toCartPage -----");

        processTemplate("cart/cart",request,response);
    }

    //获取购物车信息(cart页面动态渲染)
    private void getCart(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("----- getCart -----");
        CommonResult commonResult = null;
        try {
            //1.获取session内购物车
            HttpSession session = request.getSession();
            Cart cart = (Cart) session.getAttribute(Constants.CART_SESSION_KEY);

            //2.如果cart不为null,封装信息打包到map集合
            Map map = new HashMap<>();
            if(cart!=null){
                Integer totalCount = cart.getTotalCount();
                Double totalAmount = cart.getTotalAmount();
                List<CartItem> cartItem = cart.getCartItem();

                map.put("totalCount",totalCount);
                map.put("totalAmount",totalAmount);
                map.put("cartItemList",cartItem);
            }
            //3.将map信息添加到成功数据模型内,
            commonResult = CommonResult.ok(map);
        } catch (Exception e) {
            e.printStackTrace();
            commonResult = CommonResult.error(e.getMessage());
        }
        //3.将信息转为Json格式,响应到页面渲染
        JSONUtils.writeJson(response,commonResult);
    }
 cart.html
<script>

 "created":function (){
        //vue生命周期钩子函数
        axios({
          "url":"cart",
          "method":"post",
          "params":{
            "method":"getCart"  //获取购物车函数
          }
        }).then(function (response){
          console.log("请求成功")
          console.log(response.data);

          //当业务成功时
          if(response.data.flag){
            vue.cart = response.data.resultData;
          }
        });
      }
    })

</script>

清空购物车

 //清空购物车
    private void clearCart(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("----- clearCart -----");
        try {
            HttpSession session = request.getSession();
            //移除key中的购物车
            session.removeAttribute(Constants.CART_SESSION_KEY);

            //跳转回购物车页面
            processTemplate("cart/cart",request,response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
<a href="cart?method=clearCart" @click="clearCart" class="clear-cart">清空购物车</a>

<script>
    var vue = new Vue({
      "el":"#box",
      "data":{
        "cart":{
          "totalAmount":"总价格",
          "totalCount":"总数",
          "cartItemList":[  //用数组表示条目
            {
              /*"imgPath":"static/uploads/huozhe.jpg",
              "title":"活着",
              "count":1,
              "price":"36.8",
              "amount":"36.8"*/
            },
          ]
        }
      },
      "methods":{

        //清空购物车
        "clearCart":function (){
          //如果选择不清空,取消默认行为,不跳转Servlet
          let flag = confirm("是否清空购物车?");
          if(!flag){
            event.preventDefault();
          }
        },


</script>

减号操作(购物项-1)

        //购物项数量-1
    /*  1.
        count amount 购物项
        购物车 totalCount totalAmount
        2.当购物项只有一条记录时,要删除
     */
    private void countDecrease(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("----- countDecrease -----");
        CommonResult commonResult = null;
        try {
            //1.获取请求参数 (注意保持一致)
            int bookId = Integer.parseInt(request.getParameter("bookId"));

            //2.获取购物车
            HttpSession session = request.getSession();
            Cart cart = (Cart) session.getAttribute(Constants.CART_SESSION_KEY);

            //3.购物项数量-1
            /*CartItem cartItem = cart.getMap().get(bookId);*/
            cart.cartItemCountDecrease(bookId); //cart内方法

            //4.获取购物项,封装响应数据
            CartItem cartItem = cart.getMap().get(bookId);
            HashMap map = new HashMap<>();
            //如果购物项为null,没必要再封装该信息
            if(cartItem !=null){

                map.put("count", cartItem.getCount());
                map.put("amount", cartItem.getAmount());
            }

            map.put("totalAmount", cart.getTotalAmount());
            map.put("totalCount", cart.getTotalCount());

            //map.put("cartItemList", cart.getCartItem());

            commonResult = CommonResult.ok(map);
        } catch (Exception e) {
            e.printStackTrace();
            commonResult = CommonResult.error(e.getMessage());
        }
        JSONUtils.writeJson(response,commonResult);
    }
<script>
    var vue = new Vue({
      "el":"#box",
      "data":{
        "cart":{
          "totalAmount":"总价格",
          "totalCount":"总数",
          "cartItemList":[  //用数组表示条目
            {
              /*"imgPath":"static/uploads/huozhe.jpg",
              "title":"活着",
              "count":1,
              "price":"36.8",
              "amount":"36.8"*/
            },
          ]
        }
      },
      "methods":{
        //减号操作
        "countDecrease":function (count,title,bookId,index){
          /*console.log(count);
          console.log(title);
          console.log(bookId);
          console.log(index);*/
          //容错,如果购物项只有1,询问是否删除
          if(count==1){
            var flag = confirm("您真的要删除["+title+"]吗?")
            if(!flag){
              return;
            }
          }
          //发起异步请求
          axios({
            "url":"cart",
            "method":"post",
            "params":{
              "method":"countDecrease",    //方法
              "bookId":bookId,
            }
          }).then(function (response){
            console.log(response.data);

            if(response.data.flag){

              //如果当前项目数只有1,直接删掉即可
              if(count==1){
                vue.cart.cartItemList.splice(index,1);
              }else {
                //如果为1,-1后为0.没必要更新项目
                vue.cart.cartItemList[index].count = response.data.resultData.count;
                vue.cart.cartItemList[index].amount = response.data.resultData.amount;
              }
              //无论是否为1,都要更新购物车总内容
              vue.cart.totalCount = response.data.resultData.totalCount;
              vue.cart.totalAmount = response.data.resultData.totalAmount;
              /*vue.cart =  response.data.resultData;*/

            }
          });
        },

</script>

加号操作(购物项+1)

        //加号操作
        "countIncrease": function (count,bookId,index){

          axios({
            "url":"cart",
            "method":"post",
            "params":{
              "method":"countIncrease",
              "bookId":bookId,
            }
          }).then(function (response){

            console.log("加号成功了");
            console.log(response.data);

            if(response.data.flag){
              //修改购物项数量和金额
              vue.cart.cartItemList[index].count = response.data.resultData.count;
              vue.cart.cartItemList[index].amount = response.data.resultData.amount;
              //修改页面总金额
              vue.cart.totalCount = response.data.resultData.totalCount;
              vue.cart.totalAmount = response.data.resultData.totalAmount;
            }
          })
        },
<script>
    var vue = new Vue({
      "el":"#box",
      "data":{
        "cart":{
          "totalAmount":"总价格",
          "totalCount":"总数",
          "cartItemList":[  //用数组表示条目
            {
              /*"imgPath":"static/uploads/huozhe.jpg",
              "title":"活着",
              "count":1,
              "price":"36.8",
              "amount":"36.8"*/
            },
          ]
        }
      },
      "methods":{

        //加号操作
        "countIncrease": function (count,bookId,index){

          axios({
            "url":"cart",
            "method":"post",
            "params":{
              "method":"countIncrease",
              "bookId":bookId,
            }
          }).then(function (response){

            console.log("加号成功了");
            console.log(response.data);

            if(response.data.flag){
              //修改购物项数量和金额
              vue.cart.cartItemList[index].count = response.data.resultData.count;
              vue.cart.cartItemList[index].amount = response.data.resultData.amount;
              //修改页面总金额
              vue.cart.totalCount = response.data.resultData.totalCount;
              vue.cart.totalAmount = response.data.resultData.totalAmount;
            }
          })
        },

</script>

删除购物项

    //删除购物项
    private void removeCartItem(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("----- removeCartItem -----");
        CommonResult commonResult = null;
        try {
            //1.获取id
            int bookId = Integer.parseInt(request.getParameter("bookId"));

            //2.获取购物车
            Cart cart = (Cart) request.getSession().getAttribute(Constants.CART_SESSION_KEY);

            //3.删除购物车
            cart.removeCartItem(bookId);

            //4.准备响应数据

            HashMap map = getHashMap(bookId,cart);

            commonResult = CommonResult.ok(map);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            commonResult = CommonResult.ok(e.getMessage());
        }
        JSONUtils.writeJson(response,commonResult);
    }
<script>
    var vue = new Vue({
      "el":"#box",
      "data":{
        "cart":{
          "totalAmount":"总价格",
          "totalCount":"总数",
          "cartItemList":[  //用数组表示条目
            {
              /*"imgPath":"static/uploads/huozhe.jpg",
              "title":"活着",
              "count":1,
              "price":"36.8",
              "amount":"36.8"*/
            },
          ]
        }
      },
      "methods":{

        
        //删除购物项
        "removeCartItem":function (title,bookId,index){
          event.preventDefault();

          let flag = confirm("是否删除购物项?");

          if(!flag){
            //event.preventDefault();
          }else {

            axios({
              "url":"cart",
              "method":"post",
              "params":{
                "method":"removeCartItem",
                "bookId":bookId
              }
            }).then(function (response){

              if(response.data.flag){
                //删除数据模型中指定下标的数据
                vue.cart.cartItemList.splice(index,1);
                //更改总数量和总金额
                vue.cart.totalCount = response.data.resultData.totalCount;
                vue.cart.totalAmount = response.data.resultData.totalAmount;

              }
            })
          }

        },

      
</script>

修改购物项数量

//修改购物项
    private void countUpdate(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("----- countUpdate -----");
        CommonResult commonResult = null;
        try {
            //获取购物车
            Cart cart = (Cart) request.getSession().getAttribute(Constants.CART_SESSION_KEY);

            //获取参数,bookId,count
            int bookId = Integer.parseInt(request.getParameter("bookId"));
            Integer count = Integer.valueOf(request.getParameter("count"));

            //调用书籍业务层,调用指定购物项库存数,判断是否大于
            BookService bookService = new BookServiceImpl();
            Book book = bookService.getById(bookId);

            if(count > book.getStock()){
                throw new RuntimeException("库存不足");
            }

            //获得购物项,修改数量
            cart.cartItemUpdateCount(bookId,count);

            //封装响应数据
            CartItem cartItem = cart.getMap().get(bookId);
            HashMap map = new HashMap<>();
            //如果购物项为null,没必要再封装该信息
            if(cartItem !=null){
                map.put("count", cartItem.getCount());
                map.put("amount", cartItem.getAmount());
            }

            map.put("totalCount", cart.getTotalCount());
            map.put("totalAmount", cart.getTotalAmount());

            commonResult = CommonResult.ok(map);

        } catch (Exception e) {
            e.printStackTrace();
            commonResult = CommonResult.error(e.getMessage());
        }
        //转换为Json格式发送
        JSONUtils.writeJson(response,commonResult);
    }
<script>
    var vue = new Vue({
      "el":"#box",
      "data":{
        "cart":{
          "totalAmount":"总价格",
          "totalCount":"总数",
          "cartItemList":[  //用数组表示条目
            {
              /*"imgPath":"static/uploads/huozhe.jpg",
              "title":"活着",
              "count":1,
              "price":"36.8",
              "amount":"36.8"*/
            },
          ]
        }
      },
      "methods":{

        //修改项目数量
        "countUpdate":function (count,bookId,index){
          var reg = /^[1-9][0-9]*$/ //输入是否合法
          if(reg.test(count)){
            axios({
              "url":"cart",
              "method":"post",
              "params":{
                "method":"countUpdate",
                "bookId":bookId,
                "count":count,
              }
            }).then( function (response){
              console.log(response.data);
              if(response.data.flag){
                vue.cart.cartItemList[index].count = response.data.resultData.count;
                vue.cart.cartItemList[index].amount = response.data.resultData.amount;

                vue.cart.totalCount = response.data.resultData.totalCount;
                vue.cart.totalAmount = response.data.resultData.totalAmount;
              }else {
                alert(response.data.massage)
              }
            });
          }else {
            alert("请输入正确的数据")
          }
        }
      },
</script>

页面效果



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值