zoukankan      html  css  js  c++  java
  • 迷你商城后台管理系统————stage2核心代码实现

    应用程序主函数接口

    @SpringBootApplication(scanBasePackages = {"org.linlinjava.litemall.db", "org.linlinjava.litemall.core", "org.linlinjava.litemall.admin"})

    @MapperScan("org.linlinjava.litemall.db.dao")

    @EnableTransactionManagement

    @EnableScheduling

    public class Application {

     

        public static void main(String[] args) {

            SpringApplication.run(Application.class, args);

        }

     

    }

    优惠卷管理

    /**

     * 检测优惠券过期情况

     */

    @Component

    public class CouponJob {

        private final Log logger = LogFactory.getLog(CouponJob.class);

     

        @Autowired

        private LitemallCouponService couponService;

        @Autowired

        private LitemallCouponUserService couponUserService;

     

        /**

         * 每隔一个小时检查

         * TODO

         * 注意,因为是相隔一个小时检查,因此导致优惠券真正超时时间可能比设定时间延迟1个小时

         */

        @Scheduled(fixedDelay = 60 * 60 * 1000)

        public void checkCouponExpired() {

            logger.info("系统开启任务检查优惠券是否已经过期");

     

            List<LitemallCoupon> couponList = couponService.queryExpired();

            for(LitemallCoupon coupon : couponList){

                coupon.setStatus(CouponConstant.STATUS_EXPIRED);

                couponService.updateById(coupon);

            }

     

            List<LitemallCouponUser> couponUserList = couponUserService.queryExpired();

            for(LitemallCouponUser couponUser : couponUserList){

                couponUser.setStatus(CouponUserConstant.STATUS_EXPIRED);

                couponUserService.update(couponUser);

            }

        }

     

    }

    订单管理

    /**

     * 检测订单状态

     */

    @Component

    public class OrderJob {

        private final Log logger = LogFactory.getLog(OrderJob.class);

     

        @Autowired

        private LitemallOrderGoodsService orderGoodsService;

        @Autowired

        private LitemallOrderService orderService;

        @Autowired

        private LitemallGoodsProductService productService;

     

        /**

         * 自动取消订单

         * <p>

         * 定时检查订单未付款情况,如果超时 LITEMALL_ORDER_UNPAID 分钟则自动取消订单

         * 定时时间是每次相隔半个小时。

         * <p>

         * TODO

         * 注意,因为是相隔半小时检查,因此导致订单真正超时时间是 [LITEMALL_ORDER_UNPAID, 30 + LITEMALL_ORDER_UNPAID]

         */

        @Scheduled(fixedDelay = 30 * 60 * 1000)

        @Transactional

        public void checkOrderUnpaid() {

            logger.info("系统开启任务检查订单是否已经超期自动取消订单");

     

            List<LitemallOrder> orderList = orderService.queryUnpaid(SystemConfig.getOrderUnpaid());

            for (LitemallOrder order : orderList) {

                // 设置订单已取消状态

                order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);

                order.setEndTime(LocalDateTime.now());

                if (orderService.updateWithOptimisticLocker(order) == 0) {

                    throw new RuntimeException("更新数据已失效");

                }

     

                // 商品货品数量增加

                Integer orderId = order.getId();

                List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);

                for (LitemallOrderGoods orderGoods : orderGoodsList) {

                    Integer productId = orderGoods.getProductId();

                    Short number = orderGoods.getNumber();

                    if (productService.addStock(productId, number) == 0) {

                        throw new RuntimeException("商品货品库存增加失败");

                    }

                }

                logger.info("订单 ID=" + order.getId() + " 已经超期自动取消订单");

            }

        }

     

        /**

         * 自动确认订单

         * <p>

         * 定时检查订单未确认情况,如果超时 LITEMALL_ORDER_UNCONFIRM 天则自动确认订单

         * 定时时间是每天凌晨3点。

         * <p>

         * TODO

         * 注意,因为是相隔一天检查,因此导致订单真正超时时间是 [LITEMALL_ORDER_UNCONFIRM, 1 + LITEMALL_ORDER_UNCONFIRM]

         */

        @Scheduled(cron = "0 0 3 * * ?")

        public void checkOrderUnconfirm() {

            logger.info("系统开启任务检查订单是否已经超期自动确认收货");

     

            List<LitemallOrder> orderList = orderService.queryUnconfirm(SystemConfig.getOrderUnconfirm());

            for (LitemallOrder order : orderList) {

     

                // 设置订单已取消状态

                order.setOrderStatus(OrderUtil.STATUS_AUTO_CONFIRM);

                order.setConfirmTime(LocalDateTime.now());

                if (orderService.updateWithOptimisticLocker(order) == 0) {

                    logger.info("订单 ID=" + order.getId() + " 数据已经更新,放弃自动确认收货");

                } else {

                    logger.info("订单 ID=" + order.getId() + " 已经超期自动确认收货");

                }

            }

        }

     

        /**

         * 可评价订单商品超期

         * <p>

         * 定时检查订单商品评价情况,如果确认商品超时 LITEMALL_ORDER_COMMENT 天则取消可评价状态

         * 定时时间是每天凌晨4点。

         * <p>

         * TODO

         * 注意,因为是相隔一天检查,因此导致订单真正超时时间是 [LITEMALL_ORDER_COMMENT, 1 + LITEMALL_ORDER_COMMENT]

         */

        @Scheduled(cron = "0 0 4 * * ?")

        public void checkOrderComment() {

            logger.info("系统开启任务检查订单是否已经超期未评价");

     

            LocalDateTime now = LocalDateTime.now();

            List<LitemallOrder> orderList = orderService.queryComment(SystemConfig.getOrderComment());

            for (LitemallOrder order : orderList) {

                order.setComments((short) 0);

                orderService.updateWithOptimisticLocker(order);

     

                List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());

                for (LitemallOrderGoods orderGoods : orderGoodsList) {

                    orderGoods.setComment(-1);

                    orderGoodsService.updateById(orderGoods);

                }

            }

        }

    }

    上架商品管理服务

    @Service

    public class AdminGoodsService {

        private final Log logger = LogFactory.getLog(AdminGoodsService.class);

     

        @Autowired

        private LitemallGoodsService goodsService;

        @Autowired

        private LitemallGoodsSpecificationService specificationService;

        @Autowired

        private LitemallGoodsAttributeService attributeService;

        @Autowired

        private LitemallGoodsProductService productService;

        @Autowired

        private LitemallCategoryService categoryService;

        @Autowired

        private LitemallBrandService brandService;

        @Autowired

        private LitemallCartService cartService;

        @Autowired

        private LitemallOrderGoodsService orderGoodsService;

     

        @Autowired

        private QCodeService qCodeService;

     

        public Object list(String goodsSn, String name,

                           Integer page, Integer limit, String sort, String order) {

            List<LitemallGoods> goodsList = goodsService.querySelective(goodsSn, name, page, limit, sort, order);

            return ResponseUtil.okList(goodsList);

        }

     

        private Object validate(GoodsAllinone goodsAllinone) {

            LitemallGoods goods = goodsAllinone.getGoods();

            String name = goods.getName();

            if (StringUtils.isEmpty(name)) {

                return ResponseUtil.badArgument();

            }

            String goodsSn = goods.getGoodsSn();

            if (StringUtils.isEmpty(goodsSn)) {

                return ResponseUtil.badArgument();

            }

            // 品牌商可以不设置,如果设置则需要验证品牌商存在

            Integer brandId = goods.getBrandId();

            if (brandId != null && brandId != 0) {

                if (brandService.findById(brandId) == null) {

                    return ResponseUtil.badArgumentValue();

                }

            }

            // 分类可以不设置,如果设置则需要验证分类存在

            Integer categoryId = goods.getCategoryId();

            if (categoryId != null && categoryId != 0) {

                if (categoryService.findById(categoryId) == null) {

                    return ResponseUtil.badArgumentValue();

                }

            }

     

            LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

            for (LitemallGoodsAttribute attribute : attributes) {

                String attr = attribute.getAttribute();

                if (StringUtils.isEmpty(attr)) {

                    return ResponseUtil.badArgument();

                }

                String value = attribute.getValue();

                if (StringUtils.isEmpty(value)) {

                    return ResponseUtil.badArgument();

                }

            }

     

            LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

            for (LitemallGoodsSpecification specification : specifications) {

                String spec = specification.getSpecification();

                if (StringUtils.isEmpty(spec)) {

                    return ResponseUtil.badArgument();

                }

                String value = specification.getValue();

                if (StringUtils.isEmpty(value)) {

                    return ResponseUtil.badArgument();

                }

            }

     

            LitemallGoodsProduct[] products = goodsAllinone.getProducts();

            for (LitemallGoodsProduct product : products) {

                Integer number = product.getNumber();

                if (number == null || number < 0) {

                    return ResponseUtil.badArgument();

                }

     

                BigDecimal price = product.getPrice();

                if (price == null) {

                    return ResponseUtil.badArgument();

                }

     

                String[] productSpecifications = product.getSpecifications();

                if (productSpecifications.length == 0) {

                    return ResponseUtil.badArgument();

                }

            }

     

            return null;

        }

     

        /**

         * 编辑商品

         * <p>

         * TODO

         * 目前商品修改的逻辑是

         * 1. 更新litemall_goods

         * 2. 逻辑删除litemall_goods_specificationlitemall_goods_attributelitemall_goods_product

         * 3. 添加litemall_goods_specificationlitemall_goods_attributelitemall_goods_product

         * <p>

         * 这里商品三个表的数据采用删除再添加的策略是因为

         * 商品编辑页面,支持管理员添加删除商品规格、添加删除商品属性,因此这里仅仅更新是不可能的,

         * 只能删除三个表旧的数据,然后添加新的数据。

         * 但是这里又会引入新的问题,就是存在订单商品货品ID指向了失效的商品货品表。

         * 因此这里会拒绝管理员编辑商品,如果订单或购物车中存在商品。

         * 所以这里可能需要重新设计。

         */

        @Transactional

        public Object update(GoodsAllinone goodsAllinone) {

            Object error = validate(goodsAllinone);

            if (error != null) {

                return error;

            }

     

            LitemallGoods goods = goodsAllinone.getGoods();

            LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

            LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

            LitemallGoodsProduct[] products = goodsAllinone.getProducts();

     

            Integer id = goods.getId();

     

            //将生成的分享图片地址写入数据库

            String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

            goods.setShareUrl(url);

     

            // 商品基本信息表litemall_goods

            if (goodsService.updateById(goods) == 0) {

                throw new RuntimeException("更新数据失败");

            }

     

            Integer gid = goods.getId();

            specificationService.deleteByGid(gid);

            attributeService.deleteByGid(gid);

            productService.deleteByGid(gid);

     

            // 商品规格表litemall_goods_specification

            for (LitemallGoodsSpecification specification : specifications) {

                specification.setGoodsId(goods.getId());

                specificationService.add(specification);

            }

     

            // 商品参数表litemall_goods_attribute

            for (LitemallGoodsAttribute attribute : attributes) {

                attribute.setGoodsId(goods.getId());

                attributeService.add(attribute);

            }

     

            // 商品货品表litemall_product

            for (LitemallGoodsProduct product : products) {

                product.setGoodsId(goods.getId());

                productService.add(product);

            }

     

            return ResponseUtil.ok();

        }

     

        @Transactional

        public Object delete(LitemallGoods goods) {

            Integer id = goods.getId();

            if (id == null) {

                return ResponseUtil.badArgument();

            }

     

            Integer gid = goods.getId();

            goodsService.deleteById(gid);

            specificationService.deleteByGid(gid);

            attributeService.deleteByGid(gid);

            productService.deleteByGid(gid);

            return ResponseUtil.ok();

        }

     

        @Transactional

        public Object create(GoodsAllinone goodsAllinone) {

            Object error = validate(goodsAllinone);

            if (error != null) {

                return error;

            }

     

            LitemallGoods goods = goodsAllinone.getGoods();

            LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

            LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

            LitemallGoodsProduct[] products = goodsAllinone.getProducts();

     

            String name = goods.getName();

            if (goodsService.checkExistByName(name)) {

                return ResponseUtil.fail(GOODS_NAME_EXIST, "商品名已经存在");

            }

     

            // 商品基本信息表litemall_goods

            goodsService.add(goods);

     

            //将生成的分享图片地址写入数据库

            String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

            if (!StringUtils.isEmpty(url)) {

                goods.setShareUrl(url);

                if (goodsService.updateById(goods) == 0) {

                    throw new RuntimeException("更新数据失败");

                }

            }

     

            // 商品规格表litemall_goods_specification

            for (LitemallGoodsSpecification specification : specifications) {

                specification.setGoodsId(goods.getId());

                specificationService.add(specification);

            }

     

            // 商品参数表litemall_goods_attribute

            for (LitemallGoodsAttribute attribute : attributes) {

                attribute.setGoodsId(goods.getId());

                attributeService.add(attribute);

            }

     

            // 商品货品表litemall_product

            for (LitemallGoodsProduct product : products) {

                product.setGoodsId(goods.getId());

                productService.add(product);

            }

            return ResponseUtil.ok();

        }

     

        public Object list2() {

            // http://element-cn.eleme.io/#/zh-CN/component/cascader

            // 管理员设置所属分类

            List<LitemallCategory> l1CatList = categoryService.queryL1();

            List<CatVo> categoryList = new ArrayList<>(l1CatList.size());

     

            for (LitemallCategory l1 : l1CatList) {

                CatVo l1CatVo = new CatVo();

                l1CatVo.setValue(l1.getId());

                l1CatVo.setLabel(l1.getName());

     

                List<LitemallCategory> l2CatList = categoryService.queryByPid(l1.getId());

                List<CatVo> children = new ArrayList<>(l2CatList.size());

                for (LitemallCategory l2 : l2CatList) {

                    CatVo l2CatVo = new CatVo();

                    l2CatVo.setValue(l2.getId());

                    l2CatVo.setLabel(l2.getName());

                    children.add(l2CatVo);

                }

                l1CatVo.setChildren(children);

     

                categoryList.add(l1CatVo);

            }

     

            // http://element-cn.eleme.io/#/zh-CN/component/select

            // 管理员设置所属品牌商

            List<LitemallBrand> list = brandService.all();

            List<Map<String, Object>> brandList = new ArrayList<>(l1CatList.size());

            for (LitemallBrand brand : list) {

                Map<String, Object> b = new HashMap<>(2);

                b.put("value", brand.getId());

                b.put("label", brand.getName());

                brandList.add(b);

            }

     

            Map<String, Object> data = new HashMap<>();

            data.put("categoryList", categoryList);

            data.put("brandList", brandList);

            return ResponseUtil.ok(data);

        }

     

        public Object detail(Integer id) {

            LitemallGoods goods = goodsService.findById(id);

            List<LitemallGoodsProduct> products = productService.queryByGid(id);

            List<LitemallGoodsSpecification> specifications = specificationService.queryByGid(id);

            List<LitemallGoodsAttribute> attributes = attributeService.queryByGid(id);

     

            Integer categoryId = goods.getCategoryId();

            LitemallCategory category = categoryService.findById(categoryId);

            Integer[] categoryIds = new Integer[]{};

            if (category != null) {

                Integer parentCategoryId = category.getPid();

                categoryIds = new Integer[]{parentCategoryId, categoryId};

            }

     

            Map<String, Object> data = new HashMap<>();

            data.put("goods", goods);

            data.put("specifications", specifications);

            data.put("products", products);

            data.put("attributes", attributes);

            data.put("categoryIds", categoryIds);

     

            return ResponseUtil.ok(data);

        }

     

    }

    订单管理服务

    @Service

     

    public class AdminOrderService {

        private final Log logger = LogFactory.getLog(AdminOrderService.class);

     

        @Autowired

        private LitemallOrderGoodsService orderGoodsService;

        @Autowired

        private LitemallOrderService orderService;

        @Autowired

        private LitemallGoodsProductService productService;

        @Autowired

        private LitemallUserService userService;

        @Autowired

        private LitemallCommentService commentService;

        @Autowired

        private WxPayService wxPayService;

        @Autowired

        private NotifyService notifyService;

        @Autowired

        private LogHelper logHelper;

     

        public Object list(Integer userId, String orderSn, List<Short> orderStatusArray,

                           Integer page, Integer limit, String sort, String order) {

            List<LitemallOrder> orderList = orderService.querySelective(userId, orderSn, orderStatusArray, page, limit, sort, order);

            return ResponseUtil.okList(orderList);

        }

     

        public Object detail(Integer id) {

            LitemallOrder order = orderService.findById(id);

            List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(id);

            UserVo user = userService.findUserVoById(order.getUserId());

            Map<String, Object> data = new HashMap<>();

            data.put("order", order);

            data.put("orderGoods", orderGoods);

            data.put("user", user);

     

            return ResponseUtil.ok(data);

        }

     

        /**

         * 订单退款

         * <p>

         * 1. 检测当前订单是否能够退款;

         * 2. 微信退款操作;

         * 3. 设置订单退款确认状态;

         * 4. 订单商品库存回库。

         * <p>

         * TODO

         * 虽然接入了微信退款API,但是从安全角度考虑,建议开发者删除这里微信退款代码,采用以下两步走步骤:

         * 1. 管理员登录微信官方支付平台点击退款操作进行退款

         * 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库

         *

         * @param body 订单信息,{ orderIdxxx }

         * @return 订单退款操作结果

         */

        @Transactional

        public Object refund(String body) {

            Integer orderId = JacksonUtil.parseInteger(body, "orderId");

            String refundMoney = JacksonUtil.parseString(body, "refundMoney");

            if (orderId == null) {

                return ResponseUtil.badArgument();

            }

            if (StringUtils.isEmpty(refundMoney)) {

                return ResponseUtil.badArgument();

            }

     

            LitemallOrder order = orderService.findById(orderId);

            if (order == null) {

                return ResponseUtil.badArgument();

            }

     

            if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {

                return ResponseUtil.badArgumentValue();

            }

     

            // 如果订单不是退款状态,则不能退款

            if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {

                return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");

            }

     

            // 微信退款

            WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();

            wxPayRefundRequest.setOutTradeNo(order.getOrderSn());

            wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());

            // 元转成分

            Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();

            wxPayRefundRequest.setTotalFee(totalFee);

            wxPayRefundRequest.setRefundFee(totalFee);

     

            WxPayRefundResult wxPayRefundResult = null;

            try {

                wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);

            } catch (WxPayException e) {

                e.printStackTrace();

                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");

            }

            if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {

                logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());

                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");

            }

            if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {

                logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());

                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");

            }

     

            // 设置订单取消状态

            order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);

            if (orderService.updateWithOptimisticLocker(order) == 0) {

                throw new RuntimeException("更新数据已失效");

            }

     

            // 商品货品数量增加

            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);

            for (LitemallOrderGoods orderGoods : orderGoodsList) {

                Integer productId = orderGoods.getProductId();

                Short number = orderGoods.getNumber();

                if (productService.addStock(productId, number) == 0) {

                    throw new RuntimeException("商品货品库存增加失败");

                }

            }

     

            //TODO 发送邮件和短信通知,这里采用异步发送

            // 退款成功通知用户, 例如您申请的订单退款 [ 单号:{1} ] 已成功,请耐心等待到账。

            // 注意订单号只发后6

            notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});

     

            logHelper.logOrderSucceed("退款", "订单编号 " + orderId);

            return ResponseUtil.ok();

        }

     

        /**

         * 发货

         * 1. 检测当前订单是否能够发货

         * 2. 设置订单发货状态

         *

         * @param body 订单信息,{ orderIdxxx, shipSn: xxx, shipChannel: xxx }

         * @return 订单操作结果

         * 成功则 { errno: 0, errmsg: '成功' }

         * 失败则 { errno: XXX, errmsg: XXX }

         */

        public Object ship(String body) {

            Integer orderId = JacksonUtil.parseInteger(body, "orderId");

            String shipSn = JacksonUtil.parseString(body, "shipSn");

            String shipChannel = JacksonUtil.parseString(body, "shipChannel");

            if (orderId == null || shipSn == null || shipChannel == null) {

                return ResponseUtil.badArgument();

            }

     

            LitemallOrder order = orderService.findById(orderId);

            if (order == null) {

                return ResponseUtil.badArgument();

            }

     

            // 如果订单不是已付款状态,则不能发货

            if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {

                return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");

            }

     

            order.setOrderStatus(OrderUtil.STATUS_SHIP);

            order.setShipSn(shipSn);

            order.setShipChannel(shipChannel);

            order.setShipTime(LocalDateTime.now());

            if (orderService.updateWithOptimisticLocker(order) == 0) {

                return ResponseUtil.updatedDateExpired();

            }

     

            //TODO 发送邮件和短信通知,这里采用异步发送

            // 发货会发送通知短信给用户:          *

            // "您的订单已经发货,快递公司 {1},快递单 {2} ,请注意查收"

            notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[]{shipChannel, shipSn});

     

            logHelper.logOrderSucceed("发货", "订单编号 " + orderId);

            return ResponseUtil.ok();

        }

     

     

        /**

         * 回复订单商品

         *

         * @param body 订单信息,{ orderIdxxx }

         * @return 订单操作结果

         * 成功则 { errno: 0, errmsg: '成功' }

         * 失败则 { errno: XXX, errmsg: XXX }

         */

        public Object reply(String body) {

            Integer commentId = JacksonUtil.parseInteger(body, "commentId");

            if (commentId == null || commentId == 0) {

                return ResponseUtil.badArgument();

            }

            // 目前只支持回复一次

            if (commentService.findById(commentId) != null) {

                return ResponseUtil.fail(ORDER_REPLY_EXIST, "订单商品已回复!");

            }

            String content = JacksonUtil.parseString(body, "content");

            if (StringUtils.isEmpty(content)) {

                return ResponseUtil.badArgument();

            }

            // 创建评价回复

            LitemallComment comment = new LitemallComment();

            comment.setType((byte) 2);

            comment.setValueId(commentId);

            comment.setContent(content);

            comment.setUserId(0);                 // 评价回复没有用

            comment.setStar((short) 0);           // 评价回复没有用

            comment.setHasPicture(false);        // 评价回复没有用

            comment.setPicUrls(new String[]{});  // 评价回复没有用

            commentService.save(comment);

     

            return ResponseUtil.ok();

        }

     

    }

    操作日志管理服务

    /**

     * 这里的日志类型设计成四种(当然开发者需要可以自己扩展)

     * 一般日志:用户觉得需要查看的一般操作日志,建议是默认的日志级别

     * 安全日志:用户安全相关的操作日志,例如登录、删除管理员

     * 订单日志:用户交易相关的操作日志,例如订单发货、退款

     * 其他日志:如果以上三种不合适,可以选择其他日志,建议是优先级最低的日志级别

     *

     * 当然可能很多操作是不需要记录到数据库的,例如编辑商品、编辑广告品之类。

     */

    @Component

    public class LogHelper {

        public final static Integer LOG_TYPE_GENERAL = 0;

        public final static Integer LOG_TYPE_AUTH = 1;

        public final static Integer LOG_TYPE_ORDER = 2;

        public final static Integer LOG_TYPE_OTHER = 3;

     

        @Autowired

        private LitemallLogService logService;

     

        public void logGeneralSucceed(String action){

            logAdmin(LOG_TYPE_GENERAL, action, true, "", "");

        }

     

        public void logGeneralSucceed(String action, String result){

            logAdmin(LOG_TYPE_GENERAL, action, true, result, "");

        }

     

        public void logGeneralFail(String action, String error){

            logAdmin(LOG_TYPE_GENERAL, action, false, error, "");

        }

     

        public void logAuthSucceed(String action){

            logAdmin(LOG_TYPE_AUTH, action, true, "", "");

        }

     

        public void logAuthSucceed(String action, String result){

            logAdmin(LOG_TYPE_AUTH, action, true, result, "");

        }

     

        public void logAuthFail(String action, String error){

            logAdmin(LOG_TYPE_AUTH, action, false, error, "");

        }

     

        public void logOrderSucceed(String action){

            logAdmin(LOG_TYPE_ORDER, action, true, "", "");

        }

     

        public void logOrderSucceed(String action, String result){

            logAdmin(LOG_TYPE_ORDER, action, true, result, "");

        }

     

        public void logOrderFail(String action, String error){

            logAdmin(LOG_TYPE_ORDER, action, false, error, "");

        }

     

        public void logOtherSucceed(String action){

            logAdmin(LOG_TYPE_OTHER, action, true, "", "");

        }

     

        public void logOtherSucceed(String action, String result){

            logAdmin(LOG_TYPE_OTHER, action, true, result, "");

        }

     

     

        public void logOtherFail(String action, String error){

            logAdmin(LOG_TYPE_OTHER, action, false, error, "");

        }

     

        public void logAdmin (Integer type, String action, Boolean succeed, String result, String comment){

            LitemallLog log = new LitemallLog();

     

            Subject currentUser = SecurityUtils.getSubject();

            if(currentUser != null) {

                LitemallAdmin admin = (LitemallAdmin) currentUser.getPrincipal();

                if(admin != null) {

                    log.setAdmin(admin.getUsername());

                }

                else{

                    log.setAdmin("匿名用户");

                }

            }

            else{

                log.setAdmin("匿名用户");

            }

     

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

            if(request != null) {

                log.setIp(IpUtil.getIpAddr(request));

            }

     

            log.setType(type);

            log.setAction(action);

            log.setStatus(succeed);

            log.setResult(result);

            log.setComment(comment);

            logService.add(log);

        }

     

    }

    顾客(会员)身份认证

    public class AdminAuthorizingRealm extends AuthorizingRealm {

     

        private static final Logger log = LoggerFactory.getLogger(AdminAuthorizingRealm.class);

        @Autowired

        private LitemallAdminService adminService;

        @Autowired

        private LitemallRoleService roleService;

        @Autowired

        private LitemallPermissionService permissionService;

     

        @Override

        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

            if (principals == null) {

                throw new AuthorizationException("PrincipalCollection method argument cannot be null.");

            }

     

            LitemallAdmin admin = (LitemallAdmin) getAvailablePrincipal(principals);

            Integer[] roleIds = admin.getRoleIds();

            Set<String> roles = roleService.queryByIds(roleIds);

            Set<String> permissions = permissionService.queryByRoleIds(roleIds);

            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

            info.setRoles(roles);

            info.setStringPermissions(permissions);

            return info;

        }

     

        @Override

        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

     

            UsernamePasswordToken upToken = (UsernamePasswordToken) token;

            String username = upToken.getUsername();

            String password=new String(upToken.getPassword());

     

            if (StringUtils.isEmpty(username)) {

                throw new AccountException("用户名不能为空");

            }

            if (StringUtils.isEmpty(password)) {

                throw new AccountException("密码不能为空");

            }

     

            List<LitemallAdmin> adminList = adminService.findAdmin(username);

            Assert.state(adminList.size() < 2, "同一个用户名存在两个账户");

            if (adminList.size() == 0) {

                throw new UnknownAccountException("找不到用户("+username+")的帐号信息");

            }

            LitemallAdmin admin = adminList.get(0);

     

            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

            if (!encoder.matches(password, admin.getPassword())) {

                throw new UnknownAccountException("找不到用户("+username+")的帐号信息");

            }

     

            return new SimpleAuthenticationInfo(admin,password,getName());

        }

     

    }

    广告管理控制器

     

    Ps:其他控制器与此类似,不在一一冗赘

     

    @RestController

    @RequestMapping("/admin/ad")

    @Validated

    public class AdminAdController {

        private final Log logger = LogFactory.getLog(AdminAdController.class);

     

        @Autowired

        private LitemallAdService adService;

     

        @RequiresPermissions("admin:ad:list")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="查询")

        @GetMapping("/list")

        public Object list(String name, String content,

                           @RequestParam(defaultValue = "1") Integer page,

                           @RequestParam(defaultValue = "10") Integer limit,

                           @Sort @RequestParam(defaultValue = "add_time") String sort,

                           @Order @RequestParam(defaultValue = "desc") String order) {

            List<LitemallAd> adList = adService.querySelective(name, content, page, limit, sort, order);

            return ResponseUtil.okList(adList);

        }

     

        private Object validate(LitemallAd ad) {

            String name = ad.getName();

            if (StringUtils.isEmpty(name)) {

                return ResponseUtil.badArgument();

            }

            String content = ad.getContent();

            if (StringUtils.isEmpty(content)) {

                return ResponseUtil.badArgument();

            }

            return null;

        }

     

        @RequiresPermissions("admin:ad:create")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="添加")

        @PostMapping("/create")

        public Object create(@RequestBody LitemallAd ad) {

            Object error = validate(ad);

            if (error != null) {

                return error;

            }

            adService.add(ad);

            return ResponseUtil.ok(ad);

        }

     

        @RequiresPermissions("admin:ad:read")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="详情")

        @GetMapping("/read")

        public Object read(@NotNull Integer id) {

            LitemallAd ad = adService.findById(id);

            return ResponseUtil.ok(ad);

        }

     

        @RequiresPermissions("admin:ad:update")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="编辑")

        @PostMapping("/update")

        public Object update(@RequestBody LitemallAd ad) {

            Object error = validate(ad);

            if (error != null) {

                return error;

            }

            if (adService.updateById(ad) == 0) {

                return ResponseUtil.updatedDataFailed();

            }

     

            return ResponseUtil.ok(ad);

        }

     

        @RequiresPermissions("admin:ad:delete")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="删除")

        @PostMapping("/delete")

        public Object delete(@RequestBody LitemallAd ad) {

            Integer id = ad.getId();

            if (id == null) {

                return ResponseUtil.badArgument();

            }

            adService.deleteById(id);

            return ResponseUtil.ok();

        }

     

    }

    数据库操作部分

    Ps:其他操作和对商品品牌数据库表操作类似,再次不在冗赘。

    商品品牌数据库表操作

    @Service

    publicclassLitemallBrandService {

        @Resource

        privateLitemallBrandMapperbrandMapper;

        privateColumn[] columns = newColumn[]{Column.id, Column.name, Column.desc, Column.picUrl, Column.floorPrice};

     

        publicList<LitemallBrand> query(Integerpage, Integerlimit, Stringsort, Stringorder) {

            LitemallBrandExampleexample = newLitemallBrandExample();

            example.or().andDeletedEqualTo(false);

            if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {

                example.setOrderByClause(sort + " " + order);

            }

            PageHelper.startPage(page, limit);

            returnbrandMapper.selectByExampleSelective(example, columns);

        }

     

        publicList<LitemallBrand> query(Integerpage, Integerlimit) {

            returnquery(page, limit, null, null);

        }

     

        publicLitemallBrandfindById(Integerid) {

            returnbrandMapper.selectByPrimaryKey(id);

        }

     

        publicList<LitemallBrand> querySelective(Stringid, Stringname, Integerpage, Integersize, Stringsort, Stringorder) {

            LitemallBrandExampleexample = newLitemallBrandExample();

            LitemallBrandExample.Criteriacriteria = example.createCriteria();

     

            if (!StringUtils.isEmpty(id)) {

                criteria.andIdEqualTo(Integer.valueOf(id));

            }

            if (!StringUtils.isEmpty(name)) {

                criteria.andNameLike("%" + name + "%");

            }

            criteria.andDeletedEqualTo(false);

     

            if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {

                example.setOrderByClause(sort + " " + order);

            }

     

            PageHelper.startPage(page, size);

            returnbrandMapper.selectByExample(example);

        }

     

        publicintupdateById(LitemallBrandbrand) {

            brand.setUpdateTime(LocalDateTime.now());

            returnbrandMapper.updateByPrimaryKeySelective(brand);

        }

     

        publicvoiddeleteById(Integerid) {

            brandMapper.logicalDeleteByPrimaryKey(id);

        }

     

        publicvoidadd(LitemallBrandbrand) {

            brand.setAddTime(LocalDateTime.now());

            brand.setUpdateTime(LocalDateTime.now());

            brandMapper.insertSelective(brand);

        }

     

        publicList<LitemallBrand> all() {

            LitemallBrandExampleexample = newLitemallBrandExample();

            example.or().andDeletedEqualTo(false);

            returnbrandMapper.selectByExample(example);

        }

    }

    核心操作部分

    Ps:其他核心操作同存储(商品信息、图片对象等)操作、物流查询服务类似,不在冗赘。

    存储操作

    /**

     * 对象存储接口

     */

    publicinterfaceStorage {

     

        /**

         * 存储一个文件对象

         *

         * @paraminputStream   文件输入流

         * @paramcontentLength文件长度

         * @paramcontentType   文件类型

         * @paramkeyName       文件名

         */

        voidstore(InputStreaminputStream, longcontentLength, StringcontentType, StringkeyName);

     

        Stream<Path> loadAll();

     

        Pathload(StringkeyName);

     

        ResourceloadAsResource(StringkeyName);

     

        voiddelete(StringkeyName);

     

        StringgenerateUrl(StringkeyName);

    }

    物流查询服务

    /**

     * 物流查询服务

     *

     * 快递鸟即时查询API http://www.kdniao.com/api-track

     */

    public class ExpressService {

        //请求url

        private String ReqURL = "http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";

     

        private ExpressProperties properties;

     

        public ExpressProperties getProperties() {

            return properties;

        }

     

        public void setProperties(ExpressProperties properties) {

            this.properties = properties;

        }

     

        /**

         * 获取物流供应商名

         *

         * @param vendorCode

         * @return

         */

        public String getVendorName(String vendorCode) {

            for (Map<String, String> item : properties.getVendors()) {

                if (item.get("code").equals(vendorCode))

                    return item.get("name");

            }

            return null;

        }

     

        /**

         * 获取物流信息

         *

         * @param expCode

         * @param expNo

         * @return

         */

        public ExpressInfo getExpressInfo(String expCode, String expNo) {

            try {

                String result = getOrderTracesByJson(expCode, expNo);

                ObjectMapper objMap = new ObjectMapper();

                ExpressInfo ei = objMap.readValue(result, ExpressInfo.class);

                ei.setShipperName(getVendorName(expCode));

                return ei;

            } catch (Exception e) {

                e.printStackTrace();

            }

     

            return null;

        }

     

        /**

         * Json方式 查询订单物流轨迹

         *

         * @throws Exception

         */

        private String getOrderTracesByJson(String expCode, String expNo) throws Exception {

            if (!properties.isEnable()) {

                return null;

            }

     

            String requestData = "{'OrderCode':'','ShipperCode':'" + expCode + "','LogisticCode':'" + expNo + "'}";

     

            Map<String, String> params = new HashMap<String, String>();

            params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));

            params.put("EBusinessID", properties.getAppId());

            params.put("RequestType", "1002");

            String dataSign = encrypt(requestData, properties.getAppKey(), "UTF-8");

            params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));

            params.put("DataType", "2");

     

            String result = HttpUtil.sendPost(ReqURL, params);

     

            //根据公司业务处理返回的信息......

     

            return result;

        }

     

        /**

         * MD5加密

         *

         * @param str     内容

         * @param charset 编码方式

         * @throws Exception

         */

        private String MD5(String str, String charset) throws Exception {

            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(str.getBytes(charset));

            byte[] result = md.digest();

            StringBuffer sb = new StringBuffer(32);

            for (int i = 0; i < result.length; i++) {

                int val = result[i] & 0xff;

                if (val <= 0xf) {

                    sb.append("0");

                }

                sb.append(Integer.toHexString(val));

            }

            return sb.toString().toLowerCase();

        }

     

        /**

         * Sign签名生成

         *

         * @param content  内容

         * @param keyValue Appkey

         * @param charset  编码方式

         * @return DataSign签名

         */

        private String encrypt(String content, String keyValue, String charset) {

            if (keyValue != null) {

                content = content + keyValue;

            }

            byte[] src = new byte[0];

            try {

                src = MD5(content, charset).getBytes(charset);

                return Base64Utils.encodeToString(src);

            } catch (Exception e) {

                e.printStackTrace();

            }

     

            return null;

        } 

    }

    迷你商城后端管理

         应用程序主函数接口

    @SpringBootApplication(scanBasePackages = {"org.linlinjava.litemall.db", "org.linlinjava.litemall.core", "org.linlinjava.litemall.admin"})

    @MapperScan("org.linlinjava.litemall.db.dao")

    @EnableTransactionManagement

    @EnableScheduling

    public class Application {

     

        public static void main(String[] args) {

            SpringApplication.run(Application.class, args);

        }

     

    }

         优惠卷管理

    /**

     * 检测优惠券过期情况

     */

    @Component

    public class CouponJob {

        private final Log logger = LogFactory.getLog(CouponJob.class);

     

        @Autowired

        private LitemallCouponService couponService;

        @Autowired

        private LitemallCouponUserService couponUserService;

     

        /**

         * 每隔一个小时检查

         * TODO

         * 注意,因为是相隔一个小时检查,因此导致优惠券真正超时时间可能比设定时间延迟1个小时

         */

        @Scheduled(fixedDelay = 60 * 60 * 1000)

        public void checkCouponExpired() {

            logger.info("系统开启任务检查优惠券是否已经过期");

     

            List<LitemallCoupon> couponList = couponService.queryExpired();

            for(LitemallCoupon coupon : couponList){

                coupon.setStatus(CouponConstant.STATUS_EXPIRED);

                couponService.updateById(coupon);

            }

     

            List<LitemallCouponUser> couponUserList = couponUserService.queryExpired();

            for(LitemallCouponUser couponUser : couponUserList){

                couponUser.setStatus(CouponUserConstant.STATUS_EXPIRED);

                couponUserService.update(couponUser);

            }

        }

     

    }

    订单管理

    /**

     * 检测订单状态

     */

    @Component

    public class OrderJob {

        private final Log logger = LogFactory.getLog(OrderJob.class);

     

        @Autowired

        private LitemallOrderGoodsService orderGoodsService;

        @Autowired

        private LitemallOrderService orderService;

        @Autowired

        private LitemallGoodsProductService productService;

     

        /**

         * 自动取消订单

         * <p>

         * 定时检查订单未付款情况,如果超时 LITEMALL_ORDER_UNPAID 分钟则自动取消订单

         * 定时时间是每次相隔半个小时。

         * <p>

         * TODO

         * 注意,因为是相隔半小时检查,因此导致订单真正超时时间是 [LITEMALL_ORDER_UNPAID, 30 + LITEMALL_ORDER_UNPAID]

         */

        @Scheduled(fixedDelay = 30 * 60 * 1000)

        @Transactional

        public void checkOrderUnpaid() {

            logger.info("系统开启任务检查订单是否已经超期自动取消订单");

     

            List<LitemallOrder> orderList = orderService.queryUnpaid(SystemConfig.getOrderUnpaid());

            for (LitemallOrder order : orderList) {

                // 设置订单已取消状态

                order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);

                order.setEndTime(LocalDateTime.now());

                if (orderService.updateWithOptimisticLocker(order) == 0) {

                    throw new RuntimeException("更新数据已失效");

                }

     

                // 商品货品数量增加

                Integer orderId = order.getId();

                List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);

                for (LitemallOrderGoods orderGoods : orderGoodsList) {

                    Integer productId = orderGoods.getProductId();

                    Short number = orderGoods.getNumber();

                    if (productService.addStock(productId, number) == 0) {

                        throw new RuntimeException("商品货品库存增加失败");

                    }

                }

                logger.info("订单 ID=" + order.getId() + " 已经超期自动取消订单");

            }

        }

     

        /**

         * 自动确认订单

         * <p>

         * 定时检查订单未确认情况,如果超时 LITEMALL_ORDER_UNCONFIRM 天则自动确认订单

         * 定时时间是每天凌晨3点。

         * <p>

         * TODO

         * 注意,因为是相隔一天检查,因此导致订单真正超时时间是 [LITEMALL_ORDER_UNCONFIRM, 1 + LITEMALL_ORDER_UNCONFIRM]

         */

        @Scheduled(cron = "0 0 3 * * ?")

        public void checkOrderUnconfirm() {

            logger.info("系统开启任务检查订单是否已经超期自动确认收货");

     

            List<LitemallOrder> orderList = orderService.queryUnconfirm(SystemConfig.getOrderUnconfirm());

            for (LitemallOrder order : orderList) {

     

                // 设置订单已取消状态

                order.setOrderStatus(OrderUtil.STATUS_AUTO_CONFIRM);

                order.setConfirmTime(LocalDateTime.now());

                if (orderService.updateWithOptimisticLocker(order) == 0) {

                    logger.info("订单 ID=" + order.getId() + " 数据已经更新,放弃自动确认收货");

                } else {

                    logger.info("订单 ID=" + order.getId() + " 已经超期自动确认收货");

                }

            }

        }

     

        /**

         * 可评价订单商品超期

         * <p>

         * 定时检查订单商品评价情况,如果确认商品超时 LITEMALL_ORDER_COMMENT 天则取消可评价状态

         * 定时时间是每天凌晨4点。

         * <p>

         * TODO

         * 注意,因为是相隔一天检查,因此导致订单真正超时时间是 [LITEMALL_ORDER_COMMENT, 1 + LITEMALL_ORDER_COMMENT]

         */

        @Scheduled(cron = "0 0 4 * * ?")

        public void checkOrderComment() {

            logger.info("系统开启任务检查订单是否已经超期未评价");

     

            LocalDateTime now = LocalDateTime.now();

            List<LitemallOrder> orderList = orderService.queryComment(SystemConfig.getOrderComment());

            for (LitemallOrder order : orderList) {

                order.setComments((short) 0);

                orderService.updateWithOptimisticLocker(order);

     

                List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());

                for (LitemallOrderGoods orderGoods : orderGoodsList) {

                    orderGoods.setComment(-1);

                    orderGoodsService.updateById(orderGoods);

                }

            }

        }

    }

    上架商品管理服务

    @Service

    public class AdminGoodsService {

        private final Log logger = LogFactory.getLog(AdminGoodsService.class);

     

        @Autowired

        private LitemallGoodsService goodsService;

        @Autowired

        private LitemallGoodsSpecificationService specificationService;

        @Autowired

        private LitemallGoodsAttributeService attributeService;

        @Autowired

        private LitemallGoodsProductService productService;

        @Autowired

        private LitemallCategoryService categoryService;

        @Autowired

        private LitemallBrandService brandService;

        @Autowired

        private LitemallCartService cartService;

        @Autowired

        private LitemallOrderGoodsService orderGoodsService;

     

        @Autowired

        private QCodeService qCodeService;

     

        public Object list(String goodsSn, String name,

                           Integer page, Integer limit, String sort, String order) {

            List<LitemallGoods> goodsList = goodsService.querySelective(goodsSn, name, page, limit, sort, order);

            return ResponseUtil.okList(goodsList);

        }

     

        private Object validate(GoodsAllinone goodsAllinone) {

            LitemallGoods goods = goodsAllinone.getGoods();

            String name = goods.getName();

            if (StringUtils.isEmpty(name)) {

                return ResponseUtil.badArgument();

            }

            String goodsSn = goods.getGoodsSn();

            if (StringUtils.isEmpty(goodsSn)) {

                return ResponseUtil.badArgument();

            }

            // 品牌商可以不设置,如果设置则需要验证品牌商存在

            Integer brandId = goods.getBrandId();

            if (brandId != null && brandId != 0) {

                if (brandService.findById(brandId) == null) {

                    return ResponseUtil.badArgumentValue();

                }

            }

            // 分类可以不设置,如果设置则需要验证分类存在

            Integer categoryId = goods.getCategoryId();

            if (categoryId != null && categoryId != 0) {

                if (categoryService.findById(categoryId) == null) {

                    return ResponseUtil.badArgumentValue();

                }

            }

     

            LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

            for (LitemallGoodsAttribute attribute : attributes) {

                String attr = attribute.getAttribute();

                if (StringUtils.isEmpty(attr)) {

                    return ResponseUtil.badArgument();

                }

                String value = attribute.getValue();

                if (StringUtils.isEmpty(value)) {

                    return ResponseUtil.badArgument();

                }

            }

     

            LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

            for (LitemallGoodsSpecification specification : specifications) {

                String spec = specification.getSpecification();

                if (StringUtils.isEmpty(spec)) {

                    return ResponseUtil.badArgument();

                }

                String value = specification.getValue();

                if (StringUtils.isEmpty(value)) {

                    return ResponseUtil.badArgument();

                }

            }

     

            LitemallGoodsProduct[] products = goodsAllinone.getProducts();

            for (LitemallGoodsProduct product : products) {

                Integer number = product.getNumber();

                if (number == null || number < 0) {

                    return ResponseUtil.badArgument();

                }

     

                BigDecimal price = product.getPrice();

                if (price == null) {

                    return ResponseUtil.badArgument();

                }

     

                String[] productSpecifications = product.getSpecifications();

                if (productSpecifications.length == 0) {

                    return ResponseUtil.badArgument();

                }

            }

     

            return null;

        }

     

        /**

         * 编辑商品

         * <p>

         * TODO

         * 目前商品修改的逻辑是

         * 1. 更新litemall_goods

         * 2. 逻辑删除litemall_goods_specificationlitemall_goods_attributelitemall_goods_product

         * 3. 添加litemall_goods_specificationlitemall_goods_attributelitemall_goods_product

         * <p>

         * 这里商品三个表的数据采用删除再添加的策略是因为

         * 商品编辑页面,支持管理员添加删除商品规格、添加删除商品属性,因此这里仅仅更新是不可能的,

         * 只能删除三个表旧的数据,然后添加新的数据。

         * 但是这里又会引入新的问题,就是存在订单商品货品ID指向了失效的商品货品表。

         * 因此这里会拒绝管理员编辑商品,如果订单或购物车中存在商品。

         * 所以这里可能需要重新设计。

         */

        @Transactional

        public Object update(GoodsAllinone goodsAllinone) {

            Object error = validate(goodsAllinone);

            if (error != null) {

                return error;

            }

     

            LitemallGoods goods = goodsAllinone.getGoods();

            LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

            LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

            LitemallGoodsProduct[] products = goodsAllinone.getProducts();

     

            Integer id = goods.getId();

     

            //将生成的分享图片地址写入数据库

            String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

            goods.setShareUrl(url);

     

            // 商品基本信息表litemall_goods

            if (goodsService.updateById(goods) == 0) {

                throw new RuntimeException("更新数据失败");

            }

     

            Integer gid = goods.getId();

            specificationService.deleteByGid(gid);

            attributeService.deleteByGid(gid);

            productService.deleteByGid(gid);

     

            // 商品规格表litemall_goods_specification

            for (LitemallGoodsSpecification specification : specifications) {

                specification.setGoodsId(goods.getId());

                specificationService.add(specification);

            }

     

            // 商品参数表litemall_goods_attribute

            for (LitemallGoodsAttribute attribute : attributes) {

                attribute.setGoodsId(goods.getId());

                attributeService.add(attribute);

            }

     

            // 商品货品表litemall_product

            for (LitemallGoodsProduct product : products) {

                product.setGoodsId(goods.getId());

                productService.add(product);

            }

     

            return ResponseUtil.ok();

        }

     

        @Transactional

        public Object delete(LitemallGoods goods) {

            Integer id = goods.getId();

            if (id == null) {

                return ResponseUtil.badArgument();

            }

     

            Integer gid = goods.getId();

            goodsService.deleteById(gid);

            specificationService.deleteByGid(gid);

            attributeService.deleteByGid(gid);

            productService.deleteByGid(gid);

            return ResponseUtil.ok();

        }

     

        @Transactional

        public Object create(GoodsAllinone goodsAllinone) {

            Object error = validate(goodsAllinone);

            if (error != null) {

                return error;

            }

     

            LitemallGoods goods = goodsAllinone.getGoods();

            LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

            LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

            LitemallGoodsProduct[] products = goodsAllinone.getProducts();

     

            String name = goods.getName();

            if (goodsService.checkExistByName(name)) {

                return ResponseUtil.fail(GOODS_NAME_EXIST, "商品名已经存在");

            }

     

            // 商品基本信息表litemall_goods

            goodsService.add(goods);

     

            //将生成的分享图片地址写入数据库

            String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

            if (!StringUtils.isEmpty(url)) {

                goods.setShareUrl(url);

                if (goodsService.updateById(goods) == 0) {

                    throw new RuntimeException("更新数据失败");

                }

            }

     

            // 商品规格表litemall_goods_specification

            for (LitemallGoodsSpecification specification : specifications) {

                specification.setGoodsId(goods.getId());

                specificationService.add(specification);

            }

     

            // 商品参数表litemall_goods_attribute

            for (LitemallGoodsAttribute attribute : attributes) {

                attribute.setGoodsId(goods.getId());

                attributeService.add(attribute);

            }

     

            // 商品货品表litemall_product

            for (LitemallGoodsProduct product : products) {

                product.setGoodsId(goods.getId());

                productService.add(product);

            }

            return ResponseUtil.ok();

        }

     

        public Object list2() {

            // http://element-cn.eleme.io/#/zh-CN/component/cascader

            // 管理员设置所属分类

            List<LitemallCategory> l1CatList = categoryService.queryL1();

            List<CatVo> categoryList = new ArrayList<>(l1CatList.size());

     

            for (LitemallCategory l1 : l1CatList) {

                CatVo l1CatVo = new CatVo();

                l1CatVo.setValue(l1.getId());

                l1CatVo.setLabel(l1.getName());

     

                List<LitemallCategory> l2CatList = categoryService.queryByPid(l1.getId());

                List<CatVo> children = new ArrayList<>(l2CatList.size());

                for (LitemallCategory l2 : l2CatList) {

                    CatVo l2CatVo = new CatVo();

                    l2CatVo.setValue(l2.getId());

                    l2CatVo.setLabel(l2.getName());

                    children.add(l2CatVo);

                }

                l1CatVo.setChildren(children);

     

                categoryList.add(l1CatVo);

            }

     

            // http://element-cn.eleme.io/#/zh-CN/component/select

            // 管理员设置所属品牌商

            List<LitemallBrand> list = brandService.all();

            List<Map<String, Object>> brandList = new ArrayList<>(l1CatList.size());

            for (LitemallBrand brand : list) {

                Map<String, Object> b = new HashMap<>(2);

                b.put("value", brand.getId());

                b.put("label", brand.getName());

                brandList.add(b);

            }

     

            Map<String, Object> data = new HashMap<>();

            data.put("categoryList", categoryList);

            data.put("brandList", brandList);

            return ResponseUtil.ok(data);

        }

     

        public Object detail(Integer id) {

            LitemallGoods goods = goodsService.findById(id);

            List<LitemallGoodsProduct> products = productService.queryByGid(id);

            List<LitemallGoodsSpecification> specifications = specificationService.queryByGid(id);

            List<LitemallGoodsAttribute> attributes = attributeService.queryByGid(id);

     

            Integer categoryId = goods.getCategoryId();

            LitemallCategory category = categoryService.findById(categoryId);

            Integer[] categoryIds = new Integer[]{};

            if (category != null) {

                Integer parentCategoryId = category.getPid();

                categoryIds = new Integer[]{parentCategoryId, categoryId};

            }

     

            Map<String, Object> data = new HashMap<>();

            data.put("goods", goods);

            data.put("specifications", specifications);

            data.put("products", products);

            data.put("attributes", attributes);

            data.put("categoryIds", categoryIds);

     

            return ResponseUtil.ok(data);

        }

     

    }

    订单管理服务

    @Service

     

    public class AdminOrderService {

        private final Log logger = LogFactory.getLog(AdminOrderService.class);

     

        @Autowired

        private LitemallOrderGoodsService orderGoodsService;

        @Autowired

        private LitemallOrderService orderService;

        @Autowired

        private LitemallGoodsProductService productService;

        @Autowired

        private LitemallUserService userService;

        @Autowired

        private LitemallCommentService commentService;

        @Autowired

        private WxPayService wxPayService;

        @Autowired

        private NotifyService notifyService;

        @Autowired

        private LogHelper logHelper;

     

        public Object list(Integer userId, String orderSn, List<Short> orderStatusArray,

                           Integer page, Integer limit, String sort, String order) {

            List<LitemallOrder> orderList = orderService.querySelective(userId, orderSn, orderStatusArray, page, limit, sort, order);

            return ResponseUtil.okList(orderList);

        }

     

        public Object detail(Integer id) {

            LitemallOrder order = orderService.findById(id);

            List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(id);

            UserVo user = userService.findUserVoById(order.getUserId());

            Map<String, Object> data = new HashMap<>();

            data.put("order", order);

            data.put("orderGoods", orderGoods);

            data.put("user", user);

     

            return ResponseUtil.ok(data);

        }

     

        /**

         * 订单退款

         * <p>

         * 1. 检测当前订单是否能够退款;

         * 2. 微信退款操作;

         * 3. 设置订单退款确认状态;

         * 4. 订单商品库存回库。

         * <p>

         * TODO

         * 虽然接入了微信退款API,但是从安全角度考虑,建议开发者删除这里微信退款代码,采用以下两步走步骤:

         * 1. 管理员登录微信官方支付平台点击退款操作进行退款

         * 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库

         *

         * @param body 订单信息,{ orderIdxxx }

         * @return 订单退款操作结果

         */

        @Transactional

        public Object refund(String body) {

            Integer orderId = JacksonUtil.parseInteger(body, "orderId");

            String refundMoney = JacksonUtil.parseString(body, "refundMoney");

            if (orderId == null) {

                return ResponseUtil.badArgument();

            }

            if (StringUtils.isEmpty(refundMoney)) {

                return ResponseUtil.badArgument();

            }

     

            LitemallOrder order = orderService.findById(orderId);

            if (order == null) {

                return ResponseUtil.badArgument();

            }

     

            if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {

                return ResponseUtil.badArgumentValue();

            }

     

            // 如果订单不是退款状态,则不能退款

            if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {

                return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");

            }

     

            // 微信退款

            WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();

            wxPayRefundRequest.setOutTradeNo(order.getOrderSn());

            wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());

            // 元转成分

            Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();

            wxPayRefundRequest.setTotalFee(totalFee);

            wxPayRefundRequest.setRefundFee(totalFee);

     

            WxPayRefundResult wxPayRefundResult = null;

            try {

                wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);

            } catch (WxPayException e) {

                e.printStackTrace();

                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");

            }

            if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {

                logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());

                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");

            }

            if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {

                logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());

                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");

            }

     

            // 设置订单取消状态

            order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);

            if (orderService.updateWithOptimisticLocker(order) == 0) {

                throw new RuntimeException("更新数据已失效");

            }

     

            // 商品货品数量增加

            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);

            for (LitemallOrderGoods orderGoods : orderGoodsList) {

                Integer productId = orderGoods.getProductId();

                Short number = orderGoods.getNumber();

                if (productService.addStock(productId, number) == 0) {

                    throw new RuntimeException("商品货品库存增加失败");

                }

            }

     

            //TODO 发送邮件和短信通知,这里采用异步发送

            // 退款成功通知用户, 例如您申请的订单退款 [ 单号:{1} ] 已成功,请耐心等待到账。

            // 注意订单号只发后6

            notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});

     

            logHelper.logOrderSucceed("退款", "订单编号 " + orderId);

            return ResponseUtil.ok();

        }

     

        /**

         * 发货

         * 1. 检测当前订单是否能够发货

         * 2. 设置订单发货状态

         *

         * @param body 订单信息,{ orderIdxxx, shipSn: xxx, shipChannel: xxx }

         * @return 订单操作结果

         * 成功则 { errno: 0, errmsg: '成功' }

         * 失败则 { errno: XXX, errmsg: XXX }

         */

        public Object ship(String body) {

            Integer orderId = JacksonUtil.parseInteger(body, "orderId");

            String shipSn = JacksonUtil.parseString(body, "shipSn");

            String shipChannel = JacksonUtil.parseString(body, "shipChannel");

            if (orderId == null || shipSn == null || shipChannel == null) {

                return ResponseUtil.badArgument();

            }

     

            LitemallOrder order = orderService.findById(orderId);

            if (order == null) {

                return ResponseUtil.badArgument();

            }

     

            // 如果订单不是已付款状态,则不能发货

            if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {

                return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");

            }

     

            order.setOrderStatus(OrderUtil.STATUS_SHIP);

            order.setShipSn(shipSn);

            order.setShipChannel(shipChannel);

            order.setShipTime(LocalDateTime.now());

            if (orderService.updateWithOptimisticLocker(order) == 0) {

                return ResponseUtil.updatedDateExpired();

            }

     

            //TODO 发送邮件和短信通知,这里采用异步发送

            // 发货会发送通知短信给用户:          *

            // "您的订单已经发货,快递公司 {1},快递单 {2} ,请注意查收"

            notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[]{shipChannel, shipSn});

     

            logHelper.logOrderSucceed("发货", "订单编号 " + orderId);

            return ResponseUtil.ok();

        }

     

     

        /**

         * 回复订单商品

         *

         * @param body 订单信息,{ orderIdxxx }

         * @return 订单操作结果

         * 成功则 { errno: 0, errmsg: '成功' }

         * 失败则 { errno: XXX, errmsg: XXX }

         */

        public Object reply(String body) {

            Integer commentId = JacksonUtil.parseInteger(body, "commentId");

            if (commentId == null || commentId == 0) {

                return ResponseUtil.badArgument();

            }

            // 目前只支持回复一次

            if (commentService.findById(commentId) != null) {

                return ResponseUtil.fail(ORDER_REPLY_EXIST, "订单商品已回复!");

            }

            String content = JacksonUtil.parseString(body, "content");

            if (StringUtils.isEmpty(content)) {

                return ResponseUtil.badArgument();

            }

            // 创建评价回复

            LitemallComment comment = new LitemallComment();

            comment.setType((byte) 2);

            comment.setValueId(commentId);

            comment.setContent(content);

            comment.setUserId(0);                 // 评价回复没有用

            comment.setStar((short) 0);           // 评价回复没有用

            comment.setHasPicture(false);        // 评价回复没有用

            comment.setPicUrls(new String[]{});  // 评价回复没有用

            commentService.save(comment);

     

            return ResponseUtil.ok();

        }

     

    }

    操作日志管理服务

    /**

     * 这里的日志类型设计成四种(当然开发者需要可以自己扩展)

     * 一般日志:用户觉得需要查看的一般操作日志,建议是默认的日志级别

     * 安全日志:用户安全相关的操作日志,例如登录、删除管理员

     * 订单日志:用户交易相关的操作日志,例如订单发货、退款

     * 其他日志:如果以上三种不合适,可以选择其他日志,建议是优先级最低的日志级别

     *

     * 当然可能很多操作是不需要记录到数据库的,例如编辑商品、编辑广告品之类。

     */

    @Component

    public class LogHelper {

        public final static Integer LOG_TYPE_GENERAL = 0;

        public final static Integer LOG_TYPE_AUTH = 1;

        public final static Integer LOG_TYPE_ORDER = 2;

        public final static Integer LOG_TYPE_OTHER = 3;

     

        @Autowired

        private LitemallLogService logService;

     

        public void logGeneralSucceed(String action){

            logAdmin(LOG_TYPE_GENERAL, action, true, "", "");

        }

     

        public void logGeneralSucceed(String action, String result){

            logAdmin(LOG_TYPE_GENERAL, action, true, result, "");

        }

     

        public void logGeneralFail(String action, String error){

            logAdmin(LOG_TYPE_GENERAL, action, false, error, "");

        }

     

        public void logAuthSucceed(String action){

            logAdmin(LOG_TYPE_AUTH, action, true, "", "");

        }

     

        public void logAuthSucceed(String action, String result){

            logAdmin(LOG_TYPE_AUTH, action, true, result, "");

        }

     

        public void logAuthFail(String action, String error){

            logAdmin(LOG_TYPE_AUTH, action, false, error, "");

        }

     

        public void logOrderSucceed(String action){

            logAdmin(LOG_TYPE_ORDER, action, true, "", "");

        }

     

        public void logOrderSucceed(String action, String result){

            logAdmin(LOG_TYPE_ORDER, action, true, result, "");

        }

     

        public void logOrderFail(String action, String error){

            logAdmin(LOG_TYPE_ORDER, action, false, error, "");

        }

     

        public void logOtherSucceed(String action){

            logAdmin(LOG_TYPE_OTHER, action, true, "", "");

        }

     

        public void logOtherSucceed(String action, String result){

            logAdmin(LOG_TYPE_OTHER, action, true, result, "");

        }

     

     

        public void logOtherFail(String action, String error){

            logAdmin(LOG_TYPE_OTHER, action, false, error, "");

        }

     

        public void logAdmin (Integer type, String action, Boolean succeed, String result, String comment){

            LitemallLog log = new LitemallLog();

     

            Subject currentUser = SecurityUtils.getSubject();

            if(currentUser != null) {

                LitemallAdmin admin = (LitemallAdmin) currentUser.getPrincipal();

                if(admin != null) {

                    log.setAdmin(admin.getUsername());

                }

                else{

                    log.setAdmin("匿名用户");

                }

            }

            else{

                log.setAdmin("匿名用户");

            }

     

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

            if(request != null) {

                log.setIp(IpUtil.getIpAddr(request));

            }

     

            log.setType(type);

            log.setAction(action);

            log.setStatus(succeed);

            log.setResult(result);

            log.setComment(comment);

            logService.add(log);

        }

     

    }

         顾客(会员)身份认证

    public class AdminAuthorizingRealm extends AuthorizingRealm {

     

        private static final Logger log = LoggerFactory.getLogger(AdminAuthorizingRealm.class);

        @Autowired

        private LitemallAdminService adminService;

        @Autowired

        private LitemallRoleService roleService;

        @Autowired

        private LitemallPermissionService permissionService;

     

        @Override

        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

            if (principals == null) {

                throw new AuthorizationException("PrincipalCollection method argument cannot be null.");

            }

     

            LitemallAdmin admin = (LitemallAdmin) getAvailablePrincipal(principals);

            Integer[] roleIds = admin.getRoleIds();

            Set<String> roles = roleService.queryByIds(roleIds);

            Set<String> permissions = permissionService.queryByRoleIds(roleIds);

            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

            info.setRoles(roles);

            info.setStringPermissions(permissions);

            return info;

        }

     

        @Override

        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

     

            UsernamePasswordToken upToken = (UsernamePasswordToken) token;

            String username = upToken.getUsername();

            String password=new String(upToken.getPassword());

     

            if (StringUtils.isEmpty(username)) {

                throw new AccountException("用户名不能为空");

            }

            if (StringUtils.isEmpty(password)) {

                throw new AccountException("密码不能为空");

            }

     

            List<LitemallAdmin> adminList = adminService.findAdmin(username);

            Assert.state(adminList.size() < 2, "同一个用户名存在两个账户");

            if (adminList.size() == 0) {

                throw new UnknownAccountException("找不到用户("+username+")的帐号信息");

            }

            LitemallAdmin admin = adminList.get(0);

     

            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

            if (!encoder.matches(password, admin.getPassword())) {

                throw new UnknownAccountException("找不到用户("+username+")的帐号信息");

            }

     

            return new SimpleAuthenticationInfo(admin,password,getName());

        }

     

    }

    广告管理控制器

     

    Ps:其他控制器与此类似,不在一一冗赘

     

    @RestController

    @RequestMapping("/admin/ad")

    @Validated

    public class AdminAdController {

        private final Log logger = LogFactory.getLog(AdminAdController.class);

     

        @Autowired

        private LitemallAdService adService;

     

        @RequiresPermissions("admin:ad:list")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="查询")

        @GetMapping("/list")

        public Object list(String name, String content,

                           @RequestParam(defaultValue = "1") Integer page,

                           @RequestParam(defaultValue = "10") Integer limit,

                           @Sort @RequestParam(defaultValue = "add_time") String sort,

                           @Order @RequestParam(defaultValue = "desc") String order) {

            List<LitemallAd> adList = adService.querySelective(name, content, page, limit, sort, order);

            return ResponseUtil.okList(adList);

        }

     

        private Object validate(LitemallAd ad) {

            String name = ad.getName();

            if (StringUtils.isEmpty(name)) {

                return ResponseUtil.badArgument();

            }

            String content = ad.getContent();

            if (StringUtils.isEmpty(content)) {

                return ResponseUtil.badArgument();

            }

            return null;

        }

     

        @RequiresPermissions("admin:ad:create")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="添加")

        @PostMapping("/create")

        public Object create(@RequestBody LitemallAd ad) {

            Object error = validate(ad);

            if (error != null) {

                return error;

            }

            adService.add(ad);

            return ResponseUtil.ok(ad);

        }

     

        @RequiresPermissions("admin:ad:read")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="详情")

        @GetMapping("/read")

        public Object read(@NotNull Integer id) {

            LitemallAd ad = adService.findById(id);

            return ResponseUtil.ok(ad);

        }

     

        @RequiresPermissions("admin:ad:update")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="编辑")

        @PostMapping("/update")

        public Object update(@RequestBody LitemallAd ad) {

            Object error = validate(ad);

            if (error != null) {

                return error;

            }

            if (adService.updateById(ad) == 0) {

                return ResponseUtil.updatedDataFailed();

            }

     

            return ResponseUtil.ok(ad);

        }

     

        @RequiresPermissions("admin:ad:delete")

        @RequiresPermissionsDesc(menu={"推广管理" , "广告管理"}, button="删除")

        @PostMapping("/delete")

        public Object delete(@RequestBody LitemallAd ad) {

            Integer id = ad.getId();

            if (id == null) {

                return ResponseUtil.badArgument();

            }

            adService.deleteById(id);

            return ResponseUtil.ok();

        }

     

    }

         数据库操作部分

    Ps:其他操作和对商品品牌数据库表操作类似,再次不在冗赘。

    商品品牌数据库表操作

    @Service

    publicclassLitemallBrandService {

        @Resource

        privateLitemallBrandMapperbrandMapper;

        privateColumn[] columns = newColumn[]{Column.id, Column.name, Column.desc, Column.picUrl, Column.floorPrice};

     

        publicList<LitemallBrand> query(Integerpage, Integerlimit, Stringsort, Stringorder) {

            LitemallBrandExampleexample = newLitemallBrandExample();

            example.or().andDeletedEqualTo(false);

            if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {

                example.setOrderByClause(sort + " " + order);

            }

            PageHelper.startPage(page, limit);

            returnbrandMapper.selectByExampleSelective(example, columns);

        }

     

        publicList<LitemallBrand> query(Integerpage, Integerlimit) {

            returnquery(page, limit, null, null);

        }

     

        publicLitemallBrandfindById(Integerid) {

            returnbrandMapper.selectByPrimaryKey(id);

        }

     

        publicList<LitemallBrand> querySelective(Stringid, Stringname, Integerpage, Integersize, Stringsort, Stringorder) {

            LitemallBrandExampleexample = newLitemallBrandExample();

            LitemallBrandExample.Criteriacriteria = example.createCriteria();

     

            if (!StringUtils.isEmpty(id)) {

                criteria.andIdEqualTo(Integer.valueOf(id));

            }

            if (!StringUtils.isEmpty(name)) {

                criteria.andNameLike("%" + name + "%");

            }

            criteria.andDeletedEqualTo(false);

     

            if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {

                example.setOrderByClause(sort + " " + order);

            }

     

            PageHelper.startPage(page, size);

            returnbrandMapper.selectByExample(example);

        }

     

        publicintupdateById(LitemallBrandbrand) {

            brand.setUpdateTime(LocalDateTime.now());

            returnbrandMapper.updateByPrimaryKeySelective(brand);

        }

     

        publicvoiddeleteById(Integerid) {

            brandMapper.logicalDeleteByPrimaryKey(id);

        }

     

        publicvoidadd(LitemallBrandbrand) {

            brand.setAddTime(LocalDateTime.now());

            brand.setUpdateTime(LocalDateTime.now());

            brandMapper.insertSelective(brand);

        }

     

        publicList<LitemallBrand> all() {

            LitemallBrandExampleexample = newLitemallBrandExample();

            example.or().andDeletedEqualTo(false);

            returnbrandMapper.selectByExample(example);

        }

    }

         核心操作部分

    Ps:其他核心操作同存储(商品信息、图片对象等)操作、物流查询服务类似,不在冗赘。

    存储操作

    /**

     * 对象存储接口

     */

    publicinterfaceStorage {

     

        /**

         * 存储一个文件对象

         *

         * @paraminputStream   文件输入流

         * @paramcontentLength文件长度

         * @paramcontentType   文件类型

         * @paramkeyName       文件名

         */

        voidstore(InputStreaminputStream, longcontentLength, StringcontentType, StringkeyName);

     

        Stream<Path> loadAll();

     

        Pathload(StringkeyName);

     

        ResourceloadAsResource(StringkeyName);

     

        voiddelete(StringkeyName);

     

        StringgenerateUrl(StringkeyName);

    }

    物流查询服务

    /**

     * 物流查询服务

     *

     * 快递鸟即时查询API http://www.kdniao.com/api-track

     */

    public class ExpressService {

        //请求url

        private String ReqURL = "http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";

     

        private ExpressProperties properties;

     

        public ExpressProperties getProperties() {

            return properties;

        }

     

        public void setProperties(ExpressProperties properties) {

            this.properties = properties;

        }

     

        /**

         * 获取物流供应商名

         *

         * @param vendorCode

         * @return

         */

        public String getVendorName(String vendorCode) {

            for (Map<String, String> item : properties.getVendors()) {

                if (item.get("code").equals(vendorCode))

                    return item.get("name");

            }

            return null;

        }

     

        /**

         * 获取物流信息

         *

         * @param expCode

         * @param expNo

         * @return

         */

        public ExpressInfo getExpressInfo(String expCode, String expNo) {

            try {

                String result = getOrderTracesByJson(expCode, expNo);

                ObjectMapper objMap = new ObjectMapper();

                ExpressInfo ei = objMap.readValue(result, ExpressInfo.class);

                ei.setShipperName(getVendorName(expCode));

                return ei;

            } catch (Exception e) {

                e.printStackTrace();

            }

     

            return null;

        }

     

        /**

         * Json方式 查询订单物流轨迹

         *

         * @throws Exception

         */

        private String getOrderTracesByJson(String expCode, String expNo) throws Exception {

            if (!properties.isEnable()) {

                return null;

            }

     

            String requestData = "{'OrderCode':'','ShipperCode':'" + expCode + "','LogisticCode':'" + expNo + "'}";

     

            Map<String, String> params = new HashMap<String, String>();

            params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));

            params.put("EBusinessID", properties.getAppId());

            params.put("RequestType", "1002");

            String dataSign = encrypt(requestData, properties.getAppKey(), "UTF-8");

            params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));

            params.put("DataType", "2");

     

            String result = HttpUtil.sendPost(ReqURL, params);

     

            //根据公司业务处理返回的信息......

     

            return result;

        }

     

        /**

         * MD5加密

         *

         * @param str     内容

         * @param charset 编码方式

         * @throws Exception

         */

        private String MD5(String str, String charset) throws Exception {

            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(str.getBytes(charset));

            byte[] result = md.digest();

            StringBuffer sb = new StringBuffer(32);

            for (int i = 0; i < result.length; i++) {

                int val = result[i] & 0xff;

                if (val <= 0xf) {

                    sb.append("0");

                }

                sb.append(Integer.toHexString(val));

            }

            return sb.toString().toLowerCase();

        }

     

        /**

         * Sign签名生成

         *

         * @param content  内容

         * @param keyValue Appkey

         * @param charset  编码方式

         * @return DataSign签名

         */

        private String encrypt(String content, String keyValue, String charset) {

            if (keyValue != null) {

                content = content + keyValue;

            }

            byte[] src = new byte[0];

            try {

                src = MD5(content, charset).getBytes(charset);

                return Base64Utils.encodeToString(src);

            } catch (Exception e) {

                e.printStackTrace();

            }

     

            return null;

        }

     

     

    }

  • 相关阅读:
    查看MySQL数据库版本
    PHP如何查找一列有序数组是否包含某值(二分查找)
    TP数据查询给sql给查询加一个虚拟字段值
    TP SQL统计查询语法
    PHP如何对一组数进行重新排列(冒泡算法)
    python入门及数字、字符串类型
    GitHub及Git及GitHub搭建个人网站
    Editplus的扩展程序的删除
    50个SQL语句(MySQL版) 问题十五
    50个SQL语句(MySQL版) 问题十四
  • 原文地址:https://www.cnblogs.com/my-worldlet/p/10936307.html
Copyright © 2011-2022 走看看