2022Flink大数据比赛项目-焦点科技大数据编程大赛

news/2024/5/15 4:00:57/文章来源:https://blog.csdn.net/a284365/article/details/128077887

文章目录

  • 0.数据获取
  • 1.需求概要
  • 2.数据标准
    • 2.1.输入数据格式
    • 2.2.输出数据格式
    • 2.3.数据主键及关系
  • 3.表详细
    • 1.order_info
    • 2.bill_info
    • 3.bill_item
    • 4.ord_pay
    • 5.ord_pay_log
    • 6.pay_method
    • 7.pay_bank_card
  • 4.开发工具、语言版本、工具版本
  • 5.赛题解答
    • 数据分流
    • 任务1
    • 任务2
    • 任务3
    • 小结
  • 附录

0.数据获取

链接: https://pan.baidu.com/s/1NlmbN1cX4K9jYbYQm-IJUw 提取码: qw12
本项目适合有一定flink经验的同学学习或者巩固基础、提升使用。

1.需求概要

在实际的市场交易中为了防范银行卡信息泄露,需要风控系统对存在所有用户操作进行监控,对存在潜在风险的行为进行及时告警。以下是具体风控规则:
规则1:单个用户在一天内,付款超过1万元
源数据:order_info
规则2:在绑卡操作中发现2个不同用户绑定了同一张银行卡;
源数据:pay_method,pay_bank_card
规则3:在付款过程中,发现单个用户在5分钟内使用了10张以上的银行卡付款;
源数据:全部7张表

2.数据标准

2.1.输入数据格式

实际环境下,各数据会以JSON格式组成,发送到Kafka的一个topic里;此次比赛提供了一个Source 文件用来模拟现实的数据生成。

2.2.输出数据格式

经过计算触发了风控规则告警的以JSON格式在控制台输出

字段名 字段英文名 数据类型 内容描述
风控规则ID risk_id String 触发告警的风控规则序号,如发现不同账户绑定了同一张银行卡时,规则ID输出”1“
风控描述 risk_msg String 触发规则内容描述,如:发现不同账户绑定了同一张银行卡时,内容可以为 “不同账户绑定了同一张银行卡!user_id:userId1, userId2,card_no:1234567890123”
买家用户ID b_user_id Array[String] 触发风控买家用户ID,可能有多个

例:{“risk_id”:“1”,“risk_msg”:“不同账户绑定了同一张银行卡!user_id:userId1, userId2;card_no:1234567890123”,“b_user_id”:[“12345678”, “987654321”]}

2.3.数据主键及关系

在这里插入图片描述

3.表详细

1.order_info

字段名 字段说明 字段类型 是否业务主键 备注
ORDER_ID 订单ID String PK
B_USER_ID 买家用户id String
TOTAL_PAY 支付金额 Double
ORD_STATUS 订单状态 String 1-未支付 2-已支付 3-待发货 4-配送中 5-已完成 6-未支付已关闭
ADDER_NO 添加人id String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 更新人id String
UPDATER_NAME 更新人姓名 String
UPDATE_TIME 更新时间 Timestamp

2.bill_info

字段名 字段说明 字段类型 是否业务主键 备注
BILL_ID 账单ID String PK
S_USER_ID 卖家用户ID String
B_USER_ID 买家用户ID String
ORDER_ID 关联的订单ID String 商品订单ORDER_INFO、平台服务订单SER_ORD_PF、收费计划订单PRICE_PLAN_ORD
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 更新人编号 String
UPDATER_NAME 更新人姓名 String
UPDATE_TIME 更新时间 Timestamp

3.bill_item

字段名 字段说明 字段类型 是否业务主键 备注
BILL_ITEM_ID 账单明细ID String PK
BILL_ID 账单ID String
ORD_PAY_ID 支付订单号 String
ORD_PAY_BATCH_ID 支付批次号 String
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 更新人编号 String
UPDATER_NAME 更新人姓名 String
UPDATE_TIME 更新时间 Timestamp

4.ord_pay

字段名 字段说明 字段类型 是否业务主键 备注
ORD_PAY_ID 主键 String PK
ORD_PAY_BATCH_ID 订单给的批次号 String 表 ORD_PAY_BATCH表的主键
B_USER_ID 买家的编号 String ORD_INFO表的B_USER_ID
PAY_METHOD_ID 支付方式id String 关联PAY_METHOD表主键
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 修改人编号 String
UPDATER_NAME 修改人姓名 String
UPDATE_TIME 修改时间 Timestamp

5.ord_pay_log

字段名 字段说明 字段类型 是否业务主键 备注
ORD_PAY_LOG_ID 主键 String PK
ORD_PAY_ID ORD_PAY 表主键 String 表ORD_PAY 表主键
ORD_PAY_BATCH_ID 订单给的批次号 String 表 ORD_PAY_BATCH表的主键
B_USER_ID 买家的编号 String ORD_INFO表的B_USER_ID
PAY_METHOD_ID 支付方式id String 关联PAY_METHOD表主键
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 修改人编号 String
UPDATER_NAME 修改人姓名 String
UPDATE_TIME 修改时间 Timestamp

6.pay_method

字段名 字段说明 字段类型 是否业务主键 备注
PAY_METHOD_ID 支付方式id String PK
PAY_TYPE_FLAG 支付种类标识 String 0 卡
PAY_RELATE_ID 支付方式id(卡或账户id) String 关联PAY_BANK_CARD的主键
B_USER_ID 用户ID,USER_INFO表的PK String
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 修改人编号 String
UPDATER_NAME 修改人姓名 String
UPDATE_TIME 修改时间 Timestamp

7.pay_bank_card

字段名 字段说明 字段类型 是否业务主键 备注
PAY_BANK_CARD_ID 主键 PK String PK
B_USER_ID 用户id String
CARD_NO 用户填写的银行卡号 String
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 修改人编号 String
UPDATER_NAME 修改人姓名 String
UPDATE_TIME 修改时间 Timestamp

4.开发工具、语言版本、工具版本

IDE:idea
scala sdk 2.12.11
java jdk 1.8
flink 1.13.0

5.赛题解答

以下解答,只是我个人的一些解答方案,仅供参考。如果你有好的建议,可以在评论区告诉我。
相应的POJO类见6附录

数据分流

将表进行整理后得到如下有用信息

  表               字段order_info       ORDER_ID,B_USER_ID,TOTAL_PAY,ADD_TIMEbill_info        BILL_ID,ORDER_IDbill_item        BILL_ID,ORD_PAY_IDorder_pay        ORD_PAY_ID,PAY_METHOD_IDpay_method       PAY_METHOD_ID,PAY_RELATE_IDpay_bank_card    PAY_BANK_CARD_ID,B_USER_ID,CARD_NO

数据分流,将多信息流从发送流中分离出来。

 		//支付银行卡流(pay_method,pay_bank_card)OutputTag<PayCard> payCardOutputTag = new OutputTag<PayCard>("paycard") {};//订单流OutputTag<BillInfo> billInfoOutputTag = new OutputTag<BillInfo>("billinfo") {};//订单明细流OutputTag<BillItem> billItemOutputTag = new OutputTag<BillItem>("billitem") {};//订单支付流OutputTag<OrderPay> orderPayOutputTag = new OutputTag<OrderPay>("orderpay") {};//订单支付日志流OutputTag<OrderPayLog> orderPayLogOutputTag = new OutputTag<OrderPayLog>("orderpaylog") {};//支付主流costStream(orderId,bUserId,totalPay,addTime)SingleOutputStreamOperator<OrderInfo> costStream = inputStream.process(new ProcessFunction<String, OrderInfo>()  {@Overridepublic void processElement(String s, Context context, Collector<OrderInfo> collector) throws Exception {JSONObject jsonObject1 = JSONObject.parseObject(s);String orderInfo = jsonObject1.getString("order_info");String payMethod = jsonObject1.getString("pay_method");String payBankCard = jsonObject1.getString("pay_bank_card");String billInfo = jsonObject1.getString("bill_info");String billItem = jsonObject1.getString("bill_item");String orderPay = jsonObject1.getString("ord_pay");String orderPayLog = jsonObject1.getString("ord_pay_log");if (null != orderInfo) {JSONObject orderJson = JSONObject.parseObject(orderInfo);Integer status=orderJson.getInteger("ORD_STATUS");//只需要已支付状态的数据if(status==2) {collector.collect(new OrderInfo(orderJson.getString("ORDER_ID"), orderJson.getString("B_USER_ID"), orderJson.getDouble("TOTAL_PAY"), orderJson.getString("ADD_TIME")));}} else if (null != payMethod) {JSONObject payCardJson = JSONObject.parseObject(payMethod);String payMethodId = payCardJson.getString("PAY_METHOD_ID");String payBankCardId = payCardJson.getString("PAY_RELATE_ID");//等于0,则为卡.如果对应的支付方式是卡,那么我们将cardNO加入支付银行卡流中if(payCardJson.getInteger("PAY_TYPE_FLAG")==0){if(checkPayIsCard.containsKey(payBankCardId)) {//设置payMethodIdPayCard payCard = checkPayIsCard.get(payBankCardId);payCard.setPayMethodId(payMethodId);//加入payCard流context.output(payCardOutputTag,payCard);//清除该支付状态checkPayIsCard.remove(payBankCardId);}}else {//清除该支付状态checkPayIsCard.remove(payBankCardId);}}else if(null != payBankCard){//可以改为和payMethodStream的双流join.但是注意时间延迟。多流join时需要注意等待时间等等JSONObject payCard = JSONObject.parseObject(payBankCard);String payBankCardId = payCard.getString("PAY_BANK_CARD_ID");checkPayIsCard.put(payBankCardId, new PayCard("",payCard.getString("B_USER_ID"), payCard.getString("CARD_NO")));}else if(null!=billInfo){JSONObject billJson = JSONObject.parseObject(billInfo);context.output(billInfoOutputTag,new BillInfo(billJson.getString("BILL_ID"),billJson.getString("ORDER_ID")));}else if(null!=billItem){JSONObject billItemJson = JSONObject.parseObject(billItem);context.output(billItemOutputTag,new BillItem(billItemJson.getString("BILL_ID"),billItemJson.getString("ORD_PAY_ID")));}else if(null!=orderPay){JSONObject orderPayJson = JSONObject.parseObject(orderPay);context.output(orderPayOutputTag,new OrderPay(orderPayJson.getString("ORD_PAY_ID"),orderPayJson.getString("PAY_METHOD_ID")));}else if(null!=orderPayLog){JSONObject orderPayLogJson = JSONObject.parseObject(orderPayLog);context.output(orderPayOutputTag,new OrderPay(orderPayLogJson.getString("ORD_PAY_ID"),orderPayLogJson.getString("PAY_METHOD_ID")));}}});//获取支付银行卡流DataStream<PayCard> payCardStream = costStream.getSideOutput(payCardOutputTag);//获取订单流DataStream<BillInfo> billInfoStream = costStream.getSideOutput(billInfoOutputTag);//获取订单明细流DataStream<BillItem> billItemStream = costStream.getSideOutput(billItemOutputTag);//获取订单支付流DataStream<OrderPay> orderPayStream = costStream.getSideOutput(orderPayOutputTag);//获取订单支付日志流DataStream<OrderPayLog> orderPayLogStream = costStream.getSideOutput(orderPayLogOutputTag);

其中也可以换成filter操作对数据流一个一个的过滤来得到分流。

任务1

单个用户在一天内,付款超过1万元
其中costStream是已经支付状态的数据流

SingleOutputStreamOperator<DangerousMessage> dangerousMessage1Stream = costStream.keyBy("bUserId").process(new KeyedProcessFunction<Tuple, OrderInfo, DangerousMessage>() {private ValueState<Double> costState;private ValueState<String> timeState;@Overridepublic void open(Configuration parameters) throws Exception {costState = getRuntimeContext().getState(new ValueStateDescriptor<Double>("cost-value", Double.class));timeState = getRuntimeContext().getState(new ValueStateDescriptor< String>("time-value",  String.class));}@Overridepublic void processElement(OrderInfo orderInfo, Context ctx, Collector<DangerousMessage> collector) throws Exception {String buyUser = orderInfo.getbUserId();Double cost = orderInfo.gettotalPay();String now = orderInfo.getaddTime();//只看支付大于0的账单,避免重复报警if (cost!=0.0) {if (costState.value() == null) {costState.update(cost);timeState.update(now);if (cost > costLimit) {collector.collect(new DangerousMessage("1", "0", buyUser,cost,now));}}else {String start = timeState.value();Double lastCost=costState.value();SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");//如果为同一天if (fmt.parse(start).equals(fmt.parse(now))) {Double costSum = cost + lastCost;costState.update(costSum);if (costSum > costLimit) {/*一天内出现多次总和超过1万,应该多次警报,不清空状态(比如在一段时间,在1万以上还持续增加,则可认为非常高风险,我们可能需要打电话等方式提醒用户,所以这里选择不清空状态)*/collector.collect(new DangerousMessage("1", "0", buyUser,costSum,now));}} else {costState.update(cost);timeState.update(now);}}}}@Overridepublic void close() throws Exception {costState.clear();timeState.clear();}});

任务2

在绑卡操作中发现2个不同用户绑定了同一张银行卡
其中payCardStream是pay_method和ord_pay的关联流

SingleOutputStreamOperator<DangerousMessage> dangerousMessage2Stream = payCardStream.keyBy("cardNo").process(new KeyedProcessFunction<Tuple, PayCard, DangerousMessage>() {private ListState<String> payCardState;@Overridepublic void open(Configuration parameters) throws Exception {payCardState = getRuntimeContext().getListState(new ListStateDescriptor<String>("pay-value", String.class));}@Overridepublic void processElement(PayCard payCard, Context ctx, Collector<DangerousMessage> collector) throws Exception {String payCardUser = payCard.getbUserId();String cardNo = payCard.getcardNo();if(isEmpty(payCardState.get())){payCardState.add(payCardUser);}else{Iterable<String> users = payCardState.get();boolean flag=false;for (String user:users) {if(payCardUser.equals(user)){flag=true;break;}}if(!flag) {String conflictUsers ="";for (String user:users) {conflictUsers+="\""+user+"\",";}conflictUsers+="\""+payCardUser+"\"";payCardState.add(payCardUser);collector.collect(new DangerousMessage("2", cardNo,conflictUsers,0.0,""));}}}@Overridepublic void close() throws Exception {payCardState.clear();}});

任务3

在付款过程中,发现单个用户在5分钟内使用了10张以上的银行卡付款
使用table sql进行多流join操作

		//使用table sql进行多流joinTable orderInfoTable = tableEnv.fromDataStream(costStream);Table payCardTable = tableEnv.fromDataStream(payCardStream);Table billInfoTable = tableEnv.fromDataStream(billInfoStream);Table billItemTable = tableEnv.fromDataStream(billItemStream);Table orderPayTable = tableEnv.fromDataStream(orderPayStream);Table orderPayLogTable = tableEnv.fromDataStream(orderPayLogStream);tableEnv.createTemporaryView("order_info",orderInfoTable );tableEnv.createTemporaryView("pay_card",payCardTable );tableEnv.createTemporaryView("bill_info",billInfoTable );tableEnv.createTemporaryView("bill_item",billItemTable );tableEnv.createTemporaryView("order_pay",orderPayTable );tableEnv.createTemporaryView("order_pay_log",orderPayLogTable );//多流join,这里需要注意不能再直接使用costStream来做join操作,而是orderinfo的支付过程和已支付的所有数据。最好的做法是将costStream流的筛选工作直接放到任务一中,而非放到最开始的分流操作中。String sql="select order_info.bUserId bUserId,order_info.addTime addTime,pay_card.cardNo cardNo from order_info " +"join bill_info on order_info.orderId=bill_info.orderId " +"join bill_item on bill_info.billId=bill_item.billId " +"join order_pay on bill_item.orderPayId=order_pay.orderPayId " +"join pay_card on  order_pay.payMethodId=pay_card.payMethodId  ";Table resultTable = tableEnv.sqlQuery(sql);DataStream<Tuple2<Boolean, OverPayCard>> joinPayCardStream = tableEnv.toRetractStream(resultTable, OverPayCard.class);
//        joinPayCardStream.print("join");SingleOutputStreamOperator<DangerousMessage> dangerousMessage3Stream = joinPayCardStream.map(line -> {return line.f1;}).assignTimestampsAndWatermarks(new AscendingTimestampExtractor<OverPayCard>() {@Overridepublic long extractAscendingTimestamp(OverPayCard o) {String addTime = o.addTime;Calendar c = Calendar.getInstance();try {c.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(addTime));} catch (ParseException e) {e.printStackTrace();}return c.getTimeInMillis();}}).keyBy("bUserId")//滑动窗口设置太小报风险的情况会大量重复,所以这里设置1 minute.window(SlidingEventTimeWindows.of(Time.minutes(windowSizeLimit), Time.minutes(windowSlideSizeLimit))).aggregate(new MyaggregateFunction(), new CountBankCardsFunction());

聚合操作类:

 public static class MyaggregateFunction implements AggregateFunction<OverPayCard, Set<String>, Set<String>> {@Overridepublic Set<String> createAccumulator() {return new HashSet<>();}@Overridepublic Set<String> add(OverPayCard overPayCard, Set<String> strings) {strings.add(overPayCard.cardNo);return strings;}@Overridepublic Set<String> getResult(Set<String> strings) {return strings;}@Overridepublic Set<String> merge(Set<String> strings, Set<String> acc1) {strings.addAll(acc1);return strings;}}public static class CountBankCardsFunction implements WindowFunction<Set<String>, DangerousMessage, Tuple, TimeWindow> {@Overridepublic void apply(Tuple tuple, TimeWindow window, Iterable<Set<String>> input, Collector<DangerousMessage> out) throws Exception {String bUserId=tuple.getField(0);Integer count=input.iterator().next().size();if(count>cardLimit){//应该改为count>=cardLimitString bankCards ="";Integer l=0;for(String card:input.iterator().next()){bankCards+="\""+card+"\"";l++;if(l<count){bankCards+=',';}}out.collect(new DangerousMessage("3",bankCards,bUserId,0.0,""));}}}

小结

问题一、二的问题不是很大,不过很多地方还是可以继续优化的。问题三,解答存在一些问题,比如这里其实不能直接使用第一问中的costream作为其中的一个join流,因为第一问中要求的是付款1万元,所以需要使用已支付状态的数据。但是第三问中,题目提示“在付款过程中”,这句话表明只要有开始使用卡就要算在其内,而不只是已支付状态。另外这里和主办方工程师沟通,这里还有个问题是10张以上银行卡是包括10张的,所以count>cardLimit需要改为>=
当上述两个问题改过之后,能够输出一些数据,但是不全,可能会存在多流join等待时间(因为这些流并非同时到达的。这方面我了解比较少,所以欢迎大家给出自己的见解)的相关问题。

附录

package riskAssessment.Bean;public class BillInfo {public  String billId;public  String orderId;public BillInfo() {}public BillInfo(String billId, String orderId) {this.billId = billId;this.orderId = orderId;}public String getBillId() {return billId;}public void setBillId(String billId) {this.billId = billId;}public String getOrderId() {return orderId;}public void setOrderId(String orderId) {this.orderId = orderId;}@Overridepublic String toString() {return "BillInfo{" +"billId='" + billId + '\'' +", orderId='" + orderId + '\'' +'}';}
}
package riskAssessment.Bean;public class BillItem {public String billId;public String orderPayId;public BillItem() {}public BillItem(String billId, String orderPayId) {this.billId = billId;this.orderPayId = orderPayId;}public String getBillId() {return billId;}public void setBillId(String billId) {this.billId = billId;}public String getOrderPayId() {return orderPayId;}public void setOrderPayId(String orderPayId) {this.orderPayId = orderPayId;}@Overridepublic String toString() {return "BillItem{" +"billId='" + billId + '\'' +", orderPayId='" + orderPayId + '\'' +'}';}
}
package riskAssessment.Bean;public class DangerousMessage {public DangerousMessage() {}public String risk_id;public String card_no;public String b_user_id;public Double totoal_pay;public String time;public DangerousMessage(String risk_id, String card_no, String b_user_id, Double totoal_pay, String time) {this.risk_id = risk_id;this.card_no = card_no;this.b_user_id = b_user_id;this.totoal_pay = totoal_pay;this.time = time;}public Double getTotoal_pay() {return totoal_pay;}public void setTotoal_pay(Double totoal_pay) {this.totoal_pay = totoal_pay;}public String getTime() {return time;}public void setTime(String time) {this.time = time;}public String getRisk_id() {return risk_id;}public void setRisk_id(String risk_id) {this.risk_id = risk_id;}public String getCard_no() {return card_no;}public void setCard_no(String card_no) {this.card_no = card_no;}public String getB_user_id() {return b_user_id;}public void setB_user_id(String b_user_id) {this.b_user_id = b_user_id;}@Overridepublic String toString() {if(risk_id=="1"){return "{\"risk_id\":\"" + risk_id + "\"" +",\"risk_msg\":\"单个用户在一天内,付款超过1万元!" +"\""+",\"b_user_id\":\""+ b_user_id +"\""+",\"time\":\"" +time+"\"" +",\"total_pay\":\"" +totoal_pay.toString()+"\"" +"}";}else if(risk_id=="2"){return "{\"risk_id\":\"" + risk_id + "\"" +",\"risk_msg\":\"不同账户绑定了同一张银行卡!"  + "\"" +",\"card_no\":\"" + card_no + '\"' +",\"b_user_id\":[" + b_user_id + "]}";}else{return "{\"risk_id\":\"" + risk_id + "\"" +",\"risk_msg\":\"单个用户在5分钟内使用了10张以上的银行卡付款!"  + "\"" +",\"b_user_id\":\"" + b_user_id+'\"'+",\"card_no\":[" + card_no  + "]}";}}
}
package riskAssessment.Bean;public class OrderInfo{public String orderId;public String bUserId;public Double totalPay;public String addTime;public OrderInfo() {}public OrderInfo(String orderId, String bUserId, Double totalPay, String addTime) {this.orderId = orderId;this.bUserId = bUserId;this.totalPay = totalPay;this.addTime = addTime;}public String getorderId() {return orderId;}public void setorderId(String orderId) {this.orderId = orderId;}public String getbUserId() {return bUserId;}public void setbUserId(String bUserId) {this.bUserId = bUserId;}public Double gettotalPay() {return totalPay;}public void settotalPay(Double totalPay) {this.totalPay = totalPay;}public String getaddTime() {return addTime;}public void setaddTime(String addTime) {this.addTime = addTime;}@Overridepublic String toString() {return "OrderInfo{" +"orderId='" + orderId + '\'' +", bUserId='" + bUserId + '\'' +", totalPay=" + totalPay +", addTime=" + addTime +'}';}
}
package riskAssessment.Bean;public class OrderPay {public String orderPayId;public String payMethodId;public OrderPay() {}public OrderPay(String orderPayId, String payMethodId) {this.orderPayId = orderPayId;this.payMethodId = payMethodId;}public String getOrderPayId() {return orderPayId;}public void setOrderPayId(String orderPayId) {this.orderPayId = orderPayId;}public String getPayMethodId() {return payMethodId;}public void setPayMethodId(String payMethodId) {this.payMethodId = payMethodId;}@Overridepublic String toString() {return "OrderPay{" +"orderPayId='" + orderPayId + '\'' +", payMethodId='" + payMethodId + '\'' +'}';}
}
package riskAssessment.Bean;public class OrderPayLog {public String orderPayId;public String payMethodId;public OrderPayLog(String orderPayId, String payMethodId) {this.orderPayId = orderPayId;this.payMethodId = payMethodId;}public OrderPayLog() {}public String getOrderPayId() {return orderPayId;}public void setOrderPayId(String orderPayId) {this.orderPayId = orderPayId;}public String getPayMethodId() {return payMethodId;}public void setPayMethodId(String payMethodId) {this.payMethodId = payMethodId;}@Overridepublic String toString() {return "OrderPayLog{" +"orderPayId='" + orderPayId + '\'' +", payMethodId='" + payMethodId + '\'' +'}';}
}
package riskAssessment.Bean;public class OverPayCard {public String bUserId;public String addTime;public String cardNo;public OverPayCard() {}public OverPayCard(String bUserId, String addTime, String cardNo) {this.bUserId = bUserId;this.addTime = addTime;this.cardNo = cardNo;}public String getbUserId() {return bUserId;}public void setbUserId(String bUserId) {this.bUserId = bUserId;}public String getAddTime() {return addTime;}public void setAddTime(String addTime) {this.addTime = addTime;}public String getCardNo() {return cardNo;}public void setCardNo(String cardNo) {this.cardNo = cardNo;}@Overridepublic String toString() {return "OverPayCard{" +"bUserId='" + bUserId + '\'' +", addTime=" + addTime +", cardNo='" + cardNo + '\'' +'}';}
}
package riskAssessment.Bean;public class PayCard {public String payMethodId;public String bUserId;public String cardNo;public PayCard() {}public String getPayMethodId() {return payMethodId;}public void setPayMethodId(String payMethodId) {this.payMethodId = payMethodId;}public String getCardNo() {return cardNo;}public void setCardNo(String cardNo) {this.cardNo = cardNo;}public String getbUserId() {return bUserId;}public void setbUserId(String bUserId) {this.bUserId = bUserId;}public String getcardNo() {return cardNo;}public void setcardNo(String cardNo) {this.cardNo = cardNo;}public PayCard(String payMethodId, String bUserId, String cardNo) {this.payMethodId = payMethodId;this.bUserId = bUserId;this.cardNo = cardNo;}@Overridepublic String toString() {return "PayCard{" +"payMethodId='" + payMethodId + '\'' +", bUserId='" + bUserId + '\'' +", cardNo='" + cardNo + '\'' +'}';}
}

大家有任何问题都可以在评论区留言,我一定尽我所能解答。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_38412.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聊聊雪花算法?

随便聊聊 哈喽&#xff0c;大家好&#xff0c;最近换了份工作&#xff0c;虽然后端技术栈是老了点&#xff0c;但是呢&#xff0c;这边的前端技术确是现在市面上最新的那一套技术&#xff1a;Vue3ViteTSXPinaElement-PlusNativeUI。我本人主要是学后端的&#xff0c;确被拉去做…

【博客545】从交换机视角看四种报文:广播、组播、未知单播、已知单播

从交换机视角看四种报文&#xff1a;广播、组播、未知单播、已知单播 交换机视角的四种报文 对于二层交换机来说&#xff0c;它在转发报文时&#xff0c;只有四种类型的报文&#xff1a; 1、广播 2、组播 3、未知单播 4、已知单播。四种报文剖析 1、二层广播报文 当二层交换…

SignalR简介及实践指南

SigalR简介 ASP.NET Core SignalR 是一个开放源代码库&#xff0c;可用于简化向应用添加实时 Web 功能。 实时 Web 功能使服务器端代码能够将内容推送到客户端。 适合 SignalR 的候选项&#xff1a; 需要从服务器进行高频率更新的应用。 示例包括游戏、社交网络、投票、拍卖…

易观千帆 | 2022年10月银行APP月活跃用户规模盘点

易观分析&#xff1a;易观千帆数据显示&#xff0c;10月手机银行服务应用活跃人数52285.79万&#xff0c;环比下降3.52%。手机银行服务应用月活规模经历了连续5个月的持续增长后&#xff0c;10月出现下降。 10月城商行手机银行服务应用活跃人数3565.56万&#xff0c;环比下降2…

UNIAPP实战项目笔记46 订单确认页面的布局

UNIAPP实战项目笔记46 订单确认页面的布局 实际案例图片 订单页面 具体内容图片自己替换哈&#xff0c;随便找了个图片的做示例 具体位置见目录结构 完善布局页面和样式 代码 confirm-order.vue部分 confirm-order.vue 确认订单页面布局和渲染 flex 样式布局 <template>…

字符串5:剑指Offer58-II.左旋转字符串

主要是我自己刷题的一些记录过程。如果有错可以指出哦&#xff0c;大家一起进步。 转载代码随想录 原文链接&#xff1a; 代码随想录 leetcode链接&#xff1a;344. 反转字符串 题目&#xff1a; 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个…

衡师11月月赛web题目wp

目录 1.丢三落四的学姐 2.wep&#xff1f;Pwn&#xff01;&#xff01;&#xff01; 这题web部分是buuctf中的DASCTF X GFCTF 2022十月挑战赛&#xff01;的原题 1.丢三落四的学姐 访问题目位置&#xff0c;很明显的phpstudy搭建的痕迹 访问一下经常信息泄露的几个文件&…

Baklib|知识库应用场景:制作员工培训手册

持续的专业发展对于想要加入、保留和提升员工的组织来说是必不可少的。为了确保员工总是能从学习能力中受益&#xff0c;您需要考虑创建培训手册&#xff0c;使员工能够胜任并保持他们的工作能力。 在过去&#xff0c;您可能认为培训手册是一本厚重的册子&#xff0c;充满了密…

一文彻底搞懂Mysql索引优化

专属小彩蛋&#xff1a;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff08;前言 - 床长人工智能教程&#xff09; 目录 一、索引介绍 二、性能分析 三、查询优化 一、索引介绍…

Oracle中ALTER TABLE的五种用法(三)

首发微信公众号&#xff1a;SQL数据库运维 原文链接&#xff1a;https://mp.weixin.qq.com/s?__bizMzI1NTQyNzg3MQ&mid2247485212&idx1&sn450e9e94fa709b5eeff0de371c62072b&chksmea37536cdd40da7a94e165ce4b4c6e70fb1360d51bed4b3566eee438b587fa231315d0a5a…

通俗易懂的java设计模式(1)-单例模式

什么是单例模式&#xff1f; 单例模式是java中最简单的一种设计模式 需要注意的问题&#xff1a; 1.单例类有且只能有一个实例 2.单例类必须自己创建出这个实例&#xff0c;并提供给外界 那么如何自己创建实例而不让外界创建呢&#xff1f;很简单&#xff0c;我们将无参的构造函…

传输线理论基础01——相关定义、信号速率、分布参数与电报方程

前言一直以来都对高频信号、信号完整性、传输线、分布参数这些概念似懂非懂&#xff0c;上学时没学过相关课程&#xff0c;这导致我对高频电路和PCB理解较差&#xff0c;这里新开一个专栏&#xff0c;补齐这方面知识。 一. 传输线相关定义1.1 传输线定义 传输线指的是传输信号…

【Hack The Box】Linux练习-- Seventeen

HTB 学习笔记 【Hack The Box】Linux练习-- Seventeen &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年9月7日&#x1f334; &#x1f…

【数据去噪】SG-多项式平滑算法

文章目录一、简介二、原理5点3次多项式平滑三、代码1. 3点线性平滑2. 5点线性平滑3. 5点2次线性平滑4. 5点3次线性平滑5. 7点线性平滑6. 7点2次线性平滑一、简介 在处理工业数据的时候&#xff0c;工业数据有数据颗粒细&#xff0c;噪声大&#xff0c;量大&#xff0c;随着测量…

拿捏Fiddler抓包教程(10)-Fiddler如何设置捕获Firefox浏览器的Https会话

1.简介 经过上一篇对Fiddler的配置后&#xff0c;绝大多数的Https的会话&#xff0c;我们可以成功捕获抓取到&#xff0c;但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话&#xff0c;需要我们更进一步的配置才能捕获到会话进行抓包。 2.宏哥环境 1.宏哥的环境是Win…

【Python】四、程序顺序和分支控制结构

文章目录实验目的一、赋值语句应用练习二、if- else分支结构三、多分支选择结构四、选择嵌套五、编程实现百分制换成五级制(优,良,中,及格,不及格)1.设计思路2.设计算法3.参考代码4.实验截图实验目的 掌握顺序和分支结构&#xff1b;培养学生动手查阅资料能力和解决实际问题的能…

CAD特殊符号,你不一定会

在CAD软件中&#xff0c;有时候会输入一些特殊的符号。比如在标明高低差的时候会输入“”号&#xff0c;在标明管子或者钢筋的直径为输入直径符号“”&#xff0c;为了标明角度值需要输入符号“”&#xff0c;那么这些符号怎么快速的绘制出来呢&#xff1f;我们一起用CAD梦想画…

初识计算机网络

目录 网络的发展 重新看待计算机结构 大型存储平台 认识 "协议" 网络和OS之间的关系 初识网络协议 协议分层 OSI七层模型 TCP/IP五层(或四层)模型 网络传输基本流程 局域网通信的原理 如果进行跨网络传输 网络通信里面的基本轮廓 数据包封装和分用…

QFile(文件)

QFile QFile提供一个用于读/写的接口&#xff0c;是一个可以用来读/写二进制文件的Qt资源的I/O设备&#xff0c;QFile可以单独使用&#xff0c;一般配合QTextStream或QDataStream 输入文件路径时最好使用"/"作为分隔符 构造函数&#xff1a; 常用的函数&#xff1a;…

Terraform 华为云最佳实践

目录划分如下&#xff1a;首先是环境&#xff0c;分为网络和service。global是全局的配置&#xff0c;也就是backend的配置&#xff0c;这次使用s3的存储作为backend的存储。最后就是模块做了一些封装。 在global里面的backend里面的main.tf去创建s3的存储。华为云支持s3存储&a…