项目分布式拆分

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.java1234</groupId>
    <artifactId>miaoshasys33</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>miaosha-common</module>
        <module>miaosha-user</module>
        <module>miaosha-goods</module>
        <module>miaosha-order</module>
        <module>miaosha-miaosha</module>
        <module>miaoshacommon</module>
        <module>miaoshauser</module>
        <module>miaosha-goods</module>
        <module>miaosha-order</module>
        <module>miaosha-miaosha</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <druid.version>1.1.10</druid.version>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <springboot.version>2.3.2.RELEASE</springboot.version>
        <springcloudalibaba.version>2.2.4.RELEASE</springcloudalibaba.version>
        <mybatis-plus.version>3.3.2</mybatis-plus.version>
        <fastjson.version>1.2.35</fastjson.version>
        <commons-lang3.version>3.6</commons-lang3.version>
        <miaosha-common.version>1.0-SNAPSHOT</miaosha-common.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${springcloudalibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!-- mybatis-plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>

            <dependency>
                <groupId>com.java1234</groupId>
                <artifactId>miaosha-common</artifactId>
                <version>${miaosha-common.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>



    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>miaoshasys33</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>miaosha-common</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 服务注册/发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- 配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>

        <!-- spring boot redis 缓存引入 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- lettuce pool 缓存连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <!-- rabbmitmq -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
    </dependencies>
</project>

package com.java1234.miaosha.config;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * rabbitmg配置类
 */
@Configuration
public class MQConfig {

    public static final String MIAOSHA_QUEUE="miaosha_queue";

    @Bean
    public Queue queue(){
        return new Queue(MIAOSHA_QUEUE);
    }
}

package com.java1234.miaosha.config;


import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.time.Duration;

/**
 * Redis配置类
 * 
 * @author Administrator
 *
 */
@Configuration
public class RedisConfig {


	@Value("${spring.redis.host}")
	private String host;
	@Value("${spring.redis.port}")
	private Integer port;
	@Value("${spring.redis.password}")
	private String password;
	@Value("${spring.redis.lettuce.pool.max-idle}")
	private Integer maxIdle;
	@Value("${spring.redis.lettuce.pool.min-idle}")
	private Integer minIdle;
	@Value("${spring.redis.lettuce.pool.max-active}")
	private Integer maxTotal;
	@Value("${spring.redis.lettuce.pool.max-wait}")
	private Duration maxWaitMillis;


	@Bean
	LettuceConnectionFactory lettuceConnectionFactory() {
		// 连接池配置
		GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
		poolConfig.setMaxIdle(maxIdle == null ? 8 : maxIdle);
		poolConfig.setMinIdle(minIdle == null ? 1 : minIdle);
		poolConfig.setMaxTotal(maxTotal == null ? 8 : maxTotal);
		poolConfig.setMaxWaitMillis(maxWaitMillis == null ? 5000L : maxWaitMillis.toMillis());
		LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder()
				.poolConfig(poolConfig)
				.build();
		// 单机redis
		RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
		redisConfig.setHostName(host);
		redisConfig.setPort(port);
		if (password != null && !"".equals(password)) {
			redisConfig.setPassword(password);
		}

		// redisConfig.setPassword(password);

		return new LettuceConnectionFactory(redisConfig, lettucePoolingClientConfiguration);
	}


	@Bean(name="redisTemplate")
	public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
		RedisTemplate<String, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(lettuceConnectionFactory);
		//序列化类
		MyRedisSerializer myRedisSerializer = new MyRedisSerializer();
		//key序列化方式
		template.setKeySerializer(new StringRedisSerializer());
		//value序列化
		template.setValueSerializer(myRedisSerializer);
		//value hashmap序列化
		template.setHashValueSerializer(myRedisSerializer);
		return template;
	}

	@Bean(name="redisTemplate2")
	public RedisTemplate<String, Object> redisTemplate2(LettuceConnectionFactory lettuceConnectionFactory) {
		RedisTemplate<String, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(lettuceConnectionFactory);
		//序列化类
		MyRedisSerializer myRedisSerializer = new MyRedisSerializer();
		//key序列化方式
		template.setKeySerializer(new StringRedisSerializer());
		//value序列化
		template.setValueSerializer(new StringRedisSerializer());
		return template;
	}

	static class MyRedisSerializer implements RedisSerializer<Object> {

		@Override
		public byte[] serialize(Object o) throws SerializationException {
			return serializeObj(o);
		}

		@Override
		public Object deserialize(byte[] bytes) throws SerializationException {
			return deserializeObj(bytes);
		}

		/**
		 * 序列化
		 * @param object
		 * @return
		 */
		private static byte[] serializeObj(Object object) {
			ObjectOutputStream oos = null;
			ByteArrayOutputStream baos = null;
			try {
				baos = new ByteArrayOutputStream();
				oos = new ObjectOutputStream(baos);
				oos.writeObject(object);
				byte[] bytes = baos.toByteArray();
				return bytes;
			} catch (Exception e) {
				throw new RuntimeException("序列化失败!", e);
			}
		}

		/**
		 * 反序列化
		 * @param bytes
		 * @return
		 */
		private static Object deserializeObj(byte[] bytes) {
			if (bytes == null){
				return null;
			}
			ByteArrayInputStream bais = null;
			try {
				bais = new ByteArrayInputStream(bytes);
				ObjectInputStream ois = new ObjectInputStream(bais);
				return ois.readObject();
			} catch (Exception e) {
				throw new RuntimeException("反序列化失败!", e);
			}
		}

	}
}
package com.java1234.miaosha.config;

import com.java1234.miaosha.interceptor.SysInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE","OPTIONS")
                .maxAge(3600);
    }

    public SysInterceptor sysInterceptor(){
        return new SysInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        String[] patterns=new String[]{"/login"};
//        registry.addInterceptor(sysInterceptor())
//                .addPathPatterns("/**")
//                .excludePathPatterns(patterns);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/image/**").addResourceLocations("file:D:\\miaoshaimg\\");
    }
}

package com.java1234.miaosha.constant;


/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-11-28 14:18
 */
public class Constant {

    /**
     * redis token前缀
     */
    public static final String REDIS_TOKEN_PREFIX="tk";

    /**
     * redis 秒杀库存前缀
     */
    public static final String REDIS_STOCK_PREFIX="st";

    /**
     * redis 秒杀商品是否秒杀完标识前缀
     */
    public static final String REDIS_GOODS_MIAOSHA_OVER_PREFIX="over";

    /**
     * redis token有效期30分钟
     */
    public static final Integer REDIS_TOKEN_EXPIRE=30*60;

    /**
     * redis 秒杀商品集合
     */
    public static final String REDIS_MIAOSHA_GOODS="miaosha_goods_list";

    /**
     * redis 秒杀商品集合有效期60分钟
     */
    public static final Integer REDIS_MIAOSHA_GOODS_EXPIRE=60*60;


    /**
     * redis 验证码前缀
     */
    public static final String REDIS_VERIFYCODE_PREFIX="vc";

    /**
     * redis 验证码有效期5分钟
     */
    public static final Integer REDIS_VERIFYCODE_EXPIRE=5*60;



}




package com.java1234.miaosha.entity;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * 自定义返回JSON 数据格式中日期格式化处理
 * @author java1234 小锋 老师
 *
 */
public class CustomDateTimeSerializer extends JsonSerializer<Date>{

	@Override
	public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers)
			throws IOException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
		gen.writeString(sdf.format(value));
	}

}

package com.java1234.miaosha.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * 商品实体
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-11-17 10:57
 */
@TableName("t_goods")
@Data
public class Goods implements Serializable {

    private Integer id; // 编号

    private String name; // 名称

    private double price; // 价格

    private String image; // 商品图片

    private int stock; // 商品库存

    private String detail; // 商品详情




}

package com.java1234.miaosha.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 秒杀商品实体
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-11-17 10:57
 */
@TableName("t_goods_miaosha")
@Data
public class MiaoShaGoods implements Serializable {

    private Integer id; // 编号

    @TableField(select = false)
    private Goods goods; // 关联商品

    private double price; // 秒杀价格

    private Integer stock; // 库存数量

    @JsonSerialize(using=CustomDateTimeSerializer.class)
    private Date startTime; // 秒杀开始时间

    @JsonSerialize(using=CustomDateTimeSerializer.class)
    private Date endTime; // 秒杀结束时间




}

package com.java1234.miaosha.entity;

/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2021-01-02 19:57
 */
public class MiaoShaMessage {

    private User user;
    private Integer miaoShaGoodsId;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Integer getMiaoShaGoodsId() {
        return miaoShaGoodsId;
    }

    public void setMiaoShaGoodsId(Integer miaoShaGoodsId) {
        this.miaoShaGoodsId = miaoShaGoodsId;
    }
}

package com.java1234.miaosha.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 订单实体
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-20 17:04
 */
@TableName("t_order")
@Data
public class Order implements Serializable {

    private String id; // 编号

    private User user; // 购买用户

    private MiaoShaGoods miaoShaGoods; // 购买的秒杀商品

    @JsonSerialize(using=CustomDateTimeSerializer.class)
    private Date createDate; // 创建日期

    private Date payDate; // 支付日期

    private Integer count; // 购买数量

    private double totalPrice; // 订单总金额

    private String payMethod; // 支付方式

    private Integer status; // 订单状态   0:订单生成  1:已支付  2 已发货  3:已收货



}

package com.java1234.miaosha.entity;

import java.util.HashMap;
import java.util.Map;

/**
 * 页面响应entity
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2019-08-13 上午 10:00
 */
public class R extends HashMap<String, Object> {

    private static final long serialVersionUID = 1L;

    public R() {
        put("code", 0);
    }

    public static R error() {
        return error(500, "未知异常,请联系管理员");
    }

    public static R error(String msg) {
        return error(500, msg);
    }

    public static R error(int code, String msg) {
        R r = new R();
        r.put("code", code);
        r.put("msg", msg);
        return r;
    }

    public static R ok(String msg) {
        R r = new R();
        r.put("msg", msg);
        return r;
    }

    public static R ok(Map<String, Object> map) {
        R r = new R();
        r.putAll(map);
        return r;
    }

    public static R ok() {
        return new R();
    }

    public R put(String key, Object value) {
        super.put(key, value);
        return this;
    }
}

package com.java1234.miaosha.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 用户信息实体
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-11-25 20:30
 */
@TableName("t_user")
@Data
public class User implements Serializable {

    @TableId(type = IdType.AUTO)
    private Integer id; // 编号

    private String username; // 用户名

    private String password; // 密码

    private Date registerDate; // 注册日期

    private String address; // 邮寄地址

    private String phoneNumber; // 手机号码

    private String name; // 姓名

}

package com.java1234.miaosha.exception;

import com.java1234.miaosha.entity.R;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public R exceptionHandler(HttpServletRequest request, Exception e){
        System.out.println("全局异常捕获");
        return R.error("服务端异常,请联系管理员"+"<br/>"+e.getMessage()+"<br/>"+e.getStackTrace());
    }
}

package com.java1234.miaosha.interceptor;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SysInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String path=request.getRequestURI();
        System.out.println(path);
        if(handler instanceof HandlerMethod){
            String token = request.getHeader("token");
            System.out.println("token"+token);
            if(StringUtil.isEmpty(token)){
                System.out.println("token未空!");
                throw new RuntimeException("签名验证不存在");
            }else{
                Object o=redisUtil.get(Constant.REDIS_TOKEN_PREFIX,token);
                if(o!=null){
                    System.out.println("验证成功");
                    return true;
                }else{
                    System.out.println("签名失败");
                }
            }
        }else{
            return true;
        }
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

}

package com.java1234.miaosha.util;

import com.alibaba.fastjson.JSON;

/**
 * bean string转换工具类
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-28 15:10
 */
public class BeanUtil {

    /**
     * 将任意类型转换成字符串
     * @param value
     * @param <T>
     * @return
     */
    public static <T> String beanToString(T value) {
        Class<?> clazz = value.getClass();
        if(clazz == int.class || clazz == Integer.class) {
            return value + "";
        }else if(clazz == String.class) {
            return (String)value;
        }else if(clazz == long.class || clazz == Long.class) {
            return value + "";
        }else {
            return JSON.toJSONString(value);
        }
    }


    /**
     * 把一个字符串转换成bean对象
     * @param str
     * @param <T>
     * @return
     */
    public static <T> T stringToBean(String str, Class<T> clazz) {
        if(str == null || str.length() <= 0 || clazz == null) {
            return null;
        }
        if(clazz == int.class || clazz == Integer.class) {
            return (T)Integer.valueOf(str);
        }else if(clazz == String.class) {
            return (T)str;
        }else if(clazz == long.class || clazz == Long.class) {
            return  (T)Long.valueOf(str);
        }else {
            return JSON.toJavaObject(JSON.parseObject(str), clazz);
        }
    }

}

package com.java1234.miaosha.util;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 日期工具类
 * @author Administrator
 *
 */
public class DateUtil {

	/**
	 * 日期对象转字符串
	 * @param date
	 * @param format
	 * @return
	 */
	public static String formatDate(Date date,String format){
		String result="";
		SimpleDateFormat sdf=new SimpleDateFormat(format);
		if(date!=null){
			result=sdf.format(date);
		}
		return result;
	}
	
	/**
	 * 字符串转日期对象
	 * @param str
	 * @param format
	 * @return
	 * @throws Exception
	 */
	public static Date formatString(String str,String format) throws Exception{
		if(StringUtil.isEmpty(str)){
			return null;
		}
		SimpleDateFormat sdf=new SimpleDateFormat(format);
		return sdf.parse(str);
	}
	
	public static String getCurrentDateStr(){
		Date date=new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddhhmmssSSSSSSSSS");
		return sdf.format(date);
	}
	
	public static String getCurrentDatePath()throws Exception{
		Date date=new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd/");
		return sdf.format(date);
	}
	
	public static void main(String[] args) {
		try {
			System.out.println(getCurrentDateStr());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package com.java1234.miaosha.util;

import org.apache.commons.codec.digest.DigestUtils;

/**
 * md5加密工具类
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-11-23 18:54
 */
public class Md5Util {

    private static  final String FRONT_SALT="3dfsty"; // 前端加密盐

    private static final String BACK_SALT_BEFORE="3qx2dfdx3"; // 后端加密前置盐

    private static final String BACK_SALT_AFTER="ds2f3dsf5"; // 后端加密后置盐

    /**
     * md5加密
     * @param data
     * @return
     */
    public static String md5(String data){
        return DigestUtils.md5Hex(data);
    }

    /**
     * 前端加盐后md5加密
     * @param frontData
     * @return
     */
    public static String frontMd5(String frontData){
        return md5(FRONT_SALT+frontData);
    }

    /**
     * 后端加盐后md5加密
     * @param backData
     * @return
     */
    public static String backMd5(String backData){
        return md5(BACK_SALT_BEFORE+backData+BACK_SALT_AFTER);
    }

    public static void main(String[] args) {
        System.out.println("前端md5加密:"+Md5Util.frontMd5("123456"));

        System.out.println("后端md5加密验证:"+backMd5(frontMd5("123456")));
    }


}

package com.java1234.miaosha.util;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis工具类
 * @author Administrator
 *
 */
@Component
public class RedisUtil {

	@Resource(name="redisTemplate")
	private RedisTemplate<String, Object> redisTemplate;

	@Resource(name="redisTemplate2")
	private RedisTemplate<String, Object> redisTemplate2;


	//=============================common============================
	/**
	 * 指定缓存失效时间
	 * @param key 键
	 * @param time 时间()
	 * @return
	 */
	public boolean expire(String key,long time){
		try {
			if(time>0){
				redisTemplate.expire(key, time, TimeUnit.SECONDS);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 指定缓存失效时间
	 * @param prefix 前缀
	 * @param key 键
	 * @param time 时间()
	 * @return
	 */
	public boolean expire(String prefix,String key,long time){
		try {
			if(time>0){
				redisTemplate.expire(prefix+key, time, TimeUnit.SECONDS);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 根据key 获取过期时间
	 * @param key 键 不能为null
	 * @return 时间() 返回0代表为永久有效
	 */
	public long getExpire(String key){
		return redisTemplate.getExpire(key,TimeUnit.SECONDS);
	}

	/**
	 * 判断key是否存在
	 * @param key 键
	 * @return true 存在 false不存在
	 */
	public boolean hasKey(String key){
		try {
			return redisTemplate.hasKey(key);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 删除缓存
	 * @param key 可以传一个值 或多个
	 */
	@SuppressWarnings("unchecked")
	public void del(String ... key){
		if(key!=null&&key.length>0){
			if(key.length==1){
				redisTemplate.delete(key[0]);
			}else{
				redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
			}
		}
	}

	//============================String=============================
	/**
	 * 普通缓存获取
	 * @param key 键
	 * @return 值
	 */
	public Object get(String key){
		return key==null?null:redisTemplate.opsForValue().get(key);
	}

	/**
	 * 普通缓存获取
	 * @param prefix 前缀
	 * @param key 键
	 * @return 值
	 */
	public Object get(String prefix,String key){
		return key==null?null:redisTemplate.opsForValue().get(prefix+key);
	}

	/**
	 * 普通缓存放入
	 * @param key 键
	 * @param value 值
	 * @return true成功 false失败
	 */
	public boolean set(String key,Object value) {
		try {
			redisTemplate.opsForValue().set(key, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * 普通缓存放入(带前缀)
	 * @param prefix 前缀
	 * @param key 键
	 * @param value 值
	 * @return true成功 false失败
	 */
	public boolean set(String prefix,String key,Object value) {
		try {
			redisTemplate.opsForValue().set(prefix+key, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}


	/**
	 * 普通缓存放入(带前缀)
	 * @param prefix 前缀
	 * @param key 键
	 * @param value 值
	 * @return true成功 false失败
	 */
	public boolean set2(String prefix,String key,Object value) {
		try {
			redisTemplate2.opsForValue().set(prefix+key, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * 普通缓存放入并设置时间
	 * @param key 键
	 * @param value 值
	 * @param time 时间() time要大于0 如果time小于等于0 将设置无限期
	 * @return true成功 false 失败
	 */
	public boolean set(String key,Object value,long time){
		try {
			if(time>0){
				redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
			}else{
				set(key, value);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 普通缓存放入并设置时间
	 * @param prefix 前缀
	 * @param key 键
	 * @param value 值
	 * @param time 时间() time要大于0 如果time小于等于0 将设置无限期
	 * @return true成功 false 失败
	 */
	public boolean set(String prefix,String key,Object value,long time){
		try {
			if(time>0){
				redisTemplate.opsForValue().set(prefix+key, value, time, TimeUnit.SECONDS);
			}else{
				set(prefix+key, value);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 递增
	 * @param key 键
	 * @param by 要增加几(大于0)
	 * @return
	 */
	public long incr(String key, long delta){
		if(delta<0){
			throw new RuntimeException("递增因子必须大于0");
		}
		return redisTemplate.opsForValue().increment(key, delta);
	}

	/**
	 * 递减
	 * @param key 键
	 * @param by 要减少几(小于0)
	 * @return
	 */
	public long decr(String key, long delta){
		if(delta<0){
			throw new RuntimeException("递减因子必须大于0");
		}
		return redisTemplate2.opsForValue().increment(key, -delta);
	}

	/**
	 * 递减
	 * @param key 键
	 * @param by 要减少几(小于0)
	 * @return
	 */
	public long decr(String prefix,String key, long delta){
		if(delta<0){
			throw new RuntimeException("递减因子必须大于0");
		}
		return redisTemplate2.opsForValue().decrement(prefix+key, delta);
	}

	//================================Map=================================
	/**
	 * HashGet
	 * @param key 键 不能为null
	 * @param item 项 不能为null
	 * @return 值
	 */
	public Object hget(String key,String item){
		return redisTemplate.opsForHash().get(key, item);
	}

	/**
	 * 获取hashKey对应的所有键值
	 * @param key 键
	 * @return 对应的多个键值
	 */
	public Map<Object,Object> hmget(String key){
		return redisTemplate.opsForHash().entries(key);
	}

	/**
	 * HashSet
	 * @param key 键
	 * @param map 对应多个键值
	 * @return true 成功 false 失败
	 */
	public boolean hmset(String key, Map<String,Object> map){
		try {
			redisTemplate.opsForHash().putAll(key, map);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * HashSet 并设置时间
	 * @param key 键
	 * @param map 对应多个键值
	 * @param time 时间()
	 * @return true成功 false失败
	 */
	public boolean hmset(String key, Map<String,Object> map, long time){
		try {
			redisTemplate.opsForHash().putAll(key, map);
			if(time>0){
				expire(key, time);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 向一张hash表中放入数据,如果不存在将创建
	 * @param key 键
	 * @param item 项
	 * @param value 值
	 * @return true 成功 false失败
	 */
	public boolean hset(String key,String item,Object value) {
		try {
			redisTemplate.opsForHash().put(key, item, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 向一张hash表中放入数据,如果不存在将创建
	 * @param key 键
	 * @param item 项
	 * @param value 值
	 * @param time 时间()  注意:如果已存在的hash表有时间,这里将会替换原有的时间
	 * @return true 成功 false失败
	 */
	public boolean hset(String key,String item,Object value,long time) {
		try {
			redisTemplate.opsForHash().put(key, item, value);
			if(time>0){
				expire(key, time);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 删除hash表中的值
	 * @param key 键 不能为null
	 * @param item 项 可以使多个 不能为null
	 */
	public void hdel(String key, Object... item){
		redisTemplate.opsForHash().delete(key,item);
	}

	/**
	 * 判断hash表中是否有该项的值
	 * @param key 键 不能为null
	 * @param item 项 不能为null
	 * @return true 存在 false不存在
	 */
	public boolean hHasKey(String key, String item){
		return redisTemplate.opsForHash().hasKey(key, item);
	}

	/**
	 * hash递增 如果不存在,就会创建一个 并把新增后的值返回
	 * @param key 键
	 * @param item 项
	 * @param by 要增加几(大于0)
	 * @return
	 */
	public double hincr(String key, String item,double by){
		return redisTemplate.opsForHash().increment(key, item, by);
	}

	/**
	 * hash递减
	 * @param key 键
	 * @param item 项
	 * @param by 要减少记(小于0)
	 * @return
	 */
	public double hdecr(String key, String item,double by){
		return redisTemplate.opsForHash().increment(key, item,-by);
	}

	//============================set=============================
	/**
	 * 根据key获取Set中的所有值
	 * @param key 键
	 * @return
	 */
	public Set<Object> sGet(String key){
		try {
			return redisTemplate.opsForSet().members(key);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 根据value从一个set中查询,是否存在
	 * @param key 键
	 * @param value 值
	 * @return true 存在 false不存在
	 */
	public boolean sHasKey(String key,Object value){
		try {
			return redisTemplate.opsForSet().isMember(key, value);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将数据放入set缓存
	 * @param key 键
	 * @param values 值 可以是多个
	 * @return 成功个数
	 */
	public long sSet(String key, Object...values) {
		try {
			return redisTemplate.opsForSet().add(key, values);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 将set数据放入缓存
	 * @param key 键
	 * @param time 时间()
	 * @param values 值 可以是多个
	 * @return 成功个数
	 */
	public long sSetAndTime(String key,long time,Object...values) {
		try {
			Long count = redisTemplate.opsForSet().add(key, values);
			if(time>0) expire(key, time);
			return count;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 获取set缓存的长度
	 * @param key 键
	 * @return
	 */
	public long sGetSetSize(String key){
		try {
			return redisTemplate.opsForSet().size(key);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 移除值为value的
	 * @param key 键
	 * @param values 值 可以是多个
	 * @return 移除的个数
	 */
	public long setRemove(String key, Object ...values) {
		try {
			Long count = redisTemplate.opsForSet().remove(key, values);
			return count;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}
	//===============================list=================================

	/**
	 * 获取list缓存的内容
	 * @param key 键
	 * @param start 开始
	 * @param end 结束  0 到 -1代表所有值
	 * @return
	 */
	public List<Object> lGet(String key,long start, long end){
		try {
			return redisTemplate.opsForList().range(key, start, end);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取list缓存的长度
	 * @param key 键
	 * @return
	 */
	public long lGetListSize(String key){
		try {
			return redisTemplate.opsForList().size(key);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 通过索引 获取list中的值
	 * @param key 键
	 * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
	 * @return
	 */
	public Object lGetIndex(String key,long index){
		try {
			return redisTemplate.opsForList().index(key, index);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 将list放入缓存
	 * @param key 键
	 * @param value 值
	 * @param time 时间()
	 * @return
	 */
	public boolean lSet(String key, Object value) {
		try {
			redisTemplate.opsForList().rightPush(key, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 * @param key 键
	 * @param value 值
	 * @param time 时间()
	 * @return
	 */
	public boolean lSet(String key, Object value, long time) {
		try {
			redisTemplate.opsForList().rightPush(key, value);
			if (time > 0) expire(key, time);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 * @param key 键
	 * @param value 值
	 * @param time 时间()
	 * @return
	 */
	public boolean lSet(String key, List<Object> value) {
		try {
			redisTemplate.opsForList().rightPushAll(key, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 * @param key 键
	 * @param value 值
	 * @param time 时间()
	 * @return
	 */
	public boolean lSet(String key, List<Object> value, long time) {
		try {
			redisTemplate.opsForList().rightPushAll(key, value);
			if (time > 0) expire(key, time);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 根据索引修改list中的某条数据
	 * @param key 键
	 * @param index 索引
	 * @param value 值
	 * @return
	 */
	public boolean lUpdateIndex(String key, long index,Object value) {
		try {
			redisTemplate.opsForList().set(key, index, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 移除N个值为value
	 * @param key 键
	 * @param count 移除多少个
	 * @param value 值
	 * @return 移除的个数
	 */
	public long lRemove(String key,long count,Object value) {
		try {
			Long remove = redisTemplate.opsForList().remove(key, count, value);
			return remove;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}
}
package com.java1234.miaosha.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 字符串工具类
 * @author 
 *
 */
public class StringUtil {

	/**
	 * 判断是否是空
	 * @param str
	 * @return
	 */
	public static boolean isEmpty(String str){
		if(str==null||"".equals(str.trim())){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 判断是否不是空
	 * @param str
	 * @return
	 */
	public static boolean isNotEmpty(String str){
		if((str!=null)&&!"".equals(str.trim())){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 格式化模糊查询
	 * @param str
	 * @return
	 */
	public static String formatLike(String str){
		if(isNotEmpty(str)){
			return "%"+str+"%";
		}else{
			return null;
		}
	}
	
	/**
	 * 过滤掉集合里的空格
	 * @param list
	 * @return
	 */
	public static List<String> filterWhite(List<String> list){
		List<String> resultList=new ArrayList<String>();
		for(String l:list){
			if(isNotEmpty(l)){
				resultList.add(l);
			}
		}
		return resultList;
	}
	
	/**
	 * 去除html标签
	 */
	public static String stripHtml(String content) { 
	    // <p>段落替换为换行 
	    content = content.replaceAll("<p .*?>", "\r\n"); 
	    // <br><br/>替换为换行 
	    content = content.replaceAll("<br\\s*/?>", "\r\n"); 
	    // 去掉其它的<>之间的东西 
	    content = content.replaceAll("\\<.*?>", ""); 
	    // 去掉空格 
	    content = content.replaceAll(" ", ""); 
	    return content;   
	}
	
	/**
	 * 生成六位随机数
	 * @return
	 */
	public static String genSixRandomNum(){
		Random random = new Random();
		String result="";
		for (int i=0;i<6;i++)
		{
			result+=random.nextInt(10);
		}
		return result;
	}

	/**
	 * 生成由[A-Z,0-9]生成的随机字符串
	 * @param length  欲生成的字符串长度
	 * @return
	 */
	public static String getRandomString(int length){
		Random random = new Random();

		StringBuffer sb = new StringBuffer();

		for(int i = 0; i < length; ++i){
			int number = random.nextInt(2);
			long result = 0;

			switch(number){
				case 0:
					result = Math.round(Math.random() * 25 + 65);
					sb.append(String.valueOf((char)result));
					break;
				case 1:

					sb.append(String.valueOf(new Random().nextInt(10)));
					break;
			}
		}
		return sb.toString();
	}


}

package com.java1234.miaosha.util;

import java.util.UUID;

/**
 * uuid工具类
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-11-28 14:00
 */
public class UUIDUtil {

    public static String genUuid(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }

    public static void main(String[] args) {
        System.out.println(UUIDUtil.genUuid());
    }

}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>miaoshasys33</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>miaosha-common</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 服务注册/发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- 配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>

        <!-- spring boot redis 缓存引入 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- lettuce pool 缓存连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <!-- rabbmitmq -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
    </dependencies>
</project>

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>miaoshasys33</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>miaosha-goods</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>miaosha-common</artifactId>
        </dependency>
    </dependencies>

</project>

package com.java1234.miaosha.controller;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 秒杀商品控制器
 */
@RestController
@RequestMapping("/miaoShaGoods")
public class MiaoShaGoodsController {

    @Autowired
    private IMiaoShaGoodsService miaoShaGoodsService;


    @Autowired
    private RedisUtil redisUtil;
    /**
     * 查询所有秒杀商品
     * @return
     */
    @RequestMapping("/findAll")
    public R findAll(){
        List<MiaoShaGoodsVo> miaoShaGoodsList=null;
        Object o=redisUtil.get(Constant.REDIS_MIAOSHA_GOODS);
        if(o==null){
            System.out.println("从数据库里面查询");
            miaoShaGoodsList = miaoShaGoodsService.listAll();
            redisUtil.set(Constant.REDIS_MIAOSHA_GOODS,miaoShaGoodsList,Constant.REDIS_MIAOSHA_GOODS_EXPIRE);

        }else{
            System.out.println("从redis中取值");
            miaoShaGoodsList= (List<MiaoShaGoodsVo>) o;
        }
        Map<String,Object> map=new HashMap<>();
        map.put("data",miaoShaGoodsList);
        return R.ok(map);
    }

    /**
     * 根据id查询秒杀商品详情
     * @param id
     * @return
     */
    @RequestMapping("/detail")
    public R detail(Integer id){
        MiaoShaGoodsVo miaoShaGoodsVo = miaoShaGoodsService.findById(id);
        Integer miaoShaStatus=0; // 秒杀状态
        Integer remainBeginSecond=0; // 剩余多少秒
        Integer remainEndSecond=0; // 秒杀结束 剩余多少秒

        long startTime = miaoShaGoodsVo.getStartTime().getTime();
        long endTime = miaoShaGoodsVo.getEndTime().getTime();
        long currentTime=System.currentTimeMillis();
        System.out.println("startTime"+startTime);
        System.out.println("endTime"+endTime);
        System.out.println("currentTime"+currentTime);

        if(currentTime<startTime){  //秒杀还没开始 倒计时
            miaoShaStatus=0;
            remainBeginSecond=(int)(startTime-currentTime)/1000;
            remainEndSecond=(int)(endTime-currentTime)/1000;
        }else if(currentTime>endTime){ //秒杀结束
            miaoShaStatus=2;
            remainBeginSecond=-1;
            remainEndSecond=-1;
        }else{  //秒杀进行中
            miaoShaStatus=1;
            remainBeginSecond=0;
            remainEndSecond=(int)(endTime-currentTime)/1000;
        }

        miaoShaGoodsVo.setMiaoShaStatus(miaoShaStatus);
        miaoShaGoodsVo.setRemainBeginSecond(remainBeginSecond);
        miaoShaGoodsVo.setRemainEndSecond(remainEndSecond);

        Map<String,Object> map=new HashMap<>();
        map.put("data",miaoShaGoodsVo);
        return R.ok(map);
    }
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.Goods;

/**
 * 商品接口
 */
public interface GoodsMapper extends BaseMapper<Goods> {

    /**
     * 根据id查询商品
     * @param id
     * @return
     */
    public Goods findById(Integer id);
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.MiaoShaGoods;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;

import java.util.List;

/**
 * 秒杀商品Mapper接口
 */
public interface MiaoShaGoodsMapper extends BaseMapper<MiaoShaGoods> {

    /**
     * 查询所有秒杀商品
     * @return
     */
    public List<MiaoShaGoodsVo> listAll();

    /**
     * 根据id查询详情
     * @param id
     * @return
     */
    public MiaoShaGoodsVo findById(Integer id);

    /**
     * 商品库存减1操作
     * @param id
     * @return
     */
    public Integer reduceStock(Integer id);
}

package com.java1234.miaosha.run;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 启动的时候加载加载秒杀商品库存信息和是否秒杀完成标识
 */
@Component("startupRunner")
public class StartupRunner implements CommandLineRunner {

    @Autowired
    private IMiaoShaGoodsService miaoShaGoodsService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void run(String... args) throws Exception {
        List<MiaoShaGoodsVo> miaoShaGoodsVoList = miaoShaGoodsService.listAll();
        System.out.println("启动加载秒杀库存信息");
        for(MiaoShaGoodsVo miaoShaGoodsVo:miaoShaGoodsVoList){
            System.out.println(miaoShaGoodsVo.getId()+":"+miaoShaGoodsVo.getStock());
            redisUtil.set2(Constant.REDIS_STOCK_PREFIX,miaoShaGoodsVo.getId()+"",miaoShaGoodsVo.getStock()+"");
            redisUtil.set(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX,miaoShaGoodsVo.getId()+"",false);
        }
    }
}

package com.java1234.miaosha.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java1234.miaosha.entity.MiaoShaGoods;
import com.java1234.miaosha.mapper.MiaoShaGoodsMapper;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 秒杀商品service实现类
 */
@Service("miaoshaGoodsService")
public class MiaoShaGoodsServiceImpl extends ServiceImpl<MiaoShaGoodsMapper, MiaoShaGoods> implements IMiaoShaGoodsService {

    @Autowired
    private MiaoShaGoodsMapper miaoShaGoodsMapper;

    @Override
    public List<MiaoShaGoodsVo> listAll() {
        return miaoShaGoodsMapper.listAll();
    }

    @Override
    public MiaoShaGoodsVo findById(Integer id) {
        return miaoShaGoodsMapper.findById(id);
    }
}

package com.java1234.miaosha.service.impl;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.mapper.MiaoShaGoodsMapper;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.util.DateUtil;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;

/**
 * 秒杀Service实现类
 */
@Service("miaoShaService")
public class MiaoShaServiceImpl implements IMiaoShaService {


    @Autowired
    private MiaoShaGoodsMapper miaoShaGoodsMapper;

    @Autowired
    private OrderMapper orderMapper;


    @Autowired
    private RedisUtil redisUtil;
    /**
     * 如果执行成功,返回订单ID,否则返回Null
     * @param user
     * @param miaoShaGoodsVo
     * @return
     */
    @Override
    @Transactional
    public String miaoSha(User user, MiaoShaGoodsVo miaoShaGoodsVo) {
        //库存减1操作
        Integer affectedRows = miaoShaGoodsMapper.reduceStock(miaoShaGoodsVo.getId());

        if(affectedRows==0){
            return null;
        }

        //生成订单
        Order order = new Order();
        order.setId(DateUtil.getCurrentDateStr());  //生成订单号
        order.setUser(user);
        order.setMiaoShaGoods(miaoShaGoodsVo);
        order.setCount(1);
        order.setTotalPrice(miaoShaGoodsVo.getPrice());
        order.setPayMethod(null);
        order.setStatus(0);
        Integer affectedRows2 = orderMapper.add(order);
        if(affectedRows2==0){
            return null;
        }
        return order.getId();
    }

    @Override
    public String getMiaoShaResult(Integer userId, Integer miaoShaGoodsId) {
        HashMap map=new HashMap();
        map.put("user_id",userId);
        map.put("miaosha_goods_id",miaoShaGoodsId);
        Order order=orderMapper.findByUserIdAndMiaoShaGoodsId(map);
        if(order!=null){
            return order.getId();
        }else{
            //  TODO 查询商品是否秒杀完 从redis中判断是否商品秒杀完
            boolean isOver = (boolean) redisUtil.get(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX, miaoShaGoodsId + "");

            boolean over=true;
            if(over){
                return "-1";
            }else{
                return "0";
            }
        }
    }
}

package com.java1234.miaosha.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.java1234.miaosha.entity.MiaoShaGoods;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;

import java.util.List;

/**
 * 秒杀商品service接口
 */
public interface IMiaoShaGoodsService extends IService<MiaoShaGoods> {

    /**
     * 查询所有秒杀商品
     * @return
     */
    public List<MiaoShaGoodsVo> listAll();

    /**
     * 根据id查询详情
     * @param id
     * @return
     */
    public MiaoShaGoodsVo findById(Integer id);
}

package com.java1234.miaosha.service;


import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;


/**
 * 秒杀商品service接口
 */
public interface IMiaoShaService {

    /**
     * 执行秒杀
     * @param user
     * @param miaoShaGoodsVo
     * @return
     */
    public String miaoSha(User user, MiaoShaGoodsVo miaoShaGoodsVo);

    /**
     * 获取秒杀结果
     * @param id
     * @param miaoShaGoodsId
     * @return
     */
    public String getMiaoShaResult(Integer id, Integer miaoShaGoodsId);
}

package com.java1234.miaosha.vo;


import com.java1234.miaosha.entity.MiaoShaGoods;
import lombok.Data;

/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-17 19:28
 */
@Data
public class MiaoShaGoodsVo extends MiaoShaGoods {

    private Integer miaoShaStatus=0; // 秒杀状态
    private Integer remainBeginSecond=0; // 剩余多少秒
    private Integer remainEndSecond=0; // 秒杀结束 剩余多少秒
}

package com.java1234.miaosha;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.java1234.miaosha.mapper")
public class MiaoshaGoodsApplication {

    public static void main(String[] args) {
        SpringApplication.run(MiaoshaGoodsApplication.class, args);
    }

}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.GoodsMapper">

    <resultMap type="com.java1234.miaosha.entity.Goods" id="GoodsResult">
    </resultMap>

    <select id="findById" parameterType="Integer" resultMap="GoodsResult">
        select * from t_goods where id=#{id}
    </select>

</mapper>

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.MiaoShaGoodsMapper">

    <resultMap type="com.java1234.miaosha.vo.MiaoShaGoodsVo" id="MiaoShaGoodsResult">
        <association property="goods" column="goods_id" select="com.java1234.miaosha.mapper.GoodsMapper.findById"></association>
    </resultMap>

    <select id="listAll" resultMap="MiaoShaGoodsResult">
        select * from t_goods_miaosha
    </select>

    <select id="findById" parameterType="Integer" resultMap="MiaoShaGoodsResult">
        select * from t_goods_miaosha where id=#{id}
    </select>

   <update id="reduceStock" parameterType="Integer">
       update t_goods_miaosha set stock=stock-1 where id=#{id} and stock>0
   </update>
</mapper>


server:
  port: 8081
  servlet:
    context-path: /

spring:
  rabbitmq:
    host: 192.168.30.113
    port: 5672
    username: admin
    password: admin
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_miaosha3?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  redis: # redis配置
    host: 192.168.30.113 # IP
    port: 6379  # 端口
    password:  # 密码
    connect-timeout: 10s  # 连接超时时间
    lettuce: # lettuce redis客户端配置
      pool: # 连接池配置
        max-active: 8  # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-wait: 200s  # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-idle: 8 # 连接池中的最大空闲连接 默认 8
        min-idle: 0 # 连接池中的最小空闲连接 默认 0

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true  # 开启驼峰功能  userName  - >  user_name
    auto-mapping-behavior: full  # 自动mapping映射
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mybatis/mapper/*.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>miaoshasys33</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>miaosha-goods</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>miaosha-common</artifactId>
        </dependency>
    </dependencies>

</project>

package com.java1234.miaosha.controller;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.service.IUserService;
import com.java1234.miaosha.util.Md5Util;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.util.StringUtil;
import com.java1234.miaosha.util.UUIDUtil;
import com.java1234.miaosha.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

@RestController
@RequestMapping("/")
public class LoginController    {

    @Autowired
    private IUserService userService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 用户登录
     * @return
     */
    @RequestMapping("/login")
    public R login(@RequestBody UserVo userVo){
        System.out.println("userVo: "+userVo.toString());
        if(userVo==null){
            return R.error();
        }
        if(StringUtil.isEmpty(userVo.getUsername())){
            return R.error("用户名不能为空!");
        }
        if(StringUtil.isEmpty(userVo.getPassword())){
            return R.error("密码不能为空!");
        }
        User resultUser = userService.findByUserName(userVo.getUsername());
        if(resultUser==null){
            return R.error("用户名不存在! ");
        }
        if(!resultUser.getPassword().trim().equals(Md5Util.backMd5(userVo.getPassword().trim()))){
            return R.error("用户名或者密码错误!");
        }
        String token= UUIDUtil.genUuid();   //生成token
        redisUtil.set(Constant.REDIS_TOKEN_PREFIX,token,resultUser,Constant.REDIS_TOKEN_EXPIRE);
        return R.ok(token);
    }

    /**
     * 注册2千用户
     * @return
     */
    @RequestMapping("/register")
    public R register()throws Exception{
        for(int i=0;i<2000;i++){
            User user=new User();
            user.setUsername("user"+i);
            user.setPassword("37cbc2f0be822f5ab96485ac11f3dc98");
            // 生成token
            String token=UUIDUtil.genUuid();

            // 插入数据库
            userService.save(user);

            redisUtil.set(Constant.REDIS_TOKEN_PREFIX,token,user,Constant.REDIS_TOKEN_EXPIRE);

            // 把用户名和token写入txt文件
            addUserToTxt(user.getUsername(),token);


        }
        return R.ok();
    }



    /**
     * 把用户名和token写入txt文件
     * @param username
     * @param token
     */
    private void addUserToTxt(String username, String token) throws Exception{
        String arr=username+","+token;
        FileWriter fw=new FileWriter(new File("D:/users.txt"),true);
        BufferedWriter bw=new BufferedWriter(fw);
        bw.write(arr+"\r\n");
        bw.flush();
        bw.close();
        fw.close();
    }
}

package com.java1234.miaosha.controller;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.rabbitmq.MQSender;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.service.IOrderService;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 秒杀控制器
 */
@RestController
@RequestMapping("/miaoSha")
public class MiaoShaController {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IMiaoShaGoodsService miaoShaGoodsService;

    @Autowired
    private IMiaoShaService miaoShaService;

    @Autowired
    private IOrderService orderService;


    @Autowired
    private MQSender mqSender;

    /**
     * 执行秒杀
     * @param request
     * @param miaoShaGoodsId
     * @return
     */
    @RequestMapping("/exec")
    public R exec(HttpServletRequest request, Integer miaoShaGoodsId,String verifyCode){
        if(StringUtil.isEmpty(verifyCode)){
            return R.error("验证码不能为空!");
        }
        //第一步:根据token得到用户user对象
        String token = request.getHeader("token");
        System.out.println("token:"+token);
        User user = (User)redisUtil.get(Constant.REDIS_TOKEN_PREFIX, token);
        System.out.println(user);

        Object rnd=redisUtil.get(Constant.REDIS_VERIFYCODE_PREFIX, user.getId() + "," + miaoShaGoodsId);
        if(rnd==null){
            return R.error("验证码过期,请重新点击刷新验证码!");
        }
        if(!verifyCode.equals(String.valueOf(rnd))){
            return R.error("验证码结果错误!");
        }

        boolean isOver = (boolean) redisUtil.get(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX, miaoShaGoodsId + "");
        if(isOver){
            return R.ok("秒杀结束");
        }
        long stock = redisUtil.decr(Constant.REDIS_STOCK_PREFIX, miaoShaGoodsId + "", 1);
        if(stock<0){
            return R.error("秒杀失败,商品已经秒光,欢迎参与!");
        }
        MiaoShaMessage mm=new MiaoShaMessage();
        mm.setUser(user);
        mm.setMiaoShaGoodsId(miaoShaGoodsId);
        mqSender.sendMiaoShaMessage(mm);

        return R.ok("排队中");
//        //第二步:判断库存是否足够
//        MiaoShaGoodsVo miaoShaGoods = miaoShaGoodsService.findById(miaoShaGoodsId);
//        Integer stock = miaoShaGoods.getStock();
//        if(stock<=0){
//            return R.error("库存不足!");
//        }
//
//        //第三步:判断用户是否重复秒杀
//        HashMap map = new HashMap();
//        map.put("user_id",user.getId());
//        map.put("miaosha_goods_id",miaoShaGoodsId);
//        Order orderE = orderService.findByUserIdAndMiaoShaGoodsId(map);
//        if(orderE!=null){
//            return R.error("您已经秒杀过此商品,不能重复秒杀");
//        }
//
//        //第四步:减库存,下订单,必须同一个事务
//        String orderId = miaoShaService.miaoSha(user, miaoShaGoods);
//        if(orderId!=null){
//            Map<String,Object> resultMap=new HashMap<>();
//            resultMap.put("orderId",orderId);
//            return R.ok(resultMap);
//        }else{
//            return R.error("系统异常,请稍后重试!");
//        }
    }

    /**
     * 秒杀结果查询
     * @param request
     * @param miaoShaGoodsId
     * @return  >0 返回orderId 订单ID -1 秒杀失败 0  排队中
     */
    @RequestMapping("/result")
    public R result(HttpServletRequest request,Integer miaoShaGoodsId){
        String token = request.getHeader("token");
        System.out.println("token:"+token);
        User user = (User)redisUtil.get(Constant.REDIS_TOKEN_PREFIX, token);
        System.out.println(user);
        String result=miaoShaService.getMiaoShaResult(user.getId(),miaoShaGoodsId);
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("result",result);
        return R.ok(resultMap);
    }
}

package com.java1234.miaosha.controller;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 秒杀商品控制器
 */
@RestController
@RequestMapping("/miaoShaGoods")
public class MiaoShaGoodsController {

    @Autowired
    private IMiaoShaGoodsService miaoShaGoodsService;


    @Autowired
    private RedisUtil redisUtil;
    /**
     * 查询所有秒杀商品
     * @return
     */
    @RequestMapping("/findAll")
    public R findAll(){
        List<MiaoShaGoodsVo> miaoShaGoodsList=null;
        Object o=redisUtil.get(Constant.REDIS_MIAOSHA_GOODS);
        if(o==null){
            System.out.println("从数据库里面查询");
            miaoShaGoodsList = miaoShaGoodsService.listAll();
            redisUtil.set(Constant.REDIS_MIAOSHA_GOODS,miaoShaGoodsList,Constant.REDIS_MIAOSHA_GOODS_EXPIRE);

        }else{
            System.out.println("从redis中取值");
            miaoShaGoodsList= (List<MiaoShaGoodsVo>) o;
        }
        Map<String,Object> map=new HashMap<>();
        map.put("data",miaoShaGoodsList);
        return R.ok(map);
    }

    /**
     * 根据id查询秒杀商品详情
     * @param id
     * @return
     */
    @RequestMapping("/detail")
    public R detail(Integer id){
        MiaoShaGoodsVo miaoShaGoodsVo = miaoShaGoodsService.findById(id);
        Integer miaoShaStatus=0; // 秒杀状态
        Integer remainBeginSecond=0; // 剩余多少秒
        Integer remainEndSecond=0; // 秒杀结束 剩余多少秒

        long startTime = miaoShaGoodsVo.getStartTime().getTime();
        long endTime = miaoShaGoodsVo.getEndTime().getTime();
        long currentTime=System.currentTimeMillis();
        System.out.println("startTime"+startTime);
        System.out.println("endTime"+endTime);
        System.out.println("currentTime"+currentTime);

        if(currentTime<startTime){  //秒杀还没开始 倒计时
            miaoShaStatus=0;
            remainBeginSecond=(int)(startTime-currentTime)/1000;
            remainEndSecond=(int)(endTime-currentTime)/1000;
        }else if(currentTime>endTime){ //秒杀结束
            miaoShaStatus=2;
            remainBeginSecond=-1;
            remainEndSecond=-1;
        }else{  //秒杀进行中
            miaoShaStatus=1;
            remainBeginSecond=0;
            remainEndSecond=(int)(endTime-currentTime)/1000;
        }

        miaoShaGoodsVo.setMiaoShaStatus(miaoShaStatus);
        miaoShaGoodsVo.setRemainBeginSecond(remainBeginSecond);
        miaoShaGoodsVo.setRemainEndSecond(remainEndSecond);

        Map<String,Object> map=new HashMap<>();
        map.put("data",miaoShaGoodsVo);
        return R.ok(map);
    }
}

package com.java1234.miaosha.controller;

import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 秒杀商品控制器
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private IOrderService orderService;




    /**
     * 根据id查询秒杀商品详情
     * @param id
     * @return
     */
    @RequestMapping("/detail")
    public R detail(String id){
        Order order = orderService.findById(id);

        Map<String,Object> map=new HashMap<>();
        map.put("data",order);
        return R.ok(map);
    }
}

package com.java1234.miaosha.controller;


import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.imageio.ImageIO;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;


/**
 * 订单控制器
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-13 11:20
 */
@Controller
@RequestMapping("/verifyCode")
public class VerifyCodeController {



    @Autowired
    private RedisUtil redisUtil;


    /**
     * 返回验证码图片
     * @param miaoShaGoodsId
     * @return
     */
    @RequestMapping(value = "/get",method = RequestMethod.GET)
    public R get(HttpServletResponse response,String token, Integer miaoShaGoodsId){
        System.out.println("token:"+token);
        System.out.println("miaoShaGoodsId:"+miaoShaGoodsId);
    /*    String token = request.getParameter("token");
        System.out.println("token:"+token);*/
        Object o=redisUtil.get(Constant.REDIS_TOKEN_PREFIX,token);
        if(o==null){
            return null;
        }
        if(miaoShaGoodsId==null || miaoShaGoodsId <=0){
            return null;
        }
        try {
            BufferedImage image = this.createVerifyCodeImage(((User) o).getId(), miaoShaGoodsId);
            ServletOutputStream out = response.getOutputStream();
            ImageIO.write(image,"JPEG",out);
            out.flush();
            out.close();
            return null;
        }catch(Exception e){
            e.printStackTrace();
            return R.error("服务端异常");
        }
    }

    private BufferedImage createVerifyCodeImage(Integer userId,Integer miaoShaGoodsId) {
        int width=80;
        int height=32;
        BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        Graphics g=image.getGraphics();
        g.setColor(new Color(0xDCDCDC));
        g.fillRect(0,0,width,height);
        g.setColor(Color.black);
        g.drawRect(0,0,width-1,height-1);
        Random rdm=new Random();
        for(int i=0;i<50;i++){
            int x=rdm.nextInt(width);
            int y=rdm.nextInt(height);
            g.drawOval(x,y,0,0);
        }

        String verifyCode=createVerifyCode();
        System.out.println("验证:"+verifyCode);
        g.setColor(new Color(0,100,0));
        g.setFont(new Font("Candara",Font.BOLD,24));
        g.drawString(verifyCode+"=",8,24);
        g.dispose();

        int rnd=calc(verifyCode);
        System.out.println("rnd:"+rnd);
        redisUtil.set(Constant.REDIS_VERIFYCODE_PREFIX,userId+","+miaoShaGoodsId,rnd,Constant.REDIS_VERIFYCODE_EXPIRE);

        return image;

    }

    public static void main(String[] args) {
        String verifyCode=createVerifyCode();
        System.out.println(calc(verifyCode));
    }

    /**
     * 计算表达式
     * @param exp
     * @return
     */
    private static int calc(String exp) {
        ScriptEngineManager manager=new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        try {
            return (int) engine.eval(exp);
        } catch (ScriptException e) {
            e.printStackTrace();
            return 0;
        }
    }


    private static char[] ops=new char[]{'+','-'};

    /**
     * + - 运算
     * @return
     */
    private static String createVerifyCode() {
        Random rdm=new Random();
        int num1=rdm.nextInt(10);
        int num2=rdm.nextInt(10);
        char op1=ops[rdm.nextInt(2)];
        System.out.println("op1:"+op1);
        String exp=num1+String.valueOf(op1)+num2;
        System.out.println("exp:"+exp);
        return exp;
    }


}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.Goods;

/**
 * 商品接口
 */
public interface GoodsMapper extends BaseMapper<Goods> {

    /**
     * 根据id查询商品
     * @param id
     * @return
     */
    public Goods findById(Integer id);
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.MiaoShaGoods;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;

import java.util.List;

/**
 * 秒杀商品Mapper接口
 */
public interface MiaoShaGoodsMapper extends BaseMapper<MiaoShaGoods> {

    /**
     * 查询所有秒杀商品
     * @return
     */
    public List<MiaoShaGoodsVo> listAll();

    /**
     * 根据id查询详情
     * @param id
     * @return
     */
    public MiaoShaGoodsVo findById(Integer id);

    /**
     * 商品库存减1操作
     * @param id
     * @return
     */
    public Integer reduceStock(Integer id);
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.Order;

import java.util.Map;

/**
 * 用户Mapper接口
 */
public interface OrderMapper extends BaseMapper<Order> {

    /**
     * 根据id查询订单
     * @param id
     * @return
     */
    public Order findById(String id);

    /**
     * 订单生成
     * @param order
     * @return
     */
    public Integer add(Order order);

    /**
     * 根据用户id和秒杀商品id查询订单
     * @param map
     * @return
     */
    public Order findByUserIdAndMiaoShaGoodsId(Map map);
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.User;

/**
 * 用户Mapper接口
 */
public interface UserMapper extends BaseMapper<User> {

    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    public User findById(Integer id);
}

package com.java1234.miaosha.rabbitmq;

import com.java1234.miaosha.config.MQConfig;
import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.service.IOrderService;
import com.java1234.miaosha.util.BeanUtil;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;


@Service
public class MQReceiver {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IMiaoShaGoodsService miaoShaGoodsService;

    @Autowired
    private IMiaoShaService miaoShaService;

    @Autowired
    private IOrderService orderService;




    @RabbitListener(queues = MQConfig.MIAOSHA_QUEUE)
    public void receiveMiaoShaMessage(String message){
        MiaoShaMessage miaoShaMessage = BeanUtil.stringToBean(message, MiaoShaMessage.class);
        System.out.println("receive message:"+miaoShaMessage);
        User user = miaoShaMessage.getUser();

        Integer miaoShaGoodsId=miaoShaMessage.getMiaoShaGoodsId();

        //第二步:判断库存是否足够
        MiaoShaGoodsVo miaoShaGoods = miaoShaGoodsService.findById(miaoShaGoodsId);
        Integer stock = miaoShaGoods.getStock();
        if(stock<=0){
            redisUtil.set(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX,miaoShaGoodsId+"",true);
            System.out.println("库存不足");
            return;
        }
        //第三步:判断用户是否重复秒杀
        HashMap map = new HashMap();
        map.put("user_id",user.getId());
        map.put("miaosha_goods_id",miaoShaGoodsId);
        Order orderE = orderService.findByUserIdAndMiaoShaGoodsId(map);
        if(orderE!=null){
              System.out.println("您已经秒杀过此商品,不能重复秒杀");
              return;
        }

        //第四步:减库存,下订单,必须同一个事务
        String orderId = miaoShaService.miaoSha(user, miaoShaGoods);








    }

}

package com.java1234.miaosha.rabbitmq;


import com.java1234.miaosha.config.MQConfig;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.util.BeanUtil;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MQSender {

    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMiaoShaMessage(MiaoShaMessage miaoShaMessage){
        String msg = BeanUtil.beanToString(miaoShaMessage);
        System.out.println("send message:"+msg);
        amqpTemplate.convertAndSend(MQConfig.MIAOSHA_QUEUE,msg);
    }
}

package com.java1234.miaosha.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java1234.miaosha.entity.MiaoShaGoods;
import com.java1234.miaosha.mapper.MiaoShaGoodsMapper;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 秒杀商品service实现类
 */
@Service("miaoshaGoodsService")
public class MiaoShaGoodsServiceImpl extends ServiceImpl<MiaoShaGoodsMapper, MiaoShaGoods> implements IMiaoShaGoodsService {

    @Autowired
    private MiaoShaGoodsMapper miaoShaGoodsMapper;

    @Override
    public List<MiaoShaGoodsVo> listAll() {
        return miaoShaGoodsMapper.listAll();
    }

    @Override
    public MiaoShaGoodsVo findById(Integer id) {
        return miaoShaGoodsMapper.findById(id);
    }
}

package com.java1234.miaosha.service.impl;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.mapper.MiaoShaGoodsMapper;
import com.java1234.miaosha.mapper.OrderMapper;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.util.DateUtil;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;

/**
 * 秒杀Service实现类
 */
@Service("miaoShaService")
public class MiaoShaServiceImpl implements IMiaoShaService {


    @Autowired
    private MiaoShaGoodsMapper miaoShaGoodsMapper;

    @Autowired
    private OrderMapper orderMapper;


    @Autowired
    private RedisUtil redisUtil;
    /**
     * 如果执行成功,返回订单ID,否则返回Null
     * @param user
     * @param miaoShaGoodsVo
     * @return
     */
    @Override
    @Transactional
    public String miaoSha(User user, MiaoShaGoodsVo miaoShaGoodsVo) {
        //库存减1操作
        Integer affectedRows = miaoShaGoodsMapper.reduceStock(miaoShaGoodsVo.getId());

        if(affectedRows==0){
            return null;
        }

        //生成订单
        Order order = new Order();
        order.setId(DateUtil.getCurrentDateStr());  //生成订单号
        order.setUser(user);
        order.setMiaoShaGoods(miaoShaGoodsVo);
        order.setCount(1);
        order.setTotalPrice(miaoShaGoodsVo.getPrice());
        order.setPayMethod(null);
        order.setStatus(0);
        Integer affectedRows2 = orderMapper.add(order);
        if(affectedRows2==0){
            return null;
        }
        return order.getId();
    }

    @Override
    public String getMiaoShaResult(Integer userId, Integer miaoShaGoodsId) {
        HashMap map=new HashMap();
        map.put("user_id",userId);
        map.put("miaosha_goods_id",miaoShaGoodsId);
        Order order=orderMapper.findByUserIdAndMiaoShaGoodsId(map);
        if(order!=null){
            return order.getId();
        }else{
            //  TODO 查询商品是否秒杀完 从redis中判断是否商品秒杀完
            boolean isOver = (boolean) redisUtil.get(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX, miaoShaGoodsId + "");

            boolean over=true;
            if(over){
                return "-1";
            }else{
                return "0";
            }
        }
    }
}

package com.java1234.miaosha.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.mapper.OrderMapper;
import com.java1234.miaosha.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 用户Service实现类
 */
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;


    @Override
    public Order findById(String id) {
        return orderMapper.findById(id);
    }

    @Override
    public Order findByUserIdAndMiaoShaGoodsId(Map map) {
        return orderMapper.findByUserIdAndMiaoShaGoodsId(map);
    }
}

package com.java1234.miaosha.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.mapper.UserMapper;
import com.java1234.miaosha.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 用户Service实现类
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User findByUserName(String userName) {
        LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername,userName);
        return userMapper.selectOne(lambdaQueryWrapper);
    }
}

package com.java1234.miaosha.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.java1234.miaosha.entity.MiaoShaGoods;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;

import java.util.List;

/**
 * 秒杀商品service接口
 */
public interface IMiaoShaGoodsService extends IService<MiaoShaGoods> {

    /**
     * 查询所有秒杀商品
     * @return
     */
    public List<MiaoShaGoodsVo> listAll();

    /**
     * 根据id查询详情
     * @param id
     * @return
     */
    public MiaoShaGoodsVo findById(Integer id);
}

package com.java1234.miaosha.service;


import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;


/**
 * 秒杀商品service接口
 */
public interface IMiaoShaService {

    /**
     * 执行秒杀
     * @param user
     * @param miaoShaGoodsVo
     * @return
     */
    public String miaoSha(User user, MiaoShaGoodsVo miaoShaGoodsVo);

    /**
     * 获取秒杀结果
     * @param id
     * @param miaoShaGoodsId
     * @return
     */
    public String getMiaoShaResult(Integer id, Integer miaoShaGoodsId);
}

package com.java1234.miaosha.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.java1234.miaosha.entity.Order;

import java.util.Map;

/**
 * 用户Service接口
 */
public interface IOrderService extends IService<Order> {

    /**
     * 根据id查询订单
     * @param id
     * @return
     */
    public Order findById(String id);

    /**
     * 根据用户id和秒杀商品id查询订单
     * @param map
     * @return
     */
    public Order findByUserIdAndMiaoShaGoodsId(Map map);
}

package com.java1234.miaosha.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.java1234.miaosha.entity.User;

/**
 * 用户Service接口
 */
public interface IUserService extends IService<User> {

    /**
     * 根据用户名查询用户
     * @param userName
     * @return
     */
    public User findByUserName(String userName);
}

package com.java1234.miaosha.vo;


import com.java1234.miaosha.entity.MiaoShaGoods;
import lombok.Data;

/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-17 19:28
 */
@Data
public class MiaoShaGoodsVo extends MiaoShaGoods {

    private Integer miaoShaStatus=0; // 秒杀状态
    private Integer remainBeginSecond=0; // 剩余多少秒
    private Integer remainEndSecond=0; // 秒杀结束 剩余多少秒
}

package com.java1234.miaosha.vo;

import lombok.Data;

import java.io.Serializable;

/**
 * 用户vo
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-17 19:26
 */
@Data
public class UserVo implements Serializable {

    private String username; // 用户名

    private String password; // 密码

}

package com.java1234.miaosha;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.java1234.miaosha.mapper")
public class MiaoshaMiaoshaApplication {

    public static void main(String[] args) {
        SpringApplication.run(MiaoshaMiaoshaApplication.class, args);
    }

}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.GoodsMapper">

    <resultMap type="com.java1234.miaosha.entity.Goods" id="GoodsResult">
    </resultMap>

    <select id="findById" parameterType="Integer" resultMap="GoodsResult">
        select * from t_goods where id=#{id}
    </select>

</mapper>

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.MiaoShaGoodsMapper">

    <resultMap type="com.java1234.miaosha.vo.MiaoShaGoodsVo" id="MiaoShaGoodsResult">
        <association property="goods" column="goods_id" select="com.java1234.miaosha.mapper.GoodsMapper.findById"></association>
    </resultMap>

    <select id="listAll" resultMap="MiaoShaGoodsResult">
        select * from t_goods_miaosha
    </select>

    <select id="findById" parameterType="Integer" resultMap="MiaoShaGoodsResult">
        select * from t_goods_miaosha where id=#{id}
    </select>

   <update id="reduceStock" parameterType="Integer">
       update t_goods_miaosha set stock=stock-1 where id=#{id} and stock>0
   </update>
</mapper>


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.OrderMapper">

    <resultMap type="com.java1234.miaosha.entity.Order" id="OrderResult">
        <association property="miaoShaGoods" column="miaosha_goods_id" select="com.java1234.miaosha.mapper.MiaoShaGoodsMapper.findById" ></association>
        <association property="user" column="user_id" select="com.java1234.miaosha.mapper.UserMapper.findById" ></association>
    </resultMap>

    <select id="findById" parameterType="String"  resultMap="OrderResult">
        select * from t_order where id=#{id}
    </select>

    <insert id="add" parameterType="com.java1234.miaosha.entity.Order">
        insert into t_order values(#{id},#{user.id},#{miaoShaGoods.id},#{count},#{totalPrice},#{payMethod},#{status},now(),null)
    </insert>

    <select id="findByUserIdAndMiaoShaGoodsId" parameterType="Map" resultMap="OrderResult">
        select * from t_order where user_id=#{user_id} and miaosha_goods_id=#{miaosha_goods_id}
    </select>
</mapper>

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.UserMapper">

    <resultMap type="com.java1234.miaosha.entity.User" id="UserResult">
    </resultMap>


    <select id="findById" parameterType="Integer" resultMap="UserResult">
        select * from t_user where id=#{id}
    </select>


</mapper>

server:
  port: 8083
  servlet:
    context-path: /

spring:
  rabbitmq:
    host: 192.168.30.113
    port: 5672
    username: admin
    password: admin
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_miaosha3?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  redis: # redis配置
    host: 192.168.30.113 # IP
    port: 6379  # 端口
    password:  # 密码
    connect-timeout: 10s  # 连接超时时间
    lettuce: # lettuce redis客户端配置
      pool: # 连接池配置
        max-active: 8  # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-wait: 200s  # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-idle: 8 # 连接池中的最大空闲连接 默认 8
        min-idle: 0 # 连接池中的最小空闲连接 默认 0

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true  # 开启驼峰功能  userName  - >  user_name
    auto-mapping-behavior: full  # 自动mapping映射
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mybatis/mapper/*.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>miaoshasys33</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>miaosha-miaosha</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>miaosha-common</artifactId>
        </dependency>
    </dependencies>

</project>

package com.java1234.miaosha.controller;

import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 秒杀商品控制器
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private IOrderService orderService;




    /**
     * 根据id查询秒杀商品详情
     * @param id
     * @return
     */
    @RequestMapping("/detail")
    public R detail(String id){
        Order order = orderService.findById(id);

        Map<String,Object> map=new HashMap<>();
        map.put("data",order);
        return R.ok(map);
    }
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.Goods;

/**
 * 商品接口
 */
public interface GoodsMapper extends BaseMapper<Goods> {

    /**
     * 根据id查询商品
     * @param id
     * @return
     */
    public Goods findById(Integer id);
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.MiaoShaGoods;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;

import java.util.List;

/**
 * 秒杀商品Mapper接口
 */
public interface MiaoShaGoodsMapper extends BaseMapper<MiaoShaGoods> {

    /**
     * 查询所有秒杀商品
     * @return
     */
    public List<MiaoShaGoodsVo> listAll();

    /**
     * 根据id查询详情
     * @param id
     * @return
     */
    public MiaoShaGoodsVo findById(Integer id);

    /**
     * 商品库存减1操作
     * @param id
     * @return
     */
    public Integer reduceStock(Integer id);
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.Order;

import java.util.Map;

/**
 * 用户Mapper接口
 */
public interface OrderMapper extends BaseMapper<Order> {

    /**
     * 根据id查询订单
     * @param id
     * @return
     */
    public Order findById(String id);

    /**
     * 订单生成
     * @param order
     * @return
     */
    public Integer add(Order order);

    /**
     * 根据用户id和秒杀商品id查询订单
     * @param map
     * @return
     */
    public Order findByUserIdAndMiaoShaGoodsId(Map map);
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.User;

/**
 * 用户Mapper接口
 */
public interface UserMapper extends BaseMapper<User> {

    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    public User findById(Integer id);
}

package com.java1234.miaosha.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.mapper.OrderMapper;
import com.java1234.miaosha.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 用户Service实现类
 */
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;


    @Override
    public Order findById(String id) {
        return orderMapper.findById(id);
    }

    @Override
    public Order findByUserIdAndMiaoShaGoodsId(Map map) {
        return orderMapper.findByUserIdAndMiaoShaGoodsId(map);
    }
}

package com.java1234.miaosha.service;




import com.baomidou.mybatisplus.extension.service.IService;
import com.java1234.miaosha.entity.Order;

import java.util.Map;

/**
 * 用户Service接口
 */
public interface IOrderService extends IService<Order> {

    /**
     * 根据id查询订单
     * @param id
     * @return
     */
    public Order findById(String id);

    /**
     * 根据用户id和秒杀商品id查询订单
     * @param map
     * @return
     */
    public Order findByUserIdAndMiaoShaGoodsId(Map map);
}

package com.java1234.miaosha.vo;


import com.java1234.miaosha.entity.MiaoShaGoods;
import lombok.Data;

/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-17 19:28
 */
@Data
public class MiaoShaGoodsVo extends MiaoShaGoods {

    private Integer miaoShaStatus=0; // 秒杀状态
    private Integer remainBeginSecond=0; // 剩余多少秒
    private Integer remainEndSecond=0; // 秒杀结束 剩余多少秒
}

package com.java1234.miaosha.vo;

import lombok.Data;

import java.io.Serializable;

/**
 * 用户vo
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-17 19:26
 */
@Data
public class UserVo implements Serializable {

    private String username; // 用户名

    private String password; // 密码

}

package com.java1234.miaosha;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.java1234.miaosha.mapper")
public class MiaoshaOrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(MiaoshaOrderApplication.class, args);
    }

}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.GoodsMapper">

    <resultMap type="com.java1234.miaosha.entity.Goods" id="GoodsResult">
    </resultMap>

    <select id="findById" parameterType="Integer" resultMap="GoodsResult">
        select * from t_goods where id=#{id}
    </select>

</mapper>

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.MiaoShaGoodsMapper">

    <resultMap type="com.java1234.miaosha.vo.MiaoShaGoodsVo" id="MiaoShaGoodsResult">
        <association property="goods" column="goods_id" select="com.java1234.miaosha.mapper.GoodsMapper.findById"></association>
    </resultMap>

    <select id="listAll" resultMap="MiaoShaGoodsResult">
        select * from t_goods_miaosha
    </select>

    <select id="findById" parameterType="Integer" resultMap="MiaoShaGoodsResult">
        select * from t_goods_miaosha where id=#{id}
    </select>

   <update id="reduceStock" parameterType="Integer">
       update t_goods_miaosha set stock=stock-1 where id=#{id} and stock>0
   </update>
</mapper>


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.OrderMapper">

    <resultMap type="com.java1234.miaosha.entity.Order" id="OrderResult">
        <association property="miaoShaGoods" column="miaosha_goods_id" select="com.java1234.miaosha.mapper.MiaoShaGoodsMapper.findById" ></association>
        <association property="user" column="user_id" select="com.java1234.miaosha.mapper.UserMapper.findById" ></association>
    </resultMap>

    <select id="findById" parameterType="String"  resultMap="OrderResult">
        select * from t_order where id=#{id}
    </select>

    <insert id="add" parameterType="com.java1234.miaosha.entity.Order">
        insert into t_order values(#{id},#{user.id},#{miaoShaGoods.id},#{count},#{totalPrice},#{payMethod},#{status},now(),null)
    </insert>

    <select id="findByUserIdAndMiaoShaGoodsId" parameterType="Map" resultMap="OrderResult">
        select * from t_order where user_id=#{user_id} and miaosha_goods_id=#{miaosha_goods_id}
    </select>
</mapper>

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.UserMapper">

    <resultMap type="com.java1234.miaosha.entity.User" id="UserResult">
    </resultMap>


    <select id="findById" parameterType="Integer" resultMap="UserResult">
        select * from t_user where id=#{id}
    </select>


</mapper>

server:
  port: 8082
  servlet:
    context-path: /

spring:
  rabbitmq:
    host: 192.168.30.113
    port: 5672
    username: admin
    password: admin
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_miaosha3?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  redis: # redis配置
    host: 192.168.30.113 # IP
    port: 6379  # 端口
    password:  # 密码
    connect-timeout: 10s  # 连接超时时间
    lettuce: # lettuce redis客户端配置
      pool: # 连接池配置
        max-active: 8  # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-wait: 200s  # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-idle: 8 # 连接池中的最大空闲连接 默认 8
        min-idle: 0 # 连接池中的最小空闲连接 默认 0

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true  # 开启驼峰功能  userName  - >  user_name
    auto-mapping-behavior: full  # 自动mapping映射
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mybatis/mapper/*.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>miaoshasys33</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>miaosha-order</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>miaosha-common</artifactId>
        </dependency>
    </dependencies>


</project>

package com.java1234.miaosha.controller;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.service.IUserService;
import com.java1234.miaosha.util.Md5Util;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.util.StringUtil;
import com.java1234.miaosha.util.UUIDUtil;
import com.java1234.miaosha.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

@RestController
@RequestMapping("/")
public class LoginController    {

    @Autowired
    private IUserService userService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 用户登录
     * @return
     */
    @RequestMapping("/login")
    public R login(@RequestBody UserVo userVo){
        System.out.println("userVo: "+userVo.toString());
        if(userVo==null){
            return R.error();
        }
        if(StringUtil.isEmpty(userVo.getUsername())){
            return R.error("用户名不能为空!");
        }
        if(StringUtil.isEmpty(userVo.getPassword())){
            return R.error("密码不能为空!");
        }
        User resultUser = userService.findByUserName(userVo.getUsername());
        if(resultUser==null){
            return R.error("用户名不存在! ");
        }
        if(!resultUser.getPassword().trim().equals(Md5Util.backMd5(userVo.getPassword().trim()))){
            return R.error("用户名或者密码错误!");
        }
        String token= UUIDUtil.genUuid();   //生成token
        redisUtil.set(Constant.REDIS_TOKEN_PREFIX,token,resultUser,Constant.REDIS_TOKEN_EXPIRE);
        return R.ok(token);
    }

    /**
     * 注册2千用户
     * @return
     */
    @RequestMapping("/register")
    public R register()throws Exception{
        for(int i=0;i<2000;i++){
            User user=new User();
            user.setUsername("user"+i);
            user.setPassword("37cbc2f0be822f5ab96485ac11f3dc98");
            // 生成token
            String token=UUIDUtil.genUuid();

            // 插入数据库
            userService.save(user);

            redisUtil.set(Constant.REDIS_TOKEN_PREFIX,token,user,Constant.REDIS_TOKEN_EXPIRE);

            // 把用户名和token写入txt文件
            addUserToTxt(user.getUsername(),token);


        }
        return R.ok();
    }



    /**
     * 把用户名和token写入txt文件
     * @param username
     * @param token
     */
    private void addUserToTxt(String username, String token) throws Exception{
        String arr=username+","+token;
        FileWriter fw=new FileWriter(new File("D:/users.txt"),true);
        BufferedWriter bw=new BufferedWriter(fw);
        bw.write(arr+"\r\n");
        bw.flush();
        bw.close();
        fw.close();
    }
}

package com.java1234.miaosha.controller;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * token操作控制器
 */

@RestController
@RequestMapping("/")
public class TokenController {

    @Autowired
    private RedisUtil redisUtil;

    @GetMapping(value = "/refreshToken")
    public R refreshToken(HttpServletRequest request){
        String token = request.getHeader("token");
        System.out.println("a有效期:"+redisUtil.getExpire(Constant.REDIS_TOKEN_PREFIX+token));
        redisUtil.expire(Constant.REDIS_TOKEN_PREFIX,token,Constant.REDIS_TOKEN_EXPIRE);
        System.out.println("b有效期:"+redisUtil.getExpire(Constant.REDIS_TOKEN_PREFIX+token));
        return R.ok();
    }
}

package com.java1234.miaosha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.java1234.miaosha.entity.User;

/**
 * 用户Mapper接口
 */
public interface UserMapper extends BaseMapper<User> {

    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    public User findById(Integer id);
}

package com.java1234.miaosha.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.mapper.UserMapper;
import com.java1234.miaosha.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 用户Service实现类
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User findByUserName(String userName) {
        LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername,userName);
        return userMapper.selectOne(lambdaQueryWrapper);
    }
}

package com.java1234.miaosha.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.java1234.miaosha.entity.User;

/**
 * 用户Service接口
 */
public interface IUserService extends IService<User> {

    /**
     * 根据用户名查询用户
     * @param userName
     * @return
     */
    public User findByUserName(String userName);
}

package com.java1234.miaosha.vo;

import lombok.Data;

import java.io.Serializable;

/**
 * 用户vo
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-17 19:26
 */
@Data
public class UserVo implements Serializable {

    private String username; // 用户名

    private String password; // 密码

}

package com.java1234.miaosha;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.java1234.miaosha.mapper")
public class MiaoshaUserApplication {

    public static void main(String[] args) {
        SpringApplication.run(MiaoshaUserApplication.class, args);
    }

}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.miaosha.mapper.UserMapper">

    <resultMap type="com.java1234.miaosha.entity.User" id="UserResult">
    </resultMap>


    <select id="findById" parameterType="Integer" resultMap="UserResult">
        select * from t_user where id=#{id}
    </select>


</mapper>

server:
  port: 80
  servlet:
    context-path: /

spring:
  rabbitmq:
    host: 192.168.30.113
    port: 5672
    username: admin
    password: admin
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_miaosha3?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  redis: # redis配置
    host: 192.168.30.113 # IP
    port: 6379  # 端口
    password:  # 密码
    connect-timeout: 10s  # 连接超时时间
    lettuce: # lettuce redis客户端配置
      pool: # 连接池配置
        max-active: 8  # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-wait: 200s  # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-idle: 8 # 连接池中的最大空闲连接 默认 8
        min-idle: 0 # 连接池中的最小空闲连接 默认 0

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true  # 开启驼峰功能  userName  - >  user_name
    auto-mapping-behavior: full  # 自动mapping映射
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mybatis/mapper/*.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>miaoshasys33</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>miaoshauser</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>miaosha-common</artifactId>
        </dependency>
    </dependencies>

</project>

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.java1234</groupId>
    <artifactId>miaoshasys33</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>miaosha-common</module>
        <module>miaosha-user</module>
        <module>miaosha-goods</module>
        <module>miaosha-order</module>
        <module>miaosha-miaosha</module>
        <module>miaoshacommon</module>
        <module>miaoshauser</module>
        <module>miaosha-goods</module>
        <module>miaosha-order</module>
        <module>miaosha-miaosha</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <druid.version>1.1.10</druid.version>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <springboot.version>2.3.2.RELEASE</springboot.version>
        <springcloudalibaba.version>2.2.4.RELEASE</springcloudalibaba.version>
        <mybatis-plus.version>3.3.2</mybatis-plus.version>
        <fastjson.version>1.2.35</fastjson.version>
        <commons-lang3.version>3.6</commons-lang3.version>
        <miaosha-common.version>1.0-SNAPSHOT</miaosha-common.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${springcloudalibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!-- mybatis-plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>

            <dependency>
                <groupId>com.java1234</groupId>
                <artifactId>miaosha-common</artifactId>
                <version>${miaosha-common.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>



    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值