历史数据实体类
用于记录用户登录的历史数据
/**
* 记录是用户的登录的历史状态
*/
public class HistoryData implements Serializable {
//保存用户所有登录历史城市
private Set<String> historyCities;
//历史设备信息
private List<String> historyDeviceInformations;
//当前天登录的累计次数-无需实现
private Integer currentDayLoginCount;
//存储用户的乱序密码
private Set<String> historyOrdernessPasswords;
//输入特征更新,保留最近前N
private List<Double[]> latestInputFeatures;
//更新登录时间
private long lastLoginTime;
//登录位置
private GeoPoint lastLoginGeoPoint;
//历史登录时间区间
private Map<String, Map<String,Integer>> historyLoginTimeSlot;
public Set<String> getHistoryCities() {
return historyCities;
}
public void setHistoryCities(Set<String> historyCities) {
this.historyCities = historyCities;
}
public List<String> getHistoryDeviceInformations() {
return historyDeviceInformations;
}
public void setHistoryDeviceInformations(List<String> historyDeviceInformations) {
this.historyDeviceInformations = historyDeviceInformations;
}
public Integer getCurrentDayLoginCount() {
return currentDayLoginCount;
}
public void setCurrentDayLoginCount(Integer currentDayLoginCount) {
this.currentDayLoginCount = currentDayLoginCount;
}
public Set<String> getHistoryOrdernessPasswords() {
return historyOrdernessPasswords;
}
public void setHistoryOrdernessPasswords(Set<String> historyOrdernessPasswords) {
this.historyOrdernessPasswords = historyOrdernessPasswords;
}
public List<Double[]> getLatestInputFeatures() {
return latestInputFeatures;
}
public void setLatestInputFeatures(List<Double[]> latestInputFeatures) {
this.latestInputFeatures = latestInputFeatures;
}
public long getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(long lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public GeoPoint getLastLoginGeoPoint() {
return lastLoginGeoPoint;
}
public void setLastLoginGeoPoint(GeoPoint lastLoginGeoPoint) {
this.lastLoginGeoPoint = lastLoginGeoPoint;
}
public Map<String, Map<String, Integer>> getHistoryLoginTimeSlot() {
return historyLoginTimeSlot;
}
public void setHistoryLoginTimeSlot(Map<String, Map<String, Integer>> historyLoginTimeSlot) {
this.historyLoginTimeSlot = historyLoginTimeSlot;
}
@Override
public String toString() {
return "{" +
"historyCities=" + historyCities +
", historyDeviceInformations=" + historyDeviceInformations +
", currentDayLoginCount=" + currentDayLoginCount +
", historyOrdernessPasswords=" + historyOrdernessPasswords +
", latestInputFeatures=" + latestInputFeatures.stream().map(v-> Arrays.stream(v).map(a->a+"").reduce((v1,v2)->v1+","+v2).get()).collect(Collectors.toList()) +
", lastLoginTime=" + lastLoginTime +
", lastLoginGeoPoint=" + lastLoginGeoPoint +
", historyLoginTimeSlot=" + historyLoginTimeSlot +
'}';
}
}
历史数据更新实现
更新责任链
利用责任链模式来更新历史数据
public class UpdaterChain {
private int position=0;
private List<Updater> updaters;
public UpdaterChain(List<Updater> updaters) {
this.updaters = updaters;
}
public void doChain(LoginSuccessData loginSuccessData, HistoryData historyData){
if(position < updaters.size()){
//获取一个责任
Updater updater = updaters.get(position);
position +=1;
updater.update(loginSuccessData,historyData,this);
}
}
}
更新评估因子
登录城市
public class CitiesUpdates implements Updater {
@Override
public void update(LoginSuccessData loginSuccessData, HistoryData historyData, UpdaterChain updaterChain) {
doUpdate(loginSuccessData,historyData);
updaterChain.doChain(loginSuccessData,historyData);
}
/**
* 保留所有用户登录过的城市
* @param loginSuccessData
* @param historyData
*/
private void doUpdate(LoginSuccessData loginSuccessData, HistoryData historyData){
//获取当前登录城市
String cityName = loginSuccessData.getCityName();
Set<String> historyCities = historyData.getHistoryCities();
//第一次登录,创建集合
if(historyCities==null){
historyCities=new HashSet<String>();
}
//存入数据
historyCities.add(cityName);
historyData.setHistoryCities(historyCities);
}
}
登录设备
public class DeviceUpdates implements Updater {
//仅保存最近登录的3个设备信息
private Integer deviceCount=3;
public DeviceUpdates(Integer deviceCount) {
this.deviceCount = deviceCount;
}
@Override
public void update(LoginSuccessData loginSuccessData, HistoryData historyData, UpdaterChain updaterChain) {
doUpdate(loginSuccessData,historyData);
updaterChain.doChain(loginSuccessData,historyData);
}
/**
* 保留所有用户最近deviceCount个设备信息
* @param loginSuccessData
* @param historyData
*/
private void doUpdate(LoginSuccessData loginSuccessData, HistoryData historyData){
String deviceInformation = loginSuccessData.getDeviceInformation();
List<String> deviceInformations = historyData.getHistoryDeviceInformations();
if(deviceInformations==null){
deviceInformations=new ArrayList<String>();
}
if(!deviceInformations.contains(deviceInformation)){
deviceInformations.add(deviceInformation);`在这里插入代码片`
//判断一下集合大小是否达到阈值
if(deviceInformations.size()>deviceCount){
deviceInformations.remove(0);
}
}
historyData.setHistoryDeviceInformations(deviceInformations);
}
}
用户登录输入特征
public class InputFeaturesUpdater implements Updater {
private Integer numCount=10;
public void setNumCount(Integer numCount) {
this.numCount = numCount;
}
@Override
public void update(LoginSuccessData loginSuccessData, HistoryData historyData, UpdaterChain updaterChain) {
doUpdate(loginSuccessData,historyData);
updaterChain.doChain(loginSuccessData,historyData);
}
private void doUpdate(LoginSuccessData loginSuccessData, HistoryData historyData){
Double[] inputFeatures = loginSuccessData.getInputFeatures();
List<Double[]> latestInputFeatures = historyData.getLatestInputFeatures();
if(latestInputFeatures==null){
latestInputFeatures=new ArrayList<Double[]>();
}
latestInputFeatures.add(inputFeatures);
if(latestInputFeatures.size()>numCount){
latestInputFeatures.remove(0);
}
historyData.setLatestInputFeatures(latestInputFeatures);
}
}
用户登录地点的经纬度
public class LastLoginGeoPoint implements Updater {
@Override
public void update(LoginSuccessData loginSuccessData, HistoryData historyData, UpdaterChain updaterChain) {
doUpdate( loginSuccessData, historyData);
updaterChain.doChain(loginSuccessData,historyData);
}
public void doUpdate(LoginSuccessData loginSuccessData, HistoryData historyData) {
historyData.setLastLoginGeoPoint(loginSuccessData.getGeoPoint());
}
}
用户登录时间
public class LoginTimeUpdater implements Updater {
@Override
public void update(LoginSuccessData loginSuccessData, HistoryData historyData, UpdaterChain updaterChain) {
doUpdate(loginSuccessData,historyData);
updaterChain.doChain(loginSuccessData,historyData);
}
public void doUpdate(LoginSuccessData loginSuccessData, HistoryData historyData) {
historyData.setLastLoginTime(loginSuccessData.getLoginTime());
}
}
用户登录历史密码
public class PasswordsUpdates implements Updater {
@Override
public void update(LoginSuccessData loginSuccessData, HistoryData historyData, UpdaterChain updaterChain) {
doUpdate(loginSuccessData,historyData);
updaterChain.doChain(loginSuccessData,historyData);
}
/**
* 保留所有用户正常登录过的密码
* @param loginSuccessData
* @param historyData
*/
private void doUpdate(LoginSuccessData loginSuccessData, HistoryData historyData){
String ordernessPassword = loginSuccessData.getOrdernessPassword();
Set<String> historyOrdernessPasswords = historyData.getHistoryOrdernessPasswords();
if(historyOrdernessPasswords==null){
historyOrdernessPasswords=new HashSet<String>();
}
historyOrdernessPasswords.add(ordernessPassword);
historyData.setHistoryOrdernessPasswords(historyOrdernessPasswords);
}
}
用户登录习惯(时间段)
public class TimeSlotUpdater implements Updater {
@Override
public void update(LoginSuccessData loginSuccessData, HistoryData historyData, UpdaterChain updaterChain) {
doUpdate(loginSuccessData,historyData);
updaterChain.doChain(loginSuccessData,historyData);
}
public void doUpdate(LoginSuccessData loginSuccessData, HistoryData historyData) {
long loginTime = loginSuccessData.getLoginTime();
String[] WEEKS={"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(loginTime);
String dayOfWeek = WEEKS[calendar.get(Calendar.DAY_OF_WEEK) - 1];
DecimalFormat decimalFormat=new DecimalFormat("00");
String hourOfDay= decimalFormat.format(calendar.get(Calendar.HOUR_OF_DAY));//01 02 ... 24
Map<String, Map<String, Integer>> historyLoginTimeSlot = historyData.getHistoryLoginTimeSlot();
if(historyLoginTimeSlot==null){
historyLoginTimeSlot=new HashMap<String, Map<String, Integer>>();
}
//更新用户的登录习惯
if(!historyLoginTimeSlot.containsKey(dayOfWeek)){
HashMap<String, Integer> timeSlot = new HashMap<String, Integer>();
timeSlot.put(hourOfDay,1);
historyLoginTimeSlot.put(dayOfWeek,timeSlot);
}else{//包含dayOfWeek
Map<String, Integer> timeSlot = historyLoginTimeSlot.get(dayOfWeek);
Integer count=0;
if(timeSlot.containsKey(hourOfDay)){//含有时段
count=timeSlot.get(hourOfDay);
}
timeSlot.put(hourOfDay,count+1);
}
historyData.setHistoryLoginTimeSlot(historyLoginTimeSlot);
}
}