├── src └── main │ ├── webapp │ ├── WEB-INF │ │ ├── lib │ │ │ ├── alipay-sdk-java-3.3.0.jar │ │ │ ├── alipay-trade-sdk-20161215.jar │ │ │ ├── alipay-sdk-java-3.3.0-source.jar │ │ │ └── alipay-trade-sdk-20161215-source.jar │ │ ├── dispatcher-servlet.xml │ │ └── web.xml │ └── index.jsp │ ├── resources.prd │ ├── mmall.properties │ ├── datasource.properties │ ├── logback.xml │ └── zfbinfo.properties │ ├── java │ └── com │ │ └── mmall │ │ ├── service │ │ ├── FileService.java │ │ ├── CategoryService.java │ │ ├── ShippingService.java │ │ ├── CartService.java │ │ ├── impl │ │ │ ├── FileServiceImpl.java │ │ │ ├── ShippingServiceImpl.java │ │ │ ├── CategoryServiceImpl.java │ │ │ ├── UserServiceImpl.java │ │ │ └── CartServiceImpl.java │ │ ├── UserService.java │ │ ├── ProductService.java │ │ └── OrderService.java │ │ ├── vo │ │ ├── OrderProductVO.java │ │ ├── CartVO.java │ │ ├── ProductListVO.java │ │ ├── ShippingVO.java │ │ ├── OrderItemVO.java │ │ ├── ProductDetailVO.java │ │ ├── CartProductVO.java │ │ └── OrderVO.java │ │ ├── pojo │ │ ├── Category.java │ │ ├── Cart.java │ │ ├── PayInfo.java │ │ ├── User.java │ │ ├── OrderItem.java │ │ ├── Product.java │ │ ├── Shipping.java │ │ └── Order.java │ │ ├── util │ │ ├── Md5Utils.java │ │ ├── PropertiesUtils.java │ │ ├── DateTimeUtils.java │ │ ├── BigDecimalUtils.java │ │ ├── CookieUtils.java │ │ ├── FtpUtils.java │ │ ├── JsonUtils.java │ │ └── RedisShardedPoolUtils.java │ │ ├── common │ │ ├── ResponseCodeEnum.java │ │ ├── ExceptionResolver.java │ │ ├── RedissonManager.java │ │ ├── JsonResult.java │ │ ├── RedisShardedPool.java │ │ └── Const.java │ │ ├── dao │ │ ├── PayInfoMapper.java │ │ ├── CategoryMapper.java │ │ ├── ShippingMapper.java │ │ ├── OrderItemMapper.java │ │ ├── ProductMapper.java │ │ ├── OrderMapper.java │ │ ├── CartMapper.java │ │ └── UserMapper.java │ │ ├── controller │ │ ├── common │ │ │ ├── UserCheck.java │ │ │ ├── SessionExpireFilter.java │ │ │ └── interceptor │ │ │ │ └── AuthorityInterceptor.java │ │ ├── backend │ │ │ ├── CategoryManageController.java │ │ │ ├── OrderManageController.java │ │ │ ├── UserManageController.java │ │ │ └── ProductManageController.java │ │ └── portal │ │ │ ├── UserSessionController.java │ │ │ ├── ProductController.java │ │ │ ├── ShippingController.java │ │ │ ├── CartController.java │ │ │ ├── UserController.java │ │ │ └── OrderController.java │ │ └── task │ │ └── CloseOrderTask.java │ ├── resources.dev │ ├── datasource.properties │ ├── mmall.properties │ ├── logback.xml │ └── zfbinfo.properties │ └── resources │ ├── applicationContext.xml │ ├── applicationContext-spring-session.xml │ ├── applicationContext-datasource.xml │ ├── mappers │ ├── CategoryMapper.xml │ ├── PayInfoMapper.xml │ ├── CartMapper.xml │ ├── UserMapper.xml │ ├── OrderItemMapper.xml │ └── ProductMapper.xml │ └── generatorConfig.xml ├── .gitignore └── README.md /src/main/webapp/WEB-INF/lib/alipay-sdk-java-3.3.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leifchen/mmall/HEAD/src/main/webapp/WEB-INF/lib/alipay-sdk-java-3.3.0.jar -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/lib/alipay-trade-sdk-20161215.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leifchen/mmall/HEAD/src/main/webapp/WEB-INF/lib/alipay-trade-sdk-20161215.jar -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/lib/alipay-sdk-java-3.3.0-source.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leifchen/mmall/HEAD/src/main/webapp/WEB-INF/lib/alipay-sdk-java-3.3.0-source.jar -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/lib/alipay-trade-sdk-20161215-source.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leifchen/mmall/HEAD/src/main/webapp/WEB-INF/lib/alipay-trade-sdk-20161215-source.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | ### package file 4 | *.war 5 | *.ear 6 | 7 | ### maven ignore 8 | target/ 9 | 10 | ### idea ignore 11 | .idea/ 12 | /idea/ 13 | *.ipr 14 | *.iml 15 | *.iws 16 | 17 | ### temp file 18 | *.log 19 | *.cache 20 | *.diff 21 | *.patch 22 | *.tmp 23 | 24 | ### system ignore 25 | .DS_Store 26 | Thumbs.db 27 | -------------------------------------------------------------------------------- /src/main/resources.prd/mmall.properties: -------------------------------------------------------------------------------- 1 | # PRD 2 | 3 | ### FTP Server 4 | ftp.server.ip=192.168.33.101 5 | ftp.user=ftpuser 6 | ftp.password=123456 7 | ftp.server.http.prefix=http://image.mall.com/ 8 | 9 | ### MD5 Salt 10 | password.salt=leifchen 11 | 12 | ### Alipay 13 | alipay.callback.url=http://leifchen.51vip.biz/order/alipay_callback.do -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/FileService.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service; 2 | 3 | import org.springframework.web.multipart.MultipartFile; 4 | 5 | /** 6 | * 文件Service 7 | *

8 | * @Author LeifChen 9 | * @Date 2019-02-28 10 | */ 11 | public interface FileService { 12 | 13 | /** 14 | * 上传文件 15 | * @param file 16 | * @param path 17 | * @return 18 | */ 19 | String upload(MultipartFile file, String path); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources.dev/datasource.properties: -------------------------------------------------------------------------------- 1 | # DEV 2 | 3 | db.driverLocation=E:/mybatis-generator/mysql-connector-java-5.1.47.jar 4 | db.driverClassName=com.mysql.jdbc.Driver 5 | 6 | db.url=jdbc:mysql://192.168.33.101:3306/mmall?characterEncoding=utf-8&useSSL=false 7 | db.username=mmall 8 | db.password=Mmall@2019 9 | 10 | db.initialSize=20 11 | db.maxActive=50 12 | db.maxIdle=20 13 | db.minIdle=10 14 | db.maxWait=10 15 | db.defaultAutoCommit=true 16 | db.minEvictableIdleTimeMillis=3600000 17 | -------------------------------------------------------------------------------- /src/main/resources.prd/datasource.properties: -------------------------------------------------------------------------------- 1 | # PRD 2 | 3 | db.driverLocation=E:/mybatis-generator/mysql-connector-java-5.1.47.jar 4 | db.driverClassName=com.mysql.jdbc.Driver 5 | 6 | db.url=jdbc:mysql://192.168.33.101:3306/mmall?characterEncoding=utf-8&useSSL=false 7 | db.username=mmall 8 | db.password=Mmall@2019 9 | 10 | db.initialSize=20 11 | db.maxActive=50 12 | db.maxIdle=20 13 | db.minIdle=10 14 | db.maxWait=10 15 | db.defaultAutoCommit=true 16 | db.minEvictableIdleTimeMillis=3600000 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 电商项目 2 | 3 | 使用Maven构建SSM架构的电商项目,并引进Tomcat集群与Redis分布式。 4 | 5 | ## 一期 6 | 7 | * 用户模块 8 | * 分类模块 9 | * 商品模块 10 | * 购物车模块 11 | * 收货地址模块 12 | * 订单模块 13 | * 支付模块 14 | 15 | ## 二期 16 | 17 | * Lombok 18 | * Maven环境隔离 19 | * Tomcat集群 20 | * Redis分布式 21 | * Session单点登录 22 | * Spring Session 23 | * Spring MVC权限拦截 24 | * Redisson分布式锁 25 | 26 | # 参考 27 | 28 | 1. [从0开始 独立完成企业级Java电商网站开发(服务端)](https://coding.imooc.com/class/96.html) 29 | 2. [Java企业级电商项目架构演进之路 Tomcat集群与Redis分布式](https://coding.imooc.com/class/162.html) 30 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/vo/OrderProductVO.java: -------------------------------------------------------------------------------- 1 | package com.mmall.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | import java.util.List; 9 | 10 | /** 11 | * 订单商品VO 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-03-11 15 | */ 16 | @Getter 17 | @Setter 18 | @ToString 19 | public class OrderProductVO { 20 | 21 | private List orderItemVOList; 22 | private BigDecimal productTotalPrice; 23 | private String imageHost; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/vo/CartVO.java: -------------------------------------------------------------------------------- 1 | package com.mmall.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | import java.util.List; 9 | 10 | /** 11 | * 购物车VO 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-03-01 15 | */ 16 | @Getter 17 | @Setter 18 | @ToString 19 | public class CartVO { 20 | 21 | private List cartProductVOList; 22 | private BigDecimal cartTotalPrice; 23 | private Boolean allChecked; 24 | private String iamgeHost; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/pojo/Category.java: -------------------------------------------------------------------------------- 1 | package com.mmall.pojo; 2 | 3 | import lombok.*; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * 商品类别 9 | *

10 | * @Author LeifChen 11 | * @Date 2019-02-25 12 | */ 13 | @Getter 14 | @Setter 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | public class Category { 19 | private Integer id; 20 | 21 | private Integer parentId; 22 | 23 | private String name; 24 | 25 | private Boolean status; 26 | 27 | private Integer sortOrder; 28 | 29 | private Date createTime; 30 | 31 | private Date updateTime; 32 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/vo/ProductListVO.java: -------------------------------------------------------------------------------- 1 | package com.mmall.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * 商品VO 11 | *

12 | * @Author LeifChen 13 | * @Date 2019-02-28 14 | */ 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class ProductListVO { 19 | 20 | private Integer id; 21 | private Integer categoryId; 22 | private String name; 23 | private String subtitle; 24 | private String mainImage; 25 | private BigDecimal price; 26 | private Integer status; 27 | private String imageHost; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/vo/ShippingVO.java: -------------------------------------------------------------------------------- 1 | package com.mmall.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | /** 8 | * 收货地址VO 9 | *

10 | * @Author LeifChen 11 | * @Date 2019-03-08 12 | */ 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class ShippingVO { 17 | 18 | private String receiverName; 19 | private String receiverPhone; 20 | private String receiverMobile; 21 | private String receiverProvince; 22 | private String receiverCity; 23 | private String receiverDistrict; 24 | private String receiverAddress; 25 | private String receiverZip; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/vo/OrderItemVO.java: -------------------------------------------------------------------------------- 1 | package com.mmall.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * 订单明细VO 11 | *

12 | * @Author LeifChen 13 | * @Date 2019-03-08 14 | */ 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class OrderItemVO { 19 | 20 | private Long orderNo; 21 | private Integer productId; 22 | private String productName; 23 | private String productImage; 24 | private BigDecimal currentUnitPrice; 25 | private Integer quantity; 26 | private BigDecimal totalPrice; 27 | private String createTime; 28 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/pojo/Cart.java: -------------------------------------------------------------------------------- 1 | package com.mmall.pojo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * 购物车 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-02-25 15 | */ 16 | @Getter 17 | @Setter 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class Cart { 21 | private Integer id; 22 | 23 | private Integer userId; 24 | 25 | private Integer productId; 26 | 27 | private Integer quantity; 28 | 29 | private Integer checked; 30 | 31 | private Date createTime; 32 | 33 | private Date updateTime; 34 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/util/Md5Utils.java: -------------------------------------------------------------------------------- 1 | package com.mmall.util; 2 | 3 | import org.apache.commons.codec.binary.Hex; 4 | 5 | import java.security.MessageDigest; 6 | 7 | /** 8 | * MD5加密工具类 9 | *

10 | * @Author LeifChen 11 | * @Date 2019-02-26 12 | */ 13 | public class Md5Utils { 14 | 15 | public static String encode(String str) { 16 | try { 17 | MessageDigest md = MessageDigest.getInstance("MD5"); 18 | str += PropertiesUtils.getProperty("password.salt", ""); 19 | return Hex.encodeHexString(md.digest(str.getBytes())).toUpperCase(); 20 | } catch (Exception e) { 21 | throw new RuntimeException(e); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page pageEncoding="UTF-8"%> 2 | 3 | 4 | 5 |

Hello World!

6 | 7 |
8 | SpringMVC上传文件 9 |
10 | 11 | 12 |
13 |
14 | 15 |
16 | 富文本图片上传文件 17 |
18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/pojo/PayInfo.java: -------------------------------------------------------------------------------- 1 | package com.mmall.pojo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * 付款信息 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-02-25 15 | */ 16 | @Getter 17 | @Setter 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class PayInfo { 21 | private Integer id; 22 | 23 | private Integer userId; 24 | 25 | private Long orderNo; 26 | 27 | private Integer payPlatform; 28 | 29 | private String platformNumber; 30 | 31 | private String platformStatus; 32 | 33 | private Date createTime; 34 | 35 | private Date updateTime; 36 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/common/ResponseCodeEnum.java: -------------------------------------------------------------------------------- 1 | package com.mmall.common; 2 | 3 | /** 4 | * 返回编码枚举 5 | *

6 | * @Author LeifChen 7 | * @Date 2019-02-26 8 | */ 9 | public enum ResponseCodeEnum { 10 | 11 | // 成功 12 | SUCCESS(0, "SUCCESS"), 13 | // 失败 14 | ERROR(1, "ERROR"), 15 | // 参数不合法 16 | ILLEGAL_ARGUMENT(2, "ILLEGAL_ARGUMENT"), 17 | // 需要登录 18 | NEED_LOGIN(10, "NEED_LOGIN"); 19 | 20 | private final int code; 21 | private final String desc; 22 | 23 | ResponseCodeEnum(int code, String desc) { 24 | this.code = code; 25 | this.desc = desc; 26 | } 27 | 28 | public int getCode() { 29 | return code; 30 | } 31 | 32 | public String getDesc() { 33 | return desc; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/pojo/User.java: -------------------------------------------------------------------------------- 1 | package com.mmall.pojo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.io.Serializable; 9 | import java.util.Date; 10 | 11 | /** 12 | * 用户 13 | *

14 | * @Author LeifChen 15 | * @Date 2019-02-25 16 | */ 17 | @Getter 18 | @Setter 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class User implements Serializable { 22 | private Integer id; 23 | 24 | private String username; 25 | 26 | private String password; 27 | 28 | private String email; 29 | 30 | private String phone; 31 | 32 | private String question; 33 | 34 | private String answer; 35 | 36 | private Integer role; 37 | 38 | private Date createTime; 39 | 40 | private Date updateTime; 41 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/vo/ProductDetailVO.java: -------------------------------------------------------------------------------- 1 | package com.mmall.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * 商品详情VO 11 | *

12 | * @Author LeifChen 13 | * @Date 2019-02-28 14 | */ 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class ProductDetailVO { 19 | 20 | private Integer id; 21 | private Integer categoryId; 22 | private String name; 23 | private String subtitle; 24 | private String mainImage; 25 | private String subImages; 26 | private String detail; 27 | private BigDecimal price; 28 | private Integer stock; 29 | private Integer status; 30 | private String createTime; 31 | private String updateTime; 32 | private String imageHost; 33 | private Integer parentCategoryId; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/vo/CartProductVO.java: -------------------------------------------------------------------------------- 1 | package com.mmall.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * 购物车商品VO 11 | *

12 | * @Author LeifChen 13 | * @Date 2019-03-01 14 | */ 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class CartProductVO { 19 | 20 | private Integer id; 21 | private Integer userId; 22 | private Integer productId; 23 | private Integer quantity; 24 | private String productName; 25 | private String productSubtitle; 26 | private String productMainImage; 27 | private BigDecimal productPrice; 28 | private Integer productStatus; 29 | private BigDecimal productTotalPrice; 30 | private Integer productStock; 31 | private Integer productChecked; 32 | private String limitQuantity; 33 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/pojo/OrderItem.java: -------------------------------------------------------------------------------- 1 | package com.mmall.pojo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.math.BigDecimal; 9 | import java.util.Date; 10 | 11 | /** 12 | * 订单明细 13 | *

14 | * @Author LeifChen 15 | * @Date 2019-02-25 16 | */ 17 | @Getter 18 | @Setter 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class OrderItem { 22 | private Integer id; 23 | 24 | private Integer userId; 25 | 26 | private Long orderNo; 27 | 28 | private Integer productId; 29 | 30 | private String productName; 31 | 32 | private String productImage; 33 | 34 | private BigDecimal currentUnitPrice; 35 | 36 | private Integer quantity; 37 | 38 | private BigDecimal totalPrice; 39 | 40 | private Date createTime; 41 | 42 | private Date updateTime; 43 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/pojo/Product.java: -------------------------------------------------------------------------------- 1 | package com.mmall.pojo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.math.BigDecimal; 9 | import java.util.Date; 10 | 11 | /** 12 | * 商品 13 | *

14 | * @Author LeifChen 15 | * @Date 2019-02-25 16 | */ 17 | @Getter 18 | @Setter 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class Product { 22 | private Integer id; 23 | 24 | private Integer categoryId; 25 | 26 | private String name; 27 | 28 | private String subtitle; 29 | 30 | private String mainImage; 31 | 32 | private String subImages; 33 | 34 | private String detail; 35 | 36 | private BigDecimal price; 37 | 38 | private Integer stock; 39 | 40 | private Integer status; 41 | 42 | private Date createTime; 43 | 44 | private Date updateTime; 45 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/pojo/Shipping.java: -------------------------------------------------------------------------------- 1 | package com.mmall.pojo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * 收货地址 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-02-25 15 | */ 16 | @Getter 17 | @Setter 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class Shipping { 21 | private Integer id; 22 | 23 | private Integer userId; 24 | 25 | private String receiverName; 26 | 27 | private String receiverPhone; 28 | 29 | private String receiverMobile; 30 | 31 | private String receiverProvince; 32 | 33 | private String receiverCity; 34 | 35 | private String receiverDistrict; 36 | 37 | private String receiverAddress; 38 | 39 | private String receiverZip; 40 | 41 | private Date createTime; 42 | 43 | private Date updateTime; 44 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/pojo/Order.java: -------------------------------------------------------------------------------- 1 | package com.mmall.pojo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.math.BigDecimal; 9 | import java.util.Date; 10 | 11 | /** 12 | * 订单 13 | *

14 | * @Author LeifChen 15 | * @Date 2019-02-25 16 | */ 17 | @Getter 18 | @Setter 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class Order { 22 | private Integer id; 23 | 24 | private Long orderNo; 25 | 26 | private Integer userId; 27 | 28 | private Integer shippingId; 29 | 30 | private BigDecimal payment; 31 | 32 | private Integer paymentType; 33 | 34 | private Integer postage; 35 | 36 | private Integer status; 37 | 38 | private Date paymentTime; 39 | 40 | private Date sendTime; 41 | 42 | private Date endTime; 43 | 44 | private Date closeTime; 45 | 46 | private Date createTime; 47 | 48 | private Date updateTime; 49 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/vo/OrderVO.java: -------------------------------------------------------------------------------- 1 | package com.mmall.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | import java.util.List; 9 | 10 | /** 11 | * 订单VO 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-03-08 15 | */ 16 | @Getter 17 | @Setter 18 | @ToString 19 | public class OrderVO { 20 | 21 | private Long orderNo; 22 | private BigDecimal payment; 23 | private Integer paymentType; 24 | private String paymentTypeDesc; 25 | private Integer postage; 26 | private Integer status; 27 | private String statusDesc; 28 | private String paymentTime; 29 | private String sendTime; 30 | private String endTime; 31 | private String closeTime; 32 | private String createTime; 33 | 34 | private List orderItemVOList; 35 | 36 | private String imageHost; 37 | private Integer shippingId; 38 | private String receiverName; 39 | 40 | private ShippingVO shippingVO; 41 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/dao/PayInfoMapper.java: -------------------------------------------------------------------------------- 1 | package com.mmall.dao; 2 | 3 | import com.mmall.pojo.PayInfo; 4 | 5 | /** 6 | * 付款信息Mapper 7 | *

8 | * @Author LeifChen 9 | * @Date 2019-02-25 10 | */ 11 | public interface PayInfoMapper { 12 | /** 13 | * 根据主键id删除 14 | * @param id 15 | * @return 16 | */ 17 | int deleteByPrimaryKey(Integer id); 18 | 19 | /** 20 | * 新增 21 | * @param record 22 | * @return 23 | */ 24 | int insert(PayInfo record); 25 | 26 | /** 27 | * 选择性新增 28 | * @param record 29 | * @return 30 | */ 31 | int insertSelective(PayInfo record); 32 | 33 | /** 34 | * 根据主键id查询 35 | * @param id 36 | * @return 37 | */ 38 | PayInfo selectByPrimaryKey(Integer id); 39 | 40 | /** 41 | * 选择性更新 42 | * @param record 43 | * @return 44 | */ 45 | int updateByPrimaryKeySelective(PayInfo record); 46 | 47 | /** 48 | * 更新 49 | * @param record 50 | * @return 51 | */ 52 | int updateByPrimaryKey(PayInfo record); 53 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/CategoryService.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service; 2 | 3 | import com.mmall.common.JsonResult; 4 | import com.mmall.pojo.Category; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 类别Service 10 | *

11 | * @Author LeifChen 12 | * @Date 2019-02-28 13 | */ 14 | public interface CategoryService { 15 | 16 | /** 17 | * 添加类别 18 | * @param categoryName 19 | * @param parentId 20 | * @return 21 | */ 22 | JsonResult addCategory(String categoryName, Integer parentId); 23 | 24 | /** 25 | * 更新类别名称 26 | * @param categoryId 27 | * @param categoryName 28 | * @return 29 | */ 30 | JsonResult updateCategoryName(Integer categoryId, String categoryName); 31 | 32 | /** 33 | * 获取子节点的平级类别 34 | * @param categoryId 35 | * @return 36 | */ 37 | JsonResult> getChildrenParallelCategory(Integer categoryId); 38 | 39 | /** 40 | * 递归获取当前节点下的所有子节点 41 | * @param categoryId 42 | * @return 43 | */ 44 | JsonResult> selectCategoryAndChildrenById(Integer categoryId); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/resources.dev/mmall.properties: -------------------------------------------------------------------------------- 1 | # DEV 2 | 3 | ### FTP Server 4 | ftp.server.ip=192.168.33.101 5 | ftp.user=ftpuser 6 | ftp.password=123456 7 | ftp.server.http.prefix=http://image.mall.com/ 8 | 9 | ### MD5 Salt 10 | password.salt=leifchen 11 | 12 | ### Alipay 13 | alipay.callback.url=http://leifchen.51vip.biz/order/alipay_callback.do 14 | 15 | ### redis 16 | redis1.ip=192.168.33.101 17 | redis1.port=6379 18 | redis2.ip=192.168.33.101 19 | redis2.port=6380 20 | #\u6700\u5927\u8FDE\u63A5\u6570 21 | redis.max.total=20 22 | #\u6700\u5927\u7A7A\u95F2\u6570 23 | redis.max.idle=10 24 | #\u6700\u5C0F\u7A7A\u95F2\u6570 25 | redis.min.idle=2 26 | #\u4ECEjedis\u8FDE\u63A5\u6C60\u83B7\u53D6\u8FDE\u63A5\u65F6\uFF0C\u6821\u9A8C\u5E76\u8FD4\u56DE\u53EF\u7528\u7684\u8FDE\u63A5 27 | redis.test.borrow=true 28 | #\u628A\u8FDE\u63A5\u653E\u56DEjedis\u8FDE\u63A5\u6C60\u65F6\uFF0C\u6821\u9A8C\u5E76\u8FD4\u56DE\u53EF\u7528\u7684\u8FDE\u63A5 29 | redis.test.return=false 30 | 31 | ### Shedule Task 32 | #\u5173\u95ED\u8BA2\u5355\u7684\u8D85\u65F6\u65F6\u95F4 33 | task.order.close.time.hour=2 34 | #\u9501\u7684\u6709\u6548\u65F6\u95F4(\u6BEB\u79D2) 35 | lock.timeout=5000 36 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/common/ExceptionResolver.java: -------------------------------------------------------------------------------- 1 | package com.mmall.common; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.web.servlet.HandlerExceptionResolver; 6 | import org.springframework.web.servlet.ModelAndView; 7 | import org.springframework.web.servlet.view.json.MappingJackson2JsonView; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | /** 13 | * 全局异常处理 14 | *

15 | * @Author LeifChen 16 | * @Date 2019-03-26 17 | */ 18 | @Slf4j 19 | @Component 20 | public class ExceptionResolver implements HandlerExceptionResolver { 21 | 22 | @Override 23 | public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 24 | log.error("{} Exception", request.getRequestURI(), ex); 25 | ModelAndView mv = new ModelAndView(new MappingJackson2JsonView()); 26 | mv.addObject("status", ResponseCodeEnum.ERROR.getCode()); 27 | mv.addObject("msg", "接口异常,详情请查看服务端日志"); 28 | mv.addObject("data", ex.toString()); 29 | return mv; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/common/RedissonManager.java: -------------------------------------------------------------------------------- 1 | package com.mmall.common; 2 | 3 | import com.mmall.util.PropertiesUtils; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.redisson.Redisson; 6 | import org.redisson.config.Config; 7 | import org.springframework.stereotype.Component; 8 | 9 | import javax.annotation.PostConstruct; 10 | 11 | /** 12 | * Redisson管理类 13 | *

14 | * @Author LeifChen 15 | * @Date 2019-03-28 16 | */ 17 | @Slf4j 18 | @Component 19 | public class RedissonManager { 20 | 21 | private Config config = new Config(); 22 | private Redisson redisson = null; 23 | 24 | private static String redis1Ip = PropertiesUtils.getProperty("redis1.ip"); 25 | private static Integer redis1Port = Integer.parseInt(PropertiesUtils.getProperty("redis1.port", "6379")); 26 | 27 | @PostConstruct 28 | private void init() { 29 | try { 30 | config.useSingleServer().setAddress(redis1Ip + ":" + redis1Port); 31 | redisson = (Redisson) Redisson.create(config); 32 | log.info("Redisson init success"); 33 | } catch (Exception e) { 34 | log.error("Redisson init error", e); 35 | } 36 | } 37 | 38 | public Redisson getRedisson() { 39 | return redisson; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/dao/CategoryMapper.java: -------------------------------------------------------------------------------- 1 | package com.mmall.dao; 2 | 3 | import com.mmall.pojo.Category; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 商品类别Mapper 9 | *

10 | * @Author LeifChen 11 | * @Date 2019-02-25 12 | */ 13 | public interface CategoryMapper { 14 | /** 15 | * 根据主键id删除 16 | * @param id 17 | * @return 18 | */ 19 | int deleteByPrimaryKey(Integer id); 20 | 21 | /** 22 | * 新增 23 | * @param record 24 | * @return 25 | */ 26 | int insert(Category record); 27 | 28 | /** 29 | * 选择性新增 30 | * @param record 31 | * @return 32 | */ 33 | int insertSelective(Category record); 34 | 35 | /** 36 | * 根据主键id查询 37 | * @param id 38 | * @return 39 | */ 40 | Category selectByPrimaryKey(Integer id); 41 | 42 | /** 43 | * 选择性更新 44 | * @param record 45 | * @return 46 | */ 47 | int updateByPrimaryKeySelective(Category record); 48 | 49 | /** 50 | * 更新 51 | * @param record 52 | * @return 53 | */ 54 | int updateByPrimaryKey(Category record); 55 | 56 | /** 57 | * 根据父节点id查询类别 58 | * @param parentId 59 | * @return 60 | */ 61 | List selectCategoryChildrenByParentId(Integer parentId); 62 | } -------------------------------------------------------------------------------- /src/main/resources/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/common/UserCheck.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.common; 2 | 3 | import com.mmall.common.JsonResult; 4 | import com.mmall.common.ResponseCodeEnum; 5 | import com.mmall.pojo.User; 6 | import com.mmall.util.CookieUtils; 7 | import com.mmall.util.JsonUtils; 8 | import com.mmall.util.RedisShardedPoolUtils; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.springframework.stereotype.Component; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | 14 | /** 15 | * 校验用户 16 | *

17 | * @Author LeifChen 18 | * @Date 2019-03-21 19 | */ 20 | @Component 21 | public class UserCheck { 22 | 23 | /** 24 | * @param httpServletRequest 25 | * @return 26 | */ 27 | public JsonResult checkLogin(HttpServletRequest httpServletRequest) { 28 | String loginToken = CookieUtils.readLoginToken(httpServletRequest); 29 | if (StringUtils.isEmpty(loginToken)) { 30 | return JsonResult.error("用户未登录"); 31 | } 32 | String userJsonStr = RedisShardedPoolUtils.get(loginToken); 33 | User user = JsonUtils.string2Obj(userJsonStr, User.class); 34 | if (user == null) { 35 | return JsonResult.error(ResponseCodeEnum.NEED_LOGIN.getCode(), ResponseCodeEnum.NEED_LOGIN.getDesc()); 36 | } 37 | return JsonResult.success(user); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/ShippingService.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service; 2 | 3 | import com.github.pagehelper.PageInfo; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.pojo.Shipping; 6 | 7 | /** 8 | * 收货地址Service 9 | *

10 | * @Author LeifChen 11 | * @Date 2019-03-05 12 | */ 13 | public interface ShippingService { 14 | 15 | /** 16 | * 新增 17 | * @param userId 用户id 18 | * @param shipping 收货地址信息 19 | * @return 20 | */ 21 | JsonResult add(Integer userId, Shipping shipping); 22 | 23 | /** 24 | * 修改 25 | * @param userId 用户id 26 | * @param shipping 收货地址信息 27 | * @return 28 | */ 29 | JsonResult update(Integer userId, Shipping shipping); 30 | 31 | /** 32 | * 删除 33 | * @param userId 用户id 34 | * @param shippingId 收货地址信息 35 | * @return 36 | */ 37 | JsonResult delete(Integer userId, Integer shippingId); 38 | 39 | /** 40 | * 查询 41 | * @param userId 用户id 42 | * @param shippingId 收货地址信息 43 | * @return 44 | */ 45 | JsonResult select(Integer userId, Integer shippingId); 46 | 47 | /** 48 | * 分页列表 49 | * @param userId 用户id 50 | * @param pageNum 页码 51 | * @param pageSize 每页显示数量 52 | * @return 53 | */ 54 | JsonResult list(Integer userId, int pageNum, int pageSize); 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/util/PropertiesUtils.java: -------------------------------------------------------------------------------- 1 | package com.mmall.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.nio.charset.StandardCharsets; 9 | import java.util.Properties; 10 | 11 | /** 12 | * 配置文件工具类 13 | *

14 | * @Author LeifChen 15 | * @Date 2019-02-27 16 | */ 17 | @Slf4j 18 | public class PropertiesUtils { 19 | 20 | private static Properties props; 21 | 22 | static { 23 | String fileName = "mmall.properties"; 24 | props = new Properties(); 25 | try { 26 | props.load(new InputStreamReader(PropertiesUtils.class.getClassLoader().getResourceAsStream(fileName), StandardCharsets.UTF_8)); 27 | } catch (IOException e) { 28 | log.error("配置文件读取异常", e); 29 | } 30 | } 31 | 32 | public static String getProperty(String key) { 33 | String value = props.getProperty(key.trim()); 34 | if (StringUtils.isBlank(value)) { 35 | return null; 36 | } 37 | return value.trim(); 38 | } 39 | 40 | public static String getProperty(String key, String defaultValue) { 41 | String value = props.getProperty(key.trim()); 42 | if (StringUtils.isBlank(value)) { 43 | value = defaultValue; 44 | } 45 | return value.trim(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/applicationContext-spring-session.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/common/SessionExpireFilter.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.common; 2 | 3 | import com.mmall.common.Const; 4 | import com.mmall.pojo.User; 5 | import com.mmall.util.CookieUtils; 6 | import com.mmall.util.JsonUtils; 7 | import com.mmall.util.RedisShardedPoolUtils; 8 | import org.apache.commons.lang3.StringUtils; 9 | 10 | import javax.servlet.*; 11 | import javax.servlet.http.HttpServletRequest; 12 | import java.io.IOException; 13 | 14 | /** 15 | * Session有效时间Filter 16 | *

17 | * @Author LeifChen 18 | * @Date 2019-03-21 19 | */ 20 | public class SessionExpireFilter implements Filter { 21 | 22 | @Override 23 | public void init(FilterConfig filterConfig) { 24 | 25 | } 26 | 27 | @Override 28 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 29 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 30 | String loginToken = CookieUtils.readLoginToken(httpServletRequest); 31 | if (StringUtils.isNotEmpty(loginToken)) { 32 | String userJsonStr = RedisShardedPoolUtils.get(loginToken); 33 | User user = JsonUtils.string2Obj(userJsonStr, User.class); 34 | if (user != null) { 35 | // user不为空,则重置session的有效时间 36 | RedisShardedPoolUtils.expire(loginToken, Const.RedisCacheExtime.REDIS_SESSION_EXTIME); 37 | } 38 | } 39 | chain.doFilter(request, response); 40 | } 41 | 42 | @Override 43 | public void destroy() { 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/CartService.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service; 2 | 3 | import com.mmall.common.JsonResult; 4 | import com.mmall.vo.CartVO; 5 | 6 | /** 7 | * 购物车Service 8 | *

9 | * @Author LeifChen 10 | * @Date 2019-03-01 11 | */ 12 | public interface CartService { 13 | 14 | /** 15 | * 添加商品到购物车 16 | * @param userId 用户id 17 | * @param productId 商品id 18 | * @param count 商品数量 19 | * @return 20 | */ 21 | JsonResult add(Integer userId, Integer productId, Integer count); 22 | 23 | /** 24 | * 更新购物车的商品数量 25 | * @param userId 用户id 26 | * @param productId 商品id 27 | * @param count 商品数量 28 | * @return 29 | */ 30 | JsonResult update(Integer userId, Integer productId, Integer count); 31 | 32 | /** 33 | * 根据用户id和商品id删除 34 | * @param userId 用户id 35 | * @param productIds 商品id列表 36 | * @return 37 | */ 38 | JsonResult deleteProduct(Integer userId, String productIds); 39 | 40 | /** 41 | * 根据用户id查询 42 | * @param userId 用户id 43 | * @return 44 | */ 45 | JsonResult list(Integer userId); 46 | 47 | /** 48 | * 全选/全反选商品 49 | * @param userId 用户id 50 | * @param productId 商品id 51 | * @param checked 勾选标志 52 | * @return 53 | */ 54 | JsonResult selectOrUnselect(Integer userId, Integer productId, Integer checked); 55 | 56 | /** 57 | * 返回购物车里选中商品的数量 58 | * @param userId 用户id 59 | * @return 60 | */ 61 | JsonResult getCartProductCount(Integer userId); 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/util/DateTimeUtils.java: -------------------------------------------------------------------------------- 1 | package com.mmall.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.joda.time.DateTime; 5 | import org.joda.time.format.DateTimeFormat; 6 | import org.joda.time.format.DateTimeFormatter; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * 日期转换工具类 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-02-27 15 | */ 16 | public class DateTimeUtils { 17 | 18 | public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss"; 19 | 20 | public static Date strToDate(String dateTimeStr, String formatStr) { 21 | DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(formatStr); 22 | DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr); 23 | return dateTime.toDate(); 24 | } 25 | 26 | public static String dateToStr(Date date, String formatStr) { 27 | if (date == null) { 28 | return StringUtils.EMPTY; 29 | } 30 | DateTime dateTime = new DateTime(date); 31 | return dateTime.toString(formatStr); 32 | } 33 | 34 | public static Date strToDate(String dateTimeStr) { 35 | DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(STANDARD_FORMAT); 36 | DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr); 37 | return dateTime.toDate(); 38 | } 39 | 40 | public static String dateToStr(Date date) { 41 | if (date == null) { 42 | return StringUtils.EMPTY; 43 | } 44 | DateTime dateTime = new DateTime(date); 45 | return dateTime.toString(STANDARD_FORMAT); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/util/BigDecimalUtils.java: -------------------------------------------------------------------------------- 1 | package com.mmall.util; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * 金额计算工具类 7 | *

8 | * @Author LeifChen 9 | * @Date 2019-03-01 10 | */ 11 | public class BigDecimalUtils { 12 | 13 | /** 14 | * 相加 15 | * @param v1 16 | * @param v2 17 | * @return 18 | */ 19 | public static BigDecimal add(double v1, double v2) { 20 | BigDecimal b1 = new BigDecimal(Double.toString(v1)); 21 | BigDecimal b2 = new BigDecimal(Double.toString(v2)); 22 | return b1.add(b2); 23 | } 24 | 25 | /** 26 | * 相减 27 | * @param v1 28 | * @param v2 29 | * @return 30 | */ 31 | public static BigDecimal sub(double v1, double v2) { 32 | BigDecimal b1 = new BigDecimal(Double.toString(v1)); 33 | BigDecimal b2 = new BigDecimal(Double.toString(v2)); 34 | return b1.subtract(b2); 35 | } 36 | 37 | /** 38 | * 相乘 39 | * @param v1 40 | * @param v2 41 | * @return 42 | */ 43 | public static BigDecimal mul(double v1, double v2) { 44 | BigDecimal b1 = new BigDecimal(Double.toString(v1)); 45 | BigDecimal b2 = new BigDecimal(Double.toString(v2)); 46 | return b1.multiply(b2); 47 | } 48 | 49 | /** 50 | * 相除 51 | * @param v1 52 | * @param v2 53 | * @return 54 | */ 55 | public static BigDecimal div(double v1, double v2) { 56 | BigDecimal b1 = new BigDecimal(Double.toString(v1)); 57 | BigDecimal b2 = new BigDecimal(Double.toString(v2)); 58 | // 四舍五入,保留2位小数 59 | return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/dao/ShippingMapper.java: -------------------------------------------------------------------------------- 1 | package com.mmall.dao; 2 | 3 | import com.mmall.pojo.Shipping; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 物流信息Mapper 10 | *

11 | * @Author LeifChen 12 | * @Date 2019-02-25 13 | */ 14 | public interface ShippingMapper { 15 | /** 16 | * 根据主键id删除 17 | * @param id 18 | * @return 19 | */ 20 | int deleteByPrimaryKey(Integer id); 21 | 22 | /** 23 | * 新增 24 | * @param record 25 | * @return 26 | */ 27 | int insert(Shipping record); 28 | 29 | /** 30 | * 选择性新增 31 | * @param record 32 | * @return 33 | */ 34 | int insertSelective(Shipping record); 35 | 36 | /** 37 | * 根据主键id查询 38 | * @param id 39 | * @return 40 | */ 41 | Shipping selectByPrimaryKey(Integer id); 42 | 43 | /** 44 | * 选择性更新 45 | * @param record 46 | * @return 47 | */ 48 | int updateByPrimaryKeySelective(Shipping record); 49 | 50 | /** 51 | * 更新 52 | * @param record 53 | * @return 54 | */ 55 | int updateByPrimaryKey(Shipping record); 56 | 57 | /** 58 | * 更新收货地址信息 59 | * @param shipping 收货地址信息 60 | * @return 61 | */ 62 | int updateByShipping(Shipping shipping); 63 | 64 | /** 65 | * 根据收货地址id和用户id查询 66 | * @param shippingId 收货地址id 67 | * @param userId 用户id 68 | * @return 69 | */ 70 | Shipping selectByShippingIdAndUserId(@Param("shippingId") Integer shippingId, @Param("userId") Integer userId); 71 | 72 | /** 73 | * 根据用户id查询 74 | * @param userId 用户id 75 | * @return 76 | */ 77 | List selectByUserId(Integer userId); 78 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/dao/OrderItemMapper.java: -------------------------------------------------------------------------------- 1 | package com.mmall.dao; 2 | 3 | import com.mmall.pojo.OrderItem; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 订单明细Mapper 10 | *

11 | * @Author LeifChen 12 | * @Date 2019-02-25 13 | */ 14 | public interface OrderItemMapper { 15 | /** 16 | * 根据主键id删除 17 | * @param id 18 | * @return 19 | */ 20 | int deleteByPrimaryKey(Integer id); 21 | 22 | /** 23 | * 新增 24 | * @param record 25 | * @return 26 | */ 27 | int insert(OrderItem record); 28 | 29 | /** 30 | * 选择性新增 31 | * @param record 32 | * @return 33 | */ 34 | int insertSelective(OrderItem record); 35 | 36 | /** 37 | * 根据主键id查询 38 | * @param id 39 | * @return 40 | */ 41 | OrderItem selectByPrimaryKey(Integer id); 42 | 43 | /** 44 | * 选择性更新 45 | * @param record 46 | * @return 47 | */ 48 | int updateByPrimaryKeySelective(OrderItem record); 49 | 50 | /** 51 | * 更新 52 | * @param record 53 | * @return 54 | */ 55 | int updateByPrimaryKey(OrderItem record); 56 | 57 | 58 | /** 59 | * 根据订单号和用户id查询订单明细 60 | * @param orderNo 订单号 61 | * @param userId 用户id 62 | * @return 63 | */ 64 | List getByOrderNoAndUserId(@Param("orderNo") Long orderNo, @Param("userId") Integer userId); 65 | 66 | /** 67 | * 根据订单号查询订单明细 68 | * @param orderNo 订单号 69 | * @return 70 | */ 71 | List getByOrderNo(Long orderNo); 72 | 73 | /** 74 | * 批量插入 75 | * @param orderItemList 订单商品列表 76 | */ 77 | void batchInsert(@Param("orderItemList") List orderItemList); 78 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/backend/CategoryManageController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.backend; 2 | 3 | import com.mmall.common.JsonResult; 4 | import com.mmall.service.CategoryService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * 后台管理-类别Controller 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-02-28 15 | */ 16 | @RestController 17 | @RequestMapping("/admin/category") 18 | public class CategoryManageController { 19 | 20 | @Autowired 21 | private CategoryService categoryService; 22 | 23 | @RequestMapping("/add_category.do") 24 | public JsonResult addCategory(String categoryName, @RequestParam(value = "parentId", defaultValue = "0") Integer parentId) { 25 | return categoryService.addCategory(categoryName, parentId); 26 | } 27 | 28 | @RequestMapping("/set_category_name.do") 29 | public JsonResult setCategoryName(Integer categoryId, String categoryName) { 30 | return categoryService.updateCategoryName(categoryId, categoryName); 31 | } 32 | 33 | @RequestMapping("/get_category.do") 34 | public JsonResult getChildrenParallelCategory(@RequestParam(value = "categoryId", defaultValue = "0") Integer categoryId) { 35 | return categoryService.getChildrenParallelCategory(categoryId); 36 | } 37 | 38 | @RequestMapping("/get_deep_category.do") 39 | public JsonResult getCategoryAndDeepChildrenCategory(@RequestParam(value = "categoryId", defaultValue = "0") Integer categoryId) { 40 | return categoryService.selectCategoryAndChildrenById(categoryId); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/backend/OrderManageController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.backend; 2 | 3 | import com.mmall.common.JsonResult; 4 | import com.mmall.service.OrderService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * 后台管理-订单Controller 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-03-11 15 | */ 16 | @RestController 17 | @RequestMapping("/admin/order") 18 | public class OrderManageController { 19 | 20 | @Autowired 21 | private OrderService orderService; 22 | 23 | @RequestMapping(value = "/list.do") 24 | public JsonResult list(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum, 25 | @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) { 26 | 27 | return orderService.manageList(pageNum, pageSize); 28 | } 29 | 30 | @RequestMapping(value = "/detail.do") 31 | public JsonResult detail(Long orderNo) { 32 | return orderService.manageDetail(orderNo); 33 | } 34 | 35 | @RequestMapping(value = "/search.do") 36 | public JsonResult search(Long orderNo, 37 | @RequestParam(value = "pageNum", defaultValue = "1") int pageNum, 38 | @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) { 39 | 40 | return orderService.manageSearch(orderNo, pageNum, pageSize); 41 | } 42 | 43 | @RequestMapping(value = "/send_goods.do") 44 | public JsonResult sendGoods(Long orderNo) { 45 | return orderService.manageSendGoods(orderNo); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/backend/UserManageController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.backend; 2 | 3 | import com.mmall.common.Const; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.pojo.User; 6 | import com.mmall.service.UserService; 7 | import com.mmall.util.CookieUtils; 8 | import com.mmall.util.JsonUtils; 9 | import com.mmall.util.RedisShardedPoolUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | import javax.servlet.http.HttpServletResponse; 16 | import javax.servlet.http.HttpSession; 17 | 18 | /** 19 | * 后台管理-用户Controller 20 | *

21 | * @Author LeifChen 22 | * @Date 2019-02-27 23 | */ 24 | @RestController 25 | @RequestMapping("/admin/user") 26 | public class UserManageController { 27 | 28 | @Autowired 29 | private UserService userService; 30 | 31 | @RequestMapping(value = "/login.do", method = RequestMethod.POST) 32 | public JsonResult login(String username, String password, HttpSession session, HttpServletResponse httpServletResponse) { 33 | JsonResult response = userService.login(username, password); 34 | if (response.isSuccess()) { 35 | User user = response.getData(); 36 | if (user.getRole() == Const.Role.ROLE_ADMIN) { 37 | CookieUtils.writeLoginToken(httpServletResponse, session.getId()); 38 | RedisShardedPoolUtils.setEx(session.getId(), JsonUtils.obj2String(response.getData()), Const.RedisCacheExtime.REDIS_SESSION_EXTIME); 39 | return response; 40 | } else { 41 | return JsonResult.error("不是管理员,无法登录"); 42 | } 43 | } 44 | return response; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/impl/FileServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service.impl; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.mmall.service.FileService; 5 | import com.mmall.util.FtpUtils; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.web.multipart.MultipartFile; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.util.UUID; 13 | 14 | /** 15 | * 文件Service的实现类 16 | *

17 | * @Author LeifChen 18 | * @Date 2019-02-28 19 | */ 20 | @Slf4j 21 | @Service("fileService") 22 | public class FileServiceImpl implements FileService { 23 | 24 | @Override 25 | public String upload(MultipartFile file, String path) { 26 | String fileName = file.getOriginalFilename(); 27 | String fileExtensionName = fileName.substring(fileName.lastIndexOf(".") + 1); 28 | String uploadFileName = UUID.randomUUID().toString() + "." + fileExtensionName; 29 | log.info("开始上传文件,上传文件的文件名:{},上传的路径:{},新文件名:{}", fileName, path, uploadFileName); 30 | 31 | File fileDir = new File(path); 32 | if (!fileDir.exists()) { 33 | if (!fileDir.setWritable(true)) { 34 | log.error("无法获取路径:{}的写入权限", fileDir); 35 | } 36 | if (!fileDir.mkdirs()) { 37 | log.error("文件:{}创建失败", fileDir); 38 | } 39 | } 40 | File targetFile = new File(path, uploadFileName); 41 | 42 | try { 43 | file.transferTo(targetFile); 44 | // 文件已经上传成功 45 | FtpUtils.uploadFile(Lists.newArrayList(targetFile)); 46 | // 文件已经上传到FTP服务器上 47 | if (!targetFile.delete()) { 48 | log.error("临时文件删除失败"); 49 | } 50 | } catch (IOException e) { 51 | log.error("上传文件异常", e); 52 | return null; 53 | } 54 | return targetFile.getName(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/portal/UserSessionController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.portal; 2 | 3 | import com.mmall.common.Const; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.pojo.User; 6 | import com.mmall.service.UserService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestMethod; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import javax.servlet.http.HttpSession; 13 | 14 | /** 15 | * 门户-用户Controller 16 | *

17 | * @Author LeifChen 18 | * @Date 2019-02-26 19 | */ 20 | @RestController 21 | @RequestMapping("/user/session") 22 | public class UserSessionController { 23 | 24 | @Autowired 25 | private UserService userService; 26 | 27 | @RequestMapping(value = "/login.do", method = RequestMethod.GET) 28 | public JsonResult login(String username, String password, HttpSession session) { 29 | int i = 1 / 0; 30 | 31 | JsonResult response = userService.login(username, password); 32 | if (response.isSuccess()) { 33 | session.setAttribute(Const.CURRENT_USER, response.getData()); 34 | } 35 | return response; 36 | } 37 | 38 | @RequestMapping(value = "/logout.do", method = RequestMethod.GET) 39 | public JsonResult logout(HttpSession session) { 40 | session.removeAttribute(Const.CURRENT_USER); 41 | return JsonResult.success(); 42 | } 43 | 44 | @RequestMapping(value = "/get_user_info.do", method = RequestMethod.GET) 45 | public JsonResult getUserInfo(HttpSession session) { 46 | User user = (User) session.getAttribute(Const.CURRENT_USER); 47 | if (user != null) { 48 | return JsonResult.success(user); 49 | } else { 50 | return JsonResult.error("用户未登录,无法获取当前用户信息"); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/dao/ProductMapper.java: -------------------------------------------------------------------------------- 1 | package com.mmall.dao; 2 | 3 | import com.mmall.pojo.Product; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 商品Mapper 10 | *

11 | * @Author LeifChen 12 | * @Date 2019-02-25 13 | */ 14 | public interface ProductMapper { 15 | /** 16 | * 根据主键id删除 17 | * @param id 18 | * @return 19 | */ 20 | int deleteByPrimaryKey(Integer id); 21 | 22 | /** 23 | * 新增 24 | * @param record 25 | * @return 26 | */ 27 | int insert(Product record); 28 | 29 | /** 30 | * 选择性新增 31 | * @param record 32 | * @return 33 | */ 34 | int insertSelective(Product record); 35 | 36 | /** 37 | * 根据主键id查询 38 | * @param id 39 | * @return 40 | */ 41 | Product selectByPrimaryKey(Integer id); 42 | 43 | /** 44 | * 选择性更新 45 | * @param record 46 | * @return 47 | */ 48 | int updateByPrimaryKeySelective(Product record); 49 | 50 | /** 51 | * 更新 52 | * @param record 53 | * @return 54 | */ 55 | int updateByPrimaryKey(Product record); 56 | 57 | /** 58 | * 查询商品列表 59 | * @return 60 | */ 61 | List selectList(); 62 | 63 | /** 64 | * 根据id和名称查询商品列表 65 | * @param productName 商品名称 66 | * @param productId 商品id 67 | * @return 68 | */ 69 | List selectByNameAndProductId(@Param("productName") String productName, @Param("productId") Integer productId); 70 | 71 | /** 72 | * 根据类别id和名称查询商品列表 73 | * @param productName 商品名称 74 | * @param categoryIdList 类别id列表 75 | * @return 76 | */ 77 | List selectByNameAndCategoryIds(@Param("productName") String productName, @Param("categoryIdList") List categoryIdList); 78 | 79 | /** 80 | * 根据id查询库存 81 | * @param id 商品id 82 | * @return 83 | */ 84 | Integer selectStockByProductId(Integer id); 85 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service; 2 | 3 | import com.mmall.common.JsonResult; 4 | import com.mmall.pojo.User; 5 | 6 | /** 7 | * 用户Service 8 | *

9 | * @Author LeifChen 10 | * @Date 2019-02-26 11 | */ 12 | public interface UserService { 13 | 14 | /** 15 | * 登录 16 | * @param username 17 | * @param password 18 | * @return 19 | */ 20 | JsonResult login(String username, String password); 21 | 22 | /** 23 | * 注册 24 | * @param user 25 | * @return 26 | */ 27 | JsonResult register(User user); 28 | 29 | /** 30 | * 检查参数(用户名、email)是否有效 31 | * @param str 32 | * @param type 33 | * @return 34 | */ 35 | JsonResult checkValid(String str, String type); 36 | 37 | /** 38 | * 查询找回密码的问题 39 | * @param str 40 | * @return 41 | */ 42 | JsonResult selectQuestion(String str); 43 | 44 | /** 45 | * 检验找回密码问题的答案 46 | * @param username 47 | * @param question 48 | * @param answer 49 | * @return 50 | */ 51 | JsonResult checkAnswer(String username, String question, String answer); 52 | 53 | /** 54 | * 忘记密码的重置密码 55 | * @param username 56 | * @param passwordNew 57 | * @param forgetToken 58 | * @return 59 | */ 60 | JsonResult forgetResetPassword(String username, String passwordNew, String forgetToken); 61 | 62 | /** 63 | * 登录状态的重置密码 64 | * @param passwordOld 65 | * @param passwordNew 66 | * @param user 67 | * @return 68 | */ 69 | JsonResult resetPassword(String passwordOld, String passwordNew, User user); 70 | 71 | /** 72 | * 更新用户信息 73 | * @param user 74 | * @return 75 | */ 76 | JsonResult updateInformation(User user); 77 | 78 | /** 79 | * 校验是否管理员角色 80 | * @param user 81 | * @return 82 | */ 83 | JsonResult checkAdminRole(User user); 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service; 2 | 3 | import com.github.pagehelper.PageInfo; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.pojo.Product; 6 | import com.mmall.vo.ProductDetailVO; 7 | 8 | /** 9 | * 商品Service 10 | *

11 | * @Author LeifChen 12 | * @Date 2019-02-28 13 | */ 14 | public interface ProductService { 15 | 16 | /** 17 | * 新增/修改商品 18 | * @param product 商品 19 | * @return 20 | */ 21 | JsonResult saveOrUpdateProduct(Product product); 22 | 23 | /** 24 | * 修改商品的销售状态 25 | * @param productId 商品id 26 | * @param status 商品的销售状态 27 | * @return 28 | */ 29 | JsonResult setSaleStatus(Integer productId, Integer status); 30 | 31 | /** 32 | * 管理商品详情 33 | * @param productId 商品id 34 | * @return 35 | */ 36 | JsonResult manageProductDetail(Integer productId); 37 | 38 | /** 39 | * 获取商品列表 40 | * @param pageNum 页码 41 | * @param pageSize 每页显示数量 42 | * @return 43 | */ 44 | JsonResult getProductList(int pageNum, int pageSize); 45 | 46 | /** 47 | * 检索商品 48 | * @param productName 商品名称 49 | * @param productId 商品id 50 | * @param pageNum 页码 51 | * @param pageSize 每页显示数量 52 | * @return 53 | */ 54 | JsonResult searchProduct(String productName, Integer productId, int pageNum, int pageSize); 55 | 56 | /** 57 | * 获取商品详情 58 | * @param productId 商品id 59 | * @return 60 | */ 61 | JsonResult getProductDetail(Integer productId); 62 | 63 | /** 64 | * 根据类别关键字查找商品 65 | * @param keyword 关键字 66 | * @param categoryId 类别id 67 | * @param pageNum 页码 68 | * @param pageSize 每页显示数量 69 | * @param orderBy 排序 70 | * @return 71 | */ 72 | JsonResult getProductByKeywordCategory(String keyword, Integer categoryId, int pageNum, int pageSize, String orderBy); 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/dao/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.mmall.dao; 2 | 3 | import com.mmall.pojo.Order; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 订单Mapper 10 | *

11 | * @Author LeifChen 12 | * @Date 2019-02-25 13 | */ 14 | public interface OrderMapper { 15 | /** 16 | * 根据主键id删除 17 | * @param id 18 | * @return 19 | */ 20 | int deleteByPrimaryKey(Integer id); 21 | 22 | /** 23 | * 新增 24 | * @param record 25 | * @return 26 | */ 27 | int insert(Order record); 28 | 29 | /** 30 | * 选择性新增 31 | * @param record 32 | * @return 33 | */ 34 | int insertSelective(Order record); 35 | 36 | /** 37 | * 根据主键id查询 38 | * @param id 39 | * @return 40 | */ 41 | Order selectByPrimaryKey(Integer id); 42 | 43 | /** 44 | * 选择性更新 45 | * @param record 46 | * @return 47 | */ 48 | int updateByPrimaryKeySelective(Order record); 49 | 50 | /** 51 | * 更新 52 | * @param record 53 | * @return 54 | */ 55 | int updateByPrimaryKey(Order record); 56 | 57 | /** 58 | * 根据用户id和订单号查询 59 | * @param userId 用户id 60 | * @param orderNo 订单号 61 | * @return 62 | */ 63 | Order selectByUserIdAndOrderNo(@Param("userId") Integer userId, @Param("orderNo") Long orderNo); 64 | 65 | /** 66 | * 根据用户id查询 67 | * @param userId 用户id 68 | * @return 69 | */ 70 | List selectByUserId(Integer userId); 71 | 72 | /** 73 | * 根据订单号查询 74 | * @param orderNo 订单号 75 | * @return 76 | */ 77 | Order selectByOrderNo(Long orderNo); 78 | 79 | /** 80 | * 查询所有订单 81 | * @return 82 | */ 83 | List selectAll(); 84 | 85 | /** 86 | * 根据创建时间、状态查询订单 87 | * @param status 状态 88 | * @param date 创建时间 89 | * @return 90 | */ 91 | List selectOrderStatusByCreateTime(@Param("status") Integer status, @Param("date") String date); 92 | 93 | /** 94 | * 根据id关闭订单 95 | * @param id 订单id 96 | * @return 97 | */ 98 | int closeOrderById(Integer id); 99 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/common/JsonResult.java: -------------------------------------------------------------------------------- 1 | package com.mmall.common; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import com.fasterxml.jackson.annotation.JsonInclude; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * 统一返回结果 11 | *

12 | * @Author LeifChen 13 | * @Date 2019-02-26 14 | */ 15 | @JsonInclude(value = JsonInclude.Include.NON_NULL) 16 | public class JsonResult implements Serializable { 17 | 18 | private int status; 19 | private String msg; 20 | private T data; 21 | 22 | private JsonResult(int status) { 23 | this.status = status; 24 | } 25 | 26 | private JsonResult(int status, T data) { 27 | this.status = status; 28 | this.data = data; 29 | } 30 | 31 | private JsonResult(int status, String msg, T data) { 32 | this.status = status; 33 | this.msg = msg; 34 | this.data = data; 35 | } 36 | 37 | private JsonResult(int status, String msg) { 38 | this.status = status; 39 | this.msg = msg; 40 | } 41 | 42 | @JsonIgnore 43 | public boolean isSuccess() { 44 | return this.status == ResponseCodeEnum.SUCCESS.getCode(); 45 | } 46 | 47 | public int getStatus() { 48 | return status; 49 | } 50 | 51 | public String getMsg() { 52 | return msg; 53 | } 54 | 55 | public T getData() { 56 | return data; 57 | } 58 | 59 | public static JsonResult success() { 60 | return new JsonResult<>(ResponseCodeEnum.SUCCESS.getCode()); 61 | } 62 | 63 | public static JsonResult success(String msg) { 64 | return new JsonResult<>(ResponseCodeEnum.SUCCESS.getCode(), msg); 65 | } 66 | 67 | public static JsonResult success(T data) { 68 | return new JsonResult<>(ResponseCodeEnum.SUCCESS.getCode(), data); 69 | } 70 | 71 | public static JsonResult success(String msg, T data) { 72 | return new JsonResult<>(ResponseCodeEnum.SUCCESS.getCode(), msg, data); 73 | } 74 | 75 | public static JsonResult error() { 76 | return new JsonResult<>(ResponseCodeEnum.ERROR.getCode(), ResponseCodeEnum.ERROR.getDesc()); 77 | } 78 | 79 | public static JsonResult error(String errorMessage) { 80 | return new JsonResult<>(ResponseCodeEnum.ERROR.getCode(), errorMessage); 81 | } 82 | 83 | public static JsonResult error(int errorCode, String errorMessage) { 84 | return new JsonResult<>(errorCode, errorMessage); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/dispatcher-servlet.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | text/plain;charset=UTF-8 22 | text/html;charset=UTF-8 23 | 24 | 25 | 26 | 27 | 28 | 29 | application/json;charset=UTF-8 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/dao/CartMapper.java: -------------------------------------------------------------------------------- 1 | package com.mmall.dao; 2 | 3 | import com.mmall.pojo.Cart; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 购物车Mapper 10 | *

11 | * @Author LeifChen 12 | * @Date 2019-02-25 13 | */ 14 | public interface CartMapper { 15 | /** 16 | * 根据主键id删除 17 | * @param id 18 | * @return 19 | */ 20 | int deleteByPrimaryKey(Integer id); 21 | 22 | /** 23 | * 新增 24 | * @param record 25 | * @return 26 | */ 27 | int insert(Cart record); 28 | 29 | /** 30 | * 选择性新增 31 | * @param record 32 | * @return 33 | */ 34 | int insertSelective(Cart record); 35 | 36 | /** 37 | * 根据主键id查询 38 | * @param id 39 | * @return 40 | */ 41 | Cart selectByPrimaryKey(Integer id); 42 | 43 | /** 44 | * 选择性更新 45 | * @param record 46 | * @return 47 | */ 48 | int updateByPrimaryKeySelective(Cart record); 49 | 50 | /** 51 | * 更新 52 | * @param record 53 | * @return 54 | */ 55 | int updateByPrimaryKey(Cart record); 56 | 57 | /** 58 | * 根据用户id和商品id搜索 59 | * @param userId 用户id 60 | * @param productId 商品id 61 | * @return 62 | */ 63 | Cart selectByUserIdAndProductId(@Param("userId") Integer userId, @Param("productId") Integer productId); 64 | 65 | /** 66 | * 根据用户id搜索 67 | * @param userId 用户id 68 | * @return 69 | */ 70 | List selectByUserId(Integer userId); 71 | 72 | /** 73 | * 根据用户id搜索状态为选中的商品 74 | * @param userId 用户id 75 | * @return 76 | */ 77 | int selectCheckedStatusByUserId(Integer userId); 78 | 79 | /** 80 | * 根据用户id和商品id删除 81 | * @param userId 用户id 82 | * @param productIdList 商品id列表 83 | * @return 84 | */ 85 | int deleteByUserIdAndProductIds(@Param("userId") Integer userId, @Param("productIdList") List productIdList); 86 | 87 | /** 88 | * 选择/反选商品 89 | * @param userId 用户id 90 | * @param productId 商品id 91 | * @param checked 勾选标志 92 | * @return 93 | */ 94 | int checkedOrUncheckedProduct(@Param("userId") Integer userId, @Param("productId") Integer productId, @Param("checked") Integer checked); 95 | 96 | /** 97 | * 返回购物车里选中商品的数量 98 | * @param userId 用户id 99 | * @return 100 | */ 101 | int selectCartProductCount(Integer userId); 102 | 103 | /** 104 | * 根据用户id查询购物车 105 | * @param userId 用户id 106 | * @return 107 | */ 108 | List selectCheckedCartByUserId(Integer userId); 109 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/impl/ShippingServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service.impl; 2 | 3 | import com.github.pagehelper.PageHelper; 4 | import com.github.pagehelper.PageInfo; 5 | import com.google.common.collect.Maps; 6 | import com.mmall.common.JsonResult; 7 | import com.mmall.dao.ShippingMapper; 8 | import com.mmall.pojo.Shipping; 9 | import com.mmall.service.ShippingService; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | /** 17 | * 收货地址Service的实现类 18 | *

19 | * @Author LeifChen 20 | * @Date 2019-03-05 21 | */ 22 | @Service(value = "shippingService") 23 | public class ShippingServiceImpl implements ShippingService { 24 | 25 | @Autowired 26 | private ShippingMapper shippingMapper; 27 | 28 | @Override 29 | public JsonResult add(Integer userId, Shipping shipping) { 30 | shipping.setUserId(userId); 31 | int rowCount = shippingMapper.insert(shipping); 32 | if (rowCount > 0) { 33 | Map result = Maps.newHashMap(); 34 | result.put("shippingId", shipping.getId()); 35 | return JsonResult.success("新建地址成功", result); 36 | } 37 | return JsonResult.error("新建地址失败"); 38 | } 39 | 40 | @Override 41 | public JsonResult update(Integer userId, Shipping shipping) { 42 | shipping.setUserId(userId); 43 | int rowCount = shippingMapper.updateByShipping(shipping); 44 | if (rowCount > 0) { 45 | return JsonResult.success("更新地址成功"); 46 | } 47 | return JsonResult.error("更新地址失败"); 48 | } 49 | 50 | @Override 51 | public JsonResult delete(Integer userId, Integer shippingId) { 52 | int rowCount = shippingMapper.deleteByPrimaryKey(shippingId); 53 | if (rowCount > 0) { 54 | return JsonResult.success("删除地址成功"); 55 | } 56 | return JsonResult.error("删除地址失败"); 57 | } 58 | 59 | @Override 60 | public JsonResult select(Integer userId, Integer shippingId) { 61 | Shipping shipping = shippingMapper.selectByShippingIdAndUserId(shippingId, userId); 62 | if (shipping == null) { 63 | return JsonResult.error("无法查询到该地址"); 64 | } 65 | return JsonResult.success("查询地址成功", shipping); 66 | } 67 | 68 | @Override 69 | public JsonResult list(Integer userId, int pageNum, int pageSize) { 70 | PageHelper.startPage(pageNum, pageSize); 71 | List shippingList = shippingMapper.selectByUserId(userId); 72 | PageInfo pageInfo = new PageInfo(shippingList); 73 | return JsonResult.success(pageInfo); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | Web Application 8 | 9 | 10 | characterEncodingFilter 11 | org.springframework.web.filter.CharacterEncodingFilter 12 | 13 | encoding 14 | UTF-8 15 | 16 | 17 | forceEncoding 18 | true 19 | 20 | 21 | 22 | characterEncodingFilter 23 | /* 24 | 25 | 26 | 27 | 28 | sessionExpireFilter 29 | com.mmall.controller.common.SessionExpireFilter 30 | 31 | 32 | sessionExpireFilter 33 | *.do 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.springframework.web.context.request.RequestContextListener 47 | 48 | 49 | 50 | org.springframework.web.context.ContextLoaderListener 51 | 52 | 53 | contextConfigLocation 54 | 55 | classpath:applicationContext.xml 56 | 57 | 58 | 59 | 60 | dispatcher 61 | org.springframework.web.servlet.DispatcherServlet 62 | 1 63 | 64 | 65 | dispatcher 66 | / 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/main/resources.dev/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n 6 | 7 | 8 | DEBUG 9 | 10 | 11 | 12 | 13 | d:/mmalllog/mmall.log 14 | 15 | d:/mmalllog/mmall.log.%d{yyyy-MM-dd}.gz 16 | 10 17 | 18 | 19 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n 20 | 21 | 22 | 23 | 24 | 25 | d:/mmalllog/error.log 26 | 27 | d:/mmalllog/error.log.%d{yyyy-MM-dd}.gz 28 | 10 29 | 30 | 31 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n 32 | 33 | 34 | ERROR 35 | ACCEPT 36 | DENY 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 | -------------------------------------------------------------------------------- /src/main/resources.prd/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n 6 | 7 | 8 | DEBUG 9 | 10 | 11 | 12 | 13 | d:/mmalllog/mmall.log 14 | 15 | d:/mmalllog/mmall.log.%d{yyyy-MM-dd}.gz 16 | 10 17 | 18 | 19 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n 20 | 21 | 22 | 23 | 24 | 25 | d:/mmalllog/error.log 26 | 27 | d:/mmalllog/error.log.%d{yyyy-MM-dd}.gz 28 | 10 29 | 30 | 31 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n 32 | 33 | 34 | ERROR 35 | ACCEPT 36 | DENY 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 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/dao/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.mmall.dao; 2 | 3 | import com.mmall.pojo.User; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | /** 7 | * 用户Mapper 8 | *

9 | * @Author LeifChen 10 | * @Date 2019-02-25 11 | */ 12 | public interface UserMapper { 13 | /** 14 | * 根据主键id删除 15 | * @param id 16 | * @return 17 | */ 18 | int deleteByPrimaryKey(Integer id); 19 | 20 | /** 21 | * 新增 22 | * @param record 23 | * @return 24 | */ 25 | int insert(User record); 26 | 27 | /** 28 | * 选择性新增 29 | * @param record 30 | * @return 31 | */ 32 | int insertSelective(User record); 33 | 34 | /** 35 | * 根据主键id查询 36 | * @param id 37 | * @return 38 | */ 39 | User selectByPrimaryKey(Integer id); 40 | 41 | /** 42 | * 选择性更新 43 | * @param record 44 | * @return 45 | */ 46 | int updateByPrimaryKeySelective(User record); 47 | 48 | /** 49 | * 更新 50 | * @param record 51 | * @return 52 | */ 53 | int updateByPrimaryKey(User record); 54 | 55 | /** 56 | * 检查用户名是否存在 57 | * @param username 58 | * @return 59 | */ 60 | int checkUsername(String username); 61 | 62 | /** 63 | * 检查邮箱是否存在 64 | * @param email 65 | * @return 66 | */ 67 | int checkEmail(String email); 68 | 69 | /** 70 | * 获取当前登录用户信息 71 | * @param username 72 | * @param password 73 | * @return 74 | */ 75 | User selectLogin(@Param("username") String username, @Param("password") String password); 76 | 77 | /** 78 | * 根据用户名查询找回密码的问题 79 | * @param username 80 | * @return 81 | */ 82 | String selectQuestionByUsername(String username); 83 | 84 | /** 85 | * 检验找回密码问题的答案 86 | * @param username 87 | * @param question 88 | * @param answer 89 | * @return 90 | */ 91 | int checkAnswer(@Param("username") String username, @Param("question") String question, @Param("answer") String answer); 92 | 93 | /** 94 | * 更新密码 95 | * @param username 96 | * @param passwordNew 97 | * @return 98 | */ 99 | int updatePasswordByUsername(@Param("username") String username, @Param("passwordNew") String passwordNew); 100 | 101 | /** 102 | * 校验密码 103 | * @param password 104 | * @param userId 105 | * @return 106 | */ 107 | int checkPassword(@Param("password") String password, @Param("userId") Integer userId); 108 | 109 | /** 110 | * 根据用户id校验email是否重复 111 | * @param email 112 | * @param userId 113 | * @return 114 | */ 115 | int checkEmailByUserId(@Param("email") String email, @Param("userId") Integer userId); 116 | } -------------------------------------------------------------------------------- /src/main/java/com/mmall/util/CookieUtils.java: -------------------------------------------------------------------------------- 1 | package com.mmall.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import javax.servlet.http.Cookie; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | /** 11 | * Cookie工具类 12 | *

13 | * @Author LeifChen 14 | * @Date 2019-03-20 15 | */ 16 | @Slf4j 17 | public class CookieUtils { 18 | 19 | private static final String COOKIE_DOMAIN = "mall.com"; 20 | private static final String COOKIE_NAME = "mall_login_token"; 21 | 22 | /** 23 | * 写cookie 24 | * @param response 25 | * @param token 26 | */ 27 | public static void writeLoginToken(HttpServletResponse response, String token) { 28 | Cookie cookie = new Cookie(COOKIE_NAME, token); 29 | cookie.setDomain(COOKIE_DOMAIN); 30 | // 设置在根目录 31 | cookie.setPath("/"); 32 | cookie.setHttpOnly(true); 33 | // 如果不设置,则cookie不写入硬盘,而写在内存。只在当前页面有效。 34 | cookie.setMaxAge(60 * 60 * 24 * 365); 35 | log.info("Write cookieName:{},cookieValue:{}", cookie.getName(), cookie.getValue()); 36 | response.addCookie(cookie); 37 | } 38 | 39 | /** 40 | * 读cookie 41 | * @param request 42 | * @return 43 | */ 44 | public static String readLoginToken(HttpServletRequest request) { 45 | Cookie[] cookies = request.getCookies(); 46 | if (cookies != null) { 47 | for (Cookie cookie : cookies) { 48 | log.info("Read cookieName:{},cookieValue:{}", cookie.getName(), cookie.getValue()); 49 | if (StringUtils.equals(cookie.getName(), COOKIE_NAME)) { 50 | log.info("Return cookieName:{},cookieValue:{}", cookie.getName(), cookie.getValue()); 51 | return cookie.getValue(); 52 | } 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | /** 59 | * 删除cookie 60 | * @param request 61 | * @param response 62 | */ 63 | public static void delLoginToken(HttpServletRequest request, HttpServletResponse response) { 64 | Cookie[] cookies = request.getCookies(); 65 | if (cookies != null) { 66 | for (Cookie cookie : cookies) { 67 | if (StringUtils.equals(cookie.getName(), COOKIE_NAME)) { 68 | cookie.setDomain(COOKIE_DOMAIN); 69 | cookie.setPath("/"); 70 | // 设置成0,表示删除此cookie 71 | cookie.setMaxAge(0); 72 | log.info("Delete cookieName:{},cookieValue:{}", cookie.getName(), cookie.getValue()); 73 | response.addCookie(cookie); 74 | return; 75 | } 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/portal/ProductController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.portal; 2 | 3 | import com.github.pagehelper.PageInfo; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.service.ProductService; 6 | import com.mmall.vo.ProductDetailVO; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | /** 12 | * 商品Controller 13 | *

14 | * @Author LeifChen 15 | * @Date 2019-03-01 16 | */ 17 | @RestController 18 | @RequestMapping("/product") 19 | public class ProductController { 20 | 21 | @Autowired 22 | private ProductService productService; 23 | 24 | @RequestMapping("/detail.do") 25 | public JsonResult detail(Integer productId) { 26 | return productService.getProductDetail(productId); 27 | } 28 | 29 | @RequestMapping(value = "/{productId}", method = RequestMethod.GET) 30 | public JsonResult detailRESTful(@PathVariable Integer productId) { 31 | return productService.getProductDetail(productId); 32 | } 33 | 34 | @RequestMapping("/list.do") 35 | public JsonResult list(@RequestParam(value = "keyword", required = false) String keyword, 36 | @RequestParam(value = "categoryId", required = false) Integer categoryId, 37 | @RequestParam(value = "pageNum", defaultValue = "1") int pageNum, 38 | @RequestParam(value = "pageSize", defaultValue = "10") int pageSize, 39 | @RequestParam(value = "orderBy", defaultValue = "") String orderBy) { 40 | 41 | return productService.getProductByKeywordCategory(keyword, categoryId, pageNum, pageSize, orderBy); 42 | } 43 | 44 | @RequestMapping(value = "/{keyword}/{categoryId}/{pageNum}/{pageSize}/{orderBy}", method = RequestMethod.GET) 45 | public JsonResult listRESTful(@PathVariable(value = "keyword") String keyword, 46 | @PathVariable(value = "categoryId") Integer categoryId, 47 | @PathVariable(value = "pageNum") Integer pageNum, 48 | @PathVariable(value = "pageSize") Integer pageSize, 49 | @PathVariable(value = "orderBy") String orderBy) { 50 | 51 | if (pageNum == null) { 52 | pageNum = 1; 53 | } 54 | if (pageSize == null) { 55 | pageSize = 10; 56 | } 57 | if (StringUtils.isBlank(orderBy)) { 58 | orderBy = "price_asc"; 59 | } 60 | return productService.getProductByKeywordCategory(keyword, categoryId, pageNum, pageSize, orderBy); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/common/RedisShardedPool.java: -------------------------------------------------------------------------------- 1 | package com.mmall.common; 2 | 3 | import com.mmall.util.PropertiesUtils; 4 | import redis.clients.jedis.JedisPoolConfig; 5 | import redis.clients.jedis.JedisShardInfo; 6 | import redis.clients.jedis.ShardedJedis; 7 | import redis.clients.jedis.ShardedJedisPool; 8 | import redis.clients.util.Hashing; 9 | import redis.clients.util.Sharded; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * Redis连接池 16 | *

17 | * @Author LeifChen 18 | * @Date 2019-03-19 19 | */ 20 | public class RedisShardedPool { 21 | 22 | private static ShardedJedisPool pool; 23 | private static Integer maxTotal = Integer.parseInt(PropertiesUtils.getProperty("redis.max.total", "20")); 24 | private static Integer maxIdle = Integer.parseInt(PropertiesUtils.getProperty("redis.max.idle", "10")); 25 | private static Integer minIdle = Integer.parseInt(PropertiesUtils.getProperty("redis.min.idle", "2")); 26 | private static Boolean testOnBorrow = Boolean.parseBoolean(PropertiesUtils.getProperty("redis.test.borrow", "true")); 27 | private static Boolean testOnReturn = Boolean.parseBoolean(PropertiesUtils.getProperty("redis.test.return", "true")); 28 | private static String redis1Ip = PropertiesUtils.getProperty("redis1.ip"); 29 | private static Integer redis1Port = Integer.parseInt(PropertiesUtils.getProperty("redis1.port", "6379")); 30 | private static String redis2Ip = PropertiesUtils.getProperty("redis2.ip"); 31 | private static Integer redis2Port = Integer.parseInt(PropertiesUtils.getProperty("redis2.port", "6380")); 32 | 33 | private static void initPool() { 34 | JedisPoolConfig config = new JedisPoolConfig(); 35 | config.setMaxTotal(maxTotal); 36 | config.setMaxIdle(maxIdle); 37 | config.setMinIdle(minIdle); 38 | config.setTestOnBorrow(testOnBorrow); 39 | config.setTestOnReturn(testOnReturn); 40 | // 连接耗尽时,是否阻塞,false会抛出异常,true阻塞直到超时。默认true 41 | config.setBlockWhenExhausted(true); 42 | 43 | JedisShardInfo info1 = new JedisShardInfo(redis1Ip, redis1Port, 1000 * 2); 44 | JedisShardInfo info2 = new JedisShardInfo(redis2Ip, redis2Port, 1000 * 2); 45 | List jedisShardInfoList = new ArrayList<>(2); 46 | jedisShardInfoList.add(info1); 47 | jedisShardInfoList.add(info2); 48 | pool = new ShardedJedisPool(config, jedisShardInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN); 49 | } 50 | 51 | static { 52 | initPool(); 53 | } 54 | 55 | public static ShardedJedis getJedis() { 56 | return pool.getResource(); 57 | } 58 | 59 | public static void returnBrokenResource(ShardedJedis jedis) { 60 | pool.returnBrokenResource(jedis); 61 | } 62 | 63 | public static void returnResource(ShardedJedis jedis) { 64 | pool.returnResource(jedis); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service; 2 | 3 | import com.github.pagehelper.PageInfo; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.vo.OrderVO; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * 订单Service 11 | *

12 | * @Author LeifChen 13 | * @Date 2019-03-08 14 | */ 15 | public interface OrderService { 16 | 17 | /** 18 | * 创建订单 19 | * @param userId 用户id 20 | * @param shippingId 收货地址id 21 | * @return 22 | */ 23 | JsonResult create(Integer userId, Integer shippingId); 24 | 25 | /** 26 | * 取消订单 27 | * @param userId 用户id 28 | * @param orderNo 订单号 29 | * @return 30 | */ 31 | JsonResult cancel(Integer userId, Long orderNo); 32 | 33 | /** 34 | * 获取订单的购物车商品明细 35 | * @param userId 用户id 36 | * @return 37 | */ 38 | JsonResult getOrderCartProduct(Integer userId); 39 | 40 | /** 41 | * 普通用户查看订单明细 42 | * @param userId 用户id 43 | * @param orderNo 订单号 44 | * @return 45 | */ 46 | JsonResult getOrderDetail(Integer userId, Long orderNo); 47 | 48 | /** 49 | * 普通用户查看订单列表 50 | * @param userId 用户id 51 | * @param pageNum 页码 52 | * @param pageSize 每页显示数量 53 | * @return 54 | */ 55 | JsonResult getOrderList(Integer userId, int pageNum, int pageSize); 56 | 57 | /** 58 | * 管理员查看订单列表 59 | * @param pageNum 页码 60 | * @param pageSize 每页显示数量 61 | * @return 62 | */ 63 | JsonResult manageList(int pageNum, int pageSize); 64 | 65 | /** 66 | * 管理员查看订单明细 67 | * @param orderNo 订单号 68 | * @return 69 | */ 70 | JsonResult manageDetail(Long orderNo); 71 | 72 | /** 73 | * 管理员搜索订单号 74 | * @param orderNo 订单号 75 | * @param pageNum 页码 76 | * @param pageSize 每页显示数量 77 | * @return 78 | */ 79 | JsonResult manageSearch(Long orderNo, int pageNum, int pageSize); 80 | 81 | /** 82 | * 根据订单号发货 83 | * @param orderNo 订单号 84 | * @return 85 | */ 86 | JsonResult manageSendGoods(Long orderNo); 87 | 88 | /** 89 | * 付款 90 | * @param orderNo 订单号 91 | * @param userId 用户id 92 | * @param path 二维码路径 93 | * @return 94 | */ 95 | JsonResult pay(Long orderNo, Integer userId, String path); 96 | 97 | /** 98 | * 支付宝回调 99 | * @param params 100 | * @return 101 | */ 102 | JsonResult alipayCallback(Map params); 103 | 104 | /** 105 | * 查询订单支付状态 106 | * @param userId 用户id 107 | * @param orderNo 订单号 108 | * @return 109 | */ 110 | JsonResult queryOrderPayStatus(Integer userId, Long orderNo); 111 | 112 | /** 113 | * 关闭订单 114 | * @param hour 超时时间 115 | */ 116 | void closeOrder(int hour); 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/util/FtpUtils.java: -------------------------------------------------------------------------------- 1 | package com.mmall.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.commons.net.ftp.FTPClient; 5 | 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.IOException; 9 | import java.util.List; 10 | 11 | /** 12 | * 配置文件工具类 13 | *

14 | * @Author LeifChen 15 | * @Date 2019-02-28 16 | */ 17 | @Slf4j 18 | public class FtpUtils { 19 | 20 | private static String ftpIp = PropertiesUtils.getProperty("ftp.server.ip"); 21 | private static String ftpUser = PropertiesUtils.getProperty("ftp.user"); 22 | private static String ftpPassword = PropertiesUtils.getProperty("ftp.password"); 23 | 24 | private String ip; 25 | private String user; 26 | private String pwd; 27 | private FTPClient ftpClient; 28 | 29 | private FtpUtils(String ip, String user, String pwd) { 30 | this.ip = ip; 31 | this.user = user; 32 | this.pwd = pwd; 33 | } 34 | 35 | public static void uploadFile(List fileList) throws IOException { 36 | FtpUtils ftpUtils = new FtpUtils(ftpIp, ftpUser, ftpPassword); 37 | log.info("开始连接ftp服务器"); 38 | String remotePath = "img"; 39 | ftpUtils.uploadFile(remotePath, fileList); 40 | log.info("开始连接ftp服务器,结束上传,上传结果:{}"); 41 | } 42 | 43 | /** 44 | * 上传文件到FTP服务器的指定位置 45 | * @param remotePath 远程服务器指定位置 46 | * @param fileList 文件列表 47 | * @return 48 | * @throws IOException 49 | */ 50 | private void uploadFile(String remotePath, List fileList) throws IOException { 51 | // 连接FTP服务器 52 | if (connectServer(ip, user, pwd)) { 53 | try { 54 | ftpClient.changeWorkingDirectory(remotePath); 55 | ftpClient.setBufferSize(1024); 56 | ftpClient.setControlEncoding("UTF-8"); 57 | ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 58 | ftpClient.enterLocalPassiveMode(); 59 | for (File fileItem : fileList) { 60 | FileInputStream fis = new FileInputStream(fileItem); 61 | ftpClient.storeFile(fileItem.getName(), fis); 62 | } 63 | } catch (IOException e) { 64 | log.error("上传文件异常", e); 65 | } finally { 66 | ftpClient.disconnect(); 67 | } 68 | } 69 | } 70 | 71 | /** 72 | * 连接FTP服务 73 | * @param ip FTP的IP 74 | * @param user FTP的用户 75 | * @param pwd FTP的密码 76 | * @return 77 | */ 78 | private boolean connectServer(String ip, String user, String pwd) { 79 | boolean isSuccess = false; 80 | ftpClient = new FTPClient(); 81 | try { 82 | ftpClient.connect(ip); 83 | isSuccess = ftpClient.login(user, pwd); 84 | } catch (IOException e) { 85 | log.error("连接FTP服务器异常", e); 86 | } 87 | return isSuccess; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/portal/ShippingController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.portal; 2 | 3 | import com.mmall.common.JsonResult; 4 | import com.mmall.controller.common.UserCheck; 5 | import com.mmall.pojo.Shipping; 6 | import com.mmall.pojo.User; 7 | import com.mmall.service.ShippingService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | 15 | /** 16 | * 收货地址Controller 17 | *

18 | * @Author LeifChen 19 | * @Date 2019-03-05 20 | */ 21 | @RestController 22 | @RequestMapping("/shipping") 23 | public class ShippingController { 24 | 25 | @Autowired 26 | private ShippingService shippingService; 27 | @Autowired 28 | private UserCheck userCheck; 29 | 30 | @RequestMapping(value = "/add.do") 31 | public JsonResult add(HttpServletRequest httpServletRequest, Shipping shipping) { 32 | JsonResult response = userCheck.checkLogin(httpServletRequest); 33 | if (response.isSuccess()) { 34 | User user = (User) response.getData(); 35 | return shippingService.add(user.getId(), shipping); 36 | } else { 37 | return response; 38 | } 39 | } 40 | 41 | @RequestMapping(value = "/update.do") 42 | public JsonResult update(HttpServletRequest httpServletRequest, Shipping shipping) { 43 | JsonResult response = userCheck.checkLogin(httpServletRequest); 44 | if (response.isSuccess()) { 45 | User user = (User) response.getData(); 46 | return shippingService.update(user.getId(), shipping); 47 | } else { 48 | return response; 49 | } 50 | } 51 | 52 | @RequestMapping(value = "/delete.do") 53 | public JsonResult delete(HttpServletRequest httpServletRequest, Integer shippingId) { 54 | JsonResult response = userCheck.checkLogin(httpServletRequest); 55 | if (response.isSuccess()) { 56 | User user = (User) response.getData(); 57 | return shippingService.delete(user.getId(), shippingId); 58 | } else { 59 | return response; 60 | } 61 | } 62 | 63 | @RequestMapping(value = "/select.do") 64 | public JsonResult select(HttpServletRequest httpServletRequest, Integer shippingId) { 65 | JsonResult response = userCheck.checkLogin(httpServletRequest); 66 | if (response.isSuccess()) { 67 | User user = (User) response.getData(); 68 | return shippingService.select(user.getId(), shippingId); 69 | } else { 70 | return response; 71 | } 72 | } 73 | 74 | @RequestMapping(value = "/list.do") 75 | public JsonResult list(HttpServletRequest httpServletRequest, 76 | @RequestParam(value = "pageNum", defaultValue = "1") int pageNum, 77 | @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) { 78 | 79 | JsonResult response = userCheck.checkLogin(httpServletRequest); 80 | if (response.isSuccess()) { 81 | User user = (User) response.getData(); 82 | return shippingService.list(user.getId(), pageNum, pageSize); 83 | } else { 84 | return response; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/resources.dev/zfbinfo.properties: -------------------------------------------------------------------------------- 1 | # DEV 2 | 3 | # \u652F\u4ED8\u5B9D\u7F51\u5173\u540D\u3001partnerId\u548CappId 4 | open_api_domain = https://openapi.alipaydev.com/gateway.do 5 | mcloud_api_domain = http://mcloudmonitor.com/gateway.do 6 | pid = 2088102177227085 7 | appid = 2016092500594218 8 | 9 | # RSA\u79C1\u94A5\u3001\u516C\u94A5\u548C\u652F\u4ED8\u5B9D\u516C\u94A5 10 | private_key = MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQKN/eyObNK5ZMlVxGZS1P4kHEK5fVFkNvel255kzQN+aVvnPYlcOuAepY0afs1CSEkAlnmS9Qy60xGYTeOVRfaxgAOaUp7T7VpQ31eD/7q2pJzKMQ1MigisHyJWnEVQLKNvFS2AAL5dFyP9Ww2osykY4QU9soym9ZVMeT/p+f2V4NvNoBA6LBQoSanRnX8UNYHaUdSNxxTOhzze5/DkTQkf4rVpmYxb7SVEGF3ocAD8Q4X4zOpxGs8odUI6kt6EaY49vnWH9RftRsfBOZSaUK9r/O1GtWOSoeKsZGo745WJXGhJM5BEhEsxCQPVlMx+2qgA+SnO5e8ZbFhAdiUOtjAgMBAAECggEAVZR4dd+jBDcnU9UUWty+BFnBMCW8Bp9gmjR01Dka24AgDPCAMEtiZ+fhsSKBJ50QZm/RbgZMrasPSWB0f+iSB6i/9Ve9z776VlvFoWYO6ClRSYYYhJL26QojMqqvEUjiHMD59lVXr4yMz6vu7wbqs5+kCJJxSBPyM4fnhbDpb43whwiUfUbIG83N2fiYvuP8DCKIxSckyL1UAoZQAczc2D81Pyj0OUv0lVOnN1n0fWtohYnasu+FOm4ous98Yd2Sdq0M7cRbJzt03NRcscV9Sryh9RP4e/tKIfjIeR0uDzh0R7p87BBwvJCH80lI3yzT9iV/9pFEBpGIHqZh+CJgAQKBgQDqW9bHZMpHfTUCj+gxTzBtDqBNr/xzbOXf4Cxjm9b2KrkpBoy7ozxECIUPB3mRwWUculoicH1XQb7eL3BzZI9xh9fI/vSvJlwjDO7JN4bXdeBL8u5gz2kEkFnWsnNS2430NbVgsRoHtNduGXhmC6c8T3r62z1Udy/GsvWH416zwQKBgQDjYbK7mYha7+4ZrtNwN01ZyEl02HkCZ82Gcyckp1mtJ7VvnErmJZLF358xLEsAk36DJpZweqU9+QDbOXLWdS+YEQ1BeY5LMZwKh5jn0LbNbZ7YU8kHVazR+DOmIrqwQ+Lrv8uBNun6gnfeBOU2+Xj8bLdXVoaRxhurIVETk5RYIwKBgBArqhQ0BikMoJ2+pDzSw/qiabkyjW7BctMRur5cwGZX6FLGWuuPhdcD53pz/5VpDLsAuLtrm5prtOnLyCyOIb+pqd/6h5OWSAE7ITbNGAbB4WocJwqTBSIFe81unrp238Kb+hnj3nHtrnewVjhkUXO94DRy8DZlyuwg6QQpUh2BAoGBALkFtrqQpDPbKJQdfk/BsF9uatd5jn42mTbeXOumgYI03Z6EPy4nRNder9sDf8RoQHnX3HKKWgujot7AUIHRuXiz52Vv1Cm7pI2s6O85FobyvF6rTtl5DbeNj/mQKPllRDExUBdE5//ASmmO8jVZquk8TbPz5GyaF8mYwrB7ViqhAoGBAOCPNPTwVLftBSYsnmVXu1AskuJalLBXIEFtrGgItiZ3ElTEPdRUJngKzLep1ShNSnPEvUifcF5tU/v86YQTGtxwZr152lzxXWvbOQc8lozFSFOJ8KJ3gMyCy2vKbes0cRPeZe4qLwGna0dDfGH+OdX2ENbP3TPT2qMpPCB1+ZM7 11 | public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Cjf3sjmzSuWTJVcRmUtT+JBxCuX1RZDb3pdueZM0Dfmlb5z2JXDrgHqWNGn7NQkhJAJZ5kvUMutMRmE3jlUX2sYADmlKe0+1aUN9Xg/+6tqScyjENTIoIrB8iVpxFUCyjbxUtgAC+XRcj/VsNqLMpGOEFPbKMpvWVTHk/6fn9leDbzaAQOiwUKEmp0Z1/FDWB2lHUjccUzoc83ufw5E0JH+K1aZmMW+0lRBhd6HAA/EOF+MzqcRrPKHVCOpLehGmOPb51h/UX7UbHwTmUmlCva/ztRrVjkqHirGRqO+OViVxoSTOQRIRLMQkD1ZTMftqoAPkpzuXvGWxYQHYlDrYwIDAQAB 12 | 13 | #SHA1withRsa\u5BF9\u5E94\u652F\u4ED8\u5B9D\u516C\u94A5 14 | #alipay_public_key = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB 15 | 16 | #SHA256withRsa\u5BF9\u5E94\u652F\u4ED8\u5B9D\u516C\u94A5 17 | alipay_public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApMHctorXLLPMhoXC7zwCADlwI+qdwSXBLex1+GcKWYOfglYB5x66hx0rjM7ccxK1kMy5wZwqrd8Wj/A45jzLqOiXTBdaundm/5Oru7yHuB6lpZxBl+UUmdh6LlAKNr04HLSNtZtD3P5uNCSWQERgUpvJJdepMUvQmxibdZqatBes2EESP8b2PqfvkffHMy9Az4eioWki3SNXYwmxXcUwdKoVUeCsniuJpnigEEt6rZWPKcQEoHVKotpEeR8wlLJ4jhALWe7SqDt1tqqYDeVvgItdVqFinOSxQZRccXklPh34ycuOxHdM0Sx2Cgk3XUCNMKYihXrwz7DDghzL5o53AwIDAQAB 18 | 19 | # \u7B7E\u540D\u7C7B\u578B: RSA->SHA1withRsa,RSA2->SHA256withRsa 20 | sign_type = RSA2 21 | # \u5F53\u9762\u4ED8\u6700\u5927\u67E5\u8BE2\u6B21\u6570\u548C\u67E5\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09 22 | max_query_retry = 5 23 | query_duration = 5000 24 | 25 | # \u5F53\u9762\u4ED8\u6700\u5927\u64A4\u9500\u6B21\u6570\u548C\u64A4\u9500\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09 26 | max_cancel_retry = 3 27 | cancel_duration = 2000 28 | 29 | # \u4EA4\u6613\u4FDD\u969C\u7EBF\u7A0B\u7B2C\u4E00\u6B21\u8C03\u5EA6\u5EF6\u8FDF\u548C\u8C03\u5EA6\u95F4\u9694\uFF08\u79D2\uFF09 30 | heartbeat_delay = 5 31 | heartbeat_duration = 900 32 | -------------------------------------------------------------------------------- /src/main/resources.prd/zfbinfo.properties: -------------------------------------------------------------------------------- 1 | # PRD 2 | 3 | # \u652F\u4ED8\u5B9D\u7F51\u5173\u540D\u3001partnerId\u548CappId 4 | open_api_domain = https://openapi.alipaydev.com/gateway.do 5 | mcloud_api_domain = http://mcloudmonitor.com/gateway.do 6 | pid = 2088102177227085 7 | appid = 2016092500594218 8 | 9 | # RSA\u79C1\u94A5\u3001\u516C\u94A5\u548C\u652F\u4ED8\u5B9D\u516C\u94A5 10 | private_key = MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQKN/eyObNK5ZMlVxGZS1P4kHEK5fVFkNvel255kzQN+aVvnPYlcOuAepY0afs1CSEkAlnmS9Qy60xGYTeOVRfaxgAOaUp7T7VpQ31eD/7q2pJzKMQ1MigisHyJWnEVQLKNvFS2AAL5dFyP9Ww2osykY4QU9soym9ZVMeT/p+f2V4NvNoBA6LBQoSanRnX8UNYHaUdSNxxTOhzze5/DkTQkf4rVpmYxb7SVEGF3ocAD8Q4X4zOpxGs8odUI6kt6EaY49vnWH9RftRsfBOZSaUK9r/O1GtWOSoeKsZGo745WJXGhJM5BEhEsxCQPVlMx+2qgA+SnO5e8ZbFhAdiUOtjAgMBAAECggEAVZR4dd+jBDcnU9UUWty+BFnBMCW8Bp9gmjR01Dka24AgDPCAMEtiZ+fhsSKBJ50QZm/RbgZMrasPSWB0f+iSB6i/9Ve9z776VlvFoWYO6ClRSYYYhJL26QojMqqvEUjiHMD59lVXr4yMz6vu7wbqs5+kCJJxSBPyM4fnhbDpb43whwiUfUbIG83N2fiYvuP8DCKIxSckyL1UAoZQAczc2D81Pyj0OUv0lVOnN1n0fWtohYnasu+FOm4ous98Yd2Sdq0M7cRbJzt03NRcscV9Sryh9RP4e/tKIfjIeR0uDzh0R7p87BBwvJCH80lI3yzT9iV/9pFEBpGIHqZh+CJgAQKBgQDqW9bHZMpHfTUCj+gxTzBtDqBNr/xzbOXf4Cxjm9b2KrkpBoy7ozxECIUPB3mRwWUculoicH1XQb7eL3BzZI9xh9fI/vSvJlwjDO7JN4bXdeBL8u5gz2kEkFnWsnNS2430NbVgsRoHtNduGXhmC6c8T3r62z1Udy/GsvWH416zwQKBgQDjYbK7mYha7+4ZrtNwN01ZyEl02HkCZ82Gcyckp1mtJ7VvnErmJZLF358xLEsAk36DJpZweqU9+QDbOXLWdS+YEQ1BeY5LMZwKh5jn0LbNbZ7YU8kHVazR+DOmIrqwQ+Lrv8uBNun6gnfeBOU2+Xj8bLdXVoaRxhurIVETk5RYIwKBgBArqhQ0BikMoJ2+pDzSw/qiabkyjW7BctMRur5cwGZX6FLGWuuPhdcD53pz/5VpDLsAuLtrm5prtOnLyCyOIb+pqd/6h5OWSAE7ITbNGAbB4WocJwqTBSIFe81unrp238Kb+hnj3nHtrnewVjhkUXO94DRy8DZlyuwg6QQpUh2BAoGBALkFtrqQpDPbKJQdfk/BsF9uatd5jn42mTbeXOumgYI03Z6EPy4nRNder9sDf8RoQHnX3HKKWgujot7AUIHRuXiz52Vv1Cm7pI2s6O85FobyvF6rTtl5DbeNj/mQKPllRDExUBdE5//ASmmO8jVZquk8TbPz5GyaF8mYwrB7ViqhAoGBAOCPNPTwVLftBSYsnmVXu1AskuJalLBXIEFtrGgItiZ3ElTEPdRUJngKzLep1ShNSnPEvUifcF5tU/v86YQTGtxwZr152lzxXWvbOQc8lozFSFOJ8KJ3gMyCy2vKbes0cRPeZe4qLwGna0dDfGH+OdX2ENbP3TPT2qMpPCB1+ZM7 11 | public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Cjf3sjmzSuWTJVcRmUtT+JBxCuX1RZDb3pdueZM0Dfmlb5z2JXDrgHqWNGn7NQkhJAJZ5kvUMutMRmE3jlUX2sYADmlKe0+1aUN9Xg/+6tqScyjENTIoIrB8iVpxFUCyjbxUtgAC+XRcj/VsNqLMpGOEFPbKMpvWVTHk/6fn9leDbzaAQOiwUKEmp0Z1/FDWB2lHUjccUzoc83ufw5E0JH+K1aZmMW+0lRBhd6HAA/EOF+MzqcRrPKHVCOpLehGmOPb51h/UX7UbHwTmUmlCva/ztRrVjkqHirGRqO+OViVxoSTOQRIRLMQkD1ZTMftqoAPkpzuXvGWxYQHYlDrYwIDAQAB 12 | 13 | #SHA1withRsa\u5BF9\u5E94\u652F\u4ED8\u5B9D\u516C\u94A5 14 | #alipay_public_key = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB 15 | 16 | #SHA256withRsa\u5BF9\u5E94\u652F\u4ED8\u5B9D\u516C\u94A5 17 | alipay_public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApMHctorXLLPMhoXC7zwCADlwI+qdwSXBLex1+GcKWYOfglYB5x66hx0rjM7ccxK1kMy5wZwqrd8Wj/A45jzLqOiXTBdaundm/5Oru7yHuB6lpZxBl+UUmdh6LlAKNr04HLSNtZtD3P5uNCSWQERgUpvJJdepMUvQmxibdZqatBes2EESP8b2PqfvkffHMy9Az4eioWki3SNXYwmxXcUwdKoVUeCsniuJpnigEEt6rZWPKcQEoHVKotpEeR8wlLJ4jhALWe7SqDt1tqqYDeVvgItdVqFinOSxQZRccXklPh34ycuOxHdM0Sx2Cgk3XUCNMKYihXrwz7DDghzL5o53AwIDAQAB 18 | 19 | # \u7B7E\u540D\u7C7B\u578B: RSA->SHA1withRsa,RSA2->SHA256withRsa 20 | sign_type = RSA2 21 | # \u5F53\u9762\u4ED8\u6700\u5927\u67E5\u8BE2\u6B21\u6570\u548C\u67E5\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09 22 | max_query_retry = 5 23 | query_duration = 5000 24 | 25 | # \u5F53\u9762\u4ED8\u6700\u5927\u64A4\u9500\u6B21\u6570\u548C\u64A4\u9500\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09 26 | max_cancel_retry = 3 27 | cancel_duration = 2000 28 | 29 | # \u4EA4\u6613\u4FDD\u969C\u7EBF\u7A0B\u7B2C\u4E00\u6B21\u8C03\u5EA6\u5EF6\u8FDF\u548C\u8C03\u5EA6\u95F4\u9694\uFF08\u79D2\uFF09 30 | heartbeat_delay = 5 31 | heartbeat_duration = 900 32 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/impl/CategoryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service.impl; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.google.common.collect.Sets; 5 | import com.mmall.common.JsonResult; 6 | import com.mmall.dao.CategoryMapper; 7 | import com.mmall.pojo.Category; 8 | import com.mmall.service.CategoryService; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.apache.commons.collections.CollectionUtils; 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.List; 16 | import java.util.Set; 17 | 18 | /** 19 | * 类别Service的实现类 20 | *

21 | * @Author LeifChen 22 | * @Date 2019-02-28 23 | */ 24 | @Slf4j 25 | @Service("categoryService") 26 | public class CategoryServiceImpl implements CategoryService { 27 | 28 | @Autowired 29 | private CategoryMapper categoryMapper; 30 | 31 | @Override 32 | public JsonResult addCategory(String categoryName, Integer parentId) { 33 | if (parentId == null || StringUtils.isBlank(categoryName)) { 34 | return JsonResult.error("添加类别参数错误"); 35 | } 36 | 37 | Category category = new Category(); 38 | category.setName(categoryName); 39 | category.setParentId(parentId); 40 | category.setStatus(true); 41 | 42 | int rowCount = categoryMapper.insert(category); 43 | if (rowCount > 0) { 44 | return JsonResult.success("添加类别成功"); 45 | } 46 | return JsonResult.error("添加类别失败"); 47 | } 48 | 49 | @Override 50 | public JsonResult updateCategoryName(Integer categoryId, String categoryName) { 51 | if (categoryId == null || StringUtils.isBlank(categoryName)) { 52 | return JsonResult.error("更新类别参数错误"); 53 | } 54 | 55 | Category category = new Category(); 56 | category.setId(categoryId); 57 | category.setName(categoryName); 58 | 59 | int rowCount = categoryMapper.updateByPrimaryKeySelective(category); 60 | if (rowCount > 0) { 61 | return JsonResult.success("更新类别名称成功"); 62 | } 63 | return JsonResult.error("更新类别名称失败"); 64 | } 65 | 66 | @Override 67 | public JsonResult> getChildrenParallelCategory(Integer categoryId) { 68 | List categoryList = categoryMapper.selectCategoryChildrenByParentId(categoryId); 69 | if (CollectionUtils.isEmpty(categoryList)) { 70 | log.info("未找到当前分类的子分类"); 71 | } 72 | return JsonResult.success(categoryList); 73 | } 74 | 75 | @Override 76 | public JsonResult> selectCategoryAndChildrenById(Integer categoryId) { 77 | Set categorySet = Sets.newHashSet(); 78 | findChildCategory(categorySet, categoryId); 79 | 80 | List categoryIdList = Lists.newArrayList(); 81 | if (categoryId != null) { 82 | categorySet.forEach(categoryItem -> categoryIdList.add(categoryItem.getId())); 83 | } 84 | return JsonResult.success(categoryIdList); 85 | } 86 | 87 | /** 88 | * 算出子节点:递归算法 89 | * @param categoryId 90 | * @return 91 | */ 92 | private void findChildCategory(Set categorySet, Integer categoryId) { 93 | Category category = categoryMapper.selectByPrimaryKey(categoryId); 94 | if (category != null) { 95 | categorySet.add(category); 96 | } 97 | // 查找子节点,递归算法一定要有一个退出的条件 98 | List categoryList = categoryMapper.selectCategoryChildrenByParentId(categoryId); 99 | categoryList.forEach(categoryItem -> findChildCategory(categorySet, categoryItem.getId())); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/resources/applicationContext-datasource.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | classpath:datasource.properties 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 | dialect=mysql 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/task/CloseOrderTask.java: -------------------------------------------------------------------------------- 1 | package com.mmall.task; 2 | 3 | import com.mmall.common.Const; 4 | import com.mmall.common.RedissonManager; 5 | import com.mmall.service.OrderService; 6 | import com.mmall.util.PropertiesUtils; 7 | import com.mmall.util.RedisShardedPoolUtils; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.redisson.api.RLock; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.scheduling.annotation.Scheduled; 13 | import org.springframework.stereotype.Component; 14 | 15 | import java.util.concurrent.TimeUnit; 16 | 17 | /** 18 | * 关闭订单任务 19 | *

20 | * @Author LeifChen 21 | * @Date 2019-03-27 22 | */ 23 | @Slf4j 24 | @Component 25 | public class CloseOrderTask { 26 | 27 | public static final int WAIT_TIME = 0; 28 | public static final int LEASE_TIME = 5; 29 | 30 | @Autowired 31 | private OrderService orderService; 32 | @Autowired 33 | private RedissonManager redissonManager; 34 | 35 | @Scheduled(cron = "0 */1 * * * ?") 36 | public void closeOrderTask() { 37 | log.info("关闭订单定时任务启动"); 38 | long lockTimeout = Long.parseLong(PropertiesUtils.getProperty("lock.timeout", "5000")); 39 | Long setnxResult = RedisShardedPoolUtils.setnx(Const.RedisLock.CLOSE_ORDER_TASK_LOCK, String.valueOf(System.currentTimeMillis() + lockTimeout)); 40 | if (setnxResult != null && setnxResult.intValue() == 1) { 41 | // 返回值是1,代表设置成功,获取锁 42 | closeOrder(); 43 | } else { 44 | // 未获取到锁,继续判断时间戳,看是否可以重置并获取到锁 45 | String lockValueStr = RedisShardedPoolUtils.get(Const.RedisLock.CLOSE_ORDER_TASK_LOCK); 46 | if (lockValueStr != null && System.currentTimeMillis() > Long.parseLong(lockValueStr)) { 47 | String getSetResult = RedisShardedPoolUtils.getSet(Const.RedisLock.CLOSE_ORDER_TASK_LOCK, String.valueOf(System.currentTimeMillis() + lockTimeout)); 48 | if (getSetResult == null || (StringUtils.equals(lockValueStr, getSetResult))) { 49 | // 获取到锁 50 | closeOrder(); 51 | } else { 52 | log.info("没有获得分布式锁:{}", Const.RedisLock.CLOSE_ORDER_TASK_LOCK); 53 | } 54 | } else { 55 | log.info("没有获得分布式锁:{}", Const.RedisLock.CLOSE_ORDER_TASK_LOCK); 56 | } 57 | } 58 | log.info("关闭订单定时任务结束"); 59 | } 60 | 61 | @Scheduled(cron = "0 */1 * * * ?") 62 | public void closeOrderTaskByRedisson() { 63 | RLock lock = redissonManager.getRedisson().getLock(Const.RedisLock.CLOSE_ORDER_TASK_LOCK); 64 | boolean getLock = false; 65 | try { 66 | if (getLock = lock.tryLock(WAIT_TIME, LEASE_TIME, TimeUnit.SECONDS)) { 67 | log.info("Redisson获取到分布式锁:{},ThreadName:{}", Const.RedisLock.CLOSE_ORDER_TASK_LOCK, Thread.currentThread().getName()); 68 | int hour = Integer.parseInt(PropertiesUtils.getProperty("task.order.close.time.hour", "2")); 69 | orderService.closeOrder(hour); 70 | } else { 71 | log.info("Redisson没有获取到分布式锁:{},ThreadName:{}", Const.RedisLock.CLOSE_ORDER_TASK_LOCK, Thread.currentThread().getName()); 72 | } 73 | } catch (InterruptedException e) { 74 | log.error("Redisson分布式锁获取异常", e); 75 | } finally { 76 | if (getLock) { 77 | lock.unlock(); 78 | log.info("Redisson分布式锁释放"); 79 | } 80 | } 81 | } 82 | 83 | private void closeOrder() { 84 | // 有效期5秒,防止死锁 85 | RedisShardedPoolUtils.expire(Const.RedisLock.CLOSE_ORDER_TASK_LOCK, 5); 86 | log.info("获取{},ThreadName:{}", Const.RedisLock.CLOSE_ORDER_TASK_LOCK, Thread.currentThread().getName()); 87 | int hour = Integer.parseInt(PropertiesUtils.getProperty("task.order.close.time.hour", "2")); 88 | orderService.closeOrder(hour); 89 | RedisShardedPoolUtils.del(Const.RedisLock.CLOSE_ORDER_TASK_LOCK); 90 | log.info("释放{},ThreadName:{}", Const.RedisLock.CLOSE_ORDER_TASK_LOCK, Thread.currentThread().getName()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/backend/ProductManageController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.backend; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.pojo.Product; 6 | import com.mmall.service.FileService; 7 | import com.mmall.service.ProductService; 8 | import com.mmall.util.PropertiesUtils; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | import org.springframework.web.multipart.MultipartFile; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.util.Map; 19 | 20 | /** 21 | * 后台管理-商品Controller 22 | *

23 | * @Author LeifChen 24 | * @Date 2019-02-28 25 | */ 26 | @RestController 27 | @RequestMapping("/admin/product") 28 | public class ProductManageController { 29 | 30 | @Autowired 31 | private ProductService productService; 32 | @Autowired 33 | private FileService fileService; 34 | 35 | @RequestMapping("/save.do") 36 | public JsonResult productSave(Product product) { 37 | return productService.saveOrUpdateProduct(product); 38 | } 39 | 40 | @RequestMapping("/set_sale_status.do") 41 | public JsonResult setSaleStatus(Integer productId, Integer status) { 42 | return productService.setSaleStatus(productId, status); 43 | } 44 | 45 | @RequestMapping("/detail.do") 46 | public JsonResult getDetail(Integer productId) { 47 | return productService.manageProductDetail(productId); 48 | } 49 | 50 | @RequestMapping("/list.do") 51 | public JsonResult getList(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum, 52 | @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) { 53 | 54 | return productService.getProductList(pageNum, pageSize); 55 | } 56 | 57 | @RequestMapping("/search.do") 58 | public JsonResult productSearch(String productName, 59 | Integer productId, 60 | @RequestParam(value = "pageNum", defaultValue = "1") int pageNum, 61 | @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) { 62 | 63 | return productService.searchProduct(productName, productId, pageNum, pageSize); 64 | } 65 | 66 | @RequestMapping("/upload.do") 67 | public JsonResult upload(@RequestParam(value = "upload_file", required = false) MultipartFile file, 68 | HttpServletRequest request) { 69 | 70 | String path = request.getSession().getServletContext().getRealPath("upload"); 71 | String targetFileName = fileService.upload(file, path); 72 | String url = PropertiesUtils.getProperty("ftp.server.http.prefix") + targetFileName; 73 | 74 | Map fileMap = Maps.newHashMap(); 75 | fileMap.put("uri", targetFileName); 76 | fileMap.put("url", url); 77 | return JsonResult.success(fileMap); 78 | } 79 | 80 | @RequestMapping("/richtext_img_upload.do") 81 | public Map richtextImgUpload(@RequestParam(value = "upload_file", required = false) MultipartFile file, 82 | HttpServletRequest request, 83 | HttpServletResponse response) { 84 | 85 | Map resultMap = Maps.newHashMap(); 86 | 87 | String path = request.getSession().getServletContext().getRealPath("upload"); 88 | String targetFileName = fileService.upload(file, path); 89 | if (StringUtils.isBlank(targetFileName)) { 90 | resultMap.put("success", false); 91 | resultMap.put("msg", "上传失败"); 92 | return resultMap; 93 | } 94 | 95 | String url = PropertiesUtils.getProperty("ftp.server.http.prefix") + targetFileName; 96 | resultMap.put("success", true); 97 | resultMap.put("msg", "上传成功"); 98 | resultMap.put("file_path", url); 99 | response.addHeader("Access-Control-Allow-Headers", "X-File-Name"); 100 | return resultMap; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/util/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package com.mmall.util; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.core.type.TypeReference; 5 | import com.fasterxml.jackson.databind.DeserializationFeature; 6 | import com.fasterxml.jackson.databind.JavaType; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.databind.SerializationFeature; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.apache.commons.lang3.StringUtils; 11 | 12 | import java.io.IOException; 13 | import java.text.SimpleDateFormat; 14 | 15 | /** 16 | * Json工具类 17 | *

18 | * @Author LeifChen 19 | * @Date 2019-03-20 20 | */ 21 | @Slf4j 22 | public class JsonUtils { 23 | 24 | private static ObjectMapper objectMapper = new ObjectMapper(); 25 | 26 | static { 27 | // 对象的所有字段全部列入序列化 28 | objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); 29 | // 取消默认转换timestamps形式 30 | objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 31 | // 忽略空bean转json的错误 32 | objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 33 | // 格式化日期格式:yyyy-MM-dd HH:mm:ss 34 | objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtils.STANDARD_FORMAT)); 35 | // 忽略在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误 36 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 37 | } 38 | 39 | /** 40 | * 对象转成json字符串 41 | * @param obj 对象 42 | * @param 43 | * @return 44 | */ 45 | public static String obj2String(T obj) { 46 | if (obj == null) { 47 | return null; 48 | } 49 | try { 50 | return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj); 51 | } catch (IOException e) { 52 | log.warn("Parse object to String error", e); 53 | return null; 54 | } 55 | } 56 | 57 | /** 58 | * 对象转成json字符串并格式化 59 | * @param obj 对象 60 | * @param 61 | * @return 62 | */ 63 | public static String obj2StringPretty(T obj) { 64 | if (obj == null) { 65 | return null; 66 | } 67 | try { 68 | return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj); 69 | } catch (IOException e) { 70 | log.warn("Parse object to String error", e); 71 | return null; 72 | } 73 | } 74 | 75 | /** 76 | * json字符串转成对象 77 | * @param str json字符串 78 | * @param clazz 对象类型 79 | * @param 80 | * @return 81 | */ 82 | public static T string2Obj(String str, Class clazz) { 83 | if (StringUtils.isEmpty(str) || clazz == null) { 84 | return null; 85 | } 86 | 87 | try { 88 | return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz); 89 | } catch (IOException e) { 90 | log.warn("Parse String to Object error", e); 91 | return null; 92 | } 93 | } 94 | 95 | /** 96 | * json字符串转成复杂对象 97 | * @param str json字符串 98 | * @param typeReference 参考类型 99 | * @param 100 | * @return 101 | */ 102 | public static T string2Obj(String str, TypeReference typeReference) { 103 | if (StringUtils.isEmpty(str) || typeReference == null) { 104 | return null; 105 | } 106 | 107 | try { 108 | return typeReference.getType().equals(String.class) ? (T) str : objectMapper.readValue(str, typeReference); 109 | } catch (IOException e) { 110 | log.warn("Parse String to Object error", e); 111 | return null; 112 | } 113 | } 114 | 115 | /** 116 | * json字符串转成对象集合 117 | * @param str json字符串 118 | * @param collectionClass 集合对象类型 119 | * @param elementClasses 元素对象类型 120 | * @param 121 | * @return 122 | */ 123 | public static T string2Obj(String str, Class collectionClass, Class... elementClasses) { 124 | JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses); 125 | try { 126 | return objectMapper.readValue(str, javaType); 127 | } catch (IOException e) { 128 | log.warn("Parse String to Object error", e); 129 | return null; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/main/resources/mappers/CategoryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | id, parent_id, name, status, sort_order, create_time, update_time 17 | 18 | 24 | 25 | delete from mmall_category 26 | where id = #{id,jdbcType=INTEGER} 27 | 28 | 29 | insert into mmall_category (id, parent_id, name, 30 | status, sort_order, create_time, 31 | update_time) 32 | values (#{id,jdbcType=INTEGER}, #{parentId,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, 33 | #{status,jdbcType=BIT}, #{sortOrder,jdbcType=INTEGER}, now(), 34 | now()) 35 | 36 | 37 | insert into mmall_category 38 | 39 | 40 | id, 41 | 42 | 43 | parent_id, 44 | 45 | 46 | name, 47 | 48 | 49 | status, 50 | 51 | 52 | sort_order, 53 | 54 | 55 | create_time, 56 | 57 | 58 | update_time, 59 | 60 | 61 | 62 | 63 | #{id,jdbcType=INTEGER}, 64 | 65 | 66 | #{parentId,jdbcType=INTEGER}, 67 | 68 | 69 | #{name,jdbcType=VARCHAR}, 70 | 71 | 72 | #{status,jdbcType=BIT}, 73 | 74 | 75 | #{sortOrder,jdbcType=INTEGER}, 76 | 77 | 78 | now(), 79 | 80 | 81 | now(), 82 | 83 | 84 | 85 | 86 | update mmall_category 87 | 88 | 89 | parent_id = #{parentId,jdbcType=INTEGER}, 90 | 91 | 92 | name = #{name,jdbcType=VARCHAR}, 93 | 94 | 95 | status = #{status,jdbcType=BIT}, 96 | 97 | 98 | sort_order = #{sortOrder,jdbcType=INTEGER}, 99 | 100 | 101 | create_time = #{createTime,jdbcType=TIMESTAMP}, 102 | 103 | 104 | update_time = now(), 105 | 106 | 107 | where id = #{id,jdbcType=INTEGER} 108 | 109 | 110 | update mmall_category 111 | set parent_id = #{parentId,jdbcType=INTEGER}, 112 | name = #{name,jdbcType=VARCHAR}, 113 | status = #{status,jdbcType=BIT}, 114 | sort_order = #{sortOrder,jdbcType=INTEGER}, 115 | create_time = #{createTime,jdbcType=TIMESTAMP}, 116 | update_time = now() 117 | where id = #{id,jdbcType=INTEGER} 118 | 119 | 120 | 126 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/common/Const.java: -------------------------------------------------------------------------------- 1 | package com.mmall.common; 2 | 3 | import com.google.common.collect.Sets; 4 | 5 | import java.util.Set; 6 | 7 | /** 8 | * 常量 9 | *

10 | * @Author LeifChen 11 | * @Date 2019-02-26 12 | */ 13 | public class Const { 14 | 15 | public static final String CURRENT_USER = "currentUser"; 16 | public static final String TOKEN_PREFIX = "token_"; 17 | 18 | public static final String USERNAME = "username"; 19 | public static final String EMAIL = "email"; 20 | 21 | public interface RedisCacheExtime { 22 | /** 23 | * 30分钟 24 | */ 25 | int REDIS_SESSION_EXTIME = 60 * 30; 26 | } 27 | 28 | public interface Role { 29 | /** 30 | * 管理员 31 | */ 32 | int ROLE_ADMIN = 0; 33 | /** 34 | * 普通用户 35 | */ 36 | int ROLE_CUSTOMER = 1; 37 | } 38 | 39 | public interface ProductListOrderBy { 40 | Set PRICE_ASC_DESC = Sets.newHashSet("price_desc", "price_asc"); 41 | } 42 | 43 | public interface Cart { 44 | /** 45 | * 未选中状态 46 | */ 47 | int UN_CHECKED = 0; 48 | /** 49 | * 选中状态 50 | */ 51 | int CHECKED = 1; 52 | 53 | String LIMIT_NUM_FAIL = "LIMIT_NUM_FAIL"; 54 | String LIMIT_NUM_SUCCESS = "LIMIT_NUM_SUCCESS"; 55 | } 56 | 57 | public interface AlipayCallback { 58 | String TRADE_STATUS_TRADE_SUCCESS = "TRADE_SUCCESS"; 59 | 60 | String RESPONSE_SUCCESS = "success"; 61 | String RESPONSE_FAILED = "failed"; 62 | } 63 | 64 | public interface RedisLock { 65 | /** 66 | * 关闭订单的分布式锁 67 | */ 68 | String CLOSE_ORDER_TASK_LOCK = "CLOSE_ORDER_TASK_LOCK"; 69 | } 70 | 71 | public enum ProductStatusEnum { 72 | /** 73 | * 销售在线状态 74 | */ 75 | ON_SALE(1, "在线"); 76 | 77 | private int code; 78 | private String value; 79 | 80 | ProductStatusEnum(int code, String value) { 81 | this.code = code; 82 | this.value = value; 83 | } 84 | 85 | public int getCode() { 86 | return code; 87 | } 88 | 89 | public String getValue() { 90 | return value; 91 | } 92 | } 93 | 94 | public enum OrderStatusEnum { 95 | /** 96 | * 已取消 97 | */ 98 | CANCELED(0, "已取消"), 99 | /** 100 | * 未支付 101 | */ 102 | NO_PAY(10, "未支付"), 103 | /** 104 | * 已付款 105 | */ 106 | PAID(20, "已付款"), 107 | /** 108 | * 已发货 109 | */ 110 | SHIPPED(40, "已发货"); 111 | 112 | private int code; 113 | private String value; 114 | 115 | OrderStatusEnum(int code, String value) { 116 | this.code = code; 117 | this.value = value; 118 | } 119 | 120 | public static OrderStatusEnum codeOf(int code) { 121 | for (OrderStatusEnum orderStatusEnum : values()) { 122 | if (orderStatusEnum.getCode() == code) { 123 | return orderStatusEnum; 124 | } 125 | } 126 | throw new RuntimeException("没有找到对应的枚举"); 127 | } 128 | 129 | public int getCode() { 130 | return code; 131 | } 132 | 133 | public String getValue() { 134 | return value; 135 | } 136 | } 137 | 138 | public enum PaymentTypeEnum { 139 | /** 140 | * 在线支付 141 | */ 142 | ONLINE_PAY(1, "在线支付"); 143 | 144 | private int code; 145 | private String value; 146 | 147 | PaymentTypeEnum(int code, String value) { 148 | this.code = code; 149 | this.value = value; 150 | } 151 | 152 | public static PaymentTypeEnum codeOf(int code) { 153 | for (PaymentTypeEnum paymentTypeEnum : values()) { 154 | if (paymentTypeEnum.getCode() == code) { 155 | return paymentTypeEnum; 156 | } 157 | } 158 | throw new RuntimeException("没有找到对应的枚举"); 159 | } 160 | 161 | public int getCode() { 162 | return code; 163 | } 164 | 165 | public String getValue() { 166 | return value; 167 | } 168 | } 169 | 170 | public enum PayPlatformEnum { 171 | /** 172 | * 支付宝 173 | */ 174 | ALIPAY(1, "支付宝"); 175 | 176 | private int code; 177 | private String value; 178 | 179 | PayPlatformEnum(int code, String value) { 180 | this.code = code; 181 | this.value = value; 182 | } 183 | 184 | public int getCode() { 185 | return code; 186 | } 187 | 188 | public String getValue() { 189 | return value; 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/util/RedisShardedPoolUtils.java: -------------------------------------------------------------------------------- 1 | package com.mmall.util; 2 | 3 | import com.mmall.common.RedisShardedPool; 4 | import lombok.extern.slf4j.Slf4j; 5 | import redis.clients.jedis.ShardedJedis; 6 | 7 | /** 8 | * Redis连接池工具类 9 | *

10 | * @Author LeifChen 11 | * @Date 2019-03-20 12 | */ 13 | @Slf4j 14 | public class RedisShardedPoolUtils { 15 | 16 | /** 17 | * 获取键的值 18 | * @param key 键 19 | * @return 20 | */ 21 | public static String get(String key) { 22 | ShardedJedis jedis = null; 23 | String result; 24 | try { 25 | jedis = RedisShardedPool.getJedis(); 26 | result = jedis.get(key); 27 | } catch (Exception e) { 28 | log.error("get key:{} error", key, e); 29 | RedisShardedPool.returnBrokenResource(jedis); 30 | return null; 31 | } 32 | RedisShardedPool.returnResource(jedis); 33 | return result; 34 | } 35 | 36 | /** 37 | * 设置键值对 38 | * @param key 键 39 | * @param value 值 40 | * @return 41 | */ 42 | public static String set(String key, String value) { 43 | ShardedJedis jedis = null; 44 | String result; 45 | try { 46 | jedis = RedisShardedPool.getJedis(); 47 | result = jedis.set(key, value); 48 | } catch (Exception e) { 49 | log.error("set key:{} value:{} error", key, value, e); 50 | RedisShardedPool.returnBrokenResource(jedis); 51 | return null; 52 | } 53 | RedisShardedPool.returnResource(jedis); 54 | return result; 55 | } 56 | 57 | /** 58 | * 设置键值对和有效时间 59 | * @param key 键 60 | * @param value 值 61 | * @param exTime 有效时间(单位:秒) 62 | * @return 63 | */ 64 | public static String setEx(String key, String value, int exTime) { 65 | ShardedJedis jedis = null; 66 | String result; 67 | try { 68 | jedis = RedisShardedPool.getJedis(); 69 | result = jedis.setex(key, exTime, value); 70 | } catch (Exception e) { 71 | log.error("setex key:{} value:{} error", key, value, e); 72 | RedisShardedPool.returnBrokenResource(jedis); 73 | return null; 74 | } 75 | RedisShardedPool.returnResource(jedis); 76 | return result; 77 | } 78 | 79 | /** 80 | * 设置键的有效期 81 | * @param key 键 82 | * @param exTime 有效时间(单位:秒) 83 | * @return 84 | */ 85 | public static Long expire(String key, int exTime) { 86 | ShardedJedis jedis = null; 87 | Long result; 88 | try { 89 | jedis = RedisShardedPool.getJedis(); 90 | result = jedis.expire(key, exTime); 91 | } catch (Exception e) { 92 | log.error("expire key:{} error", key, e); 93 | RedisShardedPool.returnBrokenResource(jedis); 94 | return null; 95 | } 96 | RedisShardedPool.returnResource(jedis); 97 | return result; 98 | } 99 | 100 | /** 101 | * 删除键 102 | * @param key 键 103 | * @return 104 | */ 105 | public static Long del(String key) { 106 | ShardedJedis jedis = null; 107 | Long result; 108 | try { 109 | jedis = RedisShardedPool.getJedis(); 110 | result = jedis.del(key); 111 | } catch (Exception e) { 112 | log.error("del key:{} error", key, e); 113 | RedisShardedPool.returnBrokenResource(jedis); 114 | return null; 115 | } 116 | RedisShardedPool.returnResource(jedis); 117 | return result; 118 | } 119 | 120 | /** 121 | * 设置键值对,事前判断是否已存在 122 | * @param key 键 123 | * @param value 值 124 | * @return 125 | */ 126 | public static Long setnx(String key, String value) { 127 | ShardedJedis jedis = null; 128 | Long result; 129 | try { 130 | jedis = RedisShardedPool.getJedis(); 131 | result = jedis.setnx(key, value); 132 | } catch (Exception e) { 133 | log.error("setnx key:{} value:{} error", key, value, e); 134 | RedisShardedPool.returnBrokenResource(jedis); 135 | return null; 136 | } 137 | RedisShardedPool.returnResource(jedis); 138 | return result; 139 | } 140 | 141 | /** 142 | * 设置键值对,并立即返回旧值 143 | * @param key 键 144 | * @param value 值 145 | * @return 146 | */ 147 | public static String getSet(String key, String value) { 148 | ShardedJedis jedis = null; 149 | String result; 150 | try { 151 | jedis = RedisShardedPool.getJedis(); 152 | result = jedis.getSet(key, value); 153 | } catch (Exception e) { 154 | log.error("set key:{} value:{} error", key, value, e); 155 | RedisShardedPool.returnBrokenResource(jedis); 156 | return null; 157 | } 158 | RedisShardedPool.returnResource(jedis); 159 | return result; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/resources/generatorConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | 74 | 75 | 76 |
77 |
78 | 79 | 80 |
81 |
-------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/portal/CartController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.portal; 2 | 3 | import com.mmall.common.Const; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.controller.common.UserCheck; 6 | import com.mmall.pojo.User; 7 | import com.mmall.service.CartService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | 14 | /** 15 | * 购物车Controller 16 | *

17 | * @Author LeifChen 18 | * @Date 2019-03-01 19 | */ 20 | @RestController 21 | @RequestMapping("/cart") 22 | public class CartController { 23 | 24 | @Autowired 25 | private CartService cartService; 26 | @Autowired 27 | private UserCheck userCheck; 28 | 29 | @RequestMapping("/add.do") 30 | public JsonResult add(HttpServletRequest httpServletRequest, Integer count, Integer productId) { 31 | JsonResult response = userCheck.checkLogin(httpServletRequest); 32 | if (response.isSuccess()) { 33 | User user = (User) response.getData(); 34 | return cartService.add(user.getId(), productId, count); 35 | } else { 36 | return response; 37 | } 38 | } 39 | 40 | @RequestMapping("/update.do") 41 | public JsonResult update(HttpServletRequest httpServletRequest, Integer count, Integer productId) { 42 | JsonResult response = userCheck.checkLogin(httpServletRequest); 43 | if (response.isSuccess()) { 44 | User user = (User) response.getData(); 45 | return cartService.update(user.getId(), productId, count); 46 | } else { 47 | return response; 48 | } 49 | } 50 | 51 | @RequestMapping("/delete_product.do") 52 | public JsonResult deleteProduct(HttpServletRequest httpServletRequest, String productIds) { 53 | JsonResult response = userCheck.checkLogin(httpServletRequest); 54 | if (response.isSuccess()) { 55 | User user = (User) response.getData(); 56 | return cartService.deleteProduct(user.getId(), productIds); 57 | } else { 58 | return response; 59 | } 60 | } 61 | 62 | @RequestMapping("/list.do") 63 | public JsonResult list(HttpServletRequest httpServletRequest) { 64 | JsonResult response = userCheck.checkLogin(httpServletRequest); 65 | if (response.isSuccess()) { 66 | User user = (User) response.getData(); 67 | return cartService.list(user.getId()); 68 | } else { 69 | return response; 70 | } 71 | } 72 | 73 | @RequestMapping("/select_all.do") 74 | public JsonResult selectAll(HttpServletRequest httpServletRequest) { 75 | JsonResult response = userCheck.checkLogin(httpServletRequest); 76 | if (response.isSuccess()) { 77 | User user = (User) response.getData(); 78 | return cartService.selectOrUnselect(user.getId(), null, Const.Cart.CHECKED); 79 | } else { 80 | return response; 81 | } 82 | } 83 | 84 | @RequestMapping("/un_select_all.do") 85 | public JsonResult unSelectAll(HttpServletRequest httpServletRequest) { 86 | JsonResult response = userCheck.checkLogin(httpServletRequest); 87 | if (response.isSuccess()) { 88 | User user = (User) response.getData(); 89 | return cartService.selectOrUnselect(user.getId(), null, Const.Cart.UN_CHECKED); 90 | } else { 91 | return response; 92 | } 93 | } 94 | 95 | @RequestMapping("/select.do") 96 | public JsonResult select(HttpServletRequest httpServletRequest, Integer productId) { 97 | JsonResult response = userCheck.checkLogin(httpServletRequest); 98 | if (response.isSuccess()) { 99 | User user = (User) response.getData(); 100 | return cartService.selectOrUnselect(user.getId(), productId, Const.Cart.CHECKED); 101 | } else { 102 | return response; 103 | } 104 | } 105 | 106 | @RequestMapping("/un_select.do") 107 | public JsonResult unSelect(HttpServletRequest httpServletRequest, Integer productId) { 108 | JsonResult response = userCheck.checkLogin(httpServletRequest); 109 | if (response.isSuccess()) { 110 | User user = (User) response.getData(); 111 | return cartService.selectOrUnselect(user.getId(), productId, Const.Cart.UN_CHECKED); 112 | } else { 113 | return response; 114 | } 115 | } 116 | 117 | @RequestMapping("/get_cart_product_count.do") 118 | public JsonResult getCartProductCount(HttpServletRequest httpServletRequest) { 119 | JsonResult response = userCheck.checkLogin(httpServletRequest); 120 | if (response.isSuccess()) { 121 | User user = (User) response.getData(); 122 | return cartService.getCartProductCount(user.getId()); 123 | } else { 124 | return JsonResult.success(0); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/common/interceptor/AuthorityInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.common.interceptor; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.mmall.common.Const; 5 | import com.mmall.common.JsonResult; 6 | import com.mmall.pojo.User; 7 | import com.mmall.util.CookieUtils; 8 | import com.mmall.util.JsonUtils; 9 | import com.mmall.util.RedisShardedPoolUtils; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.springframework.web.method.HandlerMethod; 13 | import org.springframework.web.servlet.HandlerInterceptor; 14 | import org.springframework.web.servlet.ModelAndView; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.PrintWriter; 19 | import java.util.Arrays; 20 | import java.util.Map; 21 | 22 | /** 23 | * 权限拦截器 24 | *

25 | * @Author LeifChen 26 | * @Date 2019-03-26 27 | */ 28 | @Slf4j 29 | public class AuthorityInterceptor implements HandlerInterceptor { 30 | 31 | private static final String USER_MANAGE_CONTROLLER = "UserManageController"; 32 | private static final String PRODUCT_MANAGE_CONTROLLER = "ProductManageController"; 33 | 34 | @Override 35 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 36 | log.info("preHandle"); 37 | HandlerMethod handlerMethod = (HandlerMethod) handler; 38 | String methodName = handlerMethod.getMethod().getName(); 39 | String className = handlerMethod.getBean().getClass().getSimpleName(); 40 | StringBuilder requestParamBuffer = new StringBuilder(); 41 | Map paramMap = request.getParameterMap(); 42 | for (Object o : paramMap.entrySet()) { 43 | Map.Entry entry = (Map.Entry) o; 44 | String mapKey = (String) entry.getKey(); 45 | String mapValue = StringUtils.EMPTY; 46 | // request参数的map里面的value返回的是一个String[] 47 | Object obj = entry.getValue(); 48 | if (obj instanceof String[]) { 49 | String[] strs = (String[]) obj; 50 | mapValue = Arrays.toString(strs); 51 | } 52 | requestParamBuffer.append(mapKey).append("=").append(mapValue); 53 | } 54 | 55 | // 放行管理员的登录请求 56 | if (StringUtils.equals(className, USER_MANAGE_CONTROLLER) 57 | && StringUtils.equals(methodName, "login")) { 58 | log.info("权限拦截器拦截到请求,className:{},methodName:{}", className, methodName); 59 | return true; 60 | } 61 | 62 | log.info("权限拦截器拦截到请求,className:{},methodName:{},param:{}", className, methodName, requestParamBuffer.toString()); 63 | 64 | User user = null; 65 | String loginToken = CookieUtils.readLoginToken(request); 66 | if (StringUtils.isNotEmpty(loginToken)) { 67 | String userJsonStr = RedisShardedPoolUtils.get(loginToken); 68 | user = JsonUtils.string2Obj(userJsonStr, User.class); 69 | } 70 | 71 | if (user == null || (user.getRole() != Const.Role.ROLE_ADMIN)) { 72 | response.reset(); 73 | response.setCharacterEncoding("UTF-8"); 74 | response.setContentType("application/json;charset=UTF-8"); 75 | 76 | PrintWriter out = response.getWriter(); 77 | // 特殊处理上传富文本的请求 78 | if (user == null) { 79 | if (StringUtils.equals(className, PRODUCT_MANAGE_CONTROLLER) 80 | && StringUtils.equals(methodName, "richtextImgUpload")) { 81 | Map resultMap = Maps.newHashMap(); 82 | resultMap.put("success", false); 83 | resultMap.put("msg", "请登录管理员"); 84 | out.print(JsonUtils.obj2String(resultMap)); 85 | } else { 86 | out.print(JsonUtils.obj2String(JsonResult.error("拦截器拦截,用户未登录"))); 87 | } 88 | } else { 89 | if (StringUtils.equals(className, PRODUCT_MANAGE_CONTROLLER) 90 | && StringUtils.equals(methodName, "richtextImgUpload")) { 91 | Map resultMap = Maps.newHashMap(); 92 | resultMap.put("success", false); 93 | resultMap.put("msg", "无权限操作"); 94 | out.print(JsonUtils.obj2String(resultMap)); 95 | } else { 96 | out.print(JsonUtils.obj2String(JsonResult.error("拦截器拦截,用户无权限操作"))); 97 | } 98 | } 99 | out.flush(); 100 | out.close(); 101 | return false; 102 | } 103 | return true; 104 | } 105 | 106 | @Override 107 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { 108 | log.info("postHandle"); 109 | } 110 | 111 | @Override 112 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 113 | log.info("afterCompletion"); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/resources/mappers/PayInfoMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | id, user_id, order_no, pay_platform, platform_number, platform_status, create_time, 18 | update_time 19 | 20 | 26 | 27 | delete from mmall_pay_info 28 | where id = #{id,jdbcType=INTEGER} 29 | 30 | 31 | insert into mmall_pay_info (id, user_id, order_no, 32 | pay_platform, platform_number, platform_status, 33 | create_time, update_time) 34 | values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{orderNo,jdbcType=BIGINT}, 35 | #{payPlatform,jdbcType=INTEGER}, #{platformNumber,jdbcType=VARCHAR}, #{platformStatus,jdbcType=VARCHAR}, 36 | now(), now()) 37 | 38 | 39 | insert into mmall_pay_info 40 | 41 | 42 | id, 43 | 44 | 45 | user_id, 46 | 47 | 48 | order_no, 49 | 50 | 51 | pay_platform, 52 | 53 | 54 | platform_number, 55 | 56 | 57 | platform_status, 58 | 59 | 60 | create_time, 61 | 62 | 63 | update_time, 64 | 65 | 66 | 67 | 68 | #{id,jdbcType=INTEGER}, 69 | 70 | 71 | #{userId,jdbcType=INTEGER}, 72 | 73 | 74 | #{orderNo,jdbcType=BIGINT}, 75 | 76 | 77 | #{payPlatform,jdbcType=INTEGER}, 78 | 79 | 80 | #{platformNumber,jdbcType=VARCHAR}, 81 | 82 | 83 | #{platformStatus,jdbcType=VARCHAR}, 84 | 85 | 86 | now(), 87 | 88 | 89 | now(), 90 | 91 | 92 | 93 | 94 | update mmall_pay_info 95 | 96 | 97 | user_id = #{userId,jdbcType=INTEGER}, 98 | 99 | 100 | order_no = #{orderNo,jdbcType=BIGINT}, 101 | 102 | 103 | pay_platform = #{payPlatform,jdbcType=INTEGER}, 104 | 105 | 106 | platform_number = #{platformNumber,jdbcType=VARCHAR}, 107 | 108 | 109 | platform_status = #{platformStatus,jdbcType=VARCHAR}, 110 | 111 | 112 | create_time = #{createTime,jdbcType=TIMESTAMP}, 113 | 114 | 115 | update_time = now(), 116 | 117 | 118 | where id = #{id,jdbcType=INTEGER} 119 | 120 | 121 | update mmall_pay_info 122 | set user_id = #{userId,jdbcType=INTEGER}, 123 | order_no = #{orderNo,jdbcType=BIGINT}, 124 | pay_platform = #{payPlatform,jdbcType=INTEGER}, 125 | platform_number = #{platformNumber,jdbcType=VARCHAR}, 126 | platform_status = #{platformStatus,jdbcType=VARCHAR}, 127 | create_time = #{createTime,jdbcType=TIMESTAMP}, 128 | update_time = now() 129 | where id = #{id,jdbcType=INTEGER} 130 | 131 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/portal/UserController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.portal; 2 | 3 | import com.mmall.common.Const; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.controller.common.UserCheck; 6 | import com.mmall.pojo.User; 7 | import com.mmall.service.UserService; 8 | import com.mmall.util.CookieUtils; 9 | import com.mmall.util.JsonUtils; 10 | import com.mmall.util.RedisShardedPoolUtils; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import javax.servlet.http.HttpSession; 19 | 20 | /** 21 | * 门户-用户Controller 22 | *

23 | * @Author LeifChen 24 | * @Date 2019-02-26 25 | */ 26 | @RestController 27 | @RequestMapping("/user") 28 | public class UserController { 29 | 30 | @Autowired 31 | private UserService userService; 32 | @Autowired 33 | private UserCheck userCheck; 34 | 35 | @RequestMapping(value = "/login.do", method = RequestMethod.POST) 36 | public JsonResult login(String username, String password, HttpSession session, HttpServletResponse httpServletResponse) { 37 | JsonResult response = userService.login(username, password); 38 | if (response.isSuccess()) { 39 | CookieUtils.writeLoginToken(httpServletResponse, session.getId()); 40 | RedisShardedPoolUtils.setEx(session.getId(), JsonUtils.obj2String(response.getData()), Const.RedisCacheExtime.REDIS_SESSION_EXTIME); 41 | } 42 | return response; 43 | } 44 | 45 | @RequestMapping(value = "/logout.do", method = RequestMethod.POST) 46 | public JsonResult logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { 47 | String loginToken = CookieUtils.readLoginToken(httpServletRequest); 48 | CookieUtils.delLoginToken(httpServletRequest, httpServletResponse); 49 | RedisShardedPoolUtils.del(loginToken); 50 | return JsonResult.success(); 51 | } 52 | 53 | @RequestMapping(value = "/register.do", method = RequestMethod.POST) 54 | public JsonResult register(User user) { 55 | return userService.register(user); 56 | } 57 | 58 | @RequestMapping(value = "/check_valid.do", method = RequestMethod.POST) 59 | public JsonResult checkValid(String str, String type) { 60 | return userService.checkValid(str, type); 61 | } 62 | 63 | @RequestMapping(value = "/get_user_info.do", method = RequestMethod.POST) 64 | public JsonResult getUserInfo(HttpServletRequest httpServletRequest) { 65 | JsonResult response = userCheck.checkLogin(httpServletRequest); 66 | if (response.isSuccess()) { 67 | User user = (User) response.getData(); 68 | return JsonResult.success(user); 69 | } else { 70 | return JsonResult.error("用户未登录,无法获取当前用户信息"); 71 | } 72 | } 73 | 74 | @RequestMapping(value = "/forget_get_question.do", method = RequestMethod.POST) 75 | public JsonResult forgetGetQuestion(String username) { 76 | return userService.selectQuestion(username); 77 | } 78 | 79 | @RequestMapping(value = "/forget_check_answer.do", method = RequestMethod.POST) 80 | public JsonResult forgetCheckAnswer(String username, String question, String answer) { 81 | return userService.checkAnswer(username, question, answer); 82 | } 83 | 84 | @RequestMapping(value = "/forget_reset_password.do", method = RequestMethod.POST) 85 | public JsonResult forgetResetPassword(String username, String passwordNew, String forgetToken) { 86 | return userService.forgetResetPassword(username, passwordNew, forgetToken); 87 | } 88 | 89 | @RequestMapping(value = "/reset_password.do", method = RequestMethod.POST) 90 | public JsonResult resetPassword(HttpServletRequest httpServletRequest, String passwordOld, String passwordNew) { 91 | JsonResult response = userCheck.checkLogin(httpServletRequest); 92 | if (response.isSuccess()) { 93 | User user = (User) response.getData(); 94 | return userService.resetPassword(passwordOld, passwordNew, user); 95 | } else { 96 | return JsonResult.error("用户未登录"); 97 | } 98 | } 99 | 100 | @RequestMapping(value = "/update_information.do", method = RequestMethod.POST) 101 | public JsonResult updateInformation(HttpServletRequest httpServletRequest, User user) { 102 | JsonResult response = userCheck.checkLogin(httpServletRequest); 103 | if (response.isSuccess()) { 104 | User currentUser = (User) response.getData(); 105 | user.setId(currentUser.getId()); 106 | user.setUsername(currentUser.getUsername()); 107 | JsonResult result = userService.updateInformation(user); 108 | if (result.isSuccess()) { 109 | result.getData().setUsername(currentUser.getUsername()); 110 | String loginToken = CookieUtils.readLoginToken(httpServletRequest); 111 | RedisShardedPoolUtils.setEx(loginToken, JsonUtils.obj2String(response.getData()), Const.RedisCacheExtime.REDIS_SESSION_EXTIME); 112 | } 113 | return result; 114 | } else { 115 | return JsonResult.error("用户未登录"); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/controller/portal/OrderController.java: -------------------------------------------------------------------------------- 1 | package com.mmall.controller.portal; 2 | 3 | import com.alipay.api.AlipayApiException; 4 | import com.alipay.api.internal.util.AlipaySignature; 5 | import com.alipay.demo.trade.config.Configs; 6 | import com.google.common.collect.Maps; 7 | import com.mmall.common.Const; 8 | import com.mmall.common.JsonResult; 9 | import com.mmall.controller.common.UserCheck; 10 | import com.mmall.pojo.User; 11 | import com.mmall.service.OrderService; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestParam; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | import java.util.Map; 20 | 21 | /** 22 | * 订单Controller 23 | *

24 | * @Author LeifChen 25 | * @Date 2019-03-08 26 | */ 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/order") 30 | public class OrderController { 31 | 32 | @Autowired 33 | private OrderService orderService; 34 | @Autowired 35 | private UserCheck userCheck; 36 | 37 | @RequestMapping(value = "/create.do") 38 | public JsonResult create(HttpServletRequest httpServletRequest, Integer shippingId) { 39 | JsonResult response = userCheck.checkLogin(httpServletRequest); 40 | if (response.isSuccess()) { 41 | User user = (User) response.getData(); 42 | return orderService.create(user.getId(), shippingId); 43 | } else { 44 | return response; 45 | } 46 | } 47 | 48 | @RequestMapping(value = "/cancel.do") 49 | public JsonResult cancel(HttpServletRequest httpServletRequest, Long orderNo) { 50 | JsonResult response = userCheck.checkLogin(httpServletRequest); 51 | if (response.isSuccess()) { 52 | User user = (User) response.getData(); 53 | return orderService.cancel(user.getId(), orderNo); 54 | } else { 55 | return response; 56 | } 57 | } 58 | 59 | @RequestMapping(value = "/get_order_cart_product.do") 60 | public JsonResult getOrderCartProduct(HttpServletRequest httpServletRequest) { 61 | JsonResult response = userCheck.checkLogin(httpServletRequest); 62 | if (response.isSuccess()) { 63 | User user = (User) response.getData(); 64 | return orderService.getOrderCartProduct(user.getId()); 65 | } else { 66 | return response; 67 | } 68 | } 69 | 70 | @RequestMapping(value = "/detail.do") 71 | public JsonResult detail(HttpServletRequest httpServletRequest, Long orderNo) { 72 | JsonResult response = userCheck.checkLogin(httpServletRequest); 73 | if (response.isSuccess()) { 74 | User user = (User) response.getData(); 75 | return orderService.getOrderDetail(user.getId(), orderNo); 76 | } else { 77 | return response; 78 | } 79 | } 80 | 81 | @RequestMapping(value = "/list.do") 82 | public JsonResult list(HttpServletRequest httpServletRequest, 83 | @RequestParam(value = "pageNum", defaultValue = "1") int pageNum, 84 | @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) { 85 | 86 | JsonResult response = userCheck.checkLogin(httpServletRequest); 87 | if (response.isSuccess()) { 88 | User user = (User) response.getData(); 89 | return orderService.getOrderList(user.getId(), pageNum, pageSize); 90 | } else { 91 | return response; 92 | } 93 | } 94 | 95 | @RequestMapping(value = "/pay.do") 96 | public JsonResult pay(HttpServletRequest httpServletRequest, Long orderNo) { 97 | JsonResult response = userCheck.checkLogin(httpServletRequest); 98 | if (response.isSuccess()) { 99 | User user = (User) response.getData(); 100 | String path = httpServletRequest.getSession().getServletContext().getRealPath("upload"); 101 | return orderService.pay(orderNo, user.getId(), path); 102 | } else { 103 | return response; 104 | } 105 | } 106 | 107 | @RequestMapping(value = "/alipay_callback.do") 108 | public Object alipayCallback(HttpServletRequest request) { 109 | Map params = Maps.newHashMap(); 110 | 111 | Map requestParams = request.getParameterMap(); 112 | for (Object obj : requestParams.keySet()) { 113 | String name = (String) obj; 114 | String[] values = (String[]) requestParams.get(name); 115 | String valueStr = ""; 116 | for (int i = 0; i < values.length; i++) { 117 | valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; 118 | } 119 | params.put(name, valueStr); 120 | } 121 | log.info("支付宝回调,sign:{},trade_status:{},参数:{}", params.get("sign"), params.get("trade_status"), params.toString()); 122 | 123 | // 验证回调 124 | params.remove("sign_type"); 125 | try { 126 | boolean alipayRSACheckedV2 = AlipaySignature.rsaCheckV2(params, Configs.getAlipayPublicKey(), "utf-8", Configs.getSignType()); 127 | if (!alipayRSACheckedV2) { 128 | return JsonResult.error("非法请求,验证不通过"); 129 | } 130 | } catch (AlipayApiException e) { 131 | log.error("支付宝验证回调异常", e); 132 | } 133 | 134 | JsonResult response = orderService.alipayCallback(params); 135 | if (response.isSuccess()) { 136 | return Const.AlipayCallback.RESPONSE_SUCCESS; 137 | } 138 | return Const.AlipayCallback.RESPONSE_FAILED; 139 | } 140 | 141 | @RequestMapping(value = "/query_order_pay_status.do") 142 | public JsonResult queryOrderPayStatus(HttpServletRequest httpServletRequest, Long orderNo) { 143 | JsonResult response = userCheck.checkLogin(httpServletRequest); 144 | if (response.isSuccess()) { 145 | User user = (User) response.getData(); 146 | JsonResult result = orderService.queryOrderPayStatus(user.getId(), orderNo); 147 | if (result.isSuccess()) { 148 | return JsonResult.success(true); 149 | } 150 | return result; 151 | } else { 152 | return response; 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/main/resources/mappers/CartMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | id, user_id, product_id, quantity, checked, create_time, update_time 17 | 18 | 24 | 25 | delete from mmall_cart 26 | where id = #{id,jdbcType=INTEGER} 27 | 28 | 29 | insert into mmall_cart (id, user_id, product_id, 30 | quantity, checked, create_time, 31 | update_time) 32 | values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{productId,jdbcType=INTEGER}, 33 | #{quantity,jdbcType=INTEGER}, #{checked,jdbcType=INTEGER}, now(), 34 | now()) 35 | 36 | 37 | insert into mmall_cart 38 | 39 | 40 | id, 41 | 42 | 43 | user_id, 44 | 45 | 46 | product_id, 47 | 48 | 49 | quantity, 50 | 51 | 52 | checked, 53 | 54 | 55 | create_time, 56 | 57 | 58 | update_time, 59 | 60 | 61 | 62 | 63 | #{id,jdbcType=INTEGER}, 64 | 65 | 66 | #{userId,jdbcType=INTEGER}, 67 | 68 | 69 | #{productId,jdbcType=INTEGER}, 70 | 71 | 72 | #{quantity,jdbcType=INTEGER}, 73 | 74 | 75 | #{checked,jdbcType=INTEGER}, 76 | 77 | 78 | now(), 79 | 80 | 81 | now(), 82 | 83 | 84 | 85 | 86 | update mmall_cart 87 | 88 | 89 | user_id = #{userId,jdbcType=INTEGER}, 90 | 91 | 92 | product_id = #{productId,jdbcType=INTEGER}, 93 | 94 | 95 | quantity = #{quantity,jdbcType=INTEGER}, 96 | 97 | 98 | checked = #{checked,jdbcType=INTEGER}, 99 | 100 | 101 | create_time = #{createTime,jdbcType=TIMESTAMP}, 102 | 103 | 104 | update_time = now(), 105 | 106 | 107 | where id = #{id,jdbcType=INTEGER} 108 | 109 | 110 | update mmall_cart 111 | set user_id = #{userId,jdbcType=INTEGER}, 112 | product_id = #{productId,jdbcType=INTEGER}, 113 | quantity = #{quantity,jdbcType=INTEGER}, 114 | checked = #{checked,jdbcType=INTEGER}, 115 | create_time = #{createTime,jdbcType=TIMESTAMP}, 116 | update_time = now() 117 | where id = #{id,jdbcType=INTEGER} 118 | 119 | 120 | 127 | 128 | 134 | 135 | 141 | 142 | 143 | delete 144 | from mmall_cart 145 | where user_id = #{userId} 146 | 147 | and product_id in 148 | 149 | #{item} 150 | 151 | 152 | 153 | 154 | 155 | update mmall_cart 156 | set checked = #{checked}, 157 | update_time = now() 158 | where user_id = #{userId} 159 | 160 | and product_id = #{productId} 161 | 162 | 163 | 164 | 169 | 170 | 177 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service.impl; 2 | 3 | import com.mmall.common.Const; 4 | import com.mmall.common.JsonResult; 5 | import com.mmall.common.ResponseCodeEnum; 6 | import com.mmall.dao.UserMapper; 7 | import com.mmall.pojo.User; 8 | import com.mmall.service.UserService; 9 | import com.mmall.util.Md5Utils; 10 | import com.mmall.util.RedisShardedPoolUtils; 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.Date; 16 | import java.util.UUID; 17 | 18 | /** 19 | * 用户Service的实现类 20 | *

21 | * @Author LeifChen 22 | * @Date 2019-02-26 23 | */ 24 | @Service("userService") 25 | public class UserServiceImpl implements UserService { 26 | 27 | @Autowired 28 | private UserMapper userMapper; 29 | 30 | @Override 31 | public JsonResult login(String username, String password) { 32 | int resultCount = userMapper.checkUsername(username); 33 | if (resultCount == 0) { 34 | return JsonResult.error("用户名不存在"); 35 | } 36 | 37 | User user = userMapper.selectLogin(username, Md5Utils.encode(password)); 38 | if (user == null) { 39 | return JsonResult.error("密码错误"); 40 | } 41 | 42 | user.setPassword(StringUtils.EMPTY); 43 | return JsonResult.success("登录成功", user); 44 | } 45 | 46 | @Override 47 | public JsonResult register(User user) { 48 | JsonResult validResponse = checkValid(user.getUsername(), Const.USERNAME); 49 | if (!validResponse.isSuccess()) { 50 | return validResponse; 51 | } 52 | validResponse = checkValid(user.getEmail(), Const.EMAIL); 53 | if (!validResponse.isSuccess()) { 54 | return validResponse; 55 | } 56 | 57 | user.setRole(Const.Role.ROLE_CUSTOMER); 58 | user.setPassword(Md5Utils.encode(user.getPassword())); 59 | 60 | int resultCount = userMapper.insert(user); 61 | if (resultCount == 0) { 62 | return JsonResult.error("注册失败"); 63 | } 64 | return JsonResult.success("注册成功"); 65 | } 66 | 67 | @Override 68 | public JsonResult checkValid(String str, String type) { 69 | if (StringUtils.isNotEmpty(type)) { 70 | // 校验 71 | if (Const.USERNAME.equals(type)) { 72 | int resultCount = userMapper.checkUsername(str); 73 | if (resultCount > 0) { 74 | return JsonResult.error("用户名已存在"); 75 | } 76 | } else if (Const.EMAIL.equals(type)) { 77 | int resultCount = userMapper.checkEmail(str); 78 | if (resultCount > 0) { 79 | return JsonResult.error("email已存在"); 80 | } 81 | } else { 82 | return JsonResult.error("参数不合法"); 83 | } 84 | } else { 85 | return JsonResult.error(ResponseCodeEnum.ILLEGAL_ARGUMENT.getDesc()); 86 | } 87 | return JsonResult.success("校验成功"); 88 | } 89 | 90 | @Override 91 | public JsonResult selectQuestion(String username) { 92 | JsonResult validResponse = checkValid(username, Const.USERNAME); 93 | if (validResponse.isSuccess()) { 94 | return JsonResult.error("用户不存在"); 95 | } 96 | 97 | String question = userMapper.selectQuestionByUsername(username); 98 | if (StringUtils.isNotBlank(question)) { 99 | return JsonResult.success(question); 100 | } 101 | return JsonResult.error("找回密码的问题是空的"); 102 | } 103 | 104 | @Override 105 | public JsonResult checkAnswer(String username, String question, String answer) { 106 | int resultCount = userMapper.checkAnswer(username, question, answer); 107 | if (resultCount > 0) { 108 | String forgetToken = UUID.randomUUID().toString(); 109 | RedisShardedPoolUtils.setEx(Const.TOKEN_PREFIX + username, forgetToken, 60 * 60 * 12); 110 | return JsonResult.success(forgetToken); 111 | } 112 | return JsonResult.error("问题的答案错误"); 113 | } 114 | 115 | @Override 116 | public JsonResult forgetResetPassword(String username, String passwordNew, String forgetToken) { 117 | if (StringUtils.isBlank(forgetToken)) { 118 | return JsonResult.error("参数错误,token需要传递"); 119 | } 120 | JsonResult validResponse = checkValid(username, Const.USERNAME); 121 | if (validResponse.isSuccess()) { 122 | return JsonResult.error("用户不存在"); 123 | } 124 | 125 | String token = RedisShardedPoolUtils.get(Const.TOKEN_PREFIX + username); 126 | if (StringUtils.isBlank(token)) { 127 | return JsonResult.error("token无效或者过期"); 128 | } 129 | if (StringUtils.equals(forgetToken, token)) { 130 | String md5Password = Md5Utils.encode(passwordNew); 131 | int rowCount = userMapper.updatePasswordByUsername(username, md5Password); 132 | if (rowCount > 0) { 133 | return JsonResult.success("修改密码成功"); 134 | } 135 | } else { 136 | return JsonResult.error("token错误,请重新获取重置密码的token"); 137 | } 138 | return JsonResult.error("修改密码失败"); 139 | } 140 | 141 | @Override 142 | public JsonResult resetPassword(String passwordOld, String passwordNew, User user) { 143 | int resultCount = userMapper.checkPassword(Md5Utils.encode(passwordOld), user.getId()); 144 | if (resultCount == 0) { 145 | return JsonResult.error("旧密码错误"); 146 | } 147 | 148 | user.setPassword(Md5Utils.encode(passwordNew)); 149 | int updateCount = userMapper.updateByPrimaryKeySelective(user); 150 | if (updateCount > 0) { 151 | return JsonResult.success("密码更新成功"); 152 | } 153 | return JsonResult.error("密码更新失败"); 154 | } 155 | 156 | @Override 157 | public JsonResult updateInformation(User user) { 158 | int resultCount = userMapper.checkEmailByUserId(user.getEmail(), user.getId()); 159 | if (resultCount > 0) { 160 | return JsonResult.error("email已存在,请更换email再尝试更新"); 161 | } 162 | User updateUser = new User(); 163 | updateUser.setId(user.getId()); 164 | updateUser.setEmail(user.getEmail()); 165 | updateUser.setPhone(user.getPhone()); 166 | updateUser.setQuestion(user.getQuestion()); 167 | updateUser.setAnswer(user.getAnswer()); 168 | updateUser.setUpdateTime(new Date()); 169 | int updateCount = userMapper.updateByPrimaryKeySelective(updateUser); 170 | if (updateCount > 0) { 171 | return JsonResult.success("更新个人信息成功", updateUser); 172 | } 173 | return JsonResult.error("更新个人信息失败"); 174 | } 175 | 176 | // backend 177 | 178 | @Override 179 | public JsonResult checkAdminRole(User user) { 180 | if (user != null && user.getRole() == Const.Role.ROLE_ADMIN) { 181 | return JsonResult.success(); 182 | } 183 | return JsonResult.error(); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/main/resources/mappers/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | id, username, password, email, phone, question, answer, role, create_time, update_time 20 | 21 | 27 | 28 | delete from mmall_user 29 | where id = #{id,jdbcType=INTEGER} 30 | 31 | 32 | insert into mmall_user (id, username, password, 33 | email, phone, question, 34 | answer, role, create_time, 35 | update_time) 36 | values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, 37 | #{email,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{question,jdbcType=VARCHAR}, 38 | #{answer,jdbcType=VARCHAR}, #{role,jdbcType=INTEGER}, now(), 39 | now()) 40 | 41 | 42 | insert into mmall_user 43 | 44 | 45 | id, 46 | 47 | 48 | username, 49 | 50 | 51 | password, 52 | 53 | 54 | email, 55 | 56 | 57 | phone, 58 | 59 | 60 | question, 61 | 62 | 63 | answer, 64 | 65 | 66 | role, 67 | 68 | 69 | create_time, 70 | 71 | 72 | update_time, 73 | 74 | 75 | 76 | 77 | #{id,jdbcType=INTEGER}, 78 | 79 | 80 | #{username,jdbcType=VARCHAR}, 81 | 82 | 83 | #{password,jdbcType=VARCHAR}, 84 | 85 | 86 | #{email,jdbcType=VARCHAR}, 87 | 88 | 89 | #{phone,jdbcType=VARCHAR}, 90 | 91 | 92 | #{question,jdbcType=VARCHAR}, 93 | 94 | 95 | #{answer,jdbcType=VARCHAR}, 96 | 97 | 98 | #{role,jdbcType=INTEGER}, 99 | 100 | 101 | now(), 102 | 103 | 104 | now(), 105 | 106 | 107 | 108 | 109 | update mmall_user 110 | 111 | 112 | username = #{username,jdbcType=VARCHAR}, 113 | 114 | 115 | password = #{password,jdbcType=VARCHAR}, 116 | 117 | 118 | email = #{email,jdbcType=VARCHAR}, 119 | 120 | 121 | phone = #{phone,jdbcType=VARCHAR}, 122 | 123 | 124 | question = #{question,jdbcType=VARCHAR}, 125 | 126 | 127 | answer = #{answer,jdbcType=VARCHAR}, 128 | 129 | 130 | role = #{role,jdbcType=INTEGER}, 131 | 132 | 133 | create_time = #{createTime,jdbcType=TIMESTAMP}, 134 | 135 | 136 | update_time = now(), 137 | 138 | 139 | where id = #{id,jdbcType=INTEGER} 140 | 141 | 142 | update mmall_user 143 | set username = #{username,jdbcType=VARCHAR}, 144 | password = #{password,jdbcType=VARCHAR}, 145 | email = #{email,jdbcType=VARCHAR}, 146 | phone = #{phone,jdbcType=VARCHAR}, 147 | question = #{question,jdbcType=VARCHAR}, 148 | answer = #{answer,jdbcType=VARCHAR}, 149 | role = #{role,jdbcType=INTEGER}, 150 | create_time = #{createTime,jdbcType=TIMESTAMP}, 151 | update_time = now() 152 | where id = #{id,jdbcType=INTEGER} 153 | 154 | 155 | 160 | 161 | 166 | 167 | 174 | 175 | 180 | 181 | 188 | 189 | 190 | update mmall_user 191 | set password = #{passwordNew}, update_time = now() 192 | where username = #{username} 193 | 194 | 195 | 201 | 202 | 208 | -------------------------------------------------------------------------------- /src/main/java/com/mmall/service/impl/CartServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mmall.service.impl; 2 | 3 | import com.google.common.base.Splitter; 4 | import com.google.common.collect.Lists; 5 | import com.mmall.common.Const; 6 | import com.mmall.common.JsonResult; 7 | import com.mmall.common.ResponseCodeEnum; 8 | import com.mmall.dao.CartMapper; 9 | import com.mmall.dao.ProductMapper; 10 | import com.mmall.pojo.Cart; 11 | import com.mmall.pojo.Product; 12 | import com.mmall.service.CartService; 13 | import com.mmall.util.BigDecimalUtils; 14 | import com.mmall.util.PropertiesUtils; 15 | import com.mmall.vo.CartProductVO; 16 | import com.mmall.vo.CartVO; 17 | import org.apache.commons.collections.CollectionUtils; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.stereotype.Service; 20 | 21 | import java.math.BigDecimal; 22 | import java.util.List; 23 | 24 | /** 25 | * 购物车Service的实现类 26 | *

27 | * @Author LeifChen 28 | * @Date 2019-03-01 29 | */ 30 | @Service("cartService") 31 | public class CartServiceImpl implements CartService { 32 | 33 | @Autowired 34 | private CartMapper cartMapper; 35 | @Autowired 36 | private ProductMapper productMapper; 37 | 38 | @Override 39 | public JsonResult add(Integer userId, Integer productId, Integer count) { 40 | if (productId == null || count == null) { 41 | return JsonResult.error(ResponseCodeEnum.ILLEGAL_ARGUMENT.getCode(), ResponseCodeEnum.ILLEGAL_ARGUMENT.getDesc()); 42 | } 43 | 44 | Cart cart = cartMapper.selectByUserIdAndProductId(userId, productId); 45 | if (cart == null) { 46 | // 该商品不在购物车里,表示新增 47 | Cart cartItem = new Cart(); 48 | cartItem.setQuantity(count); 49 | cartItem.setChecked(Const.Cart.CHECKED); 50 | cartItem.setUserId(userId); 51 | cartItem.setProductId(productId); 52 | cartMapper.insert(cartItem); 53 | } else { 54 | // 该商品已在购物车里,表示修改 55 | count = cart.getQuantity() + count; 56 | cart.setQuantity(count); 57 | cartMapper.updateByPrimaryKeySelective(cart); 58 | } 59 | return list(userId); 60 | } 61 | 62 | @Override 63 | public JsonResult update(Integer userId, Integer productId, Integer count) { 64 | if (productId == null || count == null) { 65 | return JsonResult.error(ResponseCodeEnum.ILLEGAL_ARGUMENT.getCode(), ResponseCodeEnum.ILLEGAL_ARGUMENT.getDesc()); 66 | } 67 | 68 | Cart cart = cartMapper.selectByUserIdAndProductId(userId, productId); 69 | if (cart != null) { 70 | cart.setQuantity(count); 71 | } 72 | cartMapper.updateByPrimaryKeySelective(cart); 73 | return list(userId); 74 | } 75 | 76 | @Override 77 | public JsonResult deleteProduct(Integer userId, String productIds) { 78 | List productList = Splitter.on(",").splitToList(productIds); 79 | if (CollectionUtils.isEmpty(productList)) { 80 | return JsonResult.error(ResponseCodeEnum.ILLEGAL_ARGUMENT.getCode(), ResponseCodeEnum.ILLEGAL_ARGUMENT.getDesc()); 81 | } 82 | cartMapper.deleteByUserIdAndProductIds(userId, productList); 83 | return list(userId); 84 | } 85 | 86 | @Override 87 | public JsonResult list(Integer userId) { 88 | CartVO cartVO = getCartVOLimit(userId); 89 | return JsonResult.success(cartVO); 90 | } 91 | 92 | @Override 93 | public JsonResult selectOrUnselect(Integer userId, Integer productId, Integer checked) { 94 | cartMapper.checkedOrUncheckedProduct(userId, productId, checked); 95 | return list(userId); 96 | } 97 | 98 | @Override 99 | public JsonResult getCartProductCount(Integer userId) { 100 | if (userId == null) { 101 | return JsonResult.success(0); 102 | } 103 | return JsonResult.success(cartMapper.selectCartProductCount(userId)); 104 | } 105 | 106 | /** 107 | * 限制购物车里商品的购买数量 108 | * @param userId 用户id 109 | * @return 110 | */ 111 | private CartVO getCartVOLimit(Integer userId) { 112 | CartVO cartVO = new CartVO(); 113 | List cartList = cartMapper.selectByUserId(userId); 114 | List cartProductVOList = Lists.newArrayList(); 115 | 116 | BigDecimal cartTotalPrice = BigDecimal.ZERO; 117 | if (CollectionUtils.isNotEmpty(cartList)) { 118 | for (Cart cartItem : cartList) { 119 | CartProductVO cartProductVO = new CartProductVO(); 120 | cartProductVO.setId(cartItem.getId()); 121 | cartProductVO.setUserId(cartItem.getUserId()); 122 | cartProductVO.setProductId(cartItem.getProductId()); 123 | 124 | Product product = productMapper.selectByPrimaryKey(cartItem.getProductId()); 125 | if (product != null) { 126 | cartProductVO.setProductMainImage(product.getMainImage()); 127 | cartProductVO.setProductName(product.getName()); 128 | cartProductVO.setProductSubtitle(product.getSubtitle()); 129 | cartProductVO.setProductStatus(product.getStatus()); 130 | cartProductVO.setProductPrice(product.getPrice()); 131 | cartProductVO.setProductStock(product.getStock()); 132 | // 判断库存 133 | int buyLimitCount; 134 | if (product.getStock() >= cartItem.getQuantity()) { 135 | // 库存充足 136 | buyLimitCount = cartItem.getQuantity(); 137 | cartProductVO.setLimitQuantity(Const.Cart.LIMIT_NUM_SUCCESS); 138 | } else { 139 | buyLimitCount = product.getStock(); 140 | cartProductVO.setLimitQuantity(Const.Cart.LIMIT_NUM_FAIL); 141 | // 购物车中更新有效库存 142 | Cart cartForQuantity = new Cart(); 143 | cartForQuantity.setId(cartItem.getId()); 144 | cartForQuantity.setQuantity(buyLimitCount); 145 | cartMapper.updateByPrimaryKeySelective(cartForQuantity); 146 | } 147 | cartProductVO.setQuantity(buyLimitCount); 148 | // 计算总价 149 | cartProductVO.setProductTotalPrice(BigDecimalUtils.mul(product.getPrice().doubleValue(), cartProductVO.getQuantity())); 150 | cartProductVO.setProductChecked(cartItem.getChecked()); 151 | } 152 | 153 | // 状态为勾选,增加到整个的购物车总价中 154 | if (cartItem.getChecked() == Const.Cart.CHECKED) { 155 | cartTotalPrice = BigDecimalUtils.add(cartTotalPrice.doubleValue(), cartProductVO.getProductTotalPrice().doubleValue()); 156 | } 157 | cartProductVOList.add(cartProductVO); 158 | } 159 | } 160 | cartVO.setCartTotalPrice(cartTotalPrice); 161 | cartVO.setCartProductVOList(cartProductVOList); 162 | cartVO.setAllChecked(getAllCheckStatus(userId)); 163 | cartVO.setIamgeHost(PropertiesUtils.getProperty("ftp.server.http.prefix", "http://image.mall.com/")); 164 | return cartVO; 165 | } 166 | 167 | /** 168 | * 检查购物车里面的所有商品是否都已被勾选 169 | * @param userId 用户id 170 | * @return 171 | */ 172 | private boolean getAllCheckStatus(Integer userId) { 173 | if (userId == null) { 174 | return false; 175 | } 176 | return cartMapper.selectCheckedStatusByUserId(userId) == 0; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/main/resources/mappers/OrderItemMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | id, user_id, order_no, product_id, product_name, product_image, current_unit_price, 21 | quantity, total_price, create_time, update_time 22 | 23 | 29 | 30 | delete from mmall_order_item 31 | where id = #{id,jdbcType=INTEGER} 32 | 33 | 34 | insert into mmall_order_item (id, user_id, order_no, 35 | product_id, product_name, product_image, 36 | current_unit_price, quantity, total_price, 37 | create_time, update_time) 38 | values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{orderNo,jdbcType=BIGINT}, 39 | #{productId,jdbcType=INTEGER}, #{productName,jdbcType=VARCHAR}, #{productImage,jdbcType=VARCHAR}, 40 | #{currentUnitPrice,jdbcType=DECIMAL}, #{quantity,jdbcType=INTEGER}, #{totalPrice,jdbcType=DECIMAL}, 41 | now(), now()) 42 | 43 | 44 | insert into mmall_order_item 45 | 46 | 47 | id, 48 | 49 | 50 | user_id, 51 | 52 | 53 | order_no, 54 | 55 | 56 | product_id, 57 | 58 | 59 | product_name, 60 | 61 | 62 | product_image, 63 | 64 | 65 | current_unit_price, 66 | 67 | 68 | quantity, 69 | 70 | 71 | total_price, 72 | 73 | 74 | create_time, 75 | 76 | 77 | update_time, 78 | 79 | 80 | 81 | 82 | #{id,jdbcType=INTEGER}, 83 | 84 | 85 | #{userId,jdbcType=INTEGER}, 86 | 87 | 88 | #{orderNo,jdbcType=BIGINT}, 89 | 90 | 91 | #{productId,jdbcType=INTEGER}, 92 | 93 | 94 | #{productName,jdbcType=VARCHAR}, 95 | 96 | 97 | #{productImage,jdbcType=VARCHAR}, 98 | 99 | 100 | #{currentUnitPrice,jdbcType=DECIMAL}, 101 | 102 | 103 | #{quantity,jdbcType=INTEGER}, 104 | 105 | 106 | #{totalPrice,jdbcType=DECIMAL}, 107 | 108 | 109 | now(), 110 | 111 | 112 | now(), 113 | 114 | 115 | 116 | 117 | update mmall_order_item 118 | 119 | 120 | user_id = #{userId,jdbcType=INTEGER}, 121 | 122 | 123 | order_no = #{orderNo,jdbcType=BIGINT}, 124 | 125 | 126 | product_id = #{productId,jdbcType=INTEGER}, 127 | 128 | 129 | product_name = #{productName,jdbcType=VARCHAR}, 130 | 131 | 132 | product_image = #{productImage,jdbcType=VARCHAR}, 133 | 134 | 135 | current_unit_price = #{currentUnitPrice,jdbcType=DECIMAL}, 136 | 137 | 138 | quantity = #{quantity,jdbcType=INTEGER}, 139 | 140 | 141 | total_price = #{totalPrice,jdbcType=DECIMAL}, 142 | 143 | 144 | create_time = #{createTime,jdbcType=TIMESTAMP}, 145 | 146 | 147 | update_time = now(), 148 | 149 | 150 | where id = #{id,jdbcType=INTEGER} 151 | 152 | 153 | update mmall_order_item 154 | set user_id = #{userId,jdbcType=INTEGER}, 155 | order_no = #{orderNo,jdbcType=BIGINT}, 156 | product_id = #{productId,jdbcType=INTEGER}, 157 | product_name = #{productName,jdbcType=VARCHAR}, 158 | product_image = #{productImage,jdbcType=VARCHAR}, 159 | current_unit_price = #{currentUnitPrice,jdbcType=DECIMAL}, 160 | quantity = #{quantity,jdbcType=INTEGER}, 161 | total_price = #{totalPrice,jdbcType=DECIMAL}, 162 | create_time = #{createTime,jdbcType=TIMESTAMP}, 163 | update_time = now() 164 | where id = #{id,jdbcType=INTEGER} 165 | 166 | 167 | 174 | 175 | 181 | 182 | 183 | insert into mmall_order_item 184 | (id, user_id, order_no, 185 | product_id, product_name, product_image, 186 | current_unit_price, quantity, total_price, 187 | create_time, update_time) 188 | values 189 | 190 | (#{item.id}, #{item.userId}, #{item.orderNo}, 191 | #{item.productId}, #{item.productName}, #{item.productImage}, 192 | #{item.currentUnitPrice}, #{item.quantity}, #{item.totalPrice}, 193 | now(), now() 194 | ) 195 | 196 | 197 | -------------------------------------------------------------------------------- /src/main/resources/mappers/ProductMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | id, category_id, name, subtitle, main_image, sub_images, detail, price, stock, status, 22 | create_time, update_time 23 | 24 | 30 | 31 | delete from mmall_product 32 | where id = #{id,jdbcType=INTEGER} 33 | 34 | 35 | insert into mmall_product (id, category_id, name, 36 | subtitle, main_image, sub_images, 37 | detail, price, stock, 38 | status, create_time, update_time 39 | ) 40 | values (#{id,jdbcType=INTEGER}, #{categoryId,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, 41 | #{subtitle,jdbcType=VARCHAR}, #{mainImage,jdbcType=VARCHAR}, #{subImages,jdbcType=VARCHAR}, 42 | #{detail,jdbcType=VARCHAR}, #{price,jdbcType=DECIMAL}, #{stock,jdbcType=INTEGER}, 43 | #{status,jdbcType=INTEGER}, now(), now() 44 | ) 45 | 46 | 47 | insert into mmall_product 48 | 49 | 50 | id, 51 | 52 | 53 | category_id, 54 | 55 | 56 | name, 57 | 58 | 59 | subtitle, 60 | 61 | 62 | main_image, 63 | 64 | 65 | sub_images, 66 | 67 | 68 | detail, 69 | 70 | 71 | price, 72 | 73 | 74 | stock, 75 | 76 | 77 | status, 78 | 79 | 80 | create_time, 81 | 82 | 83 | update_time, 84 | 85 | 86 | 87 | 88 | #{id,jdbcType=INTEGER}, 89 | 90 | 91 | #{categoryId,jdbcType=INTEGER}, 92 | 93 | 94 | #{name,jdbcType=VARCHAR}, 95 | 96 | 97 | #{subtitle,jdbcType=VARCHAR}, 98 | 99 | 100 | #{mainImage,jdbcType=VARCHAR}, 101 | 102 | 103 | #{subImages,jdbcType=VARCHAR}, 104 | 105 | 106 | #{detail,jdbcType=VARCHAR}, 107 | 108 | 109 | #{price,jdbcType=DECIMAL}, 110 | 111 | 112 | #{stock,jdbcType=INTEGER}, 113 | 114 | 115 | #{status,jdbcType=INTEGER}, 116 | 117 | 118 | now(), 119 | 120 | 121 | now(), 122 | 123 | 124 | 125 | 126 | update mmall_product 127 | 128 | 129 | category_id = #{categoryId,jdbcType=INTEGER}, 130 | 131 | 132 | name = #{name,jdbcType=VARCHAR}, 133 | 134 | 135 | subtitle = #{subtitle,jdbcType=VARCHAR}, 136 | 137 | 138 | main_image = #{mainImage,jdbcType=VARCHAR}, 139 | 140 | 141 | sub_images = #{subImages,jdbcType=VARCHAR}, 142 | 143 | 144 | detail = #{detail,jdbcType=VARCHAR}, 145 | 146 | 147 | price = #{price,jdbcType=DECIMAL}, 148 | 149 | 150 | stock = #{stock,jdbcType=INTEGER}, 151 | 152 | 153 | status = #{status,jdbcType=INTEGER}, 154 | 155 | 156 | create_time = #{createTime,jdbcType=TIMESTAMP}, 157 | 158 | 159 | update_time = now(), 160 | 161 | 162 | where id = #{id,jdbcType=INTEGER} 163 | 164 | 165 | update mmall_product 166 | set category_id = #{categoryId,jdbcType=INTEGER}, 167 | name = #{name,jdbcType=VARCHAR}, 168 | subtitle = #{subtitle,jdbcType=VARCHAR}, 169 | main_image = #{mainImage,jdbcType=VARCHAR}, 170 | sub_images = #{subImages,jdbcType=VARCHAR}, 171 | detail = #{detail,jdbcType=VARCHAR}, 172 | price = #{price,jdbcType=DECIMAL}, 173 | stock = #{stock,jdbcType=INTEGER}, 174 | status = #{status,jdbcType=INTEGER}, 175 | create_time = #{createTime,jdbcType=TIMESTAMP}, 176 | update_time = now() 177 | where id = #{id,jdbcType=INTEGER} 178 | 179 | 180 | 186 | 187 | 200 | 201 | 216 | 217 | 223 | --------------------------------------------------------------------------------