商户投放子系统:
用户应用子系统:
缓存层设计:缓存使用的是Redis,其中有两类信息,首先是优惠卷PassTemplate Token的存储方案,和商户Merchants存储方案。
优惠卷Token信息会有两个文件,商户上传的原始文件init和已使用的Token文件used,在系统中直接操作io文件会很慢,所以使用Redis的set结构保存优惠卷token信息。用户领取优惠卷时直接从redis中分配。
商户信息使用redis保存,使用hashMap存储,Field是商户id,key是Merchants
项目中常用的工具类:Apache DigestUtils:编码解码工具类
commons-codec commons-codec1.9
public static String md5Hex(String data){
return Hex.encodeHexString(md5(data));
}
Apache RandomStringUtils:生成随机数字,字母的工具
commons-lang commons-lang2.6
| 函数定义 | 功能 |
| RandomStringUtils.random(5) | 产生2位长度的随机字符串 |
| RandomStringUtils.random(5,new char[] {'a','b','2','4'}) | 使用指定的字符生成5位长度的随机字符串 |
| RandomStringUtils.randomAlphanumeric(5) | 生成指定长度的字母和数字的随机组合字符串 |
| RandomStringUtils.randomNumeric(5) | 生成随机数字字符串 |
| RandomStringUtils.randomAlphabetic(5) | 生成随机[a-z]字符串,包含大小写 |
| RandomStringUtils.randomAscii(4) | 生成从ASCII32到126组成的随机字符串 |
Apache DateUtils:
commons-lang commons-lang2.6
| 函数定义 | 功能 |
| Date parseDate(String str,String...parsePatterns) | 解析日期时间字符串日期时间Date对象 |
| Date addYears(Date date,int amount) | 得到date日期时间后(前)amount年后的日期时间 |
| Date addDays(Date date,int amount) | 同addYears相似,对天数进行加减 |
| Date addHours(Date date,int amount) | 同addYears相似,对小时数进行加减 |
| boolean isSameDay(Date date1,Date date2) | 判断两个日期是否是同一天 |
Apache Guava Enums:枚举实例的使用方法
com.google.guava guava18.0
static Field getField(Enum> enumValue) //返回enumValue定义的Field static> Optional getIfPresent(Class enumClass,String value) //返回Enum类型的值,使用Enum.calueOf(java.lang.class ,java.lang.String) static > Converter stringConverter(Class enumClass) //返回一个converter对象转换成string以及给定Enum类型的值,使用Enum.valueOf(Class,String) 与Enum.name()
starter-hbase
com.spring4all spring-boot-starter-hbase1.0.0.RELEASE
| 表名 | 列族 | |
| people | f | |
| name | age | |
public class QueryService {
@Autowired
private HbaseTemplate hbaseTemplate;
//范围扫描查询
public List query(String startRow, String stopRow){
Scan scan = new Scan(Bytes.toBytes(startRow), Bytes.toBytes(stopRow));
scan.setCaching(5000); //设置scan缓存
List dtos = this.hbaseTemplate.find("people_table",scan,new PeopleRowMapper());
return dtos;
}
//确定行键查询
public PeopleDto query(String row){
PeopleDto dto = this.hbaseTemplate.get("people_table",row,new PeopleRowMapper());
return dto;
}
}
public class PeopleRowMapper implements RowMapper日志处理设计{ private static byte[] COLUMNFAMILY = "f".getBytes(); private static byte[] NAME = "name".getBytes(); private static byte[] AGE = "age".getBytes(); @Override public PeopleDto mapRow(Result result,itn rowNum)throws Exception{ PeopleDto dto = new PeopleDto(); //TODO: 设置相关的属性值 String name = Bytes.toString(result.getValue(COLUMNFAMILY ,NAME)); int age = Bytes.toInt(result.getValue(COLUMNFAMILY ,AGE)); retrun fto.setName(name).setAge(age); } }
为什么记录日志?
1.为了事件查询,问题查询 2.为了用户行为分析
日志分类?
记录日志;分析日志;
日志内容?
事件内容;action行为动作,userId用户id,timestamp时间戳,remoteIp用户Ip,info行为信息
异常处理统一的异常处理
springboot实现了/error统一处理,但是需要我们自己实现自己的统一异常处理,并以Restful Api风格返回客户端:
@ControllerAdvice:定义统一的异常处理类
@ExceptionHandler:定义函数针对的异常类型
表结构设计商户投放子系统
1.商户信息,保存在Mysql中,分别是id(商户id),name,logo_url(商户logo),business_license_url(商户营业执照),phone,address,is_audit(商户是否审核标志位,默认是未审核)。
2.优惠卷信息,保存在Hbase中,b列族表示基本信息,id表示商户id,title(用户卷标题),summary(摘要),o列族表示限制条件,limit(优惠卷最大数量),start(开始时间)
用户应用子系统
1.Pass,用户优惠卷表,保存在Hbase中,i列族表示用户基本信息,id(用户id),template_id(标识passtempalte在Hbase中的行键,用于映射具体的优惠卷信息),token(优惠卷token),assigned_date(优惠卷领取日期),con_date(消费日期)
2.Feedback,用户返回表,保存在Hbase中,i列族返回的基本信息,id(用户id),type(评论类型),template_id(优惠卷的rowkey)
id生成器:
1.user表,用户的基本信息,b列族表示基本信息,o列族表示额外信息。RowKey:用户表的行键,userId,生成策略:当前用户数+随机5位数字



