├── src
├── main
│ ├── java
│ │ └── com
│ │ │ └── hmdp
│ │ │ ├── dto
│ │ │ ├── UserDTO.java
│ │ │ ├── LoginFormDTO.java
│ │ │ ├── ScrollResult.java
│ │ │ └── Result.java
│ │ │ ├── utils
│ │ │ ├── RedisData.java
│ │ │ ├── ILock.java
│ │ │ ├── SystemConstants.java
│ │ │ ├── UserHolder.java
│ │ │ ├── RegexPatterns.java
│ │ │ ├── LoginInterceptor.java
│ │ │ ├── RedisConstants.java
│ │ │ ├── RegexUtils.java
│ │ │ ├── PasswordEncoder.java
│ │ │ ├── RedisIdWorker.java
│ │ │ ├── RefreshTokenInterceptor.java
│ │ │ ├── SimpleRedisLock.java
│ │ │ └── CacheClient.java
│ │ │ ├── mapper
│ │ │ ├── BlogMapper.java
│ │ │ ├── ShopMapper.java
│ │ │ ├── UserMapper.java
│ │ │ ├── FollowMapper.java
│ │ │ ├── UserInfoMapper.java
│ │ │ ├── BlogCommentsMapper.java
│ │ │ ├── VoucherOrderMapper.java
│ │ │ ├── SeckillVoucherMapper.java
│ │ │ ├── ShopTypeMapper.java
│ │ │ └── VoucherMapper.java
│ │ │ ├── service
│ │ │ ├── IUserInfoService.java
│ │ │ ├── ISeckillVoucherService.java
│ │ │ ├── IBlogCommentsService.java
│ │ │ ├── IShopTypeService.java
│ │ │ ├── IVoucherService.java
│ │ │ ├── IVoucherOrderService.java
│ │ │ ├── IFollowService.java
│ │ │ ├── IShopService.java
│ │ │ ├── impl
│ │ │ │ ├── UserInfoServiceImpl.java
│ │ │ │ ├── BlogCommentsServiceImpl.java
│ │ │ │ ├── SeckillVoucherServiceImpl.java
│ │ │ │ ├── VoucherServiceImpl.java
│ │ │ │ ├── ShopTypeServiceImpl.java
│ │ │ │ ├── FollowServiceImpl.java
│ │ │ │ ├── ShopServiceImpl.java
│ │ │ │ ├── UserServiceImpl.java
│ │ │ │ ├── BlogServiceImpl.java
│ │ │ │ └── VoucherOrderServiceImpl.java
│ │ │ ├── IBlogService.java
│ │ │ └── IUserService.java
│ │ │ ├── controller
│ │ │ ├── BlogCommentsController.java
│ │ │ ├── ShopTypeController.java
│ │ │ ├── FollowController.java
│ │ │ ├── VoucherOrderController.java
│ │ │ ├── VoucherController.java
│ │ │ ├── UploadController.java
│ │ │ ├── ShopController.java
│ │ │ ├── BlogController.java
│ │ │ └── UserController.java
│ │ │ ├── config
│ │ │ ├── WebExceptionAdvice.java
│ │ │ ├── RedissonConfig.java
│ │ │ ├── MybatisConfig.java
│ │ │ └── MvcConfig.java
│ │ │ ├── HmDianPingApplication.java
│ │ │ └── entity
│ │ │ ├── Follow.java
│ │ │ ├── SeckillVoucher.java
│ │ │ ├── ShopType.java
│ │ │ ├── User.java
│ │ │ ├── BlogComments.java
│ │ │ ├── VoucherOrder.java
│ │ │ ├── UserInfo.java
│ │ │ ├── Blog.java
│ │ │ ├── Voucher.java
│ │ │ └── Shop.java
│ └── resources
│ │ ├── mapper
│ │ └── VoucherMapper.xml
│ │ ├── seckill.lua
│ │ ├── application.yaml
│ │ └── db
│ │ └── hmdp.sql
└── test
│ └── java
│ └── com
│ └── hmdp
│ ├── NormalTest.java
│ ├── RedissonTest.java
│ └── HmDianPingApplicationTests.java
├── .gitignore
└── pom.xml
/src/main/java/com/hmdp/dto/UserDTO.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.dto;
2 | import lombok.Data;
3 | @Data
4 | public class UserDTO {
5 | private Long id;
6 | private String nickName;
7 | private String icon;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/dto/LoginFormDTO.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class LoginFormDTO {
7 | private String phone;
8 | private String code;
9 | private String password;
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/RedisData.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | import lombok.Data;
4 |
5 | import java.time.LocalDateTime;
6 |
7 | @Data
8 | public class RedisData {
9 | private LocalDateTime expireTime;
10 | private Object data;
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/dto/ScrollResult.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.dto;
2 |
3 | import lombok.Data;
4 |
5 | import java.util.List;
6 |
7 | @Data
8 | public class ScrollResult {
9 | private List> list;
10 | private Long minTime;
11 | private Integer offset;
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/BlogMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.entity.Blog;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | */
12 | public interface BlogMapper extends BaseMapper {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/ShopMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.entity.Shop;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | */
12 | public interface ShopMapper extends BaseMapper {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.entity.User;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | */
12 | public interface UserMapper extends BaseMapper {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/FollowMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.entity.Follow;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | */
12 | public interface FollowMapper extends BaseMapper {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/UserInfoMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.entity.UserInfo;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | */
12 | public interface UserInfoMapper extends BaseMapper {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IUserInfoService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.entity.UserInfo;
4 | import com.baomidou.mybatisplus.extension.service.IService;
5 |
6 | /**
7 | *
8 | * 服务类
9 | *
10 | *
11 | */
12 | public interface IUserInfoService extends IService {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/BlogCommentsMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.entity.BlogComments;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | */
12 | public interface BlogCommentsMapper extends BaseMapper {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/VoucherOrderMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.entity.VoucherOrder;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | */
12 | public interface VoucherOrderMapper extends BaseMapper {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/ILock.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | public interface ILock {
4 |
5 | /**
6 | * 尝试获取锁
7 | * @param timeoutSec 锁持有的超时时间,过期后自动释放
8 | * @return true代表获取锁成功; false代表获取锁失败
9 | */
10 | boolean tryLock(long timeoutSec);
11 |
12 | /**
13 | * 释放锁
14 | */
15 | void unlock();
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/SeckillVoucherMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.entity.SeckillVoucher;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * 秒杀优惠券表,与优惠券是一对一关系 Mapper 接口
9 | *
10 | *
11 | */
12 | public interface SeckillVoucherMapper extends BaseMapper {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/ShopTypeMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.hmdp.dto.Result;
4 | import com.hmdp.entity.ShopType;
5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
6 |
7 | /**
8 | *
9 | * Mapper 接口
10 | *
11 | *
12 | */
13 | public interface ShopTypeMapper extends BaseMapper {
14 |
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/ISeckillVoucherService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.entity.SeckillVoucher;
4 | import com.baomidou.mybatisplus.extension.service.IService;
5 |
6 | /**
7 | *
8 | * 秒杀优惠券表,与优惠券是一对一关系 服务类
9 | *
10 | *
11 | */
12 | public interface ISeckillVoucherService extends IService {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/SystemConstants.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | public class SystemConstants {
4 | public static final String IMAGE_UPLOAD_DIR = "D:\\nginx\\nginx-1.18.0\\html\\hmdp\\imgs\\";
5 | public static final String USER_NICK_NAME_PREFIX = "user_";
6 | public static final int DEFAULT_PAGE_SIZE = 5;
7 | public static final int MAX_PAGE_SIZE = 10;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/controller/BlogCommentsController.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.controller;
2 |
3 |
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 |
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | /**
9 | * 前端控制器
10 | */
11 | @RestController
12 | @RequestMapping("/blog-comments")
13 | public class BlogCommentsController {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IBlogCommentsService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.entity.BlogComments;
4 | import com.baomidou.mybatisplus.extension.service.IService;
5 |
6 | /**
7 | *
8 | * 服务类
9 | *
10 | *
11 | * @author 虎哥
12 | * @since 2021-12-22
13 | */
14 | public interface IBlogCommentsService extends IService {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IShopTypeService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.dto.Result;
4 | import com.hmdp.entity.ShopType;
5 | import com.baomidou.mybatisplus.extension.service.IService;
6 |
7 | /**
8 | *
9 | * 服务类
10 | *
11 | *
12 | */
13 | public interface IShopTypeService extends IService {
14 | Result queryshopTypeList();
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IVoucherService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.dto.Result;
4 | import com.hmdp.entity.Voucher;
5 | import com.baomidou.mybatisplus.extension.service.IService;
6 |
7 | /**
8 | *
9 | * 服务类
10 | *
11 | *
12 | */
13 | public interface IVoucherService extends IService {
14 |
15 | Result queryVoucherOfShop(Long shopId);
16 |
17 | void addSeckillVoucher(Voucher voucher);
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/mapper/VoucherMapper.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.hmdp.entity.Voucher;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * Mapper 接口
12 | *
13 | *
14 | */
15 | public interface VoucherMapper extends BaseMapper {
16 |
17 | List queryVoucherOfShop(@Param("shopId") Long shopId);
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IVoucherOrderService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.dto.Result;
4 | import com.hmdp.entity.VoucherOrder;
5 | import com.baomidou.mybatisplus.extension.service.IService;
6 |
7 | /**
8 | *
9 | * 服务类
10 | *
11 | *
12 | */
13 | public interface IVoucherOrderService extends IService {
14 |
15 | Result seckillVoucher(Long voucherId);
16 |
17 | void createVoucherOrder(VoucherOrder voucherOrder);
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/UserHolder.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | import com.hmdp.dto.UserDTO;
4 |
5 | public class UserHolder {
6 | private static final ThreadLocal tl = new ThreadLocal<>();
7 |
8 | public static void saveUser(UserDTO user){
9 | tl.set(user);
10 | }
11 |
12 | public static UserDTO getUser(){
13 | return tl.get();
14 | }
15 |
16 | public static void removeUser(){
17 | tl.remove();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IFollowService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.dto.Result;
4 | import com.hmdp.entity.Follow;
5 | import com.baomidou.mybatisplus.extension.service.IService;
6 |
7 | /**
8 | *
9 | * 服务类
10 | *
11 | *
12 | */
13 | public interface IFollowService extends IService {
14 |
15 | Result follow(Long followUserId, Boolean isFollow);
16 |
17 | Result isFollow(Long followUserId);
18 |
19 | Result followCommons(Long id);
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IShopService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.dto.Result;
4 | import com.hmdp.entity.Shop;
5 | import com.baomidou.mybatisplus.extension.service.IService;
6 |
7 | /**
8 | *
9 | * 服务类
10 | *
11 | *
12 | */
13 | public interface IShopService extends IService {
14 |
15 | Result queryById(Long id);
16 |
17 | Result update(Shop shop);
18 |
19 | Result queryShopByType(Integer typeId, Integer current, Double x, Double y);
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/impl/UserInfoServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service.impl;
2 |
3 | import com.hmdp.entity.UserInfo;
4 | import com.hmdp.mapper.UserInfoMapper;
5 | import com.hmdp.service.IUserInfoService;
6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | *
11 | * 服务实现类
12 | *
13 | *
14 | */
15 | @Service
16 | public class UserInfoServiceImpl extends ServiceImpl implements IUserInfoService {
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/impl/BlogCommentsServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service.impl;
2 |
3 | import com.hmdp.entity.BlogComments;
4 | import com.hmdp.mapper.BlogCommentsMapper;
5 | import com.hmdp.service.IBlogCommentsService;
6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | *
11 | * 服务实现类
12 | *
13 | *
14 | */
15 | @Service
16 | public class BlogCommentsServiceImpl extends ServiceImpl implements IBlogCommentsService {
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/config/WebExceptionAdvice.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.config;
2 |
3 | import com.hmdp.dto.Result;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.web.bind.annotation.ExceptionHandler;
6 | import org.springframework.web.bind.annotation.RestControllerAdvice;
7 |
8 | @Slf4j
9 | @RestControllerAdvice
10 | public class WebExceptionAdvice {
11 |
12 | @ExceptionHandler(RuntimeException.class)
13 | public Result handleRuntimeException(RuntimeException e) {
14 | log.error(e.toString(), e);
15 | return Result.fail("服务器异常");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/impl/SeckillVoucherServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service.impl;
2 |
3 | import com.hmdp.entity.SeckillVoucher;
4 | import com.hmdp.mapper.SeckillVoucherMapper;
5 | import com.hmdp.service.ISeckillVoucherService;
6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | *
11 | * 秒杀优惠券表,与优惠券是一对一关系 服务实现类
12 | *
13 | *
14 | */
15 | @Service
16 | public class SeckillVoucherServiceImpl extends ServiceImpl implements ISeckillVoucherService {
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/HmDianPingApplication.java:
--------------------------------------------------------------------------------
1 | package com.hmdp;
2 |
3 | import org.mybatis.spring.annotation.MapperScan;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.context.annotation.EnableAspectJAutoProxy;
7 |
8 | @EnableAspectJAutoProxy(exposeProxy = true)
9 | @MapperScan("com.hmdp.mapper")
10 | @SpringBootApplication
11 | public class HmDianPingApplication {
12 |
13 | public static void main(String[] args) {
14 | SpringApplication.run(HmDianPingApplication.class, args);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IBlogService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.hmdp.dto.Result;
4 | import com.hmdp.entity.Blog;
5 | import com.baomidou.mybatisplus.extension.service.IService;
6 |
7 | /**
8 | *
9 | * 服务类
10 | *
11 | *
12 | */
13 | public interface IBlogService extends IService {
14 |
15 | Result queryHotBlog(Integer current);
16 |
17 | Result queryBlogById(Long id);
18 |
19 | Result likeBlog(Long id);
20 |
21 | Result queryBlogLikes(Long id);
22 |
23 | Result saveBlog(Blog blog);
24 |
25 | Result queryBlogOfFollow(Long max, Integer offset);
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/service/IUserService.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.hmdp.dto.LoginFormDTO;
5 | import com.hmdp.dto.Result;
6 | import com.hmdp.entity.User;
7 |
8 | import javax.servlet.http.HttpSession;
9 |
10 | /**
11 | *
12 | * 服务类
13 | *
14 | *
15 | */
16 | public interface IUserService extends IService {
17 |
18 | Result sendCode(String phone, HttpSession session);
19 |
20 | Result login(LoginFormDTO loginForm, HttpSession session);
21 |
22 | Result sign();
23 |
24 | Result signCount();
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/RegexPatterns.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 |
4 | public abstract class RegexPatterns {
5 | /**
6 | * 手机号正则
7 | */
8 | public static final String PHONE_REGEX = "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$";
9 | /**
10 | * 邮箱正则
11 | */
12 | public static final String EMAIL_REGEX = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
13 | /**
14 | * 密码正则。4~32位的字母、数字、下划线
15 | */
16 | public static final String PASSWORD_REGEX = "^\\w{4,32}$";
17 | /**
18 | * 验证码正则, 6位数字或字母
19 | */
20 | public static final String VERIFY_CODE_REGEX = "^[a-zA-Z\\d]{6}$";
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/config/RedissonConfig.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.config;
2 |
3 | import org.redisson.Redisson;
4 | import org.redisson.api.RedissonClient;
5 | import org.redisson.config.Config;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | @Configuration
10 | public class RedissonConfig {
11 |
12 | @Bean
13 | public RedissonClient redissonClient(){
14 | // 配置
15 | Config config = new Config();
16 | config.useSingleServer().setAddress("redis://192.168.8.130:6379").setPassword("yangroot");
17 | // 创建RedissonClient对象
18 | return Redisson.create(config);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/VoucherMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/resources/seckill.lua:
--------------------------------------------------------------------------------
1 |
2 | local voucherId = ARGV[1]
3 | local userId = ARGV[2]
4 | local orderId = ARGV[3]
5 |
6 | local stockKey = "seckill:stock:" .. voucherId
7 | local orderKey = "seckill:order:" .. voucherId
8 |
9 | -- 判断库存是否充足(不足,返回 1)
10 | if (tonumber(redis.call('GET', stockKey)) <= 0) then
11 | return 1;
12 | end;
13 |
14 | -- 判断用户是否下单(重复下单,返回 2)
15 | if (redis.call('SISMEMBER', orderKey, userId) == 1) then
16 | return 2;
17 | end;
18 |
19 | -- 下单成功:扣减库存、保存用户。
20 | redis.call('INCRBY', stockKey, -1);
21 | redis.call('SADD', orderKey, userId);
22 | -- 发送消息到 stream.orders 队列中(*:消息的唯一ID 由 Redis 自动生成):XADD stream.orders * key field ...
23 | redis.call('XADD', 'stream.orders', '*', 'userId', userId, 'voucherId', voucherId, 'id', orderId);
24 | return 0;
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/config/MybatisConfig.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.config;
2 |
3 | import com.baomidou.mybatisplus.annotation.DbType;
4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
5 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | @Configuration
10 | public class MybatisConfig {
11 | @Bean
12 | public MybatisPlusInterceptor mybatisPlusInterceptor() {
13 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
14 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
15 | return interceptor;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/controller/ShopTypeController.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.controller;
2 |
3 |
4 | import com.hmdp.dto.Result;
5 | import com.hmdp.entity.ShopType;
6 | import com.hmdp.service.IShopTypeService;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | import javax.annotation.Resource;
12 | import java.util.List;
13 |
14 | /**
15 | *
16 | * 前端控制器
17 | *
18 | *
19 | * @author 虎哥
20 | */
21 | @RestController
22 | @RequestMapping("/shop-type")
23 | public class ShopTypeController {
24 | @Resource
25 | private IShopTypeService typeService;
26 |
27 | @GetMapping("list")
28 | public Result queryTypeList() {
29 | return typeService.queryshopTypeList();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/dto/Result.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.dto;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.util.List;
8 |
9 | @Data
10 | @NoArgsConstructor
11 | @AllArgsConstructor
12 | public class Result {
13 | private Boolean success;
14 | private String errorMsg;
15 | private Object data;
16 | private Long total;
17 |
18 | public static Result ok(){
19 | return new Result(true, null, null, null);
20 | }
21 | public static Result ok(Object data){
22 | return new Result(true, null, data, null);
23 | }
24 | public static Result ok(List> data, Long total){
25 | return new Result(true, null, data, total);
26 | }
27 | public static Result fail(String errorMsg){
28 | return new Result(false, errorMsg, null, null);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 | spring:
4 | application:
5 | name: hmdp
6 | datasource:
7 | driver-class-name: com.mysql.cj.jdbc.Driver
8 | # url: jdbc:mysql://127.0.0.1:3306/hmdp?useSSL=false&serverTimezone=UTC
9 | username: root
10 | password: 123456
11 | url: jdbc:mysql://localhost:3306/hmdp?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
12 | redis:
13 | host: 192.168.8.130
14 | port: 6379
15 | password: yangroot
16 | lettuce:
17 | pool:
18 | max-active: 10
19 | max-idle: 10
20 | min-idle: 1
21 | time-between-eviction-runs: 10s
22 | timeout: 2000ms
23 | jackson:
24 | default-property-inclusion: non_null # JSON处理时忽略非空字段
25 | mybatis-plus:
26 | type-aliases-package: com.hmdp.entity # 别名扫描包
27 | logging:
28 | level:
29 | com.hmdp: debug
30 | pattern:
31 | dateformat: mm:ss.SSS
32 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/entity/Follow.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableName;
4 | import com.baomidou.mybatisplus.annotation.IdType;
5 | import java.time.LocalDateTime;
6 | import com.baomidou.mybatisplus.annotation.TableId;
7 | import java.io.Serializable;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 | import lombok.experimental.Accessors;
11 |
12 | /**
13 | *
14 | */
15 | @Data
16 | @EqualsAndHashCode(callSuper = false)
17 | @Accessors(chain = true)
18 | @TableName("tb_follow")
19 | public class Follow implements Serializable {
20 |
21 | private static final long serialVersionUID = 1L;
22 |
23 | /**
24 | * 主键
25 | */
26 | @TableId(value = "id", type = IdType.AUTO)
27 | private Long id;
28 |
29 | /**
30 | * 用户id
31 | */
32 | private Long userId;
33 |
34 | /**
35 | * 关联的用户id
36 | */
37 | private Long followUserId;
38 |
39 | /**
40 | * 创建时间
41 | */
42 | private LocalDateTime createTime;
43 |
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/LoginInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | import cn.hutool.core.bean.BeanUtil;
4 | import cn.hutool.core.util.StrUtil;
5 | import com.hmdp.dto.UserDTO;
6 | import io.netty.util.internal.StringUtil;
7 | import org.springframework.data.redis.core.StringRedisTemplate;
8 | import org.springframework.web.servlet.HandlerInterceptor;
9 |
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.util.Map;
13 | import java.util.concurrent.TimeUnit;
14 |
15 | public class LoginInterceptor implements HandlerInterceptor {
16 |
17 | @Override
18 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
19 | // 1.判断是否需要拦截(ThreadLocal中是否有用户)
20 | if (UserHolder.getUser() == null) {
21 | // 没有,需要拦截,设置状态码
22 | response.setStatus(401);
23 | // 拦截
24 | return false;
25 | }
26 | // 有用户,则放行
27 | return true;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/RedisConstants.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | public class RedisConstants {
4 | public static final String LOGIN_CODE_KEY = "login:code:";
5 | public static final Long LOGIN_CODE_TTL = 2L;
6 | public static final String LOGIN_USER_KEY = "login:token:";
7 | public static final Long LOGIN_USER_TTL = 36000L;
8 |
9 | public static final Long CACHE_NULL_TTL = 2L;
10 |
11 | public static final Long CACHE_SHOP_TTL = 30L;
12 | public static final String CACHE_SHOP_KEY = "cache:shop:";
13 | public static final String CACHE_SHOPTYPE_KEY = "cache:shoptype:";
14 |
15 | public static final String LOCK_SHOP_KEY = "lock:shop:";
16 | public static final Long LOCK_SHOP_TTL = 10L;
17 |
18 | public static final String SECKILL_STOCK_KEY = "seckill:stock:";
19 | public static final String BLOG_LIKED_KEY = "blog:liked:";
20 | public static final String FEED_KEY = "feed:";
21 | public static final String SHOP_GEO_KEY = "shop:geo:";
22 | public static final String USER_SIGN_KEY = "sign:";
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/controller/FollowController.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.controller;
2 |
3 |
4 | import com.hmdp.dto.Result;
5 | import com.hmdp.service.IFollowService;
6 | import org.springframework.web.bind.annotation.*;
7 |
8 | import javax.annotation.Resource;
9 |
10 | /**
11 | *
12 | * 前端控制器
13 | *
14 | *
15 | */
16 | @RestController
17 | @RequestMapping("/follow")
18 | public class FollowController {
19 |
20 | @Resource
21 | private IFollowService followService;
22 |
23 | @PutMapping("/{id}/{isFollow}")
24 | public Result follow(@PathVariable("id") Long followUserId, @PathVariable("isFollow") Boolean isFollow) {
25 | return followService.follow(followUserId, isFollow);
26 | }
27 |
28 | @GetMapping("/or/not/{id}")
29 | public Result isFollow(@PathVariable("id") Long followUserId) {
30 | return followService.isFollow(followUserId);
31 | }
32 |
33 | @GetMapping("/common/{id}")
34 | public Result followCommons(@PathVariable("id") Long id){
35 | return followService.followCommons(id);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/RegexUtils.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | import cn.hutool.core.util.StrUtil;
4 | public class RegexUtils {
5 | /**
6 | * 是否是无效手机格式
7 | * @param phone 要校验的手机号
8 | * @return true:符合,false:不符合
9 | */
10 | public static boolean isPhoneInvalid(String phone){
11 | return mismatch(phone, RegexPatterns.PHONE_REGEX);
12 | }
13 | /**
14 | * 是否是无效邮箱格式
15 | * @param email 要校验的邮箱
16 | * @return true:符合,false:不符合
17 | */
18 | public static boolean isEmailInvalid(String email){
19 | return mismatch(email, RegexPatterns.EMAIL_REGEX);
20 | }
21 |
22 | /**
23 | * 是否是无效验证码格式
24 | * @param code 要校验的验证码
25 | * @return true:符合,false:不符合
26 | */
27 | public static boolean isCodeInvalid(String code){
28 | return mismatch(code, RegexPatterns.VERIFY_CODE_REGEX);
29 | }
30 |
31 | // 校验是否不符合正则格式
32 | private static boolean mismatch(String str, String regex){
33 | if (StrUtil.isBlank(str)) {
34 | return true;
35 | }
36 | return !str.matches(regex);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/controller/VoucherOrderController.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.controller;
2 |
3 |
4 | import com.hmdp.dto.Result;
5 | import com.hmdp.entity.VoucherOrder;
6 | import com.hmdp.service.IVoucherOrderService;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.web.bind.annotation.PathVariable;
9 | import org.springframework.web.bind.annotation.PostMapping;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 |
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 | import javax.annotation.Resource;
15 |
16 | /**
17 | *
18 | * 前端控制器
19 | *
20 | */
21 | @Slf4j
22 | @RestController
23 | @RequestMapping("/voucher-order")
24 | public class VoucherOrderController {
25 |
26 | @Resource
27 | private IVoucherOrderService voucherOrderService;
28 |
29 | @PostMapping("seckill/{id}")
30 | public Result seckillVoucher(@PathVariable("id") Long voucherId) {
31 | log.info(voucherId.toString());
32 | Result result = voucherOrderService.seckillVoucher(voucherId);
33 | System.out.println(result.toString());
34 |
35 | return voucherOrderService.seckillVoucher(voucherId);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/PasswordEncoder.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 |
4 | import cn.hutool.core.util.RandomUtil;
5 | import org.springframework.util.DigestUtils;
6 |
7 | import java.nio.charset.StandardCharsets;
8 |
9 | public class PasswordEncoder {
10 |
11 | public static String encode(String password) {
12 | // 生成盐
13 | String salt = RandomUtil.randomString(20);
14 | // 加密
15 | return encode(password,salt);
16 | }
17 | private static String encode(String password, String salt) {
18 | // 加密
19 | return salt + "@" + DigestUtils.md5DigestAsHex((password + salt).getBytes(StandardCharsets.UTF_8));
20 | }
21 | public static Boolean matches(String encodedPassword, String rawPassword) {
22 | if (encodedPassword == null || rawPassword == null) {
23 | return false;
24 | }
25 | if(!encodedPassword.contains("@")){
26 | throw new RuntimeException("密码格式不正确!");
27 | }
28 | String[] arr = encodedPassword.split("@");
29 | // 获取盐
30 | String salt = arr[0];
31 | // 比较
32 | return encodedPassword.equals(encode(rawPassword, salt));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/hmdp/NormalTest.java:
--------------------------------------------------------------------------------
1 | package com.hmdp;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | public class NormalTest {
6 |
7 | @Test
8 | void testBitMap() {
9 | int i = 0b1110111111111111111111111;
10 |
11 | long t1 = System.nanoTime();
12 | int count = 0;
13 | while (true){
14 | if ((i & 1) == 0){
15 | break;
16 | }else{
17 | count++;
18 | }
19 | i >>>= 1;
20 | }
21 | long t2 = System.nanoTime();
22 | System.out.println("time1 = " + (t2 - t1));
23 | System.out.println("count = " + count);
24 |
25 | i = 0b1110111111111111111111111;
26 | long t3 = System.nanoTime();
27 | int count2 = 0;
28 | while (true) {
29 | if(i >>> 1 << 1 == i){
30 | // 未签到,结束
31 | break;
32 | }else{
33 | // 说明签到了
34 | count2++;
35 | }
36 |
37 | i >>>= 1;
38 | }
39 | long t4 = System.nanoTime();
40 | System.out.println("time2 = " + (t4 - t3));
41 | System.out.println("count2 = " + count2);
42 | }
43 | }
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/entity/SeckillVoucher.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.annotation.TableName;
6 | import lombok.Data;
7 | import lombok.EqualsAndHashCode;
8 | import lombok.experimental.Accessors;
9 |
10 | import java.io.Serializable;
11 | import java.time.LocalDateTime;
12 |
13 | /**
14 | *
15 | * 秒杀优惠券表,与优惠券是一对一关系
16 | *
16 | *
17 | *
18 | *
19 | */
20 | @Data
21 | @EqualsAndHashCode(callSuper = false)
22 | @Accessors(chain = true)
23 | @TableName("tb_shop_type")
24 | public class ShopType implements Serializable {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | /**
29 | * 主键
30 | */
31 | @TableId(value = "id", type = IdType.AUTO)
32 | private Long id;
33 |
34 | /**
35 | * 类型名称
36 | */
37 | private String name;
38 |
39 | /**
40 | * 图标
41 | */
42 | private String icon;
43 |
44 | /**
45 | * 顺序
46 | */
47 | private Integer sort;
48 |
49 | /**
50 | * 创建时间
51 | */
52 | @JsonIgnore
53 | private LocalDateTime createTime;
54 |
55 | /**
56 | * 更新时间
57 | */
58 | @JsonIgnore
59 | private LocalDateTime updateTime;
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/entity/User.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableField;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import com.baomidou.mybatisplus.annotation.TableName;
7 | import lombok.Data;
8 | import lombok.EqualsAndHashCode;
9 | import lombok.experimental.Accessors;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | /**
15 | *
16 | *
17 | *
18 | *
19 | */
20 | @Data
21 | @EqualsAndHashCode(callSuper = false)
22 | @Accessors(chain = true)
23 | @TableName("tb_user")
24 | public class User implements Serializable {
25 |
26 | private static final long serialVersionUID = 1L;
27 | /**
28 | * 主键
29 | */
30 | @TableId(value = "id", type = IdType.AUTO)
31 | private Long id;
32 | /**
33 | * 手机号码
34 | */
35 | private String phone;
36 | /**
37 | * 密码,加密存储
38 | */
39 | private String password;
40 | /**
41 | * 昵称,默认是随机字符
42 | */
43 | private String nickName;
44 | /**
45 | * 用户头像
46 | */
47 | private String icon = "";
48 | /**
49 | * 创建时间
50 | */
51 | private LocalDateTime createTime;
52 | /**
53 | * 更新时间
54 | */
55 | private LocalDateTime updateTime;
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/config/MvcConfig.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.config;
2 |
3 | import com.hmdp.utils.LoginInterceptor;
4 | import com.hmdp.utils.RefreshTokenInterceptor;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.data.redis.core.StringRedisTemplate;
7 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
9 |
10 | import javax.annotation.Resource;
11 |
12 | @Configuration
13 | public class MvcConfig implements WebMvcConfigurer {
14 |
15 | @Resource
16 | private StringRedisTemplate stringRedisTemplate;
17 |
18 | @Override
19 | public void addInterceptors(InterceptorRegistry registry) {
20 | // 登录拦截器
21 | registry.addInterceptor(new LoginInterceptor())
22 | .excludePathPatterns(
23 | "/shop/**",
24 | "/voucher/**",
25 | "/shop-type/**",
26 | "/upload/**",
27 | "/blog/hot",
28 | "/user/code",
29 | "/user/login"
30 | ).order(1);
31 | // token刷新的拦截器
32 | registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/RedisIdWorker.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | import org.springframework.data.redis.core.StringRedisTemplate;
4 | import org.springframework.stereotype.Component;
5 |
6 | import java.time.LocalDateTime;
7 | import java.time.ZoneOffset;
8 | import java.time.format.DateTimeFormatter;
9 |
10 | @Component
11 | public class RedisIdWorker {
12 | /**
13 | * 开始时间戳
14 | */
15 | private static final long BEGIN_TIMESTAMP = 1640995200L;
16 | /**
17 | * 序列号的位数
18 | */
19 | private static final int COUNT_BITS = 32;
20 |
21 | private StringRedisTemplate stringRedisTemplate;
22 |
23 | public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
24 | this.stringRedisTemplate = stringRedisTemplate;
25 | }
26 |
27 | public long nextId(String keyPrefix) {
28 | // 1.生成时间戳
29 | LocalDateTime now = LocalDateTime.now();
30 | long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
31 | long timestamp = nowSecond - BEGIN_TIMESTAMP;
32 |
33 | // 2.生成序列号
34 | // 2.1.获取当前日期,精确到天
35 | String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
36 | // 2.2.自增长
37 | long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);
38 |
39 | // 3.拼接并返回
40 | return timestamp << COUNT_BITS | count;
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/controller/VoucherController.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.controller;
2 |
3 |
4 | import com.hmdp.dto.Result;
5 | import com.hmdp.entity.Voucher;
6 | import com.hmdp.service.IVoucherService;
7 | import org.springframework.web.bind.annotation.*;
8 |
9 | import javax.annotation.Resource;
10 |
11 | /**
12 | *
13 | * 前端控制器
14 | *
15 | *
16 | * @author 虎哥
17 | */
18 | @RestController
19 | @RequestMapping("/voucher")
20 | public class VoucherController {
21 |
22 | @Resource
23 | private IVoucherService voucherService;
24 |
25 | /**
26 | * 新增秒杀券
27 | * @param voucher 优惠券信息,包含秒杀信息
28 | * @return 优惠券id
29 | */
30 | @PostMapping("seckill")
31 | public Result addSeckillVoucher(@RequestBody Voucher voucher) {
32 | voucherService.addSeckillVoucher(voucher);
33 | return Result.ok(voucher.getId());
34 | }
35 |
36 | /**
37 | * 新增普通券
38 | * @param voucher 优惠券信息
39 | * @return 优惠券id
40 | */
41 | @PostMapping
42 | public Result addVoucher(@RequestBody Voucher voucher) {
43 | voucherService.save(voucher);
44 | return Result.ok(voucher.getId());
45 | }
46 |
47 |
48 | /**
49 | * 查询店铺的优惠券列表
50 | * @param shopId 店铺id
51 | * @return 优惠券列表
52 | */
53 | @GetMapping("/list/{shopId}")
54 | public Result queryVoucherOfShop(@PathVariable("shopId") Long shopId) {
55 | return voucherService.queryVoucherOfShop(shopId);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/entity/BlogComments.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableName;
4 | import com.baomidou.mybatisplus.annotation.IdType;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import java.time.LocalDateTime;
7 | import java.io.Serializable;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 | import lombok.experimental.Accessors;
11 |
12 | /**
13 | *
14 | */
15 | @Data
16 | @EqualsAndHashCode(callSuper = false)
17 | @Accessors(chain = true)
18 | @TableName("tb_blog_comments")
19 | public class BlogComments implements Serializable {
20 |
21 | private static final long serialVersionUID = 1L;
22 |
23 | /**
24 | * 主键
25 | */
26 | @TableId(value = "id", type = IdType.AUTO)
27 | private Long id;
28 |
29 | /**
30 | * 用户id
31 | */
32 | private Long userId;
33 |
34 | /**
35 | * 探店id
36 | */
37 | private Long blogId;
38 |
39 | /**
40 | * 关联的1级评论id,如果是一级评论,则值为0
41 | */
42 | private Long parentId;
43 |
44 | /**
45 | * 回复的评论id
46 | */
47 | private Long answerId;
48 |
49 | /**
50 | * 回复的内容
51 | */
52 | private String content;
53 |
54 | /**
55 | * 点赞数
56 | */
57 | private Integer liked;
58 |
59 | /**
60 | * 状态,0:正常,1:被举报,2:禁止查看
61 | */
62 | private Boolean status;
63 |
64 | /**
65 | * 创建时间
66 | */
67 | private LocalDateTime createTime;
68 |
69 | /**
70 | * 更新时间
71 | */
72 | private LocalDateTime updateTime;
73 |
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/test/java/com/hmdp/RedissonTest.java:
--------------------------------------------------------------------------------
1 | package com.hmdp;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.junit.jupiter.api.BeforeEach;
5 | import org.junit.jupiter.api.Test;
6 | import org.redisson.api.RLock;
7 | import org.redisson.api.RedissonClient;
8 | import org.springframework.boot.test.context.SpringBootTest;
9 |
10 | import javax.annotation.Resource;
11 | import java.util.concurrent.TimeUnit;
12 |
13 | @Slf4j
14 | @SpringBootTest
15 | class RedissonTest {
16 |
17 | @Resource
18 | private RedissonClient redissonClient;
19 |
20 | private RLock lock;
21 |
22 | @BeforeEach
23 | void setUp() {
24 | lock = redissonClient.getLock("order");
25 | }
26 |
27 | @Test
28 | void method1() throws InterruptedException {
29 | // 尝试获取锁
30 | boolean isLock = lock.tryLock(1L, TimeUnit.SECONDS);
31 | if (!isLock) {
32 | log.error("获取锁失败 .... 1");
33 | return;
34 | }
35 | try {
36 | log.info("获取锁成功 .... 1");
37 | method2();
38 | log.info("开始执行业务 ... 1");
39 | } finally {
40 | log.warn("准备释放锁 .... 1");
41 | lock.unlock();
42 | }
43 | }
44 | void method2() {
45 | // 尝试获取锁
46 | boolean isLock = lock.tryLock();
47 | if (!isLock) {
48 | log.error("获取锁失败 .... 2");
49 | return;
50 | }
51 | try {
52 | log.info("获取锁成功 .... 2");
53 | log.info("开始执行业务 ... 2");
54 | } finally {
55 | log.warn("准备释放锁 .... 2");
56 | lock.unlock();
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/entity/VoucherOrder.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.annotation.TableName;
6 | import lombok.Data;
7 | import lombok.EqualsAndHashCode;
8 | import lombok.experimental.Accessors;
9 |
10 | import java.io.Serializable;
11 | import java.time.LocalDateTime;
12 |
13 | /**
14 | *
15 | *
16 | *
17 | */
18 | @Data
19 | @EqualsAndHashCode(callSuper = false)
20 | @Accessors(chain = true)
21 | @TableName("tb_voucher_order")
22 | public class VoucherOrder implements Serializable {
23 |
24 | private static final long serialVersionUID = 1L;
25 |
26 | /**
27 | * 主键
28 | */
29 | @TableId(value = "id", type = IdType.INPUT)
30 | private Long id;
31 |
32 | /**
33 | * 下单的用户id
34 | */
35 | private Long userId;
36 |
37 | /**
38 | * 购买的代金券id
39 | */
40 | private Long voucherId;
41 |
42 | /**
43 | * 支付方式 1:余额支付;2:支付宝;3:微信
44 | */
45 | private Integer payType;
46 |
47 | /**
48 | * 订单状态,1:未支付;2:已支付;3:已核销;4:已取消;5:退款中;6:已退款
49 | */
50 | private Integer status;
51 |
52 | /**
53 | * 下单时间
54 | */
55 | private LocalDateTime createTime;
56 |
57 | /**
58 | * 支付时间
59 | */
60 | private LocalDateTime payTime;
61 |
62 | /**
63 | * 核销时间
64 | */
65 | private LocalDateTime useTime;
66 |
67 | /**
68 | * 退款时间
69 | */
70 | private LocalDateTime refundTime;
71 |
72 | /**
73 | * 更新时间
74 | */
75 | private LocalDateTime updateTime;
76 |
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/entity/UserInfo.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.annotation.TableName;
6 | import lombok.Data;
7 | import lombok.EqualsAndHashCode;
8 | import lombok.experimental.Accessors;
9 |
10 | import java.io.Serializable;
11 | import java.time.LocalDate;
12 | import java.time.LocalDateTime;
13 |
14 | /**
15 | *
16 | *
17 | *
18 | *
19 | */
20 | @Data
21 | @EqualsAndHashCode(callSuper = false)
22 | @Accessors(chain = true)
23 | @TableName("tb_user_info")
24 | public class UserInfo implements Serializable {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | /**
29 | * 主键,用户id
30 | */
31 | @TableId(value = "user_id", type = IdType.AUTO)
32 | private Long userId;
33 |
34 | /**
35 | * 城市名称
36 | */
37 | private String city;
38 |
39 | /**
40 | * 个人介绍,不要超过128个字符
41 | */
42 | private String introduce;
43 |
44 | /**
45 | * 粉丝数量
46 | */
47 | private Integer fans;
48 |
49 | /**
50 | * 关注的人的数量
51 | */
52 | private Integer followee;
53 |
54 | /**
55 | * 性别,0:男,1:女
56 | */
57 | private Boolean gender;
58 |
59 | /**
60 | * 生日
61 | */
62 | private LocalDate birthday;
63 |
64 | /**
65 | * 积分
66 | */
67 | private Integer credits;
68 |
69 | /**
70 | * 会员级别,0~9级,0代表未开通会员
71 | */
72 | private Boolean level;
73 |
74 | /**
75 | * 创建时间
76 | */
77 | private LocalDateTime createTime;
78 |
79 | /**
80 | * 更新时间
81 | */
82 | private LocalDateTime updateTime;
83 |
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/entity/Blog.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableField;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import com.baomidou.mybatisplus.annotation.TableName;
7 | import lombok.Data;
8 | import lombok.EqualsAndHashCode;
9 | import lombok.experimental.Accessors;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @EqualsAndHashCode(callSuper = false)
16 | @Accessors(chain = true)
17 | @TableName("tb_blog")
18 | public class Blog implements Serializable {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | /**
23 | * 主键
24 | */
25 | @TableId(value = "id", type = IdType.AUTO)
26 | private Long id;
27 | /**
28 | * 商户id
29 | */
30 | private Long shopId;
31 | /**
32 | * 用户id
33 | */
34 | private Long userId;
35 | /**
36 | * 用户图标
37 | */
38 | @TableField(exist = false)
39 | private String icon;
40 | /**
41 | * 用户姓名
42 | */
43 | @TableField(exist = false)
44 | private String name;
45 | /**
46 | * 是否点赞过了
47 | */
48 | @TableField(exist = false)
49 | private Boolean isLike;
50 |
51 | /**
52 | * 标题
53 | */
54 | private String title;
55 |
56 | /**
57 | * 探店的照片,最多9张,多张以","隔开
58 | */
59 | private String images;
60 |
61 | /**
62 | * 探店的文字描述
63 | */
64 | private String content;
65 |
66 | /**
67 | * 点赞数量
68 | */
69 | private Integer liked;
70 |
71 | /**
72 | * 评论数量
73 | */
74 | private Integer comments;
75 |
76 | /**
77 | * 创建时间
78 | */
79 | private LocalDateTime createTime;
80 |
81 | /**
82 | * 更新时间
83 | */
84 | private LocalDateTime updateTime;
85 |
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/com/hmdp/utils/RefreshTokenInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.hmdp.utils;
2 |
3 | import cn.hutool.core.bean.BeanUtil;
4 | import cn.hutool.core.util.StrUtil;
5 | import com.hmdp.dto.UserDTO;
6 | import org.springframework.data.redis.core.StringRedisTemplate;
7 | import org.springframework.web.servlet.HandlerInterceptor;
8 |
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 | import java.util.Map;
12 | import java.util.concurrent.TimeUnit;
13 |
14 | import static com.hmdp.utils.RedisConstants.LOGIN_USER_KEY;
15 | import static com.hmdp.utils.RedisConstants.LOGIN_USER_TTL;
16 |
17 | public class RefreshTokenInterceptor implements HandlerInterceptor {
18 |
19 | private StringRedisTemplate stringRedisTemplate;
20 |
21 | public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {
22 | this.stringRedisTemplate = stringRedisTemplate;
23 | }
24 |
25 | @Override
26 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
27 | // 1.获取请求头中的token
28 | String token = request.getHeader("authorization");
29 | if (StrUtil.isBlank(token)) {
30 | return true;
31 | }
32 | // 2.基于TOKEN获取redis中的用户
33 | String key = LOGIN_USER_KEY + token;
34 | Map