目录
4. gson、jackson 工具类 (json数据与java对象的转换)
页面效果
一、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>