├── pic ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png └── 6.png ├── src ├── main │ ├── resources │ │ └── application.properties │ └── java │ │ └── com │ │ └── sport │ │ └── sportsmallserver │ │ ├── exception │ │ ├── TokenException.java │ │ ├── SecurityServerException.java │ │ ├── IdNotFoundException.java │ │ ├── NullFiledException.java │ │ ├── BaseException.java │ │ ├── ErrorHandler.java │ │ └── ExceptionResolver.java │ │ ├── repository │ │ ├── RoleRepository.java │ │ ├── CommodityTypeRepository.java │ │ ├── OrderRepository.java │ │ ├── UserRepository.java │ │ ├── CarouselRepository.java │ │ ├── CommodityDetailRepository.java │ │ ├── CommentRepository.java │ │ ├── CartRepository.java │ │ └── CommodityRepository.java │ │ ├── security │ │ ├── MustUserLogin.java │ │ ├── MustAdminLogin.java │ │ ├── SecurityArgumentResolversWebMvcConfig.java │ │ ├── MustLogin.java │ │ └── SecurityHandlerMethodArgumentResolver.java │ │ ├── SportsMallServerApplication.java │ │ ├── entity │ │ ├── CartPrimaryKey.java │ │ ├── Role.java │ │ ├── CommodityDetail.java │ │ ├── CommodityType.java │ │ ├── Cart.java │ │ ├── User.java │ │ ├── Carousel.java │ │ ├── Comment.java │ │ ├── Commodity.java │ │ └── Order.java │ │ ├── dto │ │ ├── CarouselDTO.java │ │ ├── CommentDTO.java │ │ ├── LoginUser.java │ │ ├── CommodityDTO.java │ │ └── RestModel.java │ │ ├── service │ │ ├── CommodityDetailService.java │ │ ├── CommodityTypeService.java │ │ ├── CommentService.java │ │ ├── CarouselService.java │ │ ├── CartService.java │ │ ├── UserService.java │ │ ├── CommodityService.java │ │ ├── OrderService.java │ │ └── impl │ │ │ ├── CommodityDetailServiceImpl.java │ │ │ ├── CarouselServiceImpl.java │ │ │ ├── CommodityTypeServiceImpl.java │ │ │ ├── CartServiceImpl.java │ │ │ ├── CommentServiceImpl.java │ │ │ ├── UserServiceImpl.java │ │ │ ├── CommodityServiceImpl.java │ │ │ └── OrderServiceImpl.java │ │ ├── config │ │ ├── CustomWebMvcConfig.java │ │ └── AppTomcatConnectorCustomizer.java │ │ ├── util │ │ ├── OrikaUtils.java │ │ └── JwtUtils.java │ │ └── controller │ │ ├── CommodityDetailController.java │ │ ├── CommentController.java │ │ ├── CommodityTypeController.java │ │ ├── CarouselController.java │ │ ├── CartController.java │ │ ├── UserController.java │ │ ├── CommodityController.java │ │ └── OrderController.java └── test │ └── java │ └── com │ └── sport │ └── sportsmallserver │ └── SportsMallServerApplicationTests.java ├── .gitignore ├── pom.xml ├── README.md ├── mvnw.cmd ├── mvnw └── LICENSE /pic/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/1.png -------------------------------------------------------------------------------- /pic/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/2.png -------------------------------------------------------------------------------- /pic/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/3.png -------------------------------------------------------------------------------- /pic/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/4.png -------------------------------------------------------------------------------- /pic/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/5.png -------------------------------------------------------------------------------- /pic/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/6.png -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/sports-mall-server/master/src/main/resources/application.properties -------------------------------------------------------------------------------- /src/test/java/com/sport/sportsmallserver/SportsMallServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SportsMallServerApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/exception/TokenException.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | /** 6 | * @author itning 7 | */ 8 | public class TokenException extends BaseException { 9 | public TokenException(String msg, HttpStatus code) { 10 | super(msg, code); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.Role; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @author itning 8 | * @date 2020/2/12 10:54 9 | */ 10 | public interface RoleRepository extends JpaRepository { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/security/MustUserLogin.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.security; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 必须是用户登录 7 | * 8 | * @author itning 9 | */ 10 | @Target(ElementType.PARAMETER) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | @MustLogin(role = MustLogin.ROLE.USER) 14 | public @interface MustUserLogin { 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/security/MustAdminLogin.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.security; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 必须是管理员登录 7 | * 8 | * @author itning 9 | */ 10 | @Target(ElementType.PARAMETER) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | @MustLogin(role = MustLogin.ROLE.ADMIN) 14 | public @interface MustAdminLogin { 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/CommodityTypeRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.CommodityType; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @author itning 8 | * @date 2020/2/11 21:12 9 | */ 10 | public interface CommodityTypeRepository extends JpaRepository { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/exception/SecurityServerException.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | /** 6 | * @author itning 7 | * @date 2020/2/12 11:18 8 | */ 9 | public class SecurityServerException extends BaseException { 10 | public SecurityServerException(String msg, HttpStatus code) { 11 | super(msg, code); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/exception/IdNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | /** 6 | * 主键不存在 7 | * 8 | * @author itning 9 | * @date 2020/2/12 11:34 10 | */ 11 | public class IdNotFoundException extends BaseException { 12 | public IdNotFoundException(String msg) { 13 | super(msg, HttpStatus.NOT_FOUND); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/exception/NullFiledException.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | /** 6 | * 传入的参数为空 7 | * 8 | * @author itning 9 | * @date 2020/2/12 11:34 10 | */ 11 | public class NullFiledException extends BaseException { 12 | public NullFiledException(String msg) { 13 | super(msg, HttpStatus.BAD_REQUEST); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/** 4 | !**/src/test/** 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | build/ 28 | 29 | ### VS Code ### 30 | .vscode/ 31 | 32 | .mvn/ 33 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.Order; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 6 | 7 | /** 8 | * @author itning 9 | * @date 2020/2/11 21:19 10 | */ 11 | public interface OrderRepository extends JpaRepository, JpaSpecificationExecutor { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/SportsMallServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author itning 8 | */ 9 | @SpringBootApplication 10 | public class SportsMallServerApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(SportsMallServerApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.User; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @author itning 8 | * @date 2020/2/11 20:17 9 | */ 10 | public interface UserRepository extends JpaRepository { 11 | /** 12 | * 查询邮箱是否存在 13 | * 14 | * @param email 邮箱 15 | * @return 存在? 16 | */ 17 | boolean existsByEmail(String email); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/CartPrimaryKey.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | *

购物车复合主键 9 | *

所属实体{@link Cart} 10 | * 11 | * @author itning 12 | * @date 2020/2/11 20:41 13 | * @see Cart 14 | * @see java.io.Serializable 15 | */ 16 | @Data 17 | public class CartPrimaryKey implements Serializable { 18 | /** 19 | * 用户 20 | */ 21 | private String user; 22 | /** 23 | * 商品 24 | */ 25 | private String commodity; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/dto/CarouselDTO.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author itning 9 | * @date 2020/2/13 17:44 10 | */ 11 | @Data 12 | public class CarouselDTO implements Serializable { 13 | /** 14 | * ID 15 | */ 16 | private String id; 17 | /** 18 | * URL 19 | */ 20 | private String url; 21 | /** 22 | * 轮播类型(默认水平) 23 | */ 24 | private Integer type; 25 | /** 26 | * 链接 27 | */ 28 | private String link; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/CarouselRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.Carousel; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author itning 10 | * @date 2020/2/13 12:38 11 | */ 12 | public interface CarouselRepository extends JpaRepository { 13 | /** 14 | * 根据类型获取轮播图 15 | * 16 | * @param type 类型 17 | * @return 轮播图集合 18 | */ 19 | List findAllByType(int type); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/CommodityDetailRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.Commodity; 4 | import com.sport.sportsmallserver.entity.CommodityDetail; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import java.util.Optional; 8 | 9 | /** 10 | * @author itning 11 | * @date 2020/2/12 15:20 12 | */ 13 | public interface CommodityDetailRepository extends JpaRepository { 14 | /** 15 | * 根据商品ID获取商品详情 16 | * 17 | * @param commodity 商品 18 | * @return 商品详情 19 | */ 20 | Optional findByCommodity(Commodity commodity); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/CommodityDetailService.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service; 2 | 3 | import com.sport.sportsmallserver.entity.CommodityDetail; 4 | 5 | /** 6 | * 商品详情服务 7 | * 8 | * @author itning 9 | * @date 2020/2/12 15:32 10 | */ 11 | public interface CommodityDetailService { 12 | /** 13 | * 根据商品ID获取商品详情 14 | * 15 | * @param commodityId 商品ID 16 | * @return 商品详情 17 | */ 18 | CommodityDetail findByCommodityId(String commodityId); 19 | 20 | /** 21 | *

修改商品详情 22 | *

如果商品详情ID不存在并且商品ID存在则会新增商品详情 23 | * 24 | * @param commodityDetail 商品详情 25 | */ 26 | void modifyOrAdd(CommodityDetail commodityDetail); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/dto/CommentDTO.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | 8 | /** 9 | * 评论信息DTO 10 | * 11 | * @author itning 12 | * @date 2020/2/12 15:55 13 | */ 14 | @Data 15 | public class CommentDTO implements Serializable { 16 | /** 17 | * ID 18 | */ 19 | private String id; 20 | /** 21 | * 用户 22 | */ 23 | private String username; 24 | /** 25 | * 内容 26 | */ 27 | private String content; 28 | /** 29 | * 创建时间 30 | */ 31 | private Date gmtCreate; 32 | /** 33 | * 更新时间 34 | */ 35 | private Date gmtModified; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/CommentRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.Comment; 4 | import com.sport.sportsmallserver.entity.Commodity; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | 9 | /** 10 | * @author itning 11 | * @date 2020/2/12 10:36 12 | */ 13 | public interface CommentRepository extends JpaRepository { 14 | /** 15 | * 根据商品查询评价 16 | * 17 | * @param commodity 商品 18 | * @param pageable 分页 19 | * @return 评价集合 20 | */ 21 | Page findByCommodity(Commodity commodity, Pageable pageable); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/config/CustomWebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | /** 8 | * MVC参数配置 9 | * 10 | * @author itning 11 | */ 12 | @Configuration 13 | public class CustomWebMvcConfig implements WebMvcConfigurer { 14 | @Override 15 | public void addCorsMappings(CorsRegistry registry) { 16 | registry.addMapping("/**") 17 | .allowedOrigins("*") 18 | .allowCredentials(true) 19 | .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH") 20 | .maxAge(86400); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/exception/BaseException.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | /** 6 | * 异常基类 7 | * 8 | * @author itning 9 | */ 10 | public abstract class BaseException extends RuntimeException { 11 | private String msg; 12 | private HttpStatus code; 13 | 14 | public BaseException(String msg, HttpStatus code) { 15 | super(msg); 16 | this.msg = msg; 17 | this.code = code; 18 | } 19 | 20 | public String getMsg() { 21 | return msg; 22 | } 23 | 24 | public void setMsg(String msg) { 25 | this.msg = msg; 26 | } 27 | 28 | public HttpStatus getCode() { 29 | return code; 30 | } 31 | 32 | public void setCode(HttpStatus code) { 33 | this.code = code; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/CommodityTypeService.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service; 2 | 3 | import com.sport.sportsmallserver.entity.CommodityType; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author itning 9 | * @date 2020/2/12 12:27 10 | */ 11 | public interface CommodityTypeService { 12 | /** 13 | * 获取所有商品分类 14 | * 15 | * @return 分类集合 16 | */ 17 | List getAll(); 18 | 19 | /** 20 | * 修改分类信息 21 | * 22 | * @param commodityType 分类 23 | */ 24 | void modifyCommodityType(CommodityType commodityType); 25 | 26 | /** 27 | * 删除分类 28 | * 29 | * @param id 编号 30 | */ 31 | void delCommodityType(String id); 32 | 33 | /** 34 | * 添加分类 35 | * 36 | * @param name 分类名 37 | * @return 新增的分类 38 | */ 39 | CommodityType add(String name); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/dto/LoginUser.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.dto; 2 | 3 | import com.sport.sportsmallserver.entity.Role; 4 | import com.sport.sportsmallserver.entity.User; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * 登录用户 12 | * 13 | * @author itning 14 | * @date 2020/2/12 11:07 15 | * @see User 16 | */ 17 | @Data 18 | public class LoginUser implements Serializable { 19 | /** 20 | * 用户名(唯一) 21 | */ 22 | private String username; 23 | /** 24 | * 邮箱(唯一) 25 | */ 26 | private String email; 27 | /** 28 | * 电话 29 | */ 30 | private String tel; 31 | /** 32 | * 收货地址 33 | */ 34 | private String address; 35 | /** 36 | * 所属角色 37 | */ 38 | private Role role; 39 | /** 40 | * 创建时间 41 | */ 42 | private Date gmtCreate; 43 | /** 44 | * 更新时间 45 | */ 46 | private Date gmtModified; 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/CommentService.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service; 2 | 3 | import com.sport.sportsmallserver.dto.CommentDTO; 4 | import com.sport.sportsmallserver.dto.LoginUser; 5 | import com.sport.sportsmallserver.entity.Comment; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | 9 | /** 10 | * 评论服务 11 | * 12 | * @author itning 13 | * @date 2020/2/12 15:52 14 | */ 15 | public interface CommentService { 16 | /** 17 | * 根据商品ID查找评论 18 | * 19 | * @param commodityId 商品ID 20 | * @param pageable 分页 21 | * @return 评论集合 22 | */ 23 | Page findByCommodityId(String commodityId, Pageable pageable); 24 | 25 | /** 26 | * 新评论 27 | * 28 | * @param loginUser 登录用户 29 | * @param orderId 订单ID 30 | * @param content 内容 31 | * @return 评论 32 | */ 33 | Comment newComment(LoginUser loginUser, String orderId, String content); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/CarouselService.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service; 2 | 3 | import com.sport.sportsmallserver.dto.CarouselDTO; 4 | import com.sport.sportsmallserver.entity.Carousel; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 走马灯服务 10 | * 11 | * @author itning 12 | * @date 2020/2/13 12:39 13 | */ 14 | public interface CarouselService { 15 | /** 16 | * 获取所有走马灯列表 17 | * 18 | * @param type 类型 19 | * @return 走马灯集合 20 | */ 21 | List getAll(int type); 22 | 23 | /** 24 | * 添加走马灯 25 | * 26 | * @param url 网址 27 | * @param link 链接 28 | * @param type 类型 29 | * @return 新增的走马灯 30 | */ 31 | Carousel add(String url, String link, int type); 32 | 33 | /** 34 | * 删除走马灯 35 | * 36 | * @param id ID 37 | */ 38 | void del(String id); 39 | 40 | /** 41 | * 修改走马灯 42 | * 43 | * @param carousel 走马灯 44 | */ 45 | void modify(CarouselDTO carousel); 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/CartRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.Cart; 4 | import com.sport.sportsmallserver.entity.CartPrimaryKey; 5 | import com.sport.sportsmallserver.entity.Commodity; 6 | import com.sport.sportsmallserver.entity.User; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.jpa.repository.JpaRepository; 10 | 11 | /** 12 | * @author itning 13 | * @date 2020/2/11 21:12 14 | */ 15 | public interface CartRepository extends JpaRepository { 16 | /** 17 | * 查找某个用户的购物车信息 18 | * 19 | * @param user 用户 20 | * @param pageable 分页 21 | * @return 购物车集合 22 | */ 23 | Page findAllByUser(User user, Pageable pageable); 24 | 25 | /** 26 | * 删除购物车某样商品 27 | * 28 | * @param commodity 商品 29 | * @param user 用户 30 | */ 31 | void deleteByCommodityAndUser(Commodity commodity, User user); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/security/SecurityArgumentResolversWebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * MVC参数配置 12 | * 13 | * @author itning 14 | */ 15 | @Configuration 16 | public class SecurityArgumentResolversWebMvcConfig implements WebMvcConfigurer { 17 | private final SecurityHandlerMethodArgumentResolver securityHandlerMethodArgumentResolver; 18 | 19 | @Autowired 20 | public SecurityArgumentResolversWebMvcConfig(SecurityHandlerMethodArgumentResolver securityHandlerMethodArgumentResolver) { 21 | this.securityHandlerMethodArgumentResolver = securityHandlerMethodArgumentResolver; 22 | } 23 | 24 | @Override 25 | public void addArgumentResolvers(List resolvers) { 26 | resolvers.add(securityHandlerMethodArgumentResolver); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/dto/CommodityDTO.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.dto; 2 | 3 | import com.sport.sportsmallserver.entity.CommodityType; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * @author itning 11 | * @date 2020/2/13 22:08 12 | */ 13 | @Data 14 | public class CommodityDTO implements Serializable { 15 | /** 16 | *

商品ID 区分每个商品 17 | *

自动主键生成 18 | */ 19 | private String id; 20 | /** 21 | * 商品名 22 | */ 23 | private String name; 24 | /** 25 | * 库存,默认为 1 26 | */ 27 | private Integer stock; 28 | /** 29 | *

单价 30 | *

小数位数2位(角,分) 31 | */ 32 | private BigDecimal price; 33 | /** 34 | * 商品图片地址(主图片) 35 | */ 36 | private String imgMain; 37 | /** 38 | *

其它图片地址(使用英文分号进行分隔) 39 | *

主要用于详情展示 40 | */ 41 | private String imgSecond; 42 | /** 43 | * 推荐商品(会展示在首页) 44 | */ 45 | private Boolean recommended; 46 | /** 47 | * 商品已下架? 48 | */ 49 | private Boolean takeOff; 50 | /** 51 | * 商品分类 52 | */ 53 | private CommodityType commodityType; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/CartService.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.entity.Cart; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | /** 9 | * 购物车服务 10 | * 11 | * @author itning 12 | * @date 2020/2/12 16:45 13 | */ 14 | public interface CartService { 15 | /** 16 | *

商品加入购物车 17 | *

每调用一次商品数量变为num 18 | * 19 | * @param loginUser 登录用户 20 | * @param commodityId 商品ID 21 | * @param num 数量 22 | * @param cumulative 累加 23 | * @return 加入的购物车 24 | */ 25 | Cart addToCart(LoginUser loginUser, String commodityId, int num, boolean cumulative); 26 | 27 | /** 28 | * 获取所有购物车 29 | * 30 | * @param loginUser 登录用户 31 | * @param pageable 分页 32 | * @return 购物车集合 33 | */ 34 | Page getAll(LoginUser loginUser, Pageable pageable); 35 | 36 | /** 37 | * 删除购物车某样商品 38 | * 39 | * @param loginUser 登录用户 40 | * @param commodityId 商品ID 41 | */ 42 | void delCart(LoginUser loginUser, String commodityId); 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/security/MustLogin.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.security; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 表示登录后才可以进行访问 7 | * 8 | * @author itning 9 | */ 10 | @Target({ElementType.PARAMETER, ElementType.TYPE}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | @Inherited 14 | public @interface MustLogin { 15 | /** 16 | * 登录角色 17 | * 18 | * @return 角色数组 19 | */ 20 | ROLE[] role(); 21 | 22 | enum ROLE { 23 | /** 24 | * 管理员 25 | */ 26 | ADMIN("1", "管理员"), 27 | /** 28 | * 用户 29 | */ 30 | USER("2", "用户"); 31 | 32 | private final String id; 33 | private final String name; 34 | 35 | ROLE(String id, String name) { 36 | this.id = id; 37 | this.name = name; 38 | } 39 | 40 | public String getId() { 41 | return id; 42 | } 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | return "ROLE{" + 51 | "id='" + id + '\'' + 52 | ", name='" + name + '\'' + 53 | '}'; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.sport.sportsmallserver.dto.LoginUser; 5 | import com.sport.sportsmallserver.entity.User; 6 | 7 | /** 8 | * 用户服务 9 | * 10 | * @author itning 11 | * @date 2020/2/12 11:29 12 | */ 13 | public interface UserService { 14 | /** 15 | * 用户登录 16 | * 17 | * @param username 用户名 18 | * @param password 密码 19 | * @return jwt token 20 | * @throws JsonProcessingException JWT构建失败 21 | */ 22 | String login(String username, String password) throws JsonProcessingException; 23 | 24 | /** 25 | * 修改用户信息 26 | * 27 | * @param loginUser 登录用户 28 | * @param user 新用户信息 29 | */ 30 | void modifyUser(LoginUser loginUser, User user); 31 | 32 | /** 33 | * 用户注册 34 | * 35 | * @param username 用户名 36 | * @param email 邮箱 37 | * @param phone 电话 38 | * @param password 密码 39 | * @return 用户 40 | */ 41 | LoginUser reg(String username, String email, String phone, String password); 42 | 43 | /** 44 | * 修改密码 45 | * 46 | * @param loginUser 登录用户 47 | * @param oldPwd 旧密码 48 | * @param newPwd 新密码 49 | */ 50 | void changePwd(LoginUser loginUser, String oldPwd, String newPwd); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import com.sport.sportsmallserver.repository.RoleRepository; 4 | import lombok.Data; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.UpdateTimestamp; 7 | 8 | import javax.persistence.Column; 9 | import javax.persistence.Entity; 10 | import javax.persistence.Id; 11 | import java.io.Serializable; 12 | import java.util.Date; 13 | 14 | /** 15 | * 角色 16 | * 17 | * @author itning 18 | * @date 2020/2/12 10:53 19 | * @see RoleRepository 20 | * @see java.io.Serializable 21 | */ 22 | @Data 23 | @Entity(name = "mall_role") 24 | public class Role implements Serializable { 25 | /** 26 | * 管理员ID 27 | */ 28 | public static final String ROLE_ADMIN_ID = "1"; 29 | /** 30 | * 用户ID 31 | */ 32 | public static final String ROLE_USER_ID = "2"; 33 | /** 34 | * ID 35 | */ 36 | @Id 37 | @Column(columnDefinition = "char(1)") 38 | private String id; 39 | /** 40 | * 角色名 41 | */ 42 | @Column(nullable = false, unique = true) 43 | private String name; 44 | /** 45 | * 创建时间 46 | */ 47 | @Column(nullable = false) 48 | @CreationTimestamp 49 | private Date gmtCreate; 50 | /** 51 | * 更新时间 52 | */ 53 | @Column(nullable = false) 54 | @UpdateTimestamp 55 | private Date gmtModified; 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/CommodityDetail.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import lombok.Data; 4 | import org.hibernate.annotations.CreationTimestamp; 5 | import org.hibernate.annotations.GenericGenerator; 6 | import org.hibernate.annotations.UpdateTimestamp; 7 | 8 | import javax.persistence.*; 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | 12 | /** 13 | * 商品详情 14 | * 15 | * @author itning 16 | * @date 2020/2/12 15:09 17 | * @see java.io.Serializable 18 | */ 19 | @Data 20 | @Entity(name = "mall_commodity_detail") 21 | public class CommodityDetail implements Serializable { 22 | /** 23 | * ID 24 | */ 25 | @Id 26 | @GeneratedValue(generator = "idGenerator") 27 | @GenericGenerator(name = "idGenerator", strategy = "org.hibernate.id.UUIDGenerator") 28 | @Column(length = 36, columnDefinition = "char(36)") 29 | private String id; 30 | /** 31 | * 对应商品 32 | */ 33 | @SuppressWarnings("JpaDataSourceORMInspection") 34 | @OneToOne 35 | @JoinColumn(name = "commodity_id", unique = true) 36 | private Commodity commodity; 37 | /** 38 | * 详情 39 | */ 40 | @Column(columnDefinition = "text") 41 | private String detail; 42 | /** 43 | * 创建时间 44 | */ 45 | @Column(nullable = false) 46 | @CreationTimestamp 47 | private Date gmtCreate; 48 | /** 49 | * 更新时间 50 | */ 51 | @Column(nullable = false) 52 | @UpdateTimestamp 53 | private Date gmtModified; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/CommodityType.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import com.sport.sportsmallserver.repository.CommodityTypeRepository; 4 | import lombok.Data; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.GenericGenerator; 7 | import org.hibernate.annotations.UpdateTimestamp; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import java.io.Serializable; 14 | import java.util.Date; 15 | 16 | /** 17 | * 商品分类 18 | * 19 | * @author itning 20 | * @date 2020/2/11 21:54 21 | * @see CommodityTypeRepository 22 | * @see java.io.Serializable 23 | */ 24 | @Data 25 | @Entity(name = "mall_commodity_type") 26 | public class CommodityType implements Serializable { 27 | /** 28 | * 分类ID 29 | */ 30 | @Id 31 | @GeneratedValue(generator = "idGenerator") 32 | @GenericGenerator(name = "idGenerator", strategy = "org.hibernate.id.UUIDGenerator") 33 | @Column(length = 36, columnDefinition = "char(36)") 34 | private String id; 35 | /** 36 | * 商品分类名 37 | */ 38 | @Column(nullable = false) 39 | private String name; 40 | /** 41 | * 创建时间 42 | */ 43 | @Column(nullable = false) 44 | @CreationTimestamp 45 | private Date gmtCreate; 46 | /** 47 | * 更新时间 48 | */ 49 | @Column(nullable = false) 50 | @UpdateTimestamp 51 | private Date gmtModified; 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/Cart.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import com.sport.sportsmallserver.repository.CartRepository; 4 | import lombok.Data; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.UpdateTimestamp; 7 | 8 | import javax.persistence.*; 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | 12 | /** 13 | * 购物车 14 | * 15 | * @author itning 16 | * @date 2020/2/11 20:38 17 | * @see CartRepository 18 | * @see java.io.Serializable 19 | */ 20 | @Data 21 | @Entity(name = "mall_cart") 22 | @IdClass(CartPrimaryKey.class) 23 | public class Cart implements Serializable { 24 | /** 25 | * 用户 26 | */ 27 | @SuppressWarnings("JpaDataSourceORMInspection") 28 | @Id 29 | @ManyToOne(optional = false) 30 | @JoinColumn(name = "userId", columnDefinition = "varchar(255)") 31 | private User user; 32 | /** 33 | * 商品 34 | */ 35 | @SuppressWarnings("JpaDataSourceORMInspection") 36 | @Id 37 | @ManyToOne(optional = false) 38 | @JoinColumn(name = "commodityId", columnDefinition = "char(36)") 39 | private Commodity commodity; 40 | /** 41 | * 数量 42 | */ 43 | @Column(nullable = false, columnDefinition = "int unsigned default 1") 44 | private int countNum; 45 | /** 46 | * 创建时间 47 | */ 48 | @Column(nullable = false) 49 | @CreationTimestamp 50 | private Date gmtCreate; 51 | /** 52 | * 更新时间 53 | */ 54 | @Column(nullable = false) 55 | @UpdateTimestamp 56 | private Date gmtModified; 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import com.sport.sportsmallserver.repository.UserRepository; 4 | import lombok.Data; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.UpdateTimestamp; 7 | 8 | import javax.persistence.*; 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | 12 | /** 13 | * 用户信息 14 | * 15 | * @author itning 16 | * @date 2020/2/11 20:28 17 | * @see UserRepository 18 | * @see java.io.Serializable 19 | */ 20 | @Data 21 | @Entity(name = "mall_user") 22 | public class User implements Serializable { 23 | /** 24 | * 用户名(唯一) 25 | */ 26 | @Id 27 | private String username; 28 | /** 29 | * 密码 30 | */ 31 | @Column(nullable = false) 32 | private String password; 33 | /** 34 | * 邮箱(唯一) 35 | */ 36 | @Column(nullable = false, unique = true) 37 | private String email; 38 | /** 39 | * 电话 40 | */ 41 | @Column(nullable = false) 42 | private String tel; 43 | /** 44 | * 收货地址 45 | */ 46 | @Column(columnDefinition = "text") 47 | private String address; 48 | /** 49 | * 所属角色 50 | */ 51 | @SuppressWarnings("JpaDataSourceORMInspection") 52 | @ManyToOne(optional = false) 53 | @JoinColumn(name = "roleId") 54 | private Role role; 55 | /** 56 | * 创建时间 57 | */ 58 | @Column(nullable = false) 59 | @CreationTimestamp 60 | private Date gmtCreate; 61 | /** 62 | * 更新时间 63 | */ 64 | @Column(nullable = false) 65 | @UpdateTimestamp 66 | private Date gmtModified; 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/util/OrikaUtils.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.util; 2 | 3 | import ma.glasnost.orika.MapperFactory; 4 | import ma.glasnost.orika.impl.DefaultMapperFactory; 5 | import org.springframework.lang.NonNull; 6 | import org.springframework.lang.Nullable; 7 | 8 | /** 9 | * 实体映射工具类 10 | * 11 | * @author itning 12 | */ 13 | public class OrikaUtils { 14 | private static final MapperFactory MAPPER_FACTORY = new DefaultMapperFactory.Builder().build(); 15 | 16 | /** 17 | * 将两个实体合并为一个DTO 18 | * input1,input2 不能全为 {@code null} 19 | * 20 | * @param input1 第一个输入实体 21 | * @param input2 第二个输入实体 22 | * @param result DTO类型 23 | * @param DTO 24 | * @param ENTITY 25 | * @param ENTITY 26 | * @return DTO类型 27 | */ 28 | @NonNull 29 | public static R doubleEntity2Dto(@Nullable A input1, @Nullable B input2, @NonNull Class result) { 30 | if (input1 != null && input2 != null) { 31 | R r = MAPPER_FACTORY.getMapperFacade().map(input1, result); 32 | MAPPER_FACTORY.getMapperFacade().map(input2, r); 33 | return r; 34 | } else if (input1 != null) { 35 | return MAPPER_FACTORY.getMapperFacade().map(input1, result); 36 | } else { 37 | return MAPPER_FACTORY.getMapperFacade().map(input2, result); 38 | } 39 | } 40 | 41 | /** 42 | * A 实体 转换 B 实体 43 | * 44 | * @param a A实例 45 | * @param bClass B类型 46 | * @param A 47 | * @param B 48 | * @return B 实例 49 | */ 50 | public static B a2b(A a, Class bClass) { 51 | return MAPPER_FACTORY.getMapperFacade().map(a, bClass); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/exception/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.exception; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.web.servlet.error.ErrorAttributes; 5 | import org.springframework.boot.web.servlet.error.ErrorController; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | import org.springframework.web.context.request.ServletWebRequest; 10 | import org.springframework.web.context.request.WebRequest; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import java.util.Map; 14 | 15 | /** 16 | * 错误处理器 17 | * 18 | * @author itning 19 | */ 20 | @RestController 21 | public class ErrorHandler implements ErrorController { 22 | private final ErrorAttributes errorAttributes; 23 | 24 | @Autowired 25 | public ErrorHandler(ErrorAttributes errorAttributes) { 26 | this.errorAttributes = errorAttributes; 27 | } 28 | 29 | @Override 30 | public String getErrorPath() { 31 | return "/error"; 32 | } 33 | 34 | @RequestMapping(value = "/error", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 35 | public String error(HttpServletRequest request) { 36 | WebRequest webRequest = new ServletWebRequest(request); 37 | Map errorAttributes = this.errorAttributes.getErrorAttributes(webRequest, true); 38 | String msg = errorAttributes.getOrDefault("error", "not found").toString(); 39 | String code = errorAttributes.getOrDefault("status", 404).toString(); 40 | return "{\"code\":" + code + ",\"msg\":\"" + msg + "\",\"data\":\"\"}"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/repository/CommodityRepository.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.repository; 2 | 3 | import com.sport.sportsmallserver.entity.Commodity; 4 | import com.sport.sportsmallserver.entity.CommodityType; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author itning 13 | * @date 2020/2/11 20:17 14 | */ 15 | public interface CommodityRepository extends JpaRepository { 16 | /** 17 | * 根据商品分类获取商品 18 | * 19 | * @param commodityType 商品类别 20 | * @param takeOff 下架的商品? 21 | * @param pageable 分页 22 | * @return 商品集合 23 | */ 24 | Page findAllByCommodityTypeAndTakeOff(CommodityType commodityType, boolean takeOff, Pageable pageable); 25 | 26 | /** 27 | * 更具是否推荐和是否下架获取商品 28 | * 29 | * @param recommended 推荐商品 30 | * @param takeOff 下架的商品? 31 | * @return 商品集合 32 | */ 33 | List findAllByRecommendedAndTakeOff(boolean recommended, boolean takeOff); 34 | 35 | /** 36 | * 搜索商品 37 | * 38 | * @param takeOff 下架的商品? 39 | * @param nameLike 近似标题 40 | * @param pageable 分页 41 | * @return 商品集合 42 | */ 43 | Page findAllByTakeOffAndNameLike(boolean takeOff, String nameLike, Pageable pageable); 44 | 45 | /** 46 | * 根据商品分类查询该分类下是否有商品 47 | * 48 | * @param commodityType 分类 49 | * @return 有返回true 50 | */ 51 | boolean existsByCommodityType(CommodityType commodityType); 52 | 53 | /** 54 | * 查询所有商品 55 | * 56 | * @param takeOff 已下架? 57 | * @param pageable 分页 58 | * @return 商品集合 59 | */ 60 | Page findAllByTakeOff(boolean takeOff, Pageable pageable); 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/dto/RestModel.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.dto; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Rest 返回消息 10 | * 11 | * @author itning 12 | */ 13 | public class RestModel implements Serializable { 14 | private int code; 15 | private String msg; 16 | private T data; 17 | 18 | public RestModel() { 19 | 20 | } 21 | 22 | private RestModel(HttpStatus status, String msg, T data) { 23 | this(status.value(), msg, data); 24 | } 25 | 26 | private RestModel(int code, String msg, T data) { 27 | this.code = code; 28 | this.msg = msg; 29 | this.data = data; 30 | } 31 | 32 | public static ResponseEntity> ok(T data) { 33 | return ResponseEntity.ok(new RestModel<>(HttpStatus.OK, "查询成功", data)); 34 | } 35 | 36 | public static ResponseEntity> created() { 37 | return ResponseEntity.status(HttpStatus.CREATED).build(); 38 | } 39 | 40 | public static ResponseEntity> created(T data) { 41 | return ResponseEntity.status(HttpStatus.CREATED).body(new RestModel<>(HttpStatus.CREATED, "创建成功", data)); 42 | } 43 | 44 | public static ResponseEntity noContent() { 45 | return ResponseEntity.noContent().build(); 46 | } 47 | 48 | public int getCode() { 49 | return code; 50 | } 51 | 52 | public void setCode(int code) { 53 | this.code = code; 54 | } 55 | 56 | public String getMsg() { 57 | return msg; 58 | } 59 | 60 | public void setMsg(String msg) { 61 | this.msg = msg; 62 | } 63 | 64 | public T getData() { 65 | return data; 66 | } 67 | 68 | public void setData(T data) { 69 | this.data = data; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/Carousel.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import com.sport.sportsmallserver.repository.CarouselRepository; 4 | import lombok.Data; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.GenericGenerator; 7 | import org.hibernate.annotations.UpdateTimestamp; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import java.io.Serializable; 14 | import java.util.Date; 15 | 16 | /** 17 | * 走马灯 18 | * 19 | * @author itning 20 | * @date 2020/2/13 12:35 21 | * @see CarouselRepository 22 | * @see java.io.Serializable 23 | */ 24 | @Data 25 | @Entity(name = "mall_carousel") 26 | public class Carousel implements Serializable { 27 | /** 28 | * 水平走马灯 29 | */ 30 | public static final int HORIZONTAL = 1; 31 | /** 32 | * 垂直走马灯 33 | */ 34 | public static final int VERTICAL = 2; 35 | /** 36 | * ID 37 | */ 38 | @Id 39 | @GeneratedValue(generator = "idGenerator") 40 | @GenericGenerator(name = "idGenerator", strategy = "org.hibernate.id.UUIDGenerator") 41 | @Column(length = 36, columnDefinition = "char(36)") 42 | private String id; 43 | /** 44 | * URL 45 | */ 46 | @Column(nullable = false, columnDefinition = "text") 47 | private String url; 48 | /** 49 | * 轮播类型(默认水平) 50 | */ 51 | @Column(nullable = false, columnDefinition = "int unsigned default 1") 52 | private int type; 53 | /** 54 | * 链接 55 | */ 56 | @Column(nullable = false) 57 | private String link; 58 | /** 59 | * 创建时间 60 | */ 61 | @Column(nullable = false) 62 | @CreationTimestamp 63 | private Date gmtCreate; 64 | /** 65 | * 更新时间 66 | */ 67 | @Column(nullable = false) 68 | @UpdateTimestamp 69 | private Date gmtModified; 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/Comment.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import com.sport.sportsmallserver.repository.CommentRepository; 4 | import lombok.Data; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.GenericGenerator; 7 | import org.hibernate.annotations.UpdateTimestamp; 8 | 9 | import javax.persistence.*; 10 | import java.io.Serializable; 11 | import java.util.Date; 12 | 13 | /** 14 | *

商品评价 15 | *

已添加商品ID,用户ID索引 16 | * 17 | * @author itning 18 | * @date 2020/2/12 10:29 19 | * @see CommentRepository 20 | * @see java.io.Serializable 21 | */ 22 | @Data 23 | @Entity(name = "mall_comment") 24 | @Table(indexes = { 25 | @Index(name = "idx_user_id", columnList = "userId"), 26 | @Index(name = "idx_commodity_id", columnList = "commodityId") 27 | }) 28 | public class Comment implements Serializable { 29 | @Id 30 | @GeneratedValue(generator = "idGenerator") 31 | @GenericGenerator(name = "idGenerator", strategy = "org.hibernate.id.UUIDGenerator") 32 | @Column(length = 36, columnDefinition = "char(36)") 33 | private String id; 34 | /** 35 | * 商品 36 | */ 37 | @SuppressWarnings("JpaDataSourceORMInspection") 38 | @ManyToOne(optional = false) 39 | @JoinColumn(name = "commodityId", columnDefinition = "char(36)") 40 | private Commodity commodity; 41 | /** 42 | * 用户 43 | */ 44 | @SuppressWarnings("JpaDataSourceORMInspection") 45 | @ManyToOne(optional = false) 46 | @JoinColumn(name = "userId", columnDefinition = "varchar(255)") 47 | private User user; 48 | /** 49 | * 内容 50 | */ 51 | @Column(nullable = false, columnDefinition = "text") 52 | private String content; 53 | /** 54 | * 创建时间 55 | */ 56 | @Column(nullable = false) 57 | @CreationTimestamp 58 | private Date gmtCreate; 59 | /** 60 | * 更新时间 61 | */ 62 | @Column(nullable = false) 63 | @UpdateTimestamp 64 | private Date gmtModified; 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/CommodityService.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service; 2 | 3 | import com.sport.sportsmallserver.dto.CommodityDTO; 4 | import com.sport.sportsmallserver.entity.Commodity; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | import java.math.BigDecimal; 9 | import java.util.List; 10 | 11 | /** 12 | * @author itning 13 | * @date 2020/2/12 12:48 14 | */ 15 | public interface CommodityService { 16 | /** 17 | * 根据商品类别查找商品 18 | * 19 | * @param typeId 类别ID 20 | * @param pageable 分页 21 | * @return 该类别下所有商品 22 | */ 23 | Page findByType(String typeId, Pageable pageable); 24 | 25 | /** 26 | * 查找所有推荐商品 27 | * 28 | * @return 推荐商品集合 29 | */ 30 | List findByRecommend(); 31 | 32 | /** 33 | * 根据商品ID查询商品 34 | * 35 | * @param id 商品ID 36 | * @return 商品 37 | */ 38 | Commodity findById(String id); 39 | 40 | /** 41 | * 搜索商品 42 | * 43 | * @param keyword 关键字 44 | * @param pageable 分页 45 | * @return 商品集合 46 | */ 47 | Page search(String keyword, Pageable pageable); 48 | 49 | /** 50 | * 获取所有商品 51 | * 52 | * @param pageable 分页 53 | * @return 商品集合 54 | */ 55 | Page findAll(Pageable pageable); 56 | 57 | /** 58 | * 修改商品 59 | * 60 | * @param commodity 商品 61 | */ 62 | void modify(CommodityDTO commodity); 63 | 64 | /** 65 | * 添加商品 66 | * 67 | * @param name 标题 68 | * @param price 价格 69 | * @param stock 库存 70 | * @param recommended 推荐商品 71 | * @param commodityTypeId 商品分类ID 72 | * @param imgMain 主图 73 | * @param imgSecond 副图 74 | * @param detail 商品详情 75 | * @return 商品 76 | */ 77 | Commodity add(String name, BigDecimal price, int stock, boolean recommended, String commodityTypeId, String imgMain, String imgSecond, String detail); 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/config/AppTomcatConnectorCustomizer.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.config; 2 | 3 | import org.apache.coyote.ProtocolHandler; 4 | import org.apache.coyote.http11.AbstractHttp11Protocol; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; 8 | import org.springframework.boot.web.server.WebServerFactoryCustomizer; 9 | import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author itning 14 | * @date 2020/4/9 18:03 15 | */ 16 | @Component 17 | public class AppTomcatConnectorCustomizer implements WebServerFactoryCustomizer { 18 | private static final Logger log = LoggerFactory.getLogger(AppTomcatConnectorCustomizer.class); 19 | 20 | @Override 21 | public void customize(ConfigurableServletWebServerFactory factory) { 22 | if (factory instanceof TomcatServletWebServerFactory) { 23 | TomcatServletWebServerFactory f = (TomcatServletWebServerFactory) factory; 24 | f.setProtocol("org.apache.coyote.http11.Http11Nio2Protocol"); 25 | if (log.isDebugEnabled()) { 26 | f.addConnectorCustomizers(connector -> { 27 | ProtocolHandler protocol = connector.getProtocolHandler(); 28 | 29 | log.debug("Tomcat({}) -- MaxConnection:{};MaxThreads:{};MinSpareThreads:{}", 30 | protocol.getClass().getName(), 31 | ((AbstractHttp11Protocol) protocol).getMaxConnections(), 32 | ((AbstractHttp11Protocol) protocol).getMaxThreads(), 33 | ((AbstractHttp11Protocol) protocol).getMinSpareThreads()); 34 | }); 35 | } 36 | } else { 37 | log.warn("ConfigurableServletWebServerFactory is not instanceof TomcatServletWebServerFactory and is: {}", factory.getClass().getName()); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/controller/CommodityDetailController.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.controller; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.dto.RestModel; 5 | import com.sport.sportsmallserver.entity.CommodityDetail; 6 | import com.sport.sportsmallserver.security.MustAdminLogin; 7 | import com.sport.sportsmallserver.security.MustLogin; 8 | import com.sport.sportsmallserver.service.CommodityDetailService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | /** 14 | * 商品详情 15 | * 16 | * @author itning 17 | * @date 2020/2/12 15:30 18 | */ 19 | @RestController 20 | public class CommodityDetailController { 21 | private final CommodityDetailService commodityDetailService; 22 | 23 | @Autowired 24 | public CommodityDetailController(CommodityDetailService commodityDetailService) { 25 | this.commodityDetailService = commodityDetailService; 26 | } 27 | 28 | /** 29 | * 根据商品ID查询商品详情 30 | * 31 | * @param loginUser 登录用户 32 | * @param commodityId 商品ID 33 | * @return ResponseEntity 34 | */ 35 | @GetMapping("/commodityDetail/{commodityId}") 36 | public ResponseEntity findByCommodityId(@MustLogin(role = {MustLogin.ROLE.ADMIN, MustLogin.ROLE.USER}) LoginUser loginUser, 37 | @PathVariable String commodityId) { 38 | return RestModel.ok(commodityDetailService.findByCommodityId(commodityId)); 39 | } 40 | 41 | /** 42 | * 修改商品详情或新增 43 | * 44 | * @param loginUser 登录用户 45 | * @param commodityDetail 商品详情 46 | * @return ResponseEntity 47 | */ 48 | @PatchMapping("/commodityDetail") 49 | public ResponseEntity modifyOrAdd(@MustAdminLogin LoginUser loginUser, 50 | @RequestBody CommodityDetail commodityDetail) { 51 | commodityDetailService.modifyOrAdd(commodityDetail); 52 | return RestModel.noContent(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.entity.Order; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | import java.math.BigDecimal; 9 | 10 | /** 11 | * @author itning 12 | * @date 2020/2/12 19:12 13 | */ 14 | public interface OrderService { 15 | /** 16 | * 下订单 17 | * 18 | * @param loginUser 登录用户 19 | * @param commodityId 商品ID 20 | * @param count 数量 21 | * @param address 收货地址 22 | * @return 新订单 23 | */ 24 | Order newOrder(LoginUser loginUser, String commodityId, int count, String address); 25 | 26 | /** 27 | * 获取所有订单 28 | * 29 | * @param loginUser 登录用户 30 | * @param status 要的订单状态 31 | * @param pageable 分页 32 | * @return 所有订单 33 | */ 34 | Page getAll(LoginUser loginUser, int[] status, Pageable pageable); 35 | 36 | /** 37 | * 删除订单 38 | * 39 | * @param loginUser 登录用户 40 | * @param orderId 订单ID 41 | */ 42 | void delOrder(LoginUser loginUser, String orderId); 43 | 44 | /** 45 | * 订单付款 46 | * 47 | * @param loginUser 登录用户 48 | * @param orderId 订单ID 49 | * @return 订单 50 | */ 51 | Order pay(LoginUser loginUser, String orderId); 52 | 53 | /** 54 | * 订单发货 55 | * 56 | * @param orderId 订单ID 57 | * @param expressInformation 快递信息 58 | * @return 订单 59 | */ 60 | Order ship(String orderId, String expressInformation); 61 | 62 | /** 63 | * 订单确认收获 64 | * 65 | * @param loginUser 登录用户 66 | * @param orderId 订单ID 67 | * @return 订单 68 | */ 69 | Order receipt(LoginUser loginUser, String orderId); 70 | 71 | /** 72 | * 获取所有订单 73 | * 74 | * @param status 订单状态 75 | * @param pageable 分页 76 | * @return 订单集合 77 | */ 78 | Page getAll(int[] status, Pageable pageable); 79 | 80 | /** 81 | * 修改订单总价格 82 | * 83 | * @param id 订单ID 84 | * @param newPrice 新价格 85 | * @return 新订单 86 | */ 87 | Order changePrice(String id, BigDecimal newPrice); 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/controller/CommentController.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.controller; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.dto.RestModel; 5 | import com.sport.sportsmallserver.security.MustUserLogin; 6 | import com.sport.sportsmallserver.service.CommentService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.domain.Sort; 10 | import org.springframework.data.web.PageableDefault; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | /** 15 | * @author itning 16 | * @date 2020/2/12 15:50 17 | */ 18 | @RestController 19 | public class CommentController { 20 | private final CommentService commentService; 21 | 22 | @Autowired 23 | public CommentController(CommentService commentService) { 24 | this.commentService = commentService; 25 | } 26 | 27 | /** 28 | * 获取商品评论 29 | * 30 | * @param loginUser 登录用户 31 | * @param commodityId 商品ID 32 | * @param pageable 分页 33 | * @return ResponseEntity 34 | */ 35 | @GetMapping("/comment/{commodityId}") 36 | public ResponseEntity findByCommodityId(@MustUserLogin LoginUser loginUser, 37 | @PathVariable String commodityId, 38 | @PageableDefault( 39 | size = 20, sort = {"gmtModified"}, 40 | direction = Sort.Direction.DESC 41 | ) 42 | Pageable pageable) { 43 | return RestModel.ok(commentService.findByCommodityId(commodityId, pageable)); 44 | } 45 | 46 | /** 47 | * 新评价 48 | * 49 | * @param loginUser 登录用户 50 | * @param orderId 订单ID 51 | * @param content 内容 52 | * @return ResponseEntity 53 | */ 54 | @PostMapping("/comment") 55 | public ResponseEntity newComment(@MustUserLogin LoginUser loginUser, 56 | @RequestParam String orderId, 57 | @RequestParam String content) { 58 | return RestModel.created(commentService.newComment(loginUser, orderId, content)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/controller/CommodityTypeController.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.controller; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.dto.RestModel; 5 | import com.sport.sportsmallserver.entity.CommodityType; 6 | import com.sport.sportsmallserver.security.MustAdminLogin; 7 | import com.sport.sportsmallserver.service.CommodityTypeService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | /** 13 | * @author itning 14 | * @date 2020/2/12 12:26 15 | */ 16 | @RestController 17 | public class CommodityTypeController { 18 | private final CommodityTypeService commodityTypeService; 19 | 20 | @Autowired 21 | public CommodityTypeController(CommodityTypeService commodityTypeService) { 22 | this.commodityTypeService = commodityTypeService; 23 | } 24 | 25 | /** 26 | * 获取所有商品分类 27 | * 28 | * @return ResponseEntity 29 | */ 30 | @GetMapping("/commodity_types") 31 | public ResponseEntity getAllCommodityType() { 32 | return RestModel.ok(commodityTypeService.getAll()); 33 | } 34 | 35 | /** 36 | * 修改分类信息 37 | * 38 | * @param loginUser 登录用户 39 | * @param commodityType 分类信息 40 | * @return ResponseEntity 41 | */ 42 | @PatchMapping("/commodity_type") 43 | public ResponseEntity modifyCommodityType(@MustAdminLogin LoginUser loginUser, 44 | @RequestBody CommodityType commodityType) { 45 | commodityTypeService.modifyCommodityType(commodityType); 46 | return RestModel.noContent(); 47 | } 48 | 49 | /** 50 | * 删除分类 51 | * 52 | * @param loginUser 登录用户 53 | * @param id 分类ID 54 | * @return ResponseEntity 55 | */ 56 | @DeleteMapping("/commodity_type/{id}") 57 | public ResponseEntity delCommodityType(@MustAdminLogin LoginUser loginUser, 58 | @PathVariable String id) { 59 | commodityTypeService.delCommodityType(id); 60 | return RestModel.noContent(); 61 | } 62 | 63 | /** 64 | * 新增分类 65 | * 66 | * @param loginUser 登录用户 67 | * @param name 分类名 68 | * @return ResponseEntity 69 | */ 70 | @PostMapping("/commodity_type") 71 | public ResponseEntity addCommodityType(@MustAdminLogin LoginUser loginUser, 72 | @RequestParam String name) { 73 | return RestModel.created(commodityTypeService.add(name)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/impl/CommodityDetailServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service.impl; 2 | 3 | import com.sport.sportsmallserver.entity.Commodity; 4 | import com.sport.sportsmallserver.entity.CommodityDetail; 5 | import com.sport.sportsmallserver.exception.IdNotFoundException; 6 | import com.sport.sportsmallserver.exception.NullFiledException; 7 | import com.sport.sportsmallserver.repository.CommodityDetailRepository; 8 | import com.sport.sportsmallserver.service.CommodityDetailService; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | /** 15 | * @author itning 16 | * @date 2020/2/12 15:33 17 | */ 18 | @Service 19 | @Transactional(rollbackFor = Exception.class) 20 | public class CommodityDetailServiceImpl implements CommodityDetailService { 21 | private final CommodityDetailRepository commodityDetailRepository; 22 | 23 | @Autowired 24 | public CommodityDetailServiceImpl(CommodityDetailRepository commodityDetailRepository) { 25 | this.commodityDetailRepository = commodityDetailRepository; 26 | } 27 | 28 | @Override 29 | public CommodityDetail findByCommodityId(String commodityId) { 30 | Commodity commodity = new Commodity(); 31 | commodity.setId(commodityId); 32 | return commodityDetailRepository.findByCommodity(commodity).orElse(new CommodityDetail()); 33 | } 34 | 35 | @Override 36 | public void modifyOrAdd(CommodityDetail commodityDetail) { 37 | if (StringUtils.isBlank(commodityDetail.getId())) { 38 | if (null == commodityDetail.getCommodity() || StringUtils.isBlank(commodityDetail.getCommodity().getId())) { 39 | throw new NullFiledException("商品ID为空"); 40 | } else { 41 | Commodity commodity = new Commodity(); 42 | commodity.setId(commodityDetail.getCommodity().getId()); 43 | 44 | CommodityDetail newCommodityDetail = new CommodityDetail(); 45 | newCommodityDetail.setCommodity(commodity); 46 | newCommodityDetail.setDetail(commodityDetail.getDetail()); 47 | 48 | commodityDetailRepository.save(newCommodityDetail); 49 | } 50 | } else { 51 | CommodityDetail saved = commodityDetailRepository.findById(commodityDetail.getId()).orElseThrow(() -> new IdNotFoundException("详情ID不存在")); 52 | saved.setDetail(commodityDetail.getDetail()); 53 | commodityDetailRepository.save(saved); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/controller/CarouselController.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.controller; 2 | 3 | import com.sport.sportsmallserver.dto.CarouselDTO; 4 | import com.sport.sportsmallserver.dto.LoginUser; 5 | import com.sport.sportsmallserver.dto.RestModel; 6 | import com.sport.sportsmallserver.security.MustAdminLogin; 7 | import com.sport.sportsmallserver.service.CarouselService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | /** 13 | * @author itning 14 | * @date 2020/2/13 12:47 15 | */ 16 | @RestController 17 | public class CarouselController { 18 | private final CarouselService carouselService; 19 | 20 | @Autowired 21 | public CarouselController(CarouselService carouselService) { 22 | this.carouselService = carouselService; 23 | } 24 | 25 | /** 26 | * 获取所有轮播图 27 | * 28 | * @param type 类型 29 | * @return ResponseEntity 30 | */ 31 | @GetMapping("/carousels") 32 | public ResponseEntity getAll(@RequestParam(required = false, defaultValue = "-1") int type) { 33 | return RestModel.ok(carouselService.getAll(type)); 34 | } 35 | 36 | /** 37 | * 添加走马灯 38 | * 39 | * @param loginUser 登录用户 40 | * @param url URL 41 | * @param link 链接 42 | * @param type 类型 43 | * @return ResponseEntity 44 | */ 45 | @PostMapping("/carousel") 46 | public ResponseEntity add(@MustAdminLogin LoginUser loginUser, 47 | @RequestParam String url, 48 | @RequestParam String link, 49 | @RequestParam int type) { 50 | return RestModel.created(carouselService.add(url, link, type)); 51 | } 52 | 53 | /** 54 | * 删除走马灯 55 | * 56 | * @param loginUser 登录用户 57 | * @param id ID 58 | * @return ResponseEntity 59 | */ 60 | @DeleteMapping("/carousel/{id}") 61 | public ResponseEntity del(@MustAdminLogin LoginUser loginUser, 62 | @PathVariable String id) { 63 | carouselService.del(id); 64 | return RestModel.noContent(); 65 | } 66 | 67 | /** 68 | * 修改走马灯 69 | * 70 | * @param loginUser 登录用户 71 | * @param carousel 走马灯 72 | * @return ResponseEntity 73 | */ 74 | @PatchMapping("/carousel") 75 | public ResponseEntity modify(@MustAdminLogin LoginUser loginUser, 76 | @RequestBody CarouselDTO carousel) { 77 | carouselService.modify(carousel); 78 | return RestModel.noContent(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/Commodity.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import com.sport.sportsmallserver.repository.CommodityRepository; 4 | import lombok.Data; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.GenericGenerator; 7 | import org.hibernate.annotations.UpdateTimestamp; 8 | 9 | import javax.persistence.*; 10 | import java.io.Serializable; 11 | import java.math.BigDecimal; 12 | import java.util.Date; 13 | 14 | /** 15 | *

商品(产品) 16 | *

已添加商品名索引 17 | * 18 | * @author itning 19 | * @date 2020/2/11 19:51 20 | * @see CommodityRepository 21 | * @see java.io.Serializable 22 | */ 23 | @Data 24 | @Entity(name = "mall_commodity") 25 | @Table(indexes = {@Index(name = "idx_name", columnList = "name")}) 26 | public class Commodity implements Serializable { 27 | /** 28 | *

商品ID 区分每个商品 29 | *

自动主键生成 30 | */ 31 | @Id 32 | @GeneratedValue(generator = "idGenerator") 33 | @GenericGenerator(name = "idGenerator", strategy = "org.hibernate.id.UUIDGenerator") 34 | @Column(length = 36, columnDefinition = "char(36)") 35 | private String id; 36 | /** 37 | * 商品名 38 | */ 39 | @Column(nullable = false) 40 | private String name; 41 | /** 42 | * 库存,默认为 1 43 | */ 44 | @Column(nullable = false, columnDefinition = "int unsigned default 1") 45 | private int stock; 46 | /** 47 | * 销量,默认为 0 48 | */ 49 | @Column(nullable = false, columnDefinition = "int unsigned default 0") 50 | private int sales; 51 | /** 52 | *

单价 53 | *

小数位数2位(角,分) 54 | */ 55 | @Column(nullable = false, columnDefinition = "decimal(38,2)") 56 | private BigDecimal price; 57 | /** 58 | * 商品图片地址(主图片) 59 | */ 60 | @Column(nullable = false, columnDefinition = "text") 61 | private String imgMain; 62 | /** 63 | *

其它图片地址(使用英文分号进行分隔) 64 | *

主要用于详情展示 65 | */ 66 | @Column(nullable = false, columnDefinition = "text") 67 | private String imgSecond; 68 | /** 69 | * 推荐商品(会展示在首页) 70 | */ 71 | @Column(nullable = false) 72 | private boolean recommended; 73 | /** 74 | * 商品已下架? 75 | */ 76 | @Column(nullable = false, columnDefinition = "bit default false") 77 | private boolean takeOff; 78 | /** 79 | * 商品分类 80 | */ 81 | @SuppressWarnings("JpaDataSourceORMInspection") 82 | @ManyToOne(optional = false) 83 | @JoinColumn(name = "commodityTypeId") 84 | private CommodityType commodityType; 85 | /** 86 | * 创建时间 87 | */ 88 | @Column(nullable = false) 89 | @CreationTimestamp 90 | private Date gmtCreate; 91 | /** 92 | * 更新时间 93 | */ 94 | @Column(nullable = false) 95 | @UpdateTimestamp 96 | private Date gmtModified; 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/impl/CarouselServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service.impl; 2 | 3 | import com.sport.sportsmallserver.dto.CarouselDTO; 4 | import com.sport.sportsmallserver.entity.Carousel; 5 | import com.sport.sportsmallserver.exception.IdNotFoundException; 6 | import com.sport.sportsmallserver.exception.NullFiledException; 7 | import com.sport.sportsmallserver.repository.CarouselRepository; 8 | import com.sport.sportsmallserver.service.CarouselService; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * @author itning 18 | * @date 2020/2/13 12:46 19 | */ 20 | @Service 21 | @Transactional(rollbackFor = Exception.class) 22 | public class CarouselServiceImpl implements CarouselService { 23 | private final CarouselRepository carouselRepository; 24 | 25 | @Autowired 26 | public CarouselServiceImpl(CarouselRepository carouselRepository) { 27 | this.carouselRepository = carouselRepository; 28 | } 29 | 30 | @Override 31 | public List getAll(int type) { 32 | if (-1 == type) { 33 | return carouselRepository.findAll(); 34 | } 35 | return carouselRepository.findAllByType(type); 36 | } 37 | 38 | @Override 39 | public Carousel add(String url, String link, int type) { 40 | if (StringUtils.isAnyBlank(url, link)) { 41 | throw new NullFiledException("URL或链接为空"); 42 | } 43 | Carousel carousel = new Carousel(); 44 | carousel.setUrl(url); 45 | carousel.setType(type); 46 | carousel.setLink(link); 47 | return carouselRepository.save(carousel); 48 | } 49 | 50 | @Override 51 | public void del(String id) { 52 | carouselRepository.deleteById(id); 53 | } 54 | 55 | @Override 56 | public void modify(CarouselDTO carousel) { 57 | if (StringUtils.isBlank(carousel.getId())) { 58 | throw new NullFiledException("ID为空"); 59 | } 60 | Carousel saved = carouselRepository.findById(carousel.getId()).orElseThrow(() -> new IdNotFoundException("ID不存在")); 61 | if (!saved.getLink().equals(carousel.getLink()) && carousel.getLink() != null) { 62 | saved.setLink(carousel.getLink()); 63 | } 64 | if (!saved.getUrl().equals(carousel.getUrl()) && carousel.getUrl() != null) { 65 | saved.setUrl(carousel.getUrl()); 66 | } 67 | if (carousel.getType() != null && carousel.getType() != saved.getType()) { 68 | saved.setType(carousel.getType()); 69 | } 70 | carouselRepository.save(saved); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/controller/CartController.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.controller; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.dto.RestModel; 5 | import com.sport.sportsmallserver.security.MustUserLogin; 6 | import com.sport.sportsmallserver.service.CartService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.domain.Sort; 10 | import org.springframework.data.web.PageableDefault; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | /** 15 | * @author itning 16 | * @date 2020/2/12 16:44 17 | */ 18 | @RestController 19 | public class CartController { 20 | private final CartService cartService; 21 | 22 | @Autowired 23 | public CartController(CartService cartService) { 24 | this.cartService = cartService; 25 | } 26 | 27 | /** 28 | * 添加到购物车 29 | * 30 | * @param loginUser 登录用户 31 | * @param commodityId 商品ID 32 | * @param num 数量 33 | * @param cumulative 累加 34 | * @return 添加的商品 35 | */ 36 | @PostMapping("/cart") 37 | public ResponseEntity addToCart(@MustUserLogin LoginUser loginUser, 38 | @RequestParam String commodityId, 39 | @RequestParam(defaultValue = "1") int num, 40 | @RequestParam(defaultValue = "true") boolean cumulative) { 41 | return RestModel.created(cartService.addToCart(loginUser, commodityId, num, cumulative)); 42 | } 43 | 44 | /** 45 | * 获取某用户所有购物车 46 | * 47 | * @param loginUser 登录用户 48 | * @param pageable 分页 49 | * @return ResponseEntity 50 | */ 51 | @GetMapping("/carts") 52 | public ResponseEntity getCarts(@MustUserLogin LoginUser loginUser, 53 | @PageableDefault( 54 | size = 20, sort = {"gmtModified"}, 55 | direction = Sort.Direction.DESC 56 | ) 57 | Pageable pageable) { 58 | return RestModel.ok(cartService.getAll(loginUser, pageable)); 59 | } 60 | 61 | /** 62 | * 删除购物车某个商品 63 | * 64 | * @param loginUser 登录用户 65 | * @param commodityId 商品ID 66 | * @return ResponseEntity 67 | */ 68 | @DeleteMapping("/cart/{commodityId}") 69 | public ResponseEntity delCart(@MustUserLogin LoginUser loginUser, 70 | @PathVariable String commodityId) { 71 | cartService.delCart(loginUser, commodityId); 72 | return RestModel.noContent(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/util/JwtUtils.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.util; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.sport.sportsmallserver.dto.LoginUser; 6 | import com.sport.sportsmallserver.exception.TokenException; 7 | import io.jsonwebtoken.*; 8 | import org.springframework.http.HttpStatus; 9 | 10 | import java.util.Date; 11 | 12 | /** 13 | * Jwt 工具类 14 | * 15 | * @author itning 16 | */ 17 | public final class JwtUtils { 18 | private static final String PRIVATE_KEY = "itning"; 19 | private static final String LOGIN_USER = "loginUser"; 20 | private static final String DEFAULT_STR = "null"; 21 | private static final ObjectMapper MAPPER = new ObjectMapper(); 22 | 23 | private JwtUtils() { 24 | 25 | } 26 | 27 | public static String buildJwt(Object o) throws JsonProcessingException { 28 | return Jwts.builder() 29 | //SECRET_KEY是加密算法对应的密钥,这里使用额是HS256加密算法 30 | .signWith(SignatureAlgorithm.HS256, PRIVATE_KEY) 31 | //expTime是过期时间 32 | .setExpiration(new Date(System.currentTimeMillis() + 240 * 60 * 1000)) 33 | .claim(LOGIN_USER, MAPPER.writeValueAsString(o)) 34 | //令牌的发行者 35 | .setIssuer("itning") 36 | .compact(); 37 | } 38 | 39 | public static LoginUser getLoginUser(String jwt) { 40 | if (DEFAULT_STR.equals(jwt)) { 41 | throw new TokenException("请先登陆", HttpStatus.UNAUTHORIZED); 42 | } 43 | try { 44 | //解析JWT字符串中的数据,并进行最基础的验证 45 | Claims claims = Jwts.parser() 46 | //SECRET_KEY是加密算法对应的密钥,jjwt可以自动判断机密算法 47 | .setSigningKey(PRIVATE_KEY) 48 | //jwt是JWT字符串 49 | .parseClaimsJws(jwt) 50 | .getBody(); 51 | //获取自定义字段key 52 | String loginUserJson = claims.get(LOGIN_USER, String.class); 53 | LoginUser loginUser = MAPPER.readValue(loginUserJson, LoginUser.class); 54 | //判断自定义字段是否正确 55 | if (loginUser == null) { 56 | throw new TokenException("登陆失败", HttpStatus.UNAUTHORIZED); 57 | } else { 58 | return loginUser; 59 | } 60 | //在解析JWT字符串时,如果密钥不正确,将会解析失败,抛出SignatureException异常,说明该JWT字符串是伪造的 61 | //在解析JWT字符串时,如果‘过期时间字段’已经早于当前时间,将会抛出ExpiredJwtException异常,说明本次请求已经失效 62 | } catch (ExpiredJwtException e) { 63 | throw new TokenException("登陆超时", HttpStatus.UNAUTHORIZED); 64 | } catch (SignatureException e) { 65 | throw new TokenException("凭据错误", HttpStatus.BAD_REQUEST); 66 | } catch (Exception e) { 67 | throw new TokenException("登陆失败", HttpStatus.UNAUTHORIZED); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.controller; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.sport.sportsmallserver.dto.LoginUser; 5 | import com.sport.sportsmallserver.dto.RestModel; 6 | import com.sport.sportsmallserver.entity.User; 7 | import com.sport.sportsmallserver.security.MustUserLogin; 8 | import com.sport.sportsmallserver.service.UserService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | /** 14 | * @author itning 15 | * @date 2020/2/12 11:39 16 | */ 17 | @RestController 18 | public class UserController { 19 | private final UserService userService; 20 | 21 | @Autowired 22 | public UserController(UserService userService) { 23 | this.userService = userService; 24 | } 25 | 26 | /** 27 | * 用户登录 28 | * 29 | * @param username 用户名 30 | * @param password 密码 31 | * @return ResponseEntity 32 | * @throws JsonProcessingException See {@link UserService#login(String, String)} 33 | */ 34 | @PostMapping("/login") 35 | public ResponseEntity login(@RequestParam String username, 36 | @RequestParam String password) throws JsonProcessingException { 37 | return RestModel.ok(userService.login(username, password)); 38 | } 39 | 40 | /** 41 | * 修改用户信息(不包括密码) 42 | * 43 | * @param loginUser 登录用户 44 | * @param user 新用户信息 45 | * @return ResponseEntity 46 | */ 47 | @PatchMapping("/user") 48 | public ResponseEntity modifyUserInfo(@MustUserLogin LoginUser loginUser, 49 | @RequestBody User user) { 50 | userService.modifyUser(loginUser, user); 51 | return RestModel.noContent(); 52 | } 53 | 54 | /** 55 | * 用户注册 56 | * 57 | * @param username 用户名 58 | * @param email 邮箱 59 | * @param phone 手机号 60 | * @param password 密码 61 | * @return ResponseEntity 62 | */ 63 | @PostMapping("/reg") 64 | public ResponseEntity regUser(@RequestParam String username, 65 | @RequestParam String email, 66 | @RequestParam String phone, 67 | @RequestParam String password) { 68 | return RestModel.created(userService.reg(username, email, phone, password)); 69 | } 70 | 71 | /** 72 | * 更改密码 73 | * 74 | * @param loginUser 登录用户 75 | * @param oldPwd 旧密码 76 | * @param newPwd 新密码 77 | * @return ResponseEntity 78 | */ 79 | @PostMapping("/pwd") 80 | public ResponseEntity changePwd(@MustUserLogin LoginUser loginUser, 81 | @RequestParam String oldPwd, 82 | @RequestParam String newPwd) { 83 | userService.changePwd(loginUser, oldPwd, newPwd); 84 | return RestModel.ok("success"); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/impl/CommodityTypeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service.impl; 2 | 3 | import com.sport.sportsmallserver.entity.CommodityType; 4 | import com.sport.sportsmallserver.exception.IdNotFoundException; 5 | import com.sport.sportsmallserver.exception.NullFiledException; 6 | import com.sport.sportsmallserver.exception.SecurityServerException; 7 | import com.sport.sportsmallserver.repository.CommodityRepository; 8 | import com.sport.sportsmallserver.repository.CommodityTypeRepository; 9 | import com.sport.sportsmallserver.service.CommodityTypeService; 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * @author itning 20 | * @date 2020/2/12 12:28 21 | */ 22 | @Service 23 | @Transactional(rollbackFor = Exception.class) 24 | public class CommodityTypeServiceImpl implements CommodityTypeService { 25 | private final CommodityTypeRepository commodityTypeRepository; 26 | private final CommodityRepository commodityRepository; 27 | 28 | @Autowired 29 | public CommodityTypeServiceImpl(CommodityTypeRepository commodityTypeRepository, CommodityRepository commodityRepository) { 30 | this.commodityTypeRepository = commodityTypeRepository; 31 | this.commodityRepository = commodityRepository; 32 | } 33 | 34 | @Override 35 | public List getAll() { 36 | return commodityTypeRepository.findAll(); 37 | } 38 | 39 | @Override 40 | public void modifyCommodityType(CommodityType commodityType) { 41 | if (StringUtils.isAnyBlank(commodityType.getName(), commodityType.getId())) { 42 | throw new NullFiledException("分类名或ID为空"); 43 | } 44 | CommodityType ct = commodityTypeRepository.findById(commodityType.getId()).orElseThrow(() -> new IdNotFoundException("分类没有找到")); 45 | if (ct.getName().equals(commodityType.getName())) { 46 | throw new SecurityServerException("原名称和新名称相同", HttpStatus.BAD_REQUEST); 47 | } 48 | ct.setName(commodityType.getName()); 49 | commodityTypeRepository.save(ct); 50 | } 51 | 52 | @Override 53 | public void delCommodityType(String id) { 54 | CommodityType commodityType = commodityTypeRepository.findById(id).orElseThrow(() -> new IdNotFoundException("分类没有找到")); 55 | if (commodityRepository.existsByCommodityType(commodityType)) { 56 | throw new SecurityServerException("该分类下还有商品", HttpStatus.BAD_REQUEST); 57 | } 58 | commodityTypeRepository.delete(commodityType); 59 | } 60 | 61 | @Override 62 | public CommodityType add(String name) { 63 | if (StringUtils.isBlank(name)) { 64 | throw new NullFiledException("名称不能为空"); 65 | } 66 | CommodityType commodityType = new CommodityType(); 67 | commodityType.setName(name); 68 | return commodityTypeRepository.save(commodityType); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/entity/Order.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.entity; 2 | 3 | import com.sport.sportsmallserver.repository.OrderRepository; 4 | import lombok.Data; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.GenericGenerator; 7 | import org.hibernate.annotations.UpdateTimestamp; 8 | 9 | import javax.persistence.*; 10 | import java.io.Serializable; 11 | import java.math.BigDecimal; 12 | import java.util.Date; 13 | 14 | /** 15 | * 订单 16 | * 17 | * @author itning 18 | * @date 2020/2/11 21:15 19 | * @see OrderRepository 20 | * @see java.io.Serializable 21 | */ 22 | @Data 23 | @Entity(name = "mall_order") 24 | public class Order implements Serializable { 25 | /** 26 | * 订单状态 27 | */ 28 | public enum STATUS { 29 | /** 30 | * 0:订单已经被用户删除 31 | */ 32 | DEL_BY_USER(0), 33 | /** 34 | * 1:已下单(待付款) 35 | */ 36 | ORDERED(1), 37 | /** 38 | * 2:已付款(待发货) 39 | */ 40 | BUY(2), 41 | /** 42 | * 3:已发货(待收货) 43 | */ 44 | SHIP(3), 45 | /** 46 | * 4:已收货(待评价) 47 | */ 48 | RECEIPT(4), 49 | /** 50 | * 5:已评价(完成订单) 51 | */ 52 | EVALUATION(5), 53 | /** 54 | * 6:订单已经被商家删除 55 | */ 56 | DEL_BY_ADMIN(6), 57 | /** 58 | * 7:订单已经被商家和用户同时删除 59 | */ 60 | DEL_ALL(7); 61 | 62 | private final int status; 63 | 64 | STATUS(int status) { 65 | this.status = status; 66 | } 67 | 68 | public int getStatus() { 69 | return status; 70 | } 71 | } 72 | 73 | /** 74 | * 订单ID 75 | */ 76 | @Id 77 | @GeneratedValue(generator = "idGenerator") 78 | @GenericGenerator(name = "idGenerator", strategy = "org.hibernate.id.UUIDGenerator") 79 | @Column(length = 36, columnDefinition = "char(36)") 80 | private String id; 81 | /** 82 | * 订单对应用户 83 | */ 84 | @SuppressWarnings("JpaDataSourceORMInspection") 85 | @ManyToOne(optional = false) 86 | @JoinColumn(name = "userId") 87 | private User user; 88 | /** 89 | * 订单对应商品 90 | */ 91 | @SuppressWarnings("JpaDataSourceORMInspection") 92 | @ManyToOne(optional = false) 93 | @JoinColumn(name = "commodityId") 94 | private Commodity commodity; 95 | /** 96 | * 下单的商品数量 97 | */ 98 | @Column(nullable = false, columnDefinition = "int unsigned default 1") 99 | private int countNum; 100 | /** 101 | * 总价 102 | */ 103 | @Column(nullable = false, columnDefinition = "decimal(38,2)") 104 | private BigDecimal sumPrice; 105 | /** 106 | *

订单状态 107 | *

0:订单已经被用户删除 108 | *

1:已下单(待付款) 109 | *

2:已付款(待发货) 110 | *

3:已发货(待收货) 111 | *

4:已收货(待评价) 112 | *

5:已评价(完成订单) 113 | *

6:订单已经被商家删除 114 | *

7:订单已经被商家和用户同时删除 115 | */ 116 | @Column(nullable = false, columnDefinition = "tinyint unsigned default 1") 117 | private int status; 118 | /** 119 | * 创建时间 120 | */ 121 | @Column(nullable = false) 122 | @CreationTimestamp 123 | private Date gmtCreate; 124 | /** 125 | * 更新时间 126 | */ 127 | @Column(nullable = false) 128 | @UpdateTimestamp 129 | private Date gmtModified; 130 | } 131 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.2.RELEASE 9 | 10 | 11 | com.sport 12 | sports-mall-server 13 | 1.0.1-RELEASE 14 | sports-mall-server 15 | Demo project for Spring Boot 16 | 17 | 18 | 11 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-data-jpa 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | 32 | mysql 33 | mysql-connector-java 34 | runtime 35 | 36 | 37 | org.projectlombok 38 | lombok 39 | true 40 | 41 | 42 | 43 | io.jsonwebtoken 44 | jjwt 45 | 0.9.1 46 | 47 | 48 | 49 | ma.glasnost.orika 50 | orika-core 51 | 1.5.4 52 | 53 | 54 | 55 | org.apache.commons 56 | commons-lang3 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-test 61 | test 62 | 63 | 64 | org.junit.vintage 65 | junit-vintage-engine 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | nexus-aliyun 74 | Nexus aliyun 75 | http://maven.aliyun.com/nexus/content/groups/public 76 | 77 | 78 | 79 | 80 | 81 | 82 | org.springframework.boot 83 | spring-boot-maven-plugin 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/impl/CartServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service.impl; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.entity.Cart; 5 | import com.sport.sportsmallserver.entity.CartPrimaryKey; 6 | import com.sport.sportsmallserver.entity.Commodity; 7 | import com.sport.sportsmallserver.entity.User; 8 | import com.sport.sportsmallserver.exception.IdNotFoundException; 9 | import com.sport.sportsmallserver.exception.SecurityServerException; 10 | import com.sport.sportsmallserver.repository.CartRepository; 11 | import com.sport.sportsmallserver.repository.CommodityRepository; 12 | import com.sport.sportsmallserver.service.CartService; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.data.domain.Page; 15 | import org.springframework.data.domain.Pageable; 16 | import org.springframework.http.HttpStatus; 17 | import org.springframework.stereotype.Service; 18 | import org.springframework.transaction.annotation.Transactional; 19 | 20 | import java.util.Optional; 21 | 22 | /** 23 | * @author itning 24 | * @date 2020/2/12 16:46 25 | */ 26 | @Service 27 | @Transactional(rollbackFor = Exception.class) 28 | public class CartServiceImpl implements CartService { 29 | private final CartRepository cartRepository; 30 | private final CommodityRepository commodityRepository; 31 | 32 | @Autowired 33 | public CartServiceImpl(CartRepository cartRepository, CommodityRepository commodityRepository) { 34 | this.cartRepository = cartRepository; 35 | this.commodityRepository = commodityRepository; 36 | } 37 | 38 | @Override 39 | public Cart addToCart(LoginUser loginUser, String commodityId, int num, boolean cumulative) { 40 | Commodity cc = commodityRepository.findById(commodityId).orElseThrow(() -> new IdNotFoundException("商品不存在")); 41 | if (cc.isTakeOff()) { 42 | throw new SecurityServerException("商品已下架", HttpStatus.NOT_FOUND); 43 | } 44 | CartPrimaryKey cartPrimaryKey = new CartPrimaryKey(); 45 | cartPrimaryKey.setUser(loginUser.getUsername()); 46 | cartPrimaryKey.setCommodity(commodityId); 47 | Optional cartOptional = cartRepository.findById(cartPrimaryKey); 48 | Cart cart; 49 | if (cartOptional.isPresent()) { 50 | // 商品已经在购物车里了 51 | cart = cartOptional.get(); 52 | if (cumulative) { 53 | cart.setCountNum(cart.getCountNum() + num); 54 | } else { 55 | cart.setCountNum(num); 56 | } 57 | } else { 58 | User user = new User(); 59 | user.setUsername(loginUser.getUsername()); 60 | 61 | cart = new Cart(); 62 | cart.setCountNum(num); 63 | cart.setUser(user); 64 | cart.setCommodity(cc); 65 | } 66 | return cartRepository.save(cart); 67 | } 68 | 69 | @Override 70 | public Page getAll(LoginUser loginUser, Pageable pageable) { 71 | User user = new User(); 72 | user.setUsername(loginUser.getUsername()); 73 | return cartRepository.findAllByUser(user, pageable); 74 | } 75 | 76 | @Override 77 | public void delCart(LoginUser loginUser, String commodityId) { 78 | Commodity cc = commodityRepository.findById(commodityId).orElseThrow(() -> new IdNotFoundException("商品不存在")); 79 | 80 | User user = new User(); 81 | user.setUsername(loginUser.getUsername()); 82 | 83 | cartRepository.deleteByCommodityAndUser(cc, user); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/security/SecurityHandlerMethodArgumentResolver.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.security; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.entity.Role; 5 | import com.sport.sportsmallserver.exception.SecurityServerException; 6 | import com.sport.sportsmallserver.exception.TokenException; 7 | import com.sport.sportsmallserver.util.JwtUtils; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.core.MethodParameter; 11 | import org.springframework.http.HttpHeaders; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.lang.NonNull; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.web.bind.support.WebDataBinderFactory; 16 | import org.springframework.web.context.request.NativeWebRequest; 17 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 18 | import org.springframework.web.method.support.ModelAndViewContainer; 19 | 20 | import javax.servlet.http.HttpServletRequest; 21 | import java.util.Arrays; 22 | 23 | /** 24 | * @author itning 25 | */ 26 | @Component 27 | public class SecurityHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { 28 | private static final Logger logger = LoggerFactory.getLogger(SecurityHandlerMethodArgumentResolver.class); 29 | 30 | @Override 31 | public boolean supportsParameter(@NonNull MethodParameter parameter) { 32 | return parameter.hasParameterAnnotation(MustLogin.class) || 33 | parameter.hasParameterAnnotation(MustAdminLogin.class) || 34 | parameter.hasParameterAnnotation(MustUserLogin.class); 35 | } 36 | 37 | @Override 38 | public Object resolveArgument(@NonNull MethodParameter parameter, ModelAndViewContainer mavContainer, @NonNull NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { 39 | HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); 40 | assert request != null; 41 | String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION); 42 | if (null == authorizationHeader) { 43 | throw new TokenException("凭据错误", HttpStatus.BAD_REQUEST); 44 | } 45 | LoginUser loginUser = JwtUtils.getLoginUser(authorizationHeader); 46 | checkLoginPermission(parameter, loginUser.getRole().getId()); 47 | return loginUser; 48 | } 49 | 50 | private void checkLoginPermission(@NonNull MethodParameter parameter, String roleId) { 51 | if (parameter.hasParameterAnnotation(MustUserLogin.class) && 52 | !Role.ROLE_USER_ID.equals(roleId)) { 53 | logger.debug("MustUserLogin role id {}", roleId); 54 | throw new SecurityServerException("权限不足", HttpStatus.FORBIDDEN); 55 | } 56 | if (parameter.hasParameterAnnotation(MustAdminLogin.class) && 57 | !Role.ROLE_ADMIN_ID.equals(roleId)) { 58 | logger.debug("MustAdminLogin role id {}", roleId); 59 | throw new SecurityServerException("权限不足", HttpStatus.FORBIDDEN); 60 | } 61 | if (parameter.hasParameterAnnotation(MustLogin.class)) { 62 | MustLogin mustLogin = parameter.getParameterAnnotation(MustLogin.class); 63 | if (mustLogin != null) { 64 | if (Arrays.stream(mustLogin.role()).noneMatch(role -> role.getId().equals(roleId))) { 65 | logger.debug("MustLogin role id {} and set role array {}", roleId, Arrays.toString(mustLogin.role())); 66 | throw new SecurityServerException("权限不足", HttpStatus.FORBIDDEN); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/exception/ExceptionResolver.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.exception; 2 | 3 | import com.sport.sportsmallserver.dto.RestModel; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.web.bind.MissingServletRequestParameterException; 8 | import org.springframework.web.bind.annotation.ControllerAdvice; 9 | import org.springframework.web.bind.annotation.ExceptionHandler; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | import org.springframework.web.servlet.NoHandlerFoundException; 12 | 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | /** 16 | * 异常处理 17 | * 18 | * @author itning 19 | */ 20 | @ControllerAdvice 21 | public class ExceptionResolver { 22 | private static final Logger logger = LoggerFactory.getLogger(ExceptionResolver.class); 23 | 24 | /** 25 | * json 格式错误消息 26 | * 27 | * @param response HttpServletResponse 28 | * @param e Exception 29 | * @return 异常消息 30 | */ 31 | @ExceptionHandler(value = Exception.class) 32 | @ResponseBody 33 | public RestModel jsonErrorHandler(HttpServletResponse response, Exception e) { 34 | logger.error("jsonErrorHandler->{}:{} {}", e.getClass().getSimpleName(), e.getMessage(), e); 35 | RestModel restModel = new RestModel<>(); 36 | restModel.setCode(HttpStatus.SERVICE_UNAVAILABLE.value()); 37 | restModel.setMsg(e.getMessage()); 38 | response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value()); 39 | return restModel; 40 | } 41 | 42 | /** 43 | * BaseException 错误 44 | * 45 | * @param response HttpServletResponse 46 | * @param e BaseException 47 | * @return 异常消息 48 | */ 49 | @ExceptionHandler(value = BaseException.class) 50 | @ResponseBody 51 | public RestModel baseErrorHandler(HttpServletResponse response, BaseException e) { 52 | logger.info("baseErrorHandler->{}:{}", e.getClass().getSimpleName(), e.getMessage()); 53 | RestModel restModel = new RestModel<>(); 54 | restModel.setCode(e.getCode().value()); 55 | restModel.setMsg(e.getMessage()); 56 | response.setStatus(e.getCode().value()); 57 | return restModel; 58 | } 59 | 60 | /** 61 | * MissingServletRequestParameterException 错误 62 | * 63 | * @param response HttpServletResponse 64 | * @param e MissingServletRequestParameterException 65 | * @return 异常消息 66 | */ 67 | @ExceptionHandler(value = MissingServletRequestParameterException.class) 68 | @ResponseBody 69 | public RestModel missingServletRequestParameterExceptionHandler(HttpServletResponse response, MissingServletRequestParameterException e) { 70 | logger.info("missingServletRequestParameterExceptionHandler->{}", e.getMessage()); 71 | RestModel restModel = new RestModel<>(); 72 | restModel.setCode(HttpServletResponse.SC_BAD_REQUEST); 73 | restModel.setMsg(e.getMessage()); 74 | response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 75 | return restModel; 76 | } 77 | 78 | /** 79 | * BaseException 错误 80 | * 81 | * @param response HttpServletResponse 82 | * @param e BaseException 83 | * @return 异常消息 84 | */ 85 | @ExceptionHandler(value = NoHandlerFoundException.class) 86 | @ResponseBody 87 | public RestModel noHandlerFoundErrorHandler(HttpServletResponse response, NoHandlerFoundException e) { 88 | logger.info("noHandlerFoundErrorHandler->{}:{}", e.getClass().getSimpleName(), e.getMessage()); 89 | RestModel restModel = new RestModel<>(); 90 | restModel.setCode(HttpStatus.NOT_FOUND.value()); 91 | restModel.setMsg(e.getMessage()); 92 | response.setStatus(HttpStatus.NOT_FOUND.value()); 93 | return restModel; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/impl/CommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service.impl; 2 | 3 | import com.sport.sportsmallserver.dto.CommentDTO; 4 | import com.sport.sportsmallserver.dto.LoginUser; 5 | import com.sport.sportsmallserver.entity.Comment; 6 | import com.sport.sportsmallserver.entity.Commodity; 7 | import com.sport.sportsmallserver.entity.Order; 8 | import com.sport.sportsmallserver.entity.User; 9 | import com.sport.sportsmallserver.exception.IdNotFoundException; 10 | import com.sport.sportsmallserver.exception.NullFiledException; 11 | import com.sport.sportsmallserver.exception.SecurityServerException; 12 | import com.sport.sportsmallserver.repository.CommentRepository; 13 | import com.sport.sportsmallserver.repository.OrderRepository; 14 | import com.sport.sportsmallserver.service.CommentService; 15 | import org.apache.commons.lang3.StringUtils; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.data.domain.Page; 18 | import org.springframework.data.domain.Pageable; 19 | import org.springframework.http.HttpStatus; 20 | import org.springframework.stereotype.Service; 21 | import org.springframework.transaction.annotation.Transactional; 22 | 23 | /** 24 | * @author itning 25 | * @date 2020/2/12 15:53 26 | */ 27 | @Service 28 | @Transactional(rollbackFor = Exception.class) 29 | public class CommentServiceImpl implements CommentService { 30 | private final CommentRepository commentRepository; 31 | private final OrderRepository orderRepository; 32 | 33 | @Autowired 34 | public CommentServiceImpl(CommentRepository commentRepository, OrderRepository orderRepository) { 35 | this.commentRepository = commentRepository; 36 | this.orderRepository = orderRepository; 37 | } 38 | 39 | @Override 40 | public Page findByCommodityId(String commodityId, Pageable pageable) { 41 | Commodity commodity = new Commodity(); 42 | commodity.setId(commodityId); 43 | return commentRepository.findByCommodity(commodity, pageable) 44 | .map(comment -> { 45 | CommentDTO commentDTO = new CommentDTO(); 46 | commentDTO.setId(comment.getId()); 47 | commentDTO.setUsername(generateAnonymousUserName(comment.getUser().getUsername())); 48 | commentDTO.setContent(comment.getContent()); 49 | commentDTO.setGmtCreate(comment.getGmtCreate()); 50 | commentDTO.setGmtModified(comment.getGmtModified()); 51 | return commentDTO; 52 | }); 53 | } 54 | 55 | @Override 56 | public Comment newComment(LoginUser loginUser, String orderId, String content) { 57 | if (StringUtils.isBlank(content)) { 58 | throw new NullFiledException("评价内容不能为空"); 59 | } 60 | Order order = orderRepository.findById(orderId).orElseThrow(() -> new IdNotFoundException("订单不存在")); 61 | if (!order.getUser().getUsername().equals(loginUser.getUsername())) { 62 | throw new SecurityServerException("操作失败", HttpStatus.FORBIDDEN); 63 | } 64 | if (order.getStatus() != Order.STATUS.RECEIPT.getStatus()) { 65 | throw new SecurityServerException("重复评论或被删除", HttpStatus.BAD_REQUEST); 66 | } 67 | User user = new User(); 68 | user.setUsername(loginUser.getUsername()); 69 | 70 | order.setStatus(Order.STATUS.EVALUATION.getStatus()); 71 | Comment comment = new Comment(); 72 | comment.setCommodity(order.getCommodity()); 73 | comment.setUser(user); 74 | comment.setContent(content); 75 | 76 | orderRepository.save(order); 77 | return commentRepository.save(comment); 78 | } 79 | 80 | private String generateAnonymousUserName(String username) { 81 | if (username.length() < 2) { 82 | username += "**"; 83 | } 84 | return username.substring(0, 2) + "***"; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 体育用品商城-服务端 2 | 3 | [![GitHub stars](https://img.shields.io/github/stars/itning/sports-mall-server.svg?style=social&label=Stars)](https://github.com/itning/sports-mall-server/stargazers) 4 | [![GitHub forks](https://img.shields.io/github/forks/itning/sports-mall-server.svg?style=social&label=Fork)](https://github.com/itning/sports-mall-server/network/members) 5 | [![GitHub watchers](https://img.shields.io/github/watchers/itning/sports-mall-server.svg?style=social&label=Watch)](https://github.com/itning/sports-mall-server/watchers) 6 | [![GitHub followers](https://img.shields.io/github/followers/itning.svg?style=social&label=Follow)](https://github.com/itning?tab=followers) 7 | 8 | [![GitHub issues](https://img.shields.io/github/issues/itning/sports-mall-server.svg)](https://github.com/itning/sports-mall-server/issues) 9 | [![GitHub license](https://img.shields.io/github/license/itning/sports-mall-server.svg)](https://github.com/itning/sports-mall-server/blob/master/LICENSE) 10 | [![GitHub last commit](https://img.shields.io/github/last-commit/itning/sports-mall-server.svg)](https://github.com/itning/sports-mall-server/commits) 11 | [![GitHub release](https://img.shields.io/github/release/itning/sports-mall-server.svg)](https://github.com/itning/sports-mall-server/releases) 12 | [![GitHub repo size in bytes](https://img.shields.io/github/repo-size/itning/sports-mall-server.svg)](https://github.com/itning/sports-mall-server) 13 | [![HitCount](https://hitcount.itning.top/?u=itning&r=sports-mall-server)](https://github.com/itning/hit-count) 14 | [![language](https://img.shields.io/badge/language-JAVA-green.svg)](https://github.com/itning/sports-mall-server) 15 | 16 | ## 架构: 17 | - MySQL 8 18 | - Java 11 19 | - Spring Boot 2 20 | - Vue.JS 21 | 22 | ## 功能 23 | 24 | - 垂直/水平轮播图展示管理 25 | - 商品分类展示管理 26 | - 商品搜索 27 | - 推荐商品管理展示 28 | - 订单管理 29 | - 购物车管理 30 | - 登录注册 31 | - 商品评论展示 32 | - 商品详情信息展示 33 | - 商品介绍跑马灯 34 | 35 | ## 部署 36 | 37 | 1. 使用git克隆项目([Git是什么,如何使用?](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/)) 38 | 39 | ```bash 40 | # 克隆后端文件到本地磁盘 41 | git clone https://github.com/itning/sports-mall-server 42 | # 克隆前端文件到本地磁盘 43 | git clone https://github.com/itning/sports-mall-client 44 | ``` 45 | 46 | 2. 打开前端文件夹 47 | 48 | 安装之前确保你有[node.js](https://nodejs.org/zh-cn/)和[yarn](https://classic.yarnpkg.com/zh-Hans/docs/install/#windows-stable) 49 | 50 | ```bash 51 | # 如果已经在前端文件夹内了,则不需要这个命令 52 | cd sports-mall-client 53 | # 安装依赖 54 | yarn install 55 | ``` 56 | 57 | 3. 后端建议使用[idea](https://www.jetbrains.com/idea/)打开本项目,不建议使用Eclipse或MyEclipse 58 | 59 | 确保你有[maven](https://maven.apache.org/download.cgi),并执行编译命令 60 | 61 | ```bash 62 | mvn clean compile 63 | ``` 64 | 65 | 不出意外会出现`BUILD SUCCESS` 66 | 67 | 4. 数据库密码在哪改? 68 | 69 | [在这](https://github.com/itning/sports-mall-server/blob/master/src/main/resources/application.properties#L22) 70 | 71 | 5. 前端接口域名在哪改? 72 | 73 | [在这](https://github.com/itning/sports-mall-client/blob/master/src/api/index.js#L1) 74 | 75 | 6. 登录管理员账户? 76 | 77 | ```sql 78 | # 先插入管理员账户数据 用户名:admin 密码:admin 79 | INSERT INTO `mail_user` VALUES ('admin', NULL, 'admin@admin.co', '2020-02-13 11:31:24.451000', '2020-02-13 11:31:24.451000', 'admin', '17588755691', '1'); 80 | ``` 81 | 82 | 7. 运行项目: 83 | 84 | 后端[main方法](https://github.com/itning/sports-mall-server/blob/master/src/main/java/com/sport/sportsmallserver/SportsMailServerApplication.java#L9)直接运行 85 | 86 | 前端执行以下命令进行开发运行 87 | 88 | ```bash 89 | yarn serve 90 | ``` 91 | 92 | 8. 数据库SQL文件? 93 | 94 | JPA自动建库建表不需要SQL文件。 95 | 96 | ## 项目预览 97 | 98 | ![a](https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/1.png) 99 | 100 | ![b](https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/2.png) 101 | 102 | ![c](https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/3.png) 103 | 104 | ![d](https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/4.png) 105 | 106 | ![e](https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/5.png) 107 | 108 | ![f](https://raw.githubusercontent.com/itning/sports-mall-server/master/pic/6.png) 109 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service.impl; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.sport.sportsmallserver.dto.LoginUser; 5 | import com.sport.sportsmallserver.entity.Role; 6 | import com.sport.sportsmallserver.entity.User; 7 | import com.sport.sportsmallserver.exception.IdNotFoundException; 8 | import com.sport.sportsmallserver.exception.NullFiledException; 9 | import com.sport.sportsmallserver.exception.SecurityServerException; 10 | import com.sport.sportsmallserver.exception.TokenException; 11 | import com.sport.sportsmallserver.repository.RoleRepository; 12 | import com.sport.sportsmallserver.repository.UserRepository; 13 | import com.sport.sportsmallserver.service.UserService; 14 | import com.sport.sportsmallserver.util.JwtUtils; 15 | import com.sport.sportsmallserver.util.OrikaUtils; 16 | import org.apache.commons.lang3.StringUtils; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.http.HttpStatus; 19 | import org.springframework.stereotype.Service; 20 | import org.springframework.transaction.annotation.Transactional; 21 | 22 | /** 23 | * @author itning 24 | * @date 2020/2/12 11:31 25 | */ 26 | @Service 27 | @Transactional(rollbackFor = Exception.class) 28 | public class UserServiceImpl implements UserService { 29 | private final UserRepository userRepository; 30 | 31 | @Autowired 32 | public UserServiceImpl(UserRepository userRepository, RoleRepository roleRepository) { 33 | this.userRepository = userRepository; 34 | if (!roleRepository.existsById(Role.ROLE_ADMIN_ID)) { 35 | Role role = new Role(); 36 | role.setId(Role.ROLE_ADMIN_ID); 37 | role.setName("管理员"); 38 | roleRepository.save(role); 39 | } 40 | if (!roleRepository.existsById(Role.ROLE_USER_ID)) { 41 | Role role = new Role(); 42 | role.setId(Role.ROLE_USER_ID); 43 | role.setName("用户"); 44 | roleRepository.save(role); 45 | } 46 | } 47 | 48 | @Override 49 | public String login(String username, String password) throws JsonProcessingException { 50 | if (StringUtils.isAnyBlank(username, password)) { 51 | throw new NullFiledException("用户名/密码不能为空"); 52 | } 53 | User user = userRepository.findById(username).orElseThrow(() -> new IdNotFoundException("用户名不存在")); 54 | if (!password.equals(user.getPassword())) { 55 | throw new SecurityServerException("密码错误", HttpStatus.BAD_REQUEST); 56 | } 57 | LoginUser loginUser = OrikaUtils.a2b(user, LoginUser.class); 58 | return JwtUtils.buildJwt(loginUser); 59 | } 60 | 61 | @Override 62 | public void modifyUser(LoginUser loginUser, User user) { 63 | User savedUser = userRepository.findById(loginUser.getUsername()).orElseThrow(() -> new TokenException("用户不存在", HttpStatus.BAD_REQUEST)); 64 | if (StringUtils.isNotBlank(user.getAddress())) { 65 | savedUser.setAddress(user.getAddress()); 66 | } 67 | if (StringUtils.isNotBlank(user.getEmail())) { 68 | if (userRepository.existsByEmail(user.getEmail())) { 69 | throw new NullFiledException("该邮箱已经被注册"); 70 | } 71 | savedUser.setEmail(user.getEmail()); 72 | } 73 | if (StringUtils.isNotBlank(user.getTel())) { 74 | savedUser.setTel(user.getTel()); 75 | } 76 | userRepository.save(savedUser); 77 | } 78 | 79 | @Override 80 | public LoginUser reg(String username, String email, String phone, String password) { 81 | if (StringUtils.isAnyBlank(username, email, phone, password)) { 82 | throw new NullFiledException("某些字段为空"); 83 | } 84 | if (userRepository.existsByEmail(email)) { 85 | throw new SecurityServerException("邮箱已被注册", HttpStatus.BAD_REQUEST); 86 | } 87 | if (userRepository.existsById(username)) { 88 | throw new SecurityServerException("用户名已被注册", HttpStatus.BAD_REQUEST); 89 | } 90 | Role role = new Role(); 91 | role.setId(Role.ROLE_USER_ID); 92 | 93 | User user = new User(); 94 | user.setUsername(username); 95 | user.setPassword(password); 96 | user.setEmail(email); 97 | user.setTel(phone); 98 | user.setRole(role); 99 | User savedUser = userRepository.save(user); 100 | return OrikaUtils.a2b(savedUser, LoginUser.class); 101 | } 102 | 103 | @Override 104 | public void changePwd(LoginUser loginUser, String oldPwd, String newPwd) { 105 | if (StringUtils.isAnyBlank(oldPwd, newPwd)) { 106 | throw new NullFiledException("密码不能为空"); 107 | } 108 | User user = userRepository.findById(loginUser.getUsername()).orElseThrow(() -> new TokenException("用户不存在", HttpStatus.BAD_REQUEST)); 109 | if (!oldPwd.equals(user.getPassword())) { 110 | throw new SecurityServerException("密码错误", HttpStatus.BAD_REQUEST); 111 | } 112 | if (newPwd.equals(user.getPassword())) { 113 | throw new SecurityServerException("新密码不能和旧密码相同", HttpStatus.BAD_REQUEST); 114 | } 115 | user.setPassword(newPwd); 116 | userRepository.save(user); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/controller/CommodityController.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.controller; 2 | 3 | import com.sport.sportsmallserver.dto.CommodityDTO; 4 | import com.sport.sportsmallserver.dto.LoginUser; 5 | import com.sport.sportsmallserver.dto.RestModel; 6 | import com.sport.sportsmallserver.security.MustAdminLogin; 7 | import com.sport.sportsmallserver.security.MustUserLogin; 8 | import com.sport.sportsmallserver.service.CommodityService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.data.domain.Pageable; 11 | import org.springframework.data.domain.Sort; 12 | import org.springframework.data.web.PageableDefault; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.math.BigDecimal; 17 | 18 | /** 19 | * 商品控制器 20 | * 21 | * @author itning 22 | * @date 2020/2/12 12:46 23 | */ 24 | @RestController 25 | @RequestMapping("/commodity") 26 | public class CommodityController { 27 | private final CommodityService commodityService; 28 | 29 | @Autowired 30 | public CommodityController(CommodityService commodityService) { 31 | this.commodityService = commodityService; 32 | } 33 | 34 | /** 35 | * 根据商品类别获取商品 36 | * 37 | * @param typeId 类别ID 38 | * @param pageable 分页 39 | * @return ResponseEntity 40 | */ 41 | @GetMapping("/type") 42 | public ResponseEntity findByType(@MustUserLogin LoginUser loginUser, 43 | @RequestParam String typeId, 44 | @PageableDefault( 45 | size = 20, sort = {"gmtModified"}, 46 | direction = Sort.Direction.DESC 47 | ) 48 | Pageable pageable) { 49 | return RestModel.ok(commodityService.findByType(typeId, pageable)); 50 | } 51 | 52 | /** 53 | * 获取所有推荐商品 54 | * 55 | * @return ResponseEntity 56 | */ 57 | @GetMapping("/recommends") 58 | public ResponseEntity allRecommend() { 59 | return RestModel.ok(commodityService.findByRecommend()); 60 | } 61 | 62 | /** 63 | * 获取一个商品 64 | * 65 | * @param id 商品ID 66 | * @return ResponseEntity 67 | */ 68 | @GetMapping("/one/{id}") 69 | public ResponseEntity getById(@MustUserLogin LoginUser loginUser, 70 | @PathVariable String id) { 71 | return RestModel.ok(commodityService.findById(id)); 72 | } 73 | 74 | /** 75 | * 搜索商品 76 | * 77 | * @param loginUser 登录用户 78 | * @param keyword 关键字 79 | * @param pageable 分页 80 | * @return ResponseEntity 81 | */ 82 | @GetMapping("/search/{keyword}") 83 | public ResponseEntity search(@MustUserLogin LoginUser loginUser, 84 | @PathVariable String keyword, 85 | @PageableDefault( 86 | size = 20, sort = {"gmtModified"}, 87 | direction = Sort.Direction.DESC 88 | ) 89 | Pageable pageable) { 90 | return RestModel.ok(commodityService.search(keyword, pageable)); 91 | } 92 | 93 | /** 94 | * 管理员获取所有商品 95 | * 96 | * @param loginUser 登录用户 97 | * @param pageable 分页 98 | * @return ResponseEntity 99 | */ 100 | @GetMapping("/admin") 101 | public ResponseEntity getAll(@MustAdminLogin LoginUser loginUser, 102 | @PageableDefault( 103 | size = 20, sort = {"gmtModified"}, 104 | direction = Sort.Direction.DESC 105 | ) 106 | Pageable pageable) { 107 | return RestModel.ok(commodityService.findAll(pageable)); 108 | } 109 | 110 | /** 111 | * 修改商品信息 112 | * 113 | * @param loginUser 登录用户 114 | * @param commodity 商品 115 | * @return ResponseEntity 116 | */ 117 | @PatchMapping("/admin") 118 | public ResponseEntity modify(@MustAdminLogin LoginUser loginUser, 119 | @RequestBody CommodityDTO commodity) { 120 | commodityService.modify(commodity); 121 | return RestModel.noContent(); 122 | } 123 | 124 | /** 125 | * 添加商品 126 | * 127 | * @param loginUser 登录用户 128 | * @param name 标题 129 | * @param price 价格 130 | * @param stock 库存 131 | * @param recommended 推荐商品 132 | * @param commodityTypeId 商品分类ID 133 | * @param imgMain 主图 134 | * @param imgSecond 副图 135 | * @param detail 商品详情 136 | * @return ResponseEntity 137 | */ 138 | @PostMapping("/admin") 139 | public ResponseEntity add(@MustAdminLogin LoginUser loginUser, 140 | @RequestParam String name, 141 | @RequestParam BigDecimal price, 142 | @RequestParam BigDecimal stock, 143 | @RequestParam boolean recommended, 144 | @RequestParam String commodityTypeId, 145 | @RequestParam String imgMain, 146 | @RequestParam String imgSecond, 147 | @RequestParam(required = false) String detail) { 148 | return RestModel.created(commodityService.add(name, price, stock.intValue(), recommended, commodityTypeId, imgMain, imgSecond, detail)); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.controller; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.dto.RestModel; 5 | import com.sport.sportsmallserver.security.MustAdminLogin; 6 | import com.sport.sportsmallserver.security.MustLogin; 7 | import com.sport.sportsmallserver.security.MustUserLogin; 8 | import com.sport.sportsmallserver.service.OrderService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.data.domain.Pageable; 11 | import org.springframework.data.domain.Sort; 12 | import org.springframework.data.web.PageableDefault; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.math.BigDecimal; 17 | 18 | /** 19 | * 订单 20 | * 21 | * @author itning 22 | * @date 2020/2/12 19:02 23 | */ 24 | @RestController 25 | public class OrderController { 26 | private final OrderService orderService; 27 | 28 | @Autowired 29 | public OrderController(OrderService orderService) { 30 | this.orderService = orderService; 31 | } 32 | 33 | /** 34 | * 下订单 35 | * 36 | * @param loginUser 登录用户 37 | * @param commodityId 商品ID 38 | * @param count 数量 39 | * @param address 收货地址 40 | * @return ResponseEntity 41 | */ 42 | @PostMapping("/order") 43 | public ResponseEntity newOrder(@MustUserLogin LoginUser loginUser, 44 | @RequestParam String commodityId, 45 | @RequestParam int count, 46 | @RequestParam String address) { 47 | return RestModel.created(orderService.newOrder(loginUser, commodityId, count, address)); 48 | } 49 | 50 | /** 51 | * 获取所有订单 52 | * 53 | * @param loginUser 登录用户 54 | * @param pageable 分页 55 | * @return ResponseEntity 56 | */ 57 | @GetMapping("/orders") 58 | public ResponseEntity getAllOrders(@MustUserLogin LoginUser loginUser, 59 | @RequestParam(required = false) int[] status, 60 | @PageableDefault( 61 | size = 20, sort = {"gmtModified"}, 62 | direction = Sort.Direction.DESC 63 | ) 64 | Pageable pageable) { 65 | return RestModel.ok(orderService.getAll(loginUser, status, pageable)); 66 | } 67 | 68 | /** 69 | * 删除订单 70 | * 71 | * @param loginUser 登录用户 72 | * @param id 订单ID 73 | * @return ResponseEntity 74 | */ 75 | @DeleteMapping("/order/{id}") 76 | public ResponseEntity delOrder(@MustLogin(role = {MustLogin.ROLE.ADMIN, MustLogin.ROLE.USER}) LoginUser loginUser, 77 | @PathVariable String id) { 78 | orderService.delOrder(loginUser, id); 79 | return RestModel.noContent(); 80 | } 81 | 82 | /** 83 | * 订单付款 84 | * 85 | * @param loginUser 登录用户 86 | * @param orderId 订单ID 87 | * @return ResponseEntity 88 | */ 89 | @PostMapping("/order/pay") 90 | public ResponseEntity payOrder(@MustUserLogin LoginUser loginUser, 91 | @RequestParam String orderId) { 92 | return RestModel.created(orderService.pay(loginUser, orderId)); 93 | } 94 | 95 | /** 96 | * 订单发货 97 | * 98 | * @param loginUser 登录用户 99 | * @param orderId 订单ID 100 | * @param expressInformation 快递信息 101 | * @return ResponseEntity 102 | */ 103 | @PostMapping("/order/hip") 104 | public ResponseEntity hipOrder(@MustAdminLogin LoginUser loginUser, 105 | @RequestParam String orderId, 106 | @RequestParam String expressInformation) { 107 | return RestModel.created(orderService.ship(orderId, expressInformation)); 108 | } 109 | 110 | /** 111 | * 订单确认收货 112 | * 113 | * @param loginUser 登录用户 114 | * @param orderId 订单ID 115 | * @return ResponseEntity 116 | */ 117 | @PostMapping("/order/receipt") 118 | public ResponseEntity receiptOrder(@MustUserLogin LoginUser loginUser, 119 | @RequestParam String orderId) { 120 | return RestModel.created(orderService.receipt(loginUser, orderId)); 121 | } 122 | 123 | /** 124 | * 管理员获取订单信息 125 | * 126 | * @param loginUser 登录用户 127 | * @param status 要获取的订单状态 128 | * @param pageable 分页 129 | * @return ResponseEntity 130 | */ 131 | @GetMapping("/orders/admin") 132 | public ResponseEntity getAllOrderForAdmin(@MustAdminLogin LoginUser loginUser, 133 | @RequestParam(required = false) int[] status, 134 | @PageableDefault( 135 | size = 20, sort = {"gmtModified"}, 136 | direction = Sort.Direction.DESC 137 | ) 138 | Pageable pageable) { 139 | return RestModel.ok(orderService.getAll(status, pageable)); 140 | } 141 | 142 | /** 143 | * 修改订单 144 | * 145 | * @param loginUser 登录用户 146 | * @param id 订单ID 147 | * @param newPrice 新价格 148 | * @return ResponseEntity 149 | */ 150 | @PostMapping("/order/price") 151 | public ResponseEntity changeOrderPrice(@MustAdminLogin LoginUser loginUser, 152 | @RequestParam String id, 153 | @RequestParam BigDecimal newPrice) { 154 | return RestModel.created(orderService.changePrice(id, newPrice)); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/impl/CommodityServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service.impl; 2 | 3 | import com.sport.sportsmallserver.dto.CommodityDTO; 4 | import com.sport.sportsmallserver.entity.Commodity; 5 | import com.sport.sportsmallserver.entity.CommodityDetail; 6 | import com.sport.sportsmallserver.entity.CommodityType; 7 | import com.sport.sportsmallserver.exception.IdNotFoundException; 8 | import com.sport.sportsmallserver.exception.NullFiledException; 9 | import com.sport.sportsmallserver.exception.SecurityServerException; 10 | import com.sport.sportsmallserver.repository.CommodityDetailRepository; 11 | import com.sport.sportsmallserver.repository.CommodityRepository; 12 | import com.sport.sportsmallserver.repository.CommodityTypeRepository; 13 | import com.sport.sportsmallserver.service.CommodityService; 14 | import org.apache.commons.lang3.StringUtils; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.data.domain.Page; 17 | import org.springframework.data.domain.Pageable; 18 | import org.springframework.http.HttpStatus; 19 | import org.springframework.stereotype.Service; 20 | import org.springframework.transaction.annotation.Transactional; 21 | 22 | import java.math.BigDecimal; 23 | import java.util.Arrays; 24 | import java.util.List; 25 | 26 | /** 27 | * @author itning 28 | * @date 2020/2/12 12:49 29 | */ 30 | @Service 31 | @Transactional(rollbackFor = Exception.class) 32 | public class CommodityServiceImpl implements CommodityService { 33 | private static final String SECOND_IMG_SUFFIX = ";"; 34 | 35 | private final CommodityRepository commodityRepository; 36 | private final CommodityTypeRepository commodityTypeRepository; 37 | private final CommodityDetailRepository commodityDetailRepository; 38 | 39 | @Autowired 40 | public CommodityServiceImpl(CommodityRepository commodityRepository, CommodityTypeRepository commodityTypeRepository, CommodityDetailRepository commodityDetailRepository) { 41 | this.commodityRepository = commodityRepository; 42 | this.commodityTypeRepository = commodityTypeRepository; 43 | this.commodityDetailRepository = commodityDetailRepository; 44 | } 45 | 46 | @Override 47 | public Page findByType(String typeId, Pageable pageable) { 48 | if (StringUtils.isBlank(typeId)) { 49 | throw new NullFiledException("商品类别为空"); 50 | } 51 | CommodityType commodityType = commodityTypeRepository.findById(typeId).orElseThrow(() -> new IdNotFoundException("商品类别没有找到")); 52 | return commodityRepository.findAllByCommodityTypeAndTakeOff(commodityType, false, pageable); 53 | } 54 | 55 | @Override 56 | public List findByRecommend() { 57 | return commodityRepository.findAllByRecommendedAndTakeOff(true, false); 58 | } 59 | 60 | @Override 61 | public Commodity findById(String id) { 62 | Commodity commodity = commodityRepository.findById(id).orElseThrow(() -> new IdNotFoundException("商品不存在")); 63 | if (commodity.isTakeOff()) { 64 | throw new SecurityServerException("商品已下架", HttpStatus.NOT_FOUND); 65 | } 66 | return commodity; 67 | } 68 | 69 | @Override 70 | public Page search(String keyword, Pageable pageable) { 71 | if (StringUtils.isBlank(keyword)) { 72 | throw new NullFiledException("关键字不能为空"); 73 | } 74 | return commodityRepository.findAllByTakeOffAndNameLike(false, "%" + keyword + "%", pageable); 75 | } 76 | 77 | @Override 78 | public Page findAll(Pageable pageable) { 79 | return commodityRepository.findAllByTakeOff(false, pageable); 80 | } 81 | 82 | @Override 83 | public void modify(CommodityDTO commodity) { 84 | if (StringUtils.isBlank(commodity.getId())) { 85 | throw new NullFiledException("商品ID为空"); 86 | } 87 | Commodity saved = commodityRepository.findById(commodity.getId()).orElseThrow(() -> new IdNotFoundException("商品不存在")); 88 | // 1.库存变 89 | if (commodity.getStock() != null) { 90 | saved.setStock(commodity.getStock()); 91 | } 92 | // 2.价格变 93 | if (commodity.getPrice() != null) { 94 | saved.setPrice(commodity.getPrice()); 95 | } 96 | // 3.标题变 97 | if (StringUtils.isNotBlank(commodity.getName())) { 98 | saved.setName(commodity.getName()); 99 | } 100 | // 4.主图片变 101 | if (StringUtils.isNotBlank(commodity.getImgMain())) { 102 | saved.setImgMain(commodity.getImgMain()); 103 | } 104 | // 5.推荐变 105 | if (commodity.getRecommended() != null) { 106 | saved.setRecommended(commodity.getRecommended()); 107 | } 108 | // 6.商品下架? 109 | if (commodity.getTakeOff() != null) { 110 | saved.setTakeOff(commodity.getTakeOff()); 111 | } 112 | // 7.副图片变 113 | if (commodity.getImgSecond() != null) { 114 | try { 115 | if (commodity.getImgSecond().endsWith(SECOND_IMG_SUFFIX)) { 116 | commodity.setImgSecond(commodity.getImgSecond().substring(0, commodity.getImgSecond().length() - 1)); 117 | } 118 | String[] split = commodity.getImgSecond().split(SECOND_IMG_SUFFIX); 119 | System.out.println(Arrays.toString(split)); 120 | } catch (Exception e) { 121 | throw new SecurityServerException("副图片格式错误", HttpStatus.BAD_REQUEST); 122 | } 123 | saved.setImgSecond(commodity.getImgSecond()); 124 | } 125 | // 8.商品分类变 126 | if (commodity.getCommodityType() != null && commodity.getCommodityType().getId() != null) { 127 | CommodityType commodityType = commodityTypeRepository.findById(commodity.getCommodityType().getId()).orElseThrow(() -> new IdNotFoundException("商品分类没找到")); 128 | saved.setCommodityType(commodityType); 129 | } 130 | commodityRepository.save(saved); 131 | } 132 | 133 | @Override 134 | public Commodity add(String name, BigDecimal price, int stock, boolean recommended, String commodityTypeId, String imgMain, String imgSecond, String detail) { 135 | if (StringUtils.isAnyBlank(name, commodityTypeId, imgMain, imgSecond, detail)) { 136 | throw new NullFiledException("字段为空"); 137 | } 138 | if (price.intValue() < 0) { 139 | throw new SecurityServerException("价格不能为负数", HttpStatus.BAD_REQUEST); 140 | } 141 | if (stock < 0) { 142 | throw new SecurityServerException("库存不能为负数", HttpStatus.BAD_REQUEST); 143 | } 144 | try { 145 | if (imgSecond.endsWith(SECOND_IMG_SUFFIX)) { 146 | imgSecond = imgSecond.substring(0, imgSecond.length() - 1); 147 | } 148 | String[] split = imgSecond.split(SECOND_IMG_SUFFIX); 149 | System.out.println(Arrays.toString(split)); 150 | } catch (Exception e) { 151 | throw new SecurityServerException("副图片格式错误", HttpStatus.BAD_REQUEST); 152 | } 153 | CommodityType commodityType = commodityTypeRepository.findById(commodityTypeId).orElseThrow(() -> new IdNotFoundException("商品分类不存在")); 154 | Commodity commodity = new Commodity(); 155 | commodity.setName(name); 156 | commodity.setStock(stock); 157 | commodity.setSales(0); 158 | commodity.setPrice(price); 159 | commodity.setImgMain(imgMain); 160 | commodity.setImgSecond(imgSecond); 161 | commodity.setRecommended(recommended); 162 | commodity.setTakeOff(false); 163 | commodity.setCommodityType(commodityType); 164 | Commodity saved = commodityRepository.save(commodity); 165 | 166 | CommodityDetail commodityDetail = new CommodityDetail(); 167 | commodityDetail.setCommodity(saved); 168 | commodityDetail.setDetail(detail); 169 | commodityDetailRepository.save(commodityDetail); 170 | return saved; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/main/java/com/sport/sportsmallserver/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sport.sportsmallserver.service.impl; 2 | 3 | import com.sport.sportsmallserver.dto.LoginUser; 4 | import com.sport.sportsmallserver.entity.Commodity; 5 | import com.sport.sportsmallserver.entity.Order; 6 | import com.sport.sportsmallserver.entity.Role; 7 | import com.sport.sportsmallserver.entity.User; 8 | import com.sport.sportsmallserver.exception.IdNotFoundException; 9 | import com.sport.sportsmallserver.exception.SecurityServerException; 10 | import com.sport.sportsmallserver.repository.CommodityRepository; 11 | import com.sport.sportsmallserver.repository.OrderRepository; 12 | import com.sport.sportsmallserver.repository.UserRepository; 13 | import com.sport.sportsmallserver.service.OrderService; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.data.domain.Page; 16 | import org.springframework.data.domain.Pageable; 17 | import org.springframework.data.jpa.domain.Specification; 18 | import org.springframework.http.HttpStatus; 19 | import org.springframework.stereotype.Service; 20 | import org.springframework.transaction.annotation.Transactional; 21 | 22 | import javax.persistence.criteria.Join; 23 | import javax.persistence.criteria.JoinType; 24 | import javax.persistence.criteria.Predicate; 25 | import java.math.BigDecimal; 26 | import java.util.ArrayList; 27 | import java.util.Arrays; 28 | import java.util.List; 29 | 30 | /** 31 | * @author itning 32 | * @date 2020/2/12 19:13 33 | */ 34 | @Service 35 | @Transactional(rollbackFor = Exception.class) 36 | public class OrderServiceImpl implements OrderService { 37 | private final OrderRepository orderRepository; 38 | private final CommodityRepository commodityRepository; 39 | private final UserRepository userRepository; 40 | 41 | @Autowired 42 | public OrderServiceImpl(OrderRepository orderRepository, CommodityRepository commodityRepository, UserRepository userRepository) { 43 | this.orderRepository = orderRepository; 44 | this.commodityRepository = commodityRepository; 45 | this.userRepository = userRepository; 46 | } 47 | 48 | @Override 49 | public Order newOrder(LoginUser loginUser, String commodityId, int count, String address) { 50 | Commodity commodity = commodityRepository.findById(commodityId).orElseThrow(() -> new IdNotFoundException("商品不存在")); 51 | if (commodity.isTakeOff()) { 52 | throw new SecurityServerException("商品已下架", HttpStatus.NOT_FOUND); 53 | } 54 | if (commodity.getStock() < count) { 55 | throw new SecurityServerException("库存不足", HttpStatus.BAD_REQUEST); 56 | } 57 | User user = new User(); 58 | user.setUsername(loginUser.getUsername()); 59 | // 减库存 60 | commodity.setStock(commodity.getStock() - count); 61 | // 加销量 62 | commodity.setSales(commodity.getSales() + count); 63 | 64 | Order order = new Order(); 65 | order.setUser(user); 66 | order.setCommodity(commodity); 67 | order.setCountNum(count); 68 | order.setSumPrice(getTotalPrice(commodity.getPrice(), count)); 69 | order.setStatus(Order.STATUS.ORDERED.getStatus()); 70 | 71 | commodityRepository.save(commodity); 72 | return orderRepository.save(order); 73 | } 74 | 75 | @Override 76 | public Page getAll(LoginUser loginUser, int[] status, Pageable pageable) { 77 | final int[] ss = getStatus(status); 78 | return orderRepository.findAll((Specification) (root, query, cb) -> { 79 | List list = new ArrayList<>(); 80 | 81 | Join orderUserJoin = root.join("user", JoinType.INNER); 82 | list.add(cb.equal(orderUserJoin.get("username"), loginUser.getUsername())); 83 | 84 | List or = new ArrayList<>(ss.length); 85 | for (int s : ss) { 86 | or.add(cb.equal(root.get("status"), s)); 87 | } 88 | Predicate[] oo = new Predicate[or.size()]; 89 | list.add(cb.or(or.toArray(oo))); 90 | 91 | Predicate[] p = new Predicate[list.size()]; 92 | return cb.and(list.toArray(p)); 93 | }, pageable); 94 | } 95 | 96 | @Override 97 | public void delOrder(LoginUser loginUser, String orderId) { 98 | Order order = orderRepository.findById(orderId).orElseThrow(() -> new IdNotFoundException("订单不存在")); 99 | User user = userRepository.findById(loginUser.getUsername()).orElseThrow(() -> new IdNotFoundException("用户不存在")); 100 | if (user.getRole().getId().equals(Role.ROLE_ADMIN_ID)) { 101 | if (order.getStatus() == Order.STATUS.DEL_BY_USER.getStatus()) { 102 | order.setStatus(Order.STATUS.DEL_ALL.getStatus()); 103 | } else { 104 | order.setStatus(Order.STATUS.DEL_BY_ADMIN.getStatus()); 105 | } 106 | } else { 107 | if (!order.getUser().getUsername().equals(loginUser.getUsername())) { 108 | throw new SecurityServerException("操作失败", HttpStatus.FORBIDDEN); 109 | } 110 | if (order.getStatus() == Order.STATUS.DEL_BY_ADMIN.getStatus()) { 111 | order.setStatus(Order.STATUS.DEL_ALL.getStatus()); 112 | } else { 113 | order.setStatus(Order.STATUS.DEL_BY_USER.getStatus()); 114 | } 115 | } 116 | orderRepository.save(order); 117 | } 118 | 119 | @Override 120 | public Order pay(LoginUser loginUser, String orderId) { 121 | Order order = orderRepository.findById(orderId).orElseThrow(() -> new IdNotFoundException("订单不存在")); 122 | if (!order.getUser().getUsername().equals(loginUser.getUsername())) { 123 | throw new SecurityServerException("操作失败", HttpStatus.FORBIDDEN); 124 | } 125 | if (order.getStatus() != Order.STATUS.ORDERED.getStatus()) { 126 | throw new SecurityServerException("订单已经付款或被删除", HttpStatus.BAD_REQUEST); 127 | } 128 | order.setStatus(Order.STATUS.BUY.getStatus()); 129 | return orderRepository.save(order); 130 | } 131 | 132 | @Override 133 | public Order ship(String orderId, String expressInformation) { 134 | Order order = orderRepository.findById(orderId).orElseThrow(() -> new IdNotFoundException("订单不存在")); 135 | if (order.getStatus() != Order.STATUS.BUY.getStatus()) { 136 | throw new SecurityServerException("订单未付款或被删除", HttpStatus.BAD_REQUEST); 137 | } 138 | order.setStatus(Order.STATUS.SHIP.getStatus()); 139 | return orderRepository.save(order); 140 | } 141 | 142 | @Override 143 | public Order receipt(LoginUser loginUser, String orderId) { 144 | Order order = orderRepository.findById(orderId).orElseThrow(() -> new IdNotFoundException("订单不存在")); 145 | if (!order.getUser().getUsername().equals(loginUser.getUsername())) { 146 | throw new SecurityServerException("操作失败", HttpStatus.FORBIDDEN); 147 | } 148 | if (order.getStatus() != Order.STATUS.SHIP.getStatus()) { 149 | throw new SecurityServerException("订单已收货或被删除", HttpStatus.BAD_REQUEST); 150 | } 151 | order.setStatus(Order.STATUS.RECEIPT.getStatus()); 152 | return orderRepository.save(order); 153 | } 154 | 155 | @Override 156 | public Page getAll(int[] status, Pageable pageable) { 157 | final int[] ss = getStatus(status); 158 | return orderRepository.findAll((Specification) (root, query, cb) -> { 159 | List list = new ArrayList<>(); 160 | for (int s : ss) { 161 | list.add(cb.equal(root.get("status"), s)); 162 | } 163 | Predicate[] p = new Predicate[list.size()]; 164 | return cb.or(list.toArray(p)); 165 | }, pageable); 166 | } 167 | 168 | @Override 169 | public Order changePrice(String id, BigDecimal newPrice) { 170 | Order order = orderRepository.findById(id).orElseThrow(() -> new IdNotFoundException("订单没有找到")); 171 | order.setSumPrice(newPrice); 172 | return orderRepository.save(order); 173 | } 174 | 175 | private BigDecimal getTotalPrice(BigDecimal price, int count) { 176 | return price.multiply(BigDecimal.valueOf(count)); 177 | } 178 | 179 | private int[] getStatus(int[] status) { 180 | if (null == status || status.length == 0) { 181 | status = new int[]{ 182 | Order.STATUS.ORDERED.getStatus(), 183 | Order.STATUS.BUY.getStatus(), 184 | Order.STATUS.SHIP.getStatus(), 185 | Order.STATUS.RECEIPT.getStatus(), 186 | Order.STATUS.EVALUATION.getStatus(), 187 | }; 188 | } 189 | return Arrays.stream(status) 190 | .filter(i -> i != Order.STATUS.DEL_ALL.getStatus()) 191 | .filter(i -> i != Order.STATUS.DEL_BY_USER.getStatus()) 192 | .filter(i -> i != Order.STATUS.DEL_BY_ADMIN.getStatus()) 193 | .toArray(); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2019 itning 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------