< ?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;
@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;
}
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 =
< /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 =
< /select>
< update id = "reduceStock" parameterType = "Integer" >
update t_goods_miaosha set stock = stock-1 where id =
< /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:
host: 192.168 .30.113
port: 6379
password:
connect-timeout: 10s
lettuce:
pool:
max-active: 8
max-wait: 200s
max-idle: 8
min-idle: 0
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
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 =
< /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 =
< /select>
< update id = "reduceStock" parameterType = "Integer" >
update t_goods_miaosha set stock = stock-1 where id =
< /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 =
< /select>
< insert id = "add" parameterType = "com.java1234.miaosha.entity.Order" >
insert into t_order values(
< /insert>
< select id = "findByUserIdAndMiaoShaGoodsId" parameterType = "Map" resultMap = "OrderResult" >
select * from t_order where user_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 =
< /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:
host: 192.168 .30.113
port: 6379
password:
connect-timeout: 10s
lettuce:
pool:
max-active: 8
max-wait: 200s
max-idle: 8
min-idle: 0
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
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 =
< /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 =
< /select>
< update id = "reduceStock" parameterType = "Integer" >
update t_goods_miaosha set stock = stock-1 where id =
< /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 =
< /select>
< insert id = "add" parameterType = "com.java1234.miaosha.entity.Order" >
insert into t_order values(
< /insert>
< select id = "findByUserIdAndMiaoShaGoodsId" parameterType = "Map" resultMap = "OrderResult" >
select * from t_order where user_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 =
< /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:
host: 192.168 .30.113
port: 6379
password:
connect-timeout: 10s
lettuce:
pool:
max-active: 8
max-wait: 200s
max-idle: 8
min-idle: 0
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
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 =
< /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:
host: 192.168 .30.113
port: 6379
password:
connect-timeout: 10s
lettuce:
pool:
max-active: 8
max-wait: 200s
max-idle: 8
min-idle: 0
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
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>