发表于: 2018-03-18 23:57:42
2 665
今日完成:
1. redis实现抢红包
红包类:参考微信随机红包
@Component
public class ReadPackage {
private double remainMoney = 1000000000;
private int remainSize = 1000;
public double getRemainMoney() {
return this.remainMoney;
}
public int getRemainSize() {
return this.remainSize;
}
public boolean isEmpty() {
return 0 == remainSize;
}
public double getRandomMoney() {
if (1 == this.remainSize) {
this.remainSize--;
return (double) Math.floor(this.remainMoney * 100) / 100;
}
Random random = new Random();
double min = 0.01;
double max = this.remainMoney / this.remainSize * 2;
double money = random.nextDouble() * max;
money = money <= min ? min : money;
money = (double) Math.floor(money * 100) / 100;
this.remainSize--;
this.remainMoney -= money;
return money;
}
将生成的红包缓存到redis中,并设置抢红包方法
@Component
public class RedisReadPackage {
@Autowired
private ReadPackage readPackage;
@Autowired
private RedisTemplate redisTemplate;
public static String UNUSEDLIST = "unusedReadPackage";
public static String USEDLIST = "usedReadPackage";
public static String CUSTOMERLIST = "customer";
public void init(){
redisTemplate.delete(UNUSEDLIST);
redisTemplate.delete(USEDLIST);
redisTemplate.delete(CUSTOMERLIST);
}
public void setUnusedReadPackageList(){
while (!readPackage.isEmpty()){
redisTemplate.opsForList().leftPush(UNUSEDLIST, readPackage.getRandomMoney());
}
}
public String grabReadPackage(int id){
if(0 != redisTemplate.opsForList().size(UNUSEDLIST ) && !redisTemplate.opsForSet().isMember(CUSTOMERLIST, id)){
double money = (double)redisTemplate.opsForList().rightPop(UNUSEDLIST);
redisTemplate.opsForSet().add(CUSTOMERLIST, id);
redisTemplate.opsForList().leftPush(USEDLIST, id + "_" + money);
// System.out.println(redisTemplate.opsForSet().pop(CUSTOMERLIST));
// System.out.println(redisTemplate.opsForList().range(USEDLIST, 0 ,-1));
return "恭喜" + id + "用户抽到" + money + "元红包!";
}
return "错亿";
}
}
controller中初始化红包,重定向到抢红包页面
@RequestMapping(value = "/grabReadPackageIndex")
public String grabReadPackageIndex(){
redisReadPackage.init();
redisReadPackage.setUnusedReadPackageList();
return "redirect:/itschool/grabReadPackage";
}
@RequestMapping(value = "/grabReadPackage", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
public @ResponseBody String grabReadPackage(){
JSONObject object = new JSONObject();
Random random = new Random();
String msg = redisReadPackage.grabReadPackage(random.nextInt(1000));
object.put("meg", msg);
return object.toString();
}
结果页面:
本地压测情况:
2. xml读取多个配置文件方法
方法一(测试成功):
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- 这里支持多种寻址方式:classpath和file -->
<value>classpath:datasource/mysql.properties</value>
<value>classpath:cache/redis.properties</value>
<!-- 推荐使用file的方式引入,这样可以将配置和代码分离 -->
<!--<value>file:/opt/demo/config/demo-remote.properties</value>-->
</list>
</property>
</bean>
方法二:(测试成功)
方法一的变换,使用List:
<!-- 将多个配置文件位置放到列表中 -->
<bean id="propertyResources" class="java.util.ArrayList">
<constructor-arg>
<list>
<!-- 这里支持多种寻址方式:classpath和file -->
<value>classpath:datasource/mysql.properties</value>
<value>classpath:cache/redis.properties</value>
<!-- 推荐使用file的方式引入,这样可以将配置和代码分离 -->
<!--<value>file:/opt/demo/config/demo-remote.properties</value>-->
</list>
</constructor-arg>
</bean>
<!-- 将配置文件读取到容器中,交给Spring管理 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" ref="propertyResources" />
</bean>
方法三:(测试失败)
ignore-resource-not-found="是否忽略找不到的属性文件"
ignore-unresolvable="是否忽略解析不到的属性,如果不忽略,找不到将抛出异常"
<!--或者这样 引入配置文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath:datasource/mysql.properties, classpath:cache/redis.properties"/>
ps:配置文件依次加载,如果后一个文件中有和前面某一个文件中属性名是相同的,最终取的值是后加载的值
ps:Spring容器是采用反射扫描的发现机制,通过标签的命名空间实例化实例,当Spring探测到容器中有一个org.springframework.beans.factory.config.PropertyPlaceholderCVonfigurer的Bean就会停止对剩余PropertyPlaceholderConfigurer的扫描,即只能存在一个实例
报错:
方法四:(测试成功)
分散到不同xml分别加载,每个xml配置文件如下(也可以放置在同一个xml中)
<!-- 将redis属性配置文件位置放到列表中 -->
<bean id="redisResources" class="java.util.ArrayList">
<constructor-arg>
<list>
<value>classpath:cache/redis.properties</value>
</list>
</constructor-arg>
</bean>
<!-- 用Spring加载和管理redis属性配置文件 -->
<bean id="redisPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="2" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations" ref="redisResources" />
</bean>
注意:其中order属性代表其加载顺序,而ignoreUnresolvablePlaceholders为是否忽略不可解析的 Placeholder,如配置了多个PropertyPlaceholderConfigurer,则需设置为true。这里一定需要按照这种方式设置这两个参数。
ps:另外一种方法使用注解引用配置@Value
方法五:(测试失败)
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<property name="location" value="classpath:datasource/mysql.properties, classpath:cache/redis.properties"/>
</bean>
报错:
明日计划:
1. redis分布式
2. redis实现抢红包(锁,同步异步)
3. 整理
遇到的问题:
1. 在做单元测试中,使用@ Autowired会显示空指针异常
2. 抢红包是否要设计一个存放抢到红包的用户与红包金额的类,然后使用这个类存放抢红包结果,在添加到redis的List缓存中?
收获:
1. 简单使用redis实现抢红包
2. 多个properties文件引用方法
评论