共计 11236 个字符,预计需要花费 29 分钟才能阅读完成。
cgb2010- 京淘我的项目 Day20
1. 实现京淘购物车操作
1.1 数量更新操作
1.1.1 页面剖析
1). 页面 URL 剖析
2). 页面 html 剖析
`<div class="quantity-form" data-bind="">
<a href="javascript:void(0);" class="decrement" clstag="clickcart|keycount|xincart|diminish1" id="decrement">-</a>
<input type="text" class="quantity-text" itemPrice="${cart.itemPrice}" itemId="${cart.itemId}" value="${cart.num}" id="changeQuantity-11345721-1-1-0">
<a href="javascript:void(0);" class="increment" clstag="clickcart|keycount|xincart|add1" id="increment">+</a>
</div>
3). 页面 JS
`$(".increment").click(function(){//+
var _thisInput = $(this).siblings("input");
_thisInput.val(eval(_thisInput.val()) + 1);
$.post("/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val(),function(data){TTCart.refreshTotalPrice();
});
});
1.1.3 编辑 CartController
`/**
* 购物车数量更新操作
* URL 地址: http://www.jt.com/cart/update/num/1474391990/16
* 参数: itemId,num
* 返回值: 没有 void
*/
@RequestMapping("/update/num/{itemId}/{num}")
@ResponseBody // 将返回值转化为 json 代表 ajax 程序完结
public void updateNum(Cart cart){
long userId = 7;
cart.setUserId(userId);
cartService.updateNum(cart);
}
1.1.2 编辑 CartService
`//sql: update tb_cart set num=#{num},updated=#{updated} where user_id=#{userId} and
// item_id = #{itemId}
@Override
public void updateNum(Cart cart) {Cart temp = new Cart();
temp.setNum(cart.getNum());
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("user_id", cart.getUserId());
queryWrapper.eq("item_id", cart.getItemId());
cartMapper.update(temp,queryWrapper);
}
1.2 购物车删除操作
1.2.1 页面剖析
业务阐明: 当用户点击删除按钮时, 应该重定向到购物车展示页面.
1.2.2 编辑 CartController
`/**
* URL 地址:http://www.jt.com/cart/delete/1474391990.html
* 返回值: String 类型
*/
@RequestMapping("/delete/{itemId}")
public String deleteCart(Cart cart){
long userId = 7;
cart.setUserId(userId);
cartService.deleteCart(cart);
return "redirect:/cart/show.html";
}
1.2.3 编辑 CartService
`@Override
public void deleteCart(Cart cart) {
// 依据对象中不为 null 的属性充当 where 条件
cartMapper.delete(new QueryWrapper<>(cart));
}
2 对于前台权限管制
2.1 业务阐明
当用户在没有登录的条件下, 不容许拜访敏感业务数据例如购物车 / 订单业务等…
难点:
1. 如何判断用户是否登录? 1. 查看 cookie 2. 查看 redis
2. 如何管制权限? 拦截器!
2.2 拦截器业务实现原理
2.2.1 SpringMVC 流程图温习
2.2.2 拦截器工作流程
2.2.3 配置拦截器
2.2.4 编辑拦截器接口
`package com.jt.interceptor;
import com.jt.pojo.User;
import com.jt.util.CookieUtil;
import com.jt.util.ObjectMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import redis.clients.jedis.JedisCluster;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.function.Predicate;
@Component // 将对象交给 Spring 容器治理
public class UserInterceptor implements HandlerInterceptor {
@Autowired
private JedisCluster jedisCluster;
/**
* 通过拦截器实现拦挡, 重定向零碎登录页面
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*
* 返回值阐明:
* boolean false 示意拦挡 个别配合重定向形式应用
*
* 业务调用:
* 1. 获取 cookie 中的数据
* 2. 查看 redis 中是否有数据
* 3. 校验用户是否登录.
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1. 获取 cookie 中的数据, 查看是否登录
String ticket = CookieUtil.getCookieValue(request, "JT_TICKET");
if(StringUtils.hasLength(ticket) && jedisCluster.exists(ticket)){// 判断数据是否有值
//2. 动静获取 user 信息
String json = jedisCluster.get(ticket);
//3. 将 json 转化为用户对象
User user = ObjectMapperUtil.toObj(json, User.class);
request.setAttribute("JT_USER", user);
return true; // 示意程序放行
}
// 实现用户重定向
response.sendRedirect("/user/login.html");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { }
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {request.removeAttribute("JT_USER");
}
}
2.2.5 编辑 CartController
2.3 ThreadLocal
2.3.1 ThreadLocal 作用
名称: 本地线程变量
作用: 在同一个线程内, 实现数据共享.
2.3.2 封装工具 API
`package com.jt.util;
import com.jt.pojo.User;
public class UserThreadLocal {
// 线程的一个属性 ThreadLocal 是线程平安的
private static ThreadLocal<User> threadLocal = new ThreadLocal<>();
public static void set(User user){threadLocal.set(user);
}
public static User get(){return threadLocal.get();
}
public static void remove(){threadLocal.remove(); // 删除数据
}
}
2.3.3 基于 ThreadLocal 实现数据取赋值操作
1. 拦截器赋值
2. 用户取值
3. 数据销毁
3. 订单模块
3.1 订单确认页面跳转
3.1.1 业务剖析
阐明: 当点击去结算按钮时, 应该跳转到订单确认页面 order-cart.jsp.
3.1.2 编辑 OrderController
`package com.jt.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Cart;
import com.jt.service.DubboCartService;
import com.jt.util.UserThreadLocal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/order")
public class OrderController {
@Reference
private DubboCartService cartService;
/**
* 业务阐明:
* 当点击按钮时, 跳转到订单确认页面 cartList 购物车数据
* URL 地址:http://www.jt.com/order/create.html
* 参数: userId
* 返回值: 页面逻辑名称 order-cart
* 页面取值: ${carts}
*/
@RequestMapping("/create")
public String orderCreate(Model model){long userId = UserThreadLocal.get().getId();
List<Cart> cartList = cartService.findCartListByUserId(userId);
model.addAttribute("carts",cartList);
return "order-cart";
}
}
3.1.3 页面成果展示
3.2 订单我的项目创立
3.2.1 创立订单我的项目
3.2.2 增加继承 / 依赖 / 插件
`<dependencies>
<dependency>
<groupId>com.jt</groupId>
<artifactId>jt-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!-- 增加插件 有 main 办法时 须要增加插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
3.2.3 对于订单表设计说明
3.2.4 编辑 POJO
3.2.5 代码构造如下
3.3 SpringMVC 参数传递形式
3.3.1 为简略参数赋值
`<input type="text" name="username" value="admin" />
`public void addUser(String username){}
3.3.2 为对象赋值
`<input type="text" name="id" value="100" />
<input type="text" name="username" value="admin" />
<input type="text" name="age" value="18" />
`public void addUser(User user){}
3.3.3 为对象引入赋值
问题: 有时可能遇到重名属性! 如何解决?
`<input type="text" name="name" value="二郎神" />
<input type="text" name="age" value="30" />
<input type="text" name="dog.name" value="啸天犬" />
<-- 为 list 汇合赋值 -->
<input type="text" name="hobbys[0]" value="敲代码" />
`// 利用对象的形式进行封装
public class User {
private String name;
private Integer age;
private Dog dog;
private List hobbys
}
public class Dog {
private String name;
private Integer age;
}
// SpringMVC 参数接管
public void addUser(User user){}
3.4 订单提交
3.4.1 页面剖析
1). 页面 URL 剖析
2). 参数阐明
3).POJO 对象封装
4). 页面 JS 剖析
`jQuery.ajax( {
type : "POST",
dataType : "json",
url : "/order/submit",
// 将 name 属性与值进行拼接 模式 name=value1&name2=value2&name3=value3......
// 表单序列化, 能够简化参数写法
data : $("#orderForm").serialize(),
cache : false,
success : function(result) { //SysResult 对象
if(result.status == 200){ // 要求返回 orderId
location.href = "/order/success.html?id="+result.data;
}else{$("#submit_message").html("订单提交失败,请稍后重试...").show();}
},
error : function(error) {$("#submit_message").html("敬爱的用户请不要频繁点击, 请稍后重试...").show();}
});
3.4.2 编辑 OrderController
`/**
* 实现订单入库操作
* url 剖析: http://www.jt.com/order/submit
* 参数: 整个 form 表单 Order 对象
* 返回值: SysResult 对象
* 页面取值: 要求返回 orderId
*/
@RequestMapping("/submit")
@ResponseBody
public SysResult submit(Order order){long userId = UserThreadLocal.get().getId();
order.setUserId(userId);
String orderId = orderService.saveOrder(order);
// 实现订单之后, 应该删除购物车.. 分布式事务....
//cartService.deleteCart();
return SysResult.success(orderId);
}
3.4.3 编辑 OrderService
`package com.jt.service;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jt.mapper.OrderItemMapper;
import com.jt.mapper.OrderMapper;
import com.jt.mapper.OrderShippingMapper;
import com.jt.pojo.Order;
import com.jt.pojo.OrderItem;
import com.jt.pojo.OrderShipping;
@Service
public class OrderServiceImpl implements DubboOrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderShippingMapper orderShippingMapper;
@Autowired
private OrderItemMapper orderItemMapper;
/**
* 实现 3 张表入库操作
* order 表入库
* orderItem 表入库
* OrderShipping 表入库
* 动静生成 orderId. 设定默认状态
* 留神数据库事务管制
* @param order
* @return
*/
@Override
@Transactional
public String saveOrder(Order order) {
// 动静生成主键
String orderId = "" + order.getUserId() + System.currentTimeMillis();
//1. 实现订单入库操作
order.setOrderId(orderId).setStatus(1);
orderMapper.insert(order);
System.out.println("订单入库操作胜利!!!");
//2. 实现订单物流入库
OrderShipping orderShipping = order.getOrderShipping();
orderShipping.setOrderId(orderId);
orderShippingMapper.insert(orderShipping);
System.out.println("订单物流入库胜利!!!");
//3. 实现订单商品入库操作
List<OrderItem> orderItems = order.getOrderItems();
for (OrderItem orderItem : orderItems){orderItem.setOrderId(orderId);
orderItemMapper.insert(orderItem);
}
System.out.println("订单全副入库胜利!!!!");
return orderId;
}
}
3.5 订单查问
3.5.1 业务剖析
阐明: 当用户订单入库之后, 应该跳转到订单的胜利页面. 格局如下:
页面数据: ${order}
3.5.2 编辑 OrderController
`/**
* 实现订单查问
* url: http://www.jt.com/order/success.html?id=71613981329562
* 参数: orderId
* 返回值: 胜利页面 success.jsp
* 页面取值: Order 对象(蕴含其它 2 个业务数据) ${order.orderId}
*/
@RequestMapping("/success")
public String success(String id,Model model){
// 依据 id 查问订单对象
Order order = orderService.findOrderById(id);
model.addAttribute("order", order);
return "success";
}
3.5.3 编辑 OrderService
`@Override
public Order findOrderById(String id) {Order order = orderMapper.selectById(id);
OrderShipping orderShipping = orderShippingMapper.selectById(id);
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("order_id", id);
List<OrderItem> orderItems = orderItemMapper.selectList(queryWrapper);
return order.setOrderShipping(orderShipping).setOrderItems(orderItems);
}
3.5.4 页面成果
4 京淘我的项目总结
4.1 Maven 工作原理
1).maven 作用 一站式的项目管理工具 治理 jar 包 我的项目打包部署
2).maven 依赖传递性 A –B–C 如何实现的
3).Maven 如何保障 jar 包文件不被篡改 sha1 音讯摘要.
4.2 SpringBoot 工作原理
1). 开箱即用准则? 如何实现的??
2). 为属性赋值用法 @Value(“${key}”)
3). 动静导入 pro 配置文件 @propertySource
4). 环境宰割 — 环境命名 默认环境抉择
5).LOMBOK 插件 注解 @Data xxxx
6).SpringBoot 整合 Mybatis 了解配置文件 别名包 / 驼峰映射规定
7).SpringBoot 整合 MybatisPlus ORM 思维 对象关系映射.
8).SpringBoot 整合 web 动静资源 JSP 我的项目打包 war 包
4.3 分布式架构设计计划
1). 分布式架构设计 依照模块拆分 依照层级拆分
2). 了解分布式 / 集群 / 高可用的概念
3). 构建分布式系统的准则 如何对立治理 jar 包 如何对立管理工具 API
4.4 京淘后端我的项目搭建
1). 业务 商品 CURD 操作 / 商品分类 CURD 操作
2).VO 对象的编辑准则 调用他人的 JS 必须依照要求返回 JSON.
3). 全局异样解决的设计.
4). 如何定义零碎返回值对象 SysResult 对象
5). 文件上传案例.
4.5 反向代理服务器
1). 什么是反向代理
2). 什么是正向代理
3).nginx 相干配置 命令 配置
4).hosts 文件作用 实现域名与 IP 地址的映射
5).nginx 负载平衡形式 1. 轮询 2. 权重 3.iphash
6).nginx 高级属性用法 1.down 2.backup 3. 高可用设定.
4.6 Linux
1). 命令: cd/cp/mv/mkdir/rm/vim/…
2). 装置 JDK vim /etc/profile java -version
3).mariadb 数据库装置 思考权限 导入数据库 / 表 防火墙命令
4). 实现 manage 我的项目 Linux 部署.
5).Linux 的 nginx 我的项目部署
6). 实现数据库高可用 数据库主从同步命令 基于 Mycat 实现数据库高可用.
4.7 Redis 相干学习
1).redis 命令 反对 1 -5- 8 种数据类型
2).redis 分片机制 实现内存扩容 一致性 hash 算法 2^32 取值形式
3).redis 哨兵机制 实现高可用 哨兵的工作原理 如何监控
4).redis 集群配置 redis 分区算法. crc16(key)%16384
5).redis 长久化策略 RDB 快照 /AOF 操作过程
6).redis 内存优化策略 LRU/LFU/random/TTL
7). 什么是缓存穿透 拜访不存在的数据 布隆过滤器算法
8). 什么是缓存击穿 拜访某个热点数据生效了 多级缓存
9). 什么是缓存雪崩 大量的数据同时生效 多级缓存
10).SpringBoot 整合 redis 相干配置.
4.8 实现前端搭建
1). 跨域思维 同源策略(协定:// 域名: 端口)
2). 跨域解决方案 1.JSONP 形式(1. 利用 script 标签 src 实现跨域 2. 自定义回调函数 3. 非凡格局封装)
2.CORS(设定服务端数据共享 设定响应头信息)
3).httpClient 万能的近程过程调用的办法 个别多见于框架底层代码 例如 SpringCloud
4). 伪动态思维 以.html 结尾的申请
4.9 微服务框架
1).SOA 思维
2).RPC 近程过程调用 绝对本地而言 代词
3). 微服务调用思维
4). 注册核心 zookeeper 服务. 单台—> 集群搭建
5). 微服务框架的调用的流程 ZK 集群的选举机制 / 工作原理
6).Dubbo 框架 1. 中立的接口 2. 服务生产者 3. 服务器消费者
7).Dubbo 负载平衡机制 1. 一致性 hash 2. 最小拜访 3. 随机策略 4. 轮询机制 客户端负载平衡
4.10 业务流程调用
1). 基于 dubbo 实现商品数据的获取
2). 基于 dubbo 实现 jt-sso 单点登录 Cookie 操作 登录 / 登出 / 数据回显
3). 实现购物车性能 CRUD 操作 购物车中的记录如果存在则更新数量 / 不存在新增购物车.
4). 实现权限管制 基于拦截器
5). 利用 request 对象 /ThreadLocal 形式动静取值.
6). 订单业务逻辑 表 3 张 为对象的援用赋值. 多张表业务操作 留神事务管制.
次要学习 SpringCloud 机制… docker 容器 MQ 技术.