一、创建Maven项目
创建项目,名称为LogAnalysis
二、常用工具类
2.1 配置管理组建
ConfigurationManager.java
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 import java.io.InputStream; 2 import java.util.Properties; 3 4 /** 5 * 配置管理组件 6 * 7 * 1、配置管理组件可以复杂,也可以很简单,对于简单的配置管理组件来说,只要开发一个类,可以在第一次访问它的 8 * 时候,就从对应的properties文件中,读取配置项,并提供外界获取某个配置key对应的value的方法 9 * 2、如果是特别复杂的配置管理组件,那么可能需要使用一些软件设计中的设计模式,比如单例模式、解释器模式 10 * 可能需要管理多个不同的properties,甚至是xml类型的配置文件 11 * 3、我们这里的话,就是开发一个简单的配置管理组件,就可以了 12 * 13 */ 14 public class ConfigurationManager { 15 16 // Properties对象使用private来修饰,就代表了其是类私有的 17 // 那么外界的代码,就不能直接通过ConfigurationManager.prop这种方式获取到Properties对象 18 // 之所以这么做,是为了避免外界的代码不小心错误的更新了Properties中某个key对应的value 19 // 从而导致整个程序的状态错误,乃至崩溃 20 private static Properties prop = new Properties(); 21 22 static { 23 try { 24 InputStream in = ConfigurationManager.class 25 .getClassLoader().getResourceAsStream("conf.properties"); 26 prop.load(in); 27 } catch (Exception e) { 28 e.printStackTrace(); 29 } 30 } 31 32 /** 33 * 获取指定key对应的value 34 * 35 * @param key 36 * @return value 37 */ 38 public static String getProperty(String key) { 39 40 return prop.getProperty(key); 41 } 42 43 /** 44 * 获取整数类型的配置项 45 * @param key 46 * @return value 47 */ 48 public static Integer getInteger(String key) { 49 String value = getProperty(key); 50 try { 51 return Integer.valueOf(value); 52 } catch (Exception e) { 53 e.printStackTrace(); 54 } 55 return 0; 56 } 57 58 /** 59 * 获取布尔类型的配置项 60 * @param key 61 * @return value 62 */ 63 public static Boolean getBoolean(String key) { 64 String value = getProperty(key); 65 try { 66 return Boolean.valueOf(value); 67 } catch (Exception e) { 68 e.printStackTrace(); 69 } 70 return false; 71 } 72 73 /** 74 * 获取Long类型的配置项 75 * @param key 76 * @return 77 */ 78 public static Long getLong(String key) { 79 String value = getProperty(key); 80 try { 81 return Long.valueOf(value); 82 } catch (Exception e) { 83 e.printStackTrace(); 84 } 85 return 0L; 86 }
2.2 常量的接口
Constants.java
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /** 2 * 常量接口 3 * @author Administrator 4 * 5 */ 6 public interface Constants { 7 8 /** 9 * 项目配置相关的常量 10 */ 11 String JDBC_DRIVER = "jdbc.driver"; 12 String JDBC_DATASOURCE_SIZE = "jdbc.datasource.size"; 13 String JDBC_URL = "jdbc.url"; 14 String JDBC_USER = "jdbc.user"; 15 String JDBC_PASSWORD = "jdbc.password"; 16 String JDBC_URL_PROD = "jdbc.url.prod"; 17 String JDBC_USER_PROD = "jdbc.user.prod"; 18 String JDBC_PASSWORD_PROD = "jdbc.password.prod"; 19 String SPARK_LOCAL = "spark.local"; 20 String SPARK_LOCAL_TASKID_SESSION = "spark.local.taskid.session"; 21 String SPARK_LOCAL_TASKID_PAGE = "spark.local.taskid.page"; 22 String SPARK_LOCAL_TASKID_PRODUCT = "spark.local.taskid.product"; 23 String KAFKA_METADATA_BROKER_LIST = "kafka.metadata.broker.list"; 24 String KAFKA_TOPICS = "kafka.topics"; 25 26 /** 27 * Spark作业相关的常量 28 */ 29 String SPARK_APP_NAME_SESSION = "UserVisitSessionAnalyzeSpark"; 30 String SPARK_APP_NAME_PAGE = "PageOneStepConvertRateSpark"; 31 String FIELD_SESSION_ID = "sessionid"; 32 String FIELD_SEARCH_KEYWORDS = "searchKeywords"; 33 String FIELD_CLICK_CATEGORY_IDS = "clickCategoryIds"; 34 String FIELD_AGE = "age"; 35 String FIELD_PROFESSIONAL = "professional"; 36 String FIELD_CITY = "city"; 37 String FIELD_SEX = "sex"; 38 String FIELD_VISIT_LENGTH = "visitLength"; 39 String FIELD_STEP_LENGTH = "stepLength"; 40 String FIELD_START_TIME = "startTime"; 41 String FIELD_CLICK_COUNT = "clickCount"; 42 String FIELD_ORDER_COUNT = "orderCount"; 43 String FIELD_PAY_COUNT = "payCount"; 44 String FIELD_CATEGORY_ID = "categoryid"; 45 46 String SESSION_COUNT = "session_count"; 47 48 String TIME_PERIOD_1s_3s = "1s_3s"; 49 String TIME_PERIOD_4s_6s = "4s_6s"; 50 String TIME_PERIOD_7s_9s = "7s_9s"; 51 String TIME_PERIOD_10s_30s = "10s_30s"; 52 String TIME_PERIOD_30s_60s = "30s_60s"; 53 String TIME_PERIOD_1m_3m = "1m_3m"; 54 String TIME_PERIOD_3m_10m = "3m_10m"; 55 String TIME_PERIOD_10m_30m = "10m_30m"; 56 String TIME_PERIOD_30m = "30m"; 57 58 String STEP_PERIOD_1_3 = "1_3"; 59 String STEP_PERIOD_4_6 = "4_6"; 60 String STEP_PERIOD_7_9 = "7_9"; 61 String STEP_PERIOD_10_30 = "10_30"; 62 String STEP_PERIOD_30_60 = "30_60"; 63 String STEP_PERIOD_60 = "60"; 64 65 /** 66 * 任务相关的常量 67 */ 68 String PARAM_START_DATE = "startDate"; 69 String PARAM_END_DATE = "endDate"; 70 String PARAM_START_AGE = "startAge"; 71 String PARAM_END_AGE = "endAge"; 72 String PARAM_PROFESSIONALS = "professionals"; 73 String PARAM_CITIES = "cities"; 74 String PARAM_SEX = "sex"; 75 String PARAM_KEYWORDS = "keywords"; 76 String PARAM_CATEGORY_IDS = "categoryIds"; 77 String PARAM_TARGET_PAGE_FLOW = "targetPageFlow"; 78 79 }
2.3 时间日期工具类
DateUtils.java
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 import java.text.ParseException; 2 import java.text.SimpleDateFormat; 3 import java.util.Calendar; 4 import java.util.Date; 5 6 /** 7 * 时间日期工具类 8 * */ 9 public class DateUtils { 10 11 public static final SimpleDateFormat TIME_FORMAT = 12 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 13 public static final SimpleDateFormat DATE_FORMAT = 14 new SimpleDateFormat("yyyy-MM-dd"); 15 public static final SimpleDateFormat DATEKEY_FORMAT = 16 new SimpleDateFormat("yyyyMMdd"); 17 18 /** 19 * 判断第一个时间是否在第二个时间之前 20 * */ 21 public static boolean before(String firstTime,String secondTime){ 22 try { 23 Date first = TIME_FORMAT.parse(firstTime); 24 Date second = TIME_FORMAT.parse(secondTime); 25 26 if(first.before(second)){ 27 return true; 28 } 29 } catch (ParseException e) { 30 e.printStackTrace(); 31 } 32 return false; 33 } 34 35 /** 36 * 判断第一个时间是否在第二个时间之后 37 * */ 38 public static boolean after(String firstTime,String secondTime){ 39 try { 40 Date first = TIME_FORMAT.parse(firstTime); 41 Date second = TIME_FORMAT.parse(secondTime); 42 43 if(first.after(second)){ 44 return true; 45 } 46 }catch (ParseException e){ 47 e.printStackTrace(); 48 } 49 return false; 50 } 51 52 /** 53 * 计算2个时间的差值(单位为秒) 54 * */ 55 public static int minus(String firstTime,String secondTime){ 56 try { 57 Date first = TIME_FORMAT.parse(firstTime); 58 Date second = TIME_FORMAT.parse(secondTime); 59 long millisecond = first.getTime() - second.getTime(); 60 return Integer.valueOf(String.valueOf(millisecond/1000)); 61 }catch (ParseException e){ 62 e.printStackTrace(); 63 } 64 return 0; 65 } 66 67 /** 68 * 获取年月日和小时 69 * */ 70 public static String getDateHour(String datetime){ 71 String date = datetime.split(" ")[0]; 72 String hourMinuteSecond = datetime.split(" ")[1]; 73 String hour = hourMinuteSecond.split(":")[0]; 74 return date+"_"+hour; 75 } 76 77 /** 78 * 获取当天的日期 79 * */ 80 public static String getTodayDate(){ 81 return DATE_FORMAT.format(new Date()); 82 } 83 84 /** 85 * 获取昨天的日期 86 * */ 87 public static String getYesterdayDate(){ 88 Calendar calendar = Calendar.getInstance(); 89 calendar.setTime(new Date()); 90 calendar.add(Calendar.DAY_OF_YEAR,-1); 91 92 Date time = calendar.getTime(); 93 return DATE_FORMAT.format(time); 94 } 95 96 /** 97 * 格式化日期(yyyy-MM-dd) 98 */ 99 public static String formatDate(Date date) { 100 return DATE_FORMAT.format(date); 101 } 102 103 /** 104 * 格式化时间(yyyy-MM-dd HH:mm:ss) 105 */ 106 public static String formatTime(Date date) { 107 return TIME_FORMAT.format(date); 108 } 109 110 /** 111 * 解析时间字符串 112 */ 113 public static Date parseTime(String time) { 114 try { 115 return TIME_FORMAT.parse(time); 116 } catch (ParseException e) { 117 e.printStackTrace(); 118 } 119 return null; 120 } 121 122 /** 123 * 格式化日期key 124 */ 125 public static String formatDateKey(Date date) { 126 return DATEKEY_FORMAT.format(date); 127 } 128 129 /** 130 * 格式化日期key 131 */ 132 public static Date parseDateKey(String datekey) { 133 try { 134 return DATEKEY_FORMAT.parse(datekey); 135 } catch (ParseException e) { 136 e.printStackTrace(); 137 } 138 return null; 139 } 140 141 /** 142 * 格式化时间,保留到分钟级别 143 */ 144 public static String formatTimeMinute(Date date) { 145 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm"); 146 return sdf.format(date); 147 } 148 }
2.4 数字格式化工具类
NumberUtils.java
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 import java.math.BigDecimal; 2 3 /** 4 * 数字格式化工具类 5 * @author Administrator 6 * 7 */ 8 public class NumberUtils { 9 10 /** 11 * 格式化小数 12 * @param num 字符串 13 * @param scale 四舍五入的位数 14 * @return 格式化小数 15 */ 16 public static double formatDouble(double num, int scale) { 17 BigDecimal bd = new BigDecimal(num); 18 return bd.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue(); 19 } 20 21 }
2.5 参数工具类
ParamUtils.java
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 import com.alibaba.fastjson.JSONArray; 2 import com.alibaba.fastjson.JSONObject; 3 import com.bw.conf.ConfigurationManager; 4 import com.bw.constant.Constants; 5 6 7 /** 8 * 参数工具类 9 * @author Administrator 10 * 11 */ 12 public class ParamUtils { 13 14 /** 15 * 从命令行参数中提取任务id 16 * @param args 命令行参数 17 * @return 任务id 18 */ 19 public static Long getTaskIdFromArgs(String[] args, String taskType) { 20 boolean local = ConfigurationManager.getBoolean(Constants.SPARK_LOCAL); 21 22 if(local) { 23 return ConfigurationManager.getLong(taskType); 24 } else { 25 try { 26 if(args != null && args.length > 0) { 27 return Long.valueOf(args[0]); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } 32 } 33 34 return null; 35 } 36 37 /** 38 * 从JSON对象中提取参数 39 * @param jsonObject JSON对象 40 * @return 参数 41 */ 42 public static String getParam(JSONObject jsonObject, String field) { 43 JSONArray jsonArray = jsonObject.getJSONArray(field); 44 if(jsonArray != null && jsonArray.size() > 0) { 45 return jsonArray.getString(0); 46 } 47 return null; 48 } 49 50 }
2.6 字符串工具类
StringUtils.java
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /** 2 * 字符串工具类 3 * @author Administrator 4 * 5 */ 6 public class StringUtils { 7 8 /** 9 * 判断字符串是否为空 10 * @param str 字符串 11 * @return 是否为空 12 */ 13 public static boolean isEmpty(String str) { 14 return str == null || "".equals(str); 15 } 16 17 /** 18 * 判断字符串是否不为空 19 * @param str 字符串 20 * @return 是否不为空 21 */ 22 public static boolean isNotEmpty(String str) { 23 return str != null && !"".equals(str); 24 } 25 26 /** 27 * 截断字符串两侧的逗号 28 * @param str 字符串 29 * @return 字符串 30 */ 31 public static String trimComma(String str) { 32 if(str.startsWith(",")) { 33 str = str.substring(1); 34 } 35 if(str.endsWith(",")) { 36 str = str.substring(0, str.length() - 1); 37 } 38 return str; 39 } 40 41 /** 42 * 补全两位数字 43 * @param str 44 * @return 45 */ 46 public static String fulfuill(String str) { 47 if(str.length() == 2) { 48 return str; 49 } else { 50 return "0" + str; 51 } 52 } 53 54 /** 55 * 从拼接的字符串中提取字段 56 * @param str 字符串 57 * @param delimiter 分隔符 58 * @param field 字段 59 * @return 字段值 60 */ 61 public static String getFieldFromConcatString(String str, 62 String delimiter, String field) { 63 try { 64 String[] fields = str.split(delimiter); 65 for(String concatField : fields) { 66 // searchKeywords=|clickCategoryIds=1,2,3 67 if(concatField.split("=").length == 2) { 68 String fieldName = concatField.split("=")[0]; 69 String fieldValue = concatField.split("=")[1]; 70 if(fieldName.equals(field)) { 71 return fieldValue; 72 } 73 } 74 } 75 } catch (Exception e) { 76 e.printStackTrace(); 77 } 78 return null; 79 } 80 81 /** 82 * 从拼接的字符串中给字段设置值 83 * @param str 字符串 84 * @param delimiter 分隔符 85 * @param field 字段名 86 * @param newFieldValue 新的field值 87 * @return 字段值 88 */ 89 public static String setFieldInConcatString(String str, 90 String delimiter, String field, String newFieldValue) { 91 String[] fields = str.split(delimiter); 92 93 for(int i = 0; i < fields.length; i++) { 94 String fieldName = fields[i].split("=")[0]; 95 if(fieldName.equals(field)) { 96 String concatField = fieldName + "=" + newFieldValue; 97 fields[i] = concatField; 98 break; 99 } 100 } 101 102 StringBuffer buffer = new StringBuffer(""); 103 for(int i = 0; i < fields.length; i++) { 104 buffer.append(fields[i]); 105 if(i < fields.length - 1) { 106 buffer.append("|"); 107 } 108 } 109 110 return buffer.toString(); 111 } 112 113 }
2.7 校验工具类
ValidUtils.java
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /** 2 * 校验工具类 3 * @author Administrator 4 * 5 */ 6 public class ValidUtils { 7 8 /** 9 * 校验数据中的指定字段,是否在指定范围内 10 * @param data 数据 11 * @param dataField 数据字段 12 * @param parameter 参数 13 * @param startParamField 起始参数字段 14 * @param endParamField 结束参数字段 15 * @return 校验结果 16 */ 17 public static boolean between(String data, String dataField, 18 String parameter, String startParamField, String endParamField) { 19 String startParamFieldStr = StringUtils.getFieldFromConcatString( 20 parameter, "\\|", startParamField); 21 String endParamFieldStr = StringUtils.getFieldFromConcatString( 22 parameter, "\\|", endParamField); 23 if(startParamFieldStr == null || endParamFieldStr == null) { 24 return true; 25 } 26 27 int startParamFieldValue = Integer.valueOf(startParamFieldStr); 28 int endParamFieldValue = Integer.valueOf(endParamFieldStr); 29 30 String dataFieldStr = StringUtils.getFieldFromConcatString( 31 data, "\\|", dataField); 32 if(dataFieldStr != null) { 33 int dataFieldValue = Integer.valueOf(dataFieldStr); 34 if(dataFieldValue >= startParamFieldValue && 35 dataFieldValue <= endParamFieldValue) { 36 return true; 37 } else { 38 return false; 39 } 40 } 41 42 return false; 43 } 44 45 /** 46 * 校验数据中的指定字段,是否有值与参数字段的值相同 47 * @param data 数据 48 * @param dataField 数据字段 49 * @param parameter 参数 50 * @param paramField 参数字段 51 * @return 校验结果 52 */ 53 public static boolean in(String data, String dataField, 54 String parameter, String paramField) { 55 String paramFieldValue = StringUtils.getFieldFromConcatString( 56 parameter, "\\|", paramField); 57 if(paramFieldValue == null) { 58 return true; 59 } 60 String[] paramFieldValueSplited = paramFieldValue.split(","); 61 62 String dataFieldValue = StringUtils.getFieldFromConcatString( 63 data, "\\|", dataField); 64 if(dataFieldValue != null) { 65 String[] dataFieldValueSplited = dataFieldValue.split(","); 66 67 for(String singleDataFieldValue : dataFieldValueSplited) { 68 for(String singleParamFieldValue : paramFieldValueSplited) { 69 if(singleDataFieldValue.equals(singleParamFieldValue)) { 70 return true; 71 } 72 } 73 } 74 } 75 76 return false; 77 } 78 79 /** 80 * 校验数据中的指定字段,是否在指定范围内 81 * @param data 数据 82 * @param dataField 数据字段 83 * @param parameter 参数 84 * @param paramField 参数字段 85 * @return 校验结果 86 */ 87 public static boolean equal(String data, String dataField, 88 String parameter, String paramField) { 89 String paramFieldValue = StringUtils.getFieldFromConcatString( 90 parameter, "\\|", paramField); 91 if(paramFieldValue == null) { 92 return true; 93 } 94 95 String dataFieldValue = StringUtils.getFieldFromConcatString( 96 data, "\\|", dataField); 97 if(dataFieldValue != null) { 98 if(dataFieldValue.equals(paramFieldValue)) { 99 return true; 100 } 101 } 102 103 return false; 104 } 105 106 }