• SpringCloud+Vue校园二手市场 附带详细运行指导视频


    一、项目演示

    项目演示地址:视频地址

    二、项目介绍

    项目描述:这是一个基于SpringCloud+Vue框架开发的校园二手市场系统。首先,这是一个前后端分离的项目,代码简洁规范,注释说明详细,易于理解和学习。其次,这项目功能丰富,具有一个校园二手市场系统该有的所有功能。

    项目功能:此项目分为两个角色:普通用户管理员普通用户有登录注册、浏览商品信息、地址管理、添加购物车、结算支付订单、查看个人信息、查看个人订单详情、创建店铺、发布商品等等功能。管理员有管理所有商品信息、管理所有订单信息、管理所有用户信息、管理所有店铺信息、查看收益数据图表等等功能。

    应用技术:SpringCloud + Vue + MySQL + MyBatis + Redis + ElementUI + 沙箱支付宝 + Nacos + openFeign + GateWay

    运行环境:IntelliJ IDEA2019.3.5 + MySQL5.7(项目压缩包中自带) + Redis5.0.5(项目压缩包中自带) + JDK1.8 + Maven3.6.3(项目压缩包中自带)+ Node14.16.1(项目压缩包中自带)+ Nacos1.3.0(项目压缩包中自带)

    注意:电脑内存最好16G,否则存在运行不起来的可能!!!

    三、项目运行截图

    项目运行截图:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    四、主要代码

    1.SpringCloud GateWay 网关拦截器代码:

    package com.yjq.programmer.filter;
    
    import com.yjq.programmer.constant.WhiteList;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    import javax.annotation.Resource;
    
    /**
     * @author 杨杨吖
     * @QQ 823208782
     * @WX yjqi12345678
     * @create 2021-05-12 17:44
     */
    
    @Component
    public class LoginWebGatewayFilter implements GlobalFilter, Ordered {
    
        private static final Logger logger = LoggerFactory.getLogger(LoginWebGatewayFilter.class);
    
        @Resource
        private StringRedisTemplate stringRedisTemplate;
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            String path = exchange.getRequest().getURI().getPath();
            // 判断该路径是否需要验证
            for(String str : WhiteList.userNotNeedConfirmUrl){
                if(path.equals(str)){
                    return chain.filter(exchange);
                }
            }
            //获取header的token参数
            String token = exchange.getRequest().getHeaders().getFirst("token");
            logger.info("前台登录验证开始,token:{}", token);
            if (token == null || token.isEmpty()) {
                logger.info( "token为空,请求被拦截" );
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            Object object = stringRedisTemplate.opsForValue().get("USER_" + token);
            if (object == null) {
                logger.warn( "token无效,请求被拦截" );
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
    
            return chain.filter(exchange);
        }
    
        @Override
        public int getOrder()
        {
            // 过滤器执行优先级 值越小优先级越高
            return 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    2.沙箱支付宝支付订单业务逻辑代码:

     /**
      * 使用沙箱支付宝支付订单
      * @param orderDTO
      * @return
      */
     @Override
        public ResponseDTO<String> aliPayOrder(OrderDTO orderDTO) {
            // 判断是否进行继续支付
            if(!CommonUtil.isEmpty(orderDTO.getId())) {
                Orders orders = ordersMapper.selectByPrimaryKey(orderDTO.getId());
                return initAliPay(orders.getNo(),  orders.getTotalPrice());
            }
            if(orderDTO.getCartIdList() == null || orderDTO.getCartIdList().size() == 0) {
                return ResponseDTO.errorByMsg(CodeMsg.DATA_ERROR);
            }
            if(CommonUtil.isEmpty(orderDTO.getUserId())) {
                return ResponseDTO.errorByMsg(CodeMsg.USER_SESSION_EXPIRED);
            }
            List<OrderItem> orderItemList = new ArrayList<>();
            BigDecimal totalPrice = new BigDecimal("0.00");
            String orderNo = String.valueOf(new SnowFlake(2, 3).nextId());
            String orderId = UuidUtil.getShortUuid();
            // 获取用户挑选的商品信息
            for(String cartId : orderDTO.getCartIdList()) {
                CartDTO cartDTO = new CartDTO();
                cartDTO.setId(cartId);
                ResponseDTO<CartDTO> responseDTO = userClient.getCartById(cartDTO);
                if(!responseDTO.getCode().equals(CodeMsg.SUCCESS.getCode())) {
                    return ResponseDTO.errorByMsg(CodeMsg.ORDER_PRODUCT_ERROR);
                }
                cartDTO = responseDTO.getData();
                // 判断商品库存是否足够
                if(cartDTO.getQuantity() > cartDTO.getProductDTO().getStock()) {
                    CodeMsg codeMsg = CodeMsg.PRODUCT_STOCK_ERROR;
                    codeMsg.setMsg("商品(" + cartDTO.getProductDTO().getName() + ")库存不足!" );
                    return ResponseDTO.errorByMsg(codeMsg);
                }
                // 判断商品状态
                if(!ProductStateEnum.SUCCESS.getCode().equals(cartDTO.getProductDTO().getState())) {
                    CodeMsg codeMsg = CodeMsg.PRODUCT_STATE_ERROR;
                    codeMsg.setMsg("商品(" + cartDTO.getProductDTO().getName() + ")状态异常!" );
                    return ResponseDTO.errorByMsg(codeMsg);
                }
                // 封装订单详情数据
                OrderItem orderItem = new OrderItem();
                orderItem.setId(UuidUtil.getShortUuid());
                orderItem.setProductName(cartDTO.getProductDTO().getName());
                orderItem.setProductId(cartDTO.getProductDTO().getId());
                orderItem.setProductPhoto(cartDTO.getProductDTO().getPhoto());
                orderItem.setProductPrice(cartDTO.getProductDTO().getPrice());
                orderItem.setOrderId(orderId);
                orderItem.setState(OrderStateEnum.WAIT.getCode());
                orderItem.setStoreId(cartDTO.getProductDTO().getStoreId());
                orderItem.setQuantity(cartDTO.getQuantity());
                orderItem.setSumPrice(new BigDecimal(orderItem.getQuantity()).multiply(orderItem.getProductPrice()));
                orderItemList.add(orderItem);
                totalPrice = totalPrice.add(orderItem.getSumPrice());
                // 移除购物车数据
                userClient.removeCart(cartDTO);
            }
            // 订单详情数据入库
            for(OrderItem orderItem : orderItemList){
                if(orderItemMapper.insertSelective(orderItem) == 0) {
                    throw new RuntimeException(CodeMsg.ORDER_ADD_ERROR.getMsg());
                }
            }
            // 封装订单数据  并入库
            Orders orders = CopyUtil.copy(orderDTO, Orders.class);
            orders.setId(orderId);
            orders.setCreateTime(new Date());
            orders.setNo(orderNo);
            orders.setTotalPrice(totalPrice);
            orders.setState(OrderStateEnum.WAIT.getCode());
            if(ordersMapper.insertSelective(orders) == 0) {
                throw new RuntimeException(CodeMsg.ORDER_ADD_ERROR.getMsg());
            }
    
            return initAliPay(orderNo, totalPrice);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    3.其他服务调用商品服务的代码(openFeign):

    package com.yjq.programmer.feignclient;
    
    import com.yjq.programmer.dto.ProductDTO;
    import com.yjq.programmer.dto.ResponseDTO;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    
    import java.util.List;
    
    /**
     * @author 杨杨吖
     * @QQ 823208782
     * @WX yjqi12345678
     * @create 2022-07-08 9:52
     */
    @FeignClient("ProductService")
    public interface ProductClient {
    
        @PostMapping("/product/store/get")
        ResponseDTO<List<ProductDTO>> getByStore(@RequestBody ProductDTO productDTO);
    
        @PostMapping("/product/get")
        ResponseDTO<ProductDTO> getById(@RequestBody ProductDTO productDTO);
    
        @PostMapping("/product/save")
        ResponseDTO<Boolean> saveProduct(@RequestBody ProductDTO productDTO);
    
        @PostMapping("/product/remove/store_id")
        ResponseDTO<Boolean> removeProductByStoreId(@RequestBody ProductDTO productDTO);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    4.用户登录业务逻辑代码:

        /**
         * 前台用户登录
         * @param userDTO
         * @return
         */
        @Override
        public ResponseDTO<UserDTO> homeLogin(UserDTO userDTO) {
            // 进行是否为空判断
            if(CommonUtil.isEmpty(userDTO.getUsername())){
                return ResponseDTO.errorByMsg(CodeMsg.USERNAME_EMPTY);
            }
            if(CommonUtil.isEmpty(userDTO.getPassword())){
                return ResponseDTO.errorByMsg(CodeMsg.PASSWORD_EMPTY);
            }
            // 对比昵称和密码是否正确
            UserExample userExample = new UserExample();
            userExample.createCriteria().andUsernameEqualTo(userDTO.getUsername()).andPasswordEqualTo(userDTO.getPassword());
            List<User> userList = userMapper.selectByExample(userExample);
            if(userList == null || userList.size() != 1){
                return ResponseDTO.errorByMsg(CodeMsg.USERNAME_PASSWORD_ERROR);
            }
            // 生成登录token并存入Redis中
            UserDTO selectedUserDto = CopyUtil.copy(userList.get(0), UserDTO.class);
            String token = UuidUtil.getShortUuid();
            selectedUserDto.setToken(token);
            //把token存入redis中 有效期1小时
            stringRedisTemplate.opsForValue().set("USER_" + token, JSON.toJSONString(selectedUserDto), 3600, TimeUnit.SECONDS);
            return ResponseDTO.successByMsg(selectedUserDto, "登录成功!");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    制作一个简单HTML中华传统文化网页(HTML+CSS)
    计算机毕设 大数据工作岗位数据分析与可视化 - python flask
    3分钟看懂设计模式02:观察者模式
    MySQL调优参数配置详解
    手把手教你用代码画架构图
    openGauss学习笔记-229 openGauss性能调优-系统调优-配置Ustore
    MobileNetv1论文详解
    五大模型看深度学习用于时序预测的最新进展
    CleanMyMac X优秀首选第三方mac清理软件
    动手学习深度学习 09:循环神经网络
  • 原文地址:https://blog.csdn.net/dgfdhgghd/article/details/127848666