# 购物车订单系统 **Repository Path**: overload__hcf/shopping-cart-order-system ## Basic Information - **Project Name**: 购物车订单系统 - **Description**: 基于springboot的购物车订单后端实现 - **Primary Language**: Java - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 8 - **Forks**: 2 - **Created**: 2021-11-20 - **Last Updated**: 2024-11-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 购物车订单系统 ### 1.项目结构 ![image-20211122233832158](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122233832158.png) 采用maven多模块,父模块负责统一依赖版本管理. > cartorder_common: 包含业务实体,业务接口,业务拓展类以及mapper > cartorder_web: 包含controller层和业务实现层以及包含了统一异常处理和日志输出 ### 2.数据库设计 > 购物车记录信息cart ![image-20211122234651877](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122234651877.png) > 产品信息product ![image-20211122234722982](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122234722982.png) > 订单表 ordered ![image-20211122234754325](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122234754325.png) > 订单明细表item ![image-20211122234818789](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122234818789.png) > 类别category ![image-20211122234910997](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122234910997.png) > 收货信息shipping ![image-20211122234935509](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122234935509.png) ### 3.主要接口实现(服务器地址:120.25.144.123) #### 3.1登录接口 > 120.25.144.123/cos/user request ``` method=post username,password admin 123456 ``` response ``` fail { "status": 1, "msg": "密码错误" } ``` ``` success { "status": 0, "data": { "id": 12, "username": "aaa", "email": "aaa@163.com", "phone": null, "role": 0, "createTime": 1479048325000, "updateTime": 1479048325000 } } ``` ------- #### 3.2 订单相关接口 1.创建订单 > 引用已存在的收货地址id 120.25.144.123/cos/ordered/create?shippingId=5 > request ``` shippingId ``` > response success ``` { "status": 0, "data": { "orderNo": 1485158223095, "payment": 2999.11, "paymentType": 1, "postage": 0, "status": 10, "paymentTime": null, "sendTime": null, "endTime": null, "closeTime": null, "createTime": 1485158223095, "orderItemVoList": [ { "orderNo": 1485158223095, "productId": 2, "productName": "oppo R8", "productImage": "mainimage.jpg", "currentUnitPrice": 2999.11, "quantity": 1, "totalPrice": 2999.11, "createTime": null } ], "shippingId": 5, "shippingVo": null } } ``` fail ``` { "status": 1, "msg": "创建订单失败" } ``` ------ 2. 订单列表 > 120.25.144.123/cos/ordered/list?pageSize=3 > request ``` pageSize(default=10) pageNum(default=1) ``` > response success ``` { "status": 0, "data": { "pageNum": 1, "pageSize": 3, "size": 3, "orderBy": null, "startRow": 1, "endRow": 3, "total": 16, "pages": 6, "list": [ { "orderNo": 1485158676346, "payment": 2999.11, "paymentType": 1, "paymentTypeDesc": "在线支付", "postage": 0, "status": 10, "statusDesc": "未支付", "paymentTime": "2021-02-11 12:27:18", "sendTime": "2021-02-11 12:27:18", "endTime": "2021-02-11 12:27:18", "closeTime": "2021-02-11 12:27:18", "createTime": "2021-01-23 16:04:36", "orderItemVoList": [ { "orderNo": 1485158676346, "productId": 2, "productName": "oppo R8", "productImage": "mainimage.jpg", "currentUnitPrice": 2999.11, "quantity": 1, "totalPrice": 2999.11, "createTime": "2021-01-23 16:04:36" } ], "imageHost": "http://img.happymmall.com/", "shippingId": 5, "receiverName": "geely", "shippingVo": null }, { "orderNo": 1485158675516, "payment": 2999.11, "paymentType": 1, "paymentTypeDesc": "在线支付", "postage": 0, "status": 10, "statusDesc": "未支付", "paymentTime": "2017-02-11 12:27:18", "sendTime": "2017-02-11 12:27:18", "endTime": "2017-02-11 12:27:18", "closeTime": "2017-02-11 12:27:18", "createTime": "2017-01-23 16:04:35", "orderItemVoList": [ { "orderNo": 1485158675516, "productId": 2, "productName": "oppo R8", "productImage": "mainimage.jpg", "currentUnitPrice": 2999.11, "quantity": 1, "totalPrice": 2999.11, "createTime": "2017-01-23 16:04:35" } ], "imageHost": "http://img.happymmall.com/", "shippingId": 5, "receiverName": "geely", "shippingVo": null }, { "orderNo": 1485158675316, "payment": 2999.11, "paymentType": 1, "paymentTypeDesc": "在线支付", "postage": 0, "status": 10, "statusDesc": "未支付", "paymentTime": "2017-02-11 12:27:18", "sendTime": "2017-02-11 12:27:18", "endTime": "2017-02-11 12:27:18", "closeTime": "2017-02-11 12:27:18", "createTime": "2017-01-23 16:04:35", "orderItemVoList": [ { "orderNo": 1485158675316, "productId": 2, "productName": "oppo R8", "productImage": "mainimage.jpg", "currentUnitPrice": 2999.11, "quantity": 1, "totalPrice": 2999.11, "createTime": "2017-01-23 16:04:35" } ], "imageHost": "http://img.happymmall.com/", "shippingId": 5, "receiverName": "geely", "shippingVo": null } ], "firstPage": 1, "prePage": 0, "nextPage": 2, "lastPage": 6, "isFirstPage": true, "isLastPage": false, "hasPreviousPage": false, "hasNextPage": true, "navigatePages": 8, "navigatepageNums": [ 1, 2, 3, 4, 5, 6 ] } } ``` fail ``` { "status": 10, "msg": "用户未登录,请登录" } ``` ------ 3.订单详情detail > 120.25.144.123/cos/ordered/detail?orderNo=1480515829406 > request ``` orderNo ``` > response success ``` { "status": 0, "data": { "orderNo": 1480515829406, "payment": 30000.00, "paymentType": 1, "paymentTypeDesc": "在线支付", "postage": 0, "status": 10, "statusDesc": "未支付", "paymentTime": "", "sendTime": "", "endTime": "", "closeTime": "", "createTime": "2016-11-30 22:23:49", "orderItemVoList": [ { "orderNo": 1480515829406, "productId": 1, "productName": "iphone7", "productImage": "mainimage.jpg", "currentUnitPrice": 10000.00, "quantity": 1, "totalPrice": 10000.00, "createTime": "2016-11-30 22:23:49" }, { "orderNo": 1480515829406, "productId": 2, "productName": "oppo R8", "productImage": "mainimage.jpg", "currentUnitPrice": 20000.00, "quantity": 1, "totalPrice": 20000.00, "createTime": "2016-11-30 22:23:49" } ], "imageHost": "http://img.happymmall.com/", "shippingId": 3, "receiverName": "geely", "shippingVo": { "receiverName": "geely", "receiverPhone": "0100", "receiverMobile": "186", "receiverProvince": "北京", "receiverCity": "北京", "receiverDistrict": "昌平区", "receiverAddress": "矩阵小区", "receiverZip": "100000" } } } ``` fail ``` { "status": 1, "msg": "没有找到订单" } ``` ------ 4.取消订单 120.25.144.123/cos/ordered/cancel?orderNo=1480515829406 **/order/cancel** > request ``` orderNo ``` > response success ``` { "status": 0 } ``` fail ``` { "status": 1, "msg": "该用户没有此订单" } 或 { "status": 1, "msg": "此订单已付款,无法被取消" } ``` ------ ### 4.统一异常处理 自定义异常 ```java public class UnauthorizedException extends RuntimeException { private int code; public UnauthorizedException() { super("请先进行登录认证"); this.code = 403; } public int getCode() { return code; } } ``` 全局异常捕获 ```java @ControllerAdvice @Slf4j public class GlobalExceptionHandler { ``````` @ResponseStatus(HttpStatus.FORBIDDEN) @ExceptionHandler(UnauthorizedException.class) @ResponseBody public ServerResponse handleUnauthorizedException(UnauthorizedException e) { log.error("没有权限!", e); return ServerResponse.createByError(e.getCode(),e.getMessage()); } } ``` 当未登录访问接口时返回 ```json { "status": 403, "msg": "请先进行登录认证" } ``` ![image-20211123000851450](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211123000851450.png) ### 5.日志 > 日志 对指定包执行前后进行日志输出 ```java @Aspect @Component @Slf4j public class WebLogAspect { private ThreadLocal startTime = new ThreadLocal<>(); @Pointcut("execution(public * com.overload.web.controller..*.*(..))") public void webLog() { } @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { startTime.set(System.currentTimeMillis()); // 接收到请求,记录请求内容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 请求参数 Object[] args = joinPoint.getArgs(); String requestParam = ""; if (args != null && args.length > 0){ try { requestParam = JSONObject.toJSONString(args[0]); }catch (Exception e){ } } // 记录下请求内容 log.info("URL : " + request.getRequestURL().toString()); log.info("HTTP_METHOD : " + request.getMethod()); log.info("IP : " + request.getRemoteAddr()); log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); log.info("ARGS : " + requestParam); } @AfterReturning(returning = "ret", pointcut = "webLog()") public void doAfterReturning(Object ret) throws Throwable { // 处理完请求,返回内容 log.info("RESPONSE : " + ret); log.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get())); } } ``` > 效果 ![image-20211122214038651](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122214038651.png) ![image-20211122214119647](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211122214119647.png) ### 6.mybatisplus实现乐观锁 1.在每个表中添加version字段 2.实体类version字段上加上@version ```java @Version @TableField(fill = FieldFill.INSERT) private Integer version; ``` 3.编写配置类 ```java @Configuration @MapperScan("com.overload.common.mapper") @EnableTransactionManagement public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); interceptor.addInnerInterceptor( new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } } ``` ### 7.统一返回对象处理和前后端交互格式 > 返回格式: 例如 : return ServerResponse.createBySuccess(code,"message",data); ![image-20211123001505342](https://gitee.com/overload__hcf/shopping-cart-order-system/raw/master/%E9%A1%B9%E7%9B%AE%E6%88%AA%E5%9B%BE/image-20211123001505342.png)