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技术.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。