大数据正式京淘12
【前台我的购物车系统】
展示购物车信息
添加商品到购物车
更改购物车中商品的数量
- 局部刷新
- ajax异步请求
购物车部分代码展示
-
controller层
package com.peng.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import com.peng.pojo.Cart; import com.peng.service.CartService; import com.peng.threadlocal.UserThreadLocal; @Controller @RequestMapping("/cart") public class CartController { @Autowired @Qualifier("cartService") private CartService cartService; // 展示购物车信息 @RequestMapping("/show") public String show(Model model) { Long userId = UserThreadLocal.get().getId(); System.err.println("=========333333333333===============:" + userId); List<Cart> cartList = cartService.show(userId); model.addAttribute("cartList", cartList); return "cart"; } // 添加商品到购物车 @RequestMapping("/add/{itemId}") public String addCart(@PathVariable Long itemId, Integer num) { Long userId = UserThreadLocal.get().getId(); cartService.saveCart(userId, itemId, num); return "redirect:/cart/show.html"; } // 更改购物车商品的数量 @RequestMapping("/update/num/{itemId}/{num}") public String updataNum(@PathVariable Long itemId, @PathVariable Integer num) { Long userId = UserThreadLocal.get().getId(); cartService.updateNum(userId, itemId, num); return "";// 局部刷新 } // 删除啊购物车里的商品 @RequestMapping("/delete/{itemId}") public String deleteItem(@PathVariable Long itemId) { Long userId = UserThreadLocal.get().getId(); cartService.deleteItem(userId, itemId); return "redirect:/cart/show.html"; } }
-
service层
-
service接口
package com.peng.service; import java.util.List; import com.peng.pojo.Cart; public interface CartService { /** * 展示购物车信息 * * @param userId * @return */ List<Cart> show(Long userId); /** * 保存购物车 * * @param userId * @param itemId * @param num */ void saveCart(Long userId, Long itemId, Integer num); /** * 更新商品的数量 * * @param userId * @param itemId * @param num */ void updateNum(Long userId, Long itemId, Integer num); /** * 删除商品 * * @param userId * @param itemId */ void deleteItem(Long userId, Long itemId); }
-
service实现类
package com.peng.service.impl; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.peng.pojo.Cart; import com.peng.pojo.Item; import com.peng.service.CartService; import com.peng.service.HttpClientService; @Service("cartService") public class CartServiceImpl implements CartService { @Autowired private HttpClientService httpClient; private ObjectMapper MAPPER = new ObjectMapper(); @Override public List<Cart> show(Long userId) { List<Cart> carts = null; try { String url = "http://cart.jt.com/cart/query/" + userId; String jsonData = httpClient.doGet(url, "utf-8"); JsonNode jsonNode = MAPPER.readTree(jsonData); JsonNode data = jsonNode.get("data"); // 转化为list对象 if (data.isArray() && data.size() > 0) { carts = MAPPER.readValue(data.traverse(), MAPPER.getTypeFactory().constructCollectionType(List.class, Cart.class)); } } catch (Exception e) { e.printStackTrace(); } return carts; } @Override public void saveCart(Long userId, Long itemId, Integer num) { try { // 获取数据 String url = "http://manage.jt.com/items/" + itemId; String JsonItem = httpClient.doGet(url, "utf-8"); Item item = MAPPER.readValue(JsonItem, Item.class); // 保存数据 url = "http://cart.jt.com/cart/save"; // 封装数据 Map<String, String> params = new HashMap<String, String>(); params.put("userId", userId + ""); params.put("itemId", itemId + ""); params.put("num", num + ""); params.put("itemTitle", item.getTitle()); params.put("itemImage", item.getImages()[0]); params.put("itemPrice", item.getPrice() + ""); httpClient.doPost(url, params); } catch (Exception e) { e.printStackTrace(); } } @Override public void updateNum(Long userId, Long itemId, Integer num) { try { String url = "http://cart.jt.com/cart/update/num/" + userId + "/" + itemId + "/" + num; httpClient.doGet(url, "utf-8"); } catch (Exception e) { e.printStackTrace(); } } @Override public void deleteItem(Long userId, Long itemId) { try { String url = "http://cart.jt.com/cart/delete/" + userId + "/" + itemId; httpClient.doGet(url, "utf-8"); } catch (Exception e) { e.printStackTrace(); } } }
-
拦截器
- 拦截过程
- 访问形如“购物车”、“订单”的功能
- 判断是否登录,即拦截,进行相应的操作
- 访问形如“购物车”、“订单”的功能
- 原理:
- 将具有一定规则的发送到controller的请求
- 底层是面向切面编程
- 例子:
- 拦截器拦截地址,没有userId,系统转发到登录界面,如果已经登录,则将userId放到一个ThreadLocal【get、set、remove】中
- 拦截的对象
- 拦截订单
- 拦截购物车
- 不拦截游客能看的
- 拦截时机
- preHandle--controller处理之前-------选这个时机进行处理
- postHandle--controller【包括后台的service和到层的处理】处理之后
- afterCompletion--页面渲染之后到页面展示之前
-
拦截代码展示
- 拦截配置:在springmvc-config.xml中配置拦截器
<!-- 拦截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 拦截的请求地址:一个*代表下一级目录;两个*代表多级 --> <mvc:mapping path="/cart/**" /> <bean class="com.peng.interceptor.CartInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
-
拦截器类
package com.peng.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.peng.pojo.User; import com.peng.service.HttpClientService; import com.peng.threadlocal.UserThreadLocal; import com.peng.util.CookieUtils; public class CartInterceptor implements HandlerInterceptor { /** * 实现逻辑: 1.从cooke中获取ticket 2.去访问sso,调用httpClient访问,访问redis * 3.user.json转化为user 4.获取数据userId,判断一下 5.共享数据解决线程的安全问题 */ @Autowired HttpClientService httpClient; private static final ObjectMapper om = new ObjectMapper(); // controller之前 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在controller处理之前拦截 String cookieName = "JT_TICKET"; String ticket = CookieUtils.getCookieValue(request, cookieName); // 判断一下cookie if (StringUtils.isNotEmpty(ticket)) { String url = "http://sso.jt.com/user/query/" + ticket; String jsonString = httpClient.doGet(url, "utf-8"); if (StringUtils.isNotEmpty(jsonString)) { JsonNode jsonNode = om.readTree(jsonString); String jsonUser = jsonNode.get("data").asText(); // 将当前的用户对象转化 User user = om.readValue(jsonUser, User.class); // 封装userId,共享数据到controller UserThreadLocal.set(user);// 解决线程安全的问题--一次请求一定是一个线程对象 return true; } } UserThreadLocal.set(null);// 这个作用:防止意外 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 { } }
-
线程安全类
package com.peng.threadlocal; import com.peng.pojo.User; public class UserThreadLocal { private static ThreadLocal<User> ThreadUser = new ThreadLocal<User>(); public static void set(User user2) { ThreadUser.set(user2); } public static User get() { return ThreadUser.get(); } }
- 拦截配置:在springmvc-config.xml中配置拦截器
订单系统
订单商品表
- 复合主键
- 大于一个字段能够唯一的确定一条记录在数据表中国的位置
- 例如:【itemId和orderId】
- 冗余字段
- 例如:【总金额】
- 表设计
搭建订单系统
- 新建maven项目jt_order
- 修改相应的项目项目属性
- 添加配置文件
- 测试运行
订单模块
- 生成订单模块
- 提交订单模块
订单模块流程图示
- 购物车去结算
- 订单页面
- 提交订单:显示提交成功
订单系统部分代码展示
controller层【jt_web】
package com.peng.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.peng.pojo.Cart;
import com.peng.pojo.Order;
import com.peng.service.OrderService;
import com.peng.threadlocal.UserThreadLocal;
import com.peng.vo.SysResult;
@Controller
@RequestMapping("/order")
public class OrderController {
@Autowired
@Qualifier("orderService")
private OrderService orderService;
// 生成订单
@RequestMapping("/create")
public String orderCarts(Model model) {
Long userId = UserThreadLocal.get().getId();
List<Cart> cartList = orderService.orderCarts(userId);
model.addAttribute("carts", cartList);
return "order-cart";
}
// 提交创建订单
@RequestMapping("/submit")
@ResponseBody
public SysResult createOrder(Order order) {
Long userId = UserThreadLocal.get().getId();
System.err.println(order + ".....................................");// TODO:order信息不准
order.setUserId(userId);
String orderId = orderService.saveOrder(order);
System.err.println(orderId + ".....................................");
return SysResult.oK(orderId);
}
// 成功提交,转发到相应的成功页面
@RequestMapping("/success")
public String success(@PathVariable("id") String orderId, Model model) {
Order order = orderService.queryOrderById(orderId);// Id为null
model.addAttribute("order", order);
return "success";
}
}
service层【jt_web】
-
service接口
package com.peng.service; import java.util.List; import com.peng.pojo.Cart; import com.peng.pojo.Order; public interface OrderService { /** * 通过userId查询所有的订单 * * @param userId * @return */ List<Cart> orderCarts(Long userId); /** * * * @param order * @return */ String saveOrder(Order order); /** * 通过编号查询订单信息 * * @param orderId * @return */ Order queryOrderById(String orderId); }
-
service实现类
package com.peng.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.peng.pojo.Cart; import com.peng.pojo.Order; import com.peng.service.HttpClientService; import com.peng.service.OrderService; @Service("orderService") public class OrderServiceImpl implements OrderService { @Autowired private HttpClientService httpClient; private ObjectMapper MAPPER = new ObjectMapper(); @Override public List<Cart> orderCarts(Long userId) { List<Cart> carts = null; try { String url = "http://cart.jt.com/cart/query/" + userId; String jsonData = httpClient.doGet(url, "utf-8"); JsonNode jsonNode = MAPPER.readTree(jsonData); JsonNode data = jsonNode.get("data"); // 转化为list对象 if (data.isArray() && data.size() > 0) { carts = MAPPER.readValue(data.traverse(), MAPPER.getTypeFactory().constructCollectionType(List.class, Cart.class)); } } catch (Exception e) { e.printStackTrace(); } return carts; } @Override public String saveOrder(Order order) { String orderId = order.getOrderId(); try { String url = "http://order.jt.com/create"; String jsonData = MAPPER.writeValueAsString(order); httpClient.doPostJson(url, jsonData); } catch (Exception e) { e.printStackTrace(); } return orderId; } @Override public Order queryOrderById(String orderId) { Order order = null; try { String url = "http://order.jt.com/query/" + orderId; String jsonDta = httpClient.doGet(url, "utf-8"); order = MAPPER.readValue(jsonDta, Order.class); } catch (Exception e) { e.printStackTrace(); } return order; } }
Controller层【jt_order】
package com.peng.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.peng.pojo.Order;
import com.peng.service.OrderService;
@Controller("orderController")
@RequestMapping("/order")
public class OrderController {
@Autowired
@Qualifier("orderService")
private OrderService orderService;
private static final ObjectMapper MAPPER = new ObjectMapper();
// 创建订单
@RequestMapping("/create")
@ResponseBody
public String orderCreate(@RequestBody String json) {
String orderId = "";
try {
Order order = MAPPER.readValue(json, Order.class);
orderId = orderService.saveOrder(order);
} catch (Exception e) {
e.printStackTrace();
}
return orderId;
}
// 查询订单
@RequestMapping("/query/{orderId}")
@ResponseBody
public Order queryOrder(@PathVariable String orderId) {
Order order = null;
try {
order = orderService.queryOrderById(orderId);
} catch (Exception e) {
e.printStackTrace();
}
return order;
}
}
Service层【jt_order】
-
service接口
package com.peng.service; import com.peng.pojo.Order; public interface OrderService { /** * 保存订单 * * @param order * @return */ String saveOrder(Order order); /** * 查询订单 * * @param orderId * @return */ Order queryOrderById(String orderId); }
-
service实现类
package com.peng.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import com.peng.mapper.OrderMapper; import com.peng.pojo.Order; import com.peng.service.BaseService; import com.peng.service.OrderService; @Service("orderService") public class OrderServiceImpl extends BaseService<Order> implements OrderService { @Autowired @Qualifier("orderMapper") private OrderMapper orderMapper; @Override public String saveOrder(Order order) { // 完成order的封装 String orderId = order.getUserId() + "" + System.currentTimeMillis(); orderMapper.orderCreate(order); return orderId; } @Override public Order queryOrderById(String orderId) { return orderMapper.queryOrderById(orderId); } }
dao层【jt_order】
-
Mapper接口
package com.peng.mapper; import com.peng.pojo.Order; public interface OrderMapper extends SysMapper<Order> { /** * 新增订单 * * @param order */ void orderCreate(Order order); /** * 查询订单 * * @param orderId * @return */ Order queryOrderById(String orderId); }
- Mapper的xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.peng.mapper.OrderMapper"> <sql id="tableName">tb_order</sql> <!-- 返回封装 --> <resultMap type="Order" id="pojoResultMap" autoMapping="true"> <id column="order_id" property="orderId" /> <association property="orderShipping" javaType="OrderShipping" column="order_id" select="queryOrderShippingByOrderId" autoMapping="true"></association> <collection property="orderItems" javaType="Arraylist" ofType="OrderItem" autoMapping="true" select="queryOrderItemByOrderId" column="order_id"> </collection> </resultMap> <!-- 通过订单号查询所有商品 --> <select id="queryOrderItemByOrderId" resultType="OrderItem" parameterType="String"> SELECT * FROM tb_order_item WHERE order_id = #{orderId}; </select> <!-- 通过订单号查询所有的订单 --> <select id="queryOrderShippingByOrderId" resultType="OrderShipping" parameterType="String"> SELECT * FROM tb_order_shipping WHERE order_id = #{orderId}; </select> <!-- 查询所有的订单 --> <select id="queryList" resultMap="pojoResultMap"> SELECT * FROM <include refid="tableName" /> </select> <!-- 通过订单编号查询所有的订单 --> <select id="queryOrderById" resultMap="pojoResultMap"> SELECT * FROM <include refid="tableName" /> WHERE order_id = #{id}; </select> <!-- 新增订单 --> <insert id="orderCreate" useGeneratedKeys="true" keyProperty="id"> INSERT INTO <include refid="tableName" /> VALUES (#{orderId},#{payment},#{paymentType},#{postFee},#{status},#{createTime},#{updateTime},#{paymentTime},#{consignTime},#{endTime},#{closeTime},#{shippingName},#{shippingCode},#{userId},#{buyerMessage},#{buyerNick},#{buyerRate}); INSERT INTO tb_order_item VALUES <foreach collection="orderItems" item="item" separator=","> (#{item.itemId},#{orderId},#{item.num},#{item.title},#{item.price},#{item.totalFee},#{item.picPath}) </foreach> ; INSERT INTO tb_order_shipping VALUES (#{orderId},#{orderShipping.receiverName},#{orderShipping.receiverPhone},#{orderShipping.receiverMobile},#{orderShipping.receiverState},#{orderShipping.receiverCity},#{orderShipping.receiverDistrict},#{orderShipping.receiverAddress},#{orderShipping.receiverZip},NOW(),NOW()); </insert> </mapper>
补充--范式
三范式
- 第一范式
- 强调列的原子性,不可再拆分
- 例子
- 例子
- 强调列的原子性,不可再拆分
- 第二范式
- 满足第一范式
- 包含两个内容
- 必须有主键
- 非主键字段必须完全依赖于主键,不能部分依赖主键
- 例子
- 第三范式
- 满足第一范式
- 是第二范式的一个特例
- 非主键属性必须依赖主键属性,不能依赖于非主键属性
- 例子
- 总结
- 三范式是在数据库初期使用(时间换取空间),能外键关联,就用外键关联,能不冗余数据设计,就不设计
反范式
- 违反第二、第三范式就是反范式