



Spark项目之电商用户行为分析大数据平台之(十)IDEA项目搭建及工具类介绍
目录
一、创建Maven项目
二、常用工具类
2.1 配置管理组建
2.2 常量的接口
2.3 时间日期工具类
2.4 数字格式化工具类
2.5 参数工具类
2.6 字符串工具类
2.7 校验工具类
正文
一、创建Maven项目
创建项目,名称为LogAnalysis
二、常用工具类
2.1 配置管理组建
ConfigurationManager.java
import java.io.InputStream;
import java.util.Properties;
/**
* 配置管理组件
*
* 1、配置管理组件可以复杂,也可以很简单,对于简单的配置管理组件来说,只要开发一个类,可以在第一次访问它的
* 时候,就从对应的properties文件中,读取配置项,并提供外界获取某个配置key对应的value的方法
* 2、如果是特别复杂的配置管理组件,那么可能需要使用一些软件设计中的设计模式,比如单例模式、解释器模式
* 可能需要管理多个不同的properties,甚至是xml类型的配置文件
* 3、我们这里的话,就是开发一个简单的配置管理组件,就可以了
*
*/
public class ConfigurationManager {
// Properties对象使用private来修饰,就代表了其是类私有的
// 那么外界的代码,就不能直接通过ConfigurationManager.prop这种方式获取到Properties对象
// 之所以这么做,是为了避免外界的代码不小心错误的更新了Properties中某个key对应的value
// 从而导致整个程序的状态错误,乃至崩溃
private static Properties prop = new Properties();
static {
try {
InputStream in = ConfigurationManager.class
.getClassLoader().getResourceAsStream("conf.properties");
prop.load(in);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取指定key对应的value
*
* @param key
* @return value
*/
public static String getProperty(String key) {
return prop.getProperty(key);
}
/**
* 获取整数类型的配置项
* @param key
* @return value
*/
public static Integer getInteger(String key) {
String value = getProperty(key);
try {
return Integer.valueOf(value);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
/**
* 获取布尔类型的配置项
* @param key
* @return value
*/
public static Boolean getBoolean(String key) {
String value = getProperty(key);
try {
return Boolean.valueOf(value);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 获取Long类型的配置项
* @param key
* @return
*/
public static Long getLong(String key) {
String value = getProperty(key);
try {
return Long.valueOf(value);
} catch (Exception e) {
e.printStackTrace();
}
return 0L;
}
2.2 常量的接口
Constants.java
/**
* 常量接口
* @author Administrator
*
*/
public interface Constants {
/**
* 项目配置相关的常量
*/
String JDBC_DRIVER = "jdbc.driver";
String JDBC_DATASOURCE_SIZE = "jdbc.datasource.size";
String JDBC_URL = "jdbc.url";
String JDBC_USER = "jdbc.user";
String JDBC_PASSWORD = "jdbc.password";
String JDBC_URL_PROD = "jdbc.url.prod";
String JDBC_USER_PROD = "jdbc.user.prod";
String JDBC_PASSWORD_PROD = "jdbc.password.prod";
String SPARK_LOCAL = "spark.local";
String SPARK_LOCAL_TASKID_SESSION = "spark.local.taskid.session";
String SPARK_LOCAL_TASKID_PAGE = "spark.local.taskid.page";
String SPARK_LOCAL_TASKID_PRODUCT = "spark.local.taskid.product";
String KAFKA_METADATA_BROKER_LIST = "kafka.metadata.broker.list";
String KAFKA_TOPICS = "kafka.topics";
/**
* Spark作业相关的常量
*/
String SPARK_APP_NAME_SESSION = "UserVisitSessionAnalyzeSpark";
String SPARK_APP_NAME_PAGE = "PageOneStepConvertRateSpark";
String FIELD_SESSION_ID = "sessionid";
String FIELD_SEARCH_KEYWORDS = "searchKeywords";
String FIELD_CLICK_CATEGORY_IDS = "clickCategoryIds";
String FIELD_AGE = "age";
String FIELD_PROFESSIONAL = "professional";
String FIELD_CITY = "city";
String FIELD_SEX = "sex";
String FIELD_VISIT_LENGTH = "visitLength";
String FIELD_STEP_LENGTH = "stepLength";
String FIELD_START_TIME = "startTime";
String FIELD_CLICK_COUNT = "clickCount";
String FIELD_ORDER_COUNT = "orderCount";
String FIELD_PAY_COUNT = "payCount";
String FIELD_CATEGORY_ID = "categoryid";
String SESSION_COUNT = "session_count";
String TIME_PERIOD_1s_3s = "1s_3s";
String TIME_PERIOD_4s_6s = "4s_6s";
String TIME_PERIOD_7s_9s = "7s_9s";
String TIME_PERIOD_10s_30s = "10s_30s";
String TIME_PERIOD_30s_60s = "30s_60s";
String TIME_PERIOD_1m_3m = "1m_3m";
String TIME_PERIOD_3m_10m = "3m_10m";
String TIME_PERIOD_10m_30m = "10m_30m";
String TIME_PERIOD_30m = "30m";
String STEP_PERIOD_1_3 = "1_3";
String STEP_PERIOD_4_6 = "4_6";
String STEP_PERIOD_7_9 = "7_9";
String STEP_PERIOD_10_30 = "10_30";
String STEP_PERIOD_30_60 = "30_60";
String STEP_PERIOD_60 = "60";
/**
* 任务相关的常量
*/
String PARAM_START_DATE = "startDate";
String PARAM_END_DATE = "endDate";
String PARAM_START_AGE = "startAge";
String PARAM_END_AGE = "endAge";
String PARAM_PROFESSIONALS = "professionals";
String PARAM_CITIES = "cities";
String PARAM_SEX = "sex";
String PARAM_KEYWORDS = "keywords";
String PARAM_CATEGORY_IDS = "categoryIds";
String PARAM_TARGET_PAGE_FLOW = "targetPageFlow";
}
2.3 时间日期工具类
DateUtils.java
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
**
* 时间日期工具类
* */
public class DateUtils {
public static final SimpleDateFormat TIME_FORMAT =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static final SimpleDateFormat DATE_FORMAT =
new SimpleDateFormat("yyyy-MM-dd");
public static final SimpleDateFormat DATEKEY_FORMAT =
new SimpleDateFormat("yyyyMMdd");
**
* 判断第一个时间是否在第二个时间之前
* */
public static boolean before(String firstTime,String secondTime){
try {
Date first = TIME_FORMAT.parse(firstTime);
Date second = TIME_FORMAT.parse(secondTime);
if(first.before(second)){
return true;
}
} catch (ParseException e) {
e.printStackTrace();
}
return false;
}
**
* 判断第一个时间是否在第二个时间之后
* */
public static boolean after(String firstTime,String secondTime){
try {
Date first = TIME_FORMAT.parse(firstTime);
Date second = TIME_FORMAT.parse(secondTime);
if(first.after(second)){
return true;
}
}catch (ParseException e){
e.printStackTrace();
}
return false;
}
**
* 计算2个时间的差值(单位为秒)
* */
public static int minus(String firstTime,String secondTime){
try {
Date first = TIME_FORMAT.parse(firstTime);
Date second = TIME_FORMAT.parse(secondTime);
long millisecond = first.getTime() - second.getTime();
return Integer.valueOf(String.valueOf(millisecond/1000));
}catch (ParseException e){
e.printStackTrace();
}
return 0;
}
**
* 获取年月日和小时
* */
public static String getDateHour(String datetime){
String date = datetime.split(" ")[0];
String hourMinuteSecond = datetime.split(" ")[1];
String hour = hourMinuteSecond.split(":")[0];
return date+"_"+hour;
}
**
* 获取当天的日期
* */
public static String getTodayDate(){
return DATE_FORMAT.format(new Date());
}
**
* 获取昨天的日期
* */
public static String getYesterdayDate(){
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DAY_OF_YEAR,-1);
Date time = calendar.getTime();
return DATE_FORMAT.format(time);
}
**
* 格式化日期(yyyy-MM-dd)
*/
public static String formatDate(Date date) {
1 return DATE_FORMAT.format(date);
1 }
1
1 /**
1 * 格式化时间(yyyy-MM-dd HH:mm:ss)
1 */
1 public static String formatTime(Date date) {
1 return TIME_FORMAT.format(date);
1 }
1
1 /**
1 * 解析时间字符串
1 */
1 public static Date parseTime(String time) {
1 try {
1 return TIME_FORMAT.parse(time);
1 } catch (ParseException e) {
1 e.printStackTrace();
1 }
1 return null;
1 }
1
1 /**
1 * 格式化日期key
1 */
1 public static String formatDateKey(Date date) {
1 return DATEKEY_FORMAT.format(date);
1 }
1
1 /**
1 * 格式化日期key
1 */
1 public static Date parseDateKey(String datekey) {
1 try {
1 return DATEKEY_FORMAT.parse(datekey);
1 } catch (ParseException e) {
1 e.printStackTrace();
1 }
1 return null;
1 }
1
1 /**
1 * 格式化时间,保留到分钟级别
1 */
1 public static String formatTimeMinute(Date date) {
1 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
1 return sdf.format(date);
1 }
1 }
2.4 数字格式化工具类
NumberUtils.java
import java.math.BigDecimal;
/**
* 数字格式化工具类
* @author Administrator
*
*/
public class NumberUtils {
/**
* 格式化小数
* @param num 字符串
* @param scale 四舍五入的位数
* @return 格式化小数
*/
public static double formatDouble(double num, int scale) {
BigDecimal bd = new BigDecimal(num);
return bd.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
2.5 参数工具类
ParamUtils.java
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bw.conf.ConfigurationManager;
import com.bw.constant.Constants;
/**
* 参数工具类
* @author Administrator
*
*/
public class ParamUtils {
/**
* 从命令行参数中提取任务id
* @param args 命令行参数
* @return 任务id
*/
public static Long getTaskIdFromArgs(String[] args, String taskType) {
boolean local = ConfigurationManager.getBoolean(Constants.SPARK_LOCAL);
if(local) {
return ConfigurationManager.getLong(taskType);
} else {
try {
if(args != null && args.length > 0) {
return Long.valueOf(args[0]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 从JSON对象中提取参数
* @param jsonObject JSON对象
* @return 参数
*/
public static String getParam(JSONObject jsonObject, String field) {
JSONArray jsonArray = jsonObject.getJSONArray(field);
if(jsonArray != null && jsonArray.size() > 0) {
return jsonArray.getString(0);
}
return null;
}
}
2.6 字符串工具类
StringUtils.java
/**
* 字符串工具类
* @author Administrator
*
*/
public class StringUtils {
/**
* 判断字符串是否为空
* @param str 字符串
* @return 是否为空
*/
public static boolean isEmpty(String str) {
return str == null || "".equals(str);
}
/**
* 判断字符串是否不为空
* @param str 字符串
* @return 是否不为空
*/
public static boolean isNotEmpty(String str) {
return str != null && !"".equals(str);
}
/**
* 截断字符串两侧的逗号
* @param str 字符串
* @return 字符串
*/
public static String trimComma(String str) {
if(str.startsWith(",")) {
str = str.substring(1);
}
if(str.endsWith(",")) {
str = str.substring(0, str.length() - 1);
}
return str;
}
/**
* 补全两位数字
* @param str
* @return
*/
public static String fulfuill(String str) {
if(str.length() == 2) {
return str;
} else {
return "0" + str;
}
}
/**
* 从拼接的字符串中提取字段
* @param str 字符串
* @param delimiter 分隔符
* @param field 字段
* @return 字段值
*/
public static String getFieldFromConcatString(String str,
String delimiter, String field) {
try {
String[] fields = str.split(delimiter);
for(String concatField : fields) {
// searchKeywords=|clickCategoryIds=1,2,3
if(concatField.split("=").length == 2) {
String fieldName = concatField.split("=")[0];
String fieldValue = concatField.split("=")[1];
if(fieldName.equals(field)) {
return fieldValue;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 从拼接的字符串中给字段设置值
* @param str 字符串
* @param delimiter 分隔符
* @param field 字段名
* @param newFieldValue 新的field值
* @return 字段值
*/
public static String setFieldInConcatString(String str,
String delimiter, String field, String newFieldValue) {
String[] fields = str.split(delimiter);
for(int i = 0; i < fields.length; i++) {
String fieldName = fields[i].split("=")[0];
if(fieldName.equals(field)) {
String concatField = fieldName + "=" + newFieldValue;
fields[i] = concatField;
break;
}
}
StringBuffer buffer = new StringBuffer("");
for(int i = 0; i < fields.length; i++) {
buffer.append(fields[i]);
if(i < fields.length - 1) {
buffer.append("|");
}
}
return buffer.toString();
}
}
2.7 校验工具类
ValidUtils.java
/**
* 校验工具类
* @author Administrator
*
*/
public class ValidUtils {
/**
* 校验数据中的指定字段,是否在指定范围内
* @param data 数据
* @param dataField 数据字段
* @param parameter 参数
* @param startParamField 起始参数字段
* @param endParamField 结束参数字段
* @return 校验结果
*/
public static boolean between(String data, String dataField,
String parameter, String startParamField, String endParamField) {
String startParamFieldStr = StringUtils.getFieldFromConcatString(
parameter, "\\|", startParamField);
String endParamFieldStr = StringUtils.getFieldFromConcatString(
parameter, "\\|", endParamField);
if(startParamFieldStr == null || endParamFieldStr == null) {
return true;
}
int startParamFieldValue = Integer.valueOf(startParamFieldStr);
int endParamFieldValue = Integer.valueOf(endParamFieldStr);
String dataFieldStr = StringUtils.getFieldFromConcatString(
data, "\\|", dataField);
if(dataFieldStr != null) {
int dataFieldValue = Integer.valueOf(dataFieldStr);
if(dataFieldValue >= startParamFieldValue &&
dataFieldValue <= endParamFieldValue) {
return true;
} else {
return false;
}
}
return false;
}
/**
* 校验数据中的指定字段,是否有值与参数字段的值相同
* @param data 数据
* @param dataField 数据字段
* @param parameter 参数
* @param paramField 参数字段
* @return 校验结果
*/
public static boolean in(String data, String dataField,
String parameter, String paramField) {
String paramFieldValue = StringUtils.getFieldFromConcatString(
parameter, "\\|", paramField);
if(paramFieldValue == null) {
return true;
}
String[] paramFieldValueSplited = paramFieldValue.split(",");
String dataFieldValue = StringUtils.getFieldFromConcatString(
data, "\\|", dataField);
if(dataFieldValue != null) {
String[] dataFieldValueSplited = dataFieldValue.split(",");
for(String singleDataFieldValue : dataFieldValueSplited) {
for(String singleParamFieldValue : paramFieldValueSplited) {
if(singleDataFieldValue.equals(singleParamFieldValue)) {
return true;
}
}
}
}
return false;
}
/**
* 校验数据中的指定字段,是否在指定范围内
* @param data 数据
* @param dataField 数据字段
* @param parameter 参数
* @param paramField 参数字段
* @return 校验结果
*/
public static boolean equal(String data, String dataField,
String parameter, String paramField) {
String paramFieldValue = StringUtils.getFieldFromConcatString(
parameter, "\\|", paramField);
if(paramFieldValue == null) {
return true;
}
String dataFieldValue = StringUtils.getFieldFromConcatString(
data, "\\|", dataField);
if(dataFieldValue != null) {
if(dataFieldValue.equals(paramFieldValue)) {
return true;
}
}
return false;
}
}
Spark项目之电商用户行为分析大数据平台之(十一)JSON及FASTJSON
目录
一、概述
二、JSON的结构
2.1 简单值
2.2 对象
2.3 数组
三、JSON详解
四、FastJson
正文
一、概述
JSON的全称是”JavaScript Object Notation”,意思是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式。XML也是一种数据交换格式,为什么没 有选择XML呢?因为XML虽然可以作为跨平台的数据交换格式,但是在JS(JavaScript的简写)中处理XML非常不方便,同时XML标记比数据 多,增加了交换产生的流量,而JSON没有附加的任何标记,在JS中可作为对象处理,所以我们更倾向于选择JSON来交换数据。这篇文章主要从以下几个方 面来说明JSON。
二、JSON的结构
2.1 简单值
简单值使用与javascript相同的语法,可以在JSON中表示字符串、数值、布尔值和null
字符串必须使用双引号表示,不能使用单引号。数值必须以十进制表示,且不能使用NaN和Infinity
[注意]JSON不支持javascript中的特殊值undefined
//合格的简单值5"hello world"truenull复制

//不合格的简单值+0x1'hello world'undefined NaN Infinity复制

2.2 对象
对象作为一种复杂数据类型,表示的是一组有序的键值对儿。而每个键值对儿中的值可以是简单值,也可以是复杂数据类型的值(其中关键字是字符串,而值可以是字符串,数值,true,false,null,对象或数组)
与javascript的对象字面量相比,JSON有三个不同的地方
1、JSON没有变量的概念
2、JSON中,对象的键名必须放在双引号里面
3、因为JSON不是javascript语句,所以没有末尾的分号
[注意]同一个对象中不应该出现两个同名属性

//合格的对象{ "name":"huochai", "age":29, "school":{ "name":"diankeyuan", "location":"beijing" } }复制


//不合格的对象{ name: "张三", 'age': 32 }//属性名必须使用双引号{};//不需要末尾的分号{ "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'), "getName": function() { return this.name; } } // 不能使用函数和日期对象复制

2.3 数组
数组也是一种复杂数据类型,表示一组有序的值的列表,可以通过数值索引来访问其中的值。数组的值也可以是任意类型——简单值、对象或数组
JSON数组也没有变量和分号,把数组和对象结合起来,可以构成更复杂的数据集合
[注意]数组或对象最后一个成员的后面,不能加逗号

[ { key1:value1, key2:value2 }, { key3:value3, key4:value4 } ]复制

三、JSON详解
JSON详解
JSON的全称是”JavaScript Object Notation”,意思是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式。XML也是一种数据交换格式,为什么没 有选择XML呢?因为XML虽然可以作为跨平台的数据交换格式,但是在JS(JavaScript的简写)中处理XML非常不方便,同时XML标记比数据 多,增加了交换产生的流量,而JSON没有附加的任何标记,在JS中可作为对象处理,所以我们更倾向于选择JSON来交换数据。这篇文章主要从以下几个方 面来说明JSON。
1,JSON的两种结构
2,认识JSON字符串
3,在JS中如何使用JSON
4,在.NET中如何使用JSON
5,总结
{ key1:value1, key2:value2, ... }复制
其中关键字是字符串,而值可以是字符串,数值,true,false,null,对象或数组
数组结构以”[”开始,”]”结束。中间由0或多个以”,”分隔的值列表组成,语法结构如代码。

[ { key1:value1, key2:value2 }, { key3:value3, key4:value4 } ]复制

认识JSON字符串
之前我一直有个困惑,分不清普通字符串,json字符串和json对象的区别。经过一番研究终于给弄明白了。比如在js中。
字符串:这个很好解释,指使用“”双引号或’’单引号包括的字符。例如:var comStr = 'this is string';
json字符串:指的是符合json格式要求的js字符串。例如:var jsonStr = "{StudentID:'100',Name:'tmac',Hometown:'usa'}";
json对象:指符合json格式要求的js对象。例如:var jsonObj = { StudentID: "100", Name: "tmac", Hometown: "usa" };

var obj = { 1: "value1", "2": "value2", count: 3, person: [ //数组结构JSON对象,可以嵌套使用 { id: 1, name: "张三" }, { id: 2, name: "李四" } ], object: { //对象结构JSON对象 id: 1, msg: "对象里的对象" } };复制

1,从JSON中读数据

function ReadJSON() { alert(obj.1); //会报语法错误,可以用alert(obj["1"]);说明数字最好不要做关键字 alert(obj.2); //同上 alert(obj.person[0].name); //或者alert(obj.person[0]["name"]) alert(obj.object.msg); //或者alert(obj.object["msg"]) }复制

2,向JSON中写数据
比如要往JSON中增加一条数据,代码如下:
增加数据后的JSON对象如图:
3,修改JSON中的数据
我们现在要修改JSON中count的值,代码如下:
修改后的JSON如图。
4,删除JSON中的数据
我们现在实现从JSON中删除count这条数据,代码如下:
删除后的JSON如图
可以看到count已经从JSON对象中被删除了。
5,遍历JSON对象
可以使用for…in…循环来遍历JSON对象中的数据,比如我们要遍历输出obj对象的值,代码如下:
程序输出结果为:
.NET,它是一个非常著名的在.net中处理JSON的工具,我们最常用的是下面两个功能。
1,通过序列化将.net对象转换为JSON字符串
在web开发过程中,我们经常需要将从数据库中 查询到的数据(一般为一个集合,列表或数组等)转换为JSON格式字符串传回客户端,这就需要进行序列化,这里用到的是JsonConvert对象的 SerializeObject方法。其语法格式为:JsonConvert.SerializeObject(object),代码中 的”object”就是要序列化的.net对象,序列化后返回的是json字符串。
比如,现在我们有一个TStudent的学生表,表中的字段和已有数据如图所示
从表中我们可以看到一共有五条数据,现在我们要从数据库中取出这些数据,然后利用JSON.Net的JsonConvert对象序列化它们为json字符串,并显示在页面上。C#代码如下

protected void Page_Load(object sender, EventArgs e) { using (L2SDBDataContext db = new L2SDBDataContext()) { List<Student> studentList = new List<Student>(); var query = from s in db.TStudents select new { StudentID=s.StudentID, Name=s.Name, Hometown=s.Hometown, Gender=s.Gender, Brithday=s.Birthday, ClassID=s.ClassID, Weight=s.Weight, Height=s.Height, Desc=s.Desc }; foreach (var item in query) { Student student = new Student { StudentID=item.StudentID,Name=item.Name,Hometown=item.Hometown,Gender=item.Gender,Brithday=item.Brithday,ClassID=item.ClassID,Weight=item.Weight,Height=item.Height,Desc=item.Desc}; studentList.Add(student); } lbMsg.InnerText = JsonConvert.SerializeObject(studentList); } }复制

输出结果
从图中我们可以看到,数据库中的5条记录全部取出来并转化为json字符串了。
2,使用LINQ to JSON定制JSON数据
使用JsonConvert对象的SerializeObject只是简单地将一个list或 集合转换为json字符串。但是,有的时候我们的前端框架比如ExtJs对服务端返回的数据格式是有一定要求的,比如下面的数据格式,这时就需要用到 JSON.NET的LINQ to JSON,LINQ to JSON的作用就是根据需要的格式来定制json数据。
比如经常用在分页的json格式如代码:
使用LINQ to JSON前,需要引用Newtonsoft.Json的dll和using Newtonsoft.Json.Linq的命名空间。LINQ to JSON主要使用到JObject, JArray, JProperty和JValue这四个对象,JObject用来生成一个JSON对象,简单来说就是生成”{}”,JArray用来生成一个JSON数 组,也就是”[]”,JProperty用来生成一个JSON数据,格式为key/value的值,而JValue则直接生成一个JSON值。下面我们就 用LINQ to JSON返回上面分页格式的数据。代码如下:

protected void Page_Load(object sender, EventArgs e) { using (L2SDBDataContext db = new L2SDBDataContext()) { //从数据库中取出数据并放到列表list中 List<Student> studentList = new List<Student>(); var query = from s in db.TStudents select new { StudentID = s.StudentID, Name = s.Name, Hometown = s.Hometown, Gender = s.Gender, Brithday = s.Birthday, ClassID = s.ClassID, Weight = s.Weight, Height = s.Height, Desc = s.Desc }; foreach (var item in query) { Student student = new Student { StudentID = item.StudentID, Name = item.Name, Hometown = item.Hometown, Gender = item.Gender, Brithday = item.Brithday, ClassID = item.ClassID, Weight = item.Weight, Height = item.Height, Desc = item.Desc }; studentList.Add(student); } //基于创建的list使用LINQ to JSON创建期望格式的JSON数据 lbMsg.InnerText = new JObject( new JProperty("total",studentList.Count), new JProperty("rows", new JArray( //使用LINQ to JSON可直接在select语句中生成JSON数据对象,无须其它转换过程 from p in studentList select new JObject( new JProperty("studentID",p.StudentID), new JProperty("name",p.Name), new JProperty("homeTown",p.Hometown) ) ) ) ).ToString(); } }复制

输出结果为:
3,处理客户端提交的JSON数据
客户端提交过来的数据一般都是json字符串,有了更好地进行操作(面向对象的方式),所以我们一般都会想办法将json字符串转换为json对象。例如客户端提交了以下数组格式json字符串。
在服务端就可以使用JObject或JArray的Parse方法轻松地将json字符串转换为json对象,然后通过对象的方式提取数据。下面是服务端代码。

protected void Page_Load(object sender, EventArgs e) { string inputJsonString = @" [ {StudentID:'100',Name:'aaa',Hometown:'china'}, {StudentID:'101',Name:'bbb',Hometown:'us'}, {StudentID:'102',Name:'ccc',Hometown:'england'} ]"; JArray jsonObj = JArray.Parse(inputJsonString); string message = @"<table border='1'> <tr><td width='80'>StudentID</td><td width='100'>Name</td><td width='100'>Hometown</td></tr>"; string tpl = "<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>"; foreach (JObject jObject in jsonObj) { message += String.Format(tpl, jObject["StudentID"], jObject["Name"],jObject["Hometown"]); } message += "</table>"; lbMsg.InnerHtml = message; }复制

输出结果:
当然,服务端除了使用LINQ to JSON来转换json字符串外,也可以使用JsonConvert的DeserializeObject方法。如下面代码实现上面同样的功能。
四、FastJson
FastJson对于JSON格式字符串、JSON对象及JavaBean之间的相互转换
fastJson对于json格式字符串的解析主要用到了一下三个类:
JSON:fastJson的解析器,用于JSON格式字符串与JSON对象及javaBean之间的转换。
JSONObject:fastJson提供的json对象。
JSONArray:fastJson提供json数组对象。
我们可以把JSONObject当成一个Map<String,Object>来看,只是JSONObject提供了更为丰富便捷的方法,方便我们对于对象属性的操作。我们看一下源码。
同样我们可以把JSONArray当做一个List<Object>,可以把JSONArray看成JSONObject对象的一个集合。
此外,由于JSONObject和JSONArray继承了JSON,所以说也可以直接使用两者对JSON格式字符串与JSON对象及javaBean之间做转换,不过为了避免混淆我们还是使用JSON。
首先定义三个json格式的字符串,作为我们的数据源。

//json字符串-简单对象型private static final String JSON_OBJ_STR = "{\"studentName\":\"lily\",\"studentAge\":12}";//json字符串-数组类型private static final String JSON_ARRAY_STR = "[{\"studentName\":\"lily\",\"studentAge\":12},{\"studentName\":\"lucy\",\"studentAge\":15}]";//复杂格式json字符串private static final String COMPLEX_JSON_STR = "{\"teacherName\":\"crystall\",\"teacherAge\":27,\"course\":{\"courseName\":\"english\",\"code\":1270},\"students\":[{\"studentName\":\"lily\",\"studentAge\":12},{\"studentName\":\"lucy\",\"studentAge\":15}]}";复制

示例1:JSON格式字符串与JSON对象之间的转换。
示例1.1-json字符串-简单对象型与JSONObject之间的转换

/** * json字符串-简单对象型与JSONObject之间的转换 */ public static void testJSONStrToJSONObject(){ JSONObject jsonObject = JSON.parseObject(JSON_OBJ_STR); //JSONObject jsonObject1 = JSONObject.parseObject(JSON_OBJ_STR); //因为JSONObject继承了JSON,所以这样也是可以的 System.out.println(jsonObject.getString("studentName")+":"+jsonObject.getInteger("studentAge")); }复制

示例1.2-json字符串-数组类型与JSONArray之间的转换

/** * json字符串-数组类型与JSONArray之间的转换 */ public static void testJSONStrToJSONArray(){ JSONArray jsonArray = JSON.parseArray(JSON_ARRAY_STR); //JSONArray jsonArray1 = JSONArray.parseArray(JSON_ARRAY_STR);//因为JSONArray继承了JSON,所以这样也是可以的 //遍历方式1 int size = jsonArray.size(); for (int i = 0; i < size; i++){ JSONObject jsonObject = jsonArray.getJSONObject(i); System.out.println(jsonObject.getString("studentName")+":"+jsonObject.getInteger("studentAge")); } //遍历方式2 for (Object obj : jsonArray) { JSONObject jsonObject = (JSONObject) obj; System.out.println(jsonObject.getString("studentName")+":"+jsonObject.getInteger("studentAge")); } }复制

示例1.3-复杂json格式字符串与JSONObject之间的转换

/** * 复杂json格式字符串与JSONObject之间的转换 */ public static void testComplexJSONStrToJSONObject(){ JSONObject jsonObject = JSON.parseObject(COMPLEX_JSON_STR); //JSONObject jsonObject1 = JSONObject.parseObject(COMPLEX_JSON_STR);//因为JSONObject继承了JSON,所以这样也是可以的 String teacherName = jsonObject.getString("teacherName"); Integer teacherAge = jsonObject.getInteger("teacherAge"); JSONObject course = jsonObject.getJSONObject("course"); JSONArray students = jsonObject.getJSONArray("students"); }复制

示例2:JSON格式字符串与javaBean之间的转换。
首先,我们针对数据源所示的字符串,提供三个javaBean。

public class Student { private String studentName; private Integer studentAge; public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public Integer getStudentAge() { return studentAge; } public void setStudentAge(Integer studentAge) { this.studentAge = studentAge; } }复制


public class Course { private String courseName; private Integer code; public String getCourseName() { return courseName; } public void setCourseName(String courseName) { this.courseName = courseName; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }复制


public class Teacher { private String teacherName; private Integer teacherAge; private Course course; private List<Student> students; public String getTeacherName() { return teacherName; } public void setTeacherName(String teacherName) { this.teacherName = teacherName; } public Integer getTeacherAge() { return teacherAge; } public void setTeacherAge(Integer teacherAge) { this.teacherAge = teacherAge; } public Course getCourse() { return course; } public void setCourse(Course course) { this.course = course; } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } }复制

json字符串与javaBean之间的转换推荐使用 TypeReference<T> 这个类,使用泛型可以更加清晰,当然也有其它的转换方式,这里就不做探讨了。
示例2.1-json字符串-简单对象型与javaBean之间的转换

** * json字符串-简单对象与JavaBean_obj之间的转换 */ public static void testJSONStrToJavaBeanObj(){ Student student = JSON.parseObject(JSON_OBJ_STR, new TypeReference<Student>() {}); //Student student1 = JSONObject.parseObject(JSON_OBJ_STR, new TypeReference<Student>() {});//因为JSONObject继承了JSON,所以这样也是可以的 System.out.println(student.getStudentName()+":"+student.getStudentAge()); }复制

示例2.2-json字符串-数组类型与javaBean之间的转换

/** * json字符串-数组类型与JavaBean_List之间的转换 */ public static void testJSONStrToJavaBeanList(){ ArrayList<Student> students = JSON.parseObject(JSON_ARRAY_STR, new TypeReference<ArrayList<Student>>() {}); //ArrayList<Student> students1 = JSONArray.parseObject(JSON_ARRAY_STR, new TypeReference<ArrayList<Student>>() {});//因为JSONArray继承了JSON,所以这样也是可以的 for (Student student : students) { System.out.println(student.getStudentName()+":"+student.getStudentAge()); } }复制

示例2.3-复杂json格式字符串与与javaBean之间的转换

/** * 复杂json格式字符串与JavaBean_obj之间的转换 */ public static void testComplexJSONStrToJavaBean(){ Teacher teacher = JSON.parseObject(COMPLEX_JSON_STR, new TypeReference<Teacher>() {}); //Teacher teacher1 = JSON.parseObject(COMPLEX_JSON_STR, new TypeReference<Teacher>() {});//因为JSONObject继承了JSON,所以这样也是可以的 String teacherName = teacher.getTeacherName(); Integer teacherAge = teacher.getTeacherAge(); Course course = teacher.getCourse(); List<Student> students = teacher.getStudents(); }复制

对于TypeReference<T>,由于其构造方法使用 protected 进行修饰,所以在其他包下创建其对象的时候,要用其实现类的子类:new TypeReference<Teacher>() {}
此外的:
1,对于JSON对象与JSON格式字符串的转换可以直接用 toJSONString()这个方法。
2,javaBean与JSON格式字符串之间的转换要用到:JSON.toJSONString(obj);
3,javaBean与json对象间的转换使用:JSON.toJSON(obj),然后使用强制类型转换,JSONObject或者JSONArray。
Spark项目之电商用户行为分析大数据平台之(十二)Spark上下文构建及模拟数据生成
目录
一、模拟生成数据
二、构建Spark上下文
三、打印的测试数据
3.1 user_visit_action
3.2 user_info
3.3 product_info
正文
一、模拟生成数据
package com.bw.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import com.bw.util.DateUtils;
import com.bw.util.StringUtils;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructType;
/**
* 模拟数据程序
* @author Administrator
*
*/
public class MockData {
/**
* 模拟数据
* @param sc
* @param sqlContext
*/
public static void mock(JavaSparkContext sc,
SQLContext sqlContext) {
List<Row> rows = new ArrayList<Row>();
String[] searchKeywords = new String[] {"火锅", "蛋糕", "重庆辣子鸡", "重庆小面",
"呷哺呷哺", "新辣道鱼火锅", "国贸大厦", "太古商场", "日本料理", "温泉"};
String date = DateUtils.getTodayDate();
String[] actions = new String[]{"search", "click", "order", "pay"};
Random random = new Random();
for(int i = 0; i < 100; i++) {
//生产100个userID
long userid = random.nextInt(100);
for(int j = 0; j < 10; j++) {
//每个userID有10个sessionID
String sessionid = UUID.randomUUID().toString().replace("-", "");
String baseActionTime = date + " " + random.nextInt(23);
Long clickCategoryId = null;
//每个sessionID可能会做0-100之间的action操作
for(int k = 0; k < random.nextInt(100); k++) {
long pageid = random.nextInt(10);
String actionTime = baseActionTime + ":" + StringUtils.fulfuill(String.valueOf(random.nextInt(59))) + ":" + StringUtils.fulfuill(String.valueOf(random.nextInt(59)));
String searchKeyword = null;
Long clickProductId = null;
String orderCategoryIds = null;
String orderProductIds = null;
String payCategoryIds = null;
String payProductIds = null;
String action = actions[random.nextInt(4)];
if("search".equals(action)) {
searchKeyword = searchKeywords[random.nextInt(10)];
} else if("click".equals(action)) {
if(clickCategoryId == null) {
clickCategoryId = Long.valueOf(String.valueOf(random.nextInt(100)));
}
clickProductId = Long.valueOf(String.valueOf(random.nextInt(100)));
} else if("order".equals(action)) {
orderCategoryIds = String.valueOf(random.nextInt(100));
orderProductIds = String.valueOf(random.nextInt(100));
} else if("pay".equals(action)) {
payCategoryIds = String.valueOf(random.nextInt(100));
payProductIds = String.valueOf(random.nextInt(100));
}
Row row = RowFactory.create(date, userid, sessionid,
pageid, actionTime, searchKeyword,
clickCategoryId, clickProductId,
orderCategoryIds, orderProductIds,
payCategoryIds, payProductIds,
Long.valueOf(String.valueOf(random.nextInt(10))));
rows.add(row);
}
}
}
JavaRDD<Row> rowsRDD = sc.parallelize(rows);
StructType schema = DataTypes.createStructType(Arrays.asList(
DataTypes.createStructField("date", DataTypes.StringType, true),
DataTypes.createStructField("user_id", DataTypes.LongType, true),
DataTypes.createStructField("session_id", DataTypes.StringType, true),
DataTypes.createStructField("page_id", DataTypes.LongType, true),
DataTypes.createStructField("action_time", DataTypes.StringType, true),
DataTypes.createStructField("search_keyword", DataTypes.StringType, true),
DataTypes.createStructField("click_category_id", DataTypes.LongType, true),
DataTypes.createStructField("click_product_id", DataTypes.LongType, true),
DataTypes.createStructField("order_category_ids", DataTypes.StringType, true),
DataTypes.createStructField("order_product_ids", DataTypes.StringType, true),
DataTypes.createStructField("pay_category_ids", DataTypes.StringType, true),
DataTypes.createStructField("pay_product_ids", DataTypes.StringType, true),
DataTypes.createStructField("city_id", DataTypes.LongType, true)));
DataFrame df = sqlContext.createDataFrame(rowsRDD, schema);
df.registerTempTable("user_visit_action");
for(Row _row : df.take(1)) {
System.out.println(_row);
}
/**
* ==================================================================
*/
rows.clear();
String[] sexes = new String[]{"male", "female"};
for(int i = 0; i < 100; i ++) {
long userid = i;
String username = "user" + i;
String name = "name" + i;
int age = random.nextInt(60);
String professional = "professional" + random.nextInt(100);
String city = "city" + random.nextInt(100);
String sex = sexes[random.nextInt(2)];
Row row = RowFactory.create(userid, username, name, age,
professional, city, sex);
rows.add(row);
}
rowsRDD = sc.parallelize(rows);
StructType schema2 = DataTypes.createStructType(Arrays.asList(
DataTypes.createStructField("user_id", DataTypes.LongType, true),
DataTypes.createStructField("username", DataTypes.StringType, true),
DataTypes.createStructField("name", DataTypes.StringType, true),
DataTypes.createStructField("age", DataTypes.IntegerType, true),
DataTypes.createStructField("professional", DataTypes.StringType, true),
DataTypes.createStructField("city", DataTypes.StringType, true),
DataTypes.createStructField("sex", DataTypes.StringType, true)));
DataFrame df2 = sqlContext.createDataFrame(rowsRDD, schema2);
for(Row _row : df2.take(1)) {
System.out.println(_row);
}
df2.registerTempTable("user_info");
/**
* ==================================================================
*/
rows.clear();
int[] productStatus = new int[]{0, 1};
for(int i = 0; i < 100; i ++) {
long productId = i;
String productName = "product" + i;
String extendInfo = "{\"product_status\": " + productStatus[random.nextInt(2)] + "}";
Row row = RowFactory.create(productId, productName, extendInfo);
rows.add(row);
}
rowsRDD = sc.parallelize(rows);
StructType schema3 = DataTypes.createStructType(Arrays.asList(
DataTypes.createStructField("product_id", DataTypes.LongType, true),
DataTypes.createStructField("product_name", DataTypes.StringType, true),
DataTypes.createStructField("extend_info", DataTypes.StringType, true)));
DataFrame df3 = sqlContext.createDataFrame(rowsRDD, schema3);
for(Row _row : df3.take(1)) {
System.out.println(_row);
}
df3.registerTempTable("product_info");
}
}
二、构建Spark上下文
import com.bw.conf.ConfigurationManager;
import com.bw.constant.Constants;
import com.bw.test.MockData;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.sql.SQLContext;
/**
* 用户访问session分析Spark作业
*
* */
public class UserVisitSessionAnalyzeSpark {
public static void main(String[] args) {
//构建Spark上下文
SparkConf sparkConf = new SparkConf();
//Spark作业本地运行
sparkConf.setMaster("local");
//为了符合大型企业的开发需求,不能出现硬编码,创建一个Constants接口类,定义一些常量
sparkConf.setAppName(Constants.SPARK_APP_NAME_SESSION);
JavaSparkContext jsc = new JavaSparkContext(sparkConf);
SQLContext sqlContext = new SQLContext(jsc);
mockData(jsc,sqlContext);
jsc.stop();
}
/**
* 生成模拟数据(只有本地模式,才会去生成模拟数据)
* @param sc
* @param sqlContext
*/
private static void mockData(JavaSparkContext sc, SQLContext sqlContext) {
boolean local = ConfigurationManager.getBoolean(Constants.SPARK_LOCAL);
if(local) {
MockData.mock(sc, sqlContext);
}
}
}
三、打印的测试数据
3.1 user_visit_action
用户下的订单
[2018-05-23,34,4ad62c0824194e5687467bb84b9beeb9,3,2018-05-23 18:27:37,null,null,null,null,null,8,64,8]复制
3.2 user_info
[0,user0,name0,26,professional11,city4,male]复制
3.3 product_info
[0,product0,{"product_status": 1}]复制
