电商前台的常见业务逻辑

用户注册实现

编辑UserController

@RequestMapping("/user/doRegister")
    @ResponseBody
    public SysResult doRegister(User user) {
        
        userService.doRegister(user);
        return SysResult.success();
    }

编辑UserService

@Service
public class DubboUserServiceImpl implements DubboUserService{
    
    @Autowired
    private UserMapper userMapper;
    
    @Override
    @Transactional  //控制事务
    public void doRegister(User user) {
        //1.密码加密   md5   md5hash shiro框架
        byte[] bytes = user.getPassword().getBytes();
        String md5Pass = DigestUtils.md5DigestAsHex(bytes);
        
        user.setPassword(md5Pass).setEmail(user.getPhone())
            .setCreated(new Date()).setUpdated(user.getCreated());
        userMapper.insert(user);
    }
    
}

用户单点登陆

编辑UserController

/**
     * Cookie数据的共享问题:
     *   原则:Cookie根据不同的域名,展现的数据(权限)不同
     *     www.jd.com  默认条件下浏览器中只能看到 www.jd.com的cookie信息.
     *     www.baidu.com 默认条件下只能看到www.baidu.com的cookie信息.
     *   
     *     cookie.setDomain("jd.com");     
     *          xxxx.jd.com全部域名可以实现cookie数据共享
     * 
     * @param user
     * @return
     */
    @RequestMapping("/doLogin")
    @ResponseBody
    public SysResult doLogin(User user,HttpServletResponse response) {
        
        //1.调用远程jt-sso服务器
        String uuid = userService.doLogin(user);
        
        //2.检验uuid是否为null
        if(StringUtils.isEmpty(uuid)) {
            //说明后台服务器校验不通过.
            return SysResult.fail();
        }
        
        //3.用户登陆正常,之后需要将用户数据写入cookie中
        Cookie cookie = new Cookie("JT_TICKET", uuid);
        cookie.setMaxAge(7*24*60*60);   //7天超时
        cookie.setDomain("jt.com");     //设定cookie数据共享
        //www.jd.com/find 可以获取
        //www.jd.com/aaa/find   可以获取的!!
        cookie.setPath("/");            //当前cookie在根目录中有效
        response.addCookie(cookie);
        
        //4.返回正确的数据
        return SysResult.success();
    }

编辑UserService

/**
     * 1.根据用户信息查询数据库,检查是否有效
     * 2.根据查询结果
     *      null: 表示用户名和密码错误.
     *      有结果: 执行单点登陆的业务流程.
     */
    @Override
    public String doLogin(User user) {  //UUID
        //密码加密
        String md5Pass = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        queryWrapper.eq("username", user.getUsername())
                    .eq("password", md5Pass);
        //根据username和password获取用户信息
        User userDB = userMapper.selectOne(queryWrapper);
        
        //判断数据是否有效
        if(userDB == null) {
            //根据用户名和密码查询,没有结果
            return null;
        }
        
        //如果程序执行到这里,说明用户的查询没有错,可以进行单点登陆操作
        String key = UUID.randomUUID().toString();
        //不安全:userDB包含了用户的全部记录信息,  由于userJSON保存到第三方存储,最好
        //将敏感数据去除(脱敏处理)
        userDB.setPassword("123456");
        String userJSON = ObjectMapperUtil.toJSON(userDB);
        jedisCluster.setex(key, 7*24*60*60, userJSON);
        
        return key;
    }

用户信息回显
编辑jt-sso UserController

/**
     *JSONP调用
     * 根据ticket信息查询userJSON数据
     */
    @GetMapping("/query/{ticket}")
    public JSONPObject findUserByTicket(@PathVariable String ticket,String callback) {
        String userJSON = jedisCluster.get(ticket);
        //判断当前redis中是否有数据
        if(StringUtils.isEmpty(userJSON)) {
            
            return new JSONPObject(callback, SysResult.fail());
        }else {
            //证明用户已经登陆
            SysResult sysResult = SysResult.success(userJSON);
            return new JSONPObject(callback,sysResult);
        }
    }

用户退出

/**
     * 实现用户退出,重定向到系统首页
     * http://www.jt.com/user/logout.html
     * 思考:
     *  1.获取cookie数据.   JT_TICKET
     *  2.获取ticket信息   删除redis数据
     *  3.删除cookie记录
     *  4.重定向到系统首页
     *  
     */
    @RequestMapping("/logout")
    public String logout(HttpServletRequest request,HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();
        if(cookies !=null && cookies.length>0) {
            for (Cookie cookie : cookies) {
                if("JT_TICKET".equals(cookie.getName())) {
                    String ticket = cookie.getValue();
                    //删除redis数据
                    jedisCluster.del(ticket);
                    
                    //删除cookie时需要重新为cookie赋值,否则删除失效
                    cookie.setMaxAge(0);         //立即删除
                    cookie.setDomain("jt.com");  //设定cookie数据共享
                    cookie.setPath("/");         //当前cookie在根目录中有效
                    response.addCookie(cookie);
                    break;
                }
            }
        }
        return "redirect:/";
    }

购物车业务

编辑POJO

@TableName("tb_cart")
@Data
@Accessors(chain=true)
public class Cart extends BasePojo{
    @TableId(type=IdType.AUTO)
    private Long id;
    private Long userId;
    private Long itemId;
    private String itemTitle;   //商品标题
    private String itemImage;   //商品图片
    private Long itemPrice;     //商品价格
    private Integer num;        //数量
}

编辑CartController

@Controller             //1
@RequestMapping("/cart")
public class CartController {
    
    @Reference(check=false)
    private DubboCartService cartService;
    
    /**
     * 2.根据userId获取购物车数据
     * 页面取值:${cartList}
     * @return
     */
    @RequestMapping("/show")
    public String show(Model model) {
        Long userId = 7L;
        List<Cart> cartList = cartService.findCartListByUserId(userId);
        model.addAttribute("cartList", cartList);
        return "cart";
    }
    
}

编辑CartService

@Service
public class DubboCartServiceImpl implements DubboCartService {
    
    @Autowired
    private CartMapper cartMapper;@Override
    public List<Cart> findCartListByUserId(Long userId) {
        
        QueryWrapper<Cart> queryWrapper = new QueryWrapper<Cart>();
        queryWrapper.eq("user_id", userId);
        return cartMapper.selectList(queryWrapper);
    }
    
}

商品数量修改
编辑CartController

/**
     * 完成商品数量的修改
     * restFul规则说明:  如果参数名称与属性的名称一致,则可以使用对象接收
     */
    @RequestMapping("/update/num/{itemId}/{num}")
    @ResponseBody
    public SysResult updateCartNum(Cart cart) {
        
        Long userId = 7L;
        cart.setUserId(userId);
        cartService.updateCartNum(cart);
        return SysResult.success();
    }

编辑CartService

/**
     * entity 修改的数据信息
     * updateWrapper:修改数据的条件
     */
    @Override
    @Transactional  //控制事务
    public void updateCartNum(Cart cart) {
        Cart cartTemp = new Cart();
        cartTemp.setNum(cart.getNum())
                .setUpdated(new Date());
        UpdateWrapper<Cart> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("user_id", cart.getUserId())
                     .eq("item_id", cart.getItemId());
        cartMapper.update(cartTemp, updateWrapper);
    }

商品删除
编辑CartController

/**
     * 业务需求:根据itemId和userId删除购物车
     * 
     */
    @RequestMapping("/delete/{itemId}")
    public String  deleteCart(Cart cart) {
        
        Long userId = 7L;
        cart.setUserId(userId);
        cartService.deleteCart(cart);
        return "redirect:/cart/show.html";  //重定向到购物车列表页面
    }

编辑CartService

@Override
    public void deleteCart(Cart cart) {
        //根据对象中不为null的属性来充当where条件.
        QueryWrapper<Cart> wrapper = new QueryWrapper<Cart>(cart);
        cartMapper.delete(wrapper);
    }

购物车新增
编辑CartController

/**
     * 购物车新增
     */
    @RequestMapping("/add/{itemId}")
    public String saveCart(Cart cart) {
        
        Long userId = 7L;
        cart.setUserId(userId);
        cartService.saveCart(cart);
        return "redirect:/cart/show.html";  //重定向到购物车列表页面
    }

编辑CartService

/**
     * 思路:
     *  1.根据userId和itemId查询数据库.
     *  2.如果查询没有结果,则做新增操作.
     *  3.如果查询有结果,则做更新操作.
     */
    @Override
    @Transactional  //控制事务
    public void saveCart(Cart cart) {
        QueryWrapper<Cart> queryWrapper = new QueryWrapper<Cart>();
        queryWrapper.eq("user_id", cart.getUserId())
                    .eq("item_id", cart.getItemId());
        Cart cartDB = cartMapper.selectOne(queryWrapper);
        //判断是否有值
        if(cartDB == null) {
            cart.setCreated(new Date())
                .setUpdated(cart.getCreated());
            cartMapper.insert(cart);
        }else {
            //更新操作
            int num = cart.getNum() + cartDB.getNum();
            //cartDB.setNum(num).setUpdated(new Date());
            //UPDATE tb_cart SET user_id=?, item_id=?, item_title=?, item_image=?, item_price=?, num=?, created=?, updated=? WHERE id=?
            //UPDATE tb_cart SET num=?,updated=? WHERE id=?
            Cart cartTemp = new Cart();
            cartTemp.setNum(num).setUpdated(new Date());
            UpdateWrapper<Cart> updateWrapper = new UpdateWrapper<Cart>();
            updateWrapper.eq("id", cartDB.getId());
            cartMapper.update(cartTemp, updateWrapper);
        }
    }

项目权限设计

当用户点击购物车时需要校验用户是否登陆.如果用户没有登陆,则重定向到登陆页面.如果用户已经登陆,则放行请求.

拦截器工作流程
在这里插入图片描述
编辑拦截器

@Component
public class UserInterceptor implements HandlerInterceptor{
    
    @Autowired
    private JedisCluster jedisCluster;
    /**
     * boolean: true    拦截器放行
     *          false   拦截器拦截   一般配合重定向的方式使用.
     * 
     * 拦截器的业务策略: 
     *      如果用户已经登陆则放行,如果未登录则拦截
     * 
     * 思路:判断用户登陆的业务逻辑
     *      1.获取用户的Cookie记录
     *      2.获取JT_TICKET的值.
     *      3.查询redis
     *          null:   false
     *          !null:  true
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //根据cookie获取value结果
        String cookieValue = CookieUtils.getValue(request, "JT_TICKET");
        //判断value是否有值
        if(!StringUtils.isEmpty(cookieValue)) {
            //判断redis中是否有该记录.
            if(jedisCluster.exists(cookieValue)) {
                String key = cookieValue;
                String userJSON = jedisCluster.get(key);
                User user = ObjectMapperUtil.toObject(userJSON, User.class);
                //将数据保存到request对象中
                request.setAttribute("JT_USER", user);
                
                //如果有特殊的需求,可以利用session临时保存数据.
                //request.getSession().setAttribute(name, value);
                
                //用户已经登陆.予以放行
                return true;
            }
        }
        response.sendRedirect("/user/login.html");
        return false;   //表示拦截
    }
    
    
    /**
     * 结构完整!!!!
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        //业务处理完成之后,将用户信息删除.
        request.removeAttribute("JT_USER");
    }
    
}

动态获取UserId显示购物车信息

@RequestMapping("/show")
    public String show(Model model,HttpServletRequest request) {
        User user = (User) request.getAttribute("JT_USER");
        Long userId = user.getId();
        List<Cart> cartList = cartService.findCartListByUserId(userId);
        model.addAttribute("cartList", cartList);
        return "cart";
    }

订单业务

编辑OrderController

@Controller
@RequestMapping("/order")
public class OrderController {
    
    private static final String USERNAME = "JT_USER";
    
    @Reference(check=false)
    private DubboCartService cartService;
    
    //http://www.jt.com/order/create.html  
    @RequestMapping("/create")
    public String create(HttpServletRequest request,Model model) {
        //动态获取用户的购物车记录  ${carts}
        User user = (User) request.getAttribute(USERNAME);
        Long userId = user.getId();
        List<Cart> cartList = cartService.findCartListByUserId(userId);
        request.setAttribute("carts", cartList);
        return "order-cart";
    }
}

编辑OrderController.完成订单入库.

/**
     * 完成订单入库操作
     * url:http://www.jt.com/order/submit
     * 参数:利用order对象进行数据封装
     * 返回值结果:SysResult对象(orderId)
     */
    @RequestMapping("/submit")
    @ResponseBody
    public SysResult submit(Order order,HttpServletRequest request) {
        
        User user = (User) request.getAttribute("JT_USER");
        Long userId = user.getId();
        order.setUserId(userId);
        String orderId = orderService.saveOrder(order);
        return SysResult.success(orderId);
    }

编辑OrderService

@Service
public class OrderServiceImpl implements DubboOrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderShippingMapper orderShippingMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    
    
    @Transactional  //事务控制
    @Override
    public String saveOrder(Order order) {
        
        //1.定义orderId  登录用户id+当前时间戳'
        String orderId = ""+order.getUserId()+System.currentTimeMillis();
        Date date = new Date();
        
        //2.实现订单表入库操作
        order.setOrderId(orderId)
             .setStatus(1)
             .setCreated(date)
             .setUpdated(date);
        orderMapper.insert(order);
        System.out.println("订单入库成功!!!!");
        
        //3.订单物流入库
        OrderShipping shipping = order.getOrderShipping();
        shipping.setOrderId(orderId)
                .setCreated(date)
                .setUpdated(date);
        orderShippingMapper.insert(shipping);
        System.out.println("订单物流入库成功!!!!");
        
        //4.入库订单商品
        List<OrderItem> ordetItems = order.getOrderItems();
        for (OrderItem orderItem : ordetItems) {
            orderItem.setOrderId(orderId)
                     .setCreated(date)
                     .setUpdated(date);
            orderItemMapper.insert(orderItem);
        }
        System.out.println("订单商品入库成功!!!!!");
        
        return orderId;
    }
}

订单查询实现
编辑OrderController

/**
     * 实现订单查询
     * url:http://www.jt.com/order/success.html?id=71588226717472
     * 页面参数分析: ${order.orderId} 根据id查询订单信息.
     * 要求实现3张表查询 order对象!!!!
     */
    @RequestMapping("/success")
    public String findOrderById(String id,Model model) {
        
        //根据id查询订单信息.
        Order order = orderService.findOrderById(id);
        model.addAttribute("order", order);
        return "success";
    }

编辑OrderService

//实现3张表数据查询.
    @Override
    public Order findOrderById(String id) {
        //想使用一个数据库链接,查询3张表数据!!!
        Order order = orderMapper.selectById(id);
        OrderShipping shipping = orderShippingMapper.selectById(id);
        QueryWrapper<OrderItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", id);
        List<OrderItem> list = orderItemMapper.selectList(queryWrapper);
        return order.setOrderShipping(shipping).setOrderItems(list);
    }

订单超时处理

引入jar包

<!--添加Quartz的支持 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

配置类介绍

@Configuration
public class OrderQuartzConfig {
    
    //定义任务详情
    @Bean
    public JobDetail orderjobDetail() {
        //指定job的名称和持久化保存任务
        return JobBuilder
                .newJob(OrderQuartz.class)  //指定一个全新的任务
                .withIdentity("orderQuartz")    //指定任务名称
                .storeDurably()
                .build();   //任务创建 封装为JobDetail对象
    }
    //定义触发器
    @Bean
    public Trigger orderTrigger() {
        /*SimpleScheduleBuilder builder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInMinutes(1)   //定义时间周期
                .repeatForever();*/
        
        //定义调度器  指定任务的执行的时间 
        CronScheduleBuilder scheduleBuilder 
            = CronScheduleBuilder.cronSchedule("0 0/1 * * * ?");
        return TriggerBuilder
                .newTrigger()
                .forJob(orderjobDetail())
                .withIdentity("orderQuartz")
                .withSchedule(scheduleBuilder).build();
    }
}

指定定时任务

定时任务每隔1分钟执行一次超时订单的处理.

//准备订单定时任务
@Component
public class OrderQuartz extends QuartzJobBean{@Autowired
    private OrderMapper orderMapper;
    
    /**
     * 业务需求:如果用户30分钟没有支付,则将订单的状态由1(未支付)改为6(交易关闭)
     * 超时判定: now-created > 30分钟
     *          created < now-30  timeout
     * 
     * Sql:update tb_order set status=6,updated=#{date} 
     *     where status=1  and created < now-30
     */
    @Override
    @Transactional
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        
        //1.实例化工具API对象   获取当前时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, -30);
        Date timeOut = calendar.getTime();
        
        Order order = new Order();
        order.setStatus(6).setUpdated(new Date());
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("status", 1)
                     .lt("created", timeOut);
        orderMapper.update(order, updateWrapper);
        System.out.println("定时任务执行成功!!!!!");
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值