关于ruby:前端学-Ruby唐诗项目部署优化

前言本篇文章和 Ruby 关系不大,只是波及到部署问题 前文花了不少工夫从零到部署唐诗我的项目,过后因为篇幅问题留下了不少的坑 例如能够采纳 docker-compose 来代替两个容器相互拜访、应用 shell 命令在本地部署,本文并未对其进行革新,因为传统部署 Ruby on Rails 的弊病很显著,须要运维教训。为疾速部署 Rails 援用,笔者寻找到了 fly.io。本文将在唐诗我的项目根底上将其部署到 fly.io 上 回顾唐诗 API随机呈现一首诗:/poetry/random用诗的题目查问:/poetry/title/静夜思列出这个诗人的所有诗:/poetry/author/李白列出这个诗人的这首诗:/poetry/author/张若虚/title/春江花月夜如何启动先将我的项目中的 tangpoetry.sql 导入到 postgresql 数据库。能够应用 pgAdmin 也能够应用命令行 psql 导入数据 再 rails s 启动我的项目 查看本地启动没问题后,开始部署我的项目 部署我的项目官网 Rails 部署教程 曾经写的很分明了,能够依照下面的做一遍练练手 这里咱们依照亲自体验 Fly.io 来手把手体验 Fly.io 装置 flyctl装置形式能够参考官网文档:https://fly.io/docs/hands-on/install-flyctl/ 因为笔者是 window,可运行以下命令装置 pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"# 或者powershell -Command "iwr https://fly.io/install.ps1 -useb | iex"如果执行 flyctl version 不报错,就阐明装置胜利了 flyctl version# flyctl.exe v0.1.32 windows/amd64 注册 fly.io如果这是您第一次应用 Fly.io,则须要注册一个帐户 ...

June 16, 2023 · 2 min · jiezi

关于ruby:Java对象的序列化和反序列化

Java 对象的序列化和反序列化是一种将对象转换成字节流并存储在硬盘或网络中,以及从字节流中从新加载对象的操作。Java 的序列化和反序列化提供了一种不便的形式,使得能够将对象在不同的应用程序之间进行交互。 一、什么是 Java 序列化和反序列化?Java 对象的序列化是将 Java 对象转换成字节流的过程,可用于长久化数据,传输数据等。序列化是将 Java 对象的状态示意为字节序列的过程,能够通过网络传送,存储到文件中或者应用其余的长久化技术,如数据库等。序列化后的字节流能够被传输给近程零碎,并在那里从新结构成原始对象。Java 序列化是一个将对象转化为字节流的过程。Java 对象的反序列化是将字节流从新复原为原始对象的过程。反序列化是将字节流转化为对象的过程。反序列化是对象序列化的逆过程,通过反序列化操作可能在接收端复原出与发送端雷同的对象。当咱们须要对存储的对象进行读取操作时,就须要对序列化的字节流进行反序列化操作,将字节流转化为原始的对象信息。二、序列化和反序列化的实现形式Java 中的序列化和反序列化能够通过实现 Serializable 接口来实现。Serializable 是一种标记接口,它没有办法定义,但它具备一个特地的作用,就是用于在形容 java 类可序列化时做类型判断的信息。当一个类实现 Serializable 接口时,表明这个类是可序列化的。Serializable 接口只是一个标识接口,咱们并不需要重载任何办法。在实现 Serializable 接口后,就能够通过 ObjectOutputStream 来将对象序列化,并将序列化后的字节流输入到文件或网络中;同时,也能够通过 ObjectInputStream 来将序列化后的字节流反序列化成对象。java.io.ObjectOutputStream 继承自 OutputStream 类,因而能够将序列化后的字节序列写入到文件、网络等输入流中。来看 ObjectOutputStream 的构造方法: ObjectOutputStream(OutputStream out)一个对象要想序列化,必须满足两个条件: 该类必须实现java.io.Serializable 接口open in new window,否则会抛出NotSerializableException 。该类的所有字段都必须是可序列化的。如果一个字段不须要序列化,则须要应用transient 关键字open in new window进行润饰。该构造方法接管一个 OutputStream 对象作为参数,用于将序列化后的字节序列输入到指定的输入流中。 示例代码如下:import java.io.*; public class SerializationDemo { public static void main(String[] args) { // 序列化对象 Person person = new Person("Tom", 20); try { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("person.txt")); objectOutputStream.writeObject(person); objectOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } // 反序列化对象 try { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("person.txt")); Person restoredPerson = (Person) objectInputStream.readObject(); System.out.println(restoredPerson); objectInputStream.close(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }}} ...

April 18, 2023 · 2 min · jiezi

关于ruby:国产化我们在信创下的改变

信创是什么信创是一个统称概念,理论是把现有与信息技术相干的行业联合在一起,命名为“信息技术利用翻新产业”,简称“信创”。信创包含:根底硬件、根底软件、应用软件、信息安全四大板块。其中,根底硬件次要包含:芯片、服务器/PC、存储等;根底软件包含:数据库、操作系统、中间件等。应用软件包含:办公软件、ERP 和其它软件等;信息安全包含硬件安全、软件平安、平安服务等各类产品。 为什么这两年这么火在近几年,因为种种原因。”信创“、”国产化“、”数字化“、”自主可控“ 等名词曾经高频呈现在各种国央企的我的项目中,根本是跑不掉的一个货色。大抵的推动节奏如下图: 在 2022 年又进一步减速了,代表作是传闻中的 ”79 号文件“,要求: 明确国央企在 2027 年前必须实现国产化替换,而且提出了替换品种和推动时间表。明确替换工作分为三类推动: 全面替换:央企信创 OA、门户、邮箱、纪检、党建、档案管理等。应替就替:战略决策、ERP、风控治理、CRM 经营管理系统等。能替就替:生产制作、研发零碎等。 有风闻这个信创工作将是考核指标之一。不过比拟难讲究,但大趋势的确是往这块在走,根本都在执行和询问。常见细项零碎架构常见以下几种混合选项: 前后端拆散。BFF 架构。微服务架构(SpringCloud)。云原生部署。 编程语言广泛要求应用 Java 语言,应用 SpringCloud 框架集(生态)。有局部会要求应用 JDK8,或是没有明说。JDK 的版本上,有时候也是比拟魔幻的。像客户可能明面上没有间接要求版本,但可能提供的 JDK 版本就是 1.7 或者 1.8 的。这种时候,如果你能够适配,倒还好,不能的话,比较简单的就是要求降版本。数据库广泛要求适配国产化数据库,次要抉择适配达梦数据库、人大金仓等。常见的 MySQL 当初也还能用,很像有则加冕,无则还是连忙适配一下,能加分的感觉。 云厂商和操作系统冀望部署或适配 “华为云”,信创云的底下有的是华为云作为基建搭建的。操作系统经常会和云厂商的部署绑定在一起,总体来解决是华为云部署的统信生态居多,其余某某云并不占大劣势。在 OS 上,很多也会冀望适配欧拉(openEuler)操作系统。CPU 上,也经常与之相绑定,鲲鹏,ARM64 居多。鸿蒙也略有耳闻。通过 36kr 的分享的数据,能够看到华为云这块的劣势: 2C 和 2B 的市场状况截然相同。一些企业的懊恼如果你是非定制化起家时,就会遇到比拟大的懊恼。因为你本来就有一套成熟的技术体系、架构以及生态圈。对应着也有着与之匹配的员工的能力模型建设。但此往往和对方要的信创类诉求,多少有些不匹配。如果你强硬匹配,会呈现不少的综合老本流水。可能会呈现隐性老本大于账目支出的状况。按当初业内常见的模式,根本是非定制化(SaaS)和定制化(大客户)的会离开两个团队,两套模型。若有能用的话,再看适当抽离一些逻辑过去复用。两者如果长期迭代和保护,最终还是会是越来越远。毕竟人家原本就是大客户的定制版。总结明天给大家分享了热火朝天的信创市场、企业的个别思考状况,心愿可能给大家在做技术和方向选型时提供一些帮忙。这篇文章次要做了整体的穿针引线,没有特地的深刻关上。如果对信创有更多实际和教训分享的小伙伴。也欢送一起交换和学习!

April 4, 2023 · 1 min · jiezi

关于ruby:微服务中的鉴权该怎么做

认证与受权首先小伙伴们晓得,无论咱们学习 Shiro 还是 Spring Security,里边的性能无论有哪些,外围都是两个:认证受权 所以,咱们在微服务中解决鉴权问题,也能够从这两个方面来思考。1.1 认证认证,说白了就是登录。传统的 Web 登录是 Cookie+Session 的计划,这种计划依赖于服务器本地内存,在微服务中,因为服务泛滥,这种计划显然不再适合。 可能会有小伙伴说用 Redis+SpringSession 做 Session 共享,这是个方法,然而不是最佳计划,因为这种计划的性能以及可扩展性都比拟差。 所以,微服务中的认证,还是倡议应用令牌的形式,能够抉择 JWT 令牌,这也是目前应用较多的一种计划。然而相熟 JWT 的小伙伴都晓得,纯正的无状态登录无奈实现登记,这就很头大,所以在理论利用中,单纯的应用 JWT 是不行的,个别还是要联合 Redis 一起,将生成的 JWT 字符串在 Redis 上也保留一份,并设置过期工夫,判断用户是否登录时,须要先去 Redis 上查看 JWT 字符串是否存在,存在的话再对 JWT 字符串做解析操作,如果能胜利解析,就没问题,如果不能胜利解析,就阐明令牌不非法。这样有状态登录+无状态登录混在一起的形式,尽管看起来有点不三不四,然而就当下来说,这个折衷的方法算是一个可行的计划了。 其实,下面的计划,说白了,跟传统的 Cookie+Session 没什么两样,思路简直都是齐全 copy 的:传统的 Session 用 Redis 代替了;传统穿梭于服务端和浏览器之间的 jsessionId 被 JWT 字符串代替了;传统的 jsessionId 通过 Cookie 来传输,当初的 JWT 则通过开发者手动设置后通过申请头来传输;传统的 Session 能够主动续签,当初用 JWT 就是手动续签,每次申请达到服务端的时候,就去看下 Redis 上令牌的过期工夫,快过期了,就从新设置一下,其余都截然不同。 这是认证计划的抉择。1.2 受权微服务中受权,也能够应用 Shiro 或者 Spring Security 框架来做,省事一些。思考到微服务技术栈都是 Spring 家族的产品,所以在权限框架这块也是倡议大家首选 Spring Security(如果有小伙伴对 Spring Security 还不相熟的话,能够在微信公众号后盾回复 ss,有教程)。当然,如果感觉 Spring Security 比较复杂想本人搞的话,也是能够的。本人搞的话,也是能够借助于 Spring Security 的思路的,松哥最近的一个我的项目就是这样: ...

April 4, 2023 · 1 min · jiezi

关于ruby:浅尝高并发编程接私活差点翻车

前言作为一名本本分分的练习时长两年半的Java练习生,始终深耕在业务逻辑里,对并发编程的理解仅仅停留在八股文里。一次偶尔的机会,接到一个私活,外围逻辑是写一个 定时拜访api把数据长久化到数据库的小服务。 期间遇到了很多坑还挺有意思,做进去很简略,做得好还是挺难的,这里跟大家分享一下。maven引入内部jar包部署我的项目背景是某家厂商要对接第三方领取公司的open api拿到每日商品销售量与销售额,第三方领取公司就是哗啦啦,这里吐槽下哗啦啦做的凋谢文档写的是真捞。。。首先要把哗啦啦这边提供的jar包引入到咱们的服务里,本地开发间接引入即可能够用maven的一条命令间接把本地的jar包打到本地仓库里。mvn install:install-file -DgroupId=com.uptown -DartifactId=xxx_sdk -Dversion=1.0-SNAPSHOT -Dpackaging=jar -Dfile=E:\uptown\uptown.jar复制代码然而这样部署服务的时候就会发现打不出jar包来,我的项目能跑,然而到要害的调用sdk的时候就报ClassNofFoundException谬误。须要在pom里配置好引入内部jar包的插件才行,这里算是一个小坑。<plugin> <groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>UTF-8</encoding> <compilerArguments> <bootclasspath>${java.home}/lib/rt.jar</bootclasspath> </compilerArguments></configuration></plugin>复制代码上线程池客户大概有150个门店,这样阻塞申请下来仅仅是申请api的耗时就将近半小时,还不算入库的工夫。 这时候依据熟读并背诵的八股文只是,要充分利用cpu的能力无脑抉择线程池,于是起了一个外围线程20个的线程池去并发申请api数据入库。部署之后发现总有这么几条谬误日志。com.*.OrderDetailMapper.updateById(batch index #2) failed. 1 prior sub executor(s) completed successfully, but will be rolled back. Cause: java.sql.BatchUpdateException: Deadlock found when trying to get lock复制代码果然背八股文救不了中国,依据报错判断出入库时死锁了。。。。追究死锁因为我在服务里用了mybatis-plus的orm框架,而且数据是一些订单数据存在一些状态变更,而后服务要同步的数据可能会有更改之前旧数据的场景,所以就用了Mybatis里的SaveOrUpdate办法,好事就好事在这下面。 这个货色还要从mysql数据库的隔离级别开始说起,家喻户晓,依照八股文里mysql隔离级别默认状况下为可反复读,那可反复读隔离机制下防止了脏读,不可反复读,日常开发里也并没有呈现过幻读,看似MVCC多版本并发管制帮咱们避开了幻读。其实不然,幻读的概念与不可反复读类似,不可反复读读到了他人update的数据,幻读读到了他人insert/delete的数据。一个事务在读取了其余事务新增的数据,好像呈现了空想。这里先简略说一下,mysql在可反复读隔离级别下会为每个事务以后读的时候加间隙锁,后续会写一篇mysql在可反复读的隔离级别下如何解决幻读文章。那怎么解决的呢,工夫紧工作重,认真一想这个数据库基本上全是往里增删改的动作,查问的动作简直没有,那为什么不把它隔离级别降级,降成读已提交,这样间隙锁就不失效了。很完满,后续也验证了这个问题,再也没呈现过数据库的死锁状况。数据库链接失落这个问题是真滴恶心,客户买的服务器拉的一批,还买windows服务器,这年头正经人谁用windows,用客户端连都常常失落链接。遇到这个问题非常辣手,那不解决数据就永远不精确。然而想根治这个问题又得失相当,甲方选windows还不就是看重了可视化界面了。这时候再让他们迁徙服务器必定不可能。于是为了解决这个就疯狂在网上搜计划,什么改my.ini的wait_out_time,什么改jdbc的url都白搭,起初我一想,算球了,不靠数据库了,原本想让这么多数据每条都一次胜利也不事实。于是搞了个error_msg表,入库的时候有问题就记在error_msg里,而后启一个定时工作,每1分钟扫描表里所有插入失败记录,一次不行两次,两次不行三次,三次不行始终试。这个重试补上之后的确数据库这方面的坑根本踩的差不多了。服务假死CPU打满这个状况是出在解决mysql链接失落前,过后我想,为什么要用多线程,是因为效率低,效率低其实是低在申请api上,也就是我能够先多线程申请到数据放到一个list里,而后用单个数据库链接去写,这样升高mysql的连接数应该就不会丢了吧。这么容易就丢那还写啥啊。后果我就一个月一个月的拉数据,写完数据清空list,于是搞了个CopyAndWriteList,白背了那么多八股文了,一次也没用过,后果就cpu给人打的满满的。。。起因其实也很简略,就是这个容器外部都用锁保障了线程平安。我就把这个容器当作参数传给每个Thread,弄完间接启动。后果吧是服务忽然就没有新增数据了,而后看日志也没不打日志,jps看服务还在。遇到这种问题先上三板斧,回到家连上服务器上来先看快照,Jstack -l pid。 Locked ownable synchronizers: - None复制代码又是死锁了,这里就不深究了。后续间接换了用LinedblockingQueue的提早队列,另起生产线程一直生产提早队列入库的计划了。线程池莫名失落链接原本认为解决了写库的问题就差不多了,没想到啊没想到,这个不丢那个丢,数据还是有很多差别,找error_msg又没体现进去,一顿排查起初发现是线程池这边的问题。这里的线程池用的Guava的线程池,重写异样捕捉 @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); //线程池中的工作挂掉,主动从新提交该工作 if (!ObjectUtils.isEmpty(t)) { System.out.println("restart fetch data..."); execute(r); }}复制代码期待队列用无界队列,客户的服务器尽管拉,然而内存挺大,订单数撑不爆内存,外围线程10个,感觉一切都是那么正当。然而就是有问题,我发现在afterExecute办法拦挡挂掉的工作异样时发现有很多工作的异样是java.util.concurrent.RejectedExecutionException也就是被执行了回绝策略。这就非常不合理了,只有当队列满了且正在运行的线程数量大于或等于maximumPoolSize,那么线程池才会启动饱和回绝策略。那我定义线程池的时候明明是无界队列,来者不拒。为啥会被执行回绝策略。这个问题困扰了老久老久,以致于我都不想管了,奈何客户始终催始终催,逼得我不得不解决这问题。起初在Stack Overflow上有个老哥在源码中找到起因 public void execute(Runnable command) { ...

April 4, 2023 · 1 min · jiezi

关于ruby:传参base64时的号变空格问题

问题产生上上周,看到一位老哥找咱们组共事联调接口,不晓得是什么问题,两人坐一起搞了快1个小时,看起来如同有点简单。忽然,老哥收回一声卧槽,"我传参里的+号,到你这怎么变成了空格!",这个声音很大,我显著的听到了,很快,我就大略Get到了他们的问题点。我猜想他们遇到的问题大略如下: 咱们的接口协议上,都会将申请数据做一次base64编码,而后放到data参数上。而后某些数据做base64编码后有+,如{"notes":"代码"}base64编码为eyJub3RlcyI6IuS7o+eggSJ9Cg==。而后间接拼到data参数上,即data=eyJub3RlcyI6IuS7o+eggSJ9Cg==,组织成http申请收回。 如果写成等价的curl,就是这样:$ curl http://localhost:8080/send -d 'data=eyJub3RlcyI6IuS7o+eggSJ9Cg=='复制代码写个测试接口调试下看看,如下: 这就是他们遇到的问题,+会变成空格,这个坑其实蛮容易踩到,我本人刚工作时就踩到过这个坑,也屡次看到或听到他人同踩此坑问题起因这个问题和urlencode编码无关,urlencode编码,一般来说,除字母、数字和*,.,-和_这些字节原样输入外,其它字节都会编码为%XX(16进制)的模式。 但有一个特例,如下:String enc = URLEncoder.encode(" ", "UTF-8");System.out.println(enc); // 输入+号 String dec = URLDecoder.decode("+", "UTF-8");System.out.println(dec); // 输入空格复制代码特例就是空格会被编码为+号,反之,+号会被解码为空格! 注:在新的RFC 2396标准中,空格其实也能够编码成%20,而解码时,+号与%20都会被解码为空格。 回忆下面的场景,如果将带有+号的base64字符串,一成不变的封装到data=中,再发送给Tomcat等Web服务器,若Tomcat侧做一次urldecode解码,+是不是就变成空格了而Tomcat的确会做urldecode解码这样的操作,当调用方的Content-Type为application/x-www-form-urlencoded时,这里晓得有这种操作即可,想理解细节可看看我写的这篇文章 由x-www-form-urlencoded引发的接口对接失败解决问题解决这种问题,次要有两种办法,如下: 调用方对参数做urlencode编码。 按标准来看,当Content-Type为application/x-www-form-urlencoded时,调用方是必须对参数名与参数值做urlencode的,java实现如下:String base64Str = Base64.getEncoder().encodeToString(data);String requestStr = "data=" + URLEncoder.encode(base64Str, "UTF-8");复制代码这里做了urlencode后,+会被编码为%2B,再由服务端解码,就会变成原样的+号。 注:如果是应用apache的HttpClient,可思考应用UrlEncodedFormEntity,它会主动做这个事件。 应用urlsafe版本的base64。 一般的base64不能间接作为参数值,因为它可能蕴含+、/这两个url不平安的字符,所以base64有个变种叫urlBase64,它将+、/替换成了url平安的-、_,java实现如下:String urlBase64Str = Base64.getUrlEncoder().encodeToString(data);String requestStr = "data=" + urlBase64Str;

March 28, 2023 · 1 min · jiezi

关于ruby:Vue3-巧用自定义全局属性封装只为高效率

简介要想缩小重复性代码,少不了全局属性配置的问题,做这方面的模块封装。当然就是为了少敲点代码,以及为了后续需要变更的时候,咱们只须要批改一处中央,而不须要在用到这个模块的页面都要改变一遍,这难道不是内耗,和浪费时间吗。出于这个目标,再次深研了扩大全局属性扩大全局属性某些插件会通过 app.config.globalProperties 为所有组件都装置全局可用的属性。举例来说,import axios from 'axios' declare module 'vue' { interface ComponentCustomProperties { $http: typeof axios $translate: (key: string) => string} }复制代码咱们可能为了申请数据而装置了 this.$http,或者为了国际化而装置了 this.$translate。为了使 TypeScript 更好地反对这个行为,Vue 裸露了一个被设计为能够通过 TypeScript 模块扩大来扩大的 ComponentCustomProperties 接口:类型扩大的地位咱们能够将这些类型扩大放在一个 .ts 文件,或是一个影响整个我的项目的 *.d.ts 文件中。无论哪一种,都应确保在 tsconfig.json 中包含了此文件。对于库或插件作者,这个文件应该在 package.json 的 types 属性中被列出。留神:这里的官网介绍,是为后续工具类或者组件封装做后期思路的筹备为了利用模块扩大的劣势,咱们须要确保将扩大的模块放在 TypeScript 模块 中。 也就是说,该文件须要蕴含至多一个顶级的 import 或 export,即便它只是 export {}。如果扩大被放在模块之外,它将笼罩原始类型,而不是扩大!自定义组件封装Vue3过滤器制作对于 Vue2 中的过滤器,过滤器能够艰深了解成是一个非凡的办法,用来加工数据的。而在 vue3 中,曾经去掉了 filters 这个属性,然而咱们的需要还是在的。而官网给的倡议是能够通过写composition办法,来代替;然而这样子的话,每次须要应用到相似过滤器的这个办法,都要进行导入,还是比拟麻烦;索性在全局配置中,附加进去,如下:在 main.js 中加上 //vue3配置全局过滤器app.config.globalProperties.$filters = { //formatTime过滤器的名称 isPeriodEmpty(value: string) { // 实现一个字段为空返回--的过滤器 return value || '--'},};复制代码在组件中应用如下<template #operation="scope"> {{ $filters.isPeriodEmpty(scope.row.abc) }} </template>复制代码然而这样做的话,ts语法会提醒谬误 为了解决这个问题,咱们这里利用到了上文简介中我所提到的扩大全局属性 ComponentCustomProperties 从上文简介类型扩大的地位,tsconfig.json中 "include": ["/.ts", "src//.d.ts", "src/types/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],复制代码蕴含的任意地位,增加vue.d.ts文件,并写入// 扩大全局属性类型declare module 'vue' { ...

March 22, 2023 · 1 min · jiezi

关于ruby:在Vue3这样子写页面更快更高效

前言在开发治理后盾过程中,肯定会遇到不少了增删改查页面,而这些页面的逻辑大多都是雷同的,如获取列表数据,分页,筛选性能这些基本功能。而不同的是出现进去的数据项。还有一些操作按钮。 对于刚开始只有 1,2 个页面的时候大多数开发者可能会间接将之前的页面代码再拷贝多一份进去,而随着我的项目的推动相似页面数量可能会越来越多,这间接导致我的项目代码耦合度越来越高。这也是为什么在我的项目中一些可复用的函数或组件要抽离进去的次要起因之一上面,咱们封装一个通用的useList,适配大多数增删改查的列表页面,让你更快更高效的实现工作,准点上班 ~ 前置常识 VueVue Composition Api 封装咱们须要将一些通用的参数和函数抽离进去,封装成一个通用hook,后续在其余页面复用雷同性能更加简略不便。定义列表页面必不可少的分页数据export default function useList() { // 加载态 const loading = ref(false); // 当前页 const curPage = ref(1); // 总数量 const total = ref(0); // 分页大小 const pageSize = ref(10);}复制代码如何获取列表数据思考一番,让useList函数接管一个listRequestFn参数,用于申请列表中的数据。定义一个list变量,用于寄存网络申请回来的数据内容,因为在外部无奈间接确定列表数据类型,通过泛型的形式让内部提供列表数据类型。export default function useList<ItemType extends Object>( listRequestFn: Function) { // 疏忽其余代码 const list = ref<ItemType[]>([]);}复制代码在useList中创立一个loadData函数,用于调用获取数据函数,该函数接管一个参数用于获取指定页数的数据(可选,默认为curPage的值)。 执行流程 设置加载状态调用内部传入的函数,将获取到的数据赋值到list和total中敞开加载态 这里应用了 async/await 语法,假如申请出错、解构出错状况会走 catch 代码块,再敞开加载态 这里须要留神,传入的 listRequestFn 函数接管的参数数量和类型是否失常对应上请依据理论状况进行调整 export default function useList<ItemType extends Object>( listRequestFn: Function) { // 疏忽其余代码 // 数据 const list = ref<ItemType[]>([]); // 过滤数据 // 获取列表数据 const loadData = async (page = curPage.value) => { ...

March 22, 2023 · 4 min · jiezi

关于ruby:MongoDB为什么比Mysql高效

在当今互联网时代,数据是价值连城。为了更高效地存储和治理数据,数据库成为了重要的组成部分。MySQL和MongoDB都是罕用的数据库,但MongoDB比MySQL更为高效,这是为什么呢?数据存储形式不同MysqlMySQL是一种关系型数据库管理系统(RDBMS),它应用传统的表格形式来存储数据。具体来说,MySQL中的数据是以表格(也称为关系)的模式组织的,每个表格蕴含若干列和行。列示意数据的属性,行示意具体的数据记录。在MySQL中,表格中的每一列都必须有一个数据类型来定义其数据格式。MySQL反对的数据类型包含整型、浮点型、字符型、日期型等等。此外,MySQL还反对定义主键、外键、索引等数据束缚,以保证数据的完整性和一致性。MySQL中的数据以文件的模式存储在磁盘上,每个数据库对应一个或多个物理文件。其中,一个非凡的文件称为“数据字典”,它存储了数据库中所有表格、列、索引、束缚等信息。在查问和批改数据时,MySQL会首先从数据字典中读取表格构造信息,而后再依据表格构造和索引信息定位具体的数据记录。总的来说,MySQL的数据存储形式是传统的关系型数据库形式,实用于结构化数据的存储和查问。MySQL也反对一些非关系型数据的存储形式,比方BLOB和TEXT类型的数据,但相比于MongoDB等面向文档的数据库,MySQL的非结构化数据处理能力绝对较弱。MongoDBMongoDB是一种面向文档的数据库管理系统,它应用文档的形式来存储数据。具体来说,MongoDB中的数据是以BSON(Binary JSON)文档的模式组织的,每个文档都是一个键值对的汇合,能够蕴含任何类型的数据。在MongoDB中,数据存储在汇合(Collection)中,每个汇合蕴含若干文档。汇合的构造非常灵活,同一个汇合中的文档能够有不同的构造,每个文档能够有本人的字段和值。这种构造非常适合存储非结构化数据,比方日志、社交媒体数据等等。MongoDB中的数据以文件的模式存储在磁盘上,每个数据库对应一个或多个物理文件。在MongoDB中,数据的读写操作都是基于内存的,MongoDB会将频繁拜访的数据缓存在内存中,以进步查问和更新的速度。MongoDB还反对正本集和分片机制,能够轻松地实现数据的程度扩大和负载平衡。在正本集中,每个节点都是一个残缺的MongoDB实例,其中一个节点被指定为主节点,其余节点作为从节点。主节点负责接管所有的写操作和查问操作,从节点负责复制主节点的数据,并提供读操作。在分片机制中,MongoDB会将数据依照特定的规定分成多个分片,每个分片存储一部分数据,以实现程度扩大。总的来说,MongoDB的数据存储形式是面向文档的,非常适合存储非结构化数据。MongoDB还反对分布式部署和扩大,能够解决大规模的数据和高并发拜访。索引机制不同MysqlMySQL索引是一种数据结构,它可能放慢数据检索的速度。MySQL反对多种类型的索引,包含B-tree索引、哈希索引、全文索引等等。其中,B-tree索引是最罕用的索引类型。B-tree索引是一种均衡树结构,它将索引值依照肯定的程序组织成一个树形构造,每个节点蕴含若干索引值和指向子节点的指针。在B-tree索引中,查问操作会从根节点开始,依据索引值的大小关系顺次遍历子节点,直到找到指标节点或者达到叶子节点。这种构造能够十分疾速地定位到指标数据记录,因为树的高度通常很小,而且每个节点都能够包容很多索引值。MySQL中的B-tree索引反对单列索引和组合索引。单列索引只蕴含一个列的值,而组合索引则蕴含多个列的值,多个列的值组合在一起作为索引值。组合索引能够更加准确地定位数据记录,但它的创立和保护老本也更高。MySQL还反对笼罩索引,即查问所需的数据都能够从索引中获取,不须要再拜访数据表。笼罩索引能够大大减少查问的磁盘访问量,进步查问的性能。总的来说,MySQL的索引机制能够放慢数据检索的速度,缩小磁盘访问量,进步数据库的性能。不过,索引也有一些毛病,比方减少了数据的存储空间、升高了写入性能等等。因而,在应用索引时须要依据具体的状况进行衡量和抉择。MongoDBMongoDB的索引机制是一种基于B-tree的索引实现,相似于MySQL的B-tree索引。MongoDB反对单字段、多字段、复合、文本、地理位置等多种类型的索引。在MongoDB中,创立索引能够应用createIndex()办法,能够指定索引类型、索引字段、索引方向等参数。例如,上面的代码创立一个名为“username”的单字段索引:db.collection.createIndex({username: 1})复制代码MongoDB的索引机制能够大大提高数据的查问性能,因为它可能在索引中疾速定位数据记录,而不须要扫描整个数据汇合。如果一个查问蕴含多个条件,能够应用复合索引来进步查问性能。例如,上面的代码创立一个蕴含“username”和“email”的复合索引:db.collection.createIndex({username: 1, email: 1})复制代码在应用MongoDB的索引时须要留神以下几点: 创立过多的索引会占用大量的存储空间,影响性能,因而须要依据理论需要进行抉择。索引会减少写入操作的开销,因为每次写入操作都须要更新索引。如果写入操作频繁,能够思考应用稠密索引或者禁用索引。索引的抉择和设计要依据具体的查问需要进行优化,避免出现有效的或者低效的索引。 总的来说,MongoDB的索引机制能够进步数据的查问性能,但须要依据具体情况进行抉择和优化。分布式架构不同MysqlMySQL是一个传统的关系型数据库,最后设计并没有思考分布式架构。然而,随着数据量和访问量的一直增长,单机MySQL曾经无奈满足高可用、高性能的要求,因而呈现了分布式MySQL架构。分布式MySQL架构通常采纳主从复制和分片技术。主从复制是指将数据从主数据库复制到多个从数据库,从数据库能够解决读申请和备份数据。主数据库负责解决写申请,从数据库负责读申请。分片技术是指将数据依照肯定的规定划分为多个片(或者分区),每个片存储在不同的数据库节点上,通过路由技术来决定哪个节点解决特定的申请。分布式MySQL架构的长处是能够进步数据处理能力、升高单点故障危险、加强零碎的可扩展性和可靠性。不过,分布式MySQL架构也有一些毛病,例如: 零碎的复杂度减少,须要额定的保护和管理工作。数据的一致性和可靠性可能会受到影响,须要采纳适合的复制和同步机制来保证数据的一致性。分片机制可能会导致一些跨片的操作成为瓶颈,须要采纳适合的路由算法和负载平衡策略。分布式MySQL架构须要更高的硬件老本和网络带宽。 总的来说,分布式MySQL架构须要依据具体的业务需要和数据规模来进行设计和优化,须要综合思考性能、可靠性、一致性、复杂度等多个方面。MongoDBMongoDB是一种分布式文档型数据库,具备天生的分布式架构设计。MongoDB的分布式架构蕴含多个组件,包含分片、正本集和分布式查问路由。 分片 MongoDB的分片技术将数据宰割成多个分片(shard),每个分片存储局部数据,多个分片组成一个分片集群。分片能够依照数据的范畴、哈希值、分片键等形式进行调配。在分片集群中,有一个特定的MongoDB节点充当分片协调器(mongos),负责接管客户端的申请,将申请路由到对应的分片节点上,并将后果返回给客户端。 正本集 为了进步数据的可靠性和可用性,MongoDB采纳正本集(replica set)技术。正本集包含一个主节点和多个从节点,主节点负责解决写申请和同步数据到从节点,从节点负责解决读申请和备份数据。如果主节点生效,从节点能够选举一个新的主节点,保证系统的高可用性。 分布式查问路由 MongoDB的分布式查问路由机制将查问申请路由到适合的分片节点上。当客户端向mongos发送查问申请时,mongos会将申请转发给对应的分片节点,如果申请波及多个分片,mongos会主动将后果聚合返回给客户端。为了进步查问性能,MongoDB反对在每个分片上执行局部查问,而后将后果返回给mongos,在mongos上再进行聚合。总的来说,MongoDB的分布式架构设计能够进步数据的解决能力、可靠性和可用性,同时也减少了零碎的复杂度和治理难度。须要依据具体的业务需要和数据规模来进行分片、正本集和查问路由的配置和优化。总结 MysqlMongodb数据存储形式MySQL采纳的是传统的关系型数据库,数据以表格的模式存储,每个表都有固定的列和行。这种构造使得MySQL在解决结构化数据时表现出色,然而在解决非结构化数据时体现不佳。MongoDB则是面向文档的数据库,它应用文档的形式存储数据,文档中能够蕴含任何类型的数据,而且不须要当时定义其构造。这种形式使得MongoDB在存储和查问非结构化数据时更加高效。索引机制索引是进步数据库查问效率的重要伎俩,MySQL和MongoDB的索引机制也不同。MySQL采纳B+树索引,这种索引实用于结构化数据,但对非结构化数据的查问效率较低。MongoDB采纳的是BSON索引,BSON是一品种JSON的二进制编码格局,它反对对文档中的任何字段进行索引,查问速度十分快。此外,MongoDB还反对天文空间索引和全文索引等高级索引形式,使得非结构化数据的查问更加高效。分布式架构MySQL在分布式环境下须要进行数据分片,这会带来许多治理和保护的问题。MongoDB天生就是分布式的,它采纳的是正本集和分片机制,能够轻松地实现数据的程度扩大和负载平衡。MongoDB还具备主动故障转移和主动复原等性能,当节点产生故障时会主动将其替换为备用节点,保证系统的高可用性和数据的安全性。综上所述,MongoDB比MySQL更适宜存储和查问非结构化数据,具备更高的查问效率和更好的分布式扩展性。当然,在理论应用中,抉择哪种数据库要依据具体的业务需要和数据特点来确定。

March 7, 2023 · 1 min · jiezi

关于ruby:JDK17会代替JDK8吗

俗话说:“它发认它发,我用Java8”。然而随着Spring 6.0以及SpringBoot 3.0的公布,JDK17仿佛大有取代JDK8的趋势了。 Spring Boot 3.0 requires Java 17 as a minimum version. If you are currently using Java 8 or Java 11, you'll need to upgrade your JDK before you can develop Spring Boot 3.0 applications. Spring 6.0&SpringBoot 3.0对AOT的反对,能极大进步利用的启动速度,从而能够补救Java在云原生、Serverless等畛域的缺点,据我所知,某驰名大厂外部曾经在进行降级了。另外,JDK17是一个LTS(长期反对版),能够收费商用到2029年,JDK17自身在性能上也有优化,比方对于NIO的性能优化,至多晋升了10%。随着各大框架对JDK17的反对,JDK17取代JDK8只是工夫问题。这里我大抵列以下JDK9-JDK17中几个要害的新个性: sealed 密封类文本块record 纪录类G1成为默认垃圾收集器ZGC的欠缺与降级JDK模块化JFR飞行器新swich表达式虚构线程... 比方SpringBoot3.0的源码中就用到了新个性: 尽管JDK17跟JDK8相比拟的确减少了很多新个性,不论是语法上、性能上,都在踊跃的汲取其余语言的特点,并且整个Java生态也在一直的降级为JDK17,然而对于公司而言,除非是新我的项目、新利用,不然是不太可能把现有我的项目降级到JDK17的。你们我的项目中,当初用的是JDK哪个版本呢?

February 27, 2023 · 1 min · jiezi

关于ruby:MyBatis获取参数值的两种方式-与

{}与${}的区别{}的实质是占位符赋值,${}的实质是字符串拼接${}应用字符串拼接的形式拼接sql,若为字符串类型或日期类型的字段进行赋值时,须要手动加单引号 {}应用占位符赋值的形式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,能够主动增加单引号如何应用${}与#{}获取参数值获取单个字面量类型的参数 此时能够应用#{}和${}以任意的名称(最好见名识意)获取参数的值,留神${}须要手动加单引号 编写mapper接口: public class UserMapper { //通过id查问用户信息User getUserById(Integer id);}复制代码 编写映射文件: <select id="getUserById" resultType="com.mybatis.pojo.User"> SELECT * FROM user WHERE `id` = #{id}</select>复制代码或<select id="getUserById" resultType="com.mybatis.pojo.User"> SELECT * FROM user WHERE id = '${id}'</select>复制代码多个字面量类型的参数 若mapper接口中的办法参数为多个时,此时MyBatis会主动将这些参数放在一个map汇合中 以arg0,arg1...为键,以参数为值;以param1,param2...为键,以参数为值; 因而只须要通过${}和#{}拜访map汇合的键就能够获取绝对应的值,留神${}须要手动加单引号。 应用arg或者param都行,要留神的是,arg是从arg0开始的,param是从param1开始的 编写mapper接口: public class UserMapper { //通过姓名和年龄查问用户信息User getUserByNameAndAge(String name, Integer age);}复制代码 编写映射文件: <select id="getUserByNameAndAge" resultType="com.mybatis.pojo.User"> SELECT * FROM user WHERE name = #{arg0} AND age = #{arg1} </select>复制代码或<!--User checkLogin(String username,String password);--><select id="getUserByNameAndAge" resultType="com.mybatis.pojo.User"> SELECT * FROM user WHERE name = '${param1}' AND age = '${param2}'</select>复制代码map汇合类型的参数 ...

February 22, 2023 · 2 min · jiezi

关于ruby:详解Redisson分布式限流的实现原理

咱们目前在工作中遇到一个性能问题,咱们有个定时工作须要解决大量的数据,为了晋升吞吐量,所以部署了很多台机器,但这个工作在运行前须要从别的服务那拉取大量的数据,随着数据量的增大,如果同时多台机器并发拉取数据,会对上游服务产生十分大的压力。之前曾经减少了单机限流,但无奈解决问题,因为这个数据工作运行中只有不到10%的工夫拉取数据,如果单机限流限度太狠,尽管集群总的申请量管制住了,但工作吞吐量又降下来。如果限流阈值太高,多机并发的时候,还是有可能压垮上游。 所以目前惟一可行的解决方案就是分布式限流。 我目前是抉择间接应用Redisson库中的RRateLimiter实现了分布式限流,对于Redission可能很多人都有所耳闻,它其实是在Redis能力上构建的开发库,除了反对Redis的根底操作外,还封装了布隆过滤器、分布式锁、限流器……等工具。明天要说的RRateLimiter及时其实现的限流器。接下来本文将具体介绍下RRateLimiter的具体应用形式、实现原理还有一些注意事项,最初简略谈谈我对分布式限流底层原理的了解。RRateLimiter应用 RRateLimiter的应用形式异样的简略,参数也不多。只有创立出RedissonClient,就能够从client中获取到RRateLimiter对象,间接看代码示例。RedissonClient redissonClient = Redisson.create();RRateLimiter rateLimiter = redissonClient.getRateLimiter("xindoo.limiter");rateLimiter.trySetRate(RateType.OVERALL, 100, 1, RateIntervalUnit.HOURS); 复制代码 rateLimiter.trySetRate就是设置限流参数,RateType有两种,OVERALL是全局限流 ,PER_CLIENT是单Client限流(能够认为就是单机限流),这里咱们只探讨全局模式。而前面三个参数的作用就是设置在多长时间窗口内(rateInterval+IntervalUnit),许可总量不超过多少(rate),下面代码中我设置的值就是1小时内总许可数不超过100个。而后调用rateLimiter的tryAcquire()或者acquire()办法即可获取许可。rateLimiter.acquire(1); // 申请1份许可,直到胜利boolean res = rateLimiter.tryAcquire(1, 5, TimeUnit.SECONDS); // 申请1份许可,如果5s内未申请到就放弃复制代码 应用起来还是很简略的嘛,以上代码中的两种形式都是同步调用,但Redisson还同样提供了异步办法acquireAsync()和tryAcquireAsync(),应用其返回的RFuture就能够异步获取许可。RRateLimiter的实现 接下来咱们顺着tryAcquire()办法来看下它的实现形式,在RedissonRateLimiter类中,咱们能够看到最底层的tryAcquireAsync()办法。 private <T> RFuture<T> tryAcquireAsync(RedisCommand<T> command, Long value) { byte[] random = new byte[8]; ThreadLocalRandom.current().nextBytes(random); return commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, command, "——————————————————————————————————————" + "这里是一大段lua代码" + "____________________________________", Arrays.asList(getRawName(), getValueName(), getClientValueName(), getPermitsName(), getClientPermitsName()), value, System.currentTimeMillis(), random);}复制代码 映入眼帘的就是一大段lua代码,其实这段Lua代码就是限流实现的外围,我把这段lua代码摘出来,并加了一些正文,咱们来具体看下。local rate = redis.call("hget", KEYS[1], "rate") # 100 local interval = redis.call("hget", KEYS[1], "interval") # 3600000local type = redis.call("hget", KEYS[1], "type") # 0assert(rate ~= false and interval ~= false and type ~= false, "RateLimiter is not initialized")local valueName = KEYS[2] # {xindoo.limiter}:value 用来存储残余许可数量local permitsName = KEYS[4] # {xindoo.limiter}:permits 记录了所有许可收回的工夫戳 ...

February 14, 2023 · 2 min · jiezi

关于ruby:我终于搞懂了asyncawaitpromise和setTimeout的执行顺序

从一道题目登程明天看到一道面试题,是对于async/await、promise和setTimeout的执行程序,题目如下:async function async1() { console.log('async1 start');await async2();console.log('asnyc1 end');}async function async2() { console.log('async2');}console.log('script start');setTimeout(() => { console.log('setTimeOut');}, 0);async1();new Promise(function (reslove) { console.log('promise1');reslove();}).then(function () { console.log('promise2');})console.log('script end');复制代码我给出的答案:script startasync1 startasync2asnyc1 end // xpromise1script endpromise2setTimeOut复制代码正确的答案:script startasync1 startasync2promise1script endasnyc1 endpromise2setTimeOut复制代码为什么promise1比asnyc1 end先进去呢?带着这个疑难,我去理解了一下事件循环机制。js EventLoop 事件循环机制JavaScript的事件分两种: 宏工作(macro-task)微工作(micro-task)scriptpromise. then/catch/finally )setTimeoutprocess.nextTick(Node.js 环境)setIntervalMutaionOberver(浏览器环境)setImmediate(Node.js 环境)Object.observeIO操作xUI交互事件xpostMessagexMessageChannelx事件的执行程序,是先执行宏工作,而后执行微工作,这个是根底,工作能够有同步工作和异步工作,同步的进入主线程,异步的进入Event Table并注册函数,异步事件实现后,会将回调函数放入Event Queue中(宏工作和微工作是不同的Event Queue),同步工作执行实现后,会从Event Queue中读取事件放入主线程执行,回调函数中可能还会蕴含不同的工作,因而会循环执行上述操作。 留神: setTimeOut并不是间接的把你的回掉函数放进上述的异步队列中去,而是在定时器的工夫到了之后,把回掉函数放到执行异步队列中去。如果此时这个队列曾经有很多工作了,那就排在他们的前面。这也就解释了为什么setTimeOut为什么不能精准的执行的问题了。setTimeOut执行须要满足两个条件: 主过程必须是闲暇的状态,如果到工夫了,主过程不闲暇也不会执行你的回调函数这个回调函数须要等到插入异步队列时后面的异步函数都执行完了,才会执行 promise、async/await首先,new Promise是同步的工作,会被放到主过程中去立刻执行。而.then()函数是异步工作会放到异步队列中去,那什么时候放到异步队列中去呢?当你的promise状态完结的时候,就会立刻放进异步队列中去了。带async关键字的函数会返回一个promise对象,如果外面没有await,执行起来等同于一般函数;如果没有await,async函数并没有很厉害是不是。await 关键字要在 async 关键字函数的外部,await 写在里面会报错;await如同他的语意,就是在期待,期待右侧的表达式实现。此时的await会让出线程,阻塞async内后续的代码,先去执行async外的代码。等里面的同步代码执行结束,才会执行外面的后续代码。就算await的不是promise对象,是一个同步函数,也会等这样操作。流程梳理咱们整体再梳理一下下面代码执行的流程: 整个代码片段(script)作为一个宏工作执行console.log('script start'),输入script start;执行setTimeout,是一个异步动作,放入宏工作异步队列中;执行async1(),输入async1 start,持续向下执行;执行async2(),输入async2,并返回了一个promise对象,await让出了线程,把返回的promise退出了微工作异步队列,所以async1()上面的代码也要期待下面实现后继续执行;执行 new Promise,输入promise1,而后将resolve()放入微工作异步队列;执行console.log('script end'),输入script end;到此同步的代码就都执行实现了,而后去微工作异步队列里去获取工作接下来执行resolve(async2返回的promise返回的),输入了async1 end;而后执行resolve(new Promise的),输入了promise2;最初执行setTimeout,输入了settimeout。 在第4步中, await 这里有一个机制, 就是 await 的期待, 不会阻塞内部函数的执行, 而 await 期待的 如果是一个 Promise 则 Promise 外面的代码还是同步执行, 如果不是 Promise ,就会应用 Promise.resolve 来进行封装, 这里的 async2 是一个 async 办法, 外面的 打印会同步执行, 而 await async2() 前面的代码 会放到微工作队列中的第一个地位,期待内部同步代码执行结束当前再执行。所以我晓得了script end为什么会优先于async1 end输入。 ...

February 8, 2023 · 1 min · jiezi

关于ruby:Spring中singleton-bean如何同时服务多个请求

当我开始学习 Spring 时,两个“难”的问题次要在我脑海中回旋: 如何创立单例 bean,而后如何在不同的类中主动拆卸单个 bean?设想一下这种状况: 有 2 个用户,其中一个想要登录,另一个想要同时在咱们的应用程序中创立报告。login 和 createReport 办法都应用范畴为单例的 userService bean。在这种状况下,这些办法是否按程序应用该单例 bean?否则 singleton bean 如何同时解决多个申请?答复他们并不像我想的那么艰难。只是须要廓清简略但重要的要点。这就是为什么我会尝试用根本的代码示例来形容它们。让咱们开始:1.先讲一下Spring容器会比拟好。因为我认为这会帮忙你在脑海中更好地形容过程。Spring 容器在其中创立 bean。创立所需的 bean 后,它会注入它们的依赖项。容器通过读取配置元数据(XML 或 Java 正文)来获取指令。因而,在初始化 Spring 容器后,您的应用程序就能够应用了,如下图所示: 当你像上面这样定义一个 bean 定义时,你通知容器它必须只为容器中的那个 bean 定义创立一个实例:<bean id=”accountDao” class=”…” scope=”singleton”/>此单个实例存储在此类单例 bean 的缓存中。而后 Spring 容器将这个缓存的对象返回给具备该 bean 定义的 bean 的所有申请和援用: 如果咱们想用 new() 运算符显示下面的示例,以形容 Spring 容器在应用程序启动时所做的简化视图,咱们能够编写如下代码:UserService userService = new UserService(); UserController userController = new UserController();userController.userService = userService; ReportController reportController = new ReportController();reportController.userService = userService复制代码@RestControllerpublic class UserController { ...

February 8, 2023 · 1 min · jiezi

关于ruby:订单30分钟未支付自动取消怎么实现

目录 理解需要计划 1:数据库轮询计划 2:JDK 的提早队列计划 3:工夫轮算法计划 4:redis 缓存计划 5:应用音讯队列 理解需要在开发中,往往会遇到一些对于延时工作的需要。例如 生成订单 30 分钟未领取,则主动勾销生成订单 60 秒后,给用户发短信 对上述的工作,咱们给一个业余的名字来形容,那就是延时工作。那么这里就会产生一个问题,这个延时工作和定时工作的区别到底在哪里呢?一共有如下几点区别定时工作有明确的触发工夫,延时工作没有定时工作有执行周期,而延时工作在某事件触发后一段时间内执行,没有执行周期定时工作个别执行的是批处理操作是多个工作,而延时工作个别是单个工作上面,咱们以判断订单是否超时为例,进行计划剖析计划 1:数据库轮询思路该计划通常是在小型我的项目中应用,即通过一个线程定时的去扫描数据库,通过订单工夫来判断是否有超时的订单,而后进行 update 或 delete 等操作实现能够用 quartz 来实现的,简略介绍一下maven 我的项目引入一个依赖如下所示<dependency>   <groupId>org.quartz-scheduler</groupId>   <artifactId>quartz</artifactId>   <version>2.2.2</version></dependency>复制代码调用 Demo 类 MyJob 如下所示package com.rjzheng.delay1;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;public class MyJob implements Job {   public void execute(JobExecutionContext context) throws JobExecutionException {       System.out.println("要去数据库扫描啦。。。");   }   public static void main(String[] args) throws Exception {       // 创立工作       JobDetail jobDetail = JobBuilder.newJob(MyJob.class)               .withIdentity("job1", "group1").build();       // 创立触发器 每3秒钟执行一次       Trigger trigger = TriggerBuilder               .newTrigger()               .withIdentity("trigger1", "group3")               .withSchedule(                       SimpleScheduleBuilder                               .simpleSchedule()                               .withIntervalInSeconds(3).                               repeatForever())               .build();       Scheduler scheduler = new StdSchedulerFactory().getScheduler();       // 将工作及其触发器放入调度器       scheduler.scheduleJob(jobDetail, trigger);       // 调度器开始调度工作       scheduler.start();   }}复制代码运行代码,可发现每隔 3 秒,输入如下要去数据库扫描啦。。。复制代码长处简单易行,反对集群操作毛病 ...

February 8, 2023 · 7 min · jiezi

关于ruby:为什么大家都说-SELECT-效率低

无论在工作还是面试中,对于SQL中不要用“SELECT *”,都是大家听烂了的问题,虽说听烂了,但广泛了解还是在很浅的层面,并没有多少人去追本溯源,探索其原理。效率低的起因先看一下最新《阿里java开发手册(泰山版)》中 MySQL 局部形容:【强制】在表查问中,一律不要应用 * 作为查问的字段列表,须要哪些字段必须明确写明。阐明: 减少查问分析器解析老本。增减字段容易与 resultMap 配置不统一。无用字段减少网络 耗费,尤其是 text 类型的字段。 开发手册中比拟概括的提到了几点起因,让咱们深刻一些看看: 不须要的列会减少数据传输工夫和网络开销用“SELECT * ”数据库须要解析更多的对象、字段、权限、属性等相干内容,在 SQL 语句简单,硬解析较多的状况下,会对数据库造成惨重的累赘。增大网络开销;* 有时会误带上如log、IconMD5之类的无用且大文本字段,数据传输size会几何增涨。如果DB和应用程序不在同一台机器,这种开销非常明显即便 mysql 服务器和客户端是在同一台机器上,应用的协定还是 tcp,通信也是须要额定的工夫。 对于无用的大字段,如 varchar、blob、text,会减少 io 操作精确来说,长度超过 728 字节的时候,会先把超出的数据序列化到另外一个中央,因而读取这条记录会减少一次 io 操作。(MySQL InnoDB)失去MySQL优化器“笼罩索引”策略优化的可能性SELECT * 杜绝了笼罩索引的可能性,而基于MySQL优化器的“笼罩索引”策略又是速度极快,效率极高,业界极为举荐的查问优化形式。例如,有一个表为t(a,b,c,d,e,f),其中,a为主键,b列有索引。那么,在磁盘上有两棵 B+ 树,即汇集索引和辅助索引(包含单列索引、联结索引),别离保留(a,b,c,d,e,f)和(a,b),如果查问条件中where条件能够通过b列的索引过滤掉一部分记录,查问就会先走辅助索引,如果用户只须要a列和b列的数据,间接通过辅助索引就能够晓得用户查问的数据。如果用户应用select *,获取了不须要的数据,则首先通过辅助索引过滤数据,而后再通过汇集索引获取所有的列,这就多了一次b+树查问,速度必然会慢很多。因为辅助索引的数据比汇集索引少很多,很多状况下,通过辅助索引进行笼罩索引(通过索引就能获取用户须要的所有列),都不须要读磁盘,间接从内存取,而汇集索引很可能数据在磁盘(外存)中(取决于buffer pool的大小和命中率),这种状况下,一个是内存读,一个是磁盘读,速度差别就很显著了,简直是数量级的差别。索引常识延申下面提到了辅助索引,在MySQL中辅助索引包含单列索引、联结索引(多列联结),单列索引就不再赘述了,这里提一下联结索引的作用。联结索引 (a,b,c)联结索引 (a,b,c) 理论建设了 (a)、(a,b)、(a,b,c) 三个索引咱们能够将组合索引想成书的一级目录、二级目录、三级目录,如index(a,b,c),相当于a是一级目录,b是一级目录下的二级目录,c是二级目录下的三级目录。要应用某一目录,必须先应用其下级目录,一级目录除外。 联结索引的劣势1) 缩小开销建一个联结索引 (a,b,c) ,理论相当于建了 (a)、(a,b)、(a,b,c) 三个索引。每多一个索引,都会减少写操作的开销和磁盘空间的开销。对于大量数据的表,应用联结索引会大大的缩小开销!2)笼罩索引对联结索引 (a,b,c),如果有如下 sql 的,SELECT a,b,c from table where a='xx' and b = 'xx'; 复制代码那么 MySQL 能够间接通过遍历索引获得数据,而无需回表,这缩小了很多的随机 io 操作。缩小 io 操作,特地是随机 io 其实是 DBA 次要的优化策略。所以,在真正的理论利用中,笼罩索引是次要的晋升性能的优化伎俩之一。3)效率高索引列多,通过联结索引筛选出的数据越少。比方有 1000W 条数据的表,有如下SQL:select col1,col2,col3 from table where col1=1 and col2=2 and col3=3;复制代码假如:假如每个条件能够筛选出 10% 的数据。 ...

February 1, 2023 · 1 min · jiezi

关于ruby:这几个SQL语法的坑你踩过吗

1、LIMIT 语句分页查问是最罕用的场景之一,但也通常也是最容易出问题的中央。比方对于上面简略的语句,个别 DBA 想到的方法是在 type, name, create_time 字段上加组合索引。这样条件排序都能无效的利用到索引,性能迅速晋升。SELECT *FROM   operationWHERE type = 'SQLStats'       AND name = 'SlowLog'ORDER BY create_timeLIMIT 1000, 10;复制代码好吧,可能90%以上的 DBA 解决该问题就到此为止。但当 LIMIT 子句变成 “LIMIT 1000000,10” 时,程序员依然会埋怨:我只取10条记录为什么还是慢?要晓得数据库也并不知道第1000000条记录从什么中央开始,即便有索引也须要从头计算一次。呈现这种性能问题,少数情景下是程序员偷懒了。在前端数据浏览翻页,或者大数据分批导出等场景下,是能够将上一页的最大值当成参数作为查问条件的。SQL 从新设计如下:SELECT   *FROM     operationWHERE   type = 'SQLStats'AND     name = 'SlowLog'AND     create_time > '2017-03-16 14:00:00'ORDER BY create_time limit 10;复制代码在新设计下查问工夫根本固定,不会随着数据量的增长而发生变化。2、隐式转换SQL语句中查问变量和字段定义类型不匹配是另一个常见的谬误。比方上面的语句:mysql> explain extended SELECT *     > FROM   my_balance b     > WHERE b.bpn = 14000000123     >       AND b.isverified IS NULL ;mysql> show warnings;| Warning | 1739 | Cannot use ref access on index 'bpn' due to type or collation conversion on field 'bpn'复制代码其中字段 bpn 的定义为 varchar(20),MySQL 的策略是将字符串转换为数字之后再比拟。函数作用于表字段,索引生效。上述情况可能是应用程序框架主动填入的参数,而不是程序员的原意。当初利用框架很多很繁冗,使用方便的同时也小心它可能给本人挖坑。3、关联更新、删除尽管 MySQL5.6 引入了物化个性,但须要特地留神它目前仅仅针对查问语句的优化。对于更新或删除须要手工重写成 JOIN。比方上面 UPDATE 语句,MySQL 理论执行的是循环/嵌套子查问(DEPENDENT SUBQUERY),其执行工夫可想而知。UPDATE operation oSET   status = 'applying'WHERE o.id IN (SELECT id               FROM   (SELECT o.id,                               o.status                       FROM   operation o                       WHERE o.group = 123                               AND o.status NOT IN ( 'done' )                       ORDER BY o.parent,                                 o.id                       LIMIT 1) t);复制代码 ...

January 5, 2023 · 7 min · jiezi

关于ruby:软件测试报告模板的类型有哪些

软件测试报告模板的类型,通常状况,测试报告分为六类: 1、注销测试报告模板(实用于软件产品增值税即征即退以及双软评估)。 2、鉴定测试报告模板(实用于政府我的项目申报、高新认证、我的项目结题和翻新产品认定等)。 3、验收测试报告模板(实用于各类软件和硬件零碎相结合的综合性集成我的项目的第三方验收测试,如政府、事业单位、企业、学校等我的项目验收)。 4、零碎测试报告模板(实用于软件和系统集成我的项目,由开发方发动并组织的我的项目验收)。 5、性能测试报告模板(实用于我的项目的性能验证、性能调优、发现性能缺点等利用场景)。 6、平安测试报告模板(扫描,浸透测试,代码审计;企业在网站或者APP利用上线之前,对网站、服务器或APP进行全面粗疏的平安监测,及早发现网站、服务器或APP测试的潜在破绽,免得蒙受黑客攻击,导致敏感数据泄露)。 举荐浏览: app压力测试怎么做 小程序兼容性测试怎么做 手机兼容性测试怎么做 缺点管理工具有哪些 app性能测试工具有哪些 自动化测试工具有哪些

May 13, 2022 · 1 min · jiezi

关于ruby:从论文到代码完成-RoIPooling

从论文到代码实现 RoIPoolingRoI Pooling失去特色图和候选框,就会将候选框投影在特色图,而后进行一次缩放失去大小一致的特色图,在 Faster RCNN 中,区域候选框用来预测对象是前景还是背景,这是 class head 要做的工作,而 regression 是学习到基于 anchor 的差分,也就是核心的偏移量和宽高的缩放。 在投影过程中候选框的尺寸和地位是相干于输出图像,而不是相干于特色图,首先需要将其进行转换到候选框在特色图上具体地位,而后在对提取候选框进行尺寸的缩放。 给定一个特色图和一组提议,返回会合的特色示意。区域提议网络被用来预测对象性和回归盒的偏差(对锚点)。这些偏移量与 anchor 拆散起来生成候选框。这些倡导通常是输出图像的大小而不是特色层的大小。因此,这些倡导需要按比例缩小到特色图层,之所以这样做,以便上游的CNN层能够提取特色。 咱们在原图上有一个尺寸,也就是候选框中心点的坐标以及宽度,首先咱们投影在原图上坐标点除以下采样的倍数,也就是 32 倍下采样,如果坐标无奈整除则进行取整操作。 import numpy as npimport torchimport torch.nn as nnfloattype = torch.cuda.FloatTensorclass TorchROIPool(object): def __init__(self, output_size, scaling_factor): #输入特色图的尺寸 self.output_size = output_size #缩放比率 self.scaling_factor = scaling_factor def _roi_pool(self, features): """ 在给定的缩放提取特色图基础,返回固定大小的特色图 Args: features (np.Array): """ # 特色图的通道数、高 和 宽 num_channels, h, w = features.shape # 计算步长 w_stride = w/self.output_size h_stride = h/self.output_size # res = torch.zeros((num_channels, self.output_size, self.output_size)) res_idx = torch.zeros((num_channels, self.output_size, self.output_size)) for i in range(self.output_size): for j in range(self.output_size): # important to round the start and end, and then conver to int # w_start = int(np.floor(j*w_stride)) w_end = int(np.ceil((j+1)*w_stride)) h_start = int(np.floor(i*h_stride)) h_end = int(np.ceil((i+1)*h_stride)) # limiting start and end based on feature limits # w_start = min(max(w_start, 0), w) w_end = min(max(w_end, 0), w) h_start = min(max(h_start, 0), h) h_end = min(max(h_end, 0), h) patch = features[:, h_start: h_end, w_start: w_end] max_val, max_idx = torch.max(patch.reshape(num_channels, -1), dim=1) res[:, i, j] = max_val res_idx[:, i, j] = max_idx return res, res_idx def __call__(self, feature_layer, proposals): """Given feature layers and a list of proposals, it returns pooled respresentations of the proposals. Proposals are scaled by scaling factor before pooling. Args: feature_layer (np.Array): 特色层尺寸 proposals (list of np.Array): 列表中每一个元素 Each element of the list represents a bounding box as (w,y,w,h) Returns: np.Array: proposal 数量,通道数,输入特色图高度, self.output_size """ batch_size, num_channels, _, _ = feature_layer.shape # first scale proposals based on self.scaling factor scaled_proposals = torch.zeros_like(proposals) # the rounding by torch.ceil is important for ROI pool scaled_proposals[:, 0] = torch.ceil(proposals[:, 0] * self.scaling_factor) scaled_proposals[:, 1] = torch.ceil(proposals[:, 1] * self.scaling_factor) scaled_proposals[:, 2] = torch.ceil(proposals[:, 2] * self.scaling_factor) scaled_proposals[:, 3] = torch.ceil(proposals[:, 3] * self.scaling_factor) res = torch.zeros((len(proposals), num_channels, self.output_size, self.output_size)) res_idx = torch.zeros((len(proposals), num_channels, self.output_size, self.output_size)) # 遍历候选框 for idx in range(len(proposals)): # proposal = scaled_proposals[idx] # adding 1 to include the end indices from proposal extracted_feat = feature_layer[0, :, proposal[1].to(dtype=torch.int8):proposal[3].to(dtype=torch.int8)+1, proposal[0].to(dtype=torch.int8):proposal[2].to(dtype=torch.int8)+1] res[idx], res_idx[idx] = self._roi_pool(extracted_feat) return res

May 8, 2022 · 2 min · jiezi

关于ruby:RVM切换到rbenvMacOS

参考原文: https://gist.github.com/akdetrick/7604130本文在翻译原文根底上对在实际操作中产生的问题追加了零星的解决办法. 起初看着RVM性能要比rbenv多, 所以抉择了RVM来治理ruby的版本, 但通过一段时间的应用发现对于ruby版本的管制还是rbenv不便些, 而且Gemset的设置多少有点麻烦, 设置不好连rails创立我的项目都报错. 所以索性换成rbenv. 1) remove RVM from your system首先,要删除RVM. 以下的命令等让你清理掉RVM的安装文件以及通过RVM装置的所有版本的Ruby. # rvm 的"自爆"模式, 将主动删除装置的ruby和本身的文件$ rvm implode# 偶然会有因权限问题导致 ~/.rvm 删除不掉的问题$ rm -rf ~/.rvm$ gem uninstall rvm$ rm ~/.rvmrc$ rm /etc/rvmrc2) remove any remaining traces of RVM从以下文件中删除所有关联rvm援用门路的设置 .profile.bash_profile.bashrczsh还须要批改: .zshrc3) install rbenv应用Homebrew装置rbenv和ruby-build插件 rbenv的装置也能够参考rbenv自家的文档: https://github.com/rbenv/rbenv#installation $ brew update$ brew install rbenv ruby-build4) install rubies for rbenv应用rbenv装置须要的ruby版本 # 列出可装置的ruby稳固版本:$ rbenv install -l# 装置指定版本的ruby:$ rbenv install 2.0.0-p247Note: 新装置一个ruby版本或gem之后如果呈现问题, 运行 $ rbenv rehash命令 ...

April 28, 2022 · 1 min · jiezi

关于ruby:ruby更换gem阿里镜像

有时候下载gem文件会比较慢或不胜利等,能够批改通过gem镜像源来进步下载速度。 参考rubygems镜像-rubygems下载地址-rubygems装置教程-阿里巴巴开源镜像站 阿里巴巴开源镜像站 在批改gem镜像之前,须要先查看一下,你以后零碎中gem的镜像是什么,而后才好进行对应的删除。 首先执行命令查看以后镜像 gem sources l 我的显示如下  C:\Users\Administrator>gem sources l*** CURRENT SOURCES ***https://rubygems.org/接着删除这个镜像执行命令 gem sources --remove https://rubygems.org/显示这个阐明删除胜利 C:\Users\Administrator>gem sources -r https://rubygems.org/https://rubygems.org/ removed from sources再增加新阿里巴巴gem镜像 gem sources -a https://mirrors.aliyun.com/rubygems/返回以下后果 C:\Users\Administrator>gem sources -a https://mirrors.aliyun.com/rubygems/https://mirrors.aliyun.com/rubygems/ added to sources镜像切换胜利后, 下载相对来说就快很多了。

February 15, 2022 · 1 min · jiezi

关于ruby:使用-Mastodon-搭建个人信息平台调优篇

本篇文章是应用 Mastodon 搭建个人信息平台的第二篇内容,我将聊聊在容器环境中搭建 Mastodon 后的一些利用调整和问题修复。 这篇文章或者同样是你可能找到的为数不多的对于如何在容器环境中搭建和优化 Mastodon 服务的内容。 写在后面本篇内容须要有上一篇内容的根底,所以如果你还未浏览上一篇内容,能够思考移步过来,浏览理解 《应用 Mastodon 搭建个人信息平台:前篇》。 在上篇文章完结后,咱们曾经能够通过手机利用进行登录和发帖记录信息了,然而在 Web 端应用的话,还是会遇到一些影响体验的小问题,同时,利用运行时应用的资源也会绝对节约,所以本篇内容就来解决这些问题。 为了关照新人,解决问题的程序依照从简到难,先从根底的服务配置开始吧。 如何启用 ES 全文搜寻在登录账号之后,在侧边栏抉择“首选项”,关上利用后盾页面。在后盾页面的侧边栏中抉择“治理”,就能够看到展现利用以后运行状况的信息面板啦。 在图片中咱们能够看到“服务器配置”中的“全文搜寻”目前是敞开着的。 为了让服务失常应用,咱们须要在前文中提到的配置文件 .env.production 中增加一些内容: ES_ENABLED=trueES_HOST=esES_PORT=9200接着应用 docker-compose down && docker-compose up -d 重启服务,稍等服务运行就绪之后,咱们就可能看到“全文搜寻”曾经启用啦。 加载字体资源报错的问题在利用控制台中,咱们会看到一条扎眼的报错。 Refused to load the font 'data:application/font-woff2;base64,...' because it violates the following Content Security Policy directive: "font-src 'self' https://hub-assets.lab.com".这是因为 config/initializers/content\_security\_policy.rb 中的设置比拟严格导致: Rails.application.config.content_security_policy do |p| p.base_uri :none p.default_src :none p.frame_ancestors :none p.font_src :self, assets_host p.img_src :self, :https, :data, :blob, assets_host p.style_src :self, assets_host p.media_src :self, :https, :data, assets_host p.frame_src :self, :https p.manifest_src :self, assets_host if Rails.env.development?... else p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url p.script_src :self, assets_host p.child_src :self, :blob, assets_host p.worker_src :self, :blob, assets_host endend解决这个问题很简略,只须要在 font 资源的安全策略中容许 data: 类型的资源即可: ...

January 25, 2022 · 5 min · jiezi

关于ruby:使用-Mastodon-搭建个人信息平台前篇

本篇文章是应用 Mastodon 搭建个人信息平台的第一篇内容,我将聊聊在容器环境中搭建 Mastodon 的一些细节。 同时,这篇文章或者你可能找到的为数不多的对于如何在容器环境中搭建和优化 Mastodon 服务的内容。 写在后面随着折腾的零碎越来越多,我开始冀望有一个中央可能将这些零碎中的音讯进行集中的出现,让我可能疾速清晰的理解到有什么乏味的陈腐的、重要的事件产生了,以及让我可能通过更简略的形式对已有零碎中的数据进行疾速的查问,以及记录一些忽然呈现的想法。 我认为以时间轴为线索的 Feed 流模式的信息展现,配合和各种“虚构利用”和 Bot 的对话形式或者可能解决我这个阶段的诉求。交互简略间接、交互操作层级也浅,在少数查问和记录场景下,我只须要输出内容,按下回车就能拿到我想要的数据,而不用关上具体的利用的页面,而后再一步一步、一步一步的操作。 在以往工作和生存中,其实多多少少也有应用过一些蕴含了交互或者性能和我诉求有交加的工具,比方:在新浪云工作应用的 TeamToy、在淘宝时应用的 Redmine 和阿里门户、美团时应用的大象、之后应用的 Slack、企业微信、学城等等。 不过这类计划少数都是外部或者 SaaS 化的计划,在集体应用场景下,尤其是联合各种 HomeLab 零碎,我更心愿它是一个私有化的服务。 对于新增“实体”,我比拟克服,所以所以在此之前的摸索过程中,我对 Phabricator、Confluence 、WordPress、Dokuwiki、Outline 等各种我之前比拟相熟的零碎都进行过了一些考察和简略的二次开发,发现尽管可能解决一部分问题,然而交互和体验上总感觉不是那么难受。因为这些工具或多或少都是基于合作登程,或者基于内容整顿登程,而不是信息汇聚和展现。我须要一个即便一个人应用也能很爽的计划。 于是,我开始彻底尝试切换思路,寻找一个上文中提到的,以时间轴为信息展现线索,可能和工具中的 Bot 互动,来记录我的想法、将各种我关注的事件实时汇聚到工具中,可能以简略的命令和办法查问各种零碎中已有的数据。最终,我抉择了 Mastodon,一个两年前我就曾经折腾过一阵的 “Twitter / Weibo Like” 的产品。 在开始折腾之前,咱们先来聊聊它的技术架构。 技术架构Mastodon 的技术架构属于比拟经典的 Web 架构,次要的性能组件有:前端利用(React SPA)、利用接口(Ruby Rails6)、推送服务(Node Express + WS)、后台任务(Ruby Sidekiq)、缓存和队列(Redis)、数据库(Postgres),以及可选的全文索引(Elasticsearch 7)形成。 除此之外,反对应用匿名网络通讯的形式和互联网上其余不同的社区实例通信,替换社区已公布内容,来实现其分布式社区的构想。不过这个性能不在本文范畴之内,而且非常简单,就不啰嗦开展了。 根底服务筹备在折腾利用之前,咱们先实现利用对于根底服务的依赖设施的搭建。先来聊聊网络布局。 搭建利用网关,进行网络布局和以往利用一样,咱们应用 Traefik 作为服务利用网关,让利用能够应用服务注册的形式动静地接入 Traefik。并且应用 Traefik 提供 SSL 装载、根底的 SSO 鉴权等。 如果你还不理解 Traefik,能够浏览之前的内容进行学习和理解。 我心愿 Mastodon 各个组件在可能通信、必要的服务可能应用 Traefik 进行服务注册,提供 Web 拜访的前提下,还能和主机上其余的容器服务在网络层面互相隔离。 ...

January 25, 2022 · 8 min · jiezi

关于ruby:Ruby-将引入新-JIT-编译器YJIT平均速度提升-23

近日,Ruby 代码仓库新增了一个对于合并 YJIT 的PR。 据介绍,YJIT 是一种应用 Lazy Basic Block Versioning (LBBV) 编译器架构构建的即时编译器。 在进行理论基准测试时,YJIT 比以后的CRuby 解释器平均速度晋升了23%。 Ruby 开发团队打算将 YJIT 蕴含在 Ruby 3.1 预览版中,以便更多用户能够帮忙他们对其进行测试,从而取得性能晋升。 目前 YJIT 默认处于禁用状态,须要关上--yjit 选项或设置 YJIT\_RUBY\_ENABLE=1 进行启用。须要留神的是,YJIT 临时只反对 macOS 和 Linux 零碎和 x86-64 CPU 架构。 其余问题 在不受反对的平台上,Ruby 应用传统的解释器生成的代码没有垃圾收集性能。超过设定的--yjit-exec-mem-size 数值就会报错。开发团队称在将来几个月内会解决此问题。YJIT 在运行时会应用更多内存,因为它须要调配机器代码,可通过设置--yjit-exec-mem-size 的值进行调整YJIT 不能与 MJIT 同时启用,两者中只有一个能够在运行时处于活动状态。

October 27, 2021 · 1 min · jiezi

关于ruby:Ruby-实现-数组反转-Not-Reverse

Ruby实现Array#reverse 性能 def reverse(arrays) new_arrays = [] index = arrays.size - 1 while index >= 0 new_arrays << arrays[index] index -= 1 end new_arraysend

October 22, 2021 · 1 min · jiezi

关于ruby:Ruby-实现-九九乘法表

require 'byebug'as = 1..9 as.each do |a| (1..a).each do |b| a = a.to_i b = b.to_i #byebug # s 用作对齐 s = a*b >= 10 ? " " : " " print " #{b} * #{a} = #{a*b}#{s}" end puts " \n"end

October 20, 2021 · 1 min · jiezi

关于ruby:含着泪写完了这个Ruby-NetHTTP短信验证码接口太不容易了

成人的世界素来没有容易二字,生存如此,代码亦是如此,因为我的项目的需要,我写了一个Ruby - NetHTTP接入短信验证码接口的代码,没想到说我对接的接口的短信服务商价格太贵。 无可奈何,通过本人的聪明才智,终于在在各大云市场找到一个价格低且稳固的短信供应商~可把本人牛批坏了~ 上面就给大家分享我写的代码吧: `require "uri"require "net/http" url = URI("https://vip.veesing.com/smsApi/verifyCode") https = Net::HTTP.new(url.host, url.port);https.use_ssl = true request = Net::HTTP::Post.new(url)request["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8"request.body = "appId=41KYR0EB&appKey=IIWCKKSR7NOQ&phone=1561894**&templateId=1043&variables=1234" response = https.request(request)puts response.read_body`这件事件通知咱们一个情理,验证码接口不要轻易乱接,很有可能是无用功。 Ruby - NetHTTP.rb和文档阐明下载

November 11, 2020 · 1 min · jiezi

译-在-Rails-中使用-Flash-Message即时信息

(本文翻译自:https://www.rubyguides.com/2019/11/rails-flash-messages/) 什么是即时信息? 即时信息是即时信息是一种将信息显示给你的 Rails 网站用户的一种方式,用于告诉他们发生了什么事。 示例: 密码被修改(确认提示)用户没有找到(错误信息)即时信息往往在 Controller 中设置即时信息,然后再视图中渲染出来。你的用户得到所需要的信息。 让我们来学习它如何工作。 如何使用即时信息你可以通过使用 flash 助手函数,来发起提示信息。 他们用起来很像 Ruby hash。 即时信息对象具有像 keys,any?,或者 each 这种方法,要访问即时信息,则是使用 []。 那么,你可以设置哪些类型的的消息呢? 默认情况下,你可以设置: noticealert这是一个使用例子: flash.alert = "User not found."另一种风格: flash[:alert] = "User not found."(两者只是风格不同) 你可以使用这些代码,在你的 Controller Actions 中,比如 index,create,new 之类的。 另一种使用方式: redirect_to :books_path, notice: "Book not found"这允许你在一步中,重定向页面和创建即时消息。 这很棒呦! Alert 对比 Notice据我了解,alert 或者 notice 具体使用哪个,不是很重要。哪个用着合适,就用哪个。 我习惯使用 alert 显示错误信息,使用 notice 显示一些提示信息。 两者主要还是风格的区别。 举个例子你可以将 alert 显示为红色,将 notice 显示为绿色。 你也可以根据需要,在控制器中,使用 add_flash_types,来创建你自己的消息类型。 ...

July 5, 2020 · 1 min · jiezi

译-如何使用-Rails-Helper

翻译自:https://www.rubyguides.com/2020/01/rails-helpers/ 在 Rails 中,Helper 是指什么? Helper 是一个函数(多数时候),用于 Rails 视图之间,共享可复用的代码。Rails 内置一组 Helper 函数。 其中一个是 time_ago_in_words。 例子time_ago_in_words(Time.now)# "less than a minute"time_ago_in_words(Time.now + 60)# "1 minute"time_ago_in_words(Time.now + 600)# "10 minutes"这个函数,用于显示指定格式的日期。 另一个用于 Rails 视图的 Helper 函数是 number_to_human。 例子:number_to_human(10_000)# "10 Thousand"当你想要将数字显示为可读的形式时,这个函数很有用。 你可以在 Rails 文档中,找到更多的内容:https://api.rubyonrails.org/ 那么,该如何定义自己的 Helper 函数呢? 编写自己的 Helper 函数如果你要编写 Helper 函数,正确的路径是 app/helpers,然后将你的 Helper 函数,写在其中的 helper module 中。 每个 Rails 应用,默认都带了基础的 helper module,命名为 ApplicationHelper。这里就是存放你 helper 函数的地方。 只要在模块中写好 helper 函数,那些函数在视图中,将自动变的可用。稍后将为你展示如何在 Controller 中使用它们,以及为什么这是个坏点子。如果你愿意,你可以在 ApplicationHelper 中写一切 helper 函数,但还有更好的组织方法。你可以创建一个你自己的文件,用来存储相关 helper 函数。 ...

July 1, 2020 · 1 min · jiezi