Authored by Lixiaodi

Merge branch 'wechart_free' of http://git.yoho.cn/yoho30/yohobuy-activity into wechart_free

# Conflicts:
#	service/src/main/java/com/yoho/activity/service/impl/LotteryServiceImpl.java
package com.yoho.activity.common.redis;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yoho.core.config.ConfigReader;
import com.yoho.core.redis.YHListOperations;
import com.yoho.core.redis.YHRedisTemplate;
import com.yoho.core.redis.YHValueOperations;
import com.yoho.core.redis.YHZSetOperations;
/**
* @author xieyong
*
*/
public abstract class AbstractGracefulRedisTemplate{
// 缓存统计信息打印,本身logback是异步打印,不需要自己起线程异步去打印了
private final Logger logger = LoggerFactory.getLogger("cacheStatistic");
private final Logger redisTimeOutLogger = LoggerFactory.getLogger("redisTimeOut");
private final static Logger warnLogger = LoggerFactory.getLogger(GracefulRedisTemplate.class);
private final static Integer TIMEOUT_THRESHOLD = 50;
private static final Charset CHARSET_UTF_8 = Charset.forName("UTF-8");
@Resource( name = "core-config-reader" )
private ConfigReader configReader;
abstract YHRedisTemplate<String, String> getRedisTemplate();
abstract YHValueOperations<String, String> getValueOperations();
abstract YHListOperations<String, String> getListOperations();
abstract YHZSetOperations<String, String> getZsetOperations();
abstract boolean isAync();
public boolean isCache(){
return configReader.getBoolean("product.degrade.isCache.enable", false);
}
/**
* @param key
* @param value
* @param timeout 默认单位秒
*/
public void setEx(String key, Object value, long timeout) {
if (isCache()) {
return;
}
String redisValue = null;
if (value instanceof String) {
redisValue = (String) value;
} else {
redisValue = JSON.toJSONString(value);
}
try {
//原子命令,如果超过7天,因为twproxy不支持long time,单独用命令实现
if(timeout>604800){
getValueOperations().set(key, redisValue);
this.expire(key, timeout);
}else{
getValueOperations().set(key, redisValue, timeout, TimeUnit.SECONDS);
}
} catch (Exception e) {
warnLogger.warn("add cache failed!!! cachekey is:{}", key, e);
}
}
/**
*
* @param map
* @param timeout
*/
public void mset(Map<String, ? extends Object> map, long timeout) {
if (isCache()) {
return;
}
if (MapUtils.isEmpty(map)) {
return;
}
getRedisTemplate().mset(map, timeout);
}
/**
* @param key
*/
public boolean hasKey(String key) {
if (isCache()) {
return false;
}
try {
// 此处是读的操作
boolean hasKey = getRedisTemplate().hasKey(key);
return hasKey;
} catch (Exception e) {
warnLogger.warn("hasKey cache failed!!! key is: {}", key, e);
}
return false;
}
/**
* setex命令不支持long expire 需要将这两个命令拆开,拆开之后命令就不是原子性的了,可能会出现set 命令成功 expire命令失败
* 这样就会出现key永久有效的情况
*
* @param key
*/
public void expire(String key, long timeout) {
if (isCache()) {
return;
}
try {
getRedisTemplate().longExpire(key, timeout, TimeUnit.SECONDS);
} catch (Exception e) {
warnLogger.error("expire cache failed!!! key is: {}", key, e);
// 如果设置有效期失败,将之前塞进去的key删除
this.deleteQuietly(key);
}
}
public Long getExpire(String key) {
if (isCache()) { return null; }
try {
return getRedisTemplate().getExpire(key);
} catch (Exception e) {
warnLogger.error("Get expire failed!!! key is: {}", key, e);
}
return null;
}
private void deleteQuietly(String key) {
try {
getRedisTemplate().delete(key);
} catch (Exception e) {
warnLogger.error("delete cache failed!!! key is: {}", key, e);
}
}
/**
* @param key
* @param clazz
* @return 传入的都返回,有数据返回数据,没有数据返回 NULL
*/
public <T> Map<String, T> mget(List<String> keys, Class<T> clazz) {
if (isCache()) {
HashMap<String, T> hashMap = new HashMap<String, T>(keys.size());
for (String key : keys) {
hashMap.put(key, null);
}
return hashMap;
}
try {
List<String> multiGet = getValueOperations().multiGet(keys);
int size = multiGet.size();
Map<String, T> result = new HashMap<String, T>(size);
String curItem;
for (int i = 0; i < size; i++) {
curItem = multiGet.get(i);
if (null == curItem) {
result.put(keys.get(i), null);
} else {
result.put(keys.get(i), getValue(curItem, clazz));
}
}
return result;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! keys is: {}", keys, e);
HashMap<String, T> hashMap = new HashMap<String, T>(keys.size());
for (String key : keys) {
hashMap.put(key, null);
}
return hashMap;
}
}
/**
* 获取存在的 map 列表(不含 NULL)
*/
public <T> Map<String, T> multiGetMapNotNULL(List<String> keys, Class<T> clazz) {
if (CollectionUtils.isEmpty(keys)) return null;
Map<String, T> result = mget(keys, clazz);
return Maps.filterEntries(result, entity -> entity.getValue() != null);
}
/**
*
* @param keys
* 批量获取int类型的value
* @return
*/
public Map<String, Integer> mgetIntValue(List<String> keys) {
if (isCache()) {
HashMap<String, Integer> hashMap = new HashMap<String, Integer>(keys.size());
for (String key : keys) {
hashMap.put(key, null);
}
return hashMap;
}
try {
List<String> multiGet = getValueOperations().multiGet(keys);
int size = multiGet.size();
Map<String, Integer> result = new HashMap<String, Integer>(size);
String curItem;
for (int i = 0; i < size; i++) {
curItem = multiGet.get(i);
if (null == curItem) {
result.put(keys.get(i), null);
} else {
result.put(keys.get(i), Integer.valueOf(curItem));
}
}
return result;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! keys is: {}", keys, e);
HashMap<String, Integer> hashMap = new HashMap<String, Integer>(keys.size());
for (String key : keys) {
hashMap.put(key, null);
}
return hashMap;
}
}
/**
* @param keys
* @param clazz
* @return
*/
public <T> Map<String, List<T>> mgetList(final List<String> keys, final Class<T> clazz) {
if (isCache()) {
HashMap<String, List<T>> hashMap = new HashMap<String, List<T>>(keys.size());
for (String key : keys) {
hashMap.put(key, null);
}
return hashMap;
}
try {
List<String> multiGet = getValueOperations().multiGet(keys);
int size = multiGet.size();
Map<String, List<T>> result = new HashMap<String, List<T>>(size);
String curItem;
for (int i = 0; i < size; i++) {
curItem = multiGet.get(i);
if (null == curItem) {
result.put(keys.get(i), null);
} else {
result.put(keys.get(i), JSON.parseArray(curItem, clazz));
}
}
return result;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! keys is: {}", keys, e);
HashMap<String, List<T>> hashMap = new HashMap<String, List<T>>(keys.size());
for (String key : keys) {
hashMap.put(key, null);
}
return hashMap;
}
}
/**
* @param key
* @param value
*/
public void set(String key, Object value) {
if (isCache()) {
return;
}
String redisValue = null;
if (value instanceof String) {
redisValue = (String) value;
} else {
redisValue = JSON.toJSONString(value);
}
try {
getValueOperations().set(key, redisValue);
} catch (Exception e) {
warnLogger.warn("add cache failed!!! cachekey is:{}", key, e);
}
}
/**
* 有序set的单个元素插入
*
* @param key
* @param value
*/
public void setSortedSet(String key, Object value, double score) {
if (isCache()) {
return;
}
String redisValue = null;
if (value instanceof String) {
redisValue = (String) value;
} else {
redisValue = JSON.toJSONString(value);
}
try {
getZsetOperations().add(key, redisValue, score);
} catch (Exception e) {
warnLogger.warn("add sortedSet cache failed!!! cachekey is " + key + "value is " + value, e);
}
}
/**
* @param key
* @param value
*/
public void setIfAbsent(String key, Object value) {
if (isCache()) {
return;
}
String redisValue = null;
if (value instanceof String) {
redisValue = (String) value;
} else {
redisValue = JSON.toJSONString(value);
}
try {
getValueOperations().setIfAbsent(key, redisValue);
} catch (Exception e) {
warnLogger.warn("add cache failed!!! cachekey is:{}", key, e);
}
}
/**
* @param key
* @param clazz
* @return
*/
public <T> List<T> getList(String key, Class<T> clazz) {
if (isCache()) {
return null;
}
List<T> t = null;
try {
String value = getValueOperations().get(key);
if (StringUtils.isBlank(value)) {
logger.info("cache miss key is:{}", key);
return null;
}
t = JSON.parseArray(value, clazz);
logger.info("cache hit key is:{}", key);
return t;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
return null;
}
}
/**
* redis list 获取值列表, 全部记录
*
* @param key
* @param length
* @param startIndex
* @param clazz
* @return
*/
public List<String> getValueList(String key, int startIndex, int endIndex) {
if (isCache()) {
return Lists.newArrayList();
}
try {
List<String> valueList = getListOperations().range(key, startIndex, endIndex);
if (CollectionUtils.isEmpty(valueList)) {
logger.info("cache miss key is:{}", key);
return Lists.newArrayList();
}
logger.info("cache hit key is:{}", key);
return valueList;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
return Lists.newArrayList();
}
}
/**
* redis list 设置, 左塞
*
* @param key
* @param clazz
* @return
*/
public void leftSetValueList(String key, String value) {
if (isCache()) {
return;
}
try {
getListOperations().leftPush(key, value);
} catch (Exception e) {
warnLogger.warn("set cache failed!!! key is: {},value is:{}", key, value, e);
}
}
/**
* redis list 设置, 左塞 (批量接口)
*
* @param key
* @param clazz
* @return
*/
public void batchLeftSetValueList(String key, List<String> values) {
if (isCache()) {
return;
}
if (CollectionUtils.isEmpty(values)) {
return;
}
try {
getListOperations().leftPushAll(key, values);
} catch (Exception e) {
warnLogger.warn("batchLeftSetValueList cache failed!!! key is:{} ,values is:{}", key, values, e);
}
}
/**
*
* @param key
* @param value
* object
*/
public void leftSetObjectValueList(String key, Object value) {
if (isCache()) {
return;
}
try {
getListOperations().leftPush(key, JSON.toJSONString(value));
} catch (Exception e) {
warnLogger.warn("set cache failed!!! key is:{},value is:{} ", key, value, e);
}
}
/**
*
* @param key
* @param values
*/
public void batchLeftSetObjectValueList(String key, List<? extends Object> values) {
if (isCache()) {
return;
}
if (CollectionUtils.isEmpty(values)) {
return;
}
List<String> jsonValues = Lists.newArrayList();
for (Object object : values) {
jsonValues.add(JSON.toJSONString(object));
}
try {
getListOperations().leftPushAll(key, jsonValues);
} catch (Exception e) {
warnLogger.warn("set cache failed!!! key is:{} ", key, e);
}
}
/**
*
* @param key
* @param values
*/
public void batchRightSetObjectValueList(String key, List<? extends Object> values) {
if (isCache()) {
return;
}
if (CollectionUtils.isEmpty(values)) {
return;
}
List<String> jsonValues = Lists.newArrayList();
for (Object object : values) {
jsonValues.add(JSON.toJSONString(object));
}
try {
getListOperations().rightPushAll(key, jsonValues);
} catch (Exception e) {
warnLogger.warn("set cache failed!!! key is:{} ", key, e);
}
}
/**
* redis list 设置, 右塞 (批量接口)
*
* @param key
* @param clazz
* @return
*/
public void batchRightSetValueList(String key, List<String> values) {
if (isCache()) {
return;
}
if (CollectionUtils.isEmpty(values)) {
return;
}
try {
getListOperations().rightPushAll(key, values);
} catch (Exception e) {
warnLogger.warn("batchLeftSetValueList cache failed!!! key is:{} ", key, e);
}
}
/**
* @param key
* @param startIndex
* @param length
* @param clazz
* @return
*/
public <T> List<T> getValueObjectList(String key, int startIndex, int length, Class<T> clazz) {
if (isCache()) {
return Lists.newArrayList();
}
try {
List<String> valueList = getListOperations().range(key, startIndex, length);
if (CollectionUtils.isEmpty(valueList)) {
logger.info("cache miss key is:{}", key);
return Lists.newArrayList();
}
logger.info("cache hit key is:{}", key);
List<T> list = Lists.newArrayList();
for (String value : valueList) {
T t = JSON.parseObject(value, clazz);
if (null != t) {
list.add(t);
}
}
return list;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
return Lists.newArrayList();
}
}
/**
* @param key
* @return
*/
public String getString(String key) {
if (isCache()) {
return null;
}
String value = null;
try {
value = getValueOperations().get(key);
if (StringUtils.isBlank(value)) {
logger.info("cache miss key is:{}", key);
} else {
logger.info("cache hit key is:{}", key);
}
return value;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
return null;
}
}
public Long incr(String key, long delta) {
if (isCache()) {
return null;
}
try {
return getValueOperations().increment(key, delta);
} catch (Exception e) {
warnLogger.warn("incr failed!!! key is:{}", key, e);
return null;
}
}
/**
* @param key
* @param clazz
* @return
*/
public <T> T get(String key, Class<T> clazz) {
if (isCache()) {
return null;
}
T t = null;
try {
String value = getValueOperations().get(key);
if (StringUtils.isBlank(value)) {
logger.info("cache miss key is:{}", key);
return null;
}
t = getValue(value, clazz);
logger.info("cache hit key is:{}", key);
return t;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! key is:{}", key, e);
return null;
}
}
/**
* @param keys
*/
public void delete(Collection<String> keys) {
if (isCache() || CollectionUtils.isEmpty(keys)) {
return;
}
try {
getRedisTemplate().delete(keys);
} catch (Exception e) {
warnLogger.warn("delete from cache failed!!! key is:{}", keys, e);
}
}
public void evictFromList(String key, String value, long count) {
if (isCache()) {
return;
}
try {
getListOperations().remove(key, count, value);
} catch (Exception e) {
warnLogger.warn("remove cache failed!!! key is: " + key + "; value = " + value, e);
}
}
/**
* 查询某键值对应list列表的长度
*
* @param level
* @param name
* @param key
* @return
*/
public long getValueListCount(String key) {
if (isCache()) {
return 0;
}
try {
Long size = getListOperations().size(key);
if (null == size) {
return 0;
} else {
return size;
}
} catch (Exception e) {
warnLogger.warn("getValueListCount cache failed!!! key is:{} ", key, e);
return 0;
}
}
/**
* 批量插入sortSet元素,只支持同一键值
*
* @param valueAndScoreMap
* 键值为存储的值,map值为当前值的score(用于排序) 默认是升序
*/
public void msetSortSet(String key, Map<Object, Double> valueAndScoreMap) {
if (isCache() || MapUtils.isEmpty(valueAndScoreMap)) {
return;
}
Set<TypedTuple<String>> typedTuples = new HashSet<TypedTuple<String>>(valueAndScoreMap.size());
Object curValue;
for (Entry<Object, Double> entry : valueAndScoreMap.entrySet()) {
final String curValueStr;
curValue = entry.getKey();
if (curValue instanceof String) {
curValueStr = (String) curValue;
} else {
curValueStr = JSON.toJSONString(curValue);
}
typedTuples.add(new TypedTuple<String>() {
@Override
public int compareTo(TypedTuple<String> o) {
return this.getScore() >= o.getScore() ? 1 : -1;
}
@Override
public String getValue() {
return curValueStr;
}
@Override
public Double getScore() {
return entry.getValue();
}
});
}
try {
getZsetOperations().add(key, typedTuples);
} catch (Exception e) {
warnLogger.warn("add zSetOperations cache failed!!! map key is" + key + "; valueAndScoreMap is " + valueAndScoreMap, e);
}
}
/**
* 查询sortedSet的长度
*/
public Long countSortSet(String key) {
if (isCache()) {
return null;
}
try {
return getZsetOperations().size(key);
} catch (Exception e) {
warnLogger.warn("count zSetOperations cache failed!!! key is" + key, e);
}
return null;
}
/**
* 查询sortedSet的长度
*/
public Long removeSortSet(String key, Object... values) {
if (isCache() || null == values || 0 == values.length) {
return null;
}
try {
return getZsetOperations().remove(key, values);
} catch (Exception e) {
warnLogger.warn("remove zSetOperations cache failed!!! key is" + key + "; values is " + values, e);
}
return null;
}
/**
* 分页查询sortedSet 查询失败则返回空的set
*/
public Set<String> rangeSortSet(String key, long start, long end) {
if (isCache()) {
return null;
}
try {
return getZsetOperations().reverseRange(key, start, end);
} catch (Exception e) {
warnLogger.warn("range zSetOperations cache failed!!! key is" + key + "; start is " + start + "; end is " + end, e);
}
return new HashSet<String>(0);
}
/**
* 查询sortSet中有无当前的值 是否在set已有
*/
public boolean existSortSet(String key, Object value) {
if (isCache()) {
return false;
}
try {
return null != getZsetOperations().score(key, value);
} catch (Exception e) {
warnLogger.warn("score zSetOperations cache failed!!! key is" + key + "; value is " + value, e);
}
return false;
}
@SuppressWarnings("unchecked")
private <T> T getValue(String value, Class<T> clazz) {
T t = null;
if (clazz.equals(String.class)) {
t = (T) value;
} else if (clazz.equals(Integer.class)) {
t = (T) Integer.valueOf(value);
} else {
try{
t = JSON.parseObject(value, clazz);
}catch (Exception e) {
warnLogger.warn("get value cache failed!!! value is: "+ value,e);
}
}
return t;
}
public <T> Map<String, T> pipelineGet(List<String> keys, Class<T> clazz){
if (isCache()||CollectionUtils.isEmpty(keys)) {
return null;
}
long beginTime = System.currentTimeMillis();
Map<String, T> result = new HashMap<String, T>(keys.size());
try {
List<Object> values=getRedisTemplate().executePipelined(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
connection.openPipeline();
for (String key : keys) {
connection.get(key.getBytes(CHARSET_UTF_8));
}
// 无需返回是否缓存成功
return null;
}
});
int index=0;
for (Object redisBack : values) {
if (null != redisBack) {
result.put(keys.get(index),getValue((String)redisBack, clazz));
}else{
result.put(keys.get(index),null);
}
index++;
}
return result;
} catch (Exception e) {
warnLogger.warn("get from cache failed!!! keys is: {}", keys, e);
HashMap<String, T> hashMap = new HashMap<String, T>(keys.size());
for (String key : keys) {
hashMap.put(key, null);
}
return hashMap;
}finally {
long endTime = System.currentTimeMillis();
long costTime = endTime - beginTime;
if (costTime > TIMEOUT_THRESHOLD) {
redisTimeOutLogger.warn("get from cache timeout!!! keys size is:{} cost time:{}", keys.size(), costTime);
}
}
}
}
... ...
package com.yoho.activity.common.redis;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.yoho.core.redis.YHListOperations;
import com.yoho.core.redis.YHRedisTemplate;
import com.yoho.core.redis.YHValueOperations;
import com.yoho.core.redis.YHZSetOperations;
/**
* @author xieyong
* 双中心同步redis
*
*/
@Service(value="GracefulRedisTemplate")
public class GracefulRedisTemplate extends AbstractGracefulRedisTemplate{
@Resource(name = "yhRedisTemplate")
private YHRedisTemplate<String, String> redis;
@Resource(name="yhValueOperations")
private YHValueOperations<String, String> valueOperations;
@Resource(name="yhListOperations")
private YHListOperations<String, String> listOperations;
@Resource(name="yhZSetOperations")
private YHZSetOperations<String, String> zSetOperations;
@Override
YHRedisTemplate<String, String> getRedisTemplate() {
return redis;
}
@Override
YHValueOperations<String, String> getValueOperations() {
return valueOperations;
}
@Override
YHListOperations<String, String> getListOperations() {
return listOperations;
}
@Override
YHZSetOperations<String, String> getZsetOperations() {
return zSetOperations;
}
@Override
boolean isAync() {
return true;
}
}
... ...
package com.yoho.activity.common.redis;
public final class KeyBuilder {
public static final String WEIXIN_LOTTERY_USER_ORDER_LIST = "yh:activity:weixin:lottery:user:orders:";
}
... ...
package com.yoho.activity.common.vo;
import java.math.BigDecimal;
import java.util.List;
public class LotteryOrderVO {
private Integer id;
private String order_code;
private Byte order_type;
private Byte refund_status;
private Integer uid;
private String parent_order_code;
private Byte payment;
private BigDecimal amount;
private String payment_status;
private String user_confirm_paid;
private String use_limit_code;
private Byte payment_type;
private String counter_flag = "Y";
private Integer status;
private List<OrdersGoodsVO> ordersGoodsList;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOrder_code() {
return order_code;
}
public void setOrder_code(String order_code) {
this.order_code = order_code;
}
public Byte getOrder_type() {
return order_type;
}
public void setOrder_type(Byte order_type) {
this.order_type = order_type;
}
public Byte getRefund_status() {
return refund_status;
}
public void setRefund_status(Byte refund_status) {
this.refund_status = refund_status;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getParent_order_code() {
return parent_order_code;
}
public void setParent_order_code(String parent_order_code) {
this.parent_order_code = parent_order_code;
}
public Byte getPayment() {
return payment;
}
public void setPayment(Byte payment) {
this.payment = payment;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getPayment_status() {
return payment_status;
}
public void setPayment_status(String payment_status) {
this.payment_status = payment_status;
}
public String getUser_confirm_paid() {
return user_confirm_paid;
}
public void setUser_confirm_paid(String user_confirm_paid) {
this.user_confirm_paid = user_confirm_paid;
}
public String getUse_limit_code() {
return use_limit_code;
}
public void setUse_limit_code(String use_limit_code) {
this.use_limit_code = use_limit_code;
}
public Byte getPayment_type() {
return payment_type;
}
public void setPayment_type(Byte payment_type) {
this.payment_type = payment_type;
}
public String getCounter_flag() {
return counter_flag;
}
public void setCounter_flag(String counter_flag) {
this.counter_flag = counter_flag;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public List<OrdersGoodsVO> getOrdersGoodsList() {
return ordersGoodsList;
}
public void setOrdersGoodsList(List<OrdersGoodsVO> ordersGoodsList) {
this.ordersGoodsList = ordersGoodsList;
}
}
... ...
package com.yoho.activity.common.vo;
import java.math.BigDecimal;
public class OrdersGoodsVO {
private Integer product_id;
private Integer product_skn;
private String product_name;
private String cn_alphabet;
private Integer good_id;
private BigDecimal goods_price;
private BigDecimal goods_amount;
private String factory_color_name;
private String goods_image;
private Byte goods_type;
private String expect_arrival_time;
private Integer buy_num;
private String size_name;
private String color_name;
public Integer getProduct_id() {
return product_id;
}
public void setProduct_id(Integer product_id) {
this.product_id = product_id;
}
public Integer getProduct_skn() {
return product_skn;
}
public void setProduct_skn(Integer product_skn) {
this.product_skn = product_skn;
}
public String getProduct_name() {
return product_name;
}
public void setProduct_name(String product_name) {
this.product_name = product_name;
}
public String getCn_alphabet() {
return cn_alphabet;
}
public void setCn_alphabet(String cn_alphabet) {
this.cn_alphabet = cn_alphabet;
}
public Integer getGood_id() {
return good_id;
}
public void setGood_id(Integer good_id) {
this.good_id = good_id;
}
public BigDecimal getGoods_price() {
return goods_price;
}
public void setGoods_price(BigDecimal goods_price) {
this.goods_price = goods_price;
}
public BigDecimal getGoods_amount() {
return goods_amount;
}
public void setGoods_amount(BigDecimal goods_amount) {
this.goods_amount = goods_amount;
}
public String getFactory_color_name() {
return factory_color_name;
}
public void setFactory_color_name(String factory_color_name) {
this.factory_color_name = factory_color_name;
}
public String getGoods_image() {
return goods_image;
}
public void setGoods_image(String goods_image) {
this.goods_image = goods_image;
}
public Byte getGoods_type() {
return goods_type;
}
public void setGoods_type(Byte goods_type) {
this.goods_type = goods_type;
}
public String getExpect_arrival_time() {
return expect_arrival_time;
}
public void setExpect_arrival_time(String expect_arrival_time) {
this.expect_arrival_time = expect_arrival_time;
}
public Integer getBuy_num() {
return buy_num;
}
public void setBuy_num(Integer buy_num) {
this.buy_num = buy_num;
}
public String getSize_name() {
return size_name;
}
public void setSize_name(String size_name) {
this.size_name = size_name;
}
public String getColor_name() {
return color_name;
}
public void setColor_name(String color_name) {
this.color_name = color_name;
}
}
... ...
... ... @@ -27,5 +27,9 @@
<groupId>com.yoho.service.model</groupId>
<artifactId>activity-service-model</artifactId>
</dependency>
<dependency>
<groupId>com.yoho.service.model</groupId>
<artifactId>order-service-model</artifactId>
</dependency>
</dependencies>
</project>
... ...
... ... @@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.activity.common.ApiResponse;
import com.yoho.activity.common.vo.LotteryOrderVO;
import com.yoho.activity.common.vo.LotteryRespData;
import com.yoho.activity.common.vo.LotteryVO;
import com.yoho.activity.service.ILotteryService;
... ... @@ -66,12 +67,14 @@ public class LotteryController {
*/
@RequestMapping("/getValidOrderList")
@ResponseBody
public ApiResponse getValidOrderList(@RequestParam(value="uid")Integer uid) {
logger.info("Start getValidOrderList with uid is {}", uid);
public ApiResponse getValidOrderList(@RequestParam(value="uid")Integer uid,
@RequestParam(value="limit")Integer limit,
@RequestParam(value="page")Integer page) {
logger.info("Start getValidOrderList with uid is {}, limit is {}, page is {}", uid, limit, page);
checkUserId(uid);
LotteryRespData respData = lotteryService.getValidOrderList(uid);
List<LotteryOrderVO> respData = lotteryService.getValidOrderList(uid, limit, page);
logger.info("End getValidOrderList");
return new ApiResponse(respData);
... ...
... ... @@ -30,4 +30,7 @@ public interface LotteryRecordMapper {
List<LotteryPrizeInfo> selectLotteryPrizeInfo(@Param("lotteryId") Integer lotteryId,
@Param("shardFactor") int shardFactor);
List<LotteryRecord> selectByUidAndOrderCodes(@Param("userId") Integer userId,
@Param("shardFactor") int shardFactor, @Param("orderCodes") List<String> orderCodes);
}
\ No newline at end of file
... ...
... ... @@ -10,10 +10,16 @@
<result column="prize_id" jdbcType="INTEGER" property="prizeId" />
<result column="mod_time" jdbcType="INTEGER" property="modTime" />
</resultMap>
<sql id="Base_Column_List" >
id, lottery_id, uid, status, flag, prize_id, mod_time
</sql>
<delete id="deleteByPrimaryKey">
delete from lottery_record_${shardFactor}
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert">
insert into lottery_record_${shardFactor} (id, lottery_id, uid,
status, flag, prize_id,
... ... @@ -22,6 +28,7 @@
#{record.status,jdbcType=TINYINT}, #{record.flag,jdbcType=VARCHAR}, #{record.prizeId,jdbcType=INTEGER},
#{record.modTime,jdbcType=INTEGER})
</insert>
<update id="updateByPrimaryKey">
update lottery_record_${shardFactor}
set lottery_id = #{record.lotteryId,jdbcType=INTEGER},
... ... @@ -32,8 +39,9 @@
mod_time = #{record.modTime,jdbcType=INTEGER}
where id = #{record.id,jdbcType=INTEGER}
</update>
<select id="selectByPrimaryKey" resultMap="BaseResultMap">
select id, lottery_id, uid, status, flag, prize_id, mod_time
select <include refid="Base_Column_List" />
from lottery_record_${shardFactor}
where id = #{id,jdbcType=INTEGER}
</select>
... ... @@ -47,12 +55,12 @@
</foreach>
</select>
<select id="selectAll" resultMap="BaseResultMap">
select id, lottery_id, uid, status, flag, prize_id, mod_time
select <include refid="Base_Column_List" />
from lottery_record_${shardFactor}
</select>
<select id="selectOrderRecords" resultMap="BaseResultMap">
select id, lottery_id, uid, status, flag, prize_id, mod_time
select <include refid="Base_Column_List" />
from lottery_record_${shardFactor}
where lottery_id = #{lotteryId,jdbcType=INTEGER}
and uid = #{userId,jdbcType=INTEGER}
... ... @@ -72,16 +80,27 @@
and flag = #{orderCode,jdbcType=INTEGER}
</if>
</select>
<select id="selectUserLotteryPrizeCount" resultType="java.lang.Integer">
select case when count(*) is null then 0 else count(*) end count
from lottery_record_${shardFactor}
where lottery_id = #{lotteryId,jdbcType=INTEGER}
and uid = #{userId,jdbcType=INTEGER} and prize_id is not null
</select>
<select id="selectLotteryPrizeInfo" resultType="com.yoho.lottery.dal.model.LotteryPrizeInfo">
select prize_id as prizeId , count(*) as count
from lottery_record_${shardFactor}
where lottery_id = #{lotteryId,jdbcType=INTEGER} and prize_id is not null
group by prize_id
</select>
<select id="selectByUidAndOrderCodes" resultMap="BaseResultMap">
select <include refid="Base_Column_List" />
from lottery_record_${shardFactor}
where uid = #{userId,jdbcType=INTEGER} and flag in
<foreach item="item" index="index" collection="orderCodes" open="(" separator="," close=")">
#{item}
</foreach>
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -4,7 +4,7 @@
<parent>
<groupId>com.yoho</groupId>
<artifactId>parent</artifactId>
<version>1.1.5-SNAPSHOT</version>
<version>1.1.9-SNAPSHOT</version>
</parent>
<groupId>com.yoho.dsf</groupId>
... ...
... ... @@ -34,7 +34,11 @@
<groupId>com.yoho.core</groupId>
<artifactId>yoho-core-rest-client-simple</artifactId>
</dependency>
<dependency>
<groupId>com.yoho.service.model</groupId>
<artifactId>order-service-model</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
... ...
... ... @@ -2,6 +2,7 @@ package com.yoho.activity.service;
import java.util.List;
import com.yoho.activity.common.vo.LotteryOrderVO;
import com.yoho.activity.common.vo.LotteryRespData;
import com.yoho.lottery.dal.model.LotteryRecord;
import com.yoho.lottery.dal.model.Prize;
... ... @@ -43,13 +44,13 @@ public interface ILotteryService {
/**
* 查询用户订单列表(时间:距离当前时间15天 至 一个月)
*
* @param lotteryId 活动id
* @param userId 用户id
* @param orderCode 订单编号
* @param limit 每页显示条数
* @param page 页数
* @return 抽奖状态信息
*/
LotteryRespData getValidOrderList(Integer userId);
List<LotteryOrderVO> getValidOrderList(Integer userId, Integer limit, Integer page);
boolean hasRealPrize(Prize prize);
LotteryRecord[] getLotteryRecordByIds(List<Integer> ids, int shardFactor);
}
... ...
... ... @@ -14,7 +14,9 @@ import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
... ... @@ -27,25 +29,30 @@ import com.yoho.activity.common.cache.CacheAop;
import com.yoho.activity.common.cache.CacheKeyAndTime;
import com.yoho.activity.common.cache.Cacheable;
import com.yoho.activity.common.helper.SendCouponHelper;
import com.yoho.activity.common.redis.GracefulRedisTemplate;
import com.yoho.activity.common.redis.KeyBuilder;
import com.yoho.activity.common.vo.LotteryOrderVO;
import com.yoho.activity.common.vo.LotteryRespData;
import com.yoho.activity.common.vo.OrdersGoodsVO;
import com.yoho.activity.service.ILotteryService;
import com.yoho.core.redis.YHRedisTemplate;
import com.yoho.core.redis.YHValueOperations;
import com.yoho.core.rest.client.ServiceCaller;
import com.yoho.error.exception.ServiceException;
import com.yoho.lottery.dal.LotteryMapper;
import com.yoho.lottery.dal.LotteryRecordMapper;
import com.yoho.lottery.dal.PrizeMapper;
import com.yoho.lottery.dal.WeixinOrderListMapper;
import com.yoho.lottery.dal.model.Lottery;
import com.yoho.lottery.dal.model.LotteryRecord;
import com.yoho.lottery.dal.model.Prize;
import com.yoho.service.model.order.request.OrderListRequest;
import com.yoho.service.model.order.response.OrderQueryForLotteryResponse;
import com.yoho.service.model.order.response.Orders;
import com.yoho.service.model.order.response.OrdersGoods;
@Service
public class LotteryServiceImpl implements ILotteryService , ApplicationContextAware {
@Autowired
private WeixinOrderListMapper weixinOrderListMapper;
private static Logger logger = LoggerFactory.getLogger(LotteryServiceImpl.class);
/** 未抽奖. */
... ... @@ -74,6 +81,11 @@ public class LotteryServiceImpl implements ILotteryService , ApplicationContextA
private SendCouponHelper sendCouponHelper;
@Autowired
private ServiceCaller serviceCaller;
@Autowired
private GracefulRedisTemplate gracefulRedisTemplate;
private CacheAop cacheAop;
@Resource(name = "yhValueOperations")
... ... @@ -302,10 +314,110 @@ public class LotteryServiceImpl implements ILotteryService , ApplicationContextA
}
@Override
public LotteryRespData getValidOrderList(Integer uid) {
List<Integer> weixinOrderCodeList = weixinOrderListMapper.selectOrderCodeByUid(uid);
public List<LotteryOrderVO> getValidOrderList(Integer uid, Integer limit, Integer page) {
//1、获取有效的订单列表
//先从缓存获取
List<LotteryOrderVO> orderVoList = gracefulRedisTemplate.getList(KeyBuilder.WEIXIN_LOTTERY_USER_ORDER_LIST + uid, LotteryOrderVO.class);
if(CollectionUtils.isEmpty(orderVoList)){
OrderListRequest request = new OrderListRequest();
request.setUid(String.valueOf(uid));
request.setLimit(limit);
request.setPage(page);
OrderQueryForLotteryResponse rsp = serviceCaller.call("order.getOrderListForLottery", request, OrderQueryForLotteryResponse.class);
if(null == rsp || CollectionUtils.isEmpty(rsp.getOrderList())){
return null;
}
List<Orders> orderList = rsp.getOrderList();
orderVoList = buildOrdersVOList(orderList);
//放入缓存20分钟
gracefulRedisTemplate.setEx(KeyBuilder.WEIXIN_LOTTERY_USER_ORDER_LIST + uid, orderVoList, 20 * 60);
}
return null;
//2、获取订单号列表
List<String> orderCodeList = Lists.newArrayList();
for(LotteryOrderVO order : orderVoList){
orderCodeList.add(order.getOrder_code());
}
//3、根据订单号批量查询lottery_record表
List<LotteryRecord> recordList = lotteryRecordMapper.selectByUidAndOrderCodes(uid, uid % 10, orderCodeList);
//4、为每个订单设置状态
setLotteryOrderStatus(orderVoList, recordList);
return orderVoList;
}
private List<LotteryOrderVO> setLotteryOrderStatus(List<LotteryOrderVO> orderVOList, List<LotteryRecord> recordList){
for(LotteryOrderVO orderVO : orderVOList){
//默认设定状态为参加抽奖,即从未抽过奖
orderVO.setStatus(STATE_NOT_USE);
for(LotteryRecord record : recordList){
if(orderVO.getOrder_code().equals(record.getFlag())){
//抽中
if(1 == record.getPrizeId().intValue()){
orderVO.setStatus(STATE_USE_HAVA_PRIZE);
}else if (0 == record.getPrizeId().intValue()){//未抽中
orderVO.setStatus(STATE_USE_NO_PRIZE);
}
}
}
}
return orderVOList;
}
private List<LotteryOrderVO> buildOrdersVOList(List<Orders> orderList){
List<LotteryOrderVO> orderVoList = Lists.newArrayList();
for(Orders order : orderList){
LotteryOrderVO vo = new LotteryOrderVO();
vo.setId(order.getId());
vo.setOrder_code(String.valueOf(order.getOrderCode()));
vo.setOrder_type(order.getOrderType());
vo.setRefund_status(order.getRefundStatus());
vo.setUid(order.getUid());
vo.setParent_order_code(String.valueOf(order.getParentOrderCode()));
vo.setPayment(order.getPayment());
vo.setAmount(order.getAmount());
vo.setPayment_status(order.getPaymentStatus());
vo.setUser_confirm_paid(order.getUser_confirm_paid());
vo.setUse_limit_code(order.getUse_limit_code());
vo.setPayment_type(order.getPaymentType());
vo.setOrdersGoodsList(buildOrdersGoodsVO(order.getOrdersGoodsList()));
orderVoList.add(vo);
}
return orderVoList;
}
private List<OrdersGoodsVO> buildOrdersGoodsVO(List<OrdersGoods> ordersGoodsList){
List<OrdersGoodsVO> goodsVoList = Lists.newArrayList();
for(OrdersGoods ordersGoods : ordersGoodsList){
OrdersGoodsVO goodsVo = new OrdersGoodsVO();
goodsVo.setProduct_id(ordersGoods.getProductId());
goodsVo.setProduct_skn(ordersGoods.getProductSkn());
goodsVo.setProduct_name(ordersGoods.getProductName());
goodsVo.setCn_alphabet(ordersGoods.getCnAlphabet());
goodsVo.setGood_id(ordersGoods.getGoodsId());
goodsVo.setGoods_price(ordersGoods.getGoodsPrice());
goodsVo.setGoods_amount(ordersGoods.getGoodsAmount());
goodsVo.setFactory_color_name(ordersGoods.getFactoryGoodsName());
goodsVo.setGoods_image(ordersGoods.getGoodsImage());
goodsVo.setGoods_type(ordersGoods.getGoodsType());
goodsVo.setExpect_arrival_time(ordersGoods.getExpectArrivalTime());
goodsVo.setBuy_num(ordersGoods.getNum());
goodsVo.setSize_name(ordersGoods.getSizeName());
goodsVo.setColor_name(ordersGoods.getColorName());
goodsVoList.add(goodsVo);
}
return goodsVoList;
}
public boolean hasRealPrize(Prize prize) {
... ...