/**
* 业务实现:
* 1. 用户通过 cookie 信息查问用户数据. 通过 ticket 获取 redis 中的业务数据.
* 2.url 申请: http://sso.jt.com/user/query/+ _ticket
* 3. 参数: 参数在 url 中. 利用 restFul 获取
* 4. 返回值要求: SysResult 对象 (userJSON)
*/
@RequestMapping("/query/{ticket}")
public JSONPObject findUserByTicket(@PathVariable String ticket,
HttpServletResponse response,
String callback){String userJSON = jedisCluster.get(ticket);
//1.lru 算法清空数据 2. 有可能 cookie 信息有误
if(StringUtils.isEmpty(userJSON)){
//2. 应该删除 cookie 信息.
Cookie cookie = new Cookie("JT_TICKET", "");
cookie.setMaxAge(0);
cookie.setDomain("jt.com");
cookie.setPath("/");
response.addCookie(cookie);
return new JSONPObject(callback,SysResult.fail());
}
return new JSONPObject(callback,SysResult.success(userJSON));
}
package com.jt.util;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieUtil {
//1. 新增 cookie
public static void addCookie(HttpServletResponse response,String cookieName, String cookieValue, int seconds, String domain){Cookie cookie = new Cookie(cookieName,cookieValue);
cookie.setMaxAge(seconds);
cookie.setDomain(domain);
cookie.setPath("/");
response.addCookie(cookie);
}
//2. 依据 name 查问 value 的值
public static String getCookieValue(HttpServletRequest request,String cookieName){Cookie[] cookies = request.getCookies();
if(cookies !=null && cookies.length >0){for (Cookie cookie : cookies){if(cookieName.equals(cookie.getName())){return cookie.getValue();
}
}
}
return null;
}
//3. 删除 cookie
public static void deleteCookie(HttpServletResponse response,String cookieName,String domain){addCookie(response,cookieName,"",0, domain);
}
}
如果用户点击退出操作, 首先应该删除 Redis 中的数据 其次删除 Cookie 中的数据之后重定向到零碎首页.
/**
* 实现用户的退出操作. 重定向到零碎首页
* url: http://www.jt.com/user/logout.html
* 业务:
* 1. 删除 Redis 中的数据 key
* 2. 删除 Cookie 记录
*/
@RequestMapping("logout")
public String logout(HttpServletRequest request,HttpServletResponse response){
//1. 依据 JT_TICKET 获取指定的 ticket
String ticket = CookieUtil.getCookieValue(request,"JT_TICKET");
//2. 判断 ticket 是否为 null
if(!StringUtils.isEmpty(ticket)){jedisCluster.del(ticket);
CookieUtil.deleteCookie(response,"JT_TICKET","jt.com");
}
return "redirect:/";
}
阐明: 当用户点击商品时, 须要跳转到商品的展示页面中, 页面名称 item.jsp
阐明: 在 jt-common 中创立接口
package com.jt.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.ItemDescMapper;
import com.jt.mapper.ItemMapper;
import com.jt.pojo.Item;
import com.jt.pojo.ItemDesc;
import org.springframework.beans.factory.annotation.Autowired;
@Service(timeout = 3000)
public class DubboItemServiceImpl implements DubboItemService{
@Autowired
private ItemMapper itemMapper;
@Autowired
private ItemDescMapper itemDescMapper;
@Override
public Item findItemById(Long itemId) {return itemMapper.selectById(itemId);
}
@Override
public ItemDesc findItemDescById(Long itemId) {return itemDescMapper.selectById(itemId);
}
}
server:
port: 8091
servlet:
context-path: /
spring:
datasource:
#引入 druid 数据源
#type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush 配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.jt.mapper: debug
#对于 Dubbo 配置
dubbo:
scan:
basePackages: com.jt #指定 dubbo 的包门路 扫描 dubbo 注解
application: #利用名称
name: provider-manage #一个接口对应一个服务名称 一个接口能够有多个实现
registry: #注册核心 用户获取数据从机中获取 主机只负责监控整个集群 实现数据同步
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协定
name: dubbo #应用 dubbo 协定 (tcp-ip) web-controller 间接调用 sso-Service
port: 20881 #每一个服务都有本人特定的端口 不能反复.
package com.jt.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Item;
import com.jt.pojo.ItemDesc;
import com.jt.service.DubboItemService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/items")
public class ItemController {@Reference(timeout = 3000)
private DubboItemService itemService;
/**
* 实现商品详情页面跳转
* url: http://www.jt.com/items/562379.html
* 参数: 562379 itemId
* 返回值: item.jsp 页面
* 页面取值阐明:
* ${item.title} item 对象
* ${itemDesc.itemDesc} itemDesc 对象
*
* 思路:
* 1. 重构 jt-manage 我的项目
* 2. 创立中立接口 DubboItemService
* 3. 实现业务调用获取 item/itemDesc 对象
*/
@RequestMapping("/{itemId}")
public String findItemById(@PathVariable Long itemId, Model model){Item item = itemService.findItemById(itemId);
ItemDesc itemDesc = itemService.findItemDescById(itemId);
// 将数据保留到 request 域中
model.addAttribute("item",item);
model.addAttribute("itemDesc",itemDesc);
return "item";
}
}
<!--2. 增加依赖信息 -->
<dependencies>
<!-- 依赖本质依赖的是 jar 包文件 -->
<dependency>
<groupId>com.jt</groupId>
<artifactId>jt-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!--3. 增加插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
@TableName("tb_cart")
@Data
@Accessors(chain = true)
public class Cart extends BasePojo{ // 应用包装类型
@TableId(type = IdType.AUTO)
private Long id;
private Long uesrId; // 用户 ID 号
private Long itemId; // 商品 ID 号
private String itemTitle; // 商品题目
private String itemImage; // 图片
private Long itemPrice; // 商品价格
private Integer num; // 商品数量
}
阐明: 当用户点击购物车按钮时, 须要跳转到购物车展示页面 cart.jsp
页面取值:${cartList}
要求: 只查问 userId= 7 的购物车列表信息, 之后进行页面展示.
package com.jt.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Cart;
import com.jt.service.DubboCartService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/cart")
public class CartController {@Reference(timeout = 3000,check = false)
private DubboCartService cartService;
/**
* 业务需要: 依据 userId 查问购物车数据
* url 地址: http://www.jt.com/cart/show.html
* 申请参数: 动静获取 userId
* 返回值后果: cart.jsp 页面
* 页面取值形式: ${cartList}
*/
@RequestMapping("/show")
public String findCartListByUserId(Model model){
Long userId = 7L;
List<Cart> cartList = cartService.findCartListByUserId(userId);
model.addAttribute("cartList",cartList);
return "cart";
}
}
package com.jt.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.CartMapper;
import com.jt.pojo.Cart;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Service
public class DubboCartServiceImpl implements DubboCartService{
@Autowired
private CartMapper cartMapper;
@Override
public List<Cart> findCartListByUserId(Long userId) {QueryWrapper<Cart> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId);
return cartMapper.selectList(queryWrapper);
}
}
/**
* 业务: 实现购物车数量的更新
* url: http://www.jt.com/cart/update/num/562379/12
* 参数: itemId/num
* 返回值: void
*/
@RequestMapping("/update/num/{itemId}/{num}")
@ResponseBody //1. 返回值转化为 json 2.ajax 完结标识
public void updateCartNum(Cart cart){ //key 名称必须与属性的名称统一.
Long userId = 7L;
cart.setUserId(userId);
cartService.updateCartNum(cart);
}
@Override
public void updateCartNum(Cart cart) {//cartMapper.updateCartNum(cart);
//1. 筹备批改的数据 依据对象中不为 null 的元素当做 set 条件
Cart cartTemp = new Cart();
cartTemp.setNum(cart.getNum());
//2. 依据对象中不为 null 的元素当做 where 条件
UpdateWrapper<Cart> updateWrapper =
new UpdateWrapper<>(cart.setNum(null));
/*updateWrapper.eq("user_id", cart.getUserId())
.eq("item_id", cart.getItemId());*/
cartMapper.update(cartTemp,updateWrapper);
}
public interface CartMapper extends BaseMapper<Cart> {@Update("update tb_cart set num = #{num},updated=now() where user_id=#{userId} and item_id=#{itemId}")
void updateCartNum(Cart cart);
}
阐明: 当用户点击购物车按钮时实现购物车入库操作. 如果用户反复加购则应该批改购物车商数量. 加购胜利后, 应该重定向到购物车列表页面.
<form id="cartForm" method="post">
<input class="text" id="buy-num" name="num" value="1" onkeyup="setAmount.modify('#buy-num');"/>
<input type="hidden" class="text" name="itemTitle" value="${item.title}"/>
<input type="hidden" class="text" name="itemImage" value="${item.images[0]}"/>
<input type="hidden" class="text" name="itemPrice" value="${item.price}"/>
</form>
<a class="btn-append" id="InitCartUrl" onclick="addCart();" clstag="shangpin|keycount|product|initcarturl"> 退出购物车 <b></b></a>
// 利用 post 传值
function addCart(){var url = "http://www.jt.com/cart/add/${item.id}.html";
document.forms[0].action = url; //js 设置提交链接
document.forms[0].submit(); //js 表单提交}
/**
* 实现购物车新增
* url: http://www.jt.com/cart/add/562379.html
* 参数: form 表单提交 对象接管
* 返回值: 重定向到购物车列表页面中
*/
@RequestMapping("/add/{itemId}")
public String saveCart(Cart cart){
Long userId = 7L;
cart.setUserId(userId);
cartService.saveCart(cart);
return "redirect:/cart/show.html";
}
/**
* 如果反复加购则更新数量
* 1. 查问是否曾经有改数据 user_id/item_id
*/
@Override
public void saveCart(Cart cart) {QueryWrapper<Cart> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", cart.getUserId())
.eq("item_id", cart.getItemId());
Cart cartDB = cartMapper.selectOne(queryWrapper);
if(cartDB == null){
// 用户第一次加购
cartMapper.insert(cart);
}else {
// 用户须要批改数量
int num = cart.getNum() + cartDB.getNum();
cart.setNum(num);
cartMapper.updateCartNum(cart);
}
}