微天气-技术预研

前言 俗话说:磨刀不误砍柴工。 我想做一个天气类别的小程序,以此进行全栈开发能力的试炼。我想这会是一个微信小程序、是一个可以正常使用的小程序,以Java进行服务端开发,以Mapbox实现天气数据可视化。 但是我是一个后端开发工程师,我不怎么会写页面,我特别的讨厌写CSS。我也没有接触过微信小程序开发,也仅仅知道过Mapbox可以实现好看的地图。所以我需要进行一定的预研,避免后期花费更大的精力用来调整本可以避免的问题。 下面是我计划实现的功能列表: 利用网络接口获取数据(昨日天气、当前天气、预报天气) 实现实时天气与预报数据查看 紧急情况推送 利用地图(mapbox)进行数据可视化 天气分享(图片分享,页面分享) 常用地址 消息推送 个人信息 登录授权 应用Promise进行异步网络请求 使用阿里巴巴矢量图标库作为图标数据源 echarts图标展示 接入疫情数据? 预研对象 天气数据 天气数据需要是真实的、可用的。那么可以通过网络中提供的天气API进行获取。 通过一定的检索后,我选定了两个天气平台,分别是:和风天气、心知天气。 高德天气:大平台,但是目前服务类目比较少 彩云天气:免费接口几乎没有,收费又太贵 心知天气 心知天气试用版与开发者版开发产品几乎等同,且开发者版收费也不贵。最为关键的是,支持以经纬度方式进行天气查询。 和风天气 几乎可以免费使用其提供的所有 API,且同样支持经纬度方式进行天气查询。 小结 对比了这两者,发现至少都需要注册为开发者之后,才可以较好的使用其服务。且两者的开发者认证均需要实名。 关于天气API的选择,我最终选择了和风天气,倒不是因为它可以免费使用。其实,刚开始的时候我更倾向于使用心知天气,因为它还可以直接查昨天的天气(和风对于历史天气的查询比较麻烦)。但是和风天气首页结合了地图进行可视化,而且还提供有APP可以使用(方便参考)。再加上,我想了想,其实我并没有迫切的需要知道昨天的天气情况。 其实最重要的原因在于:我先注册了心知天气(需要审核),过了半天后再去注册了和风天气(需要审核),但是最先通过审核的是和风天气(耗时大概也就半天左右,我是在春节期间注册的)。 前端技术 我并没有想要精通前端技术,但是我需要比较体系的了解一下前端技术,方便进行小程序开发。所以我在B站找了两门前端视频学习(粗略的刷了一遍): 【尚硅谷】Web前端零基础入门HTML5+CSS3基础教程丨初学者从入门到精通 千锋web前端开发项目教程_1000集完全零基础入门HTML5+CSS3+JS到精通 微信小程序 官方文档足以 Mapbox 这里存在一个遗憾,小程序原生并不支持使用如mapbox这样的第三方地图框架,初始想法是通过webview的方式使用mapbox,但是遗憾的是,webview并不对个人类型的小程序开放使用。 所以,退而求其次,选择腾讯地图(及其提供的样式)实现地图浏览。 UI UI部分参考和风天气APP,以及WEUI 总结 天气API使用和风天气(若有空余可考虑抽取一套统一的API,可组合或切换数据来源) 地图使用腾讯地图(微信小程序解决方案,主要在于个性化样式的使用) 基于自定义服务端实现天气代理以及小程序静默登录 UI参考和风天气APP实现 参考 最好的6个免费天气 API 接口对比测评 心知天气-价格方案 和风天气-FAQ H5+Javascript技术结构图 腾讯位置服务-微信小程序解决方案-个性化地图样式 说明 如有冒犯,我在这里先向您道歉,还请联系我进行处理 email: thread_zhou@126.com

April 13, 2022 · 1 min · Fuyi

微天气-序章

前言 天气小程序产生于2022年年初,目的是用于验证自己是否有进入全栈开发(仅前后端)的能力。该项目从2022年1月12号正式启动,于2022年3月19日发布一阶段最终版本(1.1.9),总体耗时2个月零7天。从内容完整度以及界面友好程度来说,我给自己70分。 完成内容 和风天气API接入,可实现实时天气、实时空气、24小时天气预报、7天天气预报 使用echarts for wechat进行24小时天气预报展示 通过腾讯位置服务提供的微信小程序解决方案实现地图个性化展示(目前使用风格:白浅) 通过自建服务实现小程序静默登录 通过自建服务实现关注城市的持久化管理 实现天气分享功能,通过生成一张图片进行分享,可直接分享给朋友或群组 默认通过定位获取所在位置的天气数据 天气数据均通过服务端代理进行获取,从而避免相关key直接暴露在客户端 提供通过经纬度查询所处行政区划的服务,提供行政区划查询服务,皆可获取对应行政区划中心点基于边界数据,数据坐标为4326 服务通过github action自动化进行docker构建,并推送到阿里云镜像服务仓库,而后在阿里云ecs中直接拉取docker进行部署 图片服务则是通过nginx实现反向代理,图片由docker容器内服务创建,通过docker文件映射功能映射到云主机,再通过nginx可实现图片的访问 服务与图片均实现域名访问,且均提供ssl证书 不足 未实现天气地图可视化,即基于mapbox进行地图可视化(webview需要企业认证资质) 未提供坐标转换功能,因目前使用的是腾讯地图(gcj02,即从地图获取的数据均为gcj02),行政区划数据为4326(wgs84),目前是直接将4326作为gcj02进行使用(因为数据的粒度为区县,所以差异不会很大,除非在行政区边界处可能会出现行政区显示错误问题) 未完整实现小程序朋友圈分享功能,因该功能需要所分享页面的数据可直接获取,且分享页面小程序登录功能已被限制,所以目前无法直接提供数据获取服务(需要进行登录态校验,考虑到被攻击的可能) 未完成天气预警数据接入与提示功能 未完成数据推送、个人主页、图层管理功能 分享图片中未实现天气云图叠加功能,仅获取了所在位置范围的影像图与相关注记 服务端代码封装度不够,且DDD的认知不足,导致实践乱七八糟 内容 我计划将拂衣天气开发的完整过程通过文章的方式记录下来,下面是我对该整体内容的编写计划: Name Key Words Summary 序章 前期调研 模型设计 开发环境准备 行政区划数据准备 小程序静默登陆实现 小程序开发(一) 说明主页布局构建,组件拆分情况,实现地图加载以及定位 小程序开发(二) 实现上下滑动功能开发,以及左右滑动组件封装 小程序开发(三) 实时天气栏卡片、文字描述、底部7天天气预报以及Footer部分开发 小程序开发(四) 完成echarts组件封装 天气代理服务开发 提供实时天气、实时空气质量、24小时天气预报、7天天气预报代理服务开发 小程序开发(五) 完成天气部分API对接 行政区划服务开发 提供行政区划查询服务 关注城市服务开发 提供对城市的关注与取消关注能力 小程序开发(六) 完成天气图片分享功能 小程序开发(七) 完成城市选择页面开发与数据API对接 Github Action服务发布 小程序服务发布 终篇 参考 注:拂衣天气小程序的界面设计与交互设计主要参考和风天气APP。当前所述拂衣天气小程序的开发主要用于学习。 致敬和风天气! 和风天气 和风天气开发平台

April 10, 2022 · 1 min · Fuyi

深入拆解Java虚拟机(一)

1. 为什么 Java 需要运行时环境 1.1. Java 程序的启动方式 IDE中启动,比如:Eclipse、IntelliJ IDEA 构建为 jar,通过命令行的方式启动,比如:java -jar application.jar 使用构建工具(如:Gradle、Maven)启动,比如 SpringBoot 应用启动:gradle bootRun、mvn spring-boot:run 1.2. JRE 是什么 在这里引用极客时间课程Java核心技术面试精讲中的一段话 我们日常会接触到 JRE(Java Runtime Environment) 或者 JDK(Java Development Kit)。JRE,也就是 Java 运行时环境,仅包含运行 Java 程序的必须组件,包括 Java 虚拟机以及 Java 核心类库等。而 JDK 可以看作是 JRE 的一个超集,提供了更多工具,比如编译器、各种诊断工具等。 1.3. 为什么需要运行时环境 不是有这么一句话么,计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决。话说回来,Java 代码运行之所以需要运行时环境,主要是由于以下几个方面的原因: Java 语言语法非常复杂,抽象程度高,直接在硬件上运行这种复杂的程序并不现实(并不是不可以,但是这样造成与相应硬件的强耦合,且不便于抽象和复杂语法的实现。),所以需要在运行之前进行一番转换。 实现平台无关性、做到 “Write once, run anywhere”,获得跨平台的能力。这样便需要一个中间层进行解耦,达到上层统一编码、下层跨越平台、中间实现兼容(所以,Java 语言的跨平台特性是由 Java 运行时环境实现的。也就是在不同平台皆有与之相对应的 Java 运行时环境,实现相同定义、不同实现。这样的思想是不是很熟悉,当然,这仅是我的理解)。 提供托管环境(Managed Runtime),该托管环境可以代替我们处理一些通用的、容易出错的、高难度的行为,比如自动内存管理、垃圾回收、安全权限动态检测等。 2. Java 代码在虚拟机中是怎样运行的 2.1. 虚拟机视角 执行 Java 代码首先需要将它编译而成的 class 文件加载到 Java 虚拟机中,加载后的 Java 类会被存放到方法区中。实际运行时,虚拟机会执行方法区内的代码(需要将字节码翻译为机器码,在 HotSpot 实现中,有解释执行和即时编译两种)。...

November 24, 2020 · 1 min · Fuyi

持续交付之标准现行

前言 标准先行并不是一个新鲜玩意,不过是先制定事实标准,而后使用这些标准约束之后的行为。俗话说得好:“没有规矩,不成方圆”。在这里,我想说一下我认为的标准先行以及与持续交付的结合,希望不会对你产生误导。 为什么需要标准先行 我们可以先不去问为什么,而是反过来看这个问题。假设在我们的产物交付过程中,没有任何的标准,给你自由,会发生些什么问题。在一阵头脑风暴(抽搐)之后,我做出如下假设: 乱象百出,群魔乱舞。不论是正确的还是错误的产出,解释如此。比如,整体代码的可读性和可维护性直线下降;分支来回穿插,Commit 信息奇奇怪怪;开发、测试环境存在混用,测试数据过于随意;部署由心,同一个应用在不用的主机上存放位置可能还不同等等。 过程、阶段性产物不统一,且质量高低不齐,严重影响系统集成与交付。 高效完成,但前提是有着意见一致、理念相同、水平相当的一群人。 在我的假想中,自由带来的有好也有坏。但是我仍认为大部分的时候出现的都是坏的影响,毕竟要寻找到一群志同道合的人一起共事,就已经是一件很不容易的事了,且不说每个人都是单独的个体,其思想与灵魂亦是独一无二的。所以,不管在什么样的情况下,我们都需要制定标准来约束我们的行为。统一标准下的行为造成的影响几乎是一致的,那么即使是排错、修改时也是有迹可循。(在这里不会抬杠标准与自由的取舍,存在即是合理。但是从两者在大部分时候所能产生的影响来看,我会采取强标准,若自由的方式,但这绝非将两者置为对立关系。) 都有哪些标准先行 没有绝对通用的标准,任何的标准都是不同场景下最佳实践的总结,且需要持续的进行优化,是可以传承的宝贵知识集合。之所以扯这么一段话,我只是想说目前还处于实践阶段,但是这并不影响制定相关的标准。使用过 SpringBoot 开发的大佬都知道什么是约定优于配置,我认为标准亦是如此,即标准之上是约定。在这里,我将需要先行的标准分为了如下几个方面: 开发模式与分支策略(含 Commit 规范) 编码规范(Java、JavaScript) API 设计规范 数据库设计规范 环境隔离 部署规范 发布流水线标准 标准先行与持续交付 总结 参考文献 持续交付36讲 说明 我不是在卖课 本文大部分内容来源于极客时间以及网络博文节选,如有冒犯,我先向您道歉,另还请告知我进行处理,谢谢 邮箱:thread_zhou@126.com

November 17, 2020 · 1 min · Fuyi

jvm 基础入门

前言 老生长谈,Java是一个什么事物,都有些什么样的特性呢? Java:Java 是一种广泛使用的计算机编程语言,拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。 Java 编程语言的风格十分接近C++语言。继承了C++语言面向对象技术的核心,舍弃了容易引起错误的指针,以引用取代;移除了C++中的运算符重载和多重继承特性,用接口取代;增加垃圾回收器功能。在Java SE 1.5版本中引入了泛型编程、类型安全的枚举、不定长参数和自动装/拆箱特性。Sun微系统对 Java语言 的解释是:“Java 编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言”。 Java 不同于一般的编译语言或解释型语言。它首先将源代码编译成字节码,再依赖各种不同平台上的虚拟机来解释执行字节码,从而具有“一次编写,到处运行”的跨平台特性。在早期 JVM 中,这在一定程度上降低了 Java 程序的运行效率。但在J2SE1.4.2发布后,Java 的运行速度有了大幅提升。 以上内容来自于维基百科,给定了 Java 一个明确的定义,但是对于Java平台以及特性并没有很好的归结,下面是我截取自极客时间Java核心技术面试精讲的部分内容: Java 本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“书写一次,到处运行”(Write once, run anywhere),能够非常容易地获得跨平台能力;另外就是垃圾收集(GC, Garbage Collection),Java 通过垃圾收集器(Garbage Collector)回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。 我们日常会接触到 JRE(Java Runtime Environment)或者 JDK(Java Development Kit)。 JRE,也就是 Java 运行环境,包含了 JVM 和 Java 类库,以及一些模块等。而 JDK 可以看作是 JRE 的一个超集,提供了更多工具,比如编译器、各种诊断工具等。 对于“Java 是解释执行”这句话,这个说法不太准确。我们开发的 Java 的源代码,首先通过 Javac 编译成为字节码(bytecode),然后,在运行时,通过 Java 虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK 提供的 Hotspot JVM,都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。 在维基百科给出的定义中,提到 Java 编程语言是解释性的语言,而在Java核心技术面试精讲中提出该说法不太准确,我比较认可后者的看法。类似 JIT、AOT(Ahead-of-Time Compilation,在执行前直接将字节码编译成机器代码,静态编译) 技术的出现以及实践,使得 Java 的解释性变得不那么纯粹,此时从不同的角度可能会得到不同的结果,比如从占比上考虑,那么 Java 还是解释性的;如果从 JIT 的角度看,此刻的 Java 是编译性的;而从总体的角度来看,则是混合性的(解释和编译的混合)。...

November 10, 2020 · 7 min · Fuyi

持续交付(一)—— 持续交付是什么,和DevOps有什么关系

前言 在我们日常的划水中,常常听到持续集成、持续部署、持续交付、DevOps,那么这些名词到底是什么意思?对我们的日常工作有什么作用呢?能够提高划水的效率呢?其实对于名词的解释始终还是千人千面,不同环境下必然存在不同的产物,我今天想说一说我自己的理解,希望不会对你有误导。 什么是持续交付 持续交付:(英语:Continuous delivery,缩写为 CD),是一种软件工程手法,让软件产品的产出过程在一个短周期内完成,以保证软件可以稳定、持续的保持在随时可以释出的状况。它的目标在于让软件的建置、测试与释出变得更快以及更频繁。这种方式可以减少软件开发的成本与时间,减少风险。 由上可知,持续交付的关注点在于以下几个方面: 短周期 随时可释出 频繁构建 持续交付也可以拆开分析,所谓持续便是一直的频繁的做某件事,有一种开始也是结束,结束也是新的开始的感觉,需要闭环反馈来支持下一个阶段的持续行为;而交付则表示针对当前交付目标释出可行的产物。上面提到的随时可释出和频繁构建很好的体现了持续交付的行为特性,而短周期则是表示每一个阶段的交付过程应该在一个短的周期之内完成,因为短周期意味着快速交付、快速反馈、快速反应并快速的循环反复,而长周期必然会加大一次交付流程的耗时(加大试错成本,无法快速反应),所以这样才能够达到持续交付的目的(随时可交付)。至于什么才是合适的短周期,这个需要结合企业或团队的具体情况(比如项目当前所处阶段、研发人员素质、研发上线流程等)进行考虑。 说了这么多,那么持续交付是以什么样的形式。如何落地到我们日常的工作中的呢?结合美团外卖持续交付分享(美团外卖持续交付的前世今生)和极客时间课程持续交付36讲,我总结了如下的一种描述。(希望不会将你带偏) 关于持续交付,不同的企业、不同的团队站在不同的角度会存在不同的定义,我们可以把持续交付定义为一个产品价值的开发框架(站在企业的角度)、一套软件工程方法论以及许许多多最佳实践的集合。持续交付的落地便是开发框架或软件工程方法论与实际情况的结合的实践(也可以说是最佳实践的排列组合),更详细的实践情况还请接着往后看。 持续集成、持续部署、DevOps和持续交付的关系 持续集成 持续集成:(英语:Continuous integration,缩写CI),是一种软件工程流程,是将所有软件工程师的软件工作副本持续集成到共享主线(mainline)的一种举措。该名称最早由葛来迪.布区(Grady Booch)在他的布区方法中提出,在测试开发驱动(TDD)的实践中,通常还会搭配自动单元测试。持续集成的提出主要是为了解决软件进行系统集成时面临的各种问题,极限编程称这些问题为集成地狱(integration hell)。 持续集成的关注点在于: 频繁集成 有效协作 自动化测试 我们通常会将软件研发工作拆解,拆分成不同模块或不同团队进行编码,编码完成后,进行集成构建和测试。这个从编码到构建再到测试的反复持续过程,就叫做持续集成。由持续集成的定义可联想到版本控制,如 Git,进而可以关联到分支策略(如:Git Flow、GitHub FLow、GitLab Flow),可以说分支策略是持续集成的前置条件。一般情况下,会有一个分支作为集成使用,加上多个特性分支(这里和具体的分支策略强相关,并不是所有团队的都是一样的),当特性分支开发完毕,通过 PR 请求合并到集成分支,此时会触发持续集成工作流程,保证待合并的分支内容是有效的,只有通过持续集成流程验证,才能合并到集成分支。 持续部署 持续部署:(英语:Continuous deployment,缩写为CD),是一种软件工程方法,意指在软件开发流程中,以自动化、频繁而且持续性的,将软件部署到生产环境(production environment)中,使软件产品能够快速的发展。持续部署可以被整合到持续集成与持续交付的流程之中。 持续部署的关注点在于: 自动化的 频繁的 持续性 生产环境 在一些企业的软件部署工作中,仍然存在全人工操作的方式。如果只是单纯的安装部署目的还较为容易(不过繁琐的配置,人工的不规范、不确定性,部署的耗时等都是成本);而如果是已上线的服务的部署工作(服务更新),此时的涉及面以及受影响的范围就比较大了。就算释出的产物已经可以达到可交付的标准,但是要使得用户真正可用,还需要跨越安全、快速以及稳定部署的障碍。那么是否可以将部署的场景和过程进行抽象,使用统一的、规范的、自动化的方法论和流程来约束和实现部署的过程。而持续部署便是这样的一套方法论及实践工具集,旨在规范部署行为,通过自动化提高部署效率,达到持续部署目的。 持续集成、持续部署与持续交付的关系 当提到持续交付的时候,总能关联到持续集成与持续部署,我也一直傻傻分不清这三者之间有什么区别,是什么样的关系。不过从前面给出的定义和关注点可以知道,持续集成侧重于编码阶段内多人协作产物集成的有效性,持续部署侧重于将产物部署到生产环境,而持续交付则侧重于需要随时可释出;而相同点在于他们三者都推崇持续性,即存在一个反馈的过程,且反馈的结果作为下一阶段持续的支持。 再说到持续集成、持续部署和持续交付之间的关系,这里还有一个比较有趣的地方,那就是在不同的视角下,三者的关系并不一样,这里借鉴美团外卖分享的内容(美团外卖持续交付的前世今生)举例,从研发和产品的角度来分析这三者的关系。 研发视角:我们可以看到大部分研发团队,会从软件研发的角度进行定义,他们将软件的开发步骤拆解为持续集成、持续交付、持续部署,其中持续集成指开发人员从编码到构建的过程;持续交付则作为持续集成的自然延续,指将已经集成构建完成的代码,交给测试团队进行测试的过程;持续部署指将测试通过的软件交付给用户的过程。在研发的视角下,持续交付就是一个承上启下的过程,与持续集成形成了闭环,而又为将来达到持续部署做下了准备。此时持续集成 + 持续交付 + 持续部署便是一条完整的发布流水线。 产品视角:产品团队会站在产品的角度来看,他们认为持续交付,是从需求的 PRD 文档提出来,到用户能够感受这个需求的周期。也就是说,此时持续交付是完整的包含了持续集成与持续部署,但是持续交付涵盖范围是大于持续集成 + 持续部署。并且,此时的持续交付流程本身就包含了一条完整的发布流水线。 借用持续交付36讲中的 发布流水线 示意图 说到这里已经不难看出,影响三者之间相互关系的因素主要在于对于持续交付的定位。在这里先说说我自己的看法,我认为持续交付的核心要义在于:短周期、时刻可释出、持续构建,即在于持续的产出与持续验证,由产出与验证形成闭环,进而相互推动,以达到快速反应,快速实现,持续优化。而短周期便是一次交付过程耗时的预定义,也是对于效率的要求,但一定不是对用人的压榨(去你xxx)。在持续交付中,交付对象不一定就是最终用户,所以千万不要认为一定要做到端到端完整才是持续交付。持续交付是一个周期性、可持续的行为,可以只是研发到测试的闭环,此时于研发而言交付对象是测试团队,交付物为通过持续集成验证的代码;也可以如产品视角一般,从需求的 PRD 提出来到用户能够感受到这个需求的周期,此时交付对象为用户,交付物为可用的产品。 所以持续交付可以只是一套方法论,可以是产品价值开发框架,也可以是一部分流程实践。于我个人而言,我更认同持续交付是一套方法论(兼产品价值开发框架),由此指导持续交付体系的建设。如果你问我持续交付体系实践中使用到的技术是不是持续交付,我会说,在其中使用到的技术或工具只是当前持续交付体系建设的一个组成部分。所以,关于持续集成、持续部署、持续交付三者之间的关系,我认同为:三者相互渗透(可能这个词不是很恰当),并没有绝对的独立。 DevOps DevOps:(是 Development 和 Operations 的组合词),是一种重视“软件开发人员(Dev)”和“IT 运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。通过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。 传统的软件组织将开发、IT 运维和质量保障设为各自分离的部门,再这样的环境下如何采用的新的开发方法(例如敏捷软件开发),是一个重要的课题。按照从前的工作方式,开发和部署,不需要 IT 或者 QA 支持(跨部门的持之),而现在却需要极其紧密的多部门协作。而 DevOps 考虑的不仅仅是软件部署,它是一套针对这几个部门间沟通与协作问题的流程和方法。...

November 9, 2020 · 1 min · Fuyi

合并区间

前言 在工作中,还没有仔细的去研究过一些算法实现,直到最近面试才知道,自己的数据结构与算法的功底这么差。 知道总是比不知道的强,那么就一个一个的来吧,我也会通过文字的方式记录自己的算法道路,下一个目标就是LeetCode。 如题(某次面试题) 给定⼀个按开始时间从⼩到大排序的时间区间集合,请将重叠的区间合并。时间区间集合⽤用一个二维数组表示, 二维数组的每⼀行表示⼀个时间区间(闭区间),其中 0 位置元素表示时间区间开始,1 位置元素表示时间区间结束。 例 1:输入:[ [1, 3], [2, 6], [8, 10], [15, 18] ]返回: [ [1, 6], [8, 10], [15, 18]] 解释:时间区间 [1, 3] 和 [2, 6] 有部分重叠,合并之后为 [1, 6] 例 2:输入:[[1, 4], [4, 5]]返回:[[1, 5]]解释:时间区间[1,4] 和 [4,5]重叠了了⼀一个时间点,合并之后为 [1,5] 需要实现的⽅法原型:int[][] merge(int[][] intervals) 二维数组中的每一行表示一个时间区间(闭区间),其中0位置表示开始时间,1位置表示结束时间 给定的时间区间集合按照开始时间从小到大排序,即为有序 这里给出的题还是比较简单的,因为给定的时间区间集合已经是一个有序的集合了,需要实现的内容只剩下区间合并了。 由题中可知,需要合并具有重叠部分的区间,只要确定了重叠的条件,便基本完成了解答。 在已完成时间区间开始时间从小到大的排序后,那么此时的时间区间集合在时间横轴上回呈现类似上图的情况, 此时可以从小到大遍历时间区间集合,进行合并或收集。这里需要一个容器存放目标结果,也就是没有任何交集的时间区间。 具体实现代码如下所示: /** * 时间区间合并方法 * * @param intervals * @return */ public static int [][] merge(int [][] intervals) { // 二维数组行数 int rows = intervals....

September 16, 2020 · 3 min · Fuyi

Socket简单案例实现

前言 终于还是吃了自己的狗粮…… 关于 客户端-服务端 网络模型 常规情况下,网络应用都会存在客户端和服务器端,比如平时外卖应用一样,我们在外卖应用上的操作,都对应着客户端应用向服务器发起请求,并收到响应的过程。服务器为客户端提供业务数据支持,客户端则为用户提供交互界面。 在网络编程中,具体到客户端 - 服务器模型时,我们经常会考虑是使用TCP还是UDP,其实它们二者的区别也很简单:在TCP中连接是谁发起的,在UDP中报文是谁发送的。在TCP中,建立连接是一个非常重要的环节。区别出客户端和服务器,本质上是因为二者编程模型是的不同的。 服务器端需要在一开始就监听在一个确定的端口上,等待客户端发送请求,一旦有客户端建立连接,服务器端则会消耗一定的计算机资源为它服务。 客户端相对简单,它向服务器的监听端口发起请求,连接建立之后,通过连接通路和服务器端进行通信。 还有一点要强调的是,无论是客户端还是服务器端,它们运行的基本单位都是进程(Process),而不是机器。一个客户端,可以同时建立多个到不同服务器的连接;而服务器更是可能在一台机器上部署运行多个服务。 什么是 socket socket是一种操作系统提供的进程间通信机制。这里并不局限于本地,可以是本地进程间的通信,也可以是远端进程间的通信。在操作系统中,通常会为应用程序提供一组应用程序接口(API),称为套接字接口(socket API)。应用程序可以通过套接字接口来使用套接字(socket),已进行数据交换。 这里要注意一下,我们常说的TCP和UDP只是传输层协议,是一种约定。TCP三次握手则是基于TCP协议创建网络通路,该通路的具体创建与实现还是socket完成。socket是我们用来建立连接、传输数据的唯一途径。 如何使用 socket 建立连接 通过前面的客户端 - 服务器模型,我们知道至少需要一对套接字才能进行网络连接的建立,它们分别是服务端套接字和客户端套接字,这里我们先从服务端说起。 服务端准备连接过程 创建套接字(我们这里会使用 TCP的实现) 绑定监听地址:即为绑定需要监听的 IP地址以及 端口号,这里也可以使用本机 IP,但是考虑到部署环境 IP可能会发生变化,所以这里需要进行 IP地址的绑定(比如进行通配地址指定,或者主机存在多张网卡时指定具体的 IP)。如果不显式的指定端口号,就意味着把端口的选择权交给操作系统内核来处理,操作系统内核会根据一定的算法选择一个空闲的端口,完成套接字的绑定。 开启套接字监听模式:bind函数只是实现套接字与地址的关联,如同登记了电话号码,如果要让别人打通带年华,还需要我们把电话设备接入电话线,让服务器真正处于可接听的状态,这个过程需要依赖 listen函数。这里可以这么理解,socket存在 主动和 被动模式,比如服务器就是处于 被动模式下,它需要等待客户端套接字的 主动连接。而 listen函数便是可以将套接字设置为 被动模式,即告诉内核:“我这个套接字是用来等待用户请求的”。 建立连接(accept阻塞):在客户端连接请求到达时,服务端应答成功,便完成连接建立。 package com.zhoujian.socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 线程池工具类 * @author zhoujian */ public class ExecutorServicePool { /** * 初始化线程池 */ public static ExecutorService executorService = Executors.newFixedThreadPool(10); } package com....

August 3, 2020 · 3 min · Fuyi

PostgreSQL11.2 数据恢复记录(From Physical Files)

前言 记录一下PostgreSQL11.2的数据恢复,场景是这样的,我们在A主机(windows server 2008)上安装一个PostgreSQL11.2,突然有一天A主机坏掉了,只能将磁盘卸载下来挂载到新的主机上,但是如何才能快速有效的将之前磁盘中的数据恢复呢? 重新注册为windows服务(失败) 这里我使用主机B(windows server 2012 R2)进行重新注册 参考重新注册PostgreSQL服务 找到并PostgreSQL的安装路径,在此启动命令行工具 使用pg_ctl命令将PostgreSQL11.2重新注册为服务,该命令的具体用法和写法可以查看pg_ctl帮助文档(pg_ctl –help) 结果很现实,没有能够成功,具体的原因未知,返回提示消息为:无法注册服务,错误码1783 此路不通,那我只能换一种方式。 替换PostgreSQL的数据目录(成功) PostgreSQL的数据是存储到data目录下,具体的目录是服务安装的时候指定的,默认是在服务的安装目录下。只要你还拥有完整的data目录,那么你是完全可以从这一份原始物理文件进行数据恢复的。 在这里我使用主机C(windows10)作为测试机 先在C主机上安装PostgreSQL11.2 将原始data目录拷贝到C主机PostgreSQL数据存在目录(即data)的同级目录,并重命名为data-bak(命名随意,符合规则且不冲突就行) 然后参照Change the default PGDATA directory on Windows完成剩余替换步骤 停止C主机的PostgreSQl11.2服务 修改注册表,用意为重新指定服务使用的data目录,替换为我拷贝的data-bak目录,注册表路径:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\pgsql-some version,修改ImagePath项的value值中 -D 参数 到windows服务管理中查看PostgreSQL服务属性,检验可执行文件路径中是否已经指向了data-bak路径 重启PostgreSQL服务 这里有坑,请注意! 如果出现服务启动后停止,请进行以下检查: 1. 检查 data-bak 目录权限,确保该目录和同级的 data 目录的权限一致 2. 检查 是否存在 postmaster.pid 文件,如果存在将其删除(这个未测试,听说可以哦) 3. 检查 postgresql.conf 文件,保持端口号、语言环境(lc_messages、lc_monetary、lc_numeric、lc_time)等基础配置和当前的服务一致,避免配置异常导致启动失败 4. 检查 pg_hba.conf 文件 我按照步骤完成了以上操作,但是发现还是无法在服务管理中启动服务,我通过事件查看器查看日志,也只是看到超时导致启动失败,遂又google+baidu一把,获取链接一个postgresql 在等待服务器启动时超时 在这里提到需要执行一个命令:pg_resetwal -f E:\Server\PostgreSQL\11\data-bak 执行成功会得到打印信息:Write-ahead log reset 然后可以直接在命令行验证是否可以正常启动:pg_ctl -D E:\Server\PostgreSQL\11\data-bak 登录密码应该是旧的密码,我这里是直接使用刚安装PostgreSQL产生的postgresql.conf 替换了data-bak中的postgresql.conf ,所以我的登录密码是新设置的,你实在不知道你就改嘛 我到这里已经能够成功启动了,但是还有坑,还是因为语言环境导致的,如果你的语言环境都一致,那么应该没啥问题了,问题解决方案看后记,最下面...

July 16, 2020 · 1 min · Fuyi

Spring Data JPA 使用入门

前言 我一直认为 Spring Data JPA 是一个好东西,有着自己独特的黑魔法。但是由于目前接触甚少,不知道该如何开启。所以想通过从无到有的过程,逐渐的去认识它,搞清楚它与Mybatis的关系,如果站在架构的角度看会怎么怎么样的情况。在这个过程中,会使用文字的方式将过程记录下来,也算是一点经历。 Spring Data JPA 介绍 From spring.io:Spring Data JPA是Spring Data系列的一个组成部分,可以轻松快捷的实现数据访问层的增强支持,这使得基于Spring且使用了数据库访问技术的应用程序更加容易构建。Spring Data JPA 内置了简单数据库读写操作,包括分页查询,并提供接口以待增强。 Spring Data JPA 是基于Hibernate(在3.2版本中便对JPA提供了完全的支持)、JPA规范的基础上封装的一套ORM框架,可以说就是JPA规范的一个实践落地的产品。Spring Data JPA的内置实现中提供了包括增删改查、分页、自定义SQL的常用功能,且提供接口以待拓展增强。基于Spring Data JPA可以简洁的代码,快速的实现对数据库的访问。 使用示例 环境说明: windows 10 专业版 IntelliJ IDEA 2019.3.1 JDK 1.8 maven 3.6.1 Spring Boot 2.2.5.RELEASE 引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 我这里使用mysql作为数据存储 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> 定义一个简单实体 import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * @author zhoujian */ @Entity public class Customer { @Id @GeneratedValue(strategy= GenerationType....

July 14, 2020 · 3 min · Fuyi