<?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.yf</groupId> <artifactId>learn06</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.1.RELEASE</version> </parent> <dependencies> <!-- MYSQL --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- Spring Boot JDBC --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.7</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.3.RELEASE</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.3.3.Final</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> <!-- Redis NoSQL 操作依赖 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> </dependencies> <!--maven打包时应用--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
#*****************jedis连接参数设置********************* #redis服务器ip redis.ip=127.0.0.1 #redis服务器端口号 redis.port=6379 #redis访问密码 redis.passWord=test123 #与服务器建立连接的超时时间 redis.timeout=3000 #************************jedis池参数设置******************* #jedis的最大活跃连接数 jedis.pool.maxActive=1000 #jedis最大空闲连接数 jedis.pool.maxIdle=50 #jedis池没有连接对象返回时,等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。 #如果超过等待时间,则直接抛出JedisConnectionException jedis.pool.maxWait=1500 #从池中获取连接的时候,是否进行有效检查 jedis.pool.testOnBorrow=true #归还连接的时候,是否进行有效检查 jedis.pool.testOnReturn=true
package com.yf.util; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import java.util.Properties; public class RedisPoolUtil { private static JedisPool jedisPool = null; private static String redisConfigFile = "redis.properties"; //把redis连接对象放到本地线程中 private static ThreadLocal<Jedis> local=new ThreadLocal<Jedis>(); //不允许通过new创建该类的实例 private RedisPoolUtil() { } /** * 初始化Redis连接池 */ public static void initialPool() { try { Properties props = new Properties(); //加载连接池配置文件 props.load(RedisPoolUtil.class.getClassLoader().getResourceAsStream(redisConfigFile)); // 创建jedis池配置实例 JedisPoolConfig config = new JedisPoolConfig(); // 设置池配置项值 config.setMaxTotal(Integer.valueOf(props.getProperty("jedis.pool.maxActive"))); config.setMaxIdle(Integer.valueOf(props.getProperty("jedis.pool.maxIdle"))); config.setMaxWaitMillis(Long.valueOf(props.getProperty("jedis.pool.maxWait"))); config.setTestOnBorrow(Boolean.valueOf(props.getProperty("jedis.pool.testOnBorrow"))); config.setTestOnReturn(Boolean.valueOf(props.getProperty("jedis.pool.testOnReturn"))); // 根据配置实例化jedis池 jedisPool = new JedisPool(config, props.getProperty("redis.ip"), Integer.valueOf(props.getProperty("redis.port")), Integer.valueOf(props.getProperty("redis.timeout")), props.getProperty("redis.passWord")); System.out.println("线程池被成功初始化"); } catch (Exception e) { e.printStackTrace(); } } /** * 获得连接 * @return Jedis */ public static Jedis getConn() { //Redis对象 Jedis jedis =local.get(); if(jedis==null){ if (jedisPool == null) { initialPool(); } jedis = jedisPool.getResource(); local.set(jedis); } return jedis; } //新版本用close归还连接 public static void closeConn(){ //从本地线程中获取 Jedis jedis =local.get(); if(jedis!=null){ jedis.close(); } local.set(null); } //关闭池 public static void closePool(){ if(jedisPool!=null){ jedisPool.close(); } } }
package com.yf.service; import com.yf.dao.GoodUserDao; import com.yf.dao.GoodsDao; import com.yf.pojo.GoodUser; import com.yf.util.RedisPoolUtil; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import java.util.List; @Service public class GoodUserService { @Autowired private GoodUserDao goodUserDao; @Autowired private GoodsDao goodsDao; public static Logger logger = Logger.getLogger(GoodUserService.class); public List<GoodUser> getGoods() { List<GoodUser> goods = goodUserDao.getAllGoodUser(); return goods; } //保存 public void saveGoods(GoodUser goodUser){ goodUserDao.saveGoods(goodUser); } //1 判断条件 public boolean isKill(String userName){ Jedis jedis=RedisPoolUtil.getConn(); //限制用户操作频率 10秒内 String value=jedis.set(userName,"","NX","EX",10); if(!"OK".equals(value)){ logger.warn("此用户重复请求"); return false; } return true; } //秒杀1.减少数量 2.插入用户记录 public void killGood(String userName){ if(isKill(userName)){ GoodUser goodUser=new GoodUser(); goodUser.setName(userName); goodUser.setGoodsName("phone"); int i=goodsDao.minusNum("phone"); if(i>0){ goodUserDao.saveGoods(goodUser); logger.info(userName+" 秒杀成功"); } } } }
package com.yf.service; import com.yf.pojo.GoodUser; import com.yf.testMain; import com.yf.util.RedisPoolUtil; import org.apache.log4j.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; import java.util.concurrent.CountDownLatch; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = testMain.class) public class GoodsServiceTest { @Autowired private GoodsService goodsService; @Autowired private GoodUserService goodUserService; public static Logger logger = Logger.getLogger(GoodsServiceTest.class); private static final int threadNum=1000; private CountDownLatch cdl=new CountDownLatch(threadNum); @Test public void testGet() { List<GoodUser> goods=goodUserService.getGoods(); for (GoodUser gu:goods){ System.out.println(gu.getGoodsName()); } } @Test public void testSave() { GoodUser goodUser=new GoodUser(); goodUser.setName("yf"); goodUser.setGoodsName("bike"); goodUserService.saveGoods(goodUser); } @Test public void testMinus() { goodsService.minusNum("bike"); } @Test public void testKill() { try { RedisPoolUtil.initialPool(); Thread[] threads=new Thread[threadNum]; for(int i=0;i<threadNum;i++){ logger.info("循环"+i+"次"); Thread thread=new Thread(new userRequest("yf")); threads[i]=thread; thread.start(); cdl.countDown(); } for(Thread thread:threads){ thread.join(); } }catch (Exception e){ e.printStackTrace(); }finally { RedisPoolUtil.closePool(); } } class userRequest implements Runnable{ String userName; public userRequest(String userName) { this.userName = userName; } @Override public void run() { try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } goodUserService.killGood(userName); } } }
2.防止用户用脚本重复提交
String value=jedis.set(userName,"","NX","EX",10); if(!"OK".equals(value)){ logger.warn("此用户重复请求"); return false; }