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;@Servicepublic 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技术.