Flume:使用Apache Flume收集客户产品搜索点击数据

这篇文章涵盖了使用Apache flume收集客户产品搜索点击并使用hadoop和elasticsearch接收器存储信息。 数据可能包含不同的产品搜索事件,例如基于不同方面的过滤,排序信息,分页信息,以及进一步查看的产品以及某些被客户标记为喜欢的产品。 在以后的文章中,我们将进一步分析数据,以使用相同的信息进行显示和分析。

产品搜索功能

任何电子商务平台都可以为客户提供不同的产品,而搜索功能是其基础之一。 允许用户使用不同的构面/过滤器进行引导导航,或使用自由文本搜索内容,这与任何现有搜索功能无关紧要。

SearchQueryInstruction

考虑类似的情况,客户可以搜索产品,并允许我们使用以下信息来捕获产品搜索行为,

public class SearchQueryInstruction implements Serializable {@JsonIgnoreprivate final String _eventIdSuffix;private String eventId;private String hostedMachineName;private String pageUrl;private Long customerId;private String sessionId;private String queryString;private String sortOrder;private Long pageNumber;private Long totalHits;private Long hitsShown;private final Long createdTimeStampInMillis;private String clickedDocId;private Boolean favourite;@JsonIgnoreprivate Map<String, Set<String>> filters;@JsonProperty(value = "filters")private List<FacetFilter> _filters;public SearchQueryInstruction() {_eventIdSuffix = UUID.randomUUID().toString();createdTimeStampInMillis = new Date().getTime();}......private static class FacetFilter implements Serializable {private String code;private String value;public FacetFilter(String code, String value) {this.code = code;this.value = value;}......}
}

有关更多源信息,请访问SearchQueryInstruction 。 数据以JSON格式序列化,以便能够直接与ElasticSearch结合使用以进一步显示。

示例数据,基于用户点击的点击信息的外观。 数据先转换为json格式,然后再发送给嵌入式水槽代理。

{"eventid":"629e9b5f-ff4a-4168-8664-6c8df8214aa7-1399386809805-24","hostedmachinename":"192.168.182.1330","pageurl":"http://jaibigdata.com/5","customerid":24,"sessionid":"648a011d-570e-48ef-bccc-84129c9fa400","querystring":null,"sortorder":"desc","pagenumber":3,"totalhits":28,"hitsshown":7,"createdtimestampinmillis":1399386809805,"clickeddocid":"41","favourite":null,"eventidsuffix":"629e9b5f-ff4a-4168-8664-6c8df8214aa7","filters":[{"code":"searchfacettype_color_level_2","value":"Blue"},{"code":"searchfacettype_age_level_2","value":"12-18 years"}]}
{"eventid":"648b5cf7-7ca9-4664-915d-23b0d45facc4-1399386809782-298","hostedmachinename":"192.168.182.1333","pageurl":"http://jaibigdata.com/4","customerid":298,"sessionid":"7bf042ea-526a-4633-84cd-55e0984ea2cb","querystring":"queryString48","sortorder":"desc","pagenumber":0,"totalhits":29,"hitsshown":19,"createdtimestampinmillis":1399386809782,"clickeddocid":"9","favourite":null,"eventidsuffix":"648b5cf7-7ca9-4664-915d-23b0d45facc4","filters":[{"code":"searchfacettype_color_level_2","value":"Green"}]}
{"eventid":"74bb7cfe-5f8c-4996-9700-0c387249a134-1399386809799-440","hostedmachinename":"192.168.182.1330","pageurl":"http://jaibigdata.com/1","customerid":440,"sessionid":"940c9a0f-a9b2-4f1d-b114-511ac11bf2bb","querystring":"queryString16","sortorder":"asc","pagenumber":3,"totalhits":5,"hitsshown":32,"createdtimestampinmillis":1399386809799,"clickeddocid":null,"favourite":null,"eventidsuffix":"74bb7cfe-5f8c-4996-9700-0c387249a134","filters":[{"code":"searchfacettype_brand_level_2","value":"Apple"}]}
{"eventid":"9da05913-84b1-4a74-89ed-5b6ec6389cce-1399386809828-143","hostedmachinename":"192.168.182.1332","pageurl":"http://jaibigdata.com/1","customerid":143,"sessionid":"08a4a36f-2535-4b0e-b86a-cf180202829b","querystring":null,"sortorder":"desc","pagenumber":0,"totalhits":21,"hitsshown":34,"createdtimestampinmillis":1399386809828,"clickeddocid":"38","favourite":true,"eventidsuffix":"9da05913-84b1-4a74-89ed-5b6ec6389cce","filters":[{"code":"searchfacettype_color_level_2","value":"Blue"},{"code":"product_price_range","value":"10.0 - 20.0"}]}

阿帕奇水槽

Apache Flume用于收集和聚合数据。 此处,嵌入式Flume代理用于捕获搜索查询指令事件。 根据实际使用情况,

  • 您可以使用嵌入式代理来收集数据
  • 或通过rest api将数据从页面推送到专用于事件收集的后端api服务
  • 或者,您可以使用应用程序日志记录功能来记录所有搜索事件,并在日志文件的末尾收集数据

考虑一个取决于应用程序的场景,多个Web /应用程序服务器将事件数据发送到收集器水槽代理。 如下图所示,搜索点击事件是从多个Web /应用服务器和一个收集器/合并器代理收集的,以从所有代理收集数据。 数据基于选择器使用多路复用策略进一步划分,以存储在Hadoop HDFS中,并且还将相关数据定向到ElasticSearch。 最近浏览过的商品。

水槽数据流代理接收器

嵌入式Flume代理

嵌入式Flume Agent允许我们在应用程序本身中包含Flume代理,并允许我们收集数据并进一步发送给收集器代理。

private static EmbeddedAgent agent;private void createAgent() {final Map<String, String> properties = new HashMap<String, String>();properties.put("channel.type", "memory");properties.put("channel.capacity", "100000");properties.put("channel.transactionCapacity", "1000");properties.put("sinks", "sink1");properties.put("sink1.type", "avro");properties.put("sink1.hostname", "localhost");properties.put("sink1.port", "44444");properties.put("processor.type", "default");try {agent = new EmbeddedAgent("searchqueryagent");agent.configure(properties);agent.start();} catch (final Exception ex) {LOG.error("Error creating agent!", ex);}}

存储搜索事件数据

Flume提供了多个接收器选项来存储数据以供将来分析。 如图所示,我们将采用将数据存储在Apache Hadoop和ElasticSearch中的方案,以实现最近查看的项目功能。

Hadoop接收器

允许将数据永久存储到HDFS,以便以后进行分析以进行分析。
根据传入的事件数据,假设我们要每小时存储一次。 “ / searchevents / 2014/05/15/16”目录将存储16小时内的所有传入事件。

private HDFSEventSink sink;sink = new HDFSEventSink();sink.setName("HDFSEventSink-" + UUID.randomUUID());channel = new MemoryChannel();Map<String, String> channelParamters = new HashMap<>();channelParamters.put("capacity", "100000");channelParamters.put("transactionCapacity", "1000");Context channelContext = new Context(channelParamters);Configurables.configure(channel, channelContext);channel.setName("HDFSEventSinkChannel-" + UUID.randomUUID());Map<String, String> paramters = new HashMap<>();paramters.put("hdfs.type", "hdfs");String hdfsBasePath = hadoopClusterService.getHDFSUri()+ "/searchevents";paramters.put("hdfs.path", hdfsBasePath + "/%Y/%m/%d/%H");paramters.put("hdfs.filePrefix", "searchevents");paramters.put("hdfs.fileType", "DataStream");paramters.put("hdfs.rollInterval", "0");paramters.put("hdfs.rollSize", "0");paramters.put("hdfs.idleTimeout", "1");paramters.put("hdfs.rollCount", "0");paramters.put("hdfs.batchSize", "1000");paramters.put("hdfs.useLocalTimeStamp", "true");Context sinkContext = new Context(paramters);sink.configure(sinkContext);sink.setChannel(channel);sink.start();channel.start();

检查FlumeHDFSSinkServiceImpl.java以获取有关hdfs接收器的详细启动/停止信息。

下面的示例数据存储在hadoop中,

Check:hdfs://localhost.localdomain:54321/searchevents/2014/05/06/16/searchevents.1399386809864
body is:{"eventid":"e8470a00-c869-4a90-89f2-f550522f8f52-1399386809212-72","hostedmachinename":"192.168.182.1334","pageurl":"http://jaibigdata.com/0","customerid":72,"sessionid":"7871a55c-a950-4394-bf5f-d2179a553575","querystring":null,"sortorder":"desc","pagenumber":0,"totalhits":8,"hitsshown":44,"createdtimestampinmillis":1399386809212,"clickeddocid":"23","favourite":null,"eventidsuffix":"e8470a00-c869-4a90-89f2-f550522f8f52","filters":[{"code":"searchfacettype_brand_level_2","value":"Apple"},{"code":"searchfacettype_color_level_2","value":"Blue"}]}
body is:{"eventid":"2a4c1e1b-d2c9-4fe2-b38d-9b7d32feb4e0-1399386809743-61","hostedmachinename":"192.168.182.1330","pageurl":"http://jaibigdata.com/0","customerid":61,"sessionid":"78286f6d-cc1e-489c-85ce-a7de8419d628","querystring":"queryString59","sortorder":"asc","pagenumber":3,"totalhits":32,"hitsshown":9,"createdtimestampinmillis":1399386809743,"clickeddocid":null,"favourite":null,"eventidsuffix":"2a4c1e1b-d2c9-4fe2-b38d-9b7d32feb4e0","filters":[{"code":"searchfacettype_age_level_2","value":"0-12 years"}]}

ElasticSearch接收器

出于查看目的,向最终用户显示最近查看的项目。 ElasticSearch Sink允许自动创建每日最近查看的项目。 该功能可用于显示客户最近查看的项目。
假设您已经有ES实例在localhost / 9310上运行。

private ElasticSearchSink sink;sink = new ElasticSearchSink();sink.setName("ElasticSearchSink-" + UUID.randomUUID());channel = new MemoryChannel();Map<String, String> channelParamters = new HashMap<>();channelParamters.put("capacity", "100000");channelParamters.put("transactionCapacity", "1000");Context channelContext = new Context(channelParamters);Configurables.configure(channel, channelContext);channel.setName("ElasticSearchSinkChannel-" + UUID.randomUUID());Map<String, String> paramters = new HashMap<>();paramters.put(ElasticSearchSinkConstants.HOSTNAMES, "127.0.0.1:9310");String indexNamePrefix = "recentlyviewed";paramters.put(ElasticSearchSinkConstants.INDEX_NAME, indexNamePrefix);paramters.put(ElasticSearchSinkConstants.INDEX_TYPE, "clickevent");paramters.put(ElasticSearchSinkConstants.CLUSTER_NAME,"jai-testclusterName");paramters.put(ElasticSearchSinkConstants.BATCH_SIZE, "10");paramters.put(ElasticSearchSinkConstants.SERIALIZER,ElasticSearchJsonBodyEventSerializer.class.getName());Context sinkContext = new Context(paramters);sink.configure(sinkContext);sink.setChannel(channel);sink.start();channel.start();

检查FlumeESSinkServiceImpl.java以获得启动/停止ElasticSearch接收器的详细信息。

elasticsearch中的样本数据存储为

{timestamp=1399386809743, body={pageurl=http://jaibigdata.com/0, querystring=queryString59, pagenumber=3, hitsshown=9, hostedmachinename=192.168.182.1330, createdtimestampinmillis=1399386809743, sessionid=78286f6d-cc1e-489c-85ce-a7de8419d628, eventid=2a4c1e1b-d2c9-4fe2-b38d-9b7d32feb4e0-1399386809743-61, totalhits=32, clickeddocid=null, customerid=61, sortorder=asc, favourite=null, eventidsuffix=2a4c1e1b-d2c9-4fe2-b38d-9b7d32feb4e0, filters=[{value=0-12 years, code=searchfacettype_age_level_2}]}, eventId=2a4c1e1b-d2c9-4fe2-b38d-9b7d32feb4e0}
{timestamp=1399386809757, body={pageurl=http://jaibigdata.com/1, querystring=null, pagenumber=1, hitsshown=34, hostedmachinename=192.168.182.1330, createdtimestampinmillis=1399386809757, sessionid=e6a3fd51-fe07-4e21-8574-ce5ab8bfbd68, eventid=fe5279b7-0bce-4e2b-ad15-8b94107aa792-1399386809757-134, totalhits=9, clickeddocid=22, customerid=134, sortorder=desc, favourite=null, eventidsuffix=fe5279b7-0bce-4e2b-ad15-8b94107aa792, filters=[{value=Blue, code=searchfacettype_color_level_2}]}, State=VIEWED, eventId=fe5279b7-0bce-4e2b-ad15-8b94107aa792}
{timestamp=1399386809765, body={pageurl=http://jaibigdata.com/0, querystring=null, pagenumber=4, hitsshown=2, hostedmachinename=192.168.182.1331, createdtimestampinmillis=1399386809765, sessionid=29864de8-5708-40ab-a78b-4fae55698b01, eventid=886e9a28-4c8c-4e8c-a866-e86f685ecc54-1399386809765-317, totalhits=2, clickeddocid=null, customerid=317, sortorder=asc, favourite=null, eventidsuffix=886e9a28-4c8c-4e8c-a866-e86f685ecc54, filters=[{value=0-12 years, code=searchfacettype_age_level_2}, {value=0.0 - 10.0, code=product_price_range}]}, eventId=886e9a28-4c8c-4e8c-a866-e86f685ecc54}

ElasticSearchJsonBodyEventSerializer

控制如何在ElasticSearch中建立数据索引。 根据您的策略更新事件Seaalalizer,以查看应如何为数据建立索引。

public class ElasticSearchJsonBodyEventSerializer implements ElasticSearchEventSerializer {@Overridepublic BytesStream getContentBuilder(final Event event) throws IOException {final XContentBuilder builder = jsonBuilder().startObject();appendBody(builder, event);appendHeaders(builder, event);return builder;}......
}

检查ElasticSearchJsonBodyEventSerializer.java以配置序列化器以索引数据。

让我们以Java为例创建Flume源,以在测试用例中处理上述SearchQueryInstruction并存储数据。

带通道选择器的Avro Source

为了进行测试,让我们创建Avro源,以基于水槽多路复用功能将数据重定向到相关的接收器。

//Avro source to start at below port and process incoming data.private AvroSource avroSource;final Map<String, String> properties = new HashMap<String, String>();properties.put("type", "avro");properties.put("bind", "localhost");properties.put("port", "44444");avroSource = new AvroSource();avroSource.setName("AvroSource-" + UUID.randomUUID());Context sourceContext = new Context(properties);avroSource.configure(sourceContext);ChannelSelector selector = new MultiplexingChannelSelector();//Channels from above servicesChannel ESChannel = flumeESSinkService.getChannel();Channel HDFSChannel = flumeHDFSSinkService.getChannel();List<Channel> channels = new ArrayList<>();channels.add(ESChannel);channels.add(HDFSChannel);selector.setChannels(channels);final Map<String, String> selectorProperties = new HashMap<String, String>();selectorProperties.put("type", "multiplexing");selectorProperties.put("header", "State");selectorProperties.put("mapping.VIEWED", HDFSChannel.getName() + " "+ ESChannel.getName());selectorProperties.put("mapping.FAVOURITE", HDFSChannel.getName() + " "+ ESChannel.getName());selectorProperties.put("default", HDFSChannel.getName());Context selectorContext = new Context(selectorProperties);selector.configure(selectorContext);ChannelProcessor cp = new ChannelProcessor(selector);avroSource.setChannelProcessor(cp);avroSource.start();

检查FlumeAgentServiceImpl.java,将数据直接存储到上面配置的接收器,甚至将所有数据记录到日志文件中。

独立Flume / Hadoop / ElasticSearch环境

该应用程序可用于生成SearchQueryInstruction数据,并且您可以使用自己的独立环境进一步处理数据。 如果您已经在运行Flume / Hadoop / ElasticSearch环境,请使用以下设置进一步处理数据。

如果您已经在运行Flume实例,也可以使用以下配置(flume.conf),

# Name the components on this agent
searcheventscollectoragent.sources = eventsavrosource
searcheventscollectoragent.sinks = hdfssink essink
searcheventscollectoragent.channels = hdfschannel eschannel# Bind the source and sink to the channel
searcheventscollectoragent.sources.eventsavrosource.channels = hdfschannel eschannel
searcheventscollectoragent.sinks.hdfssink.channel = hdfschannel
searcheventscollectoragent.sinks.essink.channel = eschannel#Avro source. This is where data will send data to.
searcheventscollectoragent.sources.eventsavrosource.type = avro
searcheventscollectoragent.sources.eventsavrosource.bind = 0.0.0.0
searcheventscollectoragent.sources.eventsavrosource.port = 44444
searcheventscollectoragent.sources.eventsavrosource.selector.type = multiplexing
searcheventscollectoragent.sources.eventsavrosource.selector.header = State
searcheventscollectoragent.sources.eventsavrosource.selector.mapping.VIEWED = hdfschannel eschannel
searcheventscollectoragent.sources.eventsavrosource.selector.mapping.default = hdfschannel# Use a channel which buffers events in memory. This will keep all incoming stuff in memory. You may change this to file etc. in case of too much data coming and memory an issue.
searcheventscollectoragent.channels.hdfschannel.type = memory
searcheventscollectoragent.channels.hdfschannel.capacity = 100000
searcheventscollectoragent.channels.hdfschannel.transactionCapacity = 1000searcheventscollectoragent.channels.eschannel.type = memory
searcheventscollectoragent.channels.eschannel.capacity = 100000
searcheventscollectoragent.channels.eschannel.transactionCapacity = 1000#HDFS sink. Store events directly to hadoop file system.
searcheventscollectoragent.sinks.hdfssink.type = hdfs
searcheventscollectoragent.sinks.hdfssink.hdfs.path = hdfs://localhost.localdomain:54321/searchevents/%Y/%m/%d/%H
searcheventscollectoragent.sinks.hdfssink.hdfs.filePrefix = searchevents
searcheventscollectoragent.sinks.hdfssink.hdfs.fileType = DataStream
searcheventscollectoragent.sinks.hdfssink.hdfs.rollInterval = 0
searcheventscollectoragent.sinks.hdfssink.hdfs.rollSize = 134217728
searcheventscollectoragent.sinks.hdfssink.hdfs.idleTimeout = 60
searcheventscollectoragent.sinks.hdfssink.hdfs.rollCount = 0
searcheventscollectoragent.sinks.hdfssink.hdfs.batchSize = 10
searcheventscollectoragent.sinks.hdfssink.hdfs.useLocalTimeStamp = true#Elastic search
searcheventscollectoragent.sinks.essink.type = elasticsearch
searcheventscollectoragent.sinks.essink.hostNames = 127.0.0.1:9310
searcheventscollectoragent.sinks.essink.indexName = recentlyviewed
searcheventscollectoragent.sinks.essink.indexType = clickevent
searcheventscollectoragent.sinks.essink.clusterName = jai-testclusterName
searcheventscollectoragent.sinks.essink.batchSize = 10
searcheventscollectoragent.sinks.essink.ttl = 5
searcheventscollectoragent.sinks.essink.serializer = org.jai.flume.sinks.elasticsearch.serializer.ElasticSearchJsonBodyEventSerializer

要测试应用程序搜索查询指令在现有hadoop实例上的行为,请分别设置hadoop和elasticsearch实例。 该应用程序使用Cloudera hadoop distribution 5.0进行测试。

在后面的文章中,我们将介绍进一步分析生成的数据,

  • 使用Hive可以查询数据,以查询最热门的客户和产品浏览的次数。
  • 使用ElasticSearch Hadoop为客户热门查询和产品视图数据编制索引
  • 使用Pig来计算唯一客户总数
  • 使用Oozie计划针对配置单元分区进行协调的作业,并将作业捆绑以将数据索引到ElasticSearch。

翻译自: https://www.javacodegeeks.com/2014/05/flume-gathering-customer-product-search-clicks-data-using-apache-flume.html

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

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

相关文章

vue-cli使用swiper4在ie以及safari报错

vue-cli项目中&#xff0c;通过npm run swiper --save-dev安装的是swiper4版本的插件&#xff0c;这样安装以后在谷歌火狐等浏览器都可以正常运行&#xff0c;但是在safari浏览器&#xff08;可能是版本太低&#xff09;还有ie&#xff08;9,10,11&#xff09;打开会报错&#…

电脑内部,小贴士:电脑内部连接标准

小贴士&#xff1a;电脑内部连接标准在介绍电脑内部连接标准之前&#xff0c;首先应该了解一下电脑内部接线的种类&#xff0c;以便分类处置。电脑内部尽管五颜六色的导线&#xff0c;其中导线的种类可以分为3 类&#xff0c;即电源线、信号线和控制线&#xff0c;而控制线又常…

太快了,太变态了:什么会影响Java中的方法调用性能?

那么这是怎么回事&#xff1f; 让我们从一个简短的故事开始。 几周前&#xff0c;我提议对Java核心libs邮件列表进行更改 &#xff0c;以覆盖当前final一些方法。 这刺激了一些讨论主题-其中之一是其中一个性能回归通过采取这是一个方法被引入的程度final免遭停止它final 。 我…

1、dubbo的概念

Dubbo是什么&#xff1f; Dubbo是阿里巴巴SOA服务化治理方案的核心框架&#xff0c;每天为2,000个服务提供3,000,000,000次访问量支持&#xff0c;并被广泛应用于阿里巴巴集团的各成员站点。Dubbo[]是一个分布式服务框架&#xff0c;致力于提供高性能和透明化的RPC远程服务调用…

轻云服务器的性能,腾讯云轻量应用服务器性能评测(以香港地域为例)

腾讯云轻量应用服务器香港节点24元/月&#xff0c;价格很不错&#xff0c;ForeignServer来说说腾讯云轻量服务器香港地域性能评测&#xff0c;包括腾讯云轻量应用服务器CPU型号配置、网络延迟速度测试&#xff1a;腾讯云香港轻量应用服务器性能评测腾讯云轻量应用服务器地域可选…

vue2.5.2版本 :MAC设置应用在127.0.0.1:80端口访问; 并将127.0.0.1指向www.yours.com ;问题“ Invalid Host header”

0.设置自己的host文件&#xff0c;将127.0.0.1指向自己想要访问的域名 127.0.0.1 www.yours.com 1.MAC设置应用在127.0.0.1&#xff1a;80端口访问&#xff1a; config/index.js目录下修改host和port 然后sudo运行npm run dev:(mac的80端口是被自身分享应用占用的&#xff0c…

Google Android 平台正式开源

Google 推出移动设备软件平台 Android 之时&#xff0c;曾向开发者开放 SDK 包&#xff0c;并许诺将在开源许可模式下开放其全部代码&#xff0c;今天&#xff0c;Google 与其合作伙伴&#xff0c;在 Open Handset Alliance 兑现了其承诺&#xff0c;用户现在可以正式下载 Andr…

JSP彩色验证码

产生验证码图片的文件-----image.jsp <% page contentType"image/jpeg" import"java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %><%!Color getRandColor(int fc,int bc){//给定范围获得随机颜色 Random random new Random()…

自定义Windows右击菜单调用Winform程序

U9_Git中ignore文件处理 背景 U9代码中有许多自动生成的文件&#xff0c;不需要上传Git必须BE Entity中的.target文件 .bak 文件 Enum.cs结尾的文件&#xff0c;还有许多 extand文件。 这些文件都不需要上传Git。 但是这些文件太多了&#xff0c;不可能手动加入到ignore文件中。…

Gradle Introduction

目录 Compileing development ProcessOld compile MothedModern compile MothedWhat is GradleGradle EffectWhat is GroovyGroovy syntax relesStructure ScriptPeojectAttributeTaskExample #1applyExample #1Example #2Dependency ManagementExample #1Example #2Multiple P…

u8系统怎么连接服务器,用友U8 怎么连接远程服务器

用友U8 怎么连接远程服务器 内容精选换一换配置应用系统的跨云热备容灾方案如图1所示。在如图1所示的方案中&#xff0c;用户的生产数据中心的应用系统使用MySQL作为数据库&#xff0c;应用系统与MySQL均热备容灾到华为云上。用户的生产数据中心与华为云之间使用专线进行网络连…

[导入]商业智能2.0?(BI 2.0 from Timo Elliott)

译者注: 关于BI2.0的说法很多&#xff0c;不尽一致&#xff0c;目的只是想多了解一些&#xff1b;译文并不代表译者认可原文观点&#xff0c;只是顺便译了以方便不喜欢E文的朋友。本文是一篇充满探讨及疑问的文章&#xff0c;来自Timo Elliott(Business Objects历史上的第8号员…

angularjs封装bootstrap官网的时间插件datetimepicker

背景:angular与jquery类库的协作 第三方类库中&#xff0c;不得不提的是大名鼎鼎的jquery,现在基本上已经是国内web开发的必修工具了。它灵活的dom操作&#xff0c;让很多web开发人员欲罢不能。再加上已经很成熟的jquery UI 库和大量jquery 插件&#xff0c;几乎是一个取之不尽…

Java中的得墨meter耳定律–最少知识原理–实际示例

得墨meter耳定律&#xff08;也称为最少知识定律&#xff09;是一种编码原理&#xff0c;它表示模块不应该知道其操作的对象的内部细节。 如果代码依赖于特定对象的内部细节&#xff0c;则很有可能一旦该对象的内部发生更改&#xff0c;它就会被破坏。 由于封装是关于隐藏对象的…

课后作业1

自我介绍 我叫张阔&#xff0c;我的爱好是旅行&#xff0c;游览世界的美好风光&#xff1b; 我的码云个人主页是&#xff1a;https://gitee.com/ZkTt0428&#xff1b; 我的第一个项目地址是&#xff1a;https://gitee.com/ZkTt0428/Frist&#xff1b; 目前代码量有10000行了&am…

针对新手的Java EE7和Maven项目-第4部分-定义Ear模块

从前面的部分恢复 第1部分 第2部分 第3部分 我们正在恢复第四部分&#xff0c;目前我们的简单项目有 Web Maven模块&#xff08;战争&#xff09; 一个ejb模块&#xff08;ejb&#xff09;&#xff0c;其中包含我们的无状态会话bean&#xff08;EJB 3.1&#xff09; 第二…

最大公因数和最小公倍数

一丶 最大公因数求法&#xff1a;辗转相除法(也称欧几里得算法)原理: 二丶最小公倍数求法&#xff1a;两个整数的最小公倍数等于两整数之积除以最大公约数1 #include <iostream>2 3 using namespace std;4 5 //辗转相除法(欧几里得算法)6 7 int gcd(int a, int b)8 {9…

css实现div内一段文本的两端对齐

在一个固定宽度的div内&#xff0c;使得P标签内的文本两端对齐&#xff1a; text-align: justify;text-justify:inter-ideograph; <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><title>justify</title>…

QT学习三 标准对话框 QMessageBox

QMessageBox内置了几种static方法,例如 QMessageBox::question() 返回值:StandardButton 参数:QWidget * 父窗口&#xff0c;标题名&#xff0c;内容&#xff0c;按钮 YES|NO,默认选中按钮) 示例: 1 #include "mainwindow.h"2 #include <QApplication>3 #incl…

react学习笔记2

1.build文件介绍 &#xff08;1&#xff09;react.js 是react的核心库 &#xff08;2&#xff09;react-dom.js 提供与DOM相关功能 &#xff08;3&#xff09;browser.js 是将JSX语法转为javascript语法 2.组件的继续学习 注意&#xff1a;组件的第一个字母必须大写&…