关于java:后端面经JavaHashMap详解

1. HashMap的家族定位接口java.util.Map有四个罕用的实现类,如图是它们之间的类继承关系。 上面我将一一介绍其性能特点。 HashMap: 最罕用的Map实现类,通过应用Hash表构造,进步查找速度;应用键值对作为存储节点,只容许一个key值为null,容许多个value值为null;线程不平安,对于线程平安有要求的程序,能够思考应用:sychronizedMap或者ConcurrentHashMap;HashTable 同样应用Hash表构造,进步查找效率;线程平安,然而平安层级低于ConcurrentHashMap,不罕用。LinkedHashMap 继承自HashMap,应用Hash表构造,进步查找效率;链表插入维持插入程序。TreeMap sortedMap接口的实现类,可应用特定的排序规定对键值对进行排序;对四种常见的实现类的性能比拟如下图所示: 2. HashMap的数据结构2.1 Hash表的基本概念Hash表是数据结构和算法课程中学习到的一种重要的数据结构。次要设计思维是: 应用一个长度为n的数组存储相干数据。应用hash函数实现内容和数组下标的对应,也就是hash函数的函数值为0~n之间。 hash函数雷同的输出参数肯定会产生雷同函数值,不同内容尽量做到函数值扩散。在hash函数值对应的下标写入该内容。下次查找某元素的时候,先依据hash函数生成下标,而后再随机拜访数组,这样查找效率大大提高了。相似于一个叫贾斯汀·费尔兰德·亨利皮特潘(简单内容)的人,在酒店前台(hash函数)入住酒店的房间编号是1004(hash函数值/数组下标)。须要找他的人,只须要去酒店前台查问他住在1004房间,间接去1004房间找人就能够了,不须要一个一个房间去找。 2.2 Hash抵触在下面的流程阐明中,咱们能够发现Hash表的实现要害就在于Hash函数,一个好的hash函数应该保障不同的输出内容尽量扩散其函数值。当存入的数据过多,hash函数性能较差的时候,可能会呈现hash抵触: A和B是两个不同的存储内容,然而通过hash函数计算,失去的hash函数值雷同,因而两个内容存储在数组的同一地位。例如:贾斯汀·费尔兰德·亨利皮特潘和特朗普·懂王·建国同志两个人在酒店前台调配到的房间号都是1004,然而房间只有一张床,这时两个人就会发生冲突。解决抵触次要有两种思路: 凋谢定址法:发生冲突的时候,后到来的元素放弃已被占用的地位,寻找新的插入地位。(再找)链地址法:发生冲突的时候,后到来的元素在原有地位的根底上,应用链表的形式存储。(排队) HashMap应用的就是链地址法。2.3 HashMap数据结构节点NodeNode是HashMap的一个根本存储单元,从源码中可见Node实现了Map.Entry接口,寄存的是键值对。在JDK1.8中的源码中,Node的定义如下所示: static class Node<K,V> implements Map.Entry<K,V> { final int hash; //用来定位数组索引地位 final K key; V value; Node<K,V> next; //链表的下一个node Node(int hash, K key, V value, Node<K,V> next) { ... } public final K getKey(){ ... } public final V getValue() { ... } public final String toString() { ... } public final int hashCode() { ... } public final V setValue(V newValue) { ... } public final boolean equals(Object o) { ... }}JDK1.7的HashMap数据结构数组+链表 ...

June 25, 2023 · 5 min · jiezi

关于java:JDK-21-中的结构化将带来发编程的一次飞跃

最近,JEP 453,结构化并发(预览)曾经从 JDK 21 的 Targeted 状态变更为 Integrated 状态。这个最后的预览个性来源于一个孵化 API,它依据前两轮的孵化纳入了一些改良,这两轮孵化别离是 JDK 19 交付的JEP 428,结构化并发(孵化)和 JDK 20 交付的JEP 437,结构化并发(第二轮孵化)。在以后提案中,惟一的显著变动是StructuredTaskScope::fork(...)办法返回一个[Subtask],而不是Future。 JDK 21 中的结构化并发致力于引入结构化并发的 API 来简化并发编程。这种办法将在不同线程中运行的相干工作组视为一个工作单元,从而简化了错误处理和勾销,进步了可靠性,并加强了可观测性。咱们看一个样例: Response handle() throws ExecutionException, InterruptedException { try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { Supplier<String> user = scope.fork(() -> findUser()); Supplier<Integer> order = scope.fork(() -> fetchOrder()); scope.join() // Join both subtasks .throwIfFailed(); // ... and propagate errors // Here, both subtasks have succeeded, so compose their results return new Response(user.get(), order.get()); } //...}这段代码创立了一个新的StructuredTaskScope,并应用它来创立了两个分支子工作,其中一个执行findUser(),另一个执行fetchOrder()。当这两个子工作均实现时,它会应用这两个子工作的后果创立一个新的Response。 ...

June 25, 2023 · 1 min · jiezi

关于java:面试官MySQL-自增主键一定是连续的吗大部分人都会答错

测试环境:MySQL版本:8.0数据库表:T (主键id,惟一索引c,一般字段d) 如果你的业务设计依赖于自增主键的连续性,这个设计假如自增主键是间断的。但实际上,这样的假如是错的,因为自增主键不能保障间断递增。 举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice一、自增值的属性特色:1. 自增主键值是存储在哪的?MySQL5.7版本在 MySQL 5.7 及之前的版本,自增值保留在内存里,并没有长久化。每次重启后,第一次关上表的时候,都会去找自增值的最大值 max(id),而后将 max(id)+1 作为这个表以后的自增值。 MySQL8.0之后版本在 MySQL 8.0 版本,将自增值的变更记录在了 redo log 中,重启的时候依附 redo log 复原重启之前的值。 能够通过看表详情查看以后自增值,以及查看表参数详情AUTO_INCREMENT值(AUTO_INCREMENT就是以后数据表的自增值) 2. 自增主键值的批改机制?在表t中,我定义了主键id为自增值,在插入一行数据的时候,自增值的行为如下: 如果插入数据时 id 字段指定为 0、null 或未指定值,那么就把这个表以后的 AUTO_INCREMENT 值填到自增字段;如果插入数据时 id 字段指定了具体的值,就间接应用语句里指定的值。依据要插入的值和以后自增值的大小关系,自增值的变更后果也会有所不同。假如,某次要插入的值是 X,以后的自增值是 Y。 如果 X<Y,那么这个表的自增值不变;如果 X≥Y,就须要把以后自增值批改为新的自增值。二、新增语句自增主键是如何变动的:咱们执行以下SQL语句,来察看自增主键是如何进行变动的 insert into t values(null, 1, 1);流程图如下所示 流程步骤: AUTO_INCREMENT=1 (示意下一次插入数据时,如果须要主动生成自增值,会生成 id=1。)insert into t values(null, 1, 1) (执行器调用 InnoDB 引擎接口写入一行,传入的这一行的值是 (0,1,1))get AUTO_INCREMENT=1 (InnoDB 发现用户没有指定自增 id 的值,获取表 t 以后的自增值 1 )AUTO_INCREMENT=2 insert into t values(1, 1, 1) (将传入的行的值改成 (1,1,1),并把自增值改为2)insert (1,1,1) 执行插入操作,至此流程完结大家能够发现,在这个流程当中是先进行自增值的+1,在进行新增语句的执行的。大家能够发现这个操作并没有进行原子操作,如果SQL语句执行失败,那么自增是不是就不会间断了呢? ...

June 25, 2023 · 2 min · jiezi

关于java:Spring-Boot-调用外部接口的-3-种方式还有谁不会

1、简介SpringBoot不仅继承了Spring框架原有的优良个性,而且还通过简化配置来进一步简化了Spring利用的整个搭建和开发过程。 在Spring-Boot我的项目开发中,存在着本模块的代码须要拜访里面模块接口,或内部url链接的需要, 比方在apaas开发过程中须要封装接口在接口中调用apaas提供的接口(像发动流程接口submit等等)上面也是提供了三种形式(不应用dubbo的形式)供咱们抉择 举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice2、形式一:应用原始httpClient申请/* * @description get形式获取入参,插入数据并发动流程 * @author lyx * @date 2022/8/24 16:05 * @params documentId * @return String *///@RequestMapping("/submit/{documentId}")public String submit1(@PathVariable String documentId) throws ParseException { //此处将要发送的数据转换为json格局字符串 Map<String,Object> map =task2Service.getMap(documentId); String jsonStr = JSON.toJSONString(map, SerializerFeature.WRITE_MAP_NULL_FEATURES,SerializerFeature.QuoteFieldNames); JSONObject jsonObject = JSON.parseObject(jsonStr); JSONObject sr = task2Service.doPost(jsonObject); return sr.toString();}/* * @description 应用原生httpClient调用内部接口 * @author lyx * @date 2022/8/24 16:08 * @params date * @return JSONObject */public static JSONObject doPost(JSONObject date) { String assessToken="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ4ZGFwYXBwaWQiOiIzNDgxMjU4ODk2OTI2OTY1NzYiLCJleHAiOjE2NjEyMjY5MDgsImlhdCI6MTY2MTIxOTcwOCwieGRhcHRlbmFudGlkIjoiMzAwOTgxNjA1MTE0MDUyNjA5IiwieGRhcHVzZXJpZCI6IjEwMDM0NzY2MzU4MzM1OTc5NTIwMCJ9.fZAO4kJSv2rSH0RBiL1zghdko8Npmu_9ufo6Wex_TI2q9gsiLp7XaW7U9Cu7uewEOaX4DTdpbFmMPvLUtcj_sQ"; CloseableHttpClient client = HttpClients.createDefault(); // 要调用的接口url String url = "http://39.103.201.110:30661 /xdap-open/open/process/v1/submit"; HttpPost post = new HttpPost(url); JSONObject jsonObject = null; try { //创立申请体并增加数据 StringEntity s = new StringEntity(date.toString()); //此处相当于在header外头增加content-type等参数 s.setContentType("application/json"); s.setContentEncoding("UTF-8"); post.setEntity(s); //此处相当于在Authorization外头增加Bear token参数信息 post.addHeader("Authorization", "Bearer " +assessToken); HttpResponse res = client.execute(post); String response1 = EntityUtils.toString(res.getEntity()); if (res.getStatusLine() .getStatusCode() == HttpStatus.SC_OK) { // 返回json格局: String result = EntityUtils.toString(res.getEntity()); jsonObject = JSONObject.parseObject(result); } } catch (Exception e) { throw new RuntimeException(e); } return jsonObject;}3、形式二:应用RestTemplate办法Spring-Boot开发中,RestTemplate同样提供了对外拜访的接口API,这里次要介绍Get和Post办法的应用。 ...

June 25, 2023 · 3 min · jiezi

关于java:蔚来手撕代码题三个线程循环打印ABC

问题如下: https://www.nowcoder.com/discuss/493178141461041152思路剖析三个线程交替打印 ABC 的实现办法有很多,我集体比拟偏向于应用 JUC 下的 CyclicBarrier(循环栅栏,也叫循环屏障)来实现,因为循环栅栏天生就是用来实现一轮一轮多线程工作的,它的外围实现思路如下图所示:CyclicBarrier 作用是让一组线程互相期待,当达到一个共同点时,所有之前期待的线程再继续执行,且 CyclicBarrier 性能可重复使用。上图形容的就是 CyclicBarrier 每轮期待 5 个线程全副达到一个共同点时,再执行下一阶段的工作。 举个例子比方磊哥要坐班车回老家,因为中途不容许上、下乘客,那么营运的公司为了收益最大化,就会等人满之后再发车,这个发车的触发条件就是 CyclicBarrier 中多个线程执行的共同点。等汽车达到另一个站点之后也是同样的操作,期待乘客再次坐满之后,再持续发车,CyclicBarrier 就是这样执行的,它也是能够循环应用的。 实现代码import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/** * 3 个线程交替打印 ABC */public class ThreadLoopPrint { // 共享计数器 private static int sharedCounter = 0; public static void main(String[] args) { // 打印的内容 String printString = "ABC"; // 定义循环栅栏 CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> { }); // 执行工作 Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0; i < printString.length(); i++) { synchronized (this) { sharedCounter = sharedCounter > 2 ? 0 : sharedCounter; // 循环打印 System.out.println(printString.toCharArray()[sharedCounter++]); } try { // 期待 3 个线程都打印一遍之后,持续走下一轮的打印 cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } }; // 开启多个线程 new Thread(runnable).start(); new Thread(runnable).start(); new Thread(runnable).start(); }}以上程序执行的后果如下图所示: ...

June 25, 2023 · 1 min · jiezi

关于java:信创优选国产开源Solon-v236-发布

Solon 是什么开源我的项目?一个,Java 新的生态型利用开发框架。它从零开始构建,有本人的标准规范与凋谢生态(历时五年,已有寰球第二级别的生态)。与其余框架相比,它解决了两个重要的痛点:启动慢,费资源。 解决痛点?因为Solon Bean容器的独特设计,不会因为扩大依赖变多而启动很慢(开发调试时,省时、痛快)!以出名开源我的项目“小诺”为例: “snowy-spring 版” 启动 30-50秒“snowy-solon 版” 启动3-5秒(有趣味的,欢送拉取代码体验)所谓:“工夫就是生命,效率就是金钱”,“天下文治,唯快不破”。 绝对于 Spring Boot 和 Spring Cloud 的我的项目,有什么特点?启动快 5 ~ 10 倍。 (更快)qps 高 2~ 3 倍。 (更高)运行时内存节俭 1/3 ~ 1/2。 (更少)打包能够放大到 1/2 ~ 1/10;比方,300Mb 的变成了 23Mb。 (更小)同时反对 jdk8, jdk11, jdk17, jdk20,<mark> graalvm native</mark>本次更新了什么?新增 solon.boot.websocket.netty 插件新增 solon.web.sse 插件(sse: Server Send Events)新增 solon.web.flux 插件,web 响应式接口反对插件减少 Context 异步控制接口,为响应式web开发提供反对减少 ActionReturnHandler 接口,之后特地的返回后果可定制。为响应式web开发提供反对减少 ActionExecuteHandler 接口(代替旧的 ActionExecutor),并交由 chainManager 治理减少 jetty、undertow、smarthttp 对 Context 异步适配减少 solon.boot.jdkhttp 插件,虚构异步反对(进而反对响应式接口)减少 solon.boot.jlhttp 插件,虚构异步反对(进而反对响应式接口)减少 solon.scheduling 插件,简略的 Retry 性能减少 solon.validation 一次性验证所有字段的反对减少 solon.docs 插件,反对字段 transient 排除减少 mybatis-plus-solon-plugin 插件,原生编译反对(GraalVM Native Image)减少 Inject("{xxx:def}") 默认值转汇合和数组反对欠缺 mybatis-solon-plugin 原生编译反对欠缺 solon.aot 减少 lambda 序列化反对欠缺 Servlet 启动打印信息欠缺 ContextPathFilter 对根地址的映射解决修复 Context:forward 在有 context-path 时的会出错的问题修复 申请门路动态变化后,门路变量获取失败的问题guava 升为 32.0.0-jresmarthttp 升为 1.2.4smartsocket 升为 1.5.30dromara-plugins 升为 0.0.9forest 升为 1.5.32mybatis-flex 升为 1.4.1sqltoy 升为 5.2.54hutool 升为 5.8.20fastjson2 升为 2.0.34java-websocket 升为 1.5.3我的项目仓库地址?gitee:https://gitee.com/noear/solongithub:https://github.com/noear/solon技术支持与交换?https://solon.noear.org/article/support架构图?Solon 架构图: ...

June 25, 2023 · 1 min · jiezi

关于java:尚硅谷2023年java就业班10阶段

download:尚硅谷2023年java待业班10阶段IDEA工具的层级架构IDEA(IntelliJ IDEA)是一款弱小的集成开发环境,宽泛用于Java开发。IDEA的胜利离不开其清晰而有序的层级架构。本文将介绍IDEA工具的层级架构,并解释每个层级的性能和作用。 用户界面层用户界面层是IDEA与用户进行交互的局部,包含菜单栏、工具栏、编辑器窗口等。用户能够通过这些可视化的组件,不便地创立、关上、编辑和保留我的项目。IDEA提供了丰盛的快捷键、代码补全和谬误提醒等性能,使得开发过程更加高效和舒服。编辑器层编辑器层是IDEA中最外围的局部,负责源代码的编辑和展现。IDEA的编辑器反对多种编程语言,具备弱小的语法高亮、智能代码补全、重构以及代码导航性能。编辑器还能够自定义代码款式、参数提醒和代码模板,使得开发者可能依据本人的爱好和需要进行个性化设置。编译器层编译器层负责将源代码转换为可执行文件。IDEA内置了Java编译器,能够对Java代码进行编译和构建。此外,IDEA还反对其余编程语言的编译器插件,如Python、JavaScript等。编译器层不仅提供了编译谬误的检测和提醒,还能够生成调试信息和优化代码。调试器层调试器层是IDEA中用于调试程序的重要组件。它容许开发者逐行执行代码,并提供了断点设置、变量监督、堆栈跟踪等性能。调试器层能够帮忙开发者疾速定位和解决程序中的bug,进步调试效率和品质。版本控制层版本控制层是IDEA中用于治理源代码版本的模块。它反对多种版本控制系统,如Git、SVN等,能够不便地进行代码提交、拉取、分支治理和合并等操作。版本控制层还提供了代码比拟、历史记录和抵触解决等性能,使得团队合作更加顺畅和高效。插件层插件层是IDEA的灵魂所在,它为开发者提供了丰盛的扩大性能。通过装置各种插件,开发者能够减少新的语言反对、框架集成、代码生成和工具等。插件层还能够自定义IDEA的外观和行为,使得开发环境更合乎集体的需要和习惯。总结起来,IDEA工具的层级架构从用户界面到外围性能逐层开展,每个层级都有着特定的性能和作用。这种清晰而有序的架构设计使得IDEA成为一款弱小、灵便和易用的集成开发环境,深受开发者的青睐。

June 24, 2023 · 1 min · jiezi

关于java:无处不在-亚马逊云科技的-Java-生态

Java 自诞生以来就始终是热门的编程语言。得益于丰盛的生态以及欠缺保护的包和框架,Java 领有着宏大的开发者社区。这个 1995 年诞生的计算机语言,以 “一次编写,到处运行” 的跨平台个性以及面向对象、泛型编程等古代语言的个性迅速成为了企业级利用乃至挪动利用开发的首选。亚马逊云科技也始终在 Java 方面有继续的投入,以丰盛整个 Java 生态。 亚马逊云科技开发者社区为开发者们提供寰球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、流动与比赛等。帮忙中国开发者对接世界最前沿技术,观点,和我的项目,并将中国优良开发者或技术举荐给寰球云社区。如果你还没有关注/珍藏,看到这里请肯定不要匆匆划过,点这里让它成为你的技术宝库! 无论在寰球还是在中国,开发者规模的增长都越来越快。开发者们会抉择本人相熟的语言进行代码的构建、编译和生成,尽管市场上可选的编程语言很多,但 Java 始终是泛滥开发者的首选语言。 Apache 软件基金会在 2020 年的考察指出,应用 Java 语言构建源代码的数量远超其余编程语言,由此可见开发者对于 Java 语言的青睐水平。此外,TIOBE 编程语言排名调研结果显示:从 2001 年到 2022 年,Java 语言始终处于编程语言排名前三的地位,而且在 2005 年和 2015 年别离取得开发者最为青睐的编程语言。可见,Java 语言领有着非常广阔的市场以及宏大的开发者群体。 亚马逊的 Java 生态 亚马逊正在宽泛地应用 Java,无论是对外的电商批发零碎还是外部的利用,包含很多亚马逊云科技的服务也都在应用 Java 进行构建。 亚马逊有成千上万的 Java 利用在生产环境中运行。从 2016 年开始,咱们意识到不能适度依赖内部的二进制发行版构建 Java 利用。起因在于: 一是 Java 的季度公布中通常会引入重大更新,并可能产生宽泛的影响。 二是某些要害谬误的修复须要期待 Java 的公布进度,可能整体下来须要几个月的工夫能力取得反对,而咱们迫切需要把这些修复投入生产以解决问题。 因而,咱们决定从源代码开始构建 Java,以满足亚马逊对 Java 利用在性能和平安等诸多方面的需要。 2018 年咱们公布了 Amazon Correto,Amazon Corretto 是凋谢 Java 开发工具包 (OpenJDK) 的收费、多平台、生产就绪型发行版。Amazon Corretto 提供长期反对,其中包含性能加强和平安修复。咱们会借助 Amazon Correto 疾速为 Java 带来新的能力,修复更多的谬误,奉献给 Java 社区,一直为 OpenJDK 做出奉献。 ...

June 23, 2023 · 3 min · jiezi

关于java:黑马Java架构师实战训练营

download:黑马Java架构师实战训练营动静页面题目实现在网页开发中,页面题目是指浏览器标签栏上显示的文字,它对于网站的重要性显而易见。动静页面题目是一种可能依据具体内容或用户交互动静扭转的页面题目。本文将具体介绍动静页面题目的实现办法和其在网页开发中的利用。 动静页面题目的重要性页面题目作为网站的标识之一,在搜索引擎优化(SEO)和用户体验方面扮演着要害的角色。一个有吸引力和相关性的页面题目能够进步网站在搜寻后果中的排名,并吸引更多的用户点击。 实现办法以下是几种常见的实现动静页面题目的办法: JavaScript动静批改:应用JavaScript代码能够通过DOM操作找到<title>标签,并批改其中的文本内容。这使得咱们能够依据以后页面的状态或用户交互来动静更改页面题目。 服务端渲染(SSR):在服务器端生成网页时,能够依据数据动静生成页面题目。通过在服务器端解决页面的渲染,咱们能够将特定内容嵌入到题目中,从而实现动静页面题目。 响应式设计:针对不同设施和屏幕尺寸,能够采纳响应式设计来动静调整页面题目。例如,在挪动设施上能够缩短题目长度,以适应无限的屏幕空间。 利用场景动静页面题目在以下状况下特地有用: 博客或新闻网站:依据文章的题目主动生成页面题目,使其更具相关性和吸引力。 电子商务网站:基于产品名称、价格和促销流动等因素来动静生成页面题目,吸引用户点击。 多语言网站:通过将页面题目与用户的语言偏好相匹配,提供个性化的体验。 最佳实际为了实现无效的动静页面题目,以下是一些最佳实际: 关键字优化:确保页面题目蕴含相干的关键字,以进步搜寻排名和可发现性。 简洁而吸引人:应用简洁、明确且吸引人的文字,以吸引用户点击。 切勿滥用:防止在短时间内频繁更改页面题目,这可能对用户体验产生负面影响。 A/B测试:尝试不同的页面题目,并应用A/B测试方法确定哪个题目成果最佳。 总结动静页面题目是网页开发中重要的一环,它能够进步网站的SEO成果和用户体验。通过JavaScript、服务端渲染和响应式设计等办法,能够实现动静页面题目。在利用中,依据具体的场景和需要来抉择适宜的办法,并遵循最佳实际以提供最佳的用户体验。

June 22, 2023 · 1 min · jiezi

关于java:Java微服务升级

前言之前我的微服务版本是java8、spring-boot2.4.2、spring-cloud2020.0.0、spring-cloud-alibaba2021.1,然而最近随着spring-boot3.0版本的公布,再加上官网曾经阐明最低版本反对java17,所以就有了这篇文章。 <properties> <java.version>1.8</java.version> <spring-boot.version>2.4.2</spring-boot.version> <spring-cloud.version>2020.0.0</spring-cloud.version> <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version></properties>目前,Oracle 官网反对的最新 LTS(长期反对)版本是 JDK 17,而 OpenJDK 社区也正在踊跃开发和保护 JDK 17。 因而,如果你思考降级 Java 版本,并且心愿应用一个稳固和牢靠的版本,那么倡议抉择 JDK 17。JDK 17 蕴含了很多新个性和改良,例如: 新的垃圾回收器:ZGC 和 Shenandoah;加强的 Switch 表达式;改良的异样解决;新的日期和工夫 API;...此外,JDK 17 也提供了宽泛的操作系统、硬件平台和云平台反对,能够实用于各种不同的利用场景。同时,因为 JDK 17 是一个 LTS 版本,因而能够取得更长时间的更新和反对,从而提供更好的稳定性和安全性。 总之,倡议抉择 JDK 17 作为降级指标,以获得最佳的兼容性、稳定性和安全性。 版本参照上面列出了spring-boot、spring-cloud和spring-cloud-alibaba的版本对应关系,抉择适合的版本不要呈现兼容性问题。spring-boot和spring-cloud版本对应关系 spring和elasticsearch版本对应关系 spring-cloud和spring-cloud-alibaba版本对应关系 有了下面的版本对应关系,于是咱们抉择了如下的版本: <properties> <java.version>17</java.version> <spring-boot.version>3.0.2</spring-boot.version> <spring-cloud.version>2022.0.0</spring-cloud.version> <spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version></properties>降级微服务1、装置java17这里不做具体介绍了,这个应该是必备的,我给出下载地址:java17下载和jdk装置 2、装置maven 3.9这里不做具体介绍了,这个应该是必备的,我给出下载地址:maven下载和maven装置 3、配置idea 3.1设置版本都为java17 3.2增加jdk17 3.3language level抉择jdk17 3.4modules中设置sources的language level都是project default即可 保留并退出即可! 4、配置pom.xml 上面是我的pom.xml大家能够做为降级参考: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.2</version> <relativePath/></parent><properties> <java.version>17</java.version> <spring-boot.version>3.0.2</spring-boot.version> <spring-cloud.version>2022.0.0</spring-cloud.version> <spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version></properties><dependencyManagement><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- spring cloud 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- spring cloud alibaba 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency></dependencies></dependencyManagement><dependencies> <!-- 必须增加的 依赖 --> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-api</artifactId> <version>10.0.0</version> <scope>provided</scope> </dependency> <!-- 必须增加的 依赖(如果你有的话) --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.28</version> <scope>provided</scope> </dependency> <!-- 必须增加的 依赖(如果你有的话) --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-kafka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-rabbit</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency></dependencies><build> <plugins> <plugin> <groupId>com.spotify</groupId> <artifactId>dockerfile-maven-plugin</artifactId> <version>1.4.10</version> <configuration> <dockerfile>src/main/docker/Dockerfile</dockerfile> <!-- <repository>spotify/foobar</repository>--> <!--<tag>${project.version}</tag>--> <buildArgs> <!--提供参数向Dockerfile传递--> <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE> </buildArgs> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins></build>下面引入了jakartaee依赖,这是有历史起因的,感兴趣的能够看看[这篇文章 ]() ...

June 22, 2023 · 2 min · jiezi

关于java:关于-Java-和-node-affinity-这个概念的联系

在Java开发畛域,术语"node affinity"通常不是与Java语言自身间接相干的概念。然而,在某些特定的上下文中,能够将"node affinity"利用于Java应用程序的部署和调度方面。 在Java开发中,"node affinity"可能指的是以下几个方面: 服务器亲和性:在分布式环境中部署Java应用程序时,能够思考将特定的Java应用程序部署在特定的服务器节点上,以实现服务器亲和性。这能够通过在部署形容文件或配置文件中指定服务器节点的标识或属性来实现。通过将应用程序与特定的节点相关联,能够利用节点的特定个性、硬件资源或地理位置等劣势来进步应用程序的性能和可靠性。分布式缓存和数据分片:在Java分布式应用程序中,"node affinity"能够波及到数据分片和分布式缓存的治理。例如,在应用分布式缓存解决方案(如Redis或Hazelcast)时,能够应用"node affinity"来确保特定的数据分片或缓存实例与特定的Java节点相关联。这样做能够最大限度地缩小网络开销,并进步缓存的拜访效率。任务调度和并行计算:对于须要执行大量并行计算或任务调度的Java应用程序,"node affinity"能够用于管制工作或计算的散发和调度。通过将工作或计算与特定的节点相关联,能够利用节点的计算能力、内存容量或其余资源个性来实现工作的高效执行。容器化环境中的亲和性:在将Java应用程序部署到容器化环境(如Kubernetes)时,"node affinity"能够指涉到将特定的Java容器或Pod调度到特定的节点上。通过应用Kubernetes的亲和性规定,能够依据节点的属性、标签或其余条件来管制Java应用程序的调度。须要留神的是,"node affinity"在Java开发畛域中的具体含意可能因上下文和应用场景而异。它能够依据具体的利用和部署环境来定义和实现。因而,确保在特定状况下对"node affinity"的含意和应用有明确的定义和了解是很重要的。 总结而言,尽管"node affinity"在Java开发畛域中不是一个常见的术语,但在特定的部署、调度和分布式场景中,它能够指涉到管制Java应用程序与特定节点相关联的技术和办法。这些技术和办法能够优化应用程序的性能、可靠性和资源利用率。

June 21, 2023 · 1 min · jiezi

关于java:提前预体验阿里大模型通义千问的方法来了

随着AI大模型的浪潮席卷寰球,现在的AI技术曾经颠覆了大家对传统AI的意识,微软更是用浏览器与搜索引擎上的实际,证实了当今的AI技术具备突破行业格局的能力。 对于咱们利用开发者来说,AI基建的建设与竞争是无奈参加的,但在AI的应用领域仍然大有可为!目前,国内各大科技公司曾经陆续推出了各自的AI大模型,如:阿里的“通义千问”。咱们接下来要多花工夫去学习和思考如何应用它们来扭转和优化本人所处的行业产品。 以后大模型产品都还处于内测阶段,咱们须要申请或有邀请码能力应用体验。如果您目前还在着急期待试用申请的通过,那么接下来的内容你相对不能错过! 上面DD就给大家介绍一种领有自在发问30次的办法,提前预体验一下阿里大模型“通义千问”的能力。上面就跟着我的步骤,后人一步,亲手体验一下阿里大模型吧! 操作步骤这里咱们将应用阿里云的函数计算来实现对“通义千问”大模型能力的预体验,正好该函数计算产品还有个3个月的羊毛能够薅一下,只须要从这个链接进入阿里云: https://click.aliyun.com/m/1000373762/ ,找到函数计算,点击立刻试用支付收费额度即可: 上面奉上残缺操作视频,手把手教学,包教包会! https://www.bilibili.com/video/BV1WM4y1E7CD/ 其余模型下面给大家演示了“通义千问”大模型能力预体验 30 次自在发问的办法。但其实目前AIGC的场景还有很多种,不仅仅是相似ChatGPT的问答模型,还有数字绘画等与图像相干的模型。如果您的业务畛域与此相关,也一样能够通过下面的办法来体验,只须要在抉择模版的时候,如下图所示,点击“人工智能”标签,就能够看到更多有意思的模型利用: 这里涵盖了目前支流的几种模型,包含: 【文生图】一键部署Stable Diffusion基于函数计算。【图生图】一键部署3D卡通格调模型。【图生文】一键部署图像形容模型。【文生文】一键部署ChatYuan模型。大家能够依据本人的业务场景去体验把玩适宜本人业务的模型。 是不是蠢蠢欲动了呢?连忙点击链接尝试一下:https://click.aliyun.com/m/1000373762/ ,冲! 灵魂一问最初,灵魂一击!大家是否有思考过这个问题:为什么这些与AI相干的利用大多采纳Serverless部署?留言区一起聊聊呗! 欢送关注我的公众号:程序猿DD。第一工夫理解前沿行业音讯、分享深度技术干货、获取优质学习资源

June 20, 2023 · 1 min · jiezi

关于java:基于-JLisp-自定义一个规则引擎

基于 JLisp 自定义一个规定引擎JLisp 是一个编程语言解释器,代码齐全开源。本文通知你如何基于 JLisp 创立一个规定引擎。 我的项目设置援用 JLisp 能够增加 maven 依赖 <dependency> <groupId>io.github.aclisp</groupId> <artifactId>jlisp-core</artifactId> <version>1.0.14</version></dependency>以后处于 Alpha 阶段,版本会不断更新。 先看一个最根本的例子咱们的规定引擎打算实现以下这个模式 依据下面的流程图剖析一下,这个模式具备这些特点 方框框:示意某种操作。例如“查问数据”或者“操作数据”菱形:示意决策判断。依据前一个操作的后果,决定怎么办子流程和“内联子流程”:决策之后,继续执行某种操作,而后再决策,再操作……如此往返,直到完结。 如果咱们把决策之后的动作,看作一个整体,那这个整体能够叫做“子流程”。当然,间接画在以后这个流程图里的“整体”,是“内联子流程”;画在别的中央,就是援用别的“子流程”值得注意的一点是,如果把“开始”之后的内容,也看成一个子流程,那么咱们这个规定引擎的表述就是“操作,决策,子流程”一直嵌套。 用 JLisp 代码来形容依据这个表述,上面用 JLisp 提供的 API 结构出对应的代码。 最根本思维在 JLisp 中,对应子流程的数据结构叫做 ListExpression。顾名思义,它是一个 ArrayList<Expression> 的子类,表白的意思是,一系列“模式”的有序汇合。 留神看,后面说了所谓“模式”,具体细分为方框框、菱形和子流程。它们都是“模式”。在 JLisp 里,“模式”对应的数据结构叫做 Expression 。它是一个 Java interface。 既然子流程也是一种特化的“模式”,那 ListExpression 显然也是一种 Expression。 说了那么多,是不是快被绕晕了?其实用 Java 语言来定义子流程,就高深莫测! public class ListExpression extends ArrayList<Expression> implements Expression { // 内容略...}以上,就是 JLisp 的最根本思维。咱们再正式的总结一遍 JLisp 的执行对象为 ListExpressionListExpression 是一个有序列表,由一系列依照程序的 Expression 组成ListExpression 本身也是一种 Expression,因而能够一直嵌套,组成足够简单的规定,一直执行上来试试如何组装当初试试用 JLisp 提供的 API 来组装这个流程 ...

June 20, 2023 · 6 min · jiezi

关于java:让性能腾飞亚马逊云科技的-Java-云端之旅

在上篇文章中,咱们为大家介绍了亚马逊的 Java 生态及丰盛的开发工具、框架。本文将分享亚马逊的 Java 架构、迁徙路径,并分享一个具体实例,介绍如何应用机器学习来构建 Java 利用和晋升 Java 性能。 亚马逊云科技开发者社区为开发者们提供寰球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、流动与比赛等。帮忙中国开发者对接世界最前沿技术,观点,和我的项目,并将中国优良开发者或技术举荐给寰球云社区。如果你还没有关注/珍藏,看到这里请肯定不要匆匆划过,点这里让它成为你的技术宝库!Java 开发的平台之选1 为 Java 利用提供多种开发和部署抉择计算:EC2、Lambda、ECS、EKS、Fargate存储:S3、Elastic File Service网络:Classic Load Balancer、Application Load Balancer、Network Load Balancer、Security Groups、Virtual Private Cloud数据库:RDS、DynamoDB、Aurora、Neptune治理:Auto Scaling、CloudFormation、Systems Manager、CloudWatch家喻户晓,当初很多开发者基于云平台进行 Java 利用的开发和部署。亚马逊云科技提供了一整套欠缺的选项来帮忙开发者更好的开发。例如计算畛域的虚拟机、容器、无服务器,存储畛域的对象存储和文件系统;网络畛域不同层级的负载平衡和访问控制机制;数据库畛域的各种关系型和非关系型数据库;以及全方位多角度的治理和监控。 2 执行环境 在 Java 的执行环境方面,开发者通常会抉择三个次要的计算形式,包含虚构服务器 (Amazon EC2)、容器 (Amazon ECS、EKS 和 Fargate)、无服务器计算 (Amazon Lambda)。无论是哪种形式,亚马逊都在一直增加新的能力来帮忙开发者进行更好的 Java 构建。 3 无服务器利用 无服务器计算在近年来成为越来越多开发者的首选。Amazon Lambda 治理所有的基础设施,以将代码放在可用性高的容错型基础设施上运行,从而使开发者可能专一于构建有差异后端服务。应用 Lambda,开发者不用在补丁公布时更新底层操作系统 (OS),或随着使用量的减少而为调整大小或增加新服务器放心。Amazon Lambda 无缝部署代码、执行所有的治理、保护和安全补丁操作,并通过 Amazon CloudWatch 提供内置记录和监控。 应用 Amazon Lambda,不须要理解任何新语言、工具或框架。开发者能够应用任何第三方库,甚至是本机库。你还能够将任何代码(框架、软件开发工具包、库等)打包为 Lambda Layer,并在多个函数之间轻松进行治理和共享。Lambda 原生反对 Java,并提供 Runtime API,容许开发者应用任何其余编程语言来编写函数。 Lambda 函数是在齐全托管的运行时环境中执行函数代码,因而每次应用程序扩大以创立新的执行环境时都会进行初始化。在 2022 年 re:Invent 大会上,新性能 Amazon Lambda SnapStart 正式公布。利用 SnapStart 可将 Lambda 函数冷启动持续时间升高至不到 200 毫秒,提早率升高 90%,使得冷启动跟非冷启动(缓存命中)简直没有区别。目前这项性能实用于应用 Corretto 运行时的 Java 函数,包含 Spring Boot、Quarkus、Micronaut 和其余 Java 框架的利用。 ...

June 19, 2023 · 2 min · jiezi

关于java:使用-SaToken-实现-记住我-模式登录七天免登录

一、需要剖析如图所示,个别网站的登录界面都会有一个 [记住我] 按钮,当你勾选它登录后,即便你敞开浏览器再次关上网站,也仍然会处于登录状态,毋庸反复验证明码: 本文将具体介绍在 Sa-Token中,如何做到以下登录模式: 记住我登录:登录后敞开浏览器,再次关上网站登录状态仍然无效,无需反复登录。仅本次无效登录:登录后敞开浏览器,再次关上网站登录状态将生效,须要再次登录。七天免登录:为登录状态设定一个具体的有效期,在这个期限内无需反复登录,过了期限后须要再次登录。Sa-Token 是一个轻量级 java 权限认证框架,次要解决登录认证、权限认证、单点登录、OAuth2、微服务网关鉴权 等一系列权限相干问题。 Gitee 开源地址:https://gitee.com/dromara/sa-token首先在我的项目中引入 Sa-Token 依赖: <!-- Sa-Token 权限认证 --><dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.34.0</version></dependency>注:如果你应用的是 SpringBoot 3.x,只须要将 sa-token-spring-boot-starter 批改为 sa-token-spring-boot3-starter 即可。 二、在 Sa-Token 中实现记住我性能Sa-Token的登录受权,默认就是[记住我]模式,为了实现[非记住我]模式,你须要在登录时如下设置: // 设置登录账号id为10001,第二个参数指定是否为[记住我],当此值为false后,敞开浏览器后再次关上须要从新登录StpUtil.login(10001, false);那么,Sa-Token实现[记住我]的具体原理是? 三、实现原理Cookie作为浏览器提供的默认会话跟踪机制,其生命周期有两种模式,别离是: 长期Cookie:有效期为本次会话,只有敞开浏览器窗口,Cookie就会隐没。长久Cookie:有效期为一个具体的工夫,在工夫未到期之前,即便用户敞开了浏览器Cookie也不会隐没。利用Cookie的此个性,咱们便能够轻松实现 [记住我] 模式: 勾选 [记住我] 按钮时:调用StpUtil.login(10001, true),在浏览器写入一个长久Cookie贮存 Token,此时用户即便重启浏览器 Token 仍然无效。不勾选 [记住我] 按钮时:调用StpUtil.login(10001, false),在浏览器写入一个长期Cookie贮存 Token,此时用户在重启浏览器后 Token 便会隐没,导致会话生效。动静演示图: 四、前后端拆散模式下如何实现[记住我]?此时机智的你很快发现一个问题,Cookie虽好,却无奈在前后端拆散环境下应用,那是不是代表上述计划在APP、小程序等环境中有效? 精确的讲,答案是必定的,任何基于Cookie的认证计划在前后端拆散环境下都会生效(起因在于这些客户端默认没有实现Cookie性能),不过好在,这些客户端个别都提供了代替计划,惟一遗憾的是,此场景中token的生命周期须要咱们在前端手动管制: 以经典跨端框架 uni-app 为例,咱们能够应用如下形式达到同样的成果: // 应用本地存储保留token,达到 [长久Cookie] 的成果uni.setStorageSync("satoken", "xxxx-xxxx-xxxx-xxxx-xxx");// 应用globalData保留token,达到 [长期Cookie] 的成果getApp().globalData.satoken = "xxxx-xxxx-xxxx-xxxx-xxx";如果你决定在PC浏览器环境下进行前后端拆散模式开发,那么更加简略: // 应用 localStorage 保留token,达到 [长久Cookie] 的成果localStorage.setItem("satoken", "xxxx-xxxx-xxxx-xxxx-xxx");// 应用 sessionStorage 保留token,达到 [长期Cookie] 的成果sessionStorage.setItem("satoken", "xxxx-xxxx-xxxx-xxxx-xxx");Remember me, it's too easy! ...

June 19, 2023 · 2 min · jiezi

关于java:Spring-FrameWork从入门到NB-primaryQualifierResourceValue

学习几个十分罕用的然而也非常简单的Spring注解。只是做个简略阐明,具体可参考Spring官网,说的很具体。 @Primary其实后面几篇文章曾经做过理解了,咱们晓得Spring主动拆卸的时候首先是按类型获取候选对象的,那就有可能有多个对象同时满足,这种状况下被@Primary注解标注的Bean会最终被选中并注入。 @Qualifier有多个候选对象的状况下,还能够应用@Qualifier注解帮忙Spring放大抉择范畴。 @Qualifier能够和@Autowired配合,作用在属性上或者办法参数上: public class MovieRecommender { //作用在属性上 @Autowired @Qualifier("main") private MovieCatalog movieCatalog; // 作用在办法参数上 @Autowired public void prepare(@Qualifier("main") MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) { this.movieCatalog = movieCatalog; this.customerPreferenceDao = customerPreferenceDao; }}属性或参数名称是默认的Qulifier,不须要显式指定。 @Resource@Resource是 JSR-250注解(jakarta.annotation.Resource) ,能够作用在属性或者Setter办法上(CommonAnnotationBeanPostProcessor解决)。 @Resource有一个name属性: public class SimpleMovieLister { private MovieFinder movieFinder; @Resource(name="myMovieFinder") public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; }}Spring注入的时候将指定的name作为bean name去容器中查找,不指定name的话Spring默认以@Resource作用的属性名作为bean name查找。 能够通过配置Spring的SimpleJndiBeanFactory以扭转Spring的默认行为:通过JNDI查找bean,然而Spring官网倡议放弃Spring的默认属性、通过bean name匹配。 @Autowired和@Resource的区别两者都能够用来实现bena的注入,次要区别是依赖注入过程中的查找bean的规定不同。 @Autowire首先是byType + @Qulifier找到所有候选对象,之后如果候选对象比拟多的话,通过@Primary过滤,如果没有指定@Primary bean的话,再by name匹配。 @Resource实现通过name查找,匹配不到的话再通过type匹配。 所以两者查找bean的形式不同。 @Value@Value注解用来将配置文件中指定的数据拆卸到bean中,能够拆卸到属性或者办法参数中。 比方: @Componentpublic class MovieRecommender { private final String catalog; public MovieRecommender(@Value("${catalog.name}") String catalog) { this.catalog = catalog; }}Configation类文件: ...

June 18, 2023 · 1 min · jiezi

关于java:IoTOS-v100-开源-高效-实用-免费商用

<p></p> IoTOS v1.0.0一款高效实用 IoTCard 治理 & 经营零碎。IoTOS 目前取名范畴过大,其次要用于IoTCard 治理业务以高效、强壮、灵便设计 SaaS、多语言、机器人推送、自动化治理、数据同步多类型算法为次要业务。 一、 对于 IoTOS1.1 介绍IoTOS 是基于 SpringBoot、Vue、Mybatis、RabbitMq、Mysql、Redis 的开源 IoTCard(物联卡管理) 零碎,是企业私域治理与经营的综合解决方案。 IoTOS 基于多个物联网管理系统API(如:中国移动 oneLink 等 后续接入API) 凋谢能力,不仅集成了上游弱小的API治理及根底的 数据同步算法 性能,而且提供了多语言国际化计划。并通过 高效灵便的同步算法、零碎构架业务拆散 等灵便高效的数据经营模块,让企业与上游之间建设强链接,从而进一步通过多元化的治理经营计划,帮忙企业进步物联网卡经营效率,强化经营能力,拓展科盈利空间。 目前次要使用于 物联网卡 服务行业畛域。 1.2 能力IoTOS-IoTCard 基于物联网多上游API接口综合业务管理,听从高效数据同步并保护经营,再到建设零碎套餐散发进行资费营销,最初在营销、经营 等服务提供 过程中再次发明价值的流程。 整个零碎暂且 分为五大模块: 首页 :统计分析展板;连贯 :流量卡、设施、通道 经营治理 配置查看;账号核心 :企业、用户、角色 治理调配权限 账号;自动化 :自动化治理规定、模板、推送配置、触发条件 等;系统管理 :菜单、参数、字典、系统监控、零碎工具、定时工作 等;欢送有趣味的 开发者、商业单干、业务探讨 等 通过下方的联系方式分割 1.3 劣势IoTOS 基于多个上游运营商能力接口 凋谢能力平台综合业务管理经营物联网卡 但不仅限于物联网卡,可为 物联卡经营、多个第三方接口对接需要 等垂直场景提供API对接治理基础架构,次要劣势有: 多语言国际化操作(UI界面、后盾回复、单用户爱好语言)、机器人推送(国内支流机器人、国内支流社交软件)高效API同步能力采纳队列多线程实例开启接口多线程(队列多线程中再减少java多线程)更具不同运营商接口独立特定同步算法体系自动化规定定义 规定触发模板 告诉配置 触发条件等开源协定采纳 Apache-2.0 (使用者能够自在批改,进行商业应用,没有开源要求)采纳支流 Java 架构,具备高拓展性、灵活性对外提供外部 API,低成本二次开发1.4 愿景IoTOS 不做物联网专家,而是通过开源让每个企业、每个开发者 都是本人的物联网专家: ...

June 18, 2023 · 2 min · jiezi

关于java:Spring-FrameWork从入门到NB-基于注解配置-Autowired注解

基于注解的配置其实后面咱们曾经在基于注解配置了,这是因为集体比拟喜爱基于注解配置。 Spring官网文档提过一个问题:基于注解配置要好于基于xml的配置吗?其实各有千秋,依据集体爱好吧。重要的是Spring能够反对基于注解配置,也能够反对基于xml配置文件配置,也能够反对两者的混搭。 咱们能够应用Spring的基于BeanPostProcessor的@Autowire注解,Spring也反对JSR-250的@PostConstruct和@PreDestroy注解,以及基于 JSR-330 (Dependency Injection for Java) 的注解 @Inject 和 @Named。 基于注解的依赖注入的执行要早于基于xml配置文件,所以如果同时应用的话,基于xml文件的配置要优先于基于注解的:xml配置会笼罩掉注解配置。 通过以下配置能够实现混合xml和注解的配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd" > <context:annotation-config/> <context:component-scan base-package="packageName.packageName"/></beans>基于注解的配置的底层失效原理其实是通过BeanPostProcessor,配置项 <context:annotation-config/>在Spring容器中隐式的注册了如下BeanPostProcessor: ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessorEventListenerMethodProcessor比方@Autoware注解就是通过AutowiredAnnotationBeanPostProcessor(postProcessProperties办法)失效的。 @Autowired注解@Autowired注解能够作用在构造方法、属性、以及一般办法上,咱们在后面的文章中曾经做过阐明。 作用在构造方法和一般办法上,会主动拆卸办法中的参数,作用在属性上则主动拆卸该属性。 @Autowired注解是通过类型匹配的,所以增加注解的参数类型和注册到Spring IoC容器中的Bean的类型必须要匹配,如果Spring IoC在主动拆卸的过程中找不到匹配的Bean执行注入的话,会产生注入失败,抛异样。 Spring能够反对将同一类型的Bean注入到汇合对象中,比方: public class MovieRecommender { private Set<MovieCatalog> movieCatalogs; @Autowired public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) { this.movieCatalogs = movieCatalogs; } // ...}则Spring IoC容器中的所有类型为MovieCatalog的Bean都会注入到movieCatalogs中。MovieCatalog能够通过实现 org.springframework.core.Ordered接口或者应用@Order注解、 @Priority注解实现排序。 也能够将同类型的对象注入到Map中: public class MovieRecommender { private Map<String, MovieCatalog> movieCatalogs; @Autowired public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) { this.movieCatalogs = movieCatalogs; } // ...}此时Map的key值为bean name,value值为bean对象。 ...

June 17, 2023 · 1 min · jiezi

关于java:Difference-between-SoftReference-and-WeakReference-in-Java

【Java】What's the difference between SoftReference and WeakReference in Java原文What's the difference between SoftReference and WeakReference in Java? From Understanding Weak References, by Ethan Nicholas: 引言在学习JVM的过程中大概率会看到相似 SoftReference 和 WeakReference的字样,本局部筛选了Stack Flow 上的高赞答复进行整顿。 Understanding Weak ReferencesUnderstanding Weak References 尽管是一篇2006年的博客,然而写的十分好,并且至今也仍然有不小的价值,这里简略翻译和提取一下这篇文章的内容。 后面一大段阐明写这篇文章的原因是面试的时候发现很多面试者甚至不晓得这个货色,相比之下本人不仅聊了作用和一些细节反差很大。 Now, I'm not suggesting you need to be a weak reference expert to qualify as a decent Java engineer. But I humbly submit that you should at least _know what they are_ -- otherwise how will you know when you should be using them? Since they seem to be a little-known feature, here is a brief overview of what weak references are, how to use them, and when to use them.当初,我并不是说你须要成为一个单薄的参考资料专家,才有资格成为一个体面的Java工程师。但我虚心地认为,你至多应该晓得它们是什么 -- 否则你怎么会晓得什么时候应该应用它们?因为它们仿佛是一个鲜为人知的个性,这里简要介绍一下什么是弱援用,如何应用它们,以及何时应用它们。 ...

June 16, 2023 · 5 min · jiezi

关于java:Java-新的生态Solon-v233-发布

Solon 是什么框架?一个,Java 新的生态型利用开发框架。它从零开始构建,有本人的标准规范与凋谢生态(寰球第二级别的生态)。与其余框架相比,它解决了两个重要的痛点:启动慢,费资源。 解决痛点?因为Solon Bean容器的独特设计,不会因为扩大依赖变多而启动很慢(开发调试时,省时、痛快)!以出名开源我的项目“小诺”为例: “snowy-spring 版” 启动 30-50秒“snowy-solon 版” 启动3-5秒(有趣味的,欢送拉取代码体验)所谓:“工夫就是生命,效率就是金钱”,“天下文治,唯快不破”。 绝对于 Spring Boot 和 Spring Cloud 的我的项目,有什么特点?启动快 5 ~ 10 倍。 (更快)qps 高 2~ 3 倍。 (更高)运行时内存节俭 1/3 ~ 1/2。 (更少)打包能够放大到 1/2 ~ 1/10;比方,300Mb 的变成了 23Mb。 (更小)同时反对 jdk8, jdk11, jdk17, jdk20, graalvm native本次更新了什么?调整 solon-cloud-alibaba 快捷包 改用 nacos2,rocketmq5调整 file-s3-solon-cloud-plugin 插件,aws-java-sdk-s3 为必选(之前不是)增加 dromara-plugins 所有插件的版本治理增加 PathRule 工具类,做为多路由匹配规定的工具增加 PathLimiter 用于限度 RouterInterceptor 的范畴增加 MybaitsAdapter::getMapper 减少缓存解决增加 maxHeaderSize(8k), maxBodySize(2m) 为 server 对立默认配置增加 Context::sessionOrDefault(),headerOrDefault(),paramOrDefault() 接口增加 ChainManager::getFilterNodes(),getInterceptorNodes() 接口优化 AsmProxy 代理类的缓存机制(简化)优化 Utils::firstOrNull 减少 null 判断优化 ClassUtil 的异样解决优化 Context::filesMap() 改抛 IOException 异样优化 Context::param(key,def) 解决并弃用,改由 paramOrDefault 代替wood 升为 1.1.3nacos2 升为 2.2.3rocketmq5 升为 5.0.5dubbo3 升为 3.2.2我的项目仓库地址?gitee:https://gitee.com/noear/solongithub:https://github.com/noear/solon技术支持与交换?https://solon.noear.org/article/support

June 16, 2023 · 1 min · jiezi

关于java:首添机密计算创新成果龙蜥首获-ACM-SIGSOFT-杰出论文奖

近日,软件工程畛域的寰球旗舰级会议-软件工程大会 ICSE 在澳大利亚墨尔本市召开,龙蜥社区云原生秘密计算 SIG 核心成员(阿里云JVM 团队)在 Java 秘密计算方面的研究成果入选了 ICSE2023,并且以该会议往年惟一的 All Fives(审稿全满分)问题荣获 ACM SIGSOFT 卓越论文奖。“平安可信”是龙蜥社区的八大技术方向之一 ,为保障用户 Java 程序的安全性,龙蜥社区云原生秘密计算 SIG 重投 Java 秘密计算,此次获奖是对龙蜥秘密计算翻新成绩的必定,也为龙蜥将此技术创新回升为用户计划奠定了根底。 IEEE/ACM ICSE 全称 International Conference on Software Engineering,致力于为软件工程畛域的研究者、教育者和从业者们提供最新最重要的研究成果、教训及方向,是软件工程畛域排名第一的学术会议。ACM SIGSOFT 卓越论文奖为 ICSE 会议最重要的论文奖项。本年度 ICSE 国内会议接管的 207 篇高水平论文中,取得卓越论文奖的论文共计 10 篇。 龙蜥社区云原生秘密计算 SIG 联结上海交通大学计算机系陈雨亭副教授钻研团队单干研发了 Java 秘密计算的框架 Teaclave Java TEE SDK,发表题目为“Lejacon: A Lightweight and Efficient Approach to Java Confidential Computing on SGX”(Lejacon:一种实用于 SGX 的轻量高效 Java 秘密计算方法)的论文,提出了一种涵盖开发模型、编译工具链和运行时秘密计算生命周期治理的 Java 秘密计算框架,该框架基于开发者的轻量标注实现主动代码分区,利用 Java 动态编译技术部署秘密工作于 SGX 平安飞地中,晋升秘密工作执行效率的同时放弃了较小体积的可信计算基,进步了安全性。 ...

June 16, 2023 · 1 min · jiezi

关于java:Spring-Boot-实现定时任务动态管理太爽了

一、性能阐明SpringBoot的定时工作的增强工具,实现对SpringBoot原生的定时工作进行动静治理,齐全兼容原生@Scheduled注解,无需对本来的定时工作进行批改 二、疾速应用具体的性能曾经封装成SpringBoot-starter即插即用: <dependency> <groupId>com.github.guoyixing</groupId> <artifactId>spring-boot-starter-super-scheduled</artifactId> <version>0.3.1</version></dependency>应用办法和源码: 码云:https://gitee.com/qiaodaimadewangcai/super-scheduledgithub:https://github.com/guoyixing/super-scheduled举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice三、实现原理1、动静治理实现(1) 配置管理介绍 @Component("superScheduledConfig")public class SuperScheduledConfig { /** * 执行定时工作的线程池 */ private ThreadPoolTaskScheduler taskScheduler; /** * 定时工作名称与定时工作回调钩子 的关联关系容器 */ private Map<String, ScheduledFuture> nameToScheduledFuture = new ConcurrentHashMap<>(); /** * 定时工作名称与定时工作须要执行的逻辑 的关联关系容器 */ private Map<String, Runnable> nameToRunnable = new ConcurrentHashMap<>(); /** * 定时工作名称与定时工作的源信息 的关联关系容器 */ private Map<String, ScheduledSource> nameToScheduledSource = new ConcurrentHashMap<>(); /* 一般的get/sets省略 */}(2) 应用后处理器拦挡SpringBoot本来的定时工作 实现ApplicationContextAware接口拿到SpringBoot的上下文实现BeanPostProcessor接口,将这个类标记为后处理器,后处理器会在每个bean实例化之后执行应用@DependsOn注解强制依赖SuperScheduledConfig类,让SpringBoot实例化SuperScheduledPostProcessor类之前先实例化SuperScheduledConfig类次要实现逻辑在postProcessAfterInitialization()办法中 @DependsOn({"superScheduledConfig"})@Component@Orderpublic class SuperScheduledPostProcessor implements BeanPostProcessor, ApplicationContextAware { protected final Log logger = LogFactory.getLog(getClass()); private ApplicationContext applicationContext; /** * 实例化bean之前的操作 * @param bean bean实例 * @param beanName bean的Name */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } /** * 实例化bean之后的操作 * @param bean bean实例 * @param beanName bean的Name */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { //1.获取配置管理器 SuperScheduledConfig superScheduledConfig = applicationContext.getBean(SuperScheduledConfig.class); //2.获取以后实例化实现的bean的所有办法 Method[] methods = bean.getClass().getDeclaredMethods(); //循环解决对每个办法逐个解决 if (methods.length > 0) { for (Method method : methods) { //3.尝试在该办法上获取@Scheduled注解(SpringBoot的定时工作注解) Scheduled annotation = method.getAnnotation(Scheduled.class); //如果无奈获取到@Scheduled注解,就跳过这个办法 if (annotation == null) { continue; } //4.创立定时工作的源属性 //创立定时工作的源属性(用来记录定时工作的配置,初始化的时候记录的是注解上本来的属性) ScheduledSource scheduledSource = new ScheduledSource(annotation, method, bean); //对注解上获取到源属性中的属性进行检测 if (!scheduledSource.check()) { throw new SuperScheduledException("在" + beanName + "Bean中" + method.getName() + "办法的注解参数谬误"); } //生成定时工作的名称(id),应用beanName+“.”+办法名 String name = beanName + "." + method.getName(); //将以key-value的模式,将源数据存入配置管理器中,key:定时工作的名称 value:源数据 superScheduledConfig.addScheduledSource(name, scheduledSource); try { //5.将本来SpringBoot的定时工作勾销掉 clearOriginalScheduled(annotation); } catch (Exception e) { throw new SuperScheduledException("在敞开原始办法" + beanName + method.getName() + "时呈现谬误"); } } } //最初bean放弃原有返回 return bean; } /** * 批改注解原先的属性 * @param annotation 注解实例对象 * @throws Exception */ private void clearOriginalScheduled(Scheduled annotation) throws Exception { changeAnnotationValue(annotation, "cron", Scheduled.CRON_DISABLED); changeAnnotationValue(annotation, "fixedDelay", -1L); changeAnnotationValue(annotation, "fixedDelayString", ""); changeAnnotationValue(annotation, "fixedRate", -1L); changeAnnotationValue(annotation, "fixedRateString", ""); changeAnnotationValue(annotation, "initialDelay", -1L); changeAnnotationValue(annotation, "initialDelayString", ""); } /** * 获取SpringBoot的上下文 * @param applicationContext SpringBoot的上下文 */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}(3) 应用ApplicationRunner初始化自定义的定时工作运行器 ...

June 16, 2023 · 7 min · jiezi

关于java:MySQL数据库中数值字段类型长度int11和DecimalMD详解

一、Mysql中数值类型下图为Mysql反对的数值类型及取值范畴 BIT[M] 位字段类型,M示意每个值的位数,范畴从1到64,如果M被疏忽,默认为1TINYINT[(M)] [UNSIGNED] [ZEROFILL] M默认为4 ,小的整数。带符号的范畴是-128到127。无符号的范畴是0到255。SMALLINT[(M)] [UNSIGNED] [ZEROFILL] M默认为6 ,小的整数。带符号的范畴是-32768到32767。无符号的范畴是0到65535。MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] M默认为9 ,中等大小的整数。带符号的范畴是-8388608到8388607。无符号的范畴是0到16777215。INT[(M)] [UNSIGNED] [ZEROFILL] M默认为11 ,一般大小的整数。带符号的范畴是-2147483648到2147483647。无符号的范畴是0到4294967295。BIGINT[(M)] [UNSIGNED] [ZEROFILL] M默认为20 ,大整数。带符号的范畴是-9223372036854775808到9223372036854775807。无符号的范畴是0到18446744073709551615。须要留神 这里的M代表的并不是存储在数据库中的具体的长度,如果误以为int(3)只能存储3个长度的数字,int(11)就会存储11个长度的数字,这是不对的 tinyint(1) 和 tinyint(4) 中的1和4并不示意存储长度,只有字段指定zerofill才是有用(也就是零填充时), 如tinyint(4),如果理论值是2,如果列指定了zerofill,查问后果就是0002,右边用0来填充`。二、有无限度的区别是什么对应Integer 类型而言,仅示意字段的显示宽度。对于DECIMAL类型,示意数字的总数。对于字符字段,这是能够存储的最大字符数,例如VARCHAR(20)能够存储20个字符。显示宽度并不影响能够存储在该列中的最大值。int(5)和int(11) 所能存储的最大范畴是一样的。将某个字段设置成INT(20)并不意味着将可能存储20位数字,这个字段最终能存储的最大范畴还是 INT 的范畴。三、有无符号的区别是什么那么问题来了,既然加不加数字并没有什么区别,那为什么还多此一举呢? “失常”状况下的确没有什么区别,只有当字段设置为UNSIGNED ZEROFILL 属性时,INT 减少数字才会有意义。示意如果要存储的数字少于N 个字符,则这些数字将在左侧补零。四、罕用的int(11)代表什么意思id INT(11) NOT NULL AUTO_INCREMENT,在一些建表语句会呈现下面 int(11) 的类型,那么其代表什么意思呢? 对于Integer类型括号中的数字称为字段的显示宽度。这与其余类型字段的含意不同。显示宽度并不影响能够存储在该列中的最大值。INT(5) 和 INT(11)能够存储雷同的最大值。哪怕设置成 INT(20) 并不意味着将可能存储20位数字(BIGINT),该列还是只能存储INT的最大值。对于DECIMAL类型,示意数字的总数。对于字符字段,这是能够存储的最大字符数,例如VARCHAR(20)能够存储20个字符。当列设置为UNSIGNED ZEROFILL时,INT(11)才有意义,其示意的意思为如果要存储的数字少于11个字符,则这些数字将在左侧补零。五、简述Decimal(M,D)数据类型用法当咱们须要存储小数,并且有精度要求,比方存储金额时,通常会思考应用DECIMAL字段类型。 1.简述语法是DECIMAL(M,D) DECIMAL(M,D)中M为总长度,D为小数点后的保留的位数,M范畴是1到65,D范畴是0到30。M大于D,存储数值时,小数位有余会主动补0,首位数字为0主动疏忽。2.重点 六、总结对于Integer 类型而言,“数字”并不会限度其能存储的最大范畴。DECIMAL(M,D)中M为总长度,D为小数点后的保留的位数对于字符字段,这是能够存储的最大字符数,例如VARCHAR(20)最多存储20个字符。如果误以为int(3)只能存储3个长度的数字,int(11)就会存储11个长度的数字,这是不对的 3和11并不示意存储长度,只有字段指定zerofill才是有用(也就是零填充时),右边用0来填充`。**

June 16, 2023 · 1 min · jiezi

关于java:JavaBest-coding-practices-every-java-developer-should

原文Best coding practices every java developer should follow 目录引言4. 尽可能让变量私有化6. 警觉冗余初始化5. Stringbuilder替换字符串拼接【争议】15. dry和kiss14. Solid7. 尽可能应用加强for循环或者foreach13. 日志打印规定12. Hardcoding硬编码11. 正文10. 防止创立不必要对象9. 返回空集合而不是null8. 精度抉择1. 我的项目构造2. 遵循命名标准3. 不要吞异样16. 应用枚举代替动态常量【倡议】17. 按作用域划分成员变量18. 在数字字段中应用下划线【倡议】总结参考引言把题目翻译成中文在国内也是一个陈词滥调的问题:编程习惯和编码标准。 这篇文章大部分观点和国内的标准习惯相似,令我好奇的是外国人是如何了解这些内容的? 留神本文的Tips排序是打乱的,集体把感兴趣放到了后面来了。这篇文章的评论区十分精彩,这里一并整合了评论区的读者观点。 不论是学习还是理解老外的思考形式,或是在评论区当中看读者的探讨和纠正错误,浏览本文都是值得举荐的。 抱着将信将疑的态度学习这些内容,你会失去比单纯的理解和承受倡议更多的播种。 4. 尽可能让变量私有化如果变量不须要意对外拜访,那就倡议应用公有形容对于参数进行形容。 评论区的读者对于这一个大节做了补充: 如果是dto并且是final的,领有专用数据的时候能够不私有化.。比大量的setter更好倡议是更正当的利用设计模式构建对象(比方建造者),或者利用委托第三方对象生产适合的对象(动态工厂代替结构器)。尽可能让对象不可变。6. 警觉冗余初始化Therefore, a java best practice is to be aware of the default initialization values of member variables and avoid initializing the variables explicitly.Java 最佳实际是理解成员变量的默认初始化值并防止显式初始化变量,Java语言很多变量存在默认值,在本人编写初始化的时候不倡议应用Java的默认值。 另一方面,有时候能够利用Java的初始化做数据库字段的优化,比方开关状态倡议把0设置为凋谢1设置为敞开。 上面的代码的的对象初始化代码是毫无意义的: public class Person { private String name; private int age; private boolean; public Person() { String name = null; int age = 0; boolean isGenius = false; }}Although it is very common practice, it is not encouraged to initialize member variables with the values: like 0, false and null. These values are already the default initialization values of member variables in Java. Therefore, a java best practice is to be aware of the default initialization values of member variables and avoid initializing the variables explicitly.只管这是十分常见的做法,但不激励应用以下值初始化成员变量:如 0、false 和 null。这些值曾经是 Java 中成员变量的默认初始化值。因而,Java 最佳实际是理解成员变量的缺省初始化值,并防止显式初始化变量。 ...

June 15, 2023 · 5 min · jiezi

关于java:Java2小时搞定多线程个人笔记

简介基于慕课网站上的一个一元钱课程《2小时搞定多线程》的 集体笔记。 线程的起源咱们先来看看网络中对于线程起源的阐明,了解线程的前因后果对于把握多线程有肯定帮忙。 此局部内容整顿自上面两篇网络博客: # 线程是什么# 线程的起源线程的起源与计算机的倒退非亲非故。晚期的计算机系统是单指令模式,资源利用效率低下。当批处理模式即计算机的多指令模式呈现后,计算机资源利用率失去无效晋升,但这种模式又常常导致 CPU 陷入期待状态,无奈失去充分利用,于是过程呈现了。 当用户对计算机收回一系列操作指令时,每个过程会将不同的操作储存起来,随时进行切换。然而过程的指令执行效率依然不够快,无奈在同一时刻执行多个工作。为了解决这一问题,技术人员又创造了线程。 有了线程当前,每个操作指令对应的工作都可能被划分为多个子工作,由每一个独自的线程负责,而不同的线程能够同时运行,这样计算机的运行效率便失去进一步晋升。 咱们能够把下面的几段内容做一个概括: 单指令模式(相似计算器)。多指令模式(批处理)。批处理存在CPU期待状况,过程诞生。过程指令运行效率不满足需要,为了解决多任务线程诞生。咱们会发现这里存在一些不太分明的概念,单指令是什么?多指令模式又是什么?为什么批处理存在CPU期待状况等等.....上面咱们至上而下进行简略剖析。 单指令模式(相似计算器)在计算机诞生的最晚期,计算机属于政府和一些大型公司才有的”低廉“仪器,受制各种因素限度,过后计算机只能实现一些相似”1+1“的指令操作,并且要实现这样的操作须要用户把程序写入到打孔卡(能够看作最晚期的存储设备)并由专门操作人员实现执行,整个过程十分繁琐。 受这样的工作模式限度,不论来多少个用户进行输出,也只能期待计算机管理人员拿到”指令“(物理意义上)实现执行。在”拿指令“和”执行“的间隙,整个计算机都是闲暇不干活的,资源利用率极低。 多指令模式(批处理)随着CPU的执行效率晋升以及对CPU资源利用率的要求晋升,计算机管理员逐步成为执行瓶颈,由此诞生了多指令模式。 多指令模式相似饭店点餐一次性下多个指令批量实现。为此人们设计了对应的批处理操作系统,由它代替计算机管理员实现工作的执行切换工作, 批处理能够挨个执行多个指令,此时咱们能够把整个计算机本身类比为”单过程“操作,所以批处理在某些状况下仍然存在”闲置“的状况,比方4条指令中第3条须要拜访IO设施,此时第4条指令哪怕和第3条没有任何关系也仍然须要期待。 过程诞生以上的工作模式被叫做”单道批处理操作系统“,前面为了解决期待问题,人们又设计了多道批处理操作系统(也叫多任务操作系统),它的改良劣势如下: 内存划分多个区域,每个区域存储一个程序。程序执行 I/O 操作时,操作系统会将 CPU 资源分配给其它期待执行的程序。由此”过程“的根底概念便诞生了,过程就是执行中的应用程序,操作系统会为每个过程调配独立的内存、空间和所须要的资源(IO设施,文件等)。 线程诞生然而随着计算机软硬件的倒退,人们发现像过程这种”指挥军队“的粒度代价很高并且难以管制,前面又提出了线程的概念。 过程调度的一些问题: 过程切换开销大。过程占用空间是独立的,实现过程通信难度很大。单个过程自身执行相似IO操作仍然会呈现期待状况。(只不过此时能够切换到其余过程)至此咱们简略梳理了单指令模式到线程诞生的全过程。 线程和过程的关系线程蕴含于过程当中,过程是线程的汇合。 当操作系统运行时,至多有一个过程会启动,而这个过程中往往蕴含了多个线程。 线程和过程的区别相同点如下: 两者都生命周期是由一样的,线程会随着过程完结而一起完结。 不同点如下: 起源不同:先有过程后有线程,晚期CPU为了跟上内部操作,后续呈现线程的概念来提高效率。概念不同:线程是CPU调度的最小单位,而过程是操作系统调度程序的独立单位。作用域不同:通常线程存在共享区域,然而在过程和过程之间内容不共享(除非应用相似IPC伎俩进行过程通信)。开销不同:过程之间通信须要内核辅助创立开销绝对较大,而线程通信创立线程的开销很小。 线程创立终止工夫比过程短。同一个过程内线程切换工夫比过程短。同一个过程内线程能够相互共享文件资源和内存,并且不依赖内核就能够实现。领有资源不同,线程在领有过程大部分根本资源之外还有独立的内容。数量不同:同一个过程通常只有一个,而每个过程至多有一个线程。这里强调一下领有资源不同的含意,线程共享内容包含: 过程代码段。过程私有资源(线程能够利用过程的共享资源简略通信)。过程关上的文件描述符。信号处理器。过程当前目录。过程ID过程组ID线程独有内容包含: 寄存器的值线程ID线程名称线程堆栈谬误返回号码线程信号屏蔽码Java 和 多线程为了投合时代需要,Java自诞生之初就人造反对多线程,Java的多线程实现是和内核线程一对一映射。 Jvm 人造多线程验证Jvm启动须要主动开启一些后盾线程维持工作: Finalize线程:解决局部对象的finalize操作。高版本jdk曾经弃用此实现Single signature:接管操作系统的信号量来进行一些操作,比方Kill的信号量接管强制关闭程序。main 线程:也叫主线程,其余用户创立的线程都都叫做子线程reference gc:垃圾回收线程,对象清理工作为了证实下面的实践,咱们能够通过IDEA进行调试来验证答案。 首先咱们通过IDEA编写一个HelloWorld程序,当然为了不便这里集体间接拿了SpringBoot的Main启动代码进行验证。 public class InterviewApplication { public static void main(String[] args) { SpringApplication.run(InterviewApplication.class, args); } }咱们把Debug断点打在代码的第一行,而后Idea中间接Debug运行。 通过上面的筛选性能,咱们能够Debug中切换到其余的线程进行察看多线程执行状况。 上面j后果应用为JDK11运行。 除了下面这种察看形式之外,咱们能够通过“Threads“视图界面察看所有线程的运行状况。以IDEA2022版本为例,关上”Threads“视图只须要在右上角点击小方块而后勾选“Threads”即可。 上面后果应用JDK8运行。 集体更喜爱下面的展示形式,平淡无奇通知开发者以后断点内的线程运行状况。 如果想要多线程Debug,能够鼠标右击断点,接着会呈现相干提醒切换到“Thread”,,在调试多线程代码的时候,这个操作会十分不便好用。 通过下面的简略解说能够证实Java天生就是多线程程序(哪怕只有一行代码)。 ...

June 15, 2023 · 1 min · jiezi

关于java:Swagger3-使用介绍

这篇文章将介绍如何在 java 中应用 swagger3,一、Swagger3 简介官网地址:https://swagger.io/ Swagger 是一个标准和残缺的框架,用于生成可视化 RESTful 格调的 Web 服务。是一个简略且功能强大的API工具。简直所有的古代编程语言,都在反对和应用。 Swagger2曾经进行保护了,取而代之的是 swagger3, 二、与Swagger2注解比照之前在SpringBoot我的项目中始终应用的是SpringFox提供的Swagger库,曾经很久没有更新了。SpringDoc是一款能够联合SpringBoot应用的API文档生成工具,基于OpenAPI 3,是一款更好用的Swagger库!值得一提的是SpringDoc不仅反对Spring WebMvc我的项目,还能够反对Spring WebFlux我的项目,甚至Spring Rest和Spring Native我的项目,总之十分弱小常常应用的Swagger注解,看看SpringFox的和SpringDoc的有啥区别,毕竟比照已学过的技术能更快把握新技术; 三、 应用步骤1.导入依赖 <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.5.10</version> </dependency>2.增加配置类进行SpringDoc的配置,应用OpenAPI来配置根底的文档信息,通过GroupedOpenApi配置分组的API文档,SpringDoc反对间接应用接口门路进行配置。 @Configurationpublic class SwaggerConfiguration { @Bean public OpenAPI customOpenAPI() { return new OpenAPI().info(new Info() .title("代码平台 API") .description("SpringDoc API 演示") .version("v1.0.0") ); } @Bean public GroupedOpenApi adminApi() { return GroupedOpenApi.builder() .group("一般接口文档") .pathsToMatch("/web/test/**").build(); } @Bean public GroupedOpenApi homeApi() { return GroupedOpenApi.builder() .group("首页相干接口") .pathsToMatch("/query/excel/**") .build(); }3.罕用注解1.@Tag注解用来形容一组操作的信息(通常用在controller管制层类上)例: @Tag(name = "控制器")@RestController@RequestMapping("web/test")public class TestController {}2.@Operation注解用来形容接口信息(通常用在管制层的具体方法上)例: ...

June 15, 2023 · 1 min · jiezi

关于java:SpringBoot集成支付宝-少走弯路就看这篇

最近在做一个网站,后端采纳了SpringBoot,须要集成支付宝进行线上领取,在这个过程中钻研了大量支付宝的集成材料,也走了一些弯路,当初总结进去,置信你读完也能轻松集成支付宝领取。在开始集成支付宝领取之前,咱们须要筹备一个支付宝商家账户,如果是集体开发者,能够通过注册公司或者让有公司资质的单位进行受权,后续在集成相干API的时候须要提供这些信息。 上面我以电脑网页端在线领取为例,介绍整个从集成、测试到上线的具体流程。 1. 预期成果展现在开始之前咱们先看下咱们要达到的最初成果,具体如下: 前端点击领取跳转到支付宝界面支付宝界面展现付款二维码用户手机端领取实现领取,支付宝回调开发者指定的url。 2. 开发流程2.1 沙盒调试支付宝为咱们筹备了欠缺的沙盒开发环境,咱们能够先在沙盒环境调试好程序,后续新建好利用并胜利上线后,把程序中对应的参数替换为线上参数即可。 1. 创立沙盒利用间接进入 https://open.alipay.com/develop/sandbox/app 创立沙盒利用即可, 这里因为是测试环境,咱们就抉择零碎默认密钥就行了,上面抉择公钥模式,另外利用网关地址就是用户实现领取之后,支付宝会回调的url。在开发环境中,咱们能够采纳内网穿透的形式,将咱们本机的端口裸露在某个公网地址上,这里举荐 https://natapp.cn/ ,能够收费注册应用。 2. SpringBoot代码实现在创立好沙盒利用,获取到密钥,APPID,商家账户PID等信息之后,就能够在测试环境开发集成对应的API了。这里我以电脑端领取API为例,介绍如何进行集成。 对于电脑网站领取的具体产品介绍和API接入文档能够参考:https://opendocs.alipay.com/open/repo-0038oa?ref=api 和 https://opendocs.alipay.com/open/270/01didh?ref=api步骤1, 增加alipay sdk对应的Maven依赖。<!-- alipay --> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.35.132.ALL</version> </dependency>步骤2,增加支付宝下单、领取胜利后同步调用和异步调用的接口。这里须要留神,同步接口是用户实现领取后会主动跳转的地址,因而须要是Get申请。异步接口,是用户实现领取之后,支付宝会回调来告诉领取后果的地址,所以是POST申请。@RestController @RequestMapping("/alipay") public class AliPayController { @Autowired AliPayService aliPayService; @PostMapping("/order") public GenericResponse<Object> placeOrderForPCWeb(@RequestBody AliPayRequest aliPayRequest) { try { return aliPayService.placeOrderForPCWeb(aliPayRequest); } catch (IOException e) { throw new RuntimeException(e); } } @PostMapping("/callback/async") public String asyncCallback(HttpServletRequest request) { return aliPayService.orderCallbackInAsync(request); } @GetMapping("/callback/sync") public void syncCallback(HttpServletRequest request, HttpServletResponse response) { aliPayService.orderCallbackInSync(request, response); } }步骤3,实现Service层代码这里针对下面controller中的三个接口,别离实现service层对应的办法。上面是整个领取的外围流程,其中有些中央须要依据你本人的理论状况进行保留订单到DB或者查看订单状态的操作,这个能够依据理论业务需要进行设计。 ...

June 14, 2023 · 4 min · jiezi

关于java:Seata-Saga-模式快速入门和最佳实践

文|王特 (花名:亦夏) Email:yixia.wt@antgroup.com 蚂蚁团体数据中间件外围开发 本文4927 字 浏览 13 分钟 Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简略易用的分布式事务服务。Seata 为用户提供了 AT、TCC、SAGA、XA 等多种事务模式,帮忙解决不同业务场景下的事务一致性问题。 本文次要介绍 Seata Saga 模式的应用以及最佳实际,围绕三个局部开展,第一局部是 Seata Saga 的简介、第二局部旨在疾速介绍 Seata Saga 模式的应用办法并帮忙大家入门,最初一部分将会给大家分享一些 Seata Saga 实际中的教训,帮忙用户更快、更好得应用 Seata Saga 模式。 1 Seata Saga 简介1.1 Saga 模式Saga 模式是分布式事务的解决方案之一,理念起源于 1987 年 Hector & Kenneth 发表的 Sagas 论文。它将整个分布式事务流程拆分成多个阶段,每个阶段对应咱们的子事务,子事务是本地事务执行的,执行实现就会实在提交。 它是一种基于失败的设计,如上图能够看到,每个流动或者子事务流程,个别都会有对应的弥补服务。如果分布式事务产生异样的话,在 Saga 模式中,就要进行所谓的“复原”,复原有两种形式,逆向弥补和正向重试。比方下面的分布式事务执行到 T3 失败,逆向弥补将会顺次执行对应的 C3、C2、C1 操作,勾销事务流动的“影响”。那正向弥补,它是裹足不前的,T3 失败了,会进行一直的重试,而后持续依照流程执行 T4、T5 等。 依据 Saga 模式的设计,咱们能够失去 Saga 事务模式的优缺点。 长处: 子事务 (或流程) ,提交是本地事务级别的,没有所谓的全局锁,在长事务流程下,防止了长时间的资源锁定;另外这种流水线的解决模型人造合乎阶段式信号处理模型,能发掘出更高的性能和吞吐。正向服务和弥补服务都是交给业务开发实现的,所以 Saga 模式和底层数据库协定是无关的。XA/AT 模式可能依赖特定的数据库类型和版本,比方 MySQL 是 5.0 之后才反对的 XA,那么低版本的 MySQL 就不能实用到 XA 模式。毛病: ...

June 14, 2023 · 2 min · jiezi

关于java:SpringBean初始化顺序

Spring bean是Spring框架在运行时治理的对象。Spring bean是任何Spring应用程序的根本构建块。咱们编写的大多数利用程序逻辑代码都将放在Spring bean中。 执行程序: Constructor > @Autowired > @PostConstruct > InitializingBean > init-method因而不能在构造函数中间接应用@Autowired定义的参数,而应该在@PostConstruct中调用。 例如: public class Metric { @Autowired MonitorMetric monitorMetric; final String string; // 构造函数 public Metric(String string){ this.string = string; } // 在 PostConstruct 中获取 Autowired 的值 @PostConstruct public String initialize(){ return monitorMetric.getStr(); }}   学习更多编程常识,请关注我的公众号: 代码的路   

June 14, 2023 · 1 min · jiezi

关于java:Java中时间戳的使用

原文链接 以后工夫import java.sql.Timestamp; //导包Timestamp nowTime = new Timestamp(System.currentTimeMillis());System.out.println(nowTime);输入: 2022-06-08 11:15:51.014Long型工夫戳Long timeLong = System.currentTimeMillis();System.out.println("timeLong:" + timeLong + "\n");输入: 1652862076686工夫戳和工夫的转化public void learnCron() throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); // 设置格局 Long currentTime = System.currentTimeMillis(); // 获取以后工夫戳 System.out.println("currentTime:" + currentTime); String timeString = format.format(currentTime); // 工夫戳转为工夫格局 System.out.println("timeString:" + timeString); Date date = format.parse(timeString); // 工夫格局转为工夫戳 long timeLong = date.getTime(); System.out.println("timeLong:" + timeLong);}输入: currentTime:1686122941014timeString:2023-06-07 15:29:01.014timeLong:1686122941014   学习更多编程常识,请关注我的公众号: 代码的路   

June 14, 2023 · 1 min · jiezi

关于java:项目终于上了这个数据单位转换工具类金额转换太优雅了

起源:blog.csdn.net/qq_35387940/article/details/129167329 前言平时做一些统计数据,常常从数据库或者是从接口获取进去的数据,单位是跟业务需要不统一的。 比方, 咱们拿进去的 分, 实际上要是元又比方,咱们拿到的数据须要 乘以100 返回给前端做 百分比展现又比方, 千分比转换又比方,拿进去的金额须要变成 万为单位又比方,须要保留2位小数......等等等等平时咱们怎么搞? 很多时候拿到的是一个数据汇合list,就须要去遍历而后依据每个DTO的属性去做相干单位转换。 始终get 完 set ,get 完 set ,get 完 set ,get 完 set ,get 完 set ,人都麻了。 就像这样: 所以,如果通过反射主动匹配进去一些操作转换,是不是就看代码看起来难受一点,人也轻松一点。 举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice答案:是的 而后,我就搞了。 注释 本篇内容简要: 初步的封装,通过map去标记须要转换的 类属性字段进一步的封装, 配合老朋友自定义注解搞事件产品: 领取总金额 换成万 为单位, 不便经营统计 ;那个什么计数,要是百分比的 ;而后还有一个是千分比;另外,还有2个要保留2位小数;还有啊,那个。。。。。。我: 别说了,喝口水吧。 拿到的数据都在这个DTO外面 : 开始封装: ① 初步的封装,通过map去标记须要转换的 类属性字段 思路玩法: 通过反射拿出字段配合传入的转换标记Map 匹配哪些字段须要操作而后从map取出相干字段的具体操作是什么,而后执行转换操作从新赋值① 简略弄个枚举,列出当初需要上的转换操作类型 UnitConvertType.java /** * @Author : JCccc * @CreateTime : 2023/01/14 * @Description : **/public enum UnitConvertType { /** * 精度 */ R, /** * 万元 */ B, /** * 百分 */ PERCENTAGE, /** * 千分 */ PERMIL}② 外围封装的转换函数 ...

June 14, 2023 · 3 min · jiezi

关于java:真刑几行代码端了整个教务系统

作者:lyc \起源:https://www.freebuf.com/vuls/358037.html 明天给大家伙分享一个网络安全的案例,程序员和网安同学都能够看看, 前言:本文中波及到的相干破绽已报送厂商并失去修复,本文仅限技术钻研与探讨,严禁用于非法用处,否则产生的所有结果自行承当破绽成因事件的起因是这样的,在某一天我用谷歌做信息收集的时候:inurl:xxx.edu.cn pdf,忽然查找到这样一份pdf文件,看残缺集体都笑出了花,有位同学转业余,被学校调剂错了,而后被公示进去,学号和sfz都泄露了。 接着我就善意的找了一下他们学校的对立登陆的中央,发现初始登陆的明码是sfz的后六位。 间接登陆胜利了,真是我的好兄弟啊。 举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice破绽发现进入之后发现,只有日常事务这一个模块能登陆进去,先进去看看的。 进入之后测了很多中央,sql注入,文件上传之类的破绽是通通没有啊,还有很多利用竟然没有权限,然而她揭示我没有权限这一点,让我想到,会不会有未受权,然而抓包测试半天都没有胜利。 然而好在天无绝人之路,我忽然看到一个性能点,反馈这个性能点。 输出了一些内容之后,抓取数据包看了一下。 POST /api/apps/feedback HTTP/1.1Host: xxx.xxx.xxx:80Content-Length: 79Accept: application/json, text/plain, */*X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.41Content-Type: application/json;charset=UTF-8Origin: http://xxx.xxx.xxx:80Referer: http://xxx.xxx.xxx:80/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,ko;q=0.5,zh-TW;q=0.4Cookie: sid=7e670c0c-9529-4a1b-87b6-6c6aec4edbc1Connection: close{"jybh":"d997E5ee-17B6-6C9A-13c1-83EAFE09F831","bt":"1","yddh":"11","jynr":"1"}是这样一个数据包,也没有注入点之类的,感觉没啥货色啊,想着就把/api/apps/feedback这个间接拼接到url上看看,因为看到api就会让人想到信息泄露之类的。拼接下来之后,通知我短少pageNum这个参数,我把这个参数拼接下来。 后果又通知我短少pageSize这个参数。 全副拼接下来之后发现,是一条学生的信息。 扭转这个pageNum和pageSize前面数字的大小能够看到更多信息,然而只有几个学生有反馈问题,失去的信息泄露少之又少,就只有这么一点点,够谁吃啊,再来一罐,一人一罐(刘德华bushi)。 破绽深挖尽管说挖到这样一个破绽,然而毫无作用啊,感觉到有些挫败的时候,忽然想到,这个信息泄露必定是整个零碎的问题,找一个学生信息多的中央,拼接url,看看能不能泄露的更多。 间接找到个人信息这一块,编辑而后抓包看一下。 察看一下我抓到的这个数据包,首先我想到下面拼接语句的时候,是间接url发送数据的,所以申请办法应该是GET,并且我之前申请的时候是没有body这个局部的,所以body也要删除,而后拼接上pageNum和pageSize这两个参数。 Content-Length: 748Accept: application/json, text/plain, */*X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.41Content-Type: application/json;charset=UTF-8Origin: http://xxx.xxx.xxx:80Referer: http://xxx.xxx.xxx:80/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,ko;q=0.5,zh-TW;q=0.4Cookie: sid=7e670c0c-9529-4a1b-87b6-6c6aec4edbc1Connection: close{"yhbh":"xxxxxxxxxxxx","xm":"xxx","nc":"1","zt":"0","pxh":0,"yddh":"189xxxxxxx","dzyx":"xxxxxxxxxxxx","qq":null,"wechatUnion":null,"wechatOpenid":null,"salt":"test","xbm":"1","yhlx":"0","tx":"xxxxxxxxxxxx_avatar","pf":"defaultSkin","bmmc":"19xx1","bmbh":"xxxxxxxxxxxx","jzbmbh":[],"yhjs":["XS"],"positionIds":null,"userLog":{"bh":"7d83f326-7cee-4ad4-b242-17faef9fdc90","yhbh":"xxxxxxxxxxxx","dlsj":"2023-02-12 23:12:40","tcsj":"2023-02-13 11:22:25","khdczxt":"Windows","khdllq":"Chrome-110.0.0.0","khdipdz":"117.92.247.178","khdlx":"PC"},"gwbh":[],"gwmc":[],"sfzjh":null,"personalSkin":null,"personalSkinThum":null,"value":null,"id":"xxxxxxxxxxxx","nickname":"1","phone":"18xxxxxx","email":"20xxxxxxxxxxxx4@xxx.edu.cn"}然而我批改后发现申请失败了,通知我没有权限。 ...

June 13, 2023 · 1 min · jiezi

关于java:理解Java-ThreadLocal

原文链接 了解Java ThreadLocalThreadLocal是Java提供的为每个线程存储线程独立的数据的存储形式,也就是说用ThreadLocal来保留的数据,只能被以后线程所拜访,其余线程无法访问,因为只有(一个线程)以后线程可能拜访,所以它是线程平安的,能够用来存储一些不能被共享的数据。 根本应用办法ThreadLocal应用起来十分的简略,它反对泛型,能够把任意类型的数据放进ThreadLocal,一个ThreadLocal对象只能放一个对象: ThreadLocal<String> mLocalCEOHolder = new ThreadLocal<>();ThreadLocal<Integer> mOrdersCountHolder = new ThreadLocal<>();mLocalCEOHolder.set("Alex Hilton");String ceo = mLocalCEOHolder.get();mOrdersCountHolder.set(30249);int order = mOrdersCountHolder.get();实现原理解析就按下面的例子来解析它的实现原理: 创立ThreadLocal对象 先来看看它的构造方法: /** * Creates a thread local variable. * @see #withInitial(java.util.function.Supplier) */public ThreadLocal() {}很可怜,它的构造方法是空的,啥也没干。 set办法再来看下它的set办法:/** * Sets the current thread's copy of this thread-local variable * to the specified value. Most subclasses will have no need to * override this method, relying solely on the {@link #initialValue} * method to set the values of thread-locals. * * @param value the value to be stored in the current thread's copy of * this thread-local. */public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value);}这里先获取以后的调用线程,从其中获取一个叫做ThreadLocalMap的货色,如果它不为空就把以后对象this(ThreadLocal对象)作为key,把要寄存的值作为value,放到这个ThreadLocalMap外面,如果map为空就先创立再寄存。由此能够猜出ThreadLocalMap是一个Map型的数据结构,接着钻研getMap和createMap,前面再具体说ThreadLocalMap。 ...

June 12, 2023 · 3 min · jiezi

关于java:Java获取本机IP

原文链接 能够应用getLocalHost命令: import java.net.InetAddress;public class Main { public static void main(String[] args) throws Exception { InetAddress addr = InetAddress.getLocalHost(); System.out.println("Local HostAddress:" + addr.getHostAddress()); System.out.println("Local host name:" + addr.getHostName()); }}即可输入本机的IP和name。    学习更多编程常识,请关注我的公众号: 代码的路   

June 12, 2023 · 1 min · jiezi

关于java:告警线上慎用-BigDecimal

起源:cnblogs.com/zhangyinhua/p/11545305.html 一、BigDecimal概述Java在java.math包中提供的API类BigDecimal,用来对超过16位无效位的数进行准确的运算。双精度浮点型变量double能够解决16位无效数,但在理论利用中,可能须要对更大或者更小的数进行运算和解决。 个别状况下,对于那些不须要精确计算精度的数字,咱们能够间接应用Float和Double解决,然而Double.valueOf(String) 和Float.valueOf(String)会失落精度。所以开发中,如果咱们须要准确计算的后果,则必须应用BigDecimal类来操作。 BigDecimal所创立的是对象,故咱们不能应用传统的+、-、*、/等算术运算符间接对其对象进行数学运算,而必须调用其绝对应的办法。办法中的参数也必须是BigDecimal的对象。结构器是类的非凡办法,专门用来创建对象,特地是带有参数的对象。 二、BigDecimal罕用构造函数2.1、罕用构造函数BigDecimal(int)创立一个具备参数所指定整数值的对象 BigDecimal(double)创立一个具备参数所指定双精度值的对象 BigDecimal(long)创立一个具备参数所指定长整数值的对象 BigDecimal(String)创立一个具备参数所指定以字符串示意的数值的对象 2.2、应用问题剖析应用示例: BigDecimal a =new BigDecimal(0.1);System.out.println("a values is:"+a);System.out.println("=====================");BigDecimal b =new BigDecimal("0.1");System.out.println("b values is:"+b);后果示例: a values is:0.1000000000000000055511151231257827021181583404541015625=====================b values is:0.1起因剖析: 1)参数类型为double的构造方法的后果有肯定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创立的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),然而它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无奈精确地示意为 double(或者说对于该状况,不能示意为任何无限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(尽管外表上等于该值)。 2)String 构造方法是齐全可预知的:写入 newBigDecimal(“0.1”) 将创立一个 BigDecimal,它正好等于预期的 0.1。因而,比较而言, 通常倡议优先应用String构造方法。 3)当double必须用作BigDecimal的源时,请留神,此构造方法提供了一个精确转换;它不提供与以下操作雷同的后果:先应用Double.toString(double)办法,而后应用BigDecimal(String)构造方法,将double转换为String。要获取该后果,请应用static valueOf(double)办法。 三、BigDecimal罕用办法详解3.1、罕用办法add(BigDecimal)BigDecimal对象中的值相加,返回BigDecimal对象 subtract(BigDecimal)BigDecimal对象中的值相减,返回BigDecimal对象 multiply(BigDecimal)BigDecimal对象中的值相乘,返回BigDecimal对象 divide(BigDecimal)BigDecimal对象中的值相除,返回BigDecimal对象 toString()将BigDecimal对象中的值转换成字符串 doubleValue()将BigDecimal对象中的值转换成双精度数 floatValue()将BigDecimal对象中的值转换成单精度数 longValue()将BigDecimal对象中的值转换成长整数 intValue()将BigDecimal对象中的值转换成整数 3.2、BigDecimal大小比拟java中对BigDecimal比拟大小个别用的是bigdemical的compareTo办法 int a = bigdemical.compareTo(bigdemical2)返回后果剖析: a = -1,示意bigdemical小于bigdemical2;a = 0,示意bigdemical等于bigdemical2;a = 1,示意bigdemical大于bigdemical2;举例:a大于等于b new bigdemica(a).compareTo(new bigdemical(b)) >= 0四、BigDecimal格式化因为NumberFormat类的format()办法能够应用BigDecimal对象作为其参数,能够利用BigDecimal对超出16位有效数字的货币值,百分值,以及个别数值进行格式化管制。 以利用BigDecimal对货币和百分比格式化为例。首先,创立BigDecimal对象,进行BigDecimal的算术运算后,别离建设对货币和百分比格式化的援用,最初利用BigDecimal对象作为format()办法的参数,输入其格式化的货币值和百分比。 举荐一个开源收费的 Spring Boot 实战我的项目: ...

June 12, 2023 · 6 min · jiezi

关于java:Java代码性能测试实战之ContiPerf

一、前言最近测试一个开源我的项目,发现生成的 全局id 有反复,办法加上 synchronized 提交PR后,有些同行对性能有疑虑,就筹备做个 代码性能测试Java基准性能测试 个别用 JMH 比拟多,然而 官网倡议 性能测试独自一个我的项目,感觉麻烦了点前面发现了 ContiPerf,能够不便的设置 执行次数、时长、线程数、预热时长,还有 Html格局报告,感觉还比拟适宜,基于 Junit二、ContiPerf1. 装置有2个仓库,这里抉择 javatlacati 二开当前的抉择 2.4.3 版本,基于 Junit4,更好的反对 @After另最新 2.4.4-SNAPSHOT 版本,基于Junit5 <dependencies> <!-- 引入 ContiPerf 测试工具,参考 https://gitee.com/yu120/sequence --> <dependency> <groupId>com.github.javatlacati</groupId> <artifactId>contiperf</artifactId> <version>2.4.3</version> <scope>test</scope> </dependency> </dependencies>2. 应用首先,单元测试类 减少属性 ContiPerfRule测试方法减少 Junit4 的 @Test 注解减少 @PerfTest,配置 invocations 次数,或 duration 毫秒时长,threads 线程数性能测试嘛,最好配置 预热时长 warmUp,单位也是 毫秒多种不同线程数的测试,能够 多个办法加 @PerfTest 注解哦(这种状况倡议把 线程数加到 测试方法名开端,线程数小于 10的 补0,同时测试类减少 @FixMethodOrder(MethodSorters.NAME_ASCENDING),生成的 报告就按 线程数排序了)还能够配置 @Required 后果校验哦,如下示例:每秒吞吐量要 大于等于 100万 ...

June 12, 2023 · 1 min · jiezi

关于java:一篇文章带你入门HBase

本文已收录至Github,举荐浏览 Java随想录微信公众号:Java随想录 HBase(Hadoop Database)是一个开源的、分布式的、面向列的NoSQL数据库,它是构建在Hadoop之上的。HBase旨在提供牢靠的、高性能的、可扩大的存储和拜访大规模数据集的能力。 HBase个性以下是HBase的一些要害个性和概念: 分布式架构:HBase是一个分布式数据库,它能够在一个集群中运行在多个机器上。数据以程度分片的形式散布在不同的机器上,这样能够实现数据的高可用性和横向扩展性。列存储:HBase是面向列的数据库,它将数据存储在表中的列族中。每个列族能够蕴含多个列,这样能够不便地存储和检索具备不同构造的数据。HBase的列存储个性使得能够高效地读取和写入大量数据。强一致性:HBase提供强一致性的读写操作。当数据被写入或读取时,HBase会确保所有相干的正本都是最新的。这使得HBase非常适合须要强一致性的利用场景,如金融、电信等畛域。高可扩展性:HBase能够轻松地扩大到大规模的数据集和集群。通过增加更多的机器和分片数据,能够线性地扩大存储容量和吞吐量。疾速读写:HBase是为了高性能而设计的。它应用了内存和硬盘的组合来存储数据,能够实现疾速的读写操作。此外,HBase还反对批量写入和异步写入,进一步提高了写入性能。灵便的数据模型:HBase提供了灵便的数据模型,能够依据应用程序的需要设计表构造。它反对动静增加列,并且能够高效地执行范畴查问和单行读写操作。数据一致性:HBase通过应用ZooKeeper来治理集群的元数据和协调分布式操作,确保数据的一致性和可用性。集成Hadoop生态系统:HBase与Hadoop生态系统严密集成,能够与Hadoop分布式文件系统(HDFS)和Hadoop的计算框架(如MapReduce)无缝配合应用。这使得HBase可能解决大规模的数据存储和剖析工作。Hadoop的限度只管Hadoop是一个弱小的分布式计算框架,但它也存在一些不足之处,与HBase相比,以下是一些Hadoop的限度: 实时性:Hadoop次要用于批处理工作,对于实时性要求较高的利用场景,如实时数据分析和流式解决,Hadoop的提早可能会比拟高。Hadoop的MapReduce模型通常不适宜解决须要即时响应的数据处理工作。存储效率:Hadoop在存储效率方面存在一些问题。为了提供容错性和可靠性,Hadoop将数据复制屡次存储在不同的节点上,这会导致存储开销减少。绝对于HBase的列存储模型,Hadoop的存储效率可能较低。复杂性:Hadoop的配置和治理绝对简单,须要专业知识和教训。搭建和保护一个Hadoop集群须要解决许多参数和组件,对于初学者来说可能存在肯定的学习曲线。扩展性限度:尽管Hadoop具备良好的可扩展性,能够通过增加更多的节点来扩大集群的存储和计算能力,但在某些状况下,随着集群规模的减少,治理和调度节点可能变得更加艰难。解决简单查问的限度:Hadoop的次要计算模型是MapReduce,它适宜解决简略的计算工作,但对于简单的查问和数据分析,如简单聚合、连贯和实时查问等,Hadoop的性能可能不如专门设计的剖析数据库。基本概念NameSpace命名空间,相似于关系型数据库的Database概念,每个命名空间下有多个表。 HBase自带两个命名空间,别离是hbase和default,hbase 中寄存的是HBase内置的表,default表是用户默认应用的命名空间,这2个命名空间默认是不展现的。 Table相似于关系型数据库的表概念。不同的是,HBase定义表时只须要申明列族即可,不须要申明具体的列。因为数据存储时稠密的,空(null)列不占用存储空间,所有往HBase写入数据时,字段能够动静、按需指定。因而,和关系型数据库相比,HBase 可能轻松应答字段变更的场景。 RowKeyHBase表中的每行数据都由一个RowKey和多个Column(列)组成,数据是依照RowKey的字典顺序存储的,并且查问数据时只能依据RowKey进行检索,所以RowKey的设计非常重要。 ColumnHBase中的每个列都由Colunn Family (列族)和Column Qualifier (列限定符)进行限定,例如info: name, info: age。 建表时,只需指明列族,而列限定符无需事后定义。 TimeStamp用于标识数据的不同版本(version),每条数据写入时,零碎会主动为其加上该字段,其值为写入HBase的工夫。 Cell由{rowkey, column Family:column Qualifier, timestamp} 惟一确定的单元,Cell 中的数据全副是字节码模式存贮。 一条数据有多个版本,每个版本都是一个Cell。 存储构造HBase存储构造如下: 下面的这种数据会存储为上面这样,底层存储为Byte: 行分为Region,列分为Store,Region能够放在其余机器上。 HBase是基于HDFS的,而HDFS是不可能批改数据的,所以HBase其实也是不能批改数据的。HBase应用工夫戳实现批改性能。取数据的时候取最新工夫戳的数据,取出来的就是最新的数据。 HBase 数据拜访模式HBase数据拜访能够通过以下几种模式进行: 单行读写(Get和Put):应用HBase提供的API,能够通过指定行键(Row Key)来读取和写入单行数据。Get操作能够依据行键从表中获取特定行的数据,而Put操作能够将数据写入表的指定行。批量读写(Scan和Batch Put):HBase反对批量读写操作,能够一次性读取或写入多行数据。Scan操作能够依照肯定的条件扫描表中的多行数据,而Batch Put操作能够一次性写入多行数据。全表扫描(Scan):通过Scan操作,能够遍历整个表的数据,依照指定的条件进行过滤和筛选。能够设置起始行键和完结行键,还能够应用过滤器(Filter)进行更准确的数据查问。列族范畴扫描(Scan):HBase中的数据以列族(Column Family)为单位进行存储,能够通过Scan操作对指定列族的数据进行范畴扫描。这种形式能够进步数据查问的效率,只获取所需列族的数据,而不用读取整个表的数据。过滤器(Filter):HBase反对多种过滤器来进行数据的准确查问和过滤。能够应用行键过滤器(Row Filter)依照行键的条件进行数据过滤,还能够应用列族过滤器(Family Filter)、列限定符过滤器(Qualifier Filter)和值过滤器(Value Filter)等进行更细粒度的数据过滤。原子性操作(Check-and-Put和Check-and-Delete):HBase反对原子性操作,例如Check-and-Put和Check-and-Delete。这些操作容许在写入数据之前进行查看,只有在满足指定条件的状况下才执行写入操作。以上模式提供了不同的数据拜访形式,能够依据具体的需要和查问条件抉择适宜的形式来拜访和操作HBase中的数据。 架构体系HBase的架构体系是基于分布式存储和解决的设计。它蕴含了以下几个重要的组成部分: HMaster:HMaster是HBase集群的主节点,负责管理整个集群的元数据和协调各个RegionServer的工作。它保护了表的构造信息、分片规定、RegionServer的负载平衡等,并协调分布式操作,如Region的决裂和合并。RegionServer:RegionServer是HBase集群中的工作节点,负责存储和解决数据。每个RegionServer治理多个Region,每个Region负责存储表中的一部分数据。RegionServer解决客户端的读写申请,负责数据的存储、读取和写入操作。ZooKeeper:ZooKeeper是一个分布式协调服务,被HBase用于治理集群的元数据和协调分布式操作。HBase应用ZooKeeper来进行主节点的选举、故障检测、集群配置的同步等工作。HDFS(Hadoop Distributed File System):HBase应用HDFS作为底层的分布式文件系统,用于存储数据。HDFS将数据宰割成块并散布在不同的节点上,提供高可靠性和可扩展性的存储。HBase客户端:HBase客户端是与HBase交互的应用程序或工具,用于发送读写申请和接管查问后果。客户端能够通过HBase的Java API或者命令行工具(如HBase shell)来拜访和操作HBase表。表和列族:HBase数据模型是基于表的,表由一个或多个列族(Column Family)组成。每个列族能够蕴含多个列(Column),列存储着理论的数据。表被宰割成多个Region存储在不同的RegionServer上,每个Region负责存储一部分行数据。这些组成部分独特形成了HBase的架构体系,实现了分布式存储和解决大规模数据集的能力。HMaster负责管理元数据和协调工作,RegionServer存储和解决数据,ZooKeeper提供分布式协调服务,HDFS提供底层的分布式文件存储,而HBase客户端用于与HBase进行交互。表和列族的概念提供了数据的组织和存储形式。 HBase组件MemStore:每个RegionServer都有一个MemStore,它是位于内存中的长期数据存储区域。当客户端写入数据时,数据首先被写入到MemStore中,以提供疾速的写入性能。WAL(Write-Ahead-Log):WAL是HBase的日志文件,用于记录所有的写操作。当数据被写入到MemStore时,相应的写操作也会被写入WAL中,以保证数据的持久性和故障恢复能力。StoreFile:当MemStore中的数据达到肯定大小阈值后,会被刷新到磁盘上的StoreFile中。StoreFile是HBase中理论长久化存储数据的文件模式,它蕴含了曾经写入的数据和相应的索引。HFile:HFile是StoreFile的底层存储格局,采纳了块索引和工夫范畴索引的形式,提供了高效的数据查找和扫描能力。HFile应用块(Block)来组织数据,并采纳压缩和编码技术来减小存储空间。MemStore提供了长期的内存存储,StoreFile提供了长久化的磁盘存储,WAL用于保证数据的持久性。这种架构设计使得HBase可能提供高可用性、高性能和可扩展性的分布式存储和解决能力。 HBase读写流程读流程客户端发送读取申请:客户端向HBase集群发送读取申请,包含所需的表名、行键(Row Key)以及其余可选的参数(如列族、列限定符等)。定位RegionServer和Region:HBase的客户端会与ZooKeeper进行通信,获取到存储有所需数据的Region所在的RegionServer的信息。RegionServer解决申请:客户端发送的读取申请达到对应的RegionServer,RegionServer会依据申请的行键定位到蕴含所需数据的Region。数据读取:RegionServer首先会从MemStore中查找数据,如果数据在MemStore中找到,则间接返回给客户端。如果数据不在MemStore中,RegionServer会在磁盘上的StoreFile中进行查找,依据索引定位到所需的数据块,并将数据块读取到内存中进行解决。数据返回给客户端:RegionServer将读取到的数据返回给客户端,客户端能够依据须要对数据进行进一步的解决和剖析。写流程客户端发送写入申请:客户端向HBase集群发送写入申请,包含表名、行键、列族、列限定符和对应的值等信息。定位RegionServer和Region:客户端与ZooKeeper通信,获取存储指标数据的Region所在的RegionServer的信息。RegionServer解决申请:客户端发送的写入申请达到对应的RegionServer,RegionServer依据行键定位到指标Region。写入到MemStore:RegionServer将写入申请中的数据写入到指标Region对应的内存中的MemStore。写入到MemStore是一个追加操作,将数据追加到内存中的MemStore中,并不间接写入磁盘。WAL日志记录:同时,RegionServer将写入申请中的操作写入WAL(Write-Ahead-Log)日志文件,确保数据的持久性和故障恢复能力。MemStore刷新到磁盘:当MemStore中的数据达到肯定的大小阈值时,RegionServer会将MemStore中的数据刷新到磁盘上的StoreFile中。刷新过程将内存中的数据写入到磁盘上的StoreFile,并生成相应的索引。数据返回给客户端:写入实现后,RegionServer向客户端发送写入胜利的响应,示意数据已胜利写入。MemStore Flush 在HBase中,MemStore Flush是将内存中的数据刷新到磁盘上的StoreFile的过程。当MemStore中的数据达到肯定大小阈值时,或者达到了肯定的工夫限度,HBase会触发MemStore Flush操作,以将数据长久化到磁盘,确保数据的持久性和可靠性。 上面是MemStore Flush的根本过程: MemStore Flush触发:当MemStore中的数据量达到肯定的阈值(由配置参数管制)或者达到了肯定的工夫限度时,HBase会触发MemStore Flush操作。这个阈值和工夫限度能够依据需要进行配置,以均衡写入性能和数据持久性的要求。写入内存快照:在触发Flush操作时,HBase会先将MemStore中的数据做一个内存快照(Snapshot),以保障在Flush期间持续接管新的写入申请。刷写到磁盘:内存快照实现后,HBase会将内存中的数据依照列族的维度划分为多个KeyValue,而后将这些KeyValue写入磁盘上的StoreFile。StoreFile采纳HFile格局,用于长久化存储数据。更新Region元数据:实现刷写到磁盘后,HBase会更新Region的元数据,包含最新的StoreFile列表和相应的工夫戳等信息。MemStore清空:一旦数据刷写到磁盘上的StoreFile,HBase会清空相应的MemStore,以开释内存空间用于接管新的写入申请。通过MemStore Flush操作,HBase能够将内存中的数据长久化到磁盘,以确保数据的持久性和可靠性。Flush操作的频率和老本能够通过配置参数进行调整,以适应不同的利用场景和性能需求。频繁的Flush操作可能会影响写入性能,而较长的Flush距离可能会减少数据失落的危险。因而,依据理论状况,须要正当设置Flush操作的参数,以均衡数据的持久性和写入性能的要求。 ...

June 12, 2023 · 6 min · jiezi

关于java:Jenkins-Docker-一键自动化部署-Spring-Boot-项目步骤齐全少走坑路

本文章实现最简略全面的Jenkins+docker+springboot 一键主动部署我的项目,步骤齐全,少走坑路。 环境:centos7+git(gitee) 简述实现步骤:在docker装置jenkins,配置jenkins根本信息,利用Dockerfile和shell脚本实现我的项目主动拉取打包并运行。 举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice装置dockerdocker 装置社区版本CE 确保 yum 包更新到最新。yum update卸载旧版本(如果装置过旧版本的话)yum remove docker docker-common docker-selinux docker-engine装置须要的软件包yum install -y yum-utils device-mapper-persistent-data lvm2设置yum源yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo装置dockeryum install docker-ce #因为repo中默认只开启stable仓库,故这里装置的是最新稳定版17.12.0yum install <本人的版本> # 例如:sudo yum install docker-ce-17.12.0.ce启动和开机启动systemctl start dockersystemctl enable docker验证装置是否胜利docker version装置JenkinsJenkins中武官网:https://www.jenkins.io/zh/ 装置Jenkinsdocker 装置一切都是那么简略,留神查看8080是否曾经占用!如果占用批改端口 docker run --name jenkins -u root --rm -d -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock jenkinsci/blueocean如果没改端口号的话 装置实现后拜访地址-> http://{部署Jenkins所在服务IP}:8080 此处会有几分钟的等待时间。 初始化 Jenkins详情见官网教程->https://www.jenkins.io 解锁 Jenkins进入Jenkins容器:docker exec -it {Jenkins容器名} bash ...

June 12, 2023 · 1 min · jiezi

关于java:图灵Java架构班第六期无密飞湍瀑流争喧豗

download:图灵Java架构班第六期无密飞湍瀑流争喧豗音视频WebRTC实时互动:古代通信的将来WebRTC(Web Real-Time Communications)是一个基于Web浏览器的凋谢规范,它能够在不须要下载插件的状况下间接进行音频和视频通信。与传统的视频会议零碎和电话零碎不同,WebRTC可用于实现各种实时互动场景,如在线教育、近程医疗和视频游戏等。以下是无关音视频WebRTC实时互动的详细信息: WebRTC架构WebRTC采纳了一种点对点(P2P)架构,以便用户之间可能更快地建设间接连贯,并且不用通过服务器进行直达。该架构基于STUN(Session Traversal Utilities for NATs)和TURN(Traversal Using Relays around NATs)协定来解决网络地址转换(NAT)问题,并利用SRTP(Secure Real-time Transport Protocol)等协定来爱护通信数据的安全性。WebRTC实时通信利用场景WebRTC可用于多种实时通信应用程序,包含:在线教育:WebRTC能够用于在线学习和培训,例如Webinar和虚构课堂。近程医疗:WebRTC使医生和患者能够通过视频会话进行近程医疗,实现近程诊断和医治。视频游戏:WebRTC可用于实现在线多人游戏,使玩家可能实时互动和合作。社交媒体:WebRTC能够用于实时社交媒体应用程序,例如视频聊天和直播。 WebRTC的劣势相比传统的音视频通信技术,WebRTC具备许多劣势:更快的连贯速度:因为WebRTC应用P2P架构,因而用户之间的连贯速度更快,会议等待时间更短。更低的老本:WebRTC不须要下载、装置或保护任何插件或软件,这升高了老本并缩小了网络提早。更高的兼容性:WebRTC能够在所有古代浏览器中运行,并且能够在各种设施上进行音视频通信,例如桌面电脑、智能手机和平板电脑等。更好的安全性:WebRTC采纳最新的加密技术来爱护通信数据,使其更难被攻击者窃取或篡改。论断WebRTC是一种革命性的技术,将音视频通信带入了一个新的时代。它为用户提供了更疾速、更便捷和更平安的实时互动体验,并在教育、医疗、社交媒体和游戏等畛域提供了微小的发展潜力。咱们能够期待,在将来WebRTC将变得更加遍及,成为古代通信的次要形式之一。

June 11, 2023 · 1 min · jiezi

关于java:Java-POI-读取excel文件单元格数字带小数解决方案

在 Java 集成 POI 读取 Excel文件时,会发现单元格中写的数字读出来后莫名微妙的加上了小数点,甚至变成迷信计数法。 设置Excel单元格格局为“文本”后仍然如此… 其实可通过编码解决这种问题。 咱们能够应用 DataFormatter 获取单元格字符值。它能够失去一个格式化的字符串,代表了存储在单元格中的值。比方一个单元格的数值为1.234,然而该单元格的格局规定为保留小数点后两位,咱们获取到的值将为“1.23”。更多内容参考 javacorn.com。 查看更多:http://www.javacorn.com/java/poi/springboot-poi.html

June 9, 2023 · 1 min · jiezi

关于java:idea远程链接k8s-debug

首先在容器启动时减少一个环境变量 env:- name: JAVA_TOOL_OPTIONS value: >- -agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=y而后将服务端口转发裸露进去,如deployment名称是user-service kubectl port-forward deployment/user-service 5005:5005 -n=dev --address=0.0.0.0最初在idea 增加近程JVM调试的启动项 host填写上k8s服务器地址,端口填写5005 点击确定利用即可 而后在启动项抉择方才的近程jvm调试启动 能够欢快的debug了

June 9, 2023 · 1 min · jiezi

关于java:Redis和它的键们2List

ListRedis和它的键们(2)—List2.1 数据结构在介绍列表键之前,咱们先引入Redis对两个经典表构造的实现,Redis诞生之初,理论是有两种表类型的数据结构,一个是双向链表,一个是压缩列表。在咱们经典的程序数据结构中对应着不同的两个类型,别离是链表和数组,他们二者二者善于插入和利用间断的空间以节俭占地。 相比一般的List的而言,Redis的List除了反对随机拜访,还具备更多队列的个性,比方它反对左右POP元素(PUSH),它将会引出咱们关怀的对于Redis的一个重要的新构造 一个列表最多存储Integer.MAX_VALUE个元素(没错,这是Java里的表白,最大的那个32位无符号整数)以下条件必须全副满足,List才会以双向链表的模式存在 每个元素都小于64byte元素数目不大于512个如果不满足,List会转化为压缩链表2.2 压缩列表双向链表并没有什么特地的,它是和咱们学习过的双向链表没什么不同 然而压缩链表和咱们所意识的间断空间数组不太一样,它的特别之处就是它每个元素都是独自编码的,这样的设计能够极大的帮忙它节俭内存 zlbytes:整个表占用的字节数ztail:记录压缩列表「尾部」节点间隔起始地址由多少字节,也就是列表尾的偏移量zllen:记录压缩列表蕴含的节点数量zlend:标记链表完结的符号,固定为0xFF上图咱们还能够看见它其中每个元素的构造,它能够为元素独自编码,这样准确到每个元素的编码是十分节约内存的,比如说,表白65535须要16个bit,然而表白15仅仅须要4个bit(1110)(当然,Redis并非用的是如此简略的形式,咱们接下来能够专门开一期Redis的各种编码方式),这样紧凑的构造显然是通过精心设计的接下来咱们来解读一下其次要构造 prevLen存储着前一个节点的字节长度,这样它就能够实现从后往前的查找 当prevLen≤255时,prevLen局部须要占用1字节当prevLen>255时,prevLen局部须要占用2字节encoding示意data局部的编码方式和长度data是数据的本体 下面介绍的是压缩链表的编码方式(图源Redis设计与源码) 如果是整数,就会采纳上图所示的1个byte进行编码,如果是字符串类型,见下表 [redis设计与实现的解释] 看完下面的介绍,咱们能够很清晰的发现: 压缩列表的实现重视于空间的节约压缩链表的查问效率比拟低下当然,咱们无奈间接调用压缩列表,其作为list的一种实现,list所提供的接口都是很合乎压缩列表个性的,然而仍有一点须要咱们留神,那就是前文提到的prevLen长度,这个长度会因为其余节点的长度扭转而扭转本身的长度,置信你曾经发现,压缩列表具备一种叫做连锁更新的隐患,这甚至涉及到了redis单线程的命门也是文章探讨的主线,那就是阻塞。 2.3 连锁更新 当一个节点被批改了,导致其长度超过了255字节,那么对应的,其接下来的节点也必须批改以适应此变更,也就是prevLen从1字节变为2字节,如果不巧的是,此entry长度恰好为255字节,批改后,持续引发前面的entry的prevLen产生扭转。如此往返,整个压缩列表的内存空间以O(N²)的复杂度重新分配了一次。 更加蹩脚的是,这些工作都必须由主线程来实现,阻塞主线程的几率就被大大增加了。 不过,从理论状况来思考,这种想法的确是略显杞人忧天了,它必须满足几个刻薄的条件,才会使主线程的阻塞称为一个不可漠视的开销 必须对列表的某个元素做减少其长度的批改,并且这个批改必须使其长度从255以下到255以上被批改的节点的后继节点的长度必须全副为255byte由255byte的节点形成的后继节点串必须足够长很显然,除非精心设计,这样的状况并不容易产生,但即便如此,Redis对这种设计缺点还是给出了本人的解决方案 2.4 连锁更新的解决:quicklist和listpack2.4.1 quicklist在Redis3.2中为了解决连锁更新的问题,引入了quicklist 咱们能够发现,它通过增大压缩列表粒度来管制每次连锁更新的规模,这是聪慧的做法,笔者感觉到目前为止,尽管连锁更新的问题并未齐全解决,但其危害曾经到了能够预测的躲避的级别上了。 typedef struct quicklistNode { //前一个quicklistNode struct quicklistNode *prev; //前一个quicklistNode //下一个quicklistNode struct quicklistNode *next; //后一个quicklistNode //quicklistNode指向的压缩列表 unsigned char *zl; //压缩列表的的字节大小 unsigned int sz; //压缩列表的元素个数 unsigned int count : 16; //ziplist中的元素个数 ....} quicklistNode;但redis本身并不满足,并在接下来的版本中用listpack彻底解决了这个问题 2.4.1 listpacklistpack是redis在5.0推出的用来彻底取代压缩列表的构造,其改变也非常简单 次要的改变就是把entry的构造改为了本人的长度,这样在批改元素的时候,其不会影响到别的链表的长度,只须要O(N)的开销便可 prevLen不是用来从后往前遍历吗,这样还怎么找到前一个节点?这也就是listpack把len放在节点尾部的起因:当我须要从后往前遍历时,第一个找到的是len长度,这能够帮我定位到此节点的头部,再通过向前寻位的形式,找到前一个链表的len,如此我便能够读取前驱节点的encoding,进而解读data中的数据了 到此,连锁更新彻底成为了redis历史问题了,咱们也能够发现,redis的设计者对于它的谋求充斥着偏执,正是这种偏执成就了redis的精美居奇 对压缩列表的认识这种构造的优缺点都极为显著,那就是成也压缩,败也压缩,压缩为Redis所运行的宝贵的内存争取到了贵重的施展空间,然而其过于紧凑的设计让每个entry都动弹不得——稍有不慎,你将面临的就是至多O(N)甚至O(N²)的开销,Redis单线程的设计对于这些开销是很敏感的,这也通知咱们,规模微小或者须要频繁更新的构造并不适宜用列表的形式去存储(即使List提供了这些接口),而比拟矛盾的是,在数据规模比拟大的时候List才会从长于删改的双向链表改为压缩列表。 2.5 List的接口List外部经验的设计非常复杂,但其提供的接口非常简单,总结而言,有以下五类 增 ...

June 9, 2023 · 1 min · jiezi

关于java:Testng和Junit5多线程并发测试对比

一、前言最近测试一个开源我的项目,发现生成的 全局id 有反复,也没有单元测试,就筹备奉献个 PR想到多线程并发测试,依据教训,第一想法是用 Testng,前面看了下 Junit5 也有实验性反对了,就比照下(以 maven 为例)spock 不太适宜这种场景二、Testng1. 装置抉择 应用数 比拟多、也比拟新 的版本,7.7.1。<testng.version>7.7.1</testng.version>多模块我的项目,能够在 根pom.xml外面增加依赖,防止每个模块都减少配置哦 <dependencies> <!-- test --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> </dependency> </dependencies>2. 应用@Test 就能够指定 执行次数(invocationCount)、并发(threadPoolSize),很不便同一个测试对象,ids属性 不必加 static public class UniqueIdGeneratorTest { private Set<Long> ids = new ConcurrentHashSet<>(128); @org.testng.annotations.Test(invocationCount = 128, threadPoolSize = 3) public void testGenerateId() { final Long id = UniqueIdGenerator.generateId(); assertTrue(ids.add(id), "id exists," + id); }}3. 成果 三、Junit51. 装置抉择 应用数 比拟多、也比拟新 的版本,5.8.2。<junit-jupiter.version>5.8.2</junit-jupiter.version>最好通过 dependencyManagement 来对立版本,尤其是 多模块我的项目倡议放到 spring-boot-dependencies 后面,优先级更高 ...

June 9, 2023 · 1 min · jiezi

关于java:Spring-Boot-优雅实现多租户架构so-easy~

一、概述1.什么是多租户架构?多租户架构是指在一个利用中反对多个租户(Tenant)同时拜访,每个租户领有独立的资源和数据,并且彼此之间齐全隔离。艰深来说,多租户就是把一个利用依照客户的需要“宰割”成多个独立的实例,每个实例互不烦扰。 2. 多租户架构的劣势更好地满足不同租户的个性化需要。能够升高运维老本,缩小硬件、网络等基础设施的投入。节约开发成本,通过复用代码,疾速上线新的租户实例。加强了零碎的可扩展性和可伸缩性,反对程度扩大,每个租户的数据和资源均可治理和管制。3. 实现多租户架构的技术抉择对于实现多租户架构技术不是最重要的最重要的是正确的架构思路。然而抉择正确的技术能够更快地实现多租户架构。 二、设计思路1. 架构选型基于Java开发多租户利用举荐应用Spring Boot和Spring Cloud。Spring Boot能疾速搭建利用并提供许多成熟的插件。Spring Cloud则提供了许多实现微服务架构的工具和组件。 1.1 Spring Boot应用Spring Boot能够简化我的项目的搭建过程主动配置许多常见的第三方库和组件,缩小了开发人员的工作量。 @RestControllerpublic class TenantController { @GetMapping("/hello") public String hello(@RequestHeader("tenant-id") String tenantId) { return "Hello, " + tenantId; }}1.2 Spring Cloud在架构多租户的零碎时Spring Cloud会更加有用。Spring Cloud提供了一些成熟的解决方案,如Eureka、Zookeeper、Consul等,以实现服务发现、负载平衡等微服务性能。 2. 数据库设计在多租户环境中数据库必须为每个租户别离存储数据并确保数据隔离。咱们通常应用以下两种形式实现: 多个租户共享雷同的数据库,每个表中都蕴含tenant_id这一列,用于辨别不同租户的数据。为每个租户创立独自的数据库,每个数据库内的表构造雷同,但数据互相隔离。3. 利用多租户部署为了实现多租户在利用部署时咱们须要思考以下两个问题。 3.1 利用隔离在多租户环境中不同租户须要拜访不同的资源,因而须要进行利用隔离。能够通过构建独立的容器或虚拟机、应用命名空间等形式实现。Docker就是一种十分风行的隔离容器技术。 3.2 利用配置因为每个租户都有本人的配置需要因而须要为每个租户别离设置利用配置信息,例如端口号、SSL证书等等。这些配置能够存储在数据库中,也能够存储在云配置核心中。 4. 租户治理在多租户零碎中须要可能治理不同租户的数据和资源,同时须要为每个租户调配相应的权限。解决方案通常包含以下两局部。 4.1 租户信息保护租户信息的保护包含增加、批改、删除、查问等操作,要求可能依据租户名称或租户ID疾速查找对应的租户信息。 CREATE TABLE tenant ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL UNIQUE, description VARCHAR(255), created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);4.2 租户权限管制在多租户利用中必须为每个租户别离设置对系统资源的拜访权限。例如,A租户和B租户不能拜访彼此的数据。 ...

June 9, 2023 · 2 min · jiezi

关于java:Spring-FrameWork从入门到NB-Bean-Scopes

Bean Scopes,Spring Bean的作用域,也就是Spring创立的Bean实例的失效范畴。 Spring提供了如下6中不同的作用域: singleton: 单例Bean,每一个Spring IoC容器中只有一个Bean实例,这是Bean的默认作用域。prototype:原型Bean,每申请一次就生成一个新的Bean实例request:仅对 web-aware Spring ApplicationContext失效,每一次HTTP申请生成一个Bean实例。session: 仅对 web-aware Spring ApplicationContext失效,每一个HTTP session对应一个Bean 实例。application: 仅对 web-aware Spring ApplicationContext失效,ServletContext生命周期对应一个Bean实例。websocket:仅对 web-aware Spring ApplicationContext失效,websocket申请对应一个Bean实例。其中有4个是和web-aware Spring ApplicationContext相干的,也就是和web利用相干,最罕用的是singleton和prototype两种。 单例Beansingleton,单例Bean,是Spring默认的Bean作用域,咱们在配置Bean的时候如果没有指定作用域,那么他的作用域就是singleton。 Spring官网的一张图高深莫测的讲清楚了单例Bean的含意: 定义了一个id为accountDao的Bean,被其余3个Bean援用。如图,咱们在定义accountDao的时候没有指定作用域,默认的,他的作用域就是singleton,单例Bean。那么,在整个Spring IoC容器中就只创立一个accountDao的Bean实例,3个援用类援用的其实是同一个accountDao实例。 这种状况系按咱们肯定要留神accountDao的线程平安问题!应用单例Bean的时候你肯定要留神线程平安问题,尽可能的防止在单例Bean中应用属性对象,或者你十分明确的晓得该属性不须要关注线程安全性! 接下来思考一个问题:定义为单例Bena就肯定示意整个Spring IoC容器中只有该类的一个对象吗? 答案显示是No,你当然能够在Spring IoC容器中为某一个类创立多个单例对象。 原型Bean原型Bean指的是Spring IoC容器中会有多个Bena实例,利用没申请一次,Spring IoC容器就会生成一个新的Bean实例返回。如图,accountDao定义为原型Bean,被其余3个Bean援用,不论其余3个Bean是单例还是原型Bean,Spring IoC注入的accountDao都会是3个不同的对象。 原型Bean在申明的时候须要显式指定scope: <bean id="dependencyB" class="springTest.DependencyB" scope="prototype"> </bean>也通过注解形式指定scope: @Component@Scope("prototype")public class DependencyB implements IDependencyB{ @Autowired //@Qualifier(value="dependencyA3") private IDependencyA dependencyA; public static void main(String[] args) { System.out.println("I am a new comer...hello world "); } @Override public void testB(){ System.out.print("This is DependencyB's test and ..."); dependencyA.test(); }启动类加测试代码: ...

June 8, 2023 · 1 min · jiezi

关于java:jdk8小版本差异

1 Java SE 8u202 and older updates are available, under the Binary Code License (“BCL”).从官网上可知,在Oracle JDK的版本历史中,JDK 8u202是最初一个收费的版本,反对收费商业用途 2在JDK 8u131中,JDK减少了一个新的个性,使得Java运行时能够自动检测它是在Docker容器中运行,而后应用特定的零碎调用来取得内核信息。这使得availableProcessors()办法能够返回Docker容器内无效的CPU外围数。3两头还有一些版本 JDK 8u131JDK 8u141JDK 8u144JDK 8u152JDK 8u162JDK 8u172JDK 8u181JDK 8u192JDK 8u202

June 8, 2023 · 1 min · jiezi

关于java:Spring-FrameWork从入门到NB-自动装配

Spring IoC的依赖注入过程,也就是从容器中找到依赖对象、注入到以后对象的过程,叫拆卸。 咱们后面看到的通过xml文件的<constructor-arg>和 <property> 中的 ref设置依赖对象的形式,是手动拆卸,因为每一个依赖对象都须要咱们手动配置、通过ref指定须要拆卸的具体bean,而后Spring依据咱们的指定来实现拆卸。拆卸好的残缺对象最终能力放入Spring IoC容器中供后续应用。 这种形式其实也比较简单实用 ---在类比拟少、依赖关系比较简单的状况下。如果类比拟多、依赖关系比较复杂的话,配置起来就很烦很啰嗦。 为了解决这个问题,Spring提供了主动拆卸性能。主动拆卸的意思就是,Spring依据某种拆卸规定主动实现拆卸,不再须要咱们手工配置了。 主动拆卸可能防止臃肿的配置文件,进步开发效率。 主动拆卸应用起来也十分不便。还是应用咱们后面的例子: <bean id="dependencyB" class="springTest.DependencyB" autowire="byName"> </bean> <bean id="dependencyA" class="springTest.DependencyA"> </bean>不须要为DependencyB设置指向dependencyA的ref,减少autowire=byname的配置,Spring主动就能够实现拆卸。 应用xml的启动类: public class AppByXML { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("mySpring.xml"); System.out.println("Now start to getbean..."); DependencyB dependencyB = applicationContext.getBean(DependencyB.class); dependencyB.testB(); }}执行启动类: here you call set method...Now start to getbean...This is DependencyB's test and ...I am DependencyA test...配置文件中并没有指定ref,Spring能够主动依照规定实现拆卸。 主动拆卸规定Spring提供如下4种主动拆卸规定: no: 不执行主动拆卸。这个时候只能手动拆卸了。byName: 依据属性名实现主动拆卸。Spring依据以后属性的名字,查找容器中id或name等于该名字的Bean进行拆卸。找不到则不拆卸。byType: 依据属性的类型实现拆卸。Spring Ioc容器中该类型的Bean多于一个的话,抛异样。constructor: 相似byType,只不过是用在构造方法参数中,为构造方法的参数进行拆卸。上例中咱们如果把拆卸规定批改为byType: <bean id="dependencyB" class="springTest.DependencyB" autowire="byType"> </bean> <bean id="dependencyA" class="springTest.DependencyA"> </bean>执行启动类: ...

June 7, 2023 · 1 min · jiezi

关于java:接口防刷处理方案太优雅了

起源:juejin.cn/post/7200366809407750181 前言本文为形容通过Interceptor以及Redis实现接口拜访防刷Demo 这里会通过逐渐找问题,逐渐去欠缺的模式展现 原理通过ip地址+uri拼接用以作为访问者拜访接口辨别通过在Interceptor中拦挡申请,从Redis中统计用户拜访接口次数从而达到接口防刷目标如下图所示 工程举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice其中,Interceptor处代码解决逻辑最为重要 /** * @author: Zero * @time: 2023/2/14 * @description: 接口防刷拦挡解决 */@Slf4jpublic class AccessLimintInterceptor implements HandlerInterceptor { @Resource private RedisTemplate<String, Object> redisTemplate; /** * 多长时间内 */ @Value("${interfaceAccess.second}") private Long second = 10L; /** * 拜访次数 */ @Value("${interfaceAccess.time}") private Long time = 3L; /** * 禁用时长--单位/秒 */ @Value("${interfaceAccess.lockTime}") private Long lockTime = 60L; /** * 锁住时的key前缀 */ public static final String LOCK_PREFIX = "LOCK"; /** * 统计次数时的key前缀 */ public static final String COUNT_PREFIX = "COUNT"; public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String uri = request.getRequestURI(); String ip = request.getRemoteAddr(); // 这里疏忽代理软件形式拜访,默认间接拜访,也就是获取失去的就是访问者实在ip地址 String lockKey = LOCK_PREFIX + ip + uri; Object isLock = redisTemplate.opsForValue().get(lockKey); if(Objects.isNull(isLock)){ // 还未被禁用 String countKey = COUNT_PREFIX + ip + uri; Object count = redisTemplate.opsForValue().get(countKey); if(Objects.isNull(count)){ // 首次拜访 log.info("首次拜访"); redisTemplate.opsForValue().set(countKey,1,second, TimeUnit.SECONDS); }else{ // 此用户前一点工夫就拜访过该接口 if((Integer)count < time){ // 放行,拜访次数 + 1 redisTemplate.opsForValue().increment(countKey); }else{ log.info("{}禁用拜访{}",ip, uri); // 禁用 redisTemplate.opsForValue().set(lockKey, 1,lockTime, TimeUnit.SECONDS); // 删除统计 redisTemplate.delete(countKey); throw new CommonException(ResultCode.ACCESS_FREQUENT); } } }else{ // 此用户拜访此接口已被禁用 throw new CommonException(ResultCode.ACCESS_FREQUENT); } return true; }}在多长时间内拜访接口多少次,以及禁用的时长,则是通过与配置文件配合动静设置 ...

June 7, 2023 · 4 min · jiezi

关于java:jvm中类和对象定义存储基础知识-京东云技术团队

1 类文件数据结构类型Class文件构造次要有两种数据结构:无符号数和表 •无符号数:用来表述数字,索引援用、数量值以及字符串等,比方 图1中类型为u1,u2,u4,u8别离代表1个字节,2个字节,4个字节,8个字节的无符号数 •表:表是有由多个无符号数以及其它的表组成的复合构造,比方图1中类型以_info结尾的项为表类型。 2 类构造定义Class类文件是紧凑、程序、无空隙的,魔数(MagicNumber)、Class文件版本(Version)、常量池(Constant\_Pool)、拜访标记(Access\_flag)、本类(This\_class)、父类(Super\_class)、接口(Interfaces)、字段汇合(Fields)、办法汇合(Methods )、属性汇合(Attributes)。其中因为java多继承所以interfaces接口类型为数组;attribute_info则是办法表中定义的code索引,指向具体的办法体字节码。如图1所示。 上面用一段程序做阐明,此类有接口,有办法、类变量和实例变量,机器是如何辨认字节码而后依照下面的规定来定义此class类呢? package com.jd.crm.Logback;public class TestClass implements Super{ private static final int staticVar = 0; private int instanceVar=0; public int instanceMethod(int param) throws Exception{ return param ++; }}interface Super{ }通过javap帮忙解析class文件格式如下: Classfile /D:/spm-workspace/test/target/classes/com/jd/crm/Logback/TestClass.class Last modified 2023-4-14; size 597 bytes MD5 checksum 9d5dd9fc2145ac17393fee7a707d3b9c Compiled from "TestClass.java"public class com.jd.crm.Logback.TestClass implements com.jd.crm.Logback.Super minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Methodref #4.#26 // java/lang/Object."<init>":()V #2 = Fieldref #3.#27 // com/jd/crm/Logback/TestClass.instanceVar:I #3 = Class #28 // com/jd/crm/Logback/TestClass #4 = Class #29 // java/lang/Object #5 = Class #30 // com/jd/crm/Logback/Super #6 = Utf8 staticVar #7 = Utf8 I #8 = Utf8 ConstantValue #9 = Integer 0 #10 = Utf8 instanceVar #11 = Utf8 <init> #12 = Utf8 ()V #13 = Utf8 Code #14 = Utf8 LineNumberTable #15 = Utf8 LocalVariableTable #16 = Utf8 this #17 = Utf8 Lcom/jd/crm/Logback/TestClass; #18 = Utf8 instanceMethod #19 = Utf8 (I)I #20 = Utf8 param #21 = Utf8 Exceptions #22 = Class #31 // java/lang/Exception #23 = Utf8 MethodParameters #24 = Utf8 SourceFile #25 = Utf8 TestClass.java #26 = NameAndType #11:#12 // "<init>":()V #27 = NameAndType #10:#7 // instanceVar:I #28 = Utf8 com/jd/crm/Logback/TestClass #29 = Utf8 java/lang/Object #30 = Utf8 com/jd/crm/Logback/Super #31 = Utf8 java/lang/Exception{ public com.jd.crm.Logback.TestClass(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: iconst_0 6: putfield #2 // Field instanceVar:I 9: return LineNumberTable: line 3: 0 line 7: 4 LocalVariableTable: Start Length Slot Name Signature 0 10 0 this Lcom/jd/crm/Logback/TestClass; public int instanceMethod(int) throws java.lang.Exception; descriptor: (I)I flags: ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: iinc 1, 1 4: ireturn LineNumberTable: line 10: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/jd/crm/Logback/TestClass; 0 5 1 param I Exceptions: throws java.lang.Exception MethodParameters: Name Flags param}SourceFile: "TestClass.java"以上是javap帮忙咱们生成的class文件解析后果,只是给人看,而非机器。 ...

June 7, 2023 · 3 min · jiezi

关于java:Java-新的生态Solon-v232-发布

Solon 是什么框架?一个,Java 新的生态型利用开发框架。它从零开始构建,有本人的标准规范与凋谢生态(寰球第二级别的生态)。与其余框架相比,它解决了两个重要的痛点:启动慢,费资源。 解决痛点?因为Solon Bean容器的独特设计,不会因为扩大依赖变多而启动很慢(开发调试时,省时、痛快)!以出名开源我的项目“小诺”为例: “snowy-spring 版” 启动 30-50秒“snowy-solon 版” 启动3-5秒(有趣味的,欢送拉取代码体验)所谓:“工夫就是生命,效率就是金钱”,“天下文治,唯快不破”。 绝对于 Spring Boot 和 Spring Cloud 的我的项目,有什么特点?启动快 5 ~ 10 倍。 (更快)qps 高 2~ 3 倍。 (更高)运行时内存节俭 1/3 ~ 1/2。 (更少)打包能够放大到 1/2 ~ 1/10;比方,300Mb 的变成了 23Mb。 (更小)同时反对 jdk8, jdk11, jdk17, jdk20, graalvm native本次更新了什么?新增 solon.data.shardingds 插件新增 redisson-solon-plugin 插件调整 solon.docs 插件,将非 @Body model 进行字段拆解调整 solon-swagger2-knife4j 插件的优先级,以便管制 enableDoc调整 mybatis-solon-plugin 插件,减少 aot 解决适配(反对原生编译了)调整 mybaits-solon-plugin 插件,增加 configuration.mapperVerifyEnabled 配置(管制是否启用 mapper 校验)调整 mybatis 适配减少 isMapper 检测接口调整 凋谢 bean 外部状态注册的限度,之前只能用一般组件注解调整 利用启动时的事件改由 push 推送(之前是 pushTry)调整 XxxCacheService 减少新的构造函数调整 jlhttp Part 的 body string 大小限度改为 MAX_BODY_SIZE(之前为 MAX_HEADER_SIZE)调整 smarthttp Part 的 body string 大小限度改为 MAX_BODY_SIZE(之前为 MAX_HEADER_SIZE)调整 jdkhttp Part 的 body string 大小限度改为 MAX_BODY_SIZE(之前为 MAX_HEADER_SIZE)减少 Context::filesMap() 接口activemq 升为 5.15.9bean-searcher 升为 4.2.0sqltoy 升为 5.2.51redisson 升为 3.21.0netty 升为 4.1.75.Finalfastjson2 升为 2.0.33mybatis-flex 升为 1.3.2fastmybatis 升为 2.6.1我的项目仓库地址?gitee:https://gitee.com/noear/solongithub:https://github.com/noear/solon

June 7, 2023 · 1 min · jiezi

关于java:轻量级分布式日志追踪Tlog快速入门

一、前言公司目前还没有上 SkyWalking、Pinpoint等分布式追踪零碎,所以先用个轻量级的吧Tlog:只生成TraceId写入日志文件,没有 收集、存储、查问,所以 轻量以 spring-boot 2.3.12(非native) + log4j2 为例二、疾速入门1. 抉择接入形式日志框架适配器形式 最稳固,优先选择另有 Javaagent形式、字节码注入形式2. 装置倡议把 tlog的依赖 放到 log4j2后面,能够少批改 log4j2配置文件原我的项目依赖 hutool 时,版本不统一可能包抵触全量依赖 <dependency> <groupId>com.yomahub</groupId> <artifactId>tlog-all-spring-boot-starter</artifactId> <version>1.5.0</version> </dependency>按需依赖 <dependency> <groupId>com.yomahub</groupId> <artifactId>tlog-feign-spring-boot-starter</artifactId> <version>1.5.0</version> </dependency> <dependency> <groupId>com.yomahub</groupId> <artifactId>tlog-web-spring-boot-starter</artifactId> <version>1.5.0</version> </dependency>3. Log4j2框架适配器如果 tlog的依赖 没有放到 log4j2后面,需把pattern中的 m/msg/message 改成 tm/tmsg/tmessage日志pattern 没有蕴含 %X 变量(MDC变量)时,能够不必减少 %TX{tl},会自动记录日志pattern 蕴含 %X 变量时,需批改 pattern,减少 %TX{tl},记录TraceId。否则不会记录TraceId4. 成果启动日志:Converter key 'message' is already mapped to 'class com.yomahub.tlog.core.enhance.log4j2.AspectLogLog4j2Converter' 2020-09-16 18:12:56,748 [WARN] [TLOG]从新生成traceId[7161457983341056] >> com.yomahub.tlog.web.TLogWebInterceptor:392020-09-16 18:12:56,763 [INFO] <0><7161457983341056> logback-dubbox-consumer:invoke method sayHello,name=jack >> com.yomahub.tlog.example.dubbox.controller.DemoController:222020-09-16 18:12:56,763 [INFO] <0><7161457983341056> 测试日志aaaa >> com.yomahub.tlog.example.dubbox.controller.DemoController:232020-09-16 18:12:56,763 [INFO] <0><7161457983341056> 测试日志bbbb >> com.yomahub.tlog.example.dubbox.controller.DemoController:24三、配置1. 日志标签模板自定义TLog默认只打出spanId和traceId,可批改 spring-boot 配置文件调整: ...

June 7, 2023 · 1 min · jiezi

关于java:Spring-FrameWork从入门到NB-Bean

Spring Ioc容器是负责管理Bean的,所以在持续学习Spring其余内容之前,咱们须要首先理解一下Bean。 利用创立的java class,通过Spring IoC实例化创建对象并放入Spring IoC容器交给Spring IoC容器治理后,这个java对象就叫Bean。 Bean通过xml文件定义(bean标签),或者能够通过注解定义。Spring外部通过BeanDefinition治理Bean的定义信息(也叫元数据),BeanDefinition次要包含如下Bean定义的元数据: class name:全限定类名称,xml中通过class指定,注解形式的话就是该类的全限定类名。行为属性:包含scope、lifecycle、callbacks等。其余对象的援用:依赖对象。Bean的命名Spring IoC通过id惟一辨认一个Bean,在整个Spring IoC容器中不反复。 通过xml文件配置Spring的时候,id个别是要求必须要指定的,然而通过注解形式配置的时候,id不须要指定。不指定id的状况下,Spring默认通过java.beans.Introspector.decapitalize转换类名生成id:类名首字母小写后生成id。 Bean的实例化其实咱们后面的文章曾经说过了,有两种形式实例化Bean,一种是基于结构器的,一种是基于Factory Method。 Spring反对通过默认的无参结构器实现实例化,或者能够在配置文件指定结构器参数、Spring调用有参结构器实现实例化。底层理论都是通过java反射机制实现Bean的实例化。 通过Factory Method实例化有两种不同的模式,一种是动态工厂办法: <bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>还有一种是通过实例工厂办法(非静态方法): <bean id="serviceLocator" class="examples.DefaultServiceLocator"> <!-- inject any dependencies required by this locator bean --></bean><!-- the bean to be created via the factory bean --><bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/>通过实例工厂办法的形式实例化Bean,要求工厂类必须也是Spring IoC治理的Bean,这是不言而喻的,很容易了解。 工厂类能够指定多个工厂办法,实例化多个Bean。 因而,这种状况下,Bean的实在类型就不能通过配置文件决定了,因为配置文件可能并没有指定class、即便指定了class,通过动态工厂办法创立的Bean的类型也是不确定的,是由工厂办法的返回值决定的,配置文件里不反馈。也能够通过BeanFactory.getType在运行时获取到Bean的理论类型。 其实Spring的Bean实例化并不是这么简略,如果Spring发现以后类有AOP需要的话(比方办法加了@Transactional注解),那么Spring就须要通过CGLIB创立代理对象了,因为只有代理对象能力实现AOP,这部分内容咱们临时放一放。 上一篇 Spring FrameWork从入门到NB - 依赖注入DI

June 6, 2023 · 1 min · jiezi

关于java:什么是死锁它是如何产生的

死锁(Dead Lock)指的是两个或两个以上的运算单元(过程、线程或协程),相互持有对方所需的资源,导致它们都无奈向前推动,从而导致永恒阻塞的问题就是死锁。 比方线程 1 领有了锁 A 的状况下试图获取锁 B,而线程 2 又在领有了锁 B 的状况下试图获取锁 A,这样单方就进入互相阻塞期待的状况,如下图所示:死锁的代码实现如下: public class DeadlockDemo { public static void main(String[] args) { Object lock1 = new Object(); Object lock2 = new Object(); Thread thread1 = new Thread(() -> { synchronized (lock1) { System.out.println("Thread 1 acquired lock1"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2) { System.out.println("Thread 1 acquired lock2"); } } }); Thread thread2 = new Thread(() -> { synchronized (lock2) { System.out.println("Thread 2 acquired lock2"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1) { System.out.println("Thread 2 acquired lock1"); } } }); thread1.start(); thread2.start(); }}在下面的示例中,咱们创立了两个锁 lock1 和 lock2,并在两个线程中别离获取这两个锁,然而获取的程序不同。当 thread1 获取 lock1 后,它会在持有锁 lock1 的状况下尝试获取 lock2,而当 thread2 获取 lock2 后,它会在持有锁 lock2 的状况下尝试获取 lock1。如果这两个线程启动后,thread1 先获取 lock1 并且在获取 lock2 之前休眠,那么 thread2 就会获取 lock2,而后在尝试获取 lock1 时被阻塞。此时,thread1 就会在获取 lock2 时被阻塞。两个线程都在期待对方开释锁,从而造成了死锁。 ...

June 6, 2023 · 1 min · jiezi

关于java:理解-Java-关键字-final

原文链接 了解 Java 关键字 finalfinal能够用来干什么final是Java中十分常见的一个关键字,能够说每天都在应用它,尽管常见,但却也不见得都那么不言而喻,明天就来钻研一下final,以加深对它的了解和更正当的使用。 润饰类当一个类不想被继承时,就能够用final来润饰。 润饰办法当一个办法不想被子类覆写(Override)时,能够用final来润饰。另外一方面,把办法用final来润饰也有肯定的性能晋升上的帮忙,因为虚拟机晓得它不会被覆写,所以能够以更简略的形式来解决。 private的办法,默认都会被编译器加上final. 润饰变量被final润饰的变量只能赋值一次,之后不能再被批改。如: final int a = 10;a = 4; // compilation error须要留神的是,这里说的是只能赋值一次,并不意味着,非要在申明变量时间接初始化,比方,上面的代码也是齐全非法的: final int a;if (foo()) { a = 3;} else { a = 4;}润饰域变量域变量也是变量,所以用final来润饰的第一个作用就是赋值后,不能再批改变量的值,比方: final int a = 10;final Object b = new Object();对于根本类型来说,就是变量值不能再被批改;对于援用来说,就是不能再让其指向其余对象或者null。 但对于域变量,申明为final的域变量必须在申明时初始化,或者在构造方法中初始化,否则会有编译谬误。 此外,申明为final的域变量还有内存模型上的语义,上面具体说 内存模型的作用--避免变量从构造方法中逸出这个次要是针对被final润饰的域变量,虚构机会有禁止指令重排的保障: 在构造方法内对一个final变量的写入,与随后这个被结构对象的援用赋值给一个援用变量,这二个程序不扭转,final变量的写入肯定要早于对象援用的赋值。什么意思呢?在多线程环境下,域变量是有可能从构造方法中逸出的,也就是说线程有可能读到还没有被构造方法初始化的域变量的值。比方: class Foo { int a; Foo(int v) { a = v; }}如果是在多线程环境下,一个线程A在创立Foo的对象,另一个线程B在读对象的a的值,则B是有可能读到未正确初始化a的值(默认初始值0)。这就是域变量从构造方法中逸出。 关键字final能够禁止虚拟机指令重排,从而保障了构造方法执行结束前final润饰的变量肯定是初始化过了的。 这部分能够参考深刻了解Java内存模型(六)——final,解说的十分具体。 匿名外部类应用内部变量时为何要强制应用final润饰这个大家必定都司空见惯了,比方: private void initViews() { final int a = 3; // Compilation error if remove final btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (a > 1) { // volala } } }}那么,有没有想过为什么?而像其余反对完整闭包的语言如JavaScript,Python等,是没有这等限度的。究其原因,是Java对闭包反对不够残缺,或者说它并不是像动静语言那样的完整闭包。对于匿名外部类来说,编译器会创立一个命名类(OutClass$1之类的),而后把匿名类所在的能捕捉的变量),以结构参数的模式传递给外部类应用,这样一样,内部的变量与外部类看到的变量是不同的,尽管它们的值是雷同的,因而,如果再容许内部批改这些变量,或者外部类外面批改这些变量,都会造成数据的不一致性(因为它们是不同的变量),所以Java强制要求匿名外部类拜访的内部变量要加上final来润饰。 ...

June 5, 2023 · 1 min · jiezi

关于java:Spring-FrameWork从入门到NB-依赖注入DI

依赖注入DI指的是Spring IoC容器对对象的依赖对象的处理过程,对象的依赖对象,说起来比拟拗口,其实指的就是:如果一个对象A的某一属性为对象B,则对象B就是对象A的依赖对象,对象A创立的过程中也要创建对象B并注入到对象A,之后对象A能力失常工作。 Spring IoC可通过如下三种形式注入依赖对象: 结构器参数工厂办法参数Setter办法Spring DI因而也分为两种:基于结构器的DI和基于Setter的DI。 咱们须要用代码来阐明Spring两种形式DI的区别。 代码筹备创立一个Spring我的项目,Spring的任何版本都能够,在pom中退出依赖即可: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.2.8.RELEASE</version> </dependency>创立两个根底的接口,以及他们的实现类,不须要蕴含任何业务逻辑,咱们只是为了阐明依赖注入的概念。 public interface IDependencyA { public void test();}public interface IDependencyB { public void testB();}@Servicepublic class DependencyA implements IDependencyA { @Override public void test(){ System.out.println("I am DependencyA test..."); }}@Servicepublic class DependencyB implements IDependencyB{ private IDependencyA dependencyA; public static void main(String[] args) { System.out.println("I am a new comer...hello world "); } @Override public void testB(){ System.out.print("This is DependencyB's test and ..."); dependencyA.test(); } public DependencyB(){ //this.dependencyA =springTest; System.out.println("create DependencyB..."); }}其中类DependencyB蕴含了一个类型为IDependencyA的属性dependencyA,因而,DependencyB依赖于对象dependencyA。 ...

June 5, 2023 · 2 min · jiezi

关于java:理解Java关键字volatile

原文链接 了解Java关键字volatile在Java中,关键字volatile是除同步锁以外,另一个同步机制,它应用起来比锁要简略不便,然而却很容易被疏忽,或者被误用。这篇文章就来具体解说一下volatile它的作用,它的原理以及如何正确的应用它。 volatile的定义这个援用JSR中的定义: The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables. The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes. ...

June 5, 2023 · 2 min · jiezi

关于java:synchronized和Lock有什么区别

synchronized 和 Lock 都是 Java 中用于实现线程同步的机制,它们都能够保障线程平安。 synchronized 介绍与应用synchronized 可用来润饰一般办法、静态方法和代码块,当一个线程拜访一个被 synchronized 润饰的办法或者代码块时,会主动获取该对象的锁,其余线程将会被阻塞,直到该线程执行结束并开释锁。这样就保障了多个线程对共享资源的操作的互斥性,从而防止了数据的不一致性和线程平安问题。 synchronized 根本应用如下: public class SynchronizedDemo { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; }}此时咱们再应用多线程调用下面类的 increment 或 getCount 时,就不会呈现线程平安问题了,如下代码所示: public class SynchronizedDemoTest { public static void main(String[] args) { SynchronizedDemo demo = new SynchronizedDemo(); Runnable r = () -> { for (int i = 0; i < 1000; i++) { demo.increment(); } }; Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Count: " + demo.getCount()); }}Lock 介绍与应用Lock 是一种线程同步的机制,它与 synchronized 类似,能够用于管制对共享资源的拜访。相比于 synchronized,Lock 的特点在于更加灵便,反对更多的操作。 ...

June 5, 2023 · 2 min · jiezi

关于java:Spring-FrameWork从入门到NB-Ioc

SpringFramework是Spring全家桶的根底,并且曾经是公认的java开发基准框架,当初的java开发,没有spring framework会举步维艰。正是因为Spring曾经变成了以后JAVA开发的事实上的霸主,绝大部分的JAVA我的项目都不太可能没有Spring,而且,最重要的,绝大部分的初学者如果不把握Spring,你可能就很难入门:你拿不到offer,即便是小公司的offer你都拿不到。 所以初学者,包含大学校园里学完JAVA根底课程的学生,或者刚入职场的JAVA菜鸟,都有必要对Spring经验一遍“从入门到NB”的过程。 咱们先从一个面试问题说起。 面试题:你对Spring Framework的了解最常见的答复,包含:Java开源、可配置、一站式开发框架,外围是IOC与AOP,让开发者可能采纳最简略的形式构建出企业级java利用。 很多小伙伴说完下面一段之后就停下来了,面试官很尴尬,只能持续问:而后呢? 小伙伴(心里嘀咕:还有什么而后...没了):嗯...而后就是能够应用注解的形式简化开发,帮忙程序员实现了许多特地麻烦的配置,能够通过AOP实现拆散关注,让程序员可能专一于实现业务逻辑自身...... 这次就真的没有而后了。 其实集体感觉,对这个问题答复IOC和AOP,尤其是答复了Ioc和AOP之后就认为曾经答复了无关Spring Framework的全副问题的,基本就没有说到点子上,或者说你基本就不理解Spring Framework。 对Srping Freamwork的概念的解释,上来首先说Srping Freamwork是一个容器,比间接说IOC和AOP给人的感觉要好得多。这些IOC、AOP、轻量级、松耦合之类的概念,对于你真正了解Srping Freamwork,或者说对于面试官很好的了解你对Srping Freamwork框架的意识和把握,远没有以下知识点来的重要、且间接: Srping Freamwork其实是一个容器,这个容器以bean的形式治理咱们创立的类有了Srping Freamwork,程序员编写代码创立“类”之后,Srping Freamwork通过Ioc的形式帮忙咱们创建对象,也就是咱们所说的beanSrping Freamwork创立bean之后,保留在容器中咱们在须要应用对象的时候,能够从Srping Freamwork容器中十分不便的获取(DL或DI)Srping Freamwork能够采纳动静代理的机制创立bean,并在此基础上帮忙程序员实现AOP性能对于“如何了解Srping Freamwork”这个问题,以上几点纲要式的答复,感觉曾经足够了。这个答复能起到提纲挈领的作用,面试官对其中任何一个问题感兴趣,都能够持续深刻上来。 这样的答复,比水灵灵的Ioc、Aop、松耦合、可配置等等,更能切中要害。 当然,要想很好的深刻答复面试官可能提出的进一步的问题,还须要持续深刻学习。 什么是IoCIoc是Inversion of Control的首字母简写,即反转管制,其实Spring官网的文档介绍Ioc的时候,是说Ioc Container,反转管制容器: Introduction to the Spring IoC Container and BeansThis chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI).意思是说说Spring提供了一个容器、具备反转管制的能力,Spring容器的反转管制的能力和他的一个个性:dependency injection(DI)-依赖注入无关,Spring容器正是通过依赖注入来提供IoC能力。 所以说反转管制IoC其实和依赖注入(DI)是分不开的,Spring是通过DI提供IoC的。 为什么叫IoC-反转管制呢?所谓的反转,必定是和传统的解决形式(类之间的依赖关系的解决形式)比较而言的。为阐明问题,与Spring的“反转管制”绝对应,咱们假如传统的解决形式叫“失常的管制”。 假如咱们创创立了一个类A,外面蕴含各种属性,其中一个属性(属性b)是另外一个类B。 “失常的管制”过程是这样的:在应用的时候咱们会通过new创立类A的一个对象A1,给对象A1的各属性赋值,赋值过程中咱们须要创立类B的对象B1,把对象B1赋值给A1的属性b。 每次利用须要应用类A的时候,咱们可能都须要反复上述过程创立、筹备好类A的对象,提交给利用去应用。 Spring IoC的管制形式从某种意义上了解正好和这个“失常的管制”相同(这应该也是反转管制这个名字的由来):Spring的IoC容器创立类A的对象A1,并创建对象B的对象B1,并且,Spring IoC容器还负责将对象B1“注入”到对象A1中,让A1不创立而间接持有对象B1。这样一来,Spring就反转了以往的对象创立的控制权:以往是对象A1把握着创立本人的属性(对象B1)的控制权,当初这个控制权被反转了,A1没有控制权了,等着Spring IoC容器投喂(依赖注入)就好了。 ...

June 4, 2023 · 1 min · jiezi

关于java:踩坑以为是Redis缓存没想到却是Spring事务

前言 最近碰到了一个Bug,折腾了我好几天。并且这个Bug不是必现的,呈现的概率比拟低。一开始我认为是旧数据的问题,就让测试从新生成了一下数据,从新测试。因为前面几轮测试均未呈现,我也就没太在意。 惋惜好景不长,测试反馈上次的问题又呈现了。于是我立马着手排查,依据日志的体现,定位是三方服务出问题了。然而我不是十分确定,于是让测试持续察看。 然而明天又呈现了,这次并不是第三方服务引起的。于是我开始逐行审查代码,进行排查。一开始认为缓存的保护策略不对,导致数据库和redis呈现数据不统一的状况。然而通过进一步剖析日志,发现问题并不是在Redis而是在Spring事务。 场景介绍 业务场景如下:用户绑定了设施,须要显示在设施列表内,并且能够查看设施信息。 当用户绑定了一个设施,我须要在数据库内新增一条绑定记录。而后批改用户的策略,在用户的策略外面加上以后的设施,这样就能够查看设施信息了。 如果用户再次绑定同一个设施,会将原先的记录解绑,再生成一条新的绑定记录,因为是同一个设施笼罩绑定,则不会去批改用户策略。 如果在设施端或者手机端,进行解绑操作。则服务端会将绑定记录的状态变为解绑,同时用户策略也会删除以后设施。这样就看不到设施信息了。 代码示例代码构造@Slf4j@Servicepublic class DeviceUserServiceImpl { @Resource private DeviceUserServiceImpl self; /** * 绑定操作 */ @Transactional(rollbackFor = Exception.class) public DeviceBindVo doBind(DeviceBindBo bo, DevicePo device) { // 绑定逻辑 } /** * 设施解绑 */ @Override @Transactional(rollbackFor = Exception.class) public void unbind(DeviceUnbindBo bo) { DeviceUserPo deviceUser = self.getBindInfo(bo.getDeviceId(), bo.getUserId()); self.unbind(deviceUser, true); } /** * 设施解绑,公共逻辑 */ public void unbind(DeviceUserPo deviceUser, boolean modifyPolicy) { // 解绑逻辑 } /** * 获取绑定记录 */ @Override @Cacheable(value = RedisPrefixConst.DEVICE_USER, key = "#deviceId") public DeviceUserPo get(Long deviceId) { // 获取绑定记录 }} 绑定逻辑@Transactional(rollbackFor = Exception.class)public DeviceBindVo doBind(DeviceBindBo bo, DevicePo device) { // 获取设施绑定信息,判断设施是否被绑定 DeviceUserPo oldDeviceUser = self.get(bo.getDeviceId()); boolean modifyPolicy = true; if (oldDeviceUser != null) { self.unbind(oldDeviceUser); modifyPolicy = false; log.info("设施绑定->已完笼罩绑定的解绑流程"); } // 新增绑定记录 DeviceUserPo newDeviceUser = new DeviceUserPo(); log.info("设施绑定->已生成新的deviceUser数据: deviceUserId={}", newDeviceUser.getDeviceUserId()); // 删除缓存 self.deleteCache(bo.getUserId(), bo.getDeviceId()); // 依据需要,更新策略 if (modifyPolicy) { certService.modifyUserPolicy(bo.getUserId()); log.info("设施绑定->已更新用户证书策略."); } // 返回绑定信息 return new DeviceBindVo();}解绑逻辑/** * 设施解绑 * * @param bo 参数 */@Override@Transactional(rollbackFor = Exception.class)public void unbind(DeviceUnbindBo bo) { DeviceUserPo deviceUser = self.getBindInfo(bo.getDeviceId(), bo.getUserId()); self.unbind(deviceUser, true);}public void unbind(DeviceUserPo deviceUser, boolean modifyPolicy) { // 解绑 Assert.isTrue( // 执行解绑SQL, () -> new BizException(DeviceCodeEnum.DEVICE_NOT_BOUND) ); log.info("设施解绑->已更新数据库deviceUser的状态为unbind: deviceUserId={}", deviceUser.getDeviceUserId()); // 删除缓存 self.deleteCache(deviceUser.getUserId(), deviceUser.getDeviceId()); // 更改策略 if (modifyPolicy) { certService.modifyUserPolicy(deviceUser.getUserId()); log.info("设施解绑->已更新用户证书策略实现: userId={}", deviceUser.getUserId()); }}获取绑定信息@Override@Cacheable(value = RedisPrefixConst.DEVICE_USER, key = "#deviceId")public DeviceUserPo get(Long deviceId) { // 查问SQL}问题排查过程 首先咱们的业务场景是:用户绑定了设施,须要显示在设施列表内,并且能够点击查看设施信息。Bug场景是:设施曾经绑定胜利了,并且显示在设施列表内,然而无奈查看设施信息。 ...

June 4, 2023 · 2 min · jiezi

关于java:极客时间训练营高级Java工程师体系课2023版20

download:极客工夫训练营高级Java工程师体系课2023版2.0用SpringBoot和Vue3开发古代Web利用随着Web利用的日益遍及,前后端拆散的架构形式越来越受到欢送。在这种状况下,应用SpringBoot和Vue3是一个不错的抉择。本文将介绍如何应用SpringBoot和Vue3构建古代Web利用。 筹备工作在开始之前,咱们须要确保咱们曾经装置了以下软件: Java SDK 11 或以上Node.js 和 npmVue CLI 4IntelliJ IDEA 或 Eclipse创立SpringBoot我的项目首先,咱们须要创立一个SpringBoot我的项目。能够通过IntelliJ IDEA或Eclipse来实现这个工作。如果你应用IntelliJ IDEA,能够依照以下步骤来创立一个SpringBoot我的项目: 关上IntelliJ IDEA并抉择“Create New Project”。抉择“Spring Initializr”我的项目类型,并单击“Next”。在下一步中,填写你的我的项目信息,例如项目名称、形容、包名、Java版本等,并单击“Next”。抉择你须要增加的组件,但不要抉择“Spring Web”,因为咱们会在前面手动增加它。单击“Next”。最初,抉择你的我的项目存储地位,并单击“Finish”。当初,咱们曾经胜利地创立了一个SpringBoot我的项目。 增加Spring Web依赖接下来,咱们须要增加Spring Web依赖以反对Web服务。在pom.xml文件中,增加如下依赖: xml<dependency> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>创立Vue3我的项目当初,咱们须要创立一个Vue3我的项目。能够通过Vue CLI来实现这个工作。在终端窗口中执行以下命令: vue create my-app其中,“my-app”是你的项目名称。 运行Vue3我的项目接下来,咱们须要运行Vue3我的项目。在终端窗口中执行以下命令: cd my-appnpm run serve当初,咱们曾经胜利地创立了一个Vue3我的项目,并且曾经能够在浏览器中看到它的成果。 集成SpringBoot和Vue3当初,咱们须要将SpringBoot和Vue3集成在一起。首先,咱们须要将Vue3编译为动态资源并将其复制到SpringBoot我的项目的“resources/static”目录中。能够通过批改Vue3我的项目的“vue.config.js”文件来实现这一点: javascriptmodule.exports = { outputDir: '../src/main/resources/static',indexPath: '../static/index.html'}而后,在SpringBoot我的项目的“application.properties”文件中增加以下配置项: spring.mvc.view.prefix=/static/spring.mvc.view.suffix=.html最初,咱们须要在SpringBoot我的项目中创立一个控制器类来解决申请。例如,以下代码将返回Vue3的首页: java@Controllerpublic class HomeController { @GetMapping("/") public String home() { return "index";} }当初,咱们曾经胜利地将SpringBoot和Vue3集成在一起。 论断本文介绍了如何应用SpringBoot和Vue3构建古代Web利用。首先,咱们创立了一个SpringBoot我的项目并增加了Spring Web依赖。而后,咱们创立了一个Vue3我的项目并运行它。

June 2, 2023 · 1 min · jiezi

关于java:开发者必修必会的设计模式之工厂模式

本文首发自[慕课网](imooc.com) ,想理解更多IT干货内容,程序员圈内热闻,欢送关注"慕课网"及“慕课网公众号”!作者:李一鸣|慕课网讲师 工厂模式 工厂模式是平时开发过程中最常见的设计模式。工厂模式解决类的实例化问题,它属于创立型模式。工厂模式也常常会和其余设计模式组合应用。 试想你去麦当劳买一个汉堡。你只须要通知收银员要一个xx汉堡。过一会就会有一个此类型的汉堡被制作进去。而你齐全不须要晓得这个汉堡是怎么被制作进去的。这个例子中你就是客户端代码,麦当劳就是工厂,负责生产汉堡。汉堡是接口,而具体的某一种汉堡,比如说香辣鸡腿堡,就是实现了汉堡接口的类。 咱们持续通过另外一个例子,深刻了解工厂模式。当初咱们给某款音乐软件开发一个举荐性能。需要是可能依据用户抉择的音乐风格,举荐不同格调的歌曲清单。那么你打算怎么实现呢? 1. 音乐举荐器1.0版本如果之前没有学习过设计模式,很可能你的实现会是这样。编写 RecommendMusicService 类,外面有一个 Recommend办法。依据输出的格调不同,执行不同的举荐逻辑。代码如下: public class RecommendMusicService { public List<String> recommend(String style) { List<String> recommendMusicList = new ArrayList<>(); if ("metal".equals(style)) { recommendMusicList.add("Don't cry"); } else if ("country".equals(style)) { recommendMusicList.add("Hotel california"); } else if ("grunge".equals(style)) { recommendMusicList.add("About a girl"); }else { recommendMusicList.add("My heart will go on"); } return recommendMusicList; }}是不是感觉 recommed 办法太长了? OK,咱们重构下,把每种音乐风格的举荐逻辑封装到相应的办法中。这样举荐办法就能够复用了。 public class RecommendMusicService { public List<String> recommend(String style) { List<String> recommendMusicList = new ArrayList<>(); if ("metal".equals(style)) { recommendMetal(recommendMusicList); } else if ("country".equals(style)) { recommendCountry(recommendMusicList); } else if ("grunge".equals(style)) { recommendGrunge(recommendMusicList); }else { recommendPop(recommendMusicList); } return recommendMusicList; } private void recommendPop(List<String> recommendMusicList) { recommendMusicList.add("My heart will go on"); recommendMusicList.add("Beat it"); } private void recommendGrunge(List<String> recommendMusicList) { recommendMusicList.add("About a girl"); recommendMusicList.add("Smells like teen spirit"); } private void recommendCountry(List<String> recommendMusicList) { recommendMusicList.add("Hotel california"); recommendMusicList.add("Take Me Home Country Roads"); } private void recommendMetal(List<String> recommendMusicList) { recommendMusicList.add("Don't cry"); recommendMusicList.add("Fade to black"); }}这样是不是很完满了!recommend 办法精简了很多,而且每种不同的举荐逻辑都被封装到相应的办法中了。那么,如果再加一种格调举荐怎么办?这有什么难,recommed 办法中加分支就好啦。而后在 RecommendMusicService 中减少一个对应的举荐办法。等等,是不是哪里不太对?回忆一下设计模式6大准则的开闭准则----对扩大凋谢,对批改敞开。面对新格调举荐的需要,咱们始终都在批改 RecommendMusicService 这个类。当前每次有新格调举荐要增加,都会导致批改 RecommendMusicService 。显然这是个坏滋味。 ...

June 2, 2023 · 2 min · jiezi

关于java:Gradle极简入门

首发于Enaium的集体博客 什么是 GradleGradle是一个基于Apache Ant和Apache Maven概念的我的项目自动化构建工具。它应用一种基于Groovy的特定畛域语言(DSL)来申明我的项目设置,而不是传统的XML。Gradle构建脚本是用Groovy编写的,也能够应用Kotlin编写,两者都是基于JVM的语言。 装置 Gradle在开始之前,想必大家曾经学会了Java或者Kotlin,当初大家都在应用Android Studio开发Android利用,Android Studio是基于IntelliJ IDEA开发的,但当初不从Android Studio的角度来讲,也不从IntelliJ IDEA的角度来讲,而是从Gradle的角度来讲,所以咱们须要去官网下载Gradle,而后在IntelliJ IDEA中去应用Gradle。 首先去官网下载Gradle,下载地址:https://gradle.org/releases/,之后点击最新版本中的binary-only,这会间接下载一个zip压缩包,下载实现后解压到一个目录,而后再配置环境变量到bin目录,这样就能够在Terminal中应用gradle命令了,因为Java跨平台的缘故,在其余的操作系统上配置环境变量的形式都是大相不差的,这里我就不再赘述了,如果不会配置环境变量的话,能够去网上搜寻一下,这里我就不再赘述了。 配置好环境变量之后,关上Terminal,输出gradle -v,如果呈现上面的信息,阐明Gradle装置胜利了。 ------------------------------------------------------------Gradle 8.1------------------------------------------------------------Build time: 2023-04-12 12:07:45 UTCRevision: 40ba32cde9d6daf2b92c39376d2758909dd6b813Kotlin: 1.8.10Groovy: 3.0.15Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021JVM: 17.0.6 (BellSoft 17.0.6+10-LTS)OS: Windows 10 10.0 amd64创立 Hello World 我的项目创立一个文件夹,而后在文件夹中关上Terminal,输出gradle init,之后依照我的步骤来。 Select type of project to generate: 1: basic 2: application 3: library 4: Gradle pluginEnter selection (default: basic) [1..4] 2 // 抉择 applicationSelect implementation language: 1: C++ 2: Groovy 3: Java 4: Kotlin 5: Scala 6: SwiftEnter selection (default: Java) [1..6] 3 // 抉择 JavaGenerate multiple subprojects for application? (default: no) [yes, no] // 默认 noSelect build script DSL: 1: Groovy 2: KotlinEnter selection (default: Groovy) [1..2] 2 // 抉择 KotlinSelect test framework: 1: JUnit 4 2: TestNG 3: Spock 4: JUnit JupiterEnter selection (default: JUnit Jupiter) [1..4] //默认 JUnit JupiterProject name (default: gradle_learn):Source package (default: gradle_learn): cn.enaiumEnter target version of Java (min. 7) (default: 17): // 默认 17Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] // 默认 no> Task :initGet more help with your project: https://docs.gradle.org/8.1/samples/sample_building_java_applications.htmlBUILD SUCCESSFUL in 32s // 构建胜利2 actionable tasks: 2 executed如果最初呈现BUILD SUCCESSFUL,阐明我的项目创立胜利了,当初咱们来看一下我的项目的构造,这里先简略的介绍一下,前面会具体的介绍。 ...

June 2, 2023 · 4 min · jiezi

关于java:编写Java代码时应该避免的6个坑

通常状况下,咱们都心愿咱们的代码是高效和兼容的,然而理论状况下代码中经常含有一些暗藏的坑,只有等出现异常时咱们才会去解决它。本文是一篇比拟简短的文章,列出了开发人员在编写 Java 程序时常犯的谬误,防止线上问题。 1、大量应用 Enum.valuesEnum.Values() 的问题在于,依照标准它的返回必须是一个不可变的列表。为了实现这一点,它在每次调用时返回一个带有枚举值的新数组实例。 public enum Fruits { APPLE, PEAR, ORANGE, BANANA; public static void main(String[] args) { System.out.println(Fruits.values()); System.out.println(Fruits.values()); }}// output[Lcom.test.Fruits;@7ad041f3[Lcom.test.Fruits;@251a69d7它们是内存中的两个独立对象,这如同也没啥事,然而如果在解决大量申请时应用 Fruit.values() 并且机器负载很高,这可能会导致内存升高等问题。 public class Main { public static final Fruits[] values = Fruits.values(); public static void main(String[] args) { System.out.println(values); System.out.println(values); }}// output[Lcom.wayn.data.elastic.config.Fruits;@4534b60d[Lcom.wayn.data.elastic.config.Fruits;@4534b60d如上咱们能够通过引入公有动态最终变量 values 来缓存它们来轻松解决此问题。 2、将 Optional 作为办法参数传递如下代码 LocalDateTime getCurrentTime(Optional<ZoneId> zoneId) { return zoneId.stream() .map(LocalDateTime::now) .findFirst() .orElse(LocalDateTime.now(ZoneId.systemDefault()));}咱们传递可选的 zoneId 参数,并依据它的存在来决定是在零碎时区中给出工夫还是应用指定的时区。然而,这不是正确应用 Optional 的形式。咱们应该防止将它们用作参数,而是应用办法重载。 LocalDateTime getCurrentTime(ZoneId zoneId) { return LocalDateTime.now(zoneId);}LocalDateTime getCurrentTime() { return getCurrentTime(ZoneId.systemDefault());}如上代码显著更易于浏览和调试。 ...

June 1, 2023 · 3 min · jiezi

关于java:Spring-Boot-31中如何整合Spring-Security和Keycloak

在往年2月14日的时候,Keycloak 团队发表他们正在弃用大多数 Keycloak 适配器。其中包含Spring Security和Spring Boot的适配器,这意味着今后Keycloak团队将不再提供针对Spring Security和Spring Boot的集成计划。然而,如此弱小的Keycloak,还要用怎么办呢?本文就来聊聊,在最新的Spring Boot 3.1版本之下,如何将Keycloak和Spring Security一起跑起来。 筹备工作这里所采纳的框架与工具版本信息如下: Spring Boot 3.1.0Keycloak 21.1.1如果您采纳的是其余版本,本文内容不肯定无效,但能够作为参考。 配置Keycloak第一步:为Spring Boot利用创立Realm,并在上面创立一个Client 第二步:创立一个SYS_ADMIN角色,并创立一个用户赋予SYS_ADMIN角色 第三步:调用Keycloak接口生成Access Token,能够用上面的curl命令或者其余任何发申请的工具,比方:Postman等。 curl --location 'http://localhost:9090/realms/MyAppRealm/protocol/openid-connect/token' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'username=<YOUR_USER_NAME>' \--data-urlencode 'password=<YOUR_USER_PASSWORD>' \--data-urlencode 'grant_type=password' \--data-urlencode 'client_id=My-Awesome-App' \--data-urlencode 'client_secret=<KEYCLOAK_CLIENT_SECRET>' \--data-urlencode 'scope=openid'记住取得到Access Token,后续验证时候要用。 如果您学习过程中如遇艰难?能够退出咱们超高品质的Spring技术交换群,参加交换与探讨,更好的学习与提高! 配置Spring Boot利用第一步:创立一个Spring Boot利用,这个很简略,这里不赘述了。如果您还不会,能够看看我的Spring Boot教程 第二步:在pom.xml中增加依赖: <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-jose</artifactId></dependency>第三步:批改配置文件 spring: security: oauth2: resourceserver: jwt: issuer-uri: http://localhost:9090/realms/MyAppRealm jwk-set-uri: http://localhost:9090/realms/MyAppRealm/protocol/openid-connect/certs第四步:创立一个须要鉴权的测试接口 @RequestMapping("/test")@RestControllerpublic class MySuperSecuredController { @GetMapping("/hello") public String hello(){ return "hello"; }}第五步:创立SecurityFilterChain,用来告知Spring Security在JWT令牌中查找角色信息的地位。 ...

June 1, 2023 · 1 min · jiezi

关于java:为什么双重效验锁要加volatile

单例模式的实现办法有很多种,如饿汉模式、懒汉模式、动态外部类和枚举等,当面试官问到“为什么双重效验锁要加volatile?”时,那么他指的是为什么懒汉模式中的公有变量要加 volatile? 懒汉模式指的是对象的创立是懒加载的形式,并不是在程序启动时就创建对象,而是第一次被真正应用时才创建对象。要解释为什么要加 volatile?咱们先来看懒汉模式的具体实现代码: public class Singleton { // 1.避免内部间接 new 对象毁坏单例模式 private Singleton() {} // 2.通过公有变量保留单例对象【增加了 volatile 润饰】 private static volatile Singleton instance = null; // 3.提供公共获取单例对象的办法 public static Singleton getInstance() { if (instance == null) { // 第 1 次效验 synchronized (Singleton.class) { if (instance == null) { // 第 2 次效验 instance = new Singleton(); } } } return instance; }}从上述代码能够看出,为了保障线程平安和高性能,代码中应用了两次 if 和 synchronized 来保障程序的执行。那既然曾经有 synchronized 来保障线程平安了,为什么还要给变量加 volatile 呢? ...

June 1, 2023 · 2 min · jiezi

关于java:别再满屏找日志了推荐一款-IDEA-日志管理插件看日志轻松多了

1.简介Grep Console是一款不便开发者对idea控制台输入日志进行个性化治理的插件。 2.性能个性Grep Console的次要性能个性:反对自定义规定来过滤日志信息;反对不同级别的日志的输入款式的个性化配置;总结:通过过滤性能、输入日志款式配置性能,能够更不便开发者在大量的日志信息中筛选出本人比拟关注的日志信息。举荐一个开源收费的 Spring Boot 最全教程: https://github.com/javastacks/spring-boot-best-practice3.下载官网下载地址:https://plugins.jetbrains.com/,在搜寻输出中输出“Grep Console”,就能够达到下载页面。 4.装置Grep Console的装置形式有两种,优化举荐第一种在线装置: 4.1 在线装置在线装置,须要能够连贯到外网,file-->settings-->plugins-->browse repositories,在查问输入框中输出“grep console”,而后点击install,最初重启idea就能够应用了。 4.2 离线装置有的时候,无奈连贯到外网的时候,能够应用离线装置的办法进行idea插件装置 : a.从官网下载与本人应用idea的版本号相匹配的插件安装包;(我的idea版本是2018.2),所以我下载的grep console版本是9.6.162.000.1 b.file-->settings-->plugins-->install plugin from disk,而后选中下载好的插件安装包进行装置,完装实现后重启idea就能够应用了; 4.3 卸载插件file-->settings-->plugins,在搜寻输入框中输出“grep console”,而后点击uninstall进行插件卸载; 5.应用办法5.1 配置1、grep console的配置界面弹出有两种办法:第一种:file-->other settings-->grep console 第二种,我的项目启动后,点击管制台上左上角的小图标,也能够弹出配置界面 2、比拟关注的配置有两处:第一处:input filtering,这里次要是对输出到控制台的日志进行过滤。 expression:配置正则表达式;unless expression:和expression表白的意义相同;whole line:勾选中,示意匹配整行;case insensitive:示意疏忽大小写action:示意命中正则表达式后,要作出什么样的操作,有三种:1、移除(除非后面已有其余配置项匹配不移除),理论意思是说如果后面有其余不移除的配置项曾经匹配上,这里就能够不移除,否则还是要移除匹配上的内容;2、移除(匹配上就移除);3、什么也不做;continue matching:勾选中,示意下一个匹配项仍然能够持续匹配以后匹配项命中的行,即多个匹配项能够同时去匹配同一行日志信息;clear console:勾选中,示意革除控制台内除被以后配置项命中的其余日志信息,即只显示与配置项匹配的日志信息;soud:这个就比拟厉害了,命中配置项时会有声音提醒,有趣味的能够尝试一下;注:理论应用的时候,无论我怎么写expression表达式都没有方法齐全匹配整行,遇到空格就不匹配,只能匹配到一部分,有可能是我写的expression表达式不正确,也有可能插件自身在这块有问题,有晓得起因的小伙伴,能够在评论区通知我吧,非常感谢。 第二处:highlighting&folding expression:配置正则表达式;unless expression:和expression表白的意义相同;whole line:勾选中,示意匹配整行;case insensitive:示意疏忽大小写continue matching:勾选中,示意下一个匹配项仍然能够持续匹配以后匹配项命中的行,即多个匹配项能够同时去匹配同一行日志信息;bold:勾选中,示意命中的日志信息粗体显示;italic:勾选中,示意命中的日志信息斜体显示;background:设置命中日志信息的背景色彩;foreground:设置命中日志信息的字体色彩;statusbar count:勾选中,能够在Status Bar statistics panel中显示命中日志信息的次数(找了很久,没找到这个面板,有晓得的小伙伴在评论区通知我,多谢);console count:勾选中,能够在Console statistics panel上显示命中日志信息的次数(找了很久,没找到这个面板,有晓得的小伙伴在评论区通知我,多谢);fold:勾选中,能够把命中的日志信息折叠在一起(感觉这个性能没什么用);sound:这个就比拟厉害了,依据配置项命中日志信息时会有声音提醒,有趣味的能够尝试一下;5.2 实战上面理论演示一个这个插件怎么用,测试用的源代码:https://gitcode.net/fox9916/fanfu-web.git的grep-console-test分支。 1、有三个定时调度类,在被执行的时候会输入info级别日志信息; 2、对这三个调度工作输入的日志信息进行配置,要求:匹配整行日志信息;疏忽大小;EatTask调度工作输入日志信息背景色为黄色;DrinkTask调度工作输入日志信息为绿色;SportTask调用工作输入日志信息为蓝色;配置信息如下: 3、启动我的项目,输入日志信息如下: ...

May 31, 2023 · 1 min · jiezi

关于java:烂怂ifelse代码优化方案-京东云技术团队

0.问题概述代码可读性是掂量代码品质的重要规范,可读性也是可维护性、可扩展性的保障,因为代码是连贯程序员和机器的两头桥梁,要对双边敌对。Quora 上有一个帖子: “What are some of the most basic things every programmer should know?” 其中: Code that’s hard to understand is hard to maintain.Code that’s hard to maintain is next to useless.也强调了"easy understand"代码的重要性。 写这篇文章的契机是在研读Apache ShenYu我的项目时,看到了很大一坨的if else语句,如下: 这里并非评论这段代码写法有问题,因为我还并没有深刻到我的项目细节之中,可能这曾经是多轮优化的后果嘞。 然而这个多层if else的模式引发了我的思考,因为我也曾在我的项目代码中引入过如此沉重的if else构造,并在Code Review中被指出了问题。从那以后,我对if else的最大容忍层数就是三层。 我把大量if else的场景依照深度和广度两个维度划分为两种状况: 嵌套层级过深平铺范畴太广上面就讨论一下,当代码中存在大量这样构造的代码的时候,该如何优化? 1.解决方案1.1 尽早返回又称卫语句,即Guard Statement WikiPedia: In computer programming, aguardis abooleanexpression)that must evaluate to true if the program execution is to continue in the branch in question. ...

May 31, 2023 · 4 min · jiezi

关于java:volatile-底层是如何实现的

在 Java 中,volatile 是一种关键字,用于润饰变量。应用 volatile 关键字润饰的变量具备可见性和有序性,但不保障原子性。 相干定义阐明原子性(Atomicity):即一个操作或者多个操作,要么全副执行,并且执行的过程不会被任何因素打断,要么都不执行。 有序性(Ordering):指指令在执行过程中的程序,一个操作执行在另一个操作之前或者在其执行之后。即程序执行的程序依照代码的先后顺序执行。 可见性(Visibility):指当多个线程拜访同一个变量时,一个线程批改了这个变量的值,其余线程可能立刻看失去批改的值。 volatile 实现原理volatile 关键字在底层的实现次要是通过内存屏障(memory barrier)来实现的。内存屏障是一种 CPU 指令,用于强制执行 CPU 的外部缓存与主内存之间的数据同步。 在 Java 中,当线程读取一个 volatile 变量时,会从主内存中读取变量的最新值,并把它存储到线程的工作内存中。当线程写入一个 volatile 变量时,会把变量的值写入到线程的工作内存中,并强制将这个值刷新到主内存中。这样就保障了 volatile 变量的可见性和有序性。 在 Java 5 之后,volatile 的实现还引入了“内存屏障插入”的机制,内存屏障插入是指在指令序列中插入内存屏障以保障变量的可见性和有序性。 主内存和工作内存Java 内存模型规定,所有的变量(实例变量和动态变量)都必须存储在主内存中,每个线程也会有本人的工作内存,线程的工作内存保留了该线程用到的变量和主内存的正本拷贝,线程对变量的操作都在工作内存中进行。线程不能间接读写主内存中的变量,如下图所示:这样设计的目标次要是为了晋升程序的并发性能以及多线程之间的可见性问题。 主内存是 Java 虚拟机中的一块共享内存,所有线程都能够拜访。而每个线程还有本人的工作内存,线程的工作内存中存储了主内存中的变量正本的拷贝。这样做的益处是,线程之间不须要同步所有变量的读写操作,只须要同步主内存中的变量即可,这样能够进步程序的执行效率。同时,因为每个线程都有本人的工作内存,因而线程之间的变量操作相互不影响,从而进步了程序的并发性能。 内存屏障内存屏障是一种硬件机制,用于管制 CPU 缓存和主内存之间的数据同步。在 Java 中,内存屏障通常有两种:读屏障和写屏障。 在有内存屏障的中央,会禁止指令重排序,即屏障上面的代码不能跟屏障下面的代码替换执行程序。在有内存屏障的中央,线程批改完共享变量当前会马上把该变量从本地内存写回到主内存,并且让其余线程本地内存中该变量正本生效(应用 MESI 协定)。 MESI 协定是一种缓存一致性协定,它是反对写回(write-back)缓存的最罕用协定。MESI 协定基于总线嗅探机制实现了事务串形化,也用状态机机制升高了总线带宽压力,做到了 CPU 缓存一致性。MESI 协定这 4 个字母代表 4 个状态,别离是:Modified(已批改)、Exclusive(独占)、Shared(共享)、Invalidated(已生效)。 小结volatile 关键字在底层的实现次要是通过内存屏障(memory barrier)来实现的。内存屏障是一种 CPU 指令,用于强制执行 CPU 的外部缓存与主内存之间的数据同步。 本文已收录至《Java面试突击》,专一 Java 面试 100 年,查看更多:www.javacn.site

May 31, 2023 · 1 min · jiezi

关于java:腾讯二面有-40-亿个-QQ-号限制-1G-内存问如何去重被问懵了

40亿个QQ号,限度1G内存,如何去重?40亿个unsigned int,如果间接用内存存储的话,须要: 4*4000000000 /1024/1024/1024 = 14.9G ,思考到其中有一些反复的话,那1G的空间也基本上是不够用的。 想要实现这个性能,能够借助位图。 应用位图的话,一个数字只须要占用1个bit,那么40亿个数字也就是: 4000000000 * 1 /8 /1024/1024 = 476M相比于之前的14.9G来说,大大的节俭了很多空间。 比方要把我的QQ号"907607222"放到Bitmap中,就须要找到第907607222这个地位,而后把他设置成1就能够了。 这样,把40亿个数字都放到Bitmap之后,所有地位上是1的示意存在,不为1的示意不存在,雷同的QQ号只须要设置一次1就能够了,那么,最终就把所有是1的数字遍历进去就行了。 什么是BitMap?有什么用?位图(BitMap),根本思维就是用一个bit来标记元素,bit是计算机中最小的单位,也就是咱们常说的计算机中的0和1,这种就是用一个位来示意的。 所谓位图,其实就是一个bit数组,即每一个地位都是一个bit,其中的取值能够是0或者1 像下面的这个位图,能够用来示意1,4,6: 如果不必位图的话,咱们想要记录1,4,6 这三个整型的话,就须要用三个unsigned int,已知每个unsigned int占4个字节,那么就是3*4 = 12个字节,一个字节有8 bit,那么就是 12*8 = 96 个bit。 所以,位图最大的益处就是节俭空间。 位图有很多种用处,特地适宜用在去重、排序等场景中,驰名的布隆过滤器就是基于位图实现的。 然而位图也有着肯定的限度,那就是他只能示意0和1,无奈存储其余的数字。所以他只适宜这种能示意ture or false的场景。 举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice什么是布隆过滤器,实现原理是什么?布隆过滤器是一种数据结构,用于疾速检索一个元素是否可能存在于一个汇合(bit 数组)中。 它的基本原理是利用多个哈希函数,将一个元素映射成多个位,而后将这些位设置为 1。当查问一个元素时,如果这些位都被设置为 1,则认为元素可能存在于汇合中,否则必定不存在 所以,布隆过滤器能够精确的判断一个元素是否肯定不存在,然而因为哈希抵触的存在,所以他没方法判断一个元素肯定存在。只能判断可能存在。 所以,布隆过滤器是存在误判的可能的,也就是当一个不存在的Hero元素,通过hash1、hash2和hash3之后,刚好和其余的值的哈希后果抵触了。那么就会被误判为存在,然而其实他并不存在。 想要升高这种误判的概率,次要的方法就是升高哈希抵触的概率及引入更多的哈希算法。 上面是布隆过滤器的工作过程: 1、初始化布隆过滤器 在初始化布隆过滤器时,须要指定汇合的大小和误判率。布隆过滤器外部蕴含一个bit数组和多个哈希函数,每个哈希函数都会生成一个索引值。 2、增加元素到布隆过滤器 要将一个元素增加到布隆过滤器中,首先须要将该元素通过多个哈希函数生成多个索引值,而后将这些索引值对应的位设置为 1。如果这些索引值曾经被设置为 1,则不须要再次设置。 3、查问元素是否存在于布隆过滤器中 要查问一个元素是否存在于布隆过滤器中,须要将该元素通过多个哈希函数生成多个索引值,并判断这些索引值对应的位是否都被设置为 1。如果这些位都被设置为 1,则认为元素可能存在于汇合中,否则必定不存在。 布隆过滤器的次要长处是能够疾速判断一个元素是否属于某个汇合,并且能够在空间和工夫上实现较高的效率。然而,它也存在一些毛病,例如: 布隆过滤器在判断元素是否存在时,有肯定的误判率。、布隆过滤器删除元素比拟艰难,因为删除一个元素须要将其对应的多个位设置为 0,但这些位可能被其余元素共享。利用场景 布隆过滤器因为他的效率十分高,所以被宽泛的应用,比拟典型的场景有以下几个: ...

May 30, 2023 · 1 min · jiezi

关于java:求职面试场景下Spring都有哪些完美回答

本文首发自[慕课网](imooc.com) ,想理解更多IT干货内容,程序员圈内热闻,欢送关注"慕课网"及“慕课网公众号”! 人退职场混,哪有不被问,作为一名Java语言开发者,在面试的过程中,常常会和各种面试官频繁交手,甚至是有些来自灵魂的拷问~ 不过没关系,小慕认为每次面试都是对自我常识储备把握能力的一个输入和总结,提到java面试,面试官少不了会问spring的一些问题,在这里我把常见的几个根底问题进行一一解剖列举。 一、什么是spring框架简略总结概括的话,就是一个疾速开发java服务的后端框架,用户只须要关注业务需要,其余的事件交给框架解决。 二、Spring 框架中用到了哪些设计模式?这种题目,在咱们去面试前,刷各种题库的时候,必定会遇到,这是一个十分根底的面试题,一方面考查面试前的筹备是否充沛,另一方面也是看咱们作为一个程序员对spring框架的设计模式的把握和理解水平,就我集体了解而言,常见的有以下几种: 工厂设计模式 : Spring应用工厂模式通过 BeanFactory、ApplicationContext 创立 bean 对象。 代理设计模式 : Spring AOP 性能的实现。 单例设计模式 : Spring 中的 Bean 默认都是单例的。 模板办法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就应用到了模板模式。 包装器设计模式 : 咱们的我的项目须要连贯多个数据库,而且不同的客户在每次拜访中依据须要会去拜访不同的数据库。这种模式让咱们能够依据客户的需要可能动静切换不同的数据源。 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个利用。 适配器模式 :Spring AOP 的加强或告诉(Advice)应用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。 三、说说你对动静代理设计模式的了解在Spring框架内,大量用到了反射及动静代理技术,一般而言,动静代理个别分为两种,一种是JDK反射机制提供的代理,另一种就是CGLIB代理技术。 其中,JDK动静代理是须要实现类通过接口定义业务办法,对于没有接口的类,就须要应用CGLIB来实现动静代理。 四、动态代理和动静代理有什么区别?对于这类题目同样是理论知识的把握和本人对两种代理的了解是否可能做到了解透彻,集体感觉可能从概念,特点和区别下来答复,并通过理论生存中的场景例子阐明。 动态代理是什么? 某个对象提供一个代理,代理角色固定,以管制对这个对象的拜访。代理类和委托类有独特的父类或父接口,这样在任何应用委托类对象的中央都能够用代理对象代替。代理类负责申请的预处理、过滤、将申请分派给委托类解决、以及委托类执行完申请后的后续解决。 举个生存中的例子:比方一对新人结婚要举办婚礼,须要请这个婚庆公司的司仪帮忙主持婚礼,将婚礼的整个过程的举办委托给婚庆公司,由它帮咱们去执行工作同时解决工作相干的各种麻烦,最初把工作成绩交给咱们。那在这个过程中,两个人结婚就是为独特行为,是指标,这对新人就是咱们的指标角色,而婚庆公司司仪为了实现这次新人的结婚完满举办,负责代理整个环节流程的主持,氛围调节解决等,就是这个代理的角色。 所以不难从下面的实例中看到动态代理的特点是: 1、指标角色固定 2、在应用程序执行前就失去指标角色 3、代理对象会加强指标对象的行为 4、有可能存在多个代理 引起"类爆炸"(毛病) 动静代理是什么? 相比于动态代理,动静代理在创立代理对象上更加的灵便,动静代理类的字节码在程序运行时,由Java反射机制动静产生。它会依据须要,通过反射机制在程序运行期,动静的为指标对象创立代理对象,无需程序员手动编写它的源代码。动静代理不仅简化了编程工作,而且进步了软件系统的可扩展性,因为反射机制能够生成任意类型的动静代理类。代理的行为能够代理多个办法,即满足生产须要的同时又达到代码通用的目标。 同样举个例子:孩子要过生日了,为了给孩子一个典礼感,最起码先送个蛋糕。那蛋糕的口味多种多样了。有巧克力,冰淇淋,奶油等等。这都是根本的了,为了好吃又难看还再加点额定的装璜,如蛋糕里放点卡通动物图案、放贺卡、放点干果吃着更香等等。如果采纳继承会造成大量的蛋糕子类,所以就会采纳蛋糕作为主体,卡通图案,贺卡,果仁等是装璜者,须要时加到蛋糕上。要啥我就加啥。所以这外面是在不用扭转原类文件和应用继承的状况下,动静的扩大一个对象的性能。它通过创立一个包装对象,也就是装璜来包裹实在对象,提供了比继承更具弹性的代替计划。 动静代理的两种实现有形式: 别离是JDK 动静代理和 CGLIB动静代理;两者之间的区别在于JDK动静代理实现接口,Cglib动静代理继承思维,JDK动静代理(指标对象存在接口时)执行效率高于Ciglib。对于这两种形式如何去进行抉择,非常简单,如果指标对象有接口实现,就抉择JDK代理,如果没有接口实现抉择Cglib代理。 动静代理的特点是什么? 1、指标对象不固定 2、在应用程序执行时动态创建指标对象 3、代理对象会加强指标对象的行为 五、谈谈你对代理模式的了解?对于面试官这种发问的形式,首先要搞清楚这个问题的实质为了考查你的长期总结能力,是对你是否有本人独特观点视角的一个出现机会,这种开放式的发问没有标准答案,所以只须要咱们介于本人对代理模式的了解,对知识点进行个人观点论述和总结,用本人了解的语言能很好的组织表达出来即可。 ...

May 30, 2023 · 1 min · jiezi

关于java:Kstry流程编排框架

     我的项目主页      Kstry概念介绍      Kstry 应用文档      Kstry 应用demo      Kstry 流程注解+flux 应用demo      功能测试 Kstry是什么?    Kstry能够将本来存在于代码中盘根错节的办法调用关系以可视化流程图的模式更直观的展现进去,并提供了将所见的办法节点加以控制的配置伎俩。框架不能脱离程序执行之外存在,只能在办法与办法的调用中失效和应用,比方某个接口的一次调用。不会像Activiti、Camunda等工作流框架一样,脱离程序执行之外将工作实例存储和治理。     不同应用场景中,因其发挥作用的不同,能够了解成不同的框架,Kstry是:      【流程编排框架】提供所见( 流程图示 )即所得( 代码执行 )的可视化能力,可自定义流程协定,反对流程配置的热部署      【并发框架】可通过极简操作将流程从串行降级到并行,反对工作拆分、工作重试、工作降级、子工作遍历、指定流程或工作的超时工夫      【微服务业务整合框架】反对自定义指令和工作脚本,可负责各种根底能力组件的拼装      【轻量的TMF2.0框架】能够通过以下三个步骤来满足同一接口下各类业务对实现性能的不同诉求:形象能力资源、定义并将形象出的能力资源受权给业务角色、同一流程的不同场景可别离匹配不同角色再将其下的能力资源工作加以执行 Kstry有哪些特点?    【业务可视】编排好的图示模型即为代码实在的执行链路,通过所见( 图示模型 )即所得( 代码执行 )的形式在技术和业务之间架起一道通用语言的桥梁,使彼此之间沟通更加顺畅     【配置灵便】提供开始事件、完结事件、服务节点、脚本节点、排他网关、蕴含网关、并行网关、条件表达式、自定义指令、子流程、拦截器等配置组件,能够反对变态简单的业务流程     【动静配置】主流程、子流程、角色、变量等组件反对动态化配置,不启动利用的前提下能够动静变更,动态化配置反对包含开源和公司自研在内的全副存储介质     【适配度高】蕴含BPMN可视化配置文件和代码两套流程定义API,在保障可视化配置的前提下,又反对通过代码形式解析任意格局的流程配置文件,从而联合适合的前端产品搭建个性化的流程配置平台     【轻松运维】服务节点反对定义超时工夫、重试次数、失败降级、严格模式、资源迭代等,可满足生产环境下对利用稳定性的严苛要求     【性能优异】最底层采纳Spring工具集进行服务节点调用,工作执行耗费与Spring切面相当     【秒变异步】无缝连接SpringFlux。无需改变代码,仅仅在并行网关或蕴含网关上配置 open-async=true,即可在保障线程平安的前提下将其后的子链路全副并行化     【交互顺畅】引入StoryBus和其中四个数据域的概念。节点之间数据存取交互能够做到平安、灵便、不便     【业务形象】引入资源、权限、角色等概念,构建定制化业务身份,为抽象化业务能力提供技术支持和解决方案     【流程回溯】能够零老本记录节点执行程序、节点耗时、入参、出参、异样信息等重要数据,并反对自定义执行监控日志 Kstry能够解决哪些问题?      【业务含糊】代码简单、模型文档更新不及时,以致新同学和非技术同学不能短时间内理解业务现状。技术和非技术间对同一业务了解存在一致而不自知。甚至业务Owner也不能很晦涩的形容出本人所负责的业务      【代码芜杂】我的项目中波及到许多畛域对象,对象间不仅存在简单的前后依赖关系还互相掺杂没有显著边界,代码屡次迭代后更是凌乱不堪难以保护      【性能低下】某业务链路由一系列子工作组成,其中须要并行处理一些耗时长且数据间没有依赖的子工作,但苦于没有精简且无代码侵入的并发框架      【平台之殇】保护平台型产品,为泛滥上游业务线提供着根底服务,但在短时间内应对各个业务方的定制化需要顾此失彼,更不知如何做好平台与业务、业务与业务之间的隔离      【回溯艰难】业务流转数据状态追踪艰难,只存在于线上环境的偶现问题更是难以排查。须要一种能够通过简略操作就能将重要节点数据都保留下来的能力,此能力堪比对链路精细化梳理后的系统性日志打印      【测试简单】业务场景多样,不乏一些简单的链路难以被测试笼罩。或者三方数据Mock艰难,测试老本居高不下 Kstry组件概念介绍1、配置域与运行域    简略来讲配置域就是通过可视化、代码亦或者脚本的形式配置流程,执行域就是依据配置好的规定来执行。     概念上了解,通常状况下的程序执行是办法与办法之间的调用,在Kstry中却是工作节点之间的互相关系(之所以是概念上来看,是因为无论是否用Kstry,程序理论执行载体都是类中的办法,而且工作节点与办法也是一一对应的)。工作执行前的流程配置决定了节点之间在理论执行时会产生何种关系。程序未执行前的流程配置就是配置域,框架解析流程配置并在程序执行时领导工作节点先后调用就是执行域。 2、流程定义    流程定义是程序理论执行前,在配置域须要实现的工作,由开始事件、完结事件、服务节点、网关、及这些组件相连接的有向线段独特组成。编排好的图示模型即为代码实在的执行链路,通过所见( 图示模型 )即所得( 代码执行 )的形式在技术和业务之间架起一道通用语言的桥梁,使彼此之间沟通更加顺畅。     只有bpmnPath一种流程配置路径时,上面这种可视化流程图就是被定义进去的流程,也是凭此来领导程序理论线路的执行。ProcessLink呈现之后,框架提供了自定义流程的能力给使用者,在1.x之后的版本中,BPMN可视化流程图也是被解析成ProcessLink对象来失效的,此时的BPMN可视化流程就作为了流程定义的一个子集而存在。更多状况下使用者能够通过编码、解析各类配置文件等形式来创立ProcessLink实例,最终交付给框架的ProcessLink实例将会作为流程定义来领导程序的执行。    Kstry提供了三种形式来定义流程配置,别离是:      【根底流程配置】指定@EnableKstry注解的bpmnPath属性来扫描指定目录下的bpmn配置文件      【根底流程配置】创立ProcessLink实例放入Spring容器中 ...

May 30, 2023 · 1 min · jiezi

关于java:redisconf-70-配置和原理全解生产王者必备

5.5 redis.conf 配置详解我是 Redis, 当程序员用指令 ./redis-server /path/to/redis.conf 把我启动的时候,第一个参数必须是redis.conf 文件的门路。 这个文件很重要,就如同是你们的 DNA,它能管制我的运行状况,不同的配置会有不同的个性和人生,它把握我的人生命运,管制着我如何实现高可用、高性能。正当的配置能让我更快、更省内存,并施展我最大的劣势让我更平安运行。 以下这些配置大家必知必会,须要大家把握每个配置背地的技术原理,学会交融贯通并在生产中正确配置,解决问题。避免出现技术悬浮,原理说的叭叭叭,配置像个大傻瓜。 本文配置文件版本是 Redis 7.0。 5.5.1 惯例通用配置这些是我的惯例配置,每个 Redis 启动必备参数,你肯定要把握,波及到网络、模块插件、运行模式、日志等。 MODULES这个配置能够加载模块插件加强我的性能,常见的模块有 RedisSearch、RedisBloom 等。对于模块加载能够参考【5.6 布隆过滤器原理与实战】章节集成布隆过滤器便是通过以下配置实现加载布隆过滤器插件。 loadmodule /opt/app/RedisBloom-2.2.14/redisbloom.soNETWORK这部分都是与网络相干的配置,很重要滴,配置不当将会有平安和性能问题。 bindbind用于绑定本机的网络接口(网卡),留神是本机。 每台机器可能有多个网卡,每个网卡都有一个 IP 地址。配置了 bind,则示意我只容许来自本机指定网卡的 Redis 申请。 MySQL:“bind 是用于限度拜访你的机器 IP 么?”非也,留神,这个配置指的并不是只有 bind 指定的 IP 地址的计算机能力拜访我。如果想限度指定的主机连贯我,只能通过防火墙来管制,bind 参数不也能起到这个作用。 举个例子:如果我所在的服务器有两个网卡,每个网卡有一个 IP 地址, IP1,IP2。 配置 bind IP1,则示意只能通过这个网卡地址来的网络申请拜访我,也能够应用空格宰割绑定多个网卡 IP。 我的默认配置是bind 127.0.0.1 -::1 示意绑定本地回环地址 IPv4 和 Ipv6。- 示意当 ip 不存在也能启动胜利。 protected-modeMySQL:网络世界很危险滴,你如何保障平安?默认开启保护模式,如果没有设置明码或者没有 bind 配置,我只容许在本机连贯我,其它机器无奈连贯。 如果想让其它机器连贯我,有以下三种形式。 配置为 protected-mode no(不倡议,地球很危险滴,防人之心不可无)。protected-mode yes,配置 bind 绑定本机的 IP。protected-mode yes,除了设置 bind 以外,还能够通过 requirepass magebyte设置明码为 magebyte, 让其余机器的客户端能应用明码拜访我。bind、protected-mode、requirepass 之间的关系 ...

May 30, 2023 · 10 min · jiezi

关于java:一文详解-SaToken-中的-SaSession-对象

Sa-Token 是一个轻量级 java 权限认证框架,次要解决登录认证、权限认证、单点登录、OAuth2、微服务网关鉴权 等一系列权限相干问题。 Gitee 开源地址:https://gitee.com/dromara/sa-token本文将具体介绍 Sa-Token 中的不同 SaSession 对象的区别,以及各种不便的存取值的办法。 一、Session 是什么?Session 是会话中业余的数据缓存组件,通过 Session 咱们能够很不便的缓存一些高频读写数据,进步程序性能,例如: // 在登录时缓存user对象 StpUtil.getSession().set("user", user);// 而后咱们就能够在任意处应用这个user对象SysUser user = (SysUser) StpUtil.getSession().get("user");在 Sa-Token 中,SaSession 分为三种,别离是: User-Session: 指的是框架为每个 账号id 调配的 SaSession。Token-Session: 指的是框架为每个 token 调配的 SaSession。Custom-Session: 指的是以一个 特定的值 作为SessionId,来调配的 Session。假如三个客户端登录同一账号,且配置了不共享token,那么此时的Session模型是: 简而言之: User-Session 以UserId为主,只有token指向的UserId统一,那么对应的Session对象就统一。Token-Session 以token为主,只有token不同,那么对应的Session对象就不同。Custom-Session 以特定的key为主,不同key对应不同的Session对象,同样的key指向同一个Session对象。二、获取 User-Session无关账号Session的API如下: // 获取以后账号id的Session (必须是登录后能力调用)StpUtil.getSession();// 获取以后账号id的Session, 并决定在Session尚未创立时,是否新建并返回StpUtil.getSession(true);// 获取账号id为10001的SessionStpUtil.getSessionByLoginId(10001);// 获取账号id为10001的Session, 并决定在Session尚未创立时,是否新建并返回StpUtil.getSessionByLoginId(10001, true);// 获取SessionId为xxxx-xxxx的Session, 在Session尚未创立时, 返回null StpUtil.getSessionBySessionId("xxxx-xxxx");三、获取 Token-Session无关令牌Session的API如下: // 获取以后 Token 的 Token-Session 对象StpUtil.getTokenSession();// 获取指定 Token 的 Token-Session 对象StpUtil.getTokenSessionByToken(token);四、获取自定义Session自定义Session指的是以一个特定的值作为SessionId来调配的Session, 借助自定义Session,你能够为零碎中的任意元素调配相应的session例如以商品id作为key为每个商品调配一个Session,以便于缓存和商品相干的数据,其相干API如下: ...

May 30, 2023 · 2 min · jiezi

关于java:Java-亿级项目架构设计与落地应用雁声远过潇湘去

download:Java 亿级我的项目架构设计与落地利用在软件开发过程中,开发人员和架构师都是十分重要的角色。尽管两者都从事软件开发,但它们之间有着显著的区别和分割。本篇文章将探讨这两个角色之间的关系以及它们各自的职责。 开发人员的职责开发人员通常是公司中的程序员或工程师。他们负责依据指定的需要编写代码,并测试和调试应用程序。在我的项目的不同阶段,开发人员会应用一系列编程语言和技术来实现他们的工作。他们也必须理解如何应用版本控制系统(如Git)来治理代码并与其余开发人员合作。 开发人员还须要熟悉业务逻辑和用户需要,以便可能编写出符合要求的代码。此外,他们还须要解决问题、修复谬误并改良现有代码。 架构师的职责架构师是一个更高级别的职位,通常须要多年的教训。他们负责设计和布局软件系统的整体构造,并确保其满足业务需要。架构师通常须要思考性能、可扩展性和安全性等方面,并确定应用哪些技术和工具来实现零碎的指标。 架构师还须要与其余开发人员、测试人员和业务团队单干,确保整个团队都理解零碎设计,并可能无效地施行它。他们还必须监督开发过程,并确保开发团队依照指定的方向后退。 开发人员和架构师之间的关系只管职责不同,但开发人员和架构师之间有许多相互依存的关系。在软件我的项目中,架构师通常会制订技术架构和布局,而开发人员会依据这些打算进行编码和实现。如果架构师没有思考到某些因素,可能会导致代码缺点或无奈满足业务需要。同样,如果开发人员没有了解架构师的设计准则,则可能会编写出低效或不符合要求的代码。 因而,开发人员和架构师之间须要密切协作,以确保零碎可能达到预期的指标。架构师应该领导开发人员并提供反对,而开发人员则须要遵循架构师的布局并及时反馈问题和想法。 论断尽管开发人员和架构师之间存在显著的职责差别,但他们之间的关系十分亲密。架构师负责布局整个零碎,而开发人员则实现这些打算并编写代码。通过密切协作和相互支持,他们能够独特实现高效、平安且符合要求的软件系统。

May 30, 2023 · 1 min · jiezi

关于java:脱离-Spring-苦海Solon-v230-发布

Solon 是什么框架?一个,Java 新的生态型利用开发框架。它从零开始构建,有本人的标准规范与凋谢生态(寰球第二级别的生态)。与其余框架相比,它解决了两个重要的痛点:启动慢,费资源。 解决痛点?因为Solon Bean容器的独特设计,不会因为扩大依赖变多而启动很慢(开发调试时,省时、痛快)!以出名开源我的项目“小诺”为例: “snowy-spring 版” 启动 30-50秒“snowy-solon 版” 启动3-5秒(有趣味的,欢送拉取代码体验)所谓:“工夫就是生命,效率就是金钱”,“天下文治,唯快不破”。 绝对于 Spring Boot 和 Spring Cloud 的我的项目,有什么特点?启动快 5 ~ 10 倍。 (更快)qps 高 2~ 3 倍。 (更高)运行时内存节俭 1/3 ~ 1/2。 (更少)打包能够放大到 1/2 ~ 1/10;比方,300Mb 的变成了 23Mb。 (更小)同时反对 jdk8, jdk11, jdk17, jdk20, graalvm native本次更新了什么?降级 日志体系到 slf4j 2.x (如果抵触,排除旧的 1.x)!!!新增 solon.docs 插件!!!新增 solon-swagger2-knife4j 插件!!!新增 zipkin-solon-cloud-plugin 插件新增 etcd-solon-cloud-plugin 插件新增 fastmybatis-solon-plugin 插件弃用 @Dao @Repository @Service (改由 @ProxyComponent 代替)减少 ProxyUtil::attach(ctx,clz,obj,handler) 接口减少 aot 对 methodWrap 参数的主动注销解决修复 AopContext::getWrapsOfType 返回后果失真的问题调整 mybatis 按包名扫描只对 @Mapper 注解的接口无效(防止其它接口误扫)slf4j 升为 2.0.7log4j2 升为 2.20.0(基于 slf4j 2.x)logback 升为 1.3.7(基于 slf4j 2.x)sqltoy 升为 5.2.48mybatis-flex 升为 1.2.9beetlsql 升为 3.23.1-RELEASEwood 升为 1.1.2redisx 升为 1.4.8water 升为 2.11.0protobuf 升为 3.22.3jackson 升为 2.14.3dubbo3 升为 3.2.1grpc 升为 1.54.1zookeeper 升为 3.7.1nacos2-client 升为 2.2.2nacos1-client 升为 1.4.5jaeger 升为 1.8.1我的项目仓库地址?gitee:https://gitee.com/noear/solongithub:https://github.com/noear/solon

May 30, 2023 · 1 min · jiezi

关于java:MyBatis-Migrations-教程

官网地址:http://mybatis.org/migrationsGitHub地址:https://github.com/mybatis/migrations 简介(出自ChatGPT)MyBatis Migrations 是一款基于 SQL 的数据库版本控制系统,它由 MyBatis 团队开发。该工具的设计目标是为了简化数据库迁徙过程,以便更好地追踪、治理和利用数据库模式的变更。 以下是 MyBatis Migrations 的一些次要个性: SQL 为核心:MyBatis Migrations 是基于 SQL 的,这意味着数据库迁徙脚本是用 SQL 语言编写的。这样的设计使得数据库管理员和开发人员能够间接应用相熟的 SQL 语言来治理数据库模式的变更。反对撤销操作:MyBatis Migrations 提供了撤销操作,这使得你能够不便地撤销最近的数据库模式变更。每个迁徙脚本都蕴含两局部:一部分用于执行数据库变更,另一部分用于撤销这些变更。主动版本控制:每次你执行一个新的数据库迁徙,MyBatis Migrations 都会在一个非凡的表(默认名为 changlog)中记录这次变更。这使得你能够很容易地查看历史变更,以及查看哪些迁徙曾经被利用,哪些还未被利用。灵活性和可定制性:MyBatis Migrations 容许你定制迁徙过程。例如,你能够抉择在什么工夫利用哪些迁徙,你也能够抉择是否执行撤销操作。反对命令行和编程式 API:你能够通过命令行工具来应用 MyBatis Migrations,也能够在你的 Java 代码中调用 MyBatis Migrations 的 API。MyBatis Migrations 是一款十分实用的数据库版本控制工具,尤其适宜喜爱间接应用 SQL 治理数据库模式的团队。 留神❗️❗️❗️MyBatis Migrations 是一个 Java 工具,因而您必须装置 Java 能力持续。用户至多须要 Java 运行时环境(JRE),而装置 Java 开发工具包 (JDK) 则更好。MyBatis Migrations 须要 Java 版本 8 或更高版本。装置1. 下载我的项目压缩包下载地址址:点击下载 mybatis-migrations-3.3.11 2. 解压到自定义目录解压后目录文件构造: mybatis-migrations-3.3.11 lib/mybatis-${project.version}.jarlib/mybatis-migrations-${project.version}.jarbin/migrate --------------------------------------(linux 执行命令)bin/migrate.cmd ---------------------------------(windows 执行命令)LICENSENOTICEMIGRATIONS-README3. 配置环境变量Mac 零碎 ...

May 30, 2023 · 2 min · jiezi

关于java:代码语义搜索算法哪家强华为云UniXcoderVESOv1算法取得突破问鼎CodeXGLUE榜单第一名

随着语言大模型技术的倒退,一系列语言大模型在自然语言解决工作上获得了微小的胜利,为源代码解决工作提供了技术根底,这些模型曾经利用于代码摘要和代码语义搜寻。华为云PaaS技术创新团队基于UniXcoder模型,在公开测试数据集(CodeXGLUE)上的代码搜寻工作评测后果上获得冲破,在CodeXGLUE榜单上排名中第一。 依照查问语句的类型,代码搜寻能够分为代码关键字搜寻和代码语义搜寻。代码关键字搜寻次要通过索引代码实体(如类、办法、变量等),查问定位代码实体的定义及援用;代码语义搜寻的指标是反对开发人员基于自然语言形式来形容代码个性,从而进行相干代码的举荐与搜寻。在开发人员编程过程中帮忙其查找最佳代码示例实际和库应用示例,从而开发者能够通过性能形容搜寻到代码。 目前,大多数代码搜索引擎仅反对代码关键字搜寻,这须要开发者理解他们正在搜寻的代码,例如类名、函数名、API调用等等,这具备很大的局限性。少数用户通常通过搜寻代码示例来领导他们实现特定的编码工作,他们更偏向于应用自然语言来形容待编码实现的性能,从而借鉴开源社区中已存在的相干代码片段。代码语义搜寻能够反对开发人员在不晓得类或函数名称的状况下应用自然语言形式来形容所需的代码性能。借助于语言模型及不同自然语言之间的映射关系,开发者甚至能够基于中文形容搜寻出蕴含英文性能形容的代码片段。 随着语言大模型(Large Language Model, LLM)技术的倒退,一系列语言大模型(如BERT [1]、XLNet [2]、GPT [3]、RoBERTa [4]等)在自然语言解决工作上获得了微小的胜利,为源代码解决工作提供了技术根底。这些模型曾经利用于代码摘要和代码语义搜寻,战胜了以前的最先进办法。语义搜寻背地的想法是将语料库中的所有条目,无论是句子、段落还是文档,都编码到向量空间中。在搜寻时,查问被编码到雷同的向量空间中,并找到语料库中最近的向量。这些条目应与查问具备高度的语义重叠。代码语义搜寻应用编码大模型将查问及代码片段编码成向量,使得语义相干或相近的代码片段和查问在向量空间内落在相近的地位。如下图所示: 有很多算法应用不同的编码器对代码片段和查问进行编码,最新和最有心愿的钻研集中在通用编码器和解码器上,这些编码器和解码器应用雷同的神经网络来编码所有编程语言代码片段和文本。 Salza等人 [5]基于原始BERT[1]模型,用多种编程语言代码预训练一个新的BERT模型,并用两个编码器(一个解决自然语言,另一个解决代码片段)精调该模型,首先证实了解决自然语言的基于Transformer架构的模型能够被间接利用到代码搜寻工作中。 CodeBERT [6]是在自然语言和编程语言序列数据上进行训练的大型语言模型之一,它在代码搜寻方面体现较为杰出。此外,还倒退演化出RoBERTa [4]、TreeBERT [7]、GraphCodeBERT [8]、UniXcoder [9]等在代码搜寻方面表现出色的自然语言与编程语言联合训练的模型。 华为云PaaS技术创新团队基于UniXcoder模型,通过混同代码片段、减少海量开源代码作为训练集、进步批尺寸等精调办法,实现了UniXcoder-VESO-v1算法,该算法在公开测试数据集(CodeXGLUE [10])上的代码搜寻工作评测后果上获得冲破:均匀倒数排序值(MRR)达到0.58,CodeXGLUE榜单上排名中第一(如下图所示: UniXcoder-VESO-v1, 详见https://microsoft.github.io/CodeXGLUE/)。 咱们将继续推动该工作的技术创新与冲破,会抉择适合形式披露外部技术细节,如感兴趣,欢送继续关注咱们的订阅号文章。 文章来自 PaaS技术创新Lab,PaaS技术创新Lab隶属于华为云,致力于综合利用软件剖析、数据挖掘、机器学习等技术,为软件研发人员提供下一代智能研发工具服务的外围引擎和智慧大脑。咱们将聚焦软件工程畛域硬核能力,一直构筑研发利器,继续交付高价值商业个性!退出咱们,一起创始研发新“境界”!(详情欢送分割 mayuchi1@huawei.com;guodongshuo@huawei.com) PaaS技术创新Lab主页链接:https://www.huaweicloud.com/lab/paas/home.html 参考文献[1]. Jacob Devlin, Ming-Wei Chang, Kenton Lee, Kristina Toutanova: BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. NAACL-HLT (1) 2019: 4171-4186[2]. Zhilin Yang, Zihang Dai, Yiming Yang, Jaime G. Carbonell, Ruslan Salakhutdinov, Quoc V. Le: XLNet: Generalized Autoregressive Pretraining for Language Understanding. NeurIPS 2019: 5754-5764[3]. Tom B. Brown, Benjamin Mann, Nick Ryder, Melanie Subbiah, Jared Kaplan, Prafulla Dhariwal, Arvind Neelakantan, Pranav Shyam, Girish Sastry, Amanda Askell, Sandhini Agarwal, Ariel Herbert-Voss, Gretchen Krueger, Tom Henighan, Rewon Child, Aditya Ramesh, Daniel M. Ziegler, Jeffrey Wu, Clemens Winter, Christopher Hesse, Mark Chen, Eric Sigler, Mateusz Litwin, Scott Gray, Benjamin Chess, Jack Clark, Christopher Berner, Sam McCandlish, Alec Radford, Ilya Sutskever, Dario Amodei: Language Models are Few-Shot Learners. NeurIPS 2020[4]. Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar Joshi, Danqi Chen, Omer Levy, Mike Lewis, Luke Zettlemoyer, Veselin Stoyanov: RoBERTa: A Robustly Optimized BERT Pretraining Approach. CoRR abs/1907.11692 (2019)[5]. Pasquale Salza, Christoph Schwizer, Jian Gu, Harald C. Gall: On the Effectiveness of Transfer Learning for Code Search. IEEE Trans. Software Eng. 49(4): 1804-1822 (2023)[6]. Zhangyin Feng, Daya Guo, Duyu Tang, Nan Duan, Xiaocheng Feng, Ming Gong, Linjun Shou, Bing Qin, Ting Liu, Daxin Jiang, Ming Zhou: CodeBERT: A Pre-Trained Model for Programming and Natural Languages. EMNLP (Findings) 2020: 1536-1547[7]. Xue Jiang, Zhuoran Zheng, Chen Lyu, Liang Li, Lei Lyu: TreeBERT: A tree-based pre-trained model for programming language. UAI 2021: 54-63[8]. Daya Guo, Shuo Ren, Shuai Lu, Zhangyin Feng, Duyu Tang, Shujie Liu, Long Zhou, Nan Duan, Alexey Svyatkovskiy, Shengyu Fu, Michele Tufano, Shao Kun Deng, Colin B. Clement, Dawn Drain, Neel Sundaresan, Jian Yin, Daxin Jiang, Ming Zhou: GraphCodeBERT: Pre-training Code Representations with Data Flow. ICLR 2021[9]. Daya Guo, Shuai Lu, Nan Duan, Yanlin Wang, Ming Zhou, Jian Yin: UniXcoder: Unified Cross-Modal Pre-training for Code Representation. ACL (1) 2022: 7212-7225[10]. https://microsoft.github.io/CodeXGLUE/ ...

May 30, 2023 · 2 min · jiezi

关于java:为什么要用线程池

线程池是一种治理和复用线程资源的机制,它由一个线程池管理器和一组工作线程组成。线程池管理器负责创立和销毁线程池,以及治理线程池中的工作线程。工作线程则负责执行具体的工作。 线程池的次要作用是治理和复用线程资源,防止了线程的频繁创立和销毁所带来的开销。线程池蕴含两个重要的组成部分: 线程池大小:指线程池中所能包容的最大线程数。线程池大小个别依据零碎的负载状况和硬件资源来设置。工作队列:用于寄存期待执行的工作。当线程池中的工作线程曾经全副被占用时,新的工作将被退出到工作队列中期待执行。线程池创立形式Java中线程池的创立形式次要有以下几种: 应用 ThreadPoolExecutor 类手动创立:通过 ThreadPoolExecutor 类的构造函数自定义线程池的参数,包含外围线程数、最大线程数、线程存活工夫、工作队列等。应用 Executors 类提供的工厂办法创立:通过 Executors 类提供的一些动态工厂办法创立线程池,例如 newFixedThreadPool、newSingleThreadExecutor、newCachedThreadPool 等。应用 Spring 框架提供的 ThreadPoolTaskExecutor 类:在 Spring 框架中能够通过 ThreadPoolTaskExecutor 类来创立线程池。不同的创立形式实用于不同的场景,通常能够依据理论状况抉择适合的形式创立线程池。手动创立 ThreadPoolExecutor 类能够灵便地配置线程池参数,但须要对线程池的各项参数有肯定的理解;应用 Executors 工厂办法能够疾速创立线程池,但可能无奈满足特定的需要,且容易呈现内存溢出的状况;而 Spring 框架提供的 ThreadPoolTaskExecutor 类则只能在 Spring 框架中应用。 线程池应用ThreadPoolExecutor 应用ThreadPoolExecutor 线程的创立与应用示例如下: import java.util.concurrent.*;public class ThreadPoolDemo { public static void main(String[] args) { // 创立线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // 外围线程数 5, // 最大线程数 60, // 线程池中线程的闲暇工夫(单位为秒) TimeUnit.SECONDS, // 工夫单位 new ArrayBlockingQueue<>(10) // 工作队列 ); // 提交工作 for (int i = 1; i <= 20; i++) { final int taskId = i; executor.submit(() -> { System.out.println("执行工作:" + taskId + ",线程名称:" + Thread.currentThread().getName()); try { Thread.sleep(1000); // 模仿工作执行工夫 } catch (InterruptedException e) { e.printStackTrace(); } }); } // 敞开线程池 executor.shutdown(); }}在下面的示例中,咱们通过 ThreadPoolExecutor 类手动创立了一个线程池,设置了线程池的外围线程数为 2,最大线程数为 5,线程闲暇工夫为 60 秒,工作队列为长度为 10 的 ArrayBlockingQueue。而后咱们通过 submit() 办法向线程池中提交了 20 个工作,每个工作会在执行时输入本人的编号和执行线程的名称,而后睡眠1秒钟模仿工作执行工夫。最初,咱们调用 shutdown() 办法敞开线程池。 ...

May 30, 2023 · 2 min · jiezi

关于java:Java-on-Azure-开发工具路线图新发布

大家好,欢送来到Java on Azure工具产品的4月更新。让咱们首先来谈谈咱们对将来几个月的Java on Azure开发工具的投资。在这次更新中,咱们还将介绍Azure Service Bus反对和Azure Spring Apps入门模板加强性能。要应用这些新性能,请下载并装置用于IntelliJ IDEA 的Azure工具包。让咱们开始吧。 路线图更新咱们很快乐地发表咱们将来几个月的路线图。咱们的指标是为Java开发者提供一个易于应用的代码到云的旅程。上面这张图总结了咱们的投资畛域。 基于容器的服务反对随着容器技术在后端开发者社区中越来越风行,为开发者配置和治理容器资源须要破费大量的工夫和精力。为了帮忙Java开发者将他们的容器化利用轻松部署到Azure Kubernetes服务和Azure Container Apps服务,咱们打算改良和简化从构建镜像到在AKS/ACA上启动Java工作负载的用户旅程。此外,咱们还打算反对容器化服务的一系列要害性能,如监控和日志集成,以推动更轻松的故障排除体验。 与最新的Azure服务放弃同步咱们的下一个投资畛域是一直地与最新的Azure服务放弃同步。咱们将在工具中提供Azure Web App、Azure Functions、Azure Cosmos DB和集成其余Azure服务的最新性能,这将帮忙开发人员在IDE中更容易地治理和部署应用程序。咱们还打算在将来几个月内持续保护Azure Toolkit for Eclipse中的要害性能。 Azure Spring Apps用户体验优化咱们的下一个重点是Azure Spring Apps的性能 当开发人员在Spring应用程序上工作时,他们不能在部署期间间接在IDE中创立实例。他们须要切换到Azure Portal并期待服务配置。因而,咱们打算在IDE中间接启用实例创立,这将使开发人员可能留在IntelliJ IDEA中。此外,咱们将在Azure Toolkit for IntelliJ和VS Code中整合Azure Spring Apps的规范生产打算。对于Azure Spring Apps企业层,咱们还将在VS Code中集成利用加速器和利用实时视图,以提供端到端的内循环开发者体验。 命令行工具反对目前,咱们的命令行工具包含反对Azure Web Apps/Functions/Azure Spring Apps 的 Maven 插件和反对Azure Web Apps/Functions的 Gradle 插件。咱们打算在这些插件上反对新的Azure性能,如Azure的新SKU和其余最新性能。 入门体验加强更好的入门体验始终是咱们的首要任务之一。对于刚接触Azure的开发者来说,咱们了解他们在面对文档中的多个步骤和起源时,会感到不容易。咱们的指标是为初学者提供更好的入门体验。2022年,咱们在工具包中引入了指导性的入门体验,受到了开发人员的好评。咱们打算进一步改良它,并提供更多基于入门的模板。此外,咱们还打算反对Azure Functions 的本地性能执行。 故障排除体验的改良对于Azure上的Java开发人员来说,故障排除体验是一个必不可少的局部。目前咱们工具包中的日志剖析工具能够让开发人员查问Azure监控器收集的日志数据,但咱们一直听到有人问,他们心愿在IDE中的故障排除、调试、日志和指标方面有更多的监控和可察看性能。因而,咱们将对这个工具进行一些改良,让Azure Monitor在工具包中反对更多的服务,如Azure Kubernetes。 以利用为核心的开发体验对于目前在咱们的工具包中治理资源的工作流程,开发人员须要常常在我的项目视图和Azure Explorer之间切换。为了帮忙他们无效地治理这些服务,咱们之前进行了一些钻研,并打算很快在工具包中启用这种以利用为核心的体验,这将有助于开发人员在一个对立视图中治理和连贯资源,并轻松地将资源部署到云中。此外,咱们的指标是简化Azure服务之间的连贯,咱们也在钻研整合资源连接器服务。 最初但同样重要的是,咱们还打算更新和增强文档,为开发者带来更好的体验。此外,咱们将持续缩小错误率和服务故障,以提供更好的性能和可靠性。 Azure Toolkit for IntelliJ 加强Azure Toolkit for IntelliJ 加强Azure Service Bus 是一个齐全治理的多租户云信息服务,它在不肯定同时在线的利用和服务之间提供高度牢靠的异步云信息。欲了解更多细节。请浏览此文档。 ...

May 29, 2023 · 1 min · jiezi

关于java:AlibabaCloud组件版本说明

2022.X分支适配 Spring Boot 3.0,Spring Cloud 2022.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用标记): (留神,该分支 Spring Cloud Alibaba 版本命名形式进行了调整,将来将对应 Spring Cloud 版本,前三位为 Spring Cloud 版本,最初一位为扩大版本,比方适配 Spring Cloud 2022.0.0 版本对应的 Spring Cloud Alibaba 第一个版本为:2022.0.0.0,第个二版本为:2022.0.0.1,依此类推)* Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version2022.0.0.0-RC2*Spring Cloud 2022.0.03.0.22022.0.0.0-RC1Spring Cloud 2022.0.03.0.02021.x 分支适配 Spring Boot 2.4,Spring Cloud 2021.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记): Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version2021.0.5.0*Spring Cloud 2021.0.52.6.132021.0.4.0Spring Cloud 2021.0.42.6.112021.0.1.0Spring Cloud 2021.0.12.6.32021.1Spring Cloud 2020.0.12.4.22.2.x 分支适配 Spring Boot 为 2.4,Spring Cloud Hoxton 版本及以下的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记): ...

May 29, 2023 · 1 min · jiezi

关于java:单例模式

动态外部类实现单例模式原理解析https://www.jianshu.com/p/ef263cf7f7f9

May 29, 2023 · 1 min · jiezi

关于java:阿里一面MySQL-单表数据最大不要超过多少行为什么这样回答满分

起源:https://my.oschina.net/u/4090830/blog/5559454 1 背景作为在后端圈开车的多年老司机,是不是常常听到过,“mysql 单表最好不要超过 2000w”,“单表超过 2000w 就要思考数据迁徙了”,“你这个表数据都马上要到 2000w 了,难怪查问速度慢” 这些名言民语就和 “群里只探讨技术,不开车,开车速度不要超过 120 码,否则主动踢群”,只听过,没试过,哈哈。 上面咱们就把车速踩到底,干到 180 码试试……. 2 试验试验一把看看… 建一张表: CREATE TABLE person( id int NOT NULL AUTO_INCREMENT PRIMARY KEY comment '主键', person_id tinyint not null comment '用户id', person_name VARCHAR(200) comment '用户名称', gmt_create datetime comment '创立工夫', gmt_modified datetime comment '批改工夫') comment '人员信息表';插入一条数据: insert into person values(1,1,'user_1', NOW(), now());利用 mysql 伪列 rownum 设置伪列起始点为 1 select (@i:=@i+1) as rownum, person_name from person, (select @i:=100) as init;set @i=1;运行上面的 sql,间断执行 20 次,就是 2 的 20 次方约等于 100w 的数据;执行 23 次就是 2 的 23 次方约等于 800w , 如此上来即可实现千万测试数据的插入,如果不想翻倍翻倍的减少数据,而是想大量,大量的减少,有个技巧,就是在 SQL 的前面减少 where 条件,如 id > 某一个值去管制减少的数据量即可。 ...

May 29, 2023 · 3 min · jiezi

关于java:如何防御Java中的SQL注入

SQL注入是应用程序蒙受的最常见的攻打类型之一。鉴于其常见性及潜在的破坏性,须要在理解原理的根底上探讨如何爱护应用程序免受其害。 什么是SQL注入SQL注入(也称为SQLi)是指攻击者胜利篡改Web利用输出,并在该利用上执行任意SQL查问。此种攻打通常会利用编程语言用来括住字符串的转义字符。攻击者千方百计用表单字段或URL参数向利用注入额定的SQL代码进而取得在指标数据库上执行未经受权的操作的能力。 图1:SQL注入原理SQL注入的影响实现SQL注入的攻击者能够更改指标数据库中的数据。如果指标利用应用的数据库连贯字符串授予用户写入权限,SQL注入可能会造成重大毁坏:攻击者能够删除大量数据,甚至删除表自身。此外,即便攻击者只能取得对数据库的读取权限,也可能会导致敏感数据泄露,如财务信息或行业秘密等业务敏感信息,以及客户的私人信息等。随着隐衷法规越来越欠缺,数据泄露也是SQL注入最危险的结果之一。 Java中的SQL注入Java语言曾经存在了几十年。只管开发人员领有蕴含稳固的利用框架和牢靠的ORM的丰盛生态系统,仍不足以爱护Java免于SQL注入攻打。以Ruby为例。只管Rails是一个稳固的开发框架,然而SQL注入仍形成了Ruby利用70%的平安威逼。 以如下Java代码片段为例: String sql = "select "     + "id, title, excerpt, body"     + "from Posts where slug = '"      + slug       + "'";代码通过关联用户以某种形式输出的值(可能是URL参数)来组装SQL查问。 这段代码的问题在于通过用户提供的值进行关联。假如这个Web利用的基URL是 https://example.com/posts 如果咱们将my-first-java-project增加到URL中,它变为 example.com/posts/my-first-java-projec 相应的SQL代码会变为 select id, title, excerpt, body from Posts where slug = 'my-first-java-project'这段代码看起来仿佛没什么问题。进一步地,假如一个不太善意的用户将URL设置为 https://example.com/posts/whatever%27%20or%20%271%27=%271其中理论传递的参数是‘whatever’ or ‘1’=’1′ 得出的SQL代码是 select id, title, excerpt, body from Posts where slug = 'whatever' or '1'='1'当初攻击者曾经胜利注入了未经受权的代码。SQL查问的where子句有了一个判断' 1 '是否等于' 1 '的附加条件。鉴于1=1是真命题,所有POST申请都能够被取回。 这看起来不是什么大问题;但如果对象是敏感的客户信息,也即获取敏感信息只须要一点点SQL注入,问题就不容忽视了。 进攻Java SQL注入的技术只管SQL注入攻打很常见,而且具备潜在的破坏性,但它们并非无奈进攻。被利用的破绽大多源于编码谬误,改良方向有以下几种: 1.应用参数化查问针对Java中的SQL注入,能够从应用参数化查问动手。上面的例子基于前一节中提到的查问语句进行了改变 String sql = "select id, title, excerpt, body from Posts where slug = ?";用一个问号模式的占位符替换了关联信息。下一步是创立一个预编译语句,并给它绑定参数值 Connection connection = dataSource.getConnection();PreparedStatement p = c.prepareStatement(sql);p.setString(1, slug);通过应用参数化查问,咱们能够以一种平安的形式组装查问语句与用户提交的值。 2.容许列表输出验证这种办法是应用参数化查问的补充。白名单输出验证是指将输出限度为事后编译的已知有效值列表,并对其余输出进行拦挡。这包含应用正则表达式来验证某些类型的信息、验证数值参数是否合乎预期范畴以及查看参数是否合乎预期数据类型。倡议对所有类型的用户输出进行URL参数、表单字段、导入文件的内容等验证。 ...

May 29, 2023 · 1 min · jiezi

关于java:线程池是如何执行的任务太多会怎样

Java 面试不可能不问线程池,无论是大厂还是小厂。这不,前几天面试阿里时也被问到了这个问题,虽不难,但这里也零碎复盘一下。 要搞懂线程池的执行流程,最好的形式是去看它的源码,它的源码如下: public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); // 当前工作的线程数小于外围线程数 if (workerCountOf(c) < corePoolSize) { // 创立新的线程执行此工作 if (addWorker(command, true)) return; c = ctl.get(); } // 查看线程池是否处于运行状态,如果是则把工作增加到队列 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); // 再次检线程池是否处于运行状态,避免在第一次校验通过后线程池敞开 // 如果是非运行状态,则将刚退出队列的工作移除 if (! isRunning(recheck) && remove(command)) reject(command); // 如果线程池的线程数为 0 时(当 corePoolSize 设置为 0 时会产生) else if (workerCountOf(recheck) == 0) addWorker(null, false); // 新建线程执行工作 } // 外围线程都在忙且队列都已爆满,尝试新启动一个线程执行失败 else if (!addWorker(command, false)) // 执行回绝策略 reject(command);}从上述源码咱们能够看出,当工作来了之后,线程池的执行流程是:先判断以后线程数是否大于外围线程数?如果后果为 false,则新建线程并执行工作;如果后果为 true,则判断工作队列是否已满?如果后果为 false,则把工作增加到工作队列中期待线程执行,否则则判断以后线程数量是否超过最大线程数?如果后果为 false,则新建线程执行此工作,否则将执行线程池的回绝策略,如下图所示: ...

May 29, 2023 · 2 min · jiezi

关于java:小马哥Java分布式架构训练营第一期服务治理锦瑟无端五十弦

小马哥Java分布式架构训练营第一期服务治理download:3w zxit666 comJava分布式架构随着互联网技术的一直倒退,分布式架构逐步成为了大型利用程序开发的次要形式之一。Java作为一种常见的编程语言,在分布式应用程序的开发过程中也表演了重要的角色。在这篇文章中,咱们将深入探讨Java分布式架构的相干内容。 什么是Java分布式架构?Java分布式架构是指通过网络连接多个计算机以协同工作的架构。该架构的指标是实现无缝的数据交互和工作协同,以便进步零碎的可靠性、可扩展性和性能。 通常状况下,Java分布式架构须要思考以下几个方面: 网络连接:Java分布式架构须要通过网络连接不同的计算机,因而须要思考网络通信的稳定性、安全性等因素。数据传输:Java分布式架构须要实现数据在不同计算机间的传输,因而须要思考数据传输的速度和效率。工作协同:Java分布式架构须要实现不同计算机间的工作协同,因而须要思考任务分配和治理的形式。Java分布式架构的长处Java分布式架构有以下几个长处: 可扩展性:Java分布式架构能够通过增加更多的计算机节点来减少零碎的容量和吞吐量。可靠性:Java分布式架构中的每个节点都是互相独立的,因而即便某个节点解体或者呈现故障,零碎也可能失常运行。性能:Java分布式架构能够将不同任务分配到不同的计算机节点上执行,从而进步零碎的性能和响应速度。Java分布式架构的实现Java分布式架构的实现通常须要应用以下几个技术: Java Remote Method Invocation (RMI):Java RMI是Java平台提供的近程调用服务。应用Java RMI,能够轻松地在不同计算机间进行办法调用和数据传输。Java Message Service (JMS):Java JMS是一种用于消息传递的规范API。应用JMS,能够实现音讯队列、公布/订阅等性能。Java Naming and Directory Interface (JNDI):Java JNDI为Java应用程序提供了命名和目录服务。应用JNDI,能够实现不同计算机间的对象查找和绑定。除了以上技术之外,还有一些开源框架,如Apache Dubbo、Spring Cloud等,它们能够帮忙开发者疾速地搭建Java分布式应用程序。 Java分布式架构的挑战尽管Java分布式架构有很多长处,然而在理论开发过程中也会遇到一些挑战,例如: 网络通信:不同计算机节点间的网络通信可能会呈现提早、丢包等问题,因而须要应用一些技术来保障通信的稳定性和安全性。数据一致性:在分布式环境下,数据的一致性可能会呈现问题。开发者须要应用一些技术来确保数据的一致性。任务调度:在分布式环境下,任务调度可能变得更加简单。开发者须要应用一些技术来实现工作的调配和治理。论断Java分布式架构

May 28, 2023 · 1 min · jiezi

关于java:springMvc和mybatisplus中枚举值和字段的映射

最近看到有人应用这几个注解,就略微理解了一下各自的用法,发现枚举在前后台传值,DB和entity之间的映射很不便1.应用@JsonCreator,能够将前台的属性值间接转换为枚举类型2.@EnumValue 将枚举中的指定的值间接存储到数据库,不须要再手动转换3.@JsonValue 后盾返回前台数据时也不须要转换,能够间接返回指定的值

May 27, 2023 · 1 min · jiezi

关于java:Java革命性ORM框架Jimmer简单介绍

首发于Enaium的集体博客 本文应用Jimmer的官网用例来介绍Jimmer的应用办法,Jimmer同时反对Java和Kotlin,本文应用Java来介绍,实际上Kotlin比Java应用起来更不便,这里为了不便大家了解,应用Java来介绍,本篇文章只是对Jimmer的一个简略介绍,更多的内容请参考官网文档 这里开始就不从实体类开始介绍了,这里简略的把用到的三张表之间的关系介绍一下: BookStore书店 能够领有多个BookBook书 能够属于多个BookStore,能够有多个AuthorAuthor作者 能够领有多个Book,多对多书与作者的关系.查问Jimmer能够配合SpringData(不是SpringDataJPA),但这里先介绍脱离SpringData的应用办法,但还是在SpringBoot环境下,这里应用H2内存数据库,Jimmer反对H2,MySQL,PostgreSQL,Oracle等数据库,这里应用H2内存数据库. 这里的查问都应用Controller来演示. 查问所有书店createQuery就是创立一个查问,select就是抉择要查问的字段,这里间接传入了BookStoreTable示意查问所有字段. 这里用到的sql就是应用Jimmer的Sql对象,这个对象是Jimmer的外围对象,所有的查问都是通过这个对象来实现的,应用Spring的注入形式注入JSqlClient对象. final BookStoreTable bookStore = BookStoreTable.$;//这里的$是一个静态方法,返回一个BookStoreTable对象sql.createQuery(bookStore).select(bookStore).execute();查问后果如下: [ { "createdTime": "2023-05-27 11:00:37", "modifiedTime": "2023-05-27 11:00:37", "id": 1, "name": "O'REILLY", "website": null }, { "createdTime": "2023-05-27 11:00:37", "modifiedTime": "2023-05-27 11:00:37", "id": 2, "name": "MANNING", "website": null }]指定查问字段如何须要须要查问指定字段就能够这样,这里的name是BookStoreTable的一个字段,但这里的Controller返回的是BookStore对象,所以只如同下面的那样查问所有字段. sql.createQuery(bookStore).select(bookStore.name()).execute();像下面的例子中如果咱们非要查问指定字段又不想定义新的DTO对象,那么这种在Jimmer中也能够非常简单的实现,那就是应用Jimmer中的Fetchr 应用BookStore的Fetchr来指定查问的字段 sql.createQuery(bookStore).select(bookStore.fetch(BookStoreFetcher.$.name())).execute();查问后果如下: [ { "id": 2, "name": "MANNING" }, { "id": 1, "name": "O'REILLY" }]惊奇的发现,Controller的返回类型是BookStore,然而查问后果中只有id和name字段. 这里我把残缺的Controller代码贴出来,List的类型就是BookStore的实体类,这就是Jimmer的弱小之处,不须要定义DTO对象,就能够实现查问指定字段的性能. @GetMapping("/simpleList")public List<BookStore> findSimpleStores() { final BookStoreTable bookStore = BookStoreTable.$;//这里的$是一个静态方法,返回一个BookStoreTable对象 return sql.createQuery(bookStore).select(bookStore.fetch(BookStoreFetcher.$.name())).execute();}和实体类的Table一样,Fetcher也能够申明一个动态常量. ...

May 27, 2023 · 3 min · jiezi

关于java:Spring-Boot-URule-规则引擎可视化配置太爽了

作者:知了一笑\起源:juejin.cn/post/7210194936276680759 一、背景前段时间,在做我的项目重构的时候,遇到很多中央须要做很多的条件判断。当然能够用很多的if-else判断去解决,然而过后也不分明怎么回事,就想玩点别的。于是乎,就去调研了规定引擎。 当然,市面上有很多成熟的规定引擎,性能很多,性能很好。然而,就是想玩点不一样的(大家做技术选型别这样,这个是反面教材)。最终一款URule的规定引擎吸引了我,次要还是采纳浏览器可间接配置,不须要过多装置,可视化规定也做的不错。通过一系列调研,前面就把它接入了我的项目中,顺便记录下调研的后果。 二、介绍规定引擎其实是一种组件,它能够嵌入到程序当中。将程序简单的判断规定从业务代码中剥离进去,使得程序只须要关怀本人的业务,而不须要去进行简单的逻辑判断;简略的了解是规定承受一组输出的数据,通过预约好的规定配置,再输入一组后果。 当然,市面上有很多成熟的规定引擎,如:Drools、Aviator、EasyRules等等。然而URule,它能够运行在Windows、Linux、Unix等各种类型的操作系统之上,采纳纯浏览器的编辑模式,不须要装置工具,间接在浏览器上编辑规定和测试规定。 当然这款规定引擎有开源和pro版本的区别,至于pro版是啥,懂的都懂,上面放个表格,理解下具体的区别 个性PRO版开源版向导式决策集有有脚本式决策集有有决策树有有决策流有有决策表有有穿插决策表有无简单评分卡有无文件名、我的项目名重构有无参数名、变量常量名重构有无Excel决策表导入有无规定集模版保留与加载有无中文我的项目名和文件名反对有无服务器推送常识包到客户端性能的反对有无常识包优化与压缩的反对有无客户端服务器模式下大常识包的推拉反对有无规定集中执行组的反对有无规定流中所有节点向导式条件与动作配置的反对有无循环规定多循环单元反对有无循环规定中无条件执行的反对有无导入我的项目主动重命名性能有无规定树构建优化有无对象查找索引反对有无规定树中短路计算的反对有无规定条件冗余计算缓存反对有无基于计划的批量场景测试性能有无常识包调用监控有无更为欠缺的文件读写权限管制有无常识包版本控制有无SpringBean及Java类的热部署有无技术支持有无三、装置应用理论应用时,有四种应用URule Pro的形式,别离是嵌入式模式、本地模式、分布式计算模式以及独立服务模式。 然而咱们这里不思考URule Pro,咱本人整个开源版,在开源版集成springboot的根底上做一个二次开发,搜了一圈,其实就有解决方案。 大抵的我的项目模块如下: Spring Boot 根底就不介绍了,举荐看这个实战我的项目: https://github.com/javastacks/spring-boot-best-practice本人创立个空数据库,只须要在edas-rule-server服务中批改下数据库的配置,而后启动服务即可。第一次启动实现,数据库中会创立表。 spring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/urule-data?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=falsespring.datasource.username=rootspring.datasource.password=mysql下面说过,它是纯用浏览器进行编辑,配置规定的,只须要关上浏览器,输出地址:http://localhost:8090/urule/frame,看到这个界面,就阐明启动胜利了。 四、根底概念3.1整体介绍先说下URule它的形成局部,次要是两局部:1、设计器局部 2、规定执行引擎。设计器局部次要是库文件和规定文件形成。上面看下整体的结构图 3.2库文件如上图介绍的,库文件有4种,包含变量库,参数库,常量库和动作库。其实相似于Java开发的零碎中的实体对象,枚举,常量以及办法。 下面说过,规定都是可视化配置的。在配置规定的过程中,就须要引入各种曾经定义好的库文件,再联合业务需要,从而配置出合乎业务场景的业务规定,所以哪里都有库文件的身影。 3.2.1变量库文件在业务开发中,咱们会创立很多Getter和Setter的Java类,比方PO、VO、BO、DTO、POJO等等,其实这些类new对象后次要起到的作用就是数据的载体,用来传输数据。 在URule中,变量库就是用来映射这些对象,而后能够在规定中应用,最终实现业务和规定的互动。最初上一张图,用来创立变量库 对了,下面废话了这么多可视化配置,这才是第一次展现配置界面,羞愧羞愧。 上图高深莫测,在“库”这个菜单底下右键,而后点击增加变量库即可,最初定义本人喜爱的变量库名,当然名字只反对中文或者英文,其余字符不可用。 创立完变量库后,就能够对变量库进行编辑,能够认为就是给POJO增加属性 也不弯弯绕绕讲什么术语,就集体了解。图右边是创立类,其中名称是它的别名,配置规定用它代替这个类。图左边是类的属性,我这里轻易写了几个,预计看了懂得都懂。 最初在业务零碎中创立对应的类,留神全限定名和配置变量库的类门路统一。 package com.cicada;import com.bstek.urule.model.Label;import lombok.Data;/** * @author 往事如风 * @version 1.0 * @date 2023/3/3 15:38 * @description */@Datapublic class Stu { @Label("姓名") private String name; @Label("年龄") private int age; @Label("班级") private String classes;}最初说下这个@Label注解,这个是由URule提供的注解,次要是形容字段的属性,跟变量库的题目一栏统一就行。听官网介绍能够通过这个注解,实现POJO属性和变量库属性映射。就是POJO写好,而后对应规定的变量库就不须要从新写,能够间接生成。反正就有这个性能,这里就间接一笔带过了。 3.2.2常量库文件说到常量库,这个就能够认为是咱们Java零碎中的常量,枚举。比方性别,要定义枚举吧;比方对接的机构,也能够定义一个枚举吧。 当然,相似于变量库,常量库也能够实现和零碎中的枚举互相映射,这样做的益处能够防止咱们手动输出,避免输出谬误。创立常量库也比较简单,间接在“库”这个菜单下右键,“增加常量库”。 创立好常量库文件后,也会呈现如下页面: 3.2.3参数库文件参数库,就是URule规定中的长期变量,变量的类型和数量不固定。能够认为相似于Map,实际上存储参数库的也就是个Map。 同样的套路,间接在“库”这个菜单下右键,“增加参数库”。 ...

May 26, 2023 · 2 min · jiezi

关于java:图灵JAVA互联网架构师五期胡琴琵琶与羌笛

download:图灵JAVA互联网架构师五期量化交易开发流程:从策略构建到实盘操作的具体指南 导言: 量化交易作为一种基于算法的交易策略,通过系统性的办法和自动化的操作,为投资人提供更精准和更高无效的交易会。本文将具体介绍量化交易开发的流程,从策略构建到实盘操作,为读者提供一份全面的指南。 阶段落一:策略构建 量化交易的开发流程始于策略构建。这一步的要害是确定交易指标、抉择适合的市场和资产类别,并确定交易策略的公布和规定。交易策略能够基于技术剖析指标、根底面剖析、统计模型等多种办法。在策略构建过程中,须要进行大量的数据分析和回测,以评估策略的有效性和可行性性。 段落二:数据取得和解决 数据是量化交易的根底,精确、全面的数据对策略开发至关重要。在这一阶段,须要取得和解决各种市场数据,如股票价格、指数数据、财务报表等。数据能够通过第三方数据供应商、凋谢API、网络笨蛋等形式获取。在解决数据时,须要进行数据清理、去除异样常值、填充缺失值等预测解决操作,确保数据的品质和可用性。 段落三:策略回测和优化 策略回测是量化交易中至关重要的环。通过应用历史市场数据,模仿策略在过来的体现,评估其盈利能力和危险程度。在回测过程中,须要抉择实用的回测指标和评估指标,如收益率、冬季普比率、最大回输等,来评估策略的能力。如果策略体现以不佳,可持续进行参数优化和策略调整,一步步提降级策略的成果。 段落四:实盘交易执行阶段 一步策略通过回测和优化阶段,就能够进入实盘交易执行阶段。在这一阶段,须要抉择适宜的交易平台和券商,将策略与实盘交易系统连接起来。交易系统利用工具装备稳固的执行能力、疾速的交易速度和牢靠的风控机制。在实盘交易中,须要亲密关注策略的体现和市场变动,及时调整和优化策略,确保交易的成果和稳定性。

May 26, 2023 · 1 min · jiezi

关于java:Java-查找和替换-Excel-数据

Excel电子表格是贮存和解决数据的不二抉择。当数据内容过多时,咱们能够通过一些快捷工具来进行操作。“查找和替换”就是其中之一,比起手动搜寻和更新数据,这个性能能帮忙咱们在大型电子表格中疾速获取指标数据,并更改为新数据。Microsoft办公软件已提供了该性能,这里就不再赘述。明天想为大家分享的是如何通过代码来查找和替换数据(以Java代码为例)。应用到的是Free Spire.XLS for Java组件。示例代码和操作成果请参考以下内容。 程序环境IntelliJ IDEA 2018 (jdk 1.8.0)在进行操作之前先导入JAR包,请参考以下两种导入形式:办法一:如果您应用的是 maven,先创立maven我的项目。而后通过增加以下代码来配置pom.xml 文件,再点击Import Changes将 JAR文件导入到应用程序中。 <repositories> <repository> <id>com.e-iceblue</id> <name>e-iceblue</name> <url>https://repo.e-iceblue.cn/nexus/content/groups/public/</url> </repository></repositories><dependencies> <dependency> <groupId>e-iceblue</groupId> <artifactId>spire.xls.free</artifactId> <version>5.1.0</version> </dependency></dependencies>办法二:如果您没有应用 maven,则能够从此链接下载Free Spire.XLS for Java,找到lib文件夹下的Spire.XLS.jar并进行解压;而后在IDEA中创立一个新我的项目,顺次点击“文件”(File),“我的项目构造”(Project Structure),“组件”(Modules),“依赖项”(Dependencies),再点击右方绿色“+”下的第一个选项“JAR文件或门路”(JARs or Directories),找到解压后的Spire.XLS.jar 文件,点击确认,将其导入到我的项目中。 代码解释:首先创立一个Workbook实例,再应用Workbook.loadFromFile办法加载示例文档。调用Workbook.getWorksheets().get()办法来获取指定工作表。Worksheet.findAllString()和CellRange.setText办法别离反对查找和替换指定文档。最初再通过Workbook.saveToFile()办法保留后果文档。 示例代码:import com.spire.xls.CellRange;import com.spire.xls.ExcelVersion;import com.spire.xls.Workbook;import com.spire.xls.Worksheet;public class ReplaceData { public static void main(String[] args){ //创立Workbook实例 Workbook workbook = new Workbook(); //加载Excel示例文档 workbook.loadFromFile("sample.xlsx"); //获取第一个工作表 Worksheet worksheet = workbook.getWorksheets().get(0); //在工作表中查找指定的文字 CellRange[] ranges = worksheet.findAllString("个别", true, true); for (CellRange range : ranges) { //替换为新文字 range.setText("一般"); } //保留后果文档 workbook.saveToFile("ReplaceData.xlsx", ExcelVersion.Version2013); }}效果图: ...

May 26, 2023 · 1 min · jiezi

关于java:Fastjson-很快但不适合我

作者:nyingping\起源:juejin.cn/post/7215886869199863869 记者:大爷您有什么专长呀? FastJson:我很快。 记者:23423 乘以 4534 等于多少? FastJson:等于 2343. 记者:?? FastJson:你就说快不快吧! 这个略显马丽苏的题目,各位看官将就着看吧。次要是怕被喷。FastJson 真的很好,我用不必我喜不喜欢的,太不重要了,我只是感觉不适宜我而已。 话说以前 Gson 用得好好的,共事极力推荐我应用 FastJson,说很快云云。只管咱们的零碎基本感知不进去这点速度差别。 之前也据说 FastJson 爆进去什么重大破绽,但对咱们根本没什么影响,所以这一点倒是没什么偏见。 而后在一个新我的项目上,脑抽抽,把 Gson 换成了 FastJson,Spring Boot 默认反对的 Jackson 换成了 FastJson。 而后就开始遇到了一些问题。先申明,这真不是尬黑,为了文章成果,成心网上扒些黑料拼凑起来,本文所提到的问题,都来源于自己最近我的项目的实在经验。 举荐一个开源收费的 Spring Boot 最全教程: https://github.com/javastacks/spring-boot-best-practicedateformat 优先级原本是一个风和日丽的下午,一个非常简单的改变需要。接口返回的工夫只须要年月日日期类型不须要时分秒。因为我配置全局工夫格式化为yyyy-MM-dd HH:mmss,于是我欢快的在 javabean 的属性上加了个注解。 本地测试一下,没问题,提交到测试环境,搞定,完满。 而后就接到产品的疑难,改变呢? 我登上去看了一下,唉,没改到啊,日期还是带了时分秒。我粗心了啊,这么小的改变,又是在测试环境,就没加验证。 那么当初的间接问题是:FastJson 对于工夫配置在部分的配置没有失效,应用的还是全局配置。 景象是,开发环境 Windows 上没有问题,测试环境 Linux 上呈现了问题。两者有什么区别呢?零碎问题? 既然狐疑是两个零碎导致的问题,那么就在 idea 里模仿一下 linux 零碎。在 VM options 增加 -Dos.name=linux 这不能齐全模仿 linux 零碎,只针对通过System.getproperty("os.name")来判断以后零碎做某些操作的时候有用。通过这种形式没复现,我又想到了近程调试。 一阵操作猛如虎,近程调试倒是能进断点,只是断点进不了第三方 jar 包的源码。等于白搞。 得,还是回到源码吧。拉下源码,断点,察看 JSONSerializer 类,次要是writeWithFormat办法。没有发现问题。 因为狐疑是零碎导致的,在源码中搜寻'linux''unix'关键字,没有发现。断点整个流程重点察看了一下这部份也没有发现问题。 ...

May 26, 2023 · 2 min · jiezi

关于java:聊聊短信渠道的设计与实现

有多久,没有发过短信了?一、背景简介在惯例的分布式架构下,「音讯核心」的服务里通常会集成「短信」的渠道,作为信息触达的重要伎俩,其余罕用的伎俩还包含:「某微」、「某钉」、「邮件」等形式; 对于《音讯核心》的设计和实现来说,在后面曾经具体的总结过,本文重点来聊聊音讯核心的短信渠道的形式; 短信在实现的逻辑上,也遵循音讯核心的根底设计,即音讯生产之后,通过音讯核心进行投递和生产,属于典型的生产生产模型; 二、渠道方对接在大部分的零碎中,短信性能的实现都依赖第三方的短信推送,之前总结过《三方对接》的教训,这里不再赘述; 然而与惯例第三方对接不同的是,短信的渠道通常会对接多个,从而应答各种音讯投递的场景,比方常见的「验证码」场景,「告诉揭示」场景,「营销推广」场景; 这里须要思考的外围因素有好几个,比方老本问题,短信平台的稳定性,时效性,触达率,并发能力,须要进行不同场景的综合考量; 验证码:该场景通常是用户和产品的要害交互环节,非常依赖短信的时效性和稳定性,如果出问题间接影响用户体验; 告诉揭示:该场景同样与业务联系亲密,然而相对来说对短信触达的时效性依赖并不高,只有在肯定的工夫范畴内最终触达用户即可; 营销推广:该场景的数据量比拟大,并且从实际效果来看,具备很大的不确定性,会对短信渠道的老本和并发能力重点考量; 三、短信渠道1、流程设计从整体上来看短信的实现流程,能够分为三段:「1」短信需要的业务场景,「2」音讯核心的短信集成能力,「3」对接的第三方短信渠道; 需要场景:在产品体系中,须要用到短信的场景很多,不过最次要的还是对用户方的信息触达,比方身份验证,告诉,营销等,其次则是对内的重要音讯告诉; 音讯核心:提供音讯发送的对立接口办法,不同业务场景下的音讯提交到音讯核心,进行对立保护治理,并依据音讯的起源和去向,适配相应的推送逻辑,短信只是作为其中的一种形式; 渠道对接:依据具体的需要场景来定,如果只有验证码的对接需要,能够只集成一个渠道,或者从老本方面兼顾思考,对接多个第三方短信渠道,倡议设计时思考肯定的可扩大; 2、外围逻辑单从短信这种形式的治理来看,逻辑复杂度并不算很高,然而很依赖细节的解决,很多不留神的轻微点都可能导致推送失败的状况; 理论在整个逻辑中,除了「验证码」性能有时效性依赖之外,其余场景的短信触达都能够抉择「MQ队列」进行解耦,在音讯核心的设计上,也具备很高的流程复用性,图中只是重点形容短信场景; 3、应用场景3.1 验证码对于「短信」性能中的「验证码」场景来说,个人感觉在惯例的利用中是最简单的,这可能会波及到「账户」和相干「业务」的集成问题; 【验证码获取】 这个流程相对来说门路还比拟简短,只有实现手机号的校验后,依照短信推送逻辑失常执行即可; 这里须要阐明的是,为了确保零碎的安全性,通常会设定验证码的时效性,并且只能应用一次,然而偶然可能因为延时问题,引起用户屡次申请验证码,基于缓存能够很好的治理这种场景的数据结构; 【验证码生产】 验证码的应用是非常简单的,当初很多产品在设计上,都弱化了登录和注册的概念,只有通过验证码机制,会默认的新建帐户和执行相干业务流程; 无论是何种业务场景下的「验证码」依赖,在解决流程时都要先校验其「验证码」的正确与否,能力判断流程是否向下执行,在局部敏感的场景中,还会限度验证码的谬误次数,防止出现账户平安问题; 3.2 短信触达无论是「告诉揭示」还是「营销推广」,其本质上是谋求信息的最终触达即可,大部分短信运营商都能够提供这种能力,只是零碎外部的解决形式有很大差别; 在局部业务流程中,须要向用户投递短信音讯,在营销推广的需要中,更多的是批量发送短信,局部需要其外部逻辑上,还可能存在一个转化率统计的问题,须要监控相干短信的交互状态; 四、模型设计因为短信是集成在音讯核心的服务中,其相干的数据结构模型都是复用音讯治理的,具体细节形容,参考《音讯核心》的内容即可,此处不赘述; 从技术角度来看的话,波及经典的生产生产模型,第三方平台对接,工作和状态机治理等,音讯核心作为分布式架构的根底服务,在设计上还要思考肯定的复用性。 五、参考源码编程文档:https://gitee.com/cicadasmile/butte-java-note利用仓库:https://gitee.com/cicadasmile/butte-flyer-parent

May 26, 2023 · 1 min · jiezi

关于java:系统设计快速粗略计算系统容量和性能需求

原文题目是"Back-of-the-envelope estimation",直译是信封反面估算的意思,"Back-of-the-envelope estimation"是一个短语,用于形容应用简化的假如和基本原理进行的粗略或疾速计算,通常在信封反面或任何可用的纸上进行。它是一种在不进行详细分析或简单计算的状况下进行粗略预计或近似的办法。 信封反面估算的目标是提供一个大抵数字或对概念的规模或可行性有个大抵的理解,而无需投入大量工夫或资源进行准确计算。它可用于评估一个想法的可行性,评估决策的潜在影响,或疾速比拟不同选项。 尽管信封反面估算可能不足详细分析的精确性,但它们对于疾速决策、启动进一步考察或以扼要易懂的形式传播思维是有价值的。在零碎设计面试中,你有时会被要求应用信封反面估算来评估零碎容量或性能需求。依据谷歌高级研究员杰夫·迪恩的说法,“信封反面的计算是你利用思维试验和常见性能数字组合创立的估算,以便对哪些设计将满足你的需要有一个好的了解”[1]。 你须要有对可扩展性根底的良好了解,以无效地进行信封反面估算。以下概念应该失去充沛了解:二的力量[2],每个程序员应该晓得的提早数字,以及可用性数字。 欢送关注我的公众号:更AI。第一工夫理解前沿行业音讯、分享深度技术干货、获取优质学习资源二的力量尽管在解决分布式系统时,数据量可能会变得十分大,但所有的计算都归结为根本的计算。为了失去正确的计算结果,晓得以二的幂来示意的数据量单位至关重要。一个字节是8个比特的序列。一个ASCII字符应用一个字节的内存(8比特)。上面是一个解释数据量单位的表格(表2-1)。 每个程序员都应该晓得的提早数字谷歌的迪恩博士揭示了2010年典型计算机操作的长度[1]。随着计算机变得更快、更弱小,一些数字曾经过期。然而,这些数字依然应该可能让咱们对不同计算机操作的快慢有个大抵的理解。 正文 ns = 纳秒,s = 微秒,ms = 毫秒1 ns = 10^-9 秒1 s= 10^-6 秒 = 1,000 ns1 ms = 10^-3 秒 = 1,000 s = 1,000,000 ns 一位谷歌软件工程师建设了一个工具来可视化迪恩博士的数字。这个工具也将工夫因素思考在内。图2-1显示了截至2020年的可视化提早数字(图源:参考资料[3])。 通过剖析图2-1中的数字,咱们失去以下论断: 内存速度快,但磁盘速度慢。尽可能防止磁盘寻址。简略的压缩算法速度快。如果可能,压缩数据后再通过互联网发送。数据中心通常位于不同地区,发送数据之间须要工夫。可用性数字高可用性是一个零碎可能间断运行一个冀望的长时间段的能力。高可用性以百分比掂量,其中100%示意服务没有停机工夫。大多数服务的可用性在99%到100%之间。 服务级别协定(SLA)是服务提供商罕用的术语。这是你(作为服务提供商)与你的客户之间的协定,这个协定正式定义了你的服务将提供的运行工夫程度。云服务提供商Amazon [4],Google [5]和Microsoft [6]将他们的SLA设定在99.9%或以上。运行工夫传统上以九为单位掂量。九的数量越多,体现越好。如表2-3所示,九的数量与预期的零碎停机工夫相干。 示例:估算Twitter的QPS和存储需要请留神,以下数字仅用于此练习,因为它们并非来自Twitter的实在数字。 假如: 有3亿月沉闷用户。50%的用户每天应用Twitter。用户均匀每天公布2条推文。10%的推文蕴含媒体内容。数据存储5年。估算: 每秒查问数(QPS)估算: 每日沉闷用户(DAU)= 300 million * 50% = 1.5亿推文QPS = 1.5亿 * 2 条推文 / 24小时 / 3600秒 = ~3500峰值QPS = 2 * QPS = ~7000咱们只在这里估算媒体存储。 ...

May 25, 2023 · 1 min · jiezi

关于java:项目终于用上了-Spring-状态机非常优雅

起源:https://www.duidaima.com/Group/Topic/JAVA/11942 1、什么是状态机1.1 什么是状态先来解释什么是“状态”( State )。事实事物是有不同状态的,例如一个自动门,就有 open 和 closed 两种状态。咱们通常所说的状态机是无限状态机,也就是被形容的事物的状态的数量是无限个,例如自动门的状态就是两个 open 和 closed 。 状态机,也就是 State Machine ,不是指一台理论机器,而是指一个数学模型。说白了,个别就是指一张状态转换图。例如,依据自动门的运行规定,咱们能够形象出上面这么一个图。 自动门有两个状态,open 和 closed ,closed 状态下,如果读取开门信号,那么状态就会切换为 open 。open 状态下如果读取关门信号,状态就会切换为 closed 。 状态机的全称是无限状态自动机,主动两个字也是蕴含重要含意的。给定一个状态机,同时给定它的以后状态以及输出,那么输入状态时能够明确的运算进去的。例如对于自动门,给定初始状态 closed ,给定输出“开门”,那么下一个状态时能够运算进去的。 这样状态机的根本定义咱们就介绍结束了。反复一下:状态机是无限状态自动机的简称,是事实事物运行规定形象而成的一个数学模型。 1.2 四大概念上面来给出状态机的四大概念。 第一个是 State ,状态。一个状态机至多要蕴含两个状态。例如下面自动门的例子,有 open 和 closed 两个状态。第二个是 Event ,事件。事件就是执行某个操作的触发条件或者口令。对于自动门,“按下开门按钮”就是一个事件。第三个是 Action ,动作。事件产生当前要执行动作。例如事件是“按开门按钮”,动作是“开门”。编程的时候,一个 Action个别就对应一个函数。第四个是 Transition ,变换。也就是从一个状态变动为另一个状态。例如“开门过程”就是一个变换。1.3 状态机无限状态机(Finite-state machine,FSM),又称无限状态自动机,简称状态机,是示意无限个状态以及在这些状态之间的转移和动作等行为的数学模型。 FSM是一种算法思维,简略而言,无限状态机由一组状态、一个初始状态、输出和依据输出及现有状态转换为下一个状态的转换函数组成。 其作用次要是形容对象在它的生命周期内所经验的状态序列,以及如何响应来自外界的各种事件。 举荐一个开源收费的 Spring Boot 实战我的项目: https://github.com/javastacks/spring-boot-best-practice2、状态机图做需要时,须要理解以下六种元素:起始、终止、现态、次态(指标状态)、动作、条件,咱们就能够实现一个状态机图了: 以订单为例:以从待领取状态转换为待发货状态为例 ①现态:是指以后所处的状态。待领取②条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁徙。领取事件③动作:条件满足后执行的动作。动作执行结束后,能够迁徙到新的状态,也能够仍旧放弃原状态。动作不是必须的,当条件满足后,也能够不执行任何动作,间接迁徙到新状态。状态转换为待发货④次态:条件满足后要迁往的新状态。“次态”是绝对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。待发货 注意事项1、防止把某个“程序动作”当作是一种“状态”来解决。那么如何辨别“动作”和“状态”?“动作”是不稳固的,即便没有条件的触发,“动作”一旦执行结束就完结了;而“状态”是绝对稳固的,如果没有内部条件的触发,一个状态会始终继续上来。 2、状态划分时漏掉一些状态,导致跳转逻辑不残缺。所以在设计状态机时,咱们须要重复的查看设计的状态图或者状态表,最终达到一种颠扑不破的设计方案。 3、spring statemachine3.1 状态机spring statemachine 概述Spring Statemachine是应用程序开发人员在Spring应用程序中应用状态机概念的框架 Spring Statemachine旨在提供以下性能: 易于应用的扁平单级状态机,用于简略的应用案例。分层状态机构造,以简化简单的状态配置。状态机区域提供更简单的状态配置。应用触发器,转换,警卫和操作。键入平安配置适配器。生成器模式,用于在Spring Application上下文之外应用的简略实例化通常用例的食谱基于Zookeeper的分布式状态机状态机事件监听器。UML Eclipse Papyrus建模。将计算机配置存储在永恒存储中。Spring IOC集成将bean与状态机关联起来。状态机功能强大,因为行为始终保障统一,使调试绝对容易。这是因为操作规定是在机器启动时写成的。这个想法是你的应用程序可能存在于无限数量的状态中,某些预约义的触发器能够将你的应用程序从一个状态转移到另一个状态。此类触发器能够基于事件或计时器。 ...

May 25, 2023 · 9 min · jiezi

关于java:Flink消费kafka数据打包

flink介绍Flink是一个框架和分布式解决引擎,用于对无限度和有限度的数据留进行有状态的计算。Flink被设计为可在所有常见的集群环境中运行,以内存速度和任何规模执行计算。解决无界和有界数据任何类型的数据都是作为事件流产生的。信用卡交易,传感器测量,机器日志或网站挪动应用程序上的用户交互,所有这些数据均作为流生成。Flink 功能强大,反对开发和运行多种不同品种的应用程序。它的次要个性包含:批流一体化、精细的状态治理、事件工夫反对以及准确一次的状态一致性保障等。在启用高可用选项的状况下,它不存在单点生效问题。事实证明,Flink 曾经能够扩大到数千外围,其状态能够达到 TB 级别,且仍能放弃高吞吐、低提早的个性。世界各地有很多要求严苛的流解决利用都运行在 Flink 之上。外围点:1、高吞吐,低提早2、后果的准确性3、准确一次的状态一致性保障4、高可用,反对动静扩大依赖 <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-java</artifactId> <version>1.8.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-streaming-java_2.11</artifactId> <version>1.8.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-clients_2.11</artifactId> <version>1.8.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-connector-kafka_2.11</artifactId> <version>1.8.1</version> </dependency> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency>Flink生产Kafka数据package com.kafka;import lombok.extern.slf4j.Slf4j;import org.apache.flink.api.common.functions.MapFunction;import org.apache.flink.api.common.serialization.SimpleStringSchema;import org.apache.flink.streaming.api.datastream.DataStreamSource;import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;import org.apache.kafka.clients.CommonClientConfigs;import org.apache.kafka.common.config.SaslConfigs;import java.util.ArrayList;import java.util.List;import java.util.Properties;@Slf4jpublic class Flink { public static void main(String[] args) { try { //TODO 1、初始化flink流解决的运行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); //TODO 2、创立数据源 Properties properties = new Properties(); //封装kafka的连贯地址 properties.setProperty("bootstrap.servers", "127.0.0.1:9092"); //指定消费者id properties.setProperty("group.id", "consumer-group"); //设置动静监测分区或者主题的变动 properties.setProperty("flink.partition-discovery.interval-millis", "30000"); //配置security.protocol properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_PLAINTEXT"); //配置sasl.mechanism// properties.put(SaslConfigs.SASL_MECHANISM, "PLAIN"); properties.put(SaslConfigs.SASL_MECHANISM, "SCRAM-SHA-256"); //配置sasl.jaas.config properties.put(SaslConfigs.SASL_JAAS_CONFIG, "org.apache.kafka.common.security.scram.ScramLoginModule required username=\"账号\" password=\"明码\";");// 生产主题// 生产多个主题 List<String> topicList = new ArrayList<>(); topicList.add("OGG_TEST.T_OGGO_FB");// topicList.add("OGG_TEST.T_OGG_FB");// topicList.add("OGG_TEST.T_OGGO_EB");// topicList.add("OGG_TEST.T_OGG_EB");// topicList.add("OGG_TEST.T_OGGO_DB");// topicList.add("OGG_TEST.T_OGG_DB"); FlinkKafkaConsumer<String> kafkaConsumer = new FlinkKafkaConsumer<>(topicList, new SimpleStringSchema(), properties);// KafkaConsumer.setStartFromEarliest():从topic的最早offset地位开始解决数据,如果kafka中保留有消费者组的生产地位将被疏忽。// KafkaConsumer.setStartFromLatest():从topic的最新offset地位开始解决数据,如果kafka中保留有消费者组的生产地位将被疏忽。// KafkaConsumer.setStartFromTimestamp(…):从指定的工夫戳(毫秒)开始生产数据,Kafka中每个分区中数据大于等于设置的工夫戳的数据地位将被当做开始生产的地位。如果kafka中保留有消费者组的生产地位将被疏忽。// KafkaConsumer.setStartFromGroupOffsets():默认的设置。依据代码中设置的group.id设置的消费者组,去kafka中或者zookeeper中找到对应的消费者offset地位生产数据。如果没有找到对应的消费者组的地位,那么将依照auto.offset.reset设置的策略读取offset。 //读取kafka数据的时候须要指定生产策略,如果不指定会应用auto.offset.reset设置// kafkaConsumer.setStartFromEarliest(); kafkaConsumer.setStartFromLatest(); DataStreamSource<String> dataStreamSource = env.addSource(kafkaConsumer); dataStreamSource.map(new MapFunction<String, String>() { @Override public String map(String value) throws Exception { log.info("kafka数据:" + value); return "Flink生产kafka数据" + value; } }).print(); //TODO 5、调用execute办法触发程序执行 env.execute(); } catch (Exception e) { e.printStackTrace(); } } }打包放flink中执行1、配置打包2、配置打包3、配置打包4、配置打包5、打包6、打包7、上传8、配置启动 ...

May 25, 2023 · 1 min · jiezi

关于java:Java-亿级项目架构设计与落地应用完结渚清沙白鸟飞回

download:Java 亿级我的项目架构设计与落地利用完结架构设计与落地 随着技术的一直倒退,软件开发也越来越简单。而架构的重要性在这个畛域中变得越来越突出。一个好的架构能够使得软件开发更加高效、可保护和可扩大,并且合乎用户需要。然而如何将架构设计落地,实现真正的胜利呢? 一、什么是架构设计? 架构设计(Architecture Design)是指为了达成肯定指标而对系统或者工程进行的高层次设计。它旨在使得零碎更加稳固、灵便、平安、扩展性强,同时可能满足用户需要。 架构设计通常包含以下几个方面: 系统结构:确定零碎的整体构造,包含软件组件、硬件设施以及它们之间的关系等。 数据架构:确定如何存储和解决数据,包含数据库、数据流以及数据传输等。 网络架构:确定网络拓扑、协定和安全策略等。 利用架构:确定应用程序的分层架构、组件架构以及模块化设计等。 平安架构:确定安全策略,包含身份验证、访问控制、加密和审计等。 二、架构设计的重要性 好的架构设计能够进步软件开发效率,并且使得软件更加具备可维护性和可扩展性。以下是几个方面的具体长处: 进步开发效率:一个好的架构可能使得开发人员更疾速地编写代码,缩小反复工作。 缩小保护老本:当零碎须要更新或者保护时,一个好的架构可能使得这个过程更加顺利和高效。 进步零碎稳定性:通过正当的架构设计,能够升高零碎出错的概率,从而进步零碎的稳定性。 改善用户体验:一个好的架构可能使得零碎更加易用和用户敌对,从而晋升用户的满意度。 三、如何落地架构设计? 只管架构设计在软件开发中十分重要,但它仅仅是开始。真正的挑战在于将架构设计落地,实现真正的胜利。以下是一些关键步骤: 确定指标:在开始施行架构设计之前,必须确定指标。这些指标可能包含进步性能、缩小老本、改善用户体验等。 参加团队:架构设计必须是一个团队致力的后果。因而,所有相干人员都应该参加到这个过程中来。 明确需要:确定用户和业务需要,从而为架构设计提供方向。 抉择适合的技术:在施行架构设计之前,必须抉择最合适的技术,包含编程语言、框架、数据库等。 建设测试计划:建设一个具体的测试计划,以确保架构设计符合要求。 实施方案:依照架构设计计划进行施行,并且在整个过程中一直监控和调整。 迭代优化:架构设计并非变化无穷,须要一直迭代和优化,以满足变动的需要。 四、如何评估架构设计? 架构设计的评估能够帮忙查看是否达到了预期成果。以下是几个要害指标: 可扩展性:架构设计是否具备可扩展性,是否疾速地响应变动的需要。 性能:零碎的性能是否满足了预期的需要。 可维护性:零碎是否容易保护和更新。 安全性:零碎是否具备正当的安全策略,是否避免安全漏洞。 用户体验:零碎是否易用和用户敌对。 总之,架构设计是软件开发中十分重要的一个方面。通过正当的架构设计,能够进步开发效率,升高保护老本,改善用户体验,并且进步零碎的稳定性。然而架构设计仅仅是开始,真正的挑战在于将架构设计落地,实现真正的胜利。

May 25, 2023 · 1 min · jiezi

关于java:ConcurrentHashMap是如何实现的

家喻户晓 ConcurrentHashMap 是 HashMap 的多线程版本,HashMap 在并发操作时会有各种问题,比方死循环问题、数据笼罩等问题。而这些问题,只有应用 ConcurrentHashMap 就能够完满解决了,那问题来了,ConcurrentHashMap 是如何保障线程平安的?它的底层又是如何实现的? ConcurrentHashMap 线程平安实现简述ConcurrentHashMap 在 JDK 1.7 时,应用的是分段锁也就是 Segment 来实现线程平安的。 然而它在 JDK 1.8 之后,应用的是 CAS + synchronized 或 CAS + volatile 来实现线程平安的。 JDK 1.7 底层构造ConcurrentHashMap 在不同的 JDK 版本中实现是不同的,在 JDK 1.7 中它应用的是数组加链表的模式实现的,而数组又分为:大数组 Segment 和小数组 HashEntry。 大数组 Segment 能够了解为 MySQL 中的数据库,而每个数据库(Segment)中又有很多张表 HashEntry,每个 HashEntry 中又有多条数据,这些数据是用链表连贯的,如下图所示: JDK 1.7 线程平安实现理解了 ConcurrentHashMap 的底层实现,再看它的线程平安实现就比较简单了。 接下来,咱们通过增加元素 put 办法,来看 JDK 1.7 中 ConcurrentHashMap 是如何保障线程平安的,具体实现源码如下: final V put(K key, int hash, V value, boolean onlyIfAbsent) { // 在往该 Segment 写入前,先确保获取到锁 HashEntry<K,V> node = tryLock() ? null : scanAndLockForPut(key, hash, value); V oldValue; try { // Segment 外部数组 HashEntry<K,V>[] tab = table; int index = (tab.length - 1) & hash; HashEntry<K,V> first = entryAt(tab, index); for (HashEntry<K,V> e = first;;) { if (e != null) { K k; // 更新已有值... } else { // 搁置 HashEntry 到特定地位,如果超过阈值则进行 rehash // 疏忽其余代码... } } } finally { // 开释锁 unlock(); } return oldValue;}从上述源码咱们能够看出,Segment 自身是基于 ReentrantLock 实现的加锁和开释锁的操作,这样就能保障多个线程同时拜访 ConcurrentHashMap 时,同一时间只有一个线程能操作相应的节点,这样就保障了 ConcurrentHashMap 的线程平安了。 ...

May 25, 2023 · 2 min · jiezi

关于java:尚硅谷2023年java就业班阶段10完结升堂坐阶新雨足

download:尚硅谷2023年java待业班阶段10完结音视频根底 - 从采集到传输前言随着互联网的倒退,音视频技术曾经成为了人们日常生活中不可或缺的一部分。本文将介绍从音视频的采集、编码、传输和播放等方面来深刻了解音视频技术。 音视频采集音视频采集是指将声音和图像转换成数字信号的过程。在计算机中,通常应用麦克风和摄像头来进行音视频采集。采集后的数据须要通过解决能力用于后续的编码和传输。 音视频编码音视频编码是指将采集失去的音视频数据进行压缩的过程。在理论利用中,因为音视频数据量宏大,如果不进行压缩,将会占用大量存储空间和网络带宽。因而,须要应用一些编码器对音视频数据进行压缩。常见的音视频编码格局包含MP3、AAC、H.264和HEVC等。 音视频传输音视频传输是指将编码后的音视频数据通过网络传输到接收端的过程。在传输过程中,须要思考网络带宽、提早和丢包等问题。为了进步传输效率和升高提早,通常采纳一些专门的传输协定,如RTMP、HLS和WebRTC等。 音视频播放音视频播放是指在接收端将传输过去的音视频数据进行解码和播放的过程。在进行解码和播放时,须要思考硬件设施的性能和操作系统的反对状况。 总结本文介绍了音视频技术的采集、编码、传输和播放等方面的基础知识。通过深刻了解音视频技术的整个流程,咱们能够更好地利用音视频技术,并且在理论利用中能够更好地解决各种问题。 FFmpeg原理 - 实现音视频解决前言FFmpeg是一个开源的音视频解决库,它能够对音视频文件进行格局转换、剪辑、合并等操作。本文将介绍FFmpeg的基本原理和应用办法。 FFmpeg的基本原理FFmpeg蕴含了多个音视频解决工具,其中最外围的局部是libavcodec和libavformat两个库。libavcodec提供了各种音视频编码器和解码器,能够将不同格局的音视频文件进行相互转换。而libavformat提供了各种音视频文件的输出和输入格局反对,能够读取和写入各种音视频文件。 FFmpeg的应用办法应用FFmpeg进行音视频解决非常简单,只须要通过命令行输出相应的参数即可。上面是一个简略的例子: ffmpeg -i input.mp4 -vf "transpose=1" -an output.mp4该命令能够将input.mp4文件进行逆时针旋转90度后输入为output.mp4文件,并且去掉了音频轨道。 除了通过命令行应用FFmpeg外,也能够通过调用FFmpeg提供的API来进行音视频解决。例如,要将一段MP3格局的音频文件转换为WAV格局,能够应用以下代码: include <libavutil/avutil.h>include <libavcodec/avcodec.h>include <libavformat/avformat.h>int main(int argc, char *argv[]) { av_register_all();AVFormatContext *fmt_ctx = NULL;int ret = avformat_open_input(&fmt_ctx, argv[1], NULL, NULL);if (ret < 0) { return ret;}ret = avformat_find_stream_info(fmt_ctx, NULL);if (ret < 0) { return ret;}int audio_stream_index = -1;for (int i = 0; i < fmt_ctx->nb_streams; ++i) { if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { audio_stream_index = i; break; }}AVCodecParameters *codec_par = fmt_ctx->streams[audio_stream_index]->codecpar;AVCodec *codec = avcodec_find_decoder(codec_par->codec_id);AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);ret = avcodec_parameters_to_context(codec_ctx, codec_par);if (ret < 0) { return ret;}ret = avcodec_open2(codec_ctx, codec, NULL);if (ret < 0) { return ret;}AVPacket pkt;av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;AVFrame *frame = av_frame_alloc();while (av_read_frame(fmt_ctx, &pkt) >= 0) { if (pkt.stream_index == audio_stream_index) { ret = avcodec_send_packet(codec_ctx, &pkt); if (ret < 0) { break; } while (ret >= 0) { ret = avcodec_receive_frame(codec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { break; } // 对音频帧进行解决,此处省略具体代码 } } av_packet_unref(&pkt);}avcodec_free_context(&codec_ctx);avformat_close_input(&fmt_ctx);return 0;}总结本文介绍了FFmpeg的基本原理和应用办法。通过深刻理解FFmpeg的API,咱们能够更加灵便地进行音视频解决,并且在理论利用中可能更好地满足各种需要。 ...

May 24, 2023 · 1 min · jiezi

关于java:Netty简介及ByteBuf组件原理

Netty是什么Netty 是由 JBOSS 提供的一个Java开源框架。Netty提供异步的、基于事件驱动的网络应用程序框架,用以疾速开发高性能、高可靠性的网络 IO 程序,是目前最风行的NIO框架,Netty在互联网畛域、大数据分布式计算畛域、游戏行业、通信行业等取得了宽泛的利用,出名的Elasticsearch 、Dubbo框架外部都采纳了 Netty。 为什么应用NettyJavaNIO 的缺点 NIO的类库和API繁冗,应用麻烦,你须要熟练掌握Selector、 ByteBuffer ServerSocketChannel、SocketChannel 等。须要具备其它的额定技能做铺垫,例如相熟Java多线程编程,因为NIO编程波及到Reactor模式,你必须对多线程和网络编程十分相熟,能力编写出高质量的NIO程序。可靠性能力补齐,开发工作量和难度都十分大。例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异样码流的解决等等,NIO编程的特点是性能开发绝对容易,然而可靠性能力补齐工作量和难度都十分大。JDK NIO的BUG,例如epoll bug,它会导致Selector空轮询,最终导致CPU 100%。官网宣称在JDK1.6版本的update18修复了该问题,然而直到JDK1.7版本该问题仍旧存在,只不过该bug产生概率升高了一些而已,它并没有被基本解决。 Netty的长处从以下几个方面形容应用简略:封装了NIO的很多细节,应用更简略; 功能强大:预置了多种编解码性能,反对多种支流协定; 定制能力强:能够通过ChannelHandler对通信框架进行灵便的扩大; 性能高:通过与其余业界支流的NIO框架比照,Netty的综合性能最优; 稳固:Netty修复了曾经发现的NIO的bug,让开发人员能够专一于业务自身; 社区沉闷:Netty是沉闷的开源我的项目,版本迭代周期短,bug修复速度快。 Netty 的线程模型Netty采纳的线程模型是Reactor线程模型。Reactor模型,是指通过一个或多个输出同时传递给服务处理器的服务申请的事件驱动解决模式。服务端程序处理传入多路申请,并将它们同步分派给申请对应的解决线程。 Reactor模式也叫Dispatcher模式,即I/O多了复用对立监听事件,收到事件后散发(Dispatch)给某过程,是编写高性能网络服务器的必备技术之一。 Reactor模型中有2个要害组件 Reactor在一个独自的线程中运行,负责监听和散发事件,分发给适当的处理程序来对IO事件做出反馈。它就像公司的电话接线员,它接听来自客户的电话并将线路转移到适当的联系人。Handlers处理程序执行I/O事件要实现的理论事件,相似于客户想要与之交谈的公司中的理论官员。Reactor通过调度适当的处理程序来响应I/O事件,处理程序执行非阻塞操作。 Netty的Reactor的具体实现:Netty通过Reactor模型基于多路复用器接管并解决用户申请,外部实现了两个线程池,boss线程池和work线程池,其中boss线程池的线程负责解决申请的accept事件,当接管到accept事件的申请时,把对应的socket封装到一个NioSocketChannel 中,并交给work线程池,其中work线程池负责申请的read和write事件,由对应Handler解决。其中MainReactor负责客户端的连贯申请,并将申请转交给SubReactor。SubReactor负责相应通道的IO读写申请。非IO申请(具体逻辑解决)的工作则会间接写入队列,期待worker threads进行解决。Netty的组件Bootstrap、ServerBootstrap:Bootstrap意思是疏导,一个Netty利用通常由一个Bootstrap开始,次要作用是配置整个Netty程序,串联各个组件,Netty中Bootstrap类是客户端程序的启动疏导类,ServerBootstrap是服务端启动疏导类。Future、ChannelFuture:在Netty中所有的IO操作都是异步的,不能立即得悉音讯是否被正确处理,然而能够过一会等它执行实现或者间接注册一个监听,具体的实现就是通过Future和ChannelFutures,他们能够注册一个监听,当操作执行胜利或失败时监听会主动触发注册的监听事件。Selector :Netty基于Selector对象实现I/O多路复用,通过 Selector,一个线程能够监听多个连贯的Channel事件,当向一个Selector中注册Channel 后,Selector 外部的机制就能够主动一直地查问(select) 这些注册的Channel是否有已就绪的I/O事件(例如可读,可写,网络连接实现等),这样程序就能够很简略地应用一个线程高效地治理多个 Channel 。ChannelHandler:是一个接口,解决I/O事件或拦挡I/O操作,并将其转发到其ChannelPipeline中的下一个处理程序。ChannelHandler自身并没有提供很多办法,因为这个接口有许多的办法须要实现,方便使用期间能够继承它的子类,如下: ChannelInboundHandler用于解决入站I/O事件;ChannelOutboundHandler用于解决出站I/O操作。 或者应用以下适配器类: ChannelInboundHandlerAdapter用于解决入站I/O事件;ChannelOutboundHandlerAdapter用于解决出站I/O操作。 ChannelHandlerContext:保留Channel相干的所有上下文信息,同时关联一个ChannelHandler对象;ChannelPipline:保留ChannelHandler的List,用于解决或拦挡Channel的入站事件和出站操作。ChannelPipeline实现了一种高级模式的拦挡过滤器模式,使用户能够齐全管制事件的解决形式,以及Channel中各个的ChannelHandler如何互相交互。read操作从head往tail,write操作从tail往head **ByteBuf组件JavaNIO提供了缓存容器(ByteBuffer),然而应用简单。因而Netty引入缓存ButeBuf,一串字节数组形成。ByteBuf的个性: 池化 - 能够重用池中ByteBuf实例,更节约内存,缩小内存溢出的可能;读写指针拆散,不须要像 ByteBuffer 一样切换读写模式;能够主动扩容;反对链式调用,应用更晦涩;很多中央体现零拷贝,例如 slice、duplicate、CompositeByteBuf。 ByteBuf提供了两个指针变量来反对程序读取和写入操作----读取操作的readerIndex和写入操作的writerIndex。下图显示了如何通过两个指针将缓冲区分为三个区域: | 可抛弃字节 | 可读字节 | 可写入字节 | (内容) |0 <= readerIndex <= writerIndex <= 容量可读字节 (理论内容)通过调用discardReadBytes()来抛弃读取的字节以回收未应用的区域。能够应用mark和reset重置readIndex索引和writerIndex索引,来反复读取目标。扩容规定:如果写入后数据大小未超过 512,则抉择下一个 16 的整数倍,例如写入后大小为 12 ,则扩容后 capacity 是 16;如果写入后数据大小超过 512,则抉择下一个 2^n-1之前的容量,扩容不能超过max capacity会报错。ByteBuf依据内存类型分类:基于间接内存的ByteBuf(默认)和基于堆内存的ByteBuf。ByteBuf buffer = ByteBufAllocator.DEFAULT.heapBuffer(10);//基于堆内存ByteBuf buffer = ByteBufAllocator.DEFAULT.directBuffer(10);//基于堆外内存ByteBuf实现池化:没有池化,每次都创立新的 ByteBuf 实例,这个操作对间接内存代价低廉,就算是堆内存,也会减少 GC 压力。通过重用 ByteBuf 实例,并且采纳了与 jemalloc 相似的内存调配算法晋升调配效率,高并发时,池化性能更节约内存,缩小内存溢出的可能。池化性能是否开启,能够通过上面的零碎环境变量来设置-Dio.netty.allocator.type={unpooled|pooled} //4.1当前对于非安卓平台默认池化,安卓平台非池化。 ...

May 24, 2023 · 1 min · jiezi

关于java:Spring-Boot-我随手封装了一个万能的-Excel-导出工具传什么都能导出

前言如题,这个小玩意,就是不限度你查的是哪张表,用的是什么类。 我间接一把梭,嘎嘎给你一顿导出。 我晓得,这是很多人都想过的, 至多我就收到很多人问过我这个相似的问题。 我也跟他们说了,然而他们就是不入手,其实真的很简略。 不入手怎么办? 我出手呗。 不多说开搞 。 注释玩法很简略。 要实现的成果 : 类是不确定的 ,User ?Student ? District ? 不确定。 然而呢咱们封装进去的函数,要足够撑持不同的类,咱们主动去读取遍历list ,而后导出生成文件。 外围的思路是什么 ? 其实就还是利用csv文件的内容格局实质 ,看这两幅图 : 咱们要实现万能的类导出excel !!!思路是什么 : ① 咱们从不确定的类 的汇合list 中,取出 外面的类。反射一手,拿出外面的属性名, 做第一行表格行题目名称拼接。 ②拼接内容因为类不确定,那么咱们就采取反射把类全副字段属性作为key丢到map外面,同时把值丢到value外面。 这样咱们拼接内容的时候只须要依据map 嘎嘎一顿遍历拼接即可。 举荐一个开源收费的 Spring Boot 最全教程: https://github.com/javastacks/spring-boot-best-practice1.依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.15</version></dependency><dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>3.15</version></dependency><dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.69</version></dependency><dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version></dependency>2. 外围的工具类,函数我都封装好了 MyCsvFileUtil.java import lombok.extern.slf4j.Slf4j;import org.apache.commons.io.IOUtils;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.text.SimpleDateFormat;import java.util.*;/** * @author JCccc * @Remark 是我 */@Slf4jpublic class MyCsvFileUtil { public static final String FILE_SUFFIX = ".csv"; public static final String CSV_DELIMITER = ","; public static final String CSV_TAIL = "\r\n"; protected static final String DATE_STR_FILE_NAME = "yyyyMMddHHmmssSSS"; /** * 将字符串转成csv文件 */ public static void createCsvFile(String savePath, String contextStr) throws IOException { File file = new File(savePath); //创立文件 file.createNewFile(); //创立文件输入流 FileOutputStream fileOutputStream = new FileOutputStream(file); //将指定字节写入此文件输入流 fileOutputStream.write(contextStr.getBytes("gbk")); fileOutputStream.flush(); fileOutputStream.close(); } /** * 写文件 * * @param fileName * @param content */ public static void writeFile(String fileName, String content) { FileOutputStream fos = null; OutputStreamWriter writer = null; try { fos = new FileOutputStream(fileName, true); writer = new OutputStreamWriter(fos, "GBK"); writer.write(content); writer.flush(); } catch (Exception e) { log.error("写文件异样|{}", e); } finally { if (fos != null) { IOUtils.closeQuietly(fos); } if (writer != null) { IOUtils.closeQuietly(writer); } } } /** * 构建文件名称 * @param dataList * @return */ public static String buildCsvFileFileName(List dataList) { return dataList.get(0).getClass().getSimpleName() + new SimpleDateFormat(DATE_STR_FILE_NAME).format(new Date()) + FILE_SUFFIX; } /** * 构建excel 题目行名 * @param dataList * @return */ public static String buildCsvFileTableNames(List dataList) { Map<String, Object> map = toMap(dataList.get(0)); StringBuilder tableNames = new StringBuilder(); for (String key : map.keySet()) { tableNames.append(key).append(MyCsvFileUtil.CSV_DELIMITER); } return tableNames.append(MyCsvFileUtil.CSV_TAIL).toString(); } /** * 构建excel内容 * @param dataLists * @return */ public static String buildCsvFileBodyMap(List dataLists) { //不论你传什么玩意,我都给你反射一手,搞成Map List<Map<String, Object>> mapList = new ArrayList<>(); for (Object o : dataLists) { mapList.add(toMap(o)); } //而后利用csv格局,对着map嘎嘎一顿拼接数据 StringBuilder lineBuilder = new StringBuilder(); for (Map<String, Object> rowData : mapList) { for (String key : rowData.keySet()) { Object value = rowData.get(key); if (Objects.nonNull(value)) { lineBuilder.append(value).append(MyCsvFileUtil.CSV_DELIMITER); } else { lineBuilder.append("--").append(MyCsvFileUtil.CSV_DELIMITER); } } lineBuilder.append(MyCsvFileUtil.CSV_TAIL); } return lineBuilder.toString(); } /** * 类转map * @param entity * @param <T> * @return */ public static<T> Map<String, Object> toMap(T entity){ Class<? extends Object> bean = entity.getClass(); Field[] fields = bean.getDeclaredFields(); Map<String, Object> map = new HashMap<>(fields.length); for(Field field:fields){ try { if(!"serialVersionUID".equals(field.getName())){ String methodName = "get"+field.getName().substring(0, 1).toUpperCase()+field.getName().substring(1); Method method = bean.getDeclaredMethod(methodName); Object fieldValue = method.invoke(entity); map.put(field.getName(),fieldValue); } } catch (Exception e) { log.warn("toMap() Exception={}",e.getMessage()); } } return map; }}代码留神点(各种小封装): ...

May 24, 2023 · 3 min · jiezi