关于java:面试必问RabbitMQ-有哪几种消息模式

原文:juejin.cn/post/6998363970037874724 前言Rabbitmq 是应用 Erlang 语言开发的开源音讯队列零碎,基于 AMQP 实现,是一种应用程序对应用程序的通信办法,应用程序通过读写出入队列的音讯来通信,而无需专用连贯来链接它们。消息传递指的是应用程序之间通过在音讯中发送数据进行通信,而不是通过间接调用彼此通信,间接调用通常是指近程过程调用的技术。 外围组成 Server:又称 Broker,接管客户端的连贯,实现 AMQP 实体服务,装置 rabbitmq-serverConnection:连贯,应用程序与Broker的网络连接TCP/IP/三次握手和四次挥手Channel:网络信道,简直所有操作都在 Channel 中进行,Channel 是进行音讯读写的通道,客户端能够建设多个 Channel,每个 Channel 代表一个会话工作。Message:音讯,服务与应用程序之间传送的数据,由 Properties 和 Body 组成,Properties 能够对音讯进行润饰,比方音讯的优先级,提早等高级个性,Body 则是音讯体的内容。Virtual Host:虚拟地址,用于进行逻辑隔离,最上层的音讯路由,一个虚拟主机能够有若干个 exchange 和 queue,同一个虚拟主机外面不能有雷同名称的 exchangeExchange:交换机,接管音讯,依据路由键发送音讯到绑定的队列(不具备音讯存储能力)Bindings:exchange 和 queue 之间的虚构连贯,binding 中能够保留多个 routing keyRouting key:是一个路由规定,虚拟机能够用它来确定如何路由一个特定音讯Queue:队列,也称为 Message Queue,音讯队列,保留音讯并将它们转发给消费者Rabbitmq 音讯模式3.1 Simple 模式 Simple 模式是最简略的一个模式,由一个生产者,一个队列,一个消费者组成,生产者将音讯通过交换机(此时,图中并没有交换机的概念,如不定义交换机,会应用默认的交换机)把音讯存储到队列,消费者从队列中取出音讯进行解决。 用 Java demo 实现此模式,举荐一个开源收费的 Spring Boot 最全教程: https://github.com/javastacks/spring-boot-best-practiceProductor public class Send { private final static String QUEUE_NAME = "queue1"; public static void main(String[] args) { // 1、创立连贯工程 ConnectionFactory factory = new ConnectionFactory(); factory.setHost("192.168.96.109"); factory.setVirtualHost("/"); Connection connection = null; Channel channel = null; try { // 2、创立连贯、通道 connection = factory.newConnection(); channel = connection.createChannel(); // 3、申明队列 channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 音讯内容 String message = "Hello world"; // 4、发送音讯到指定队列 channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8)); System.out.println(" [x] Sent '" + message + "'"); } catch (TimeoutException | IOException e) { e.printStackTrace(); } finally { // 敞开通道 if (channel != null && channel.isOpen()) { try { channel.close(); } catch (Exception e) { e.printStackTrace(); } } // 敞开连贯 if (connection != null && connection.isOpen()) { try { connection.close(); } catch (Exception e) { e.printStackTrace(); } } } }}Customer ...

May 24, 2023 · 7 min · jiezi

关于java:被问懵了什么是负载因子为什么是075

前几天面试被问懵了,还是对于 HashMap 的面试题,什么是负载因子?为什么是0.75?第一个问题还好答复,然而第二个问题就有点含糊其辞说不清楚了,所以明天就来好好复盘一下这道题。 HashMap 负载因子 load factor,也叫做扩容因子和装载因子,它是 HashMap 在进行扩容时的一个阈值,当 HashMap 中的元素个数超过了容量乘以负载因子时,就会进行扩容。默认的负载因子是 0.75,也就是说当 HashMap 中的元素个数超过了容量的 75% 时,就会进行扩容。当然,咱们也能够通过构造函数来指定负载因子,如下所示: 扩容计算公式HashMap 扩容的计算公式是:initialCapacity * loadFactor = HashMap 扩容。其中,initialCapacity 是初始容量,默认值为 16(懒加载机制,只有当第一次 put 的时候才创立),loadFactor 是负载因子,默认值为 0.75。也就是说当 16 * 0.75 = 12 时,HashMap 就会开始扩容。 为什么要进行扩容?HashMap 扩容的目标是为了缩小哈希抵触,进步 HashMap 性能的。 为什么默认负载因子是 0.75?HashMap 负载因子 loadFactor 的默认值是 0.75,为什么是 0.75 呢?官网给的答案是这样的: As a general rule, the default load factor (.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the lookup cost (reflected in most of the operations of the HashMap class, including get and put). The expected number of entries in the map and its load factor should be taken into account when setting its initial capacity, so as to minimize the number of rehash operations. If the initial capacity is greater than the maximum number of entries divided by the load factor, no rehash operations will ever occur.下面的意思,简略来说是默认负载因子为 0.75,是因为它提供了空间和工夫复杂度之间的良好均衡。 ...

May 24, 2023 · 2 min · jiezi

关于java:从零开始用Java-实现Parser-Combinator

引言什么是Parser CombinatorParser Combinator是函数式语言中的概念,它是一种通过组合小型解析器来构建简单解析器的技术。其中Parser是把输出数据(通常是文本)转换成特定数据结构的函数或者对象。Parser接管一个字符串(或者字节流)作为输出,尝试依据预约义的规定对其进行解析,最终返回胜利或者失败的后果。Combinator是组合器,它是一些用于组合各种Parser的函数。 Parser Combinator的劣势与劣势Parser Combinator的劣势是它具备十分高的可读性和灵活性,可读性体现在它对解析对象的语法形容十分的直观,灵活性体现它能够得心应手的组合。 Parser Combinator的劣势在于它的性能会比专门的解析器(例如应用Flex/Bison生成的解析器)差,易用性和性能难以兼得。 为什么要用Java来实现第一,我的工作是一个Java程序员;第二,文本解析或者语法解析的在日常中需要比拟多;第三,大部分的解析工作对性能的要求不会太高,好用且易读的Parser Combinator十分有应用价值;第四,目前没有找到好用的Parser Combinator的实现。 函数式语言中的Parser Combinator以haskell中的parsec为例。假如有一个解析格式化之后的工夫字符串的需要,格式化之后的工夫是这样的:2023-05-01 12:30:30,应用parsec来解析这个工夫字符串的代码能够这样写: -- 定义解析的指标数据结构data Time = Time { year :: Int , month :: Int , day :: Int , hour :: Int , minute :: Int , second :: int }-- 解析整数的解析器anyInt :: Parser IntanyInt = read <$> many1 (satisfy isDigit)-- 指标解析器,通过组合anyInt 和 char函数实现timeParser :: Parser TimetimeParser = Time <$> anyInt << char '-' <*> anyInt << char '-' <*> anyInt << char ' ' <*> anyInt << char ':' <*> anyInt << char ':' <*> anyInt即便没学过haskell的人也能够领会到应用Parser Combinator带来的那种直观感。再举个解析解析一行csv数据的例子: ...

May 23, 2023 · 6 min · jiezi

关于java:Spring-Boot-31-正式发布王炸

Spring Boot 3.1 正式公布大家好,我是R哥。 上一篇:Spring Boot 3.0 正式公布,王炸!! Spring Boot 3.0 公布半年左右,Spring Boot 3.1 正式公布了: 同时公布更新的还有 2.7.x 版本,同时,R哥留神到 2.6.x 版本线曾经进行保护了,最新反对版本如下图所示: 2.7.x 这也是目前惟一正在保护的 2.x 版本线了,商业反对的版本也只有 2.5.x 了。 如果你还没用过 Spring Boot,这里举荐下R哥的《Spring Boot 3 核心技术与最佳实际》最新书籍,包含底层实现原理及代码实战,知识点十分齐全,助你疾速买通 Spring Boot 的各个环节。 Spring Boot 3.0 重大新个性R哥看了下,Spring Boot 3.1 更新了不少内容,明天R哥就简略分享下几个重要的更新。 1、最低环境要求Spring Boot 3.0 的公布,其最低要求 Java 17,并向上兼容反对 Java 19,Spring Boot 3.1 能够反对 Java 20 了,因为前段时间 Java 20 公布了。 对 Java 开发环境的要求比照表: Spring BootJDKSpringMavenGradle3.1.017 ~ 206.0.9+3.6.3+7.5+,8.x3.0.017 ~ 196.0.2+3.5+7.5+2.7.128 ~ 205.3.27+3.5+6.8.x, 6.9.x, 7.x, 8.x2、大量依赖降级Spring Boot 3.1 最低反对的 Spring 框架也变成了 Spring 6.0.9+,除此之外,Spring Boot 治理的大量第三方的技术依赖也有大幅度的的降级,具体能够参考官网版本公布文档: ...

May 23, 2023 · 2 min · jiezi

关于java:自动化回归测试平台-AREX-Agent-源码再阅读

AREX 启动过程通用 Java Agent 的启动过程Java Agent 是一种 Java 应用程序,它能够在 Java 应用程序启动时动静地注入到 JVM 中,并在利用程序运行时监督和批改应用程序的行为。Java Agent 通常用于性能剖析、代码覆盖率、安全检查等方面。 以下是 Java Agent 的启动过程: 编写 Java Agent 程序,实现 premain 办法。premain 办法是 Java Agent 的入口办法,它会在 Java 应用程序启动时被调用。在 premain 办法中,能够进行一些初始化操作,如设置代理、加载配置文件等。将 Java Agent 打包成 jar 文件,并在 MANIFEST.MF 文件中指定 Premain-Class 属性,该属性指定了 Java Agent 的入口类。在启动Java应用程序时,通过 -javaagent 参数指定 Java Agent 的 jar 文件门路。例如: java -javaagent:/path/to/agent.jar -jar myapp.jar在下面的命令中,/path/to/agent.jar 是 Java Agent 的 jar 文件门路,myapp.jar 是 Java 应用程序的 jar 文件门路。 当 Java 应用程序启动时,JVM 会加载 Java Agent 的 jar 文件,并调用 premain 办法。在 premain 办法中,Java Agent 能够应用 Java Instrumentation API 来批改 Java 应用程序的字节码,实现对应用程序的监督和批改。AREX 源码视角的启动过程步骤一在arex-agent module 的pom.xml文件中,通过配置manifestEntries,将Premain-Class属性设置为io.arex.agent.ArexJavaAgent。这意味着在构建arex-agent.jar时,将在manifest文件中指定ArexJavaAgent类作为 Agent 的入口点。 ...

May 23, 2023 · 3 min · jiezi

关于java:数据分片库内分表实践

序因为疫情不再进行防控,我的项目的根本业务是扫码乘坐公交车,订单表的增量相比过来有了较大的减少, 目前零碎中存在订单表保留3个月的数据,数据在1300W左右,按当初日增数据为30W,月增量为900W 那么将来某个时刻的数据会达到峰值2700W(3个月),整体数据量翻倍增长。 剖析与实际前置常识分库分表 垂直分表程度分表垂直分库程度分库概念以字段为根据,依照活跃度,将表中的数据拆分到不同表(主表和子表)以字段为根据,依照肯定的策略,将一个表中的数据拆分到多个表中以表为根据,依照业务归属不同将不同表拆分到不同库中以字段为根据,依照肯定策略,将一个库中的数据拆分到多个库中后果每个表的构造,数据都不同,子表存在和主表的关联字段;相干的表的并集是全量数据每个表的构造雷同,数据不同;所有表的并集是全量数据;每个库的构造,数据不同;所有库的并集是全量数据;每个库的构造雷同,数据不同;所有库的并集是全量数据;场景零碎并发量不大,表的字段多,单行数据空间占用大,表中字段存在热点和非热点数据;零碎并发量不大,仅是单表数据过多,影响了SQL效率,减轻CPU累赘;零碎并发量较大,业务模块划分清晰;零碎并发量较大,分表难以解决问题;图示罕用架构模式分库分表架构次要有两种模式:client 客户端模式 和 proxy 代理模式 客户模式client模式指分库分表的逻辑都在你的零碎利用外部进行管制,利用会将拆分后的SQL直连多个数据库进行操作,而后本地进行数据的合并汇总等操作。 代理模式proxy代理模式将应用程序与MySQL数据库隔离,业务方的利用不在须要直连数据库,而是连贯proxy代理服务,代理服务实现了MySQL的协定,对业务方来说代理服务就是数据库,它会将SQL散发到具体的数据库进行执行,并返回后果。该服务内有分库分表的配置,依据配置主动创立分片表。 区别 客户模式代理模式性能性能方面体现的稍好一些,它是间接连贯MySQL执行命令代理服务则将整个执行链路缩短了,利用->代理服务->MySQL,可能导致性能有一些损耗复杂度在开发应用通常引入一个jar能够须要搭建独自的服务,有肯定的保护老本,既然是服务那么就要思考高可用,毕竟利用的所有SQL都要通过它转发至MySQL降级分库分表个别是依赖基础架构团队的Jar包,一旦有版本升级或者Bug批改,所有利用到的我的项目都要跟着降级小规模的团队服务少降级问题不大,如果是大公司服务规模大,且波及到跨多部门,那么降级一次老本就比拟高在降级方面劣势很显著,公布新性能或者修复Bug,只有重新部署代理服务集群即可,业务方是无感知的,但要保障公布过程中服务的可用性治理,监控因为是内嵌在利用内,利用集群部署不太不便对立解决在对SQL限流、读写权限管制、监控、告警等服务治理方面更优雅一些。开源组件sharding-jdbc ,zebrasharding-jdbc,MyCAT,DBProxy,cobar,Atlas目前状况依据序中论述的内容将来的订单表寄存三个月的数据将会寄存2700W左右的数据量甚至更多,数据量上单表曾经存在了一些压力,数据库RDS零碎中查问到的慢SQL中存在订单表的慢查问,但剖析上数据库语句曾经无奈优化了;订单表作为业务的外围表来说曾经做了 冷热数据拆散(即针对3个月之前的数据进行数据归档寄存到订单备份表中);业务存在显著的高峰期,但基于MQ做了削峰填谷,不会呈现连接数不够;基于上述剖析:仅仅是单表内数据量过大,且针对目前的体量来说,对订单表数据分片进行库内程度分表是一种比拟适合的形式。 问题剖析根本方向已确定,那么接下来就是针对库内分表所要面临的问题进行剖析。 程度分表以字段为根据,那么哪个字段作为分表的键比拟适合?程度分表具体要分多少张表?分片算法或者说分片策略是什么?业务革新计划?数据如何平滑迁徙? 抉择分片键对上述问题咱们先看下第一个问题 程度分表以字段为根据,那么哪个字段作为分表的键比拟适合?思考的因素次要有哪些?既然是对订单表分片,那么首先剖析下订单表的字段,订单实质上是一种交易单方的合约,那么必然存在买方和卖方,字段上蕴含如下: oid:order_id 订单表id或订单号uid:user_id 用户idmid:merchant_id 商户idprice,time等其余字段 这里的买方是用户,花钱买公交服务,卖方是公交公司,提供公交车营运的业务。其次咱们再剖析下业务场景,通过具体业务场景来具体分析解决方案。 谁在用这个零碎?他们的查问维度是什么?零碎用户大体上可分为两类:用户侧 经营侧,用户侧蕴含乘客(用户)和公交公司(商户),经营侧蕴含 产品经理、经营、开发等。用户侧的查问需要仅仅是查问本人相干的数据,并发量大,且对服务查问品质容忍度低;经营侧的查问需要是查问大多是多个商户的数据,并发量低,且对服务查问品质绝对较高。罕用查问需要: 用户侧 乘客 订单列表:依据 uid 查问本人肯定创立工夫内的订单列表订单详情:依据 oid 查问具体订单公交公司 订单列表:多维度(工夫,线路,设施等)依据mid查问商户的订单列表订单详情:依据oid查问具体订单经营侧: 管理员 订单列表:后盾多维度,多条件的分页查问基于上述咱们来看一下依照各个字段来作为分片键会产生什么样的成果? 字段解决的问题未解决的问题uid依据uid进行分片,查问中存在uid的sql可能疾速查问,如查问乘客订单列表等等没有uid的查问则须要通过其余办法来进行查问oid依据oid进行分片,查问中存在oid的sql可能疾速查问,如查问订单详情等等没有oid的查问则须要通过其余办法来进行查问mid依据mid进行分片,查问中存在mid的sql可能疾速查问,如查问商户订单列表等等没有mid的查问则须要通过其余办法来进行查问time依据time进行分片,查问中存在time的sql可能疾速查问,如管理员查看的订单列表等没有time的查问则须要通过其余办法来进行查问从上述的剖析表格当中能够显著看出,无论抉择哪个字段作为分片键都会存在如果该查问不存在该分片键,那么这个查问都会须要通过其余办法来进行解决,存在肯定局限性。这个其余办法通常有哪些呢? 遍历法 遍历所有数据分片的表进行查问索引表法 所须要查问的字段与分片键建设关联关系,在查问之前先查问关系再定位到对应的分片,毛病则是须要多查问一次缓存映射法 同样是建设查问须要的字段与分片键建设关联关系,若不存在则通过遍历法获取而后放到cache,之后间接通过cache来查问对应关系,毛病依然是须要多查问一次基因法 是指将某个字段融入到分片键中,比方oid中融入uid,这样通过uid或者oid都能通过疾速匹配到对应数据分片抉择这个分片键,哪些因素是咱们须要思考的? 业务优先级 为什么要剖析查问需要,就是要确定哪些查问是重要的,哪些查问是能够斗争的字段可变性 分片键是不可扭转的,如果能够变动,就会呈现数据存在但查问不到的状况业务优先级通常是用户侧比拟重要,毕竟是客户起源,其次咱们这个零碎实质是个saas零碎,那么对应的优先级最高的应该是用户侧中的商户,且零碎中大部分的查问都存在mid这个字段,所以抉择mid作为咱们的分片键是比拟适合的,假如是2c的业务,那么抉择uid作为分片键也是比拟常见的计划;对于字段可变性来说,上述抉择的分片键都是不可变的,所以都是能够抉择的。既然抉择了mid作为分片键,尽管对于用户侧(商户)的查问是比拟不便的,然而对于用户侧(乘客)的查问就不那么不便,用户侧(乘客)又是间接应用公司小程序的,如果查问迟缓必然会引起一些客诉等等。因为是库内分表,且零碎中对于用户侧(乘客)的查问较少且查问根本为oid+uid或独自为uid,在建设好对应的索引且分表数量不是很多的状况下应用 UNION ALL来查问也是一个较为适合的折中计划。假如是分库分表呢? 有一种计划是利用空间换工夫的,就是冗余表数据,将订单数据分为两份,一份数据应用商户的分片键来分表,一份数据用乘客的分片键来分表,即商户的用mid作为分片键,用户的用uid作为分片键,这样不同的查问就应用不同的数据反对,然而由此也带来了一些问题: 因为是数据冗余,为了避免单方同时批改订单状态,所以批改时要订单上锁(分布式锁),避免两端同时同步;因为是数据冗余,数据是同步的,那么必然存在数据不统一的工夫窗口;加大了零碎的整体复杂度;下面把用户侧的查问需要根本都解决了,那么接下来的就是经营侧的查问需要,经营侧的查问需要查问多个商户之间的数据,那么这里对于应用mid作为数据分片键的话就无奈提供较好的反对了,通常经营侧的查问也是公司内部人员在应用,咱们为了缩小零碎整体的复杂度对经营侧的查问页面做了一些斗争,针对大部分状况下经营侧必须抉择商户能力查问,但小局部比拟罕用的查问则无需必填商户查问,例如(订单号,手机号,uid等等),这类查问同样是应用UNION ALL反对。 此处也有一种计划是将将数据数据灌入es解决,通过es反对多条件分页查问,如果es数据量过大,能够配合hive数据联合应用,es只落入要害数据,hive落入全副数据,每次进行条件查问获取rowId,而后依据再到hive中查问所有数据。分片数量抉择好了分片键,接下来看下第二个问题 程度分表具体要分多少张表?通常在设计分片数量时要思考业务将来的增长量,这样次要是为了防止或缩小扩容次数。那么以后数据库容量为1300W(3个月) 依照目前的增量 每日30W左右,月增量为3030=900W,将来某个工夫点订单表为 9003=2700W(3个月);因为产品对将来拓展商户持激进态度,则将来5年咱们依照50%的增量算,30(1+0.5)=45W, 月增量为4530=1350W,将来某个工夫点订单表为 1350*3 = 4050W;这里咱们预估将来5年内的数据在4000W左右,那么每张分片的数量咱们权且依照阿里巴巴Java开发手册中的500W来作为节点,那么4000/500 = 8, 分片的数量为8,能够撑持将来5年内的数据增长。 真的是500W为规范吗?MySQL 单表数据最大不要超过多少行?为什么?分片策略抉择完了分片键和确定分片数量之后,接下来看看第三个问题 分片算法或者说分片策略是什么?分片策略实质上就是说数据通过肯定的策略晓得本人到哪个分片去,先看看支流的分片策略别离有哪些 分片策略形容长处毛病范畴(Range)将数据依照范畴划分为不同分片,例如 id,工夫;单表数据可控,不便扩容热点问题:比方依照工夫划分,因为数据是间断的,那么最近的数据就会频繁读写取模(Hash)分片键取模(对hash后果取余数 hash(分片键) mod N),N为数据库实例数或子表数量)实现简略,无效防止数据歪斜扩容麻烦,若产生扩容,数据则须要迁徙,所以倡议提前布局好分片规模或分表实例为2的N次方再或者应用一致性hash;范畴+取模(Range+Hash)将数据先依照范畴划分到不同分片库,再在分片库内应用取模将数据划分到分片表,罕用在分库分表场景蕴含了上述两者的长处,解决了hash的扩容麻烦如同没啥毛病预约义(List)对分片键进行预约义列表划分,间接将某类数据路由到指定数据分片实现简略,不便扩容须要提前将数据划分到对应的分片规定,后续若有新增分片键须要批改配置基于咱们上述的剖析,曾经明确了分片键和分片数量的场景下,目前可能抉择的只有取模或者预约义,那么假如应用取模的话,这里就存在一个问题,因为咱们是通过mid进行分片,每一个mid的数据量不同,有的商户数据量大,有的商户数据量小,hash取模之后分到的数据分片的数据量可能存在数据歪斜的状况,而预约义列表咱们能够通过已知的订单数据来将商户进行分组,划分到不同的表,能够做到数据尽量不歪斜,实现上也绝对简略,对前期的扩容也不会有太大的影响。 ...

May 23, 2023 · 1 min · jiezi

关于java:java并发之可见性问题引发的思考

前言本文将以一个java代码的可见性问题作为引子,一步步从硬件层面推导到软件层面,最初引出volatile的作用。文章篇幅较长,需急躁观看。这是作者学习完这块后本人做的整顿,若存在形容有误、不清晰和混同的状况,欢送评论区及时斧正批评! 1. 存在可见性问题的java代码public class VisableDemo { private static boolean stop = false; public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { int i = 0; while (!stop) { i++; } System.out.println("退出循环:" + i); }); thread.start(); System.out.println("线程开始运行..."); Thread.sleep(1000); stop = true; }}这段代码中,先启动子线程,子线程通过标记位stop管制循环的运行。咱们冀望在主线程睡眠一秒后批改标记位,完结子线程的运行。然而在理论运行中,咱们会发现子线程基本停不下来,这阐明了咱们在主线程批改标记位这个操作,对子线程是不可见的。为什么会有这个问题?这个问题该如何解决?这里不焦急给出答案,咱们先进行一番推导,最初再找到问题实质和解决方案。 2. 可见性问题硬件层面推导过程2.1 cpu高速缓存在算机零碎中,cpu资源十分贵重,它会从主内存或IO设施中加载数据并执行指令。然而,cpu的执行速度远远大于从主内存读取数据的速度,主内存存取数据的速度又远远大于IO设施。这里就呈现了木桶效应,零碎运行的速度取决于最慢的IO设施,这导致cpu资源无奈失去充沛的利用。 为了解决上述问题,引入了高速缓存来均衡CPU和主内存之间的速度差别;引入了过程、线程、工夫片调度等机制来均衡cpu和io设施之间的速度差别。 引入高速缓存是为了晋升性能和cpu利用率,然而却带来了数据一致性问题。不同的cpu不再是间接把数据写到主内存,而是优先写入本人的高速缓存行,在适合的机会同步到主内存。假如cpu0批改了数据,但还没同步到主内存,此时主内存的数据其实就是过期的。而cpu1从主内存读取了数据并进行操作,这时候cpu1操作的数据并不是最新的,就呈现了数据一致性的问题。那么,如何解决引入高速缓存带来的数据一致性问题呢? 2.2 总线锁1.什么是总线锁?总线能够了解为是用于联通cpu和主内存的桥梁,它是一种处理器级别的同步机制。通过在总线上加锁(即总线锁),能够保障各个cpu拜访主内存时的互斥个性,从而解决数据一致性问题。 2.总线锁是怎么解决数据一致性问题的?当CPU须要读取或写入某个共享数据时,它会通过总线发送一个锁定信号。其余的CPU在接管到该信号后会进行对该共享数据的拜访,并期待锁的开释。这个操作将CPU的读写操作变成了串行执行,以确保数据的一致性。 然而,CPU架构从单核倒退到多核,次要目标是为了实现并发执行以进步程序的执行效率。这样一来,引入锁机制后的串行化操作会带来性能问题,升高了CPU的利用率。为了解决这个问题,在x86架构的CPU中引入了缓存锁的概念来进行优化。 2.3 缓存锁1.什么是缓存锁?首先,缓存锁不是锁,能够把它了解为是一种实现缓存一致性协定的机制,通过某些规定管制缓存的状态来保障缓存一致性。缓存锁只在数据被缓存在高速缓存时起作用,相较于总线锁而言粒度更小。常见的缓存一致性协定:MESI、MSI、MOSI等,上面以MESI为例开展阐述。 2.什么是MESI协定?MESI协定是应用最宽泛的缓存一致性协定,基于总线嗅探实现。 3.什么是总线嗅探?总线嗅探是多处理器零碎中的一种通信机制,用于解决多个处理器的共享数据。每个处理器都能够监督总线上的数据传输,如果传输的数据和本处理器相干,则能够进行相应操作。总线嗅探机制可能缩小数据抵触和锁竞争,进步零碎的并行性和效率。然而总线嗅探也会引发总线风暴的问题,即多个处理器同时竞争总线上的资源时,会产生大量的总线通信。总线风暴会升高零碎的性能,并可能导致系统解体。 4.MESI的四种状态含意? 1.Modified(M):批改状态,示意缓存行数据曾经被批改,并且与主内存中的数据不统一,这意味着该数据只存在于以后缓存行; 2.Exclusive(E):独占状态,示意数据被以后缓存行独占,与主内存中的数据统一,并且数据只存在于以后缓存行中,其它缓存行没有该数据; 3.Shared(S):共享状态,示意以后缓存行的数据和主内存统一,并且其它缓存行也有这个数据; 4.Invalid(I):有效状态,示意以后缓存行有效 缓存锁实际上是通过相似MESI等缓存一致性协定来解决缓存一致性问题的。如果想理解各个CPU缓存行之间状态切换的状况,能够通过上面的链接进行理论尝试,须要记住以下两点: CPU首先会尝试从本人的缓存行读取数据,并依据缓存行中数据的状态来确定下一步的操作。为了更好地了解这一点,你能够参考链接中的动画演示并向ChatGPT发问;总线嗅探是通过应用总线上的信号来实现的。各个处理器能够同时嗅探总线上的信号,这一景象在操作过程中是可见的。MESI过程演示网址 5.MESI中存在的问题在cpu批改缓存行数据时,会去告诉其它缓存行批改状态为Invalid。其它缓存行收到告诉并批改缓存行状态后,给该cpu一个ack响应。在此期间该cpu须要期待ack响应,期待的这段时间尽管很短,但却是阻塞状态的,这节约了cpu资源,升高了cpu利用率,因而又引入了写缓存Store Buffer和有效化队列Invalidate Queue。 ...

May 23, 2023 · 2 min · jiezi

关于java:VS-Code-大量-Java-新功能来袭

大家好,欢送来到 Visual Studio Code Java 的 4 月更新!在此博客中,咱们将带来大量根底用户体验更新,其中包含调试性能改良、Maven 插件中的配置文件反对、全新 Java Project Explorer 的用户界面和 Spring Boot 我的项目的可视化加强性能。有很多内容要讲,让咱们开始吧! Maven 插件中的 Profile 反对Maven Profile 容许您创立特定的构建配置并针对不同的环境或指标执行特定的构建阶段,从而优化您的构建过程。它们能够节省时间并缩小谬误,因而您不用保护多个 POM 文件。 咱们在 Maven 插件中增加了对配置文件(Profile)的反对,它是 Java 插件包的一部分,因而您能够直观地看到您领有的 Maven 配置文件。您还能够应用此插件在 Maven 配置文件之间切换,因而间接应用插件治理配置文件要容易得多。上面是一个演示。 调试模式主动展现变量值当咱们为调试器引入惰性变量(Lazy Variable)时,咱们的目标是推延对低廉变量的计算操作,直到用户显式扩大查看它们的值,目标是优化性能。然而,咱们听到用户反映,这带来了一些用户体验的副作用,在调试模式下,开发者必须一直地额定点击能力显示一些根本类型变量的值,十分不不便。 因而,咱们增加了“Auto Expand Lazy Variables”(主动开展惰性变量)的菜单项来主动开展所有惰性变量。当用户在菜单中单击它时,将主动显示所有惰性变量的值,因而用户无需手动单击每个惰性变量即可查看值。如果用户想要复原此行为,只需再次在菜单中单击“Manual Expand Lazy Variables”(手动开展惰性变量)。上面是此性能的演示。 新的 Java Project Explorer 用户界面咱们总是从用户那里听到他们心愿在 Java Project Explorer 中看到更多的我的项目,尤其是与构建工具相干的文件(例如 POM.xml)以及资源文件。因而,咱们从新设计了 Java Project Explorer 的 UI 以蕴含额定的文件资源。对于那些依赖 Java Project Explorer 视图的开发人员,当初您能够轻松地间接拜访这些文件。目前此设计仍处于晚期阶段,请让咱们晓得您的想法,并在 GitHub 上留下您的反馈。 查看 Spring 我的项目的实时属性属性配置是 Spring Boot 我的项目的要害局部,因为它们提供了一种不便的办法来配置和自定义咱们的 Spring 应用程序的行为。然而,有时随着咱们应用程序的增长,很容易遗记这些属性的值,并且很难在利用程序运行时将它们可视化。作为咱们最新的 Spring Boot 加强性能的一部分,咱们增加了对在 Spring Boot Dashboard 中可视化正在运行的 Spring 我的项目实时属性的反对。让咱们看一个疾速演示。 ...

May 23, 2023 · 1 min · jiezi

关于java:Openjob更强大更智能的分布式任务调度框架重磅发布

Openjob 是一款历时一年多打造的分布式高性能任务调度框架,反对多种定时工作、延时工作、工作流设计,采纳无中心化架构,底层应用一致性分片算法,反对有限扩容。 个性高牢靠分布式无状态设计,采纳 Master/Worker 架构,只依赖一种数据库(MySQL/PostgreSQL/Oracle) 高性能任务调度准确到秒级别,反对轻量级分布式计算,底层应用一致性分片算法,反对有限扩容。 定时调度反对分布式定时工作、固定频率工作、高性能秒级任务、一次性工作定时调度。 分布式计算反对单机、播送、Map、MapReduce 和分片多种分布式编程模型,轻松实现大数据分布式计算。 工作流内置工作流调度引擎,反对可视化 DAG 设计,简略高效实现简单任务调度。 延时工作基于 Redis 高性能延时工作,底层工作多级存储,提供丰盛的工作治理。 跨语言反对 Java/Go/PHP/Python 多语言 ,以及Spring Boot、Gin、Swoft 常见框架集成。 权限治理命名空间设计,丰盛的按钮级别权限治理。 报警监控全面的监控指标,丰盛及时的报警形式,便于运维人员疾速定位和解决线上问题。 文档官方网站官网文档Github在线体验 用户名: openjob密 码: openjob.io分割咱们微信公众号:

May 23, 2023 · 1 min · jiezi

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

高级 Java 工程师是指在 Java 开发畛域经验丰富、技术实力弱小的业余人员。本文将介绍高级 Java 工程师的职责、技能和工作环境等方面。download:https://www.97yrbl.com/t-1670.html 职责高级 Java 工程师的主要职责包含: 技术架构设计:高级 Java 工程师须要依据我的项目需要和技术特点,进行零碎架构设计和技术选型,提供高效、可扩大、平安、易保护的解决方案。代码开发和优化:高级 Java 工程师须要精通 Java 编程语言和各种罕用框架,编写高质量、高效率、可读性强的代码,并一直优化代码性能和可维护性。技术支持和问题解决:高级 Java 工程师须要及时处理和解决我的项目中呈现的技术问题,提供无效的技术支持和解决方案。团队治理:高级 Java 工程师须要协调团队外部成员的开发进度和品质,领导和培训其余开发人员,进步整个团队的技术水平和工作效率。技能高级 Java 工程师须要具备以下几种技能: Java 编程语言:高级 Java 工程师须要精通 Java 编程语言的各种个性和利用场景,包含多线程编程、JVM 优化、垃圾回收等。框架和库:高级 Java 工程师须要相熟并把握各种罕用的框架和库,如 Spring、Hibernate、MyBatis 等,以便进行疾速开发和系统优化。数据库和缓存:高级 Java 工程师须要理解各种数据库和缓存技术的利用场景和原理,如 MySQL、Redis、MongoDB 等。架构设计和分布式系统:高级 Java 工程师须要熟练掌握分布式系统和微服务架构的原理和实践经验,如 Dubbo、Spring Cloud 等。工作环境高级 Java 工程师的工作环境能够是企业、科技公司或政府机构等。他们通常在较大规模的团队中工作,负责我的项目的技术架构设计和代码开发,协调团队外部成员的开发进度和品质,并提供无效的技术支持和解决方案。高级 Java 工程师须要一直关注行业新技术和趋势,放弃本人的技术水平和市场竞争力。 总之,高级 Java 工程师是一种经验丰富、技术实力弱小的业余人员。他们须要具备精通 Java 编程语言、框架和库、数据库和缓存、架构设计和分布式系统等技能,以便提供高效、可扩大、平安、易保护的解决方案。高级 Java 工程师通常在较大规模的团队中工作,负责我的项目的技术架构设计和代码开发,协调团队外部成员的开发进度和品质,并提供无效的技术支持和解决方案。

May 22, 2023 · 1 min · jiezi

关于java:极客时间训练营高级Java工程师体系课2023版20遂教方士殷勤觅

download:极客工夫训练营高级Java工程师体系课2023版2.0JVM调优实战-堆内存与元空间优化 Java虚拟机(JVM)是Java应用程序的外围组成部分。在运行Java应用程序时,JVM必须动静分配内存来运行代码。然而,如果调配的内存不足或者过多,就会影响应用程序性能。因而,在进行JVM调优时,咱们须要重点关注堆内存和元空间的优化。 一、堆内存优化 堆内存是Java应用程序最大的内存区域,用于存储对象实例。在进行堆内存优化时,咱们通常须要思考以下几个方面: 堆大小调整:通过调整-Xmx和-Xms参数来设置堆的最大和最小大小。如果堆内存太小,就可能导致频繁的垃圾回收,从而升高应用程序性能。如果堆内存太大,就可能节约系统资源。 垃圾回收:垃圾回收是Java应用程序中最重要的优化策略之一。通过正当设置堆内存和垃圾回收算法,能够升高垃圾回收的频率和工夫,从而进步应用程序性能。 对象池:对象池是一种缓存技术,用于保留曾经创立的对象。通过应用对象池,能够防止频繁地创立和销毁对象,从而升高堆内存的使用量。 二、元空间优化 元空间是JVM用于存储类元数据的区域。在进行元空间优化时,咱们须要重点思考以下几个方面: 元空间大小调整:通过设置-XX:MetaspaceSize和-XX:MaxMetaspaceSize参数来设置元空间的最小和最大大小。如果元空间太小,就可能导致类加载失败,从而影响应用程序的性能。如果元空间太大,就可能节约系统资源。 类加载器缓存:类加载器缓存是一种缓存技术,用于保留曾经加载的类。通过应用类加载器缓存,能够防止频繁地加载类,从而升高元空间的使用量。 元空间压缩:元空间压缩是一种优化策略,能够通过去除无用的类元数据来升高元空间的使用量。通过应用元空间压缩,能够进步应用程序性能并升高系统资源的使用量。 总结 JVM调优实战是Java利用程序开发中十分重要的一环。在进行JVM调优时,咱们须要重点关注堆内存和元空间的优化。通过正当地设置堆内存大小、垃圾回收算法和元空间大小,以及应用对象池、类加载器缓存和元空间压缩等技术,能够进步应用程序性能并升高系统资源的使用量。

May 22, 2023 · 1 min · jiezi

关于java:使用大模型学习logback框架太香了

大模型,如chatGPT3.5、GPT-4,国内的文心一言、通义千问、讯飞星火等,对文字工作者,图片、视频工作者的工作效率晋升是微小的,当你学会应用这些工具之后,你的工作和学习效率会大大晋升,把其他人甩在身后。 明天,我就用 zelinAI 包装 chatGPT3.5 学习了 Spring Boot 我的项目应用 logback 打印日志的最佳实际,效率杠杠的,一起来学习吧。 应用spring boot我的项目打印log的最佳实际,给出代码Spring Boot 我的项目打印 log 的最佳实际是应用 SLF4J API,以及在 logback.xml 中进行配置。 SLF4J(Simple Logging Facade for Java)是一种针对 Java 利用开发的日志标准,反对多种日志实现(如 log4j、logback)。在 Spring Boot 我的项目中,能够应用 SLF4J API 进行对立的日志输入。 具体应用办法如下: 增加 Maven 依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><!-- 引入 SLF4J 相干依赖 --><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId></dependency><dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId></dependency>在 logback.xml 中进行配置logback.xml 是 logback 日志框架的配置文件,须要搁置在我的项目的 src/main/resources 目录下。上面是一个示例配置文件: <?xml version="1.0" encoding="UTF-8"?><configuration> <!-- 定义日志输入地位 --> <property name="LOG_HOME" value="${user.home}/logs" /> <property name="PROJECT_NAME" value="myproject" /> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_HOME}/${PROJECT_NAME}.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}.%d{yyyy-MM-dd}.log.gz</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 定义日志输入级别 --> <root level="INFO"> <appender-ref ref="STDOUT" /> <appender-ref ref="FILE" /> </root></configuration>该配置文件中定义了两个日志输入器,别离是控制台输入器 STDOUT 和文件输入器 FILE。能够依据本人的需要进行批改。 ...

May 22, 2023 · 2 min · jiezi

关于java:flowable动态创建多级流程

flowable动态创建多级流程引入Maven依赖 <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring-boot-starter</artifactId> <version>6.6.0</version></dependency>动态创建流程节点工具类 /** * 动态创建流程节点 */@Slf4j@Component@RequiredArgsConstructorpublic class FlowableBpmnHandler { /** * 创立开始节点信息 * * @return */ public static FlowElement createStartFlowElement(String id, String name) { StartEvent startEvent = new StartEvent(); startEvent.setId(id); startEvent.setName(name); return startEvent; } /** * 创立完结节点信息 * * @param id * @param name * @return */ public static FlowElement createEndFlowElement(String id, String name) { EndEvent endEvent = new EndEvent(); endEvent.setId(id); endEvent.setName(name); return endEvent; } /** * 循环创立一般工作节点信息 * * @param processEntity 流程实体 * @return */ public static List<UserTask> createCommonUserTask(ProcessEntity processEntity) { List<ProcessNode> processNodes = processEntity.getProcessNodeList(); List<UserTask> userTaskList = Lists.newLinkedList(); for (int i = 0; i < processNodes.size(); i++) { ProcessNode node = processNodes.get(i); node.setNodeId(UUIDHelper.randomUUID()); node.setNodeLevel(i + 1); UserTask userTask = new UserTask(); userTask.setId(TypeEnum.getProcessKey(processEntity.getType()) + "_task_" + node.getNodeId()); userTask.setCategory(String.valueOf(i + 1)); userTask.setDocumentation(i == processNodes.size() - 1 ? "true" : "false"); userTask.setName(node.getNodeName()); userTaskList.add(userTask); } return userTaskList; } /** * 创立排它网关节点 * * @return */ public static ExclusiveGateway createExclusiveGateway(Integer i) { ExclusiveGateway gateway = new ExclusiveGateway(); gateway.setName("getaway_name_" + i); gateway.setId("getaway_id_" + i); return gateway; }}动态创建流程模板工具类 ...

May 22, 2023 · 3 min · jiezi

关于java:小马哥Java分布式架构训练营第一期服务治理山在虚无缥缈间

download:小马哥Java分布式架构训练营第一期服务治理MAC 电脑上那些让你骑虎难下的开发工具 H2:Xcode、Visual Studio Code、Terminal、Homebrew 作为一名开发人员,咱们须要一些高效、牢靠的工具来进步咱们的工作效率。在MAC电脑上,有一些十分杰出的开发工具,它们可能让你无法自拔。上面就是其中的四个: Xcode 如果你是一个苹果应用程序的开发人员,那么你肯定会喜爱这款工具。Xcode是苹果公司推出的一款集成开发环境(IDE)。它能够帮忙你疾速地创立和调试iOS、macOS、watchOS和tvOS应用程序。不仅如此,它还有很多弱小的性能,比方代码补全、调试器、性能分析器等等。 Visual Studio Code VS Code是微软公司推出的一款轻量级代码编辑器。它反对多种编程语言,包含JavaScript、TypeScript、Python、Java、C#等等。它的长处在于它的扩展性、智能感知、内置调试器、Git集成等等。这个编辑器被宽泛认为是目前最好的代码编辑器之一。 Terminal Terminal 是Mac OS X 中自带的命令行工具。它提供了一个文本界面,并且能够与操作系统进行交互。在终端中,你能够应用各种命令来管制你的Mac。它能够让你更快地实现一些工作,而且非常适合那些相熟Unix命令行工具的开发人员。 Homebrew Homebrew是一个包管理器,它能够帮忙你轻松地装置和降级各种开发工具。它提供了一个简略的形式来增加、更新和删除软件包,这使得你能够很容易地放弃最新版本的所有工具。如果你常常须要装置或降级一些工具,那么Homebrew是一个不错的抉择。 总结 在MAC电脑上,有许多杰出的开发工具,它们可能大大提高咱们的工作效率。以上四个工具(Xcode、Visual Studio Code、Terminal和Homebrew)都是十分好的抉择,它们都有弱小的性能,并且易于应用。当然,还有许多其余的工具可供选择,你能够依据本人的须要来抉择最适宜本人的工具。

May 22, 2023 · 1 min · jiezi

关于java:超清Java-亿级项目架构设计与落地应用

Java是一种宽泛应用的编程语言,它在企业级利用程序开发中失去了广泛应用。而亿级数据量是一个很常见的问题,因而Java也须要可能解决这么大的数据量。上面是对于Java亿级数据量的文章。download:https://www.666xit.com/4003/ Java利用程序处理亿级数据量须要思考以下方面: 数据存储解决亿级数据时,存储是一个十分重要的问题。Java应用程序能够抉择应用关系型数据库或者NoSQL数据库来存储数据。在应用关系型数据库时,应该依据数据的特点和查问需要来抉择最适宜的数据库,并优化查问语句以进步执行效率。在应用NoSQL数据库时,须要依据数据的特点和拜访模式来抉择最适宜的数据库和数据模型,从而减速数据读写操作。 数据分区当数据量达到亿级时,繁多节点可能无奈满足数据的存储和解决需要。因而,须要将数据扩散到多个节点上进行存储和解决。Java应用程序能够抉择应用分布式数据库或者分布式文件系统来进行数据分区。应用分布式数据库时,应该依据数据特点和查问需要来设计分区策略,并保证数据的一致性和完整性。在应用分布式文件系统时,须要依据数据拜访模式和数据的物理构造来抉择最适宜的文件系统,并优化文件读写操作以进步性能。 并行处理当数据量达到亿级时,繁多节点可能无奈满足数据的解决需要。因而,须要应用并行计算来减速数据的解决。Java应用程序能够抉择应用多线程或分布式计算框架来进行并行处理。在应用多线程时,须要思考线程平安和任务调度等问题。在应用分布式计算框架时,须要依据数据拜访模式和计算需要来抉择最适宜的框架,并优化任务调度和数据传输以进步性能。 缓存当数据量达到亿级时,数据查问和计算耗时可能会很长。因而,须要应用缓存来减速数据的读取和计算。Java应用程序能够抉择应用本地缓存或者分布式缓存来进行缓存。在应用本地缓存时,须要思考内存占用和缓存策略等问题。在应用分布式缓存时,须要依据数据拜访模式和缓存一致性要求来抉择最适宜的缓存零碎,并优化缓存读取和更新操作以进步性能。 总之,Java利用程序处理亿级数据须要综合思考数据存储、数据分区、并行处理和缓存等方面。只有通过正当的架构设计和优化策略,才可能实现高效、稳固和牢靠的数据处理。

May 22, 2023 · 1 min · jiezi

关于java:MyBatis教程

1.什么是MyBatisMyba是一款优良的长久层框架MyBatis 防止了简直所有的 JDBC 代码和手动设置参数以及获取后果集的过程,缩小了代码的冗余,缩小程序员的操作。MyBatis 能够应用简略的 XML 或注解来配置和映射原生信息,将接口和 Java 的 实体类 【Plain Old Java Objects,一般的 Java对象】映射成数据库中的记录。MyBatis原来是apache的一个开源我的项目,叫做ibatis,2010年这个我的项目由apache迁徙到了google code,并且改名为MyBatis2013年11月官网代码迁徙到GitHubMyBatis中文文档:https://mybatis.net.cn/GitHub:GitHub - mybatis/mybatis-3: MyBatis SQL mapper framework for Java 2.长久层长久层,顾名思义是实现长久化工作的代码块,也就是Date Access Object(Dao层)大多数状况下特地是企业级利用,数据长久化往往也就意味着将内存中的数据保留到磁盘上加以固化,而长久化的实现过程则大多通过各种关系数据库来实现。不过这里有一个字须要特别强调,也就是所谓的“层”。对于利用零碎而言,数据长久性能大多是必不可少的组成部分。也就是说,咱们的零碎中,曾经人造的具备了“长久层”概念?兴许是,但兴许理论状况并非如此。之所以要独立出一个“长久层”的概念,而不是“长久模块”,“长久单元”,也就意味着,咱们的零碎架构中,应该有一个绝对独立的逻辑层面,专一于数据长久化逻辑的实现.与零碎其余局部相对而言,这个层面应该具备一个较为清晰和严格的逻辑边界。(也就是改层就是为了操作数据库而设计的) 3.Mybatis的作用Mybatis就是帮忙程序员将数据存取到数据库外面。传统的jdbc操作 , 有很多反复代码块 .比方 : 数据取出时的封装 , 数据库的建设连贯等等… , 通过框架能够缩小反复代码,进步开发效率 .MyBatis 是一个半自动化的ORM框架 (Object Relationship Mapping) -->对象关系映射所有的事件,不必Mybatis仍旧能够做到,只是用了它,会更加不便更加简略,开发更疾速。 4.MyBatis的长处简略易学:自身就很小且简略。没有任何第三方依赖,最简略装置只有两个jar文件+配置几个sql映射文件就能够了,易于学习,易于应用,通过文档和源代码,能够比拟齐全的把握它的设计思路和实现。灵便:mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于对立治理和优化。通过sql语句能够满足操作数据库的所有需要。解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据拜访逻辑拆散,使零碎的设计更清晰,更易保护,更易单元测试。sql和代码的拆散,进步了可维护性。提供xml标签,反对编写动静sql。当初支流应用办法 Mybatis 操作数据库的形式1.能够通过xml文件的形式执行sql;2.能够通过注解的形式执行SQL; Mybatis 操作数据库的七大步骤?1.SQLSession 传递SQL骨架给MappedStatement2.由MappedStatement 联合骨架和SQL参数映射成残缺的SQL语句3.将残缺的SQL语句交给Executer4.执行SQL语句5.返回后果集给MappedStatement6.封装后果集7.将后果集返回给SQLSession 5.搭建数据库,sql脚本,间接在数据库中运行即可 CREATE TABLE `user` ( `userId` bigint NOT NULL AUTO_INCREMENT, `userName` varchar(255) COLLATE utf8mb4_bin NOT NULL, `userAddress` varchar(255) COLLATE utf8mb4_bin NOT NULL, PRIMARY KEY (`userId`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;6.创立MyBatis程序 ...

May 22, 2023 · 2 min · jiezi

关于java:MyBatisPlus-可视化代码生成器来啦让你的开发效率大大提速

前言在基于Mybatis的开发模式中,很多开发者还会抉择Mybatis-Plus来辅助性能开发,以此进步开发的效率。尽管Mybatis也有代码生成的工具,但Mybatis-Plus因为在Mybatis根底上做了一些调整,因而,惯例的生成工具生成的代码还有一些不太合乎预期。而且对于多数据库的反对不是很好。 因而,咱们须要一款反对高度定制化,带图形UI页面,能适配少数数据库的根底程序生成框架。本文就介绍这款基于Mybatis-Plus的代码自助生成器,github地址:mybatis-plus-generator-ui。 文章通过实例集成的形式来具体解说mybatis-plus-generator-ui,感兴趣的敌人能够本人clone下来,也能够本人进行扩大自定义。一、mybatis-plus-generator-ui是什么?它是对mybatis-plus-generator进行封装,通过Web UI疾速生成兼容Spring boot,mybatis-plus框架的各类业务代码。提供交互式的Web UI用于生成兼容mybatis-plus框架的相干性能代码,包含Entity、Mapper、Mapper.xml、Service、Controller等,能够自定义模板以及各类输入参数,也可通过SQL查问语句间接生成代码。 性能列表: Table查问: 查问配置的关系型数据库表的列表查问。输入配置: 对须要生成的相干代码,比方Entity、Mapper、Servcie、Controller等代码模板信息进行配置,用于在转换时调用。我的项目导入: 能够导入其它我的项目配置好的信息给本我的项目应用。下载模板: 反对本我的项目配置的模板信息下载后共享。策略配置: 间接定义各种文件的生成策略。模板上传: 反对从别的我的项目中下载模板,同上传供本我的项目应用。SQL输出上传: 反对将查问语句间接上传或者复制到输入框中。SQL代码生成: 基于SQL脚本生成相应的代码。二、 mybatis-plus-generator-ui怎么用?mybatis-plus-generator-ui提供以jar包的模式为内部我的项目提供服务,通过配置的数据库配置去读取数据库的配置信息,并通过Web UI的形式提供给开发者应用。mybatis-plus-generator-ui反对POSTGRE_SQL、ORACLE、DB2、MySQL、SQLSERVER等常见的关系型数据库。 举荐一个开源收费的 Spring Boot 最全教程: https://github.com/javastacks/spring-boot-best-practice1、maven pom引入<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.yelang</groupId> <artifactId>mybatis-plus-generator-ui-case</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.github.davidfantasy</groupId> <artifactId>mybatis-plus-generator-ui</artifactId> <version>1.4.5</version> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.25</version> </dependency> </dependencies></project>2、新建程序入口,以main函数的形式运行mybatis-plus-generator-ui在1.4.0版本之后,可反对将GeberatorUIServer独立部署为一个独自的spring boot我的项目,通过页面指定指标我的项目根目录的形式为多个我的项目提供源码生成服务。这种形式实用于有多个我的项目库须要独立进行开发的模式。实例要害代码如下: package com.yelang;import com.github.davidfantasy.mybatisplus.generatorui.GeneratorConfig;import com.github.davidfantasy.mybatisplus.generatorui.MybatisPlusToolsApplication;import com.github.davidfantasy.mybatisplus.generatorui.mbp.NameConverter;public class GeneratorMain { public static void main(String[] args) { GeneratorConfig config = GeneratorConfig.builder().jdbcUrl("jdbc:postgresql://127.0.0.1:5432/ghyapp") .userName("ghy01").password("ghy01").driverClassName("org.postgresql.Driver") // 数据库schema,POSTGRE_SQL,ORACLE,DB2类型的数据库须要指定 // .schemaName("myBusiness") // 如果须要批改各类生成文件的默认命名规定,可自定义一个NameConverter实例,笼罩相应的名称转换方法: .nameConverter(new NameConverter() { /** * 自定义Service类文件的名称规定 */ public String serviceNameConvert(String tableName) { return this.entityNameConvert(tableName) + "Service"; } /** * 自定义Controller类文件的名称规定 */ public String controllerNameConvert(String tableName) { return this.entityNameConvert(tableName) + "Action"; } }).basePackage("com.github.davidfantasy.mybatisplustools.example").port(8068).build(); MybatisPlusToolsApplication.run(config); }}在下面的配置中,咱们连贯的示例数据库是PostgerSQL,须要在Maven中定义相应的驱动程序,并且在上述代码中正确配置相应的类。最初指定了程序的运行端口为8086,这种运行形式跟SpringBoot十分类似。 ...

May 22, 2023 · 2 min · jiezi

关于java:让-Java-Agent-在-Dragonwell-上更好用

背景随着越来越多的云原生微服务利用的大规模部署,大家对微服务治理的能力需要越来越强。Java Agent技术可能让业务专一于业务逻辑,与此同时,中间件通过Java Agent反对无侵入批改程序行为,提供微服务治理能力。 此外,Java Agent反对通过环境变量的形式注入,中间件、云产品团队能够通过设置环境变量来反对所以目前基于Java Agent实现的云原生可观测、微服务治理能力被越来越多的采纳。比方开源的Skywalking、OpenTelemetry,商业化的阿里云MSE等,都反对Java Agent接入。 残缺内容请点击下方链接查看: https://developer.aliyun.com/article/1132324?utm_content=g_10... 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

May 22, 2023 · 1 min · jiezi

关于java:基于-SpringBoot实现文档管理编辑器

拜访【WRITE-BUG数字空间】_[内附残缺源码和文档] 本我的项目实现性能如下:注册、登录和个人资料批改;文档编辑:Markdown 文档的浏览和编辑、公布;文档治理; 应用 Cookies 保留登录状态;在数据库中应用 MD5 保留明码,提供肯定的安全性; 反对 Markdown;进行权限查看,保障隐衷性;读写拆散,定期和退出时主动保留到缓存。 设计概述本设计中,咱们应用了来自如下起源的一些内容:Editor.md,用于实现 Markdown 的编辑和浏览;耿晨歌老师提供的 Demo 中的局部 CSS;文末 参考资料 中的一些实现思路或代码。本设计参考了助教陆涛涛老师提供的《SpringBoot 入门》。该文档给我的入门提供了很大的帮忙! 1.1 选题及基本功能基于 SpringBoot 设计了一个简略的文档治理编辑器 咸鱼雀 (xianyuque),性能包含: 注册、登录和个人资料批改应用 Cookies 保留登录状态在数据库中应用 MD5 保留明码,提供肯定的 安全性 文档编辑:Markdown 文档的浏览和编辑、公布在进入文档浏览和编辑页面,以及公布时,进行 权限查看,保障隐衷性读写拆散,用户未手动点击公布时,浏览页面仍为上一次公布的后果编辑页中 每 2 分钟主动保留到缓存从编辑页 退出时主动保留 到缓存下一次 编辑时复原缓存 文档治理文件的列表展现文件的新增、删除文件归档

May 22, 2023 · 1 min · jiezi

关于java:天下苦-Spring-久矣Solon-v2220-发布

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似曾相识的体验,入门更简略,迁徙很不便:@Controllerpublic class App { public static void main(String[] args) { Solon.start(App.class, args, app->{ //手写模式 app.get("/", ctx -> ctx.outputAsJson("{message:'Hello world!'}")) }); } //注解模式 @Get @Socket @Mapping("/hello") public String hello(String name) { return String.format("Hello %s!", name); }}本次更新:公布 Solon Native (整合 Solon + Java AOT + GraalVM Native 三者的编译能力)公布 Solon Aot (Java AOT 的 Solon 增强版)调整 solon server maxThreads 默认为 coreThreads 的 32 倍调整 solon server 的 maxBodySize,maxFileSize 配置解决减少 日志框架在 window 下的黑白打印反对减少 solon.boot.jdkhttp 对 HttpServerConfigure 接口的反对,不便增加端口及ssl的编程管制减少 solon.boot.jlhttp 对 HttpServerConfigure 接口的反对,不便增加端口及ssl的编程管制减少 solon.boot.smarthttp 对 HttpServerConfigure 接口的反对,不便增加端口及ssl的编程管制减少 solon.boot.jetty 对 HttpServerConfigure 接口的反对,不便增加端口及ssl的编程管制减少 solon.boot.undertow 对 HttpServerConfigure 接口的反对,不便增加端口及ssl的编程管制减少 solon.logging.logback 插件,文件扩展名配置(.log, .log.gz)减少 solon.logging.log4j2 插件,文件扩展名配置(.log, .log.gz)减少 Props::bindTo 接口修复 solon.boot.undertow 的 maxBodySize 配置有效问题修复 solon.boot.smarthttp + ssl 在某些状况下会慢的问题snack3 升为 3.2.72我的项目仓库:gitee:https://gitee.com/noear/solongithub:https://github.com/noear/solon

May 22, 2023 · 1 min · jiezi

关于java:面试复盘哈希冲突的常见解决方案

哈希抵触是指在哈希表中,两个或多个元素被映射到了同一个地位的状况。 String str1 = "3C";String str2 = "2b";int hashCode1 = str1.hashCode();int hashCode2 = str2.hashCode();System.out.println("字符串: " + str1 + ", hashCode: " + hashCode1);System.out.println("字符串: " + str2 + ", hashCode: " + hashCode2);程序的运行后果如下:不同的字符串,却领有了雷同的 hashCode 这就是哈希抵触。因为元素的地位是依据 hashCode 的值进行定位的,此时它们的 hashCode 雷同,但一个地位只能存储一个值,这就是哈希抵触。 解决哈希抵触在 Java 中,解决哈希抵触的罕用办法有以下三种:链地址法、凋谢地址法和再哈希法。 链地址法(Separate Chaining):将哈希表中的每个桶都设置为一个链表,当产生哈希抵触时,将新的元素插入到链表的开端。这种办法的长处是简略易懂,实用于元素数量较少的状况。毛病是当链表过长时,查问效率会升高。凋谢地址法(Open Addressing):当产生哈希抵触时,通过肯定的探测办法(如线性探测、二次探测、双重哈希等)在哈希表中寻找下一个可用的地位。这种办法的长处是不须要额定的存储空间,实用于元素数量较多的状况。毛病是容易产生汇集景象,即某些桶中的元素过多,而其余桶中的元素很少。再哈希法(Rehashing):当产生哈希抵触时,应用另一个哈希函数计算出一个新的哈希值,而后将元素插入到对应的桶中。这种办法的长处是简略易懂,实用于元素数量较少的状况。毛病是须要额定的哈希函数,且当哈希函数不够随机时,容易产生汇集景象。链地址法 VS 凋谢地址法链地址法和凋谢地址法集体感觉以下几点不同: 存储构造不同:链地址法规定了存储的构造为链表(每个桶为一个链表),每次将值存储到链表的开端;而凋谢地址法未规定存储的构造,所以它能够是链表也能够是树结构等。查找形式不同:链地址法查找时,先通过哈希函数计算出哈希值,而后在哈希表中查找对应的链表,再遍历链表查找对应的值。而凋谢地址法查找时,先通过哈希函数计算出哈希值,而后在哈希表中查找对应的值,如果查找到的值不是要查找的值,就持续查找下一个值,直到查找到为止。插入方法不同:链地址法插入时,先通过哈希函数计算出哈希值,而后在哈希表中查找对应的链表,再将值插入到链表的开端。而凋谢地址法插入时,是通过肯定的探测办法,如线性探测、二次探测、双重哈希等,在哈希表中寻找下一个可用的地位。所以链地址法插入方法实现非常简单,而凋谢地址法插入方法实现绝对简单。线性探测 VS 二次探测线性探测是产生哈希抵触时,线性探测会在哈希表中寻找下一个可用的地位,具体来说,它会查看哈希表中下一个地位是否为空,如果为空,则将元素插入该地位;如果不为空,则持续查看下一个地位,直到找到一个闲暇的地位为止。 二次探测是产生哈希抵触时,二次探测会应用一个二次探测序列来寻找下一个可用的地位,具体来说,它会计算出一个二次探测序列,而后顺次查看哈希表中的每个地位,直到找到一个闲暇的地位为止。二次探测的长处是绝对于线性探测来说,它更加平均地散布元素,毛病是当哈希表的大小扭转时,须要从新计算二次探测序列。 具体来说,二次探测序列是一个二次函数,它的模式如下: f(i) = i^2其中,i 示意探测的步数,f(i) 示意探测的地位。 例如,当产生哈希抵触时,如果哈希表中的第 k 个地位曾经被占用,那么二次探测会顺次查看第 k+1^2、第 k-1^2、第 k+2^2、第 k-2^2、第 k+3^2、第 k-3^2……等地位,直到找到一个闲暇的地位为止。 二次探测的长处是绝对于线性探测来说,它更加平均地散布元素,但毛病是容易产生二次探测汇集景象,即某些桶中的元素过多,而其余桶中的元素很少。 HashMap 如何解决哈希抵触?在 Java 中,HashMap 应用的是凋谢地址法解决哈希抵触的,因为在 JDK 1.8 之后(蕴含 JDK 1.8),HashMap 应用的数组 + 链表或红黑树的构造来存储数据了,所以显然不能应用链地址法来解决哈希抵触。 ...

May 22, 2023 · 1 min · jiezi

关于java:mkw体系课Java-亿级项目架构设计与落地应用无密

Java是一种宽泛应用的编程语言,它在企业级利用程序开发中失去了广泛应用。而亿级数据量是一个很常见的问题,因而Java也须要可能解决这么大的数据量。上面是对于Java亿级数据量的文章。download:https://www.666xit.com/4003/ Java利用程序处理亿级数据量须要思考以下方面: 数据存储解决亿级数据时,存储是一个十分重要的问题。Java应用程序能够抉择应用关系型数据库或者NoSQL数据库来存储数据。在应用关系型数据库时,应该依据数据的特点和查问需要来抉择最适宜的数据库,并优化查问语句以进步执行效率。在应用NoSQL数据库时,须要依据数据的特点和拜访模式来抉择最适宜的数据库和数据模型,从而减速数据读写操作。 数据分区当数据量达到亿级时,繁多节点可能无奈满足数据的存储和解决需要。因而,须要将数据扩散到多个节点上进行存储和解决。Java应用程序能够抉择应用分布式数据库或者分布式文件系统来进行数据分区。应用分布式数据库时,应该依据数据特点和查问需要来设计分区策略,并保证数据的一致性和完整性。在应用分布式文件系统时,须要依据数据拜访模式和数据的物理构造来抉择最适宜的文件系统,并优化文件读写操作以进步性能。 并行处理当数据量达到亿级时,繁多节点可能无奈满足数据的解决需要。因而,须要应用并行计算来减速数据的解决。Java应用程序能够抉择应用多线程或分布式计算框架来进行并行处理。在应用多线程时,须要思考线程平安和任务调度等问题。在应用分布式计算框架时,须要依据数据拜访模式和计算需要来抉择最适宜的框架,并优化任务调度和数据传输以进步性能。 缓存当数据量达到亿级时,数据查问和计算耗时可能会很长。因而,须要应用缓存来减速数据的读取和计算。Java应用程序能够抉择应用本地缓存或者分布式缓存来进行缓存。在应用本地缓存时,须要思考内存占用和缓存策略等问题。在应用分布式缓存时,须要依据数据拜访模式和缓存一致性要求来抉择最适宜的缓存零碎,并优化缓存读取和更新操作以进步性能。 总之,Java利用程序处理亿级数据须要综合思考数据存储、数据分区、并行处理和缓存等方面。只有通过正当的架构设计和优化策略,才可能实现高效、稳固和牢靠的数据处理。

May 21, 2023 · 1 min · jiezi

关于java:java的新特性反射

前言说起发射,先说正射是什么,咱们代码中通过User user = new User();代码创立一个对象,并调用User类的成员变量或办法,这种咱们通过Class信息获取class实例,称之为正射,这种代码编译器编译时便晓得他会生成一个user对象。 如果咱们在写代码时不晓得咱们要操作的对象类型,他可能是User类型,也可能是House类型,而User类型和Clazz类型有没有继承关系,只晓得要调用他的getId()办法,那又该怎么调用对象的办法呢? 反射对于反射而言,咱们取得了一个对象的实例,并且晓得了这个对象的类型,那么咱们便能够对他进行所有操作。 这是因为JVM为每一个加载的class都创立了一个class实例,并保留了实例的所有信息,包含类型,父类,办法,属性等等,这使得咱们能够获取class实例的所有信息。这种通过class实例获取class信息的办法称为反射 获取class又3种办法 通过一个class的动态变量class获取 Class clazz = User.class;通过完整包门路获取 Class clazz = Class.forName("xiaoqiangZzz.busticket;");通过实例获取 Object object = getObject();Class clazz = object.getClass();获取到class后,咱们也能够通过class创立实例对象 Object object = clazz.newInstance();获取属性 Field getField(name):依据字段名获取某个public的field(包含父类)Field getDeclaredField(name):依据字段名获取以后类的某个field(不包含父类)Field[] getFields():获取所有public的field(包含父类)Field[] getDeclaredFields():获取以后类的所有field(不包含父类)public void getId(Object object) throws IllegalAccessException { Class clazz = object.getClass(); Field field = clazz.getField("age"); field.setAccessible(true); System.out.println(field.get(object)); field.setAccessible(false); }相似的,咱们能够获取办法并调用 Method getMethod(name, Class...):获取某个public的Method(包含父类)Method getDeclaredMethod(name, Class...):获取以后类的某个Method(不包含父类)Method[] getMethods():获取所有public的Method(包含父类)Method[] getDeclaredMethods():获取以后类的所有Method(不包含父类)public void getMethod(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class clazz = object.getClass(); Method method = clazz.getMethod("getId"); method.invoke(object);}反射利用制作一个通用的数据库表导出办法 ...

May 21, 2023 · 1 min · jiezi

关于java:SpringBoot限制接口访问频率-这些错误千万不能犯

最近在基于SpringBoot做一个面向普通用户的零碎,为了保证系统的稳定性,避免被歹意攻打,我想管制用户拜访每个接口的频率。为了实现这个性能,能够设计一个annotation,而后借助AOP在调用办法之前查看以后ip的拜访频率,如果超过设定频率,间接返回错误信息。常见的谬误设计在开始介绍具体实现之前,我先列举几种我在网上找到的几种常见谬误设计。 1. 固定窗口有人设计了一个在每分钟内只容许拜访1000次的限流计划,如下图01:00s-02:00s之间只容许拜访1000次,这种设计最大的问题在于,申请可能在01:59s-02:00s之间被申请1000次,02:00s-02:01s之间被申请了1000次,这种状况下01:59s-02:01s距离0.02s之间被申请2000次,很显然这种设计是谬误的。 2. 缓存工夫更新谬误我在钻研这个问题的时候,发现网上有一种很常见的形式来进行限流,思路是基于redis,每次有用户的request进来,就会去以用户的ip和request的url为key去判断拜访次数是否超标,如果有就返回谬误,否则就把redis中的key对应的value加1,并从新设置key的过期工夫为用户指定的拜访周期。外围代码如下: // core logicint limit = accessLimit.limit();long sec = accessLimit.sec();String key = IPUtils.getIpAddr(request) + request.getRequestURI();Integer maxLimit =null;Object value =redisService.get(key);if(value!=null && !value.equals("")) { maxLimit = Integer.valueOf(String.valueOf(value));}if (maxLimit == null) { redisService.set(key, "1", sec);} else if (maxLimit < limit) { Integer i = maxLimit+1; redisService.set(key, i.toString(), sec);} else { throw new BusinessException(500,"申请太频繁!");}// redis related public boolean set(final String key, Object value, Long expireTime) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { e.printStackTrace(); } return result; }这外面很大的问题,就是每次都会更新key的缓存过期工夫,这样相当于变相缩短了每个计数周期, 可能咱们想管制用户一分钟内只能拜访5次,然而如果用户在前一分钟只拜访了三次,后一分钟拜访了三次,在下面的实现外面,很可能在第6次访问的时候返回谬误,但这样是有问题的,因为用户的确在两分钟内都没有超过对应的拜访频率阈值。 ...

May 21, 2023 · 3 min · jiezi

关于java:java生产问题记录

背景:公司有专门的k8s运维,做的我的项目是酒店自助机,根本业务:自助机前端有刷身份证查订单/现场预约/退房/办理入住/生成房卡等性能,后端对接不同的酒店零碎以及公安系统,业务办理须要公安和原生酒店零碎都要对接。问题形容:如家酒店有两套环境,私有化环境和公网环境,公网环境性能少,私有化环境的零碎部署到如家本人的服务器上,公网的后端是部署在阿里云。当然,测试环境也是两套。后果就再一次公布生产(私有化)的时候,对接如家的java我的项目启动失败抽丝剥茧:看报错日志,发现是连贯配置核心连不上,连的是公网的配置核心。也就是说用公网的docker镜像部署到了私有化环境(公网用的配置核心是阿里云的acm,私有化用的配置核心是nacos),私有化环境是连不了外网的。运维说是代码问题, 可查看了配置也没故障,而后让运维帮忙查,运维始终认为是代码的故障不给查。他还凶我。很受伤。持续抽丝剥茧:那就本人查。先让如家的开发把生产环境的镜像给发过来,解压进去,找到jar,再解压,发现的确用的是公网的jar(acm的jar,没有nacos的jar),那就要看devOps是怎么把私有化的镜像打包成公网镜像的,就去查jenkins的打包部署日志。日志里找到了打包生成的镜像id,而后问运维这个镜像id的逻辑是什么样的,他说是这个镜像id是测试和生产环境专用的id,也就是部署到生产和测试的镜像是一样的。 那就是说,生产的那个镜像id是在测试环境部署的时候生成的,而后问他,生产的镜像id是怎么来的,他说是最新一次部署的,也就是说,测试测的是哪个镜像,部署就用哪个镜像上生产。而后我就去拿生产环境镜像的id去测试jenkins的两套环境里的部署日志里找,果然,在公网的环境jenkins上找到了这个镜像id.起因:找到了 “私有化生产环境的镜像 是 公网测试环境所打的镜像包”,且生产环境是用一个我的项目的最新的镜像, 问题的起因就浮出水面:原本测试是在私有化的测试环境测的,可过后有些性能是在公网的,测试就部署了公网的测试环境, 巧在 正好在这次部署后, 就公布了生产(私有化)解决方案:运维给两套环境生成的镜像id减少了环境的前缀public/private,用来示意公网还是私有化,部署的时候,取最新一个对应前缀的镜像id去部署。

May 20, 2023 · 1 min · jiezi

关于java:怎么把Java枚举名称作为注解的属性值

一、前言Java注解的属性值,必须为 常量有些场景想把 枚举名称 设置为 注解的属性值(如 spring-cache 用枚举配置缓存,应用时 须要 缓存名称)二、计划计划一:名称属性 + 内部名称接口 @lombok.Getter@lombok.AllArgsConstructorpublic enum CommonCacheConfig { QUOTE_LEVEL(CommonCacheConstant.QUOTE_LEVEL, 2); private final String name; private final int ttl;}public interface CommonCacheConstant { String QUOTE_LEVEL = "QUOTE_LEVEL";}应用:@Cacheable(cacheNames = CommonCacheConstant.QUOTE_LEVEL) 计划二:名称属性 + 外部名称接口 public enum CommonCacheConfig { QUOTE_LEVEL(Constant.QUOTE_LEVEL, 2); private final String name; private final Integer ttl; public interface Constant { String QUOTE_LEVEL = "QUOTE_LEVEL"; }}应用:@Cacheable(cacheNames = CommonCacheConfig.Constant.QUOTE_LEVEL) 计划三:Lombok 的 FieldNameConstants @lombok.Getter@lombok.AllArgsConstructor@lombok.experimental.FieldNameConstants(onlyExplicitlyIncluded = true)public enum CommonCacheConfig { @FieldNameConstants.Include QUOTE_LEVEL(2); private final Integer ttl;}应用:@Cacheable(cacheNames = CommonCacheConfig.Fields.QUOTE_LEVEL) 留神:FieldNameConstants 的 onlyExplicitlyIncluded 需设置为 true,否则 按枚举的属性(如 ttl)生成,同时在 枚举项前加 @FieldNameConstants.Include ...

May 20, 2023 · 1 min · jiezi

关于java:java并发系列之死锁

前言在本文中,咱们将探讨死锁的概念及其产生的起因,并通过示例代码来阐明死锁的呈现状况。咱们还将介绍如何通过毁坏死锁的不同条件来解决死锁问题,通过深刻理解死锁及其解决办法,咱们能够更好地应答并解决零碎中可能呈现的死锁状况。 1. 死锁的概念与产生死锁的条件死锁指的是,一组相互竞争资源的线程,它们之间互相期待而导致永恒阻塞的景象。当上面四个条件同时满足时,就会产生死锁: 1.互斥:一个共享资源同一时间只能被一个线程占用; 2.占有且期待:线程1曾经取得共享资源X,在期待获取共享资源Y的时候,它不会开释曾经占有的共享资源X; 3.不可抢占:线程不能抢占其它线程曾经占有的共享资源; 4.循环期待:线程1期待线程2占有的资源,线程2期待线程1占有的资源,这就是循环期待。 2. 死锁示例及解决方案呈现死锁时,只须要毁坏四个条件中的任意一个即可。然而,互斥条件是不能毁坏的,因为只有互斥能力解决线程平安问题,所以只须要毁坏其它三个条件中的任意一个即可。 2.1 死锁示例以下代码模仿了两个人互相转账的场景。转账操作须要依照肯定的程序对账户进行加锁,以确保转账过程的安全性。然而,因为两个线程转账方向不同,导致加锁的程序也不同。最终,两个线程互相期待对方开释锁资源,导致呈现死锁景象。 账户类代码: // 账户类@Datapublic class Account { private String accountName; // 账户名 private int balance; // 账户余额 public Account(String accountName, int balance) { this.accountName = accountName; this.balance = balance; } // 转出操作,缩小转出方的余额 public void debit(int count) { this.balance -= count; } // 转入操作,减少转入方的余额 public void credit(int count) { this.balance += count; }}转账示例代码: // 呈现死锁的示例public class TransferAccount implements Runnable { private Account formAccount; // 转出账户 private Account toAccount; // 转入账户 private int amount; // 转账金额 public TransferAccount(Account formAccount, Account toAccount, int amount) { this.formAccount = formAccount; this.toAccount = toAccount; this.amount = amount; } @Override public void run() { while(true) { // 爱护转入转出账户,其余线程在转账期间无奈操作,保障线程平安 synchronized (formAccount) { synchronized (toAccount) { // 转出方余额足够 if (formAccount.getBalance() >= amount) { formAccount.debit(amount); toAccount.credit(amount); } } } System.out.println("fromAccount:" + formAccount.getAccountName() + ":" + formAccount.getBalance()); System.out.println("toAccount:" + toAccount.getAccountName() + ":" + toAccount.getBalance()); } } public static void main(String[] args) { Account zhangsan = new Account("张三", 1000); Account lisi = new Account("李四", 2000); // 因为上面持有锁的程序是相同的,所以可能会呈现持有并期待的状况而导致死锁 // 张三向李四转10块钱 Thread t1 = new Thread(new TransferAccount(zhangsan, lisi, 10)); // 李四向张三转20块钱 Thread t2 = new Thread(new TransferAccount(lisi, zhangsan, 20)); t1.start(); t2.start(); }} ...

May 20, 2023 · 4 min · jiezi

关于java:Java-亿级项目架构设计与落地应用

download:Java 亿级我的项目架构设计与落地利用Java是当今最为风行的编程语言之一,被宽泛用于大型项目的开发。对于亿级我的项目,架构设计至关重要,因为它波及到高可用性、伸缩性和安全性等方面。在本文中,咱们将探讨Java亿级我的项目的架构设计,并重点介绍H2数据库。 架构设计在设计亿级我的项目的架构时,须要思考以下几个方面: 高可用性对于一个亿级我的项目,必须保证系统可能24/7稳固运行,即便呈现故障也应该可能主动复原。为此,能够采纳多节点部署、负载平衡和容错机制等形式来进步零碎的可用性。 高伸缩性因为亿级我的项目通常须要解决海量数据和用户申请,因而须要具备高伸缩性,即可能疾速扩大节点以满足业务需要。这能够通过分布式架构、微服务架构和云计算技术等实现。 安全性对于任何一个大型项目来说,数据安全都是至关重要的问题。因而,在设计亿级我的项目的架构时,必须思考数据的安全性,包含数据加密、权限管制和破绽修复等方面。 H2数据库H2是一款轻量级的Java数据库,具备高性能、嵌入式和分布式反对等特点,非常适合于亿级我的项目的架构设计。 高性能H2的查问速度十分快,能够通过应用索引和缓存来优化性能。此外,H2能够在内存中运行,从而进一步提高性能。 嵌入式反对H2能够作为一个嵌入式数据库应用,这意味着应用程序能够间接拜访数据库,而无需应用独立的数据库服务器。这不仅不便了开发人员,还能够缩小系统资源的占用。 分布式反对对于亿级我的项目,通常须要采纳分布式架构来实现高伸缩性。H2反对分布式部署,能够将数据库扩散到多个节点上,从而实现数据的摊派和负载平衡。 总结在设计Java亿级我的项目的架构时,须要思考高可用性、高伸缩性和安全性等方面。H2数据库是一款非常适合于亿级我的项目的轻量级数据库,具备高性能、嵌入式和分布式反对等特点。如果您正在设计一个大型Java我的项目,无妨思考应用H2数据库来优化性能和进步可扩展性。

May 19, 2023 · 1 min · jiezi

关于java:springMVC异常处理流程

springMVC异样解决流程 1.创立异样状态的类 package com.javasm.http;//创立异样状态public enum EnumStatus { //枚举对象 这里的 ; 是创立EnumStatus类时主动生成的,不是敲的 SUCCESS(20000, "申请胜利"), ERROR(50000, "申请失败"), LOGIN_EXCEPTION(40002,"用户名或者明码谬误"), ORDER_ABNORMALITY(40003,"订单异样"), PARAMETER_EXCEPTIONS(40004,"参数不正确"); private int status;//状态码 private String message;//状态码对应的提示信息 EnumStatus(int status, String message) { this.status = status; this.message = message; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } //1.定义status 和message //2.生成getter和setter办法 //3.生成构造方法 //4.调用构造方法创立枚举对象}2.创立LoginException类,生成一个构造方法,在controller层抛出异样的时候调用 ...

May 19, 2023 · 1 min · jiezi

关于java:千峰java就业班2023重磅升级又闻子规啼夜月

download:千峰java待业班2023重磅降级“又闻子规啼夜月,愁空山”,这是唐代诗人杜甫《月夜忆舍弟》中的一句诗句。这句诗描述了一个沉寂的夜晚,孤单的人在空山听到子规的啼声,感觉本人的情绪也像那空山一样苍凉。 夜晚是一个非凡的时间段,往往给人带来思考、深思和回顾。在夜晚中,世界变得更加宁静,许多人会抉择独自一人,享受这份平静。然而,宁静的夜晚也经常使人感到孤单和寂寞。就像杜甫所写的,“愁空山”,在夜晚中,大自然的缄默和孤寂会显得更加显著和粗浅。 子规是一种鸟类,夜间的子规啼声经常被人们视为沉寂夜晚的“伴音”。在中国传统文化中,子规也具备象征着孤单和悲痛的意义。当人们在夜晚听到子规的啼声时,情绪也会随之起伏。杜甫的这句诗句正是通过子规的啼声,体现出一种孤单、悲凉和怀念的情感。 “愁空山”这个词组,则更加强调了孤单和寂寞的气氛。空山是指没有人寓居和往来的山林,在夜晚中显得更加荒凉和沉寂。在这样的环境下,人们往往会感到本人的无助和渺小,好像整个大自然都在默默地讥笑或者同情着本人。 然而,夜晚也能够给人带来启发和反思。在宁静的夜晚中,人们能够更加清晰地思考问题,积淀心田,找到本人的方向和指标。正如唐代诗人白居易所说:“夜来幽梦忽还乡,小轩窗。正梳妆。相顾无言,惟有泪千行。”即使是在孤单和寂寞的夜晚中,咱们依然能够通过思考和反思,找到生命的意义和价值。 总之,“又闻子规啼夜月,愁空山”这句诗句,将孤单和寂寞的情感与大自然的沉静和漂亮相结合,体现了夜晚中独特的气氛和人们对生命粗浅的思考。在这个快节奏、充斥清静的时代中,咱们也须要有一份平静和思考,在夜晚中找到本人的灵魂归属,发现更加实在和美妙的本人。

May 19, 2023 · 1 min · jiezi

关于java:Java数据结构及算法算法的4路描述方式

本文首发自「慕课网」,想理解更多IT干货内容,程序员圈内热闻,欢送关注"慕课网"!作者:老卫|慕课网讲师 要定义一个算法,咱们能够用自然语言、流程图、伪代码的形式形容解决某个问题的过程或是编写一段程序来实现这个过程。比方,在后面所举的“学生信息管理系统”例子中,咱们心愿实现增加用户、删除用户、查问用户三个算法。1. 自然语言形容算法能够采纳自然语言的形式来形容增加用户、删除用户、查问用户三个算法: 增加用户:将用户信息增加到零碎中。如果曾经增加了过该用户的信息,则提醒用户。否则将用户信息增加到零碎中,并给出提醒。删除用户:将用户信息从零碎中删除。如果用户信息不存在于零碎中,则提醒用户。否则将用户信息从零碎中删除,并给出提醒。查问用户:将零碎中所有的用户信息查问进去。如果零碎中不存在用户,则提醒用户。否则将用户信息查问进去返回,并将用户信息打印进去。应用自然语言形容的益处是任何人都能看懂。当然相比于伪代码或者程序语言而言,应用自然语言形容有时会显得繁琐。2. 流程图形容算法流程图(Flow Diagram)是一种通用的图形符号表示法是一种非正式的,能够分明形容步骤和判断。图1-2展现的是用流程图的形式来形容增加用户、删除用户、查问用户三个算法。 相比拟自然语言而言,通过流程图的形容,能够很分明的看到操作的流向及通过的步骤。但须要留神的是,流程图应该只形容外围的操作步骤以及要害的节点判断,而不是事无巨细的把所有的操作都形容进去,否则只会让整个图看上去简单难以了解。 3. 伪代码形容算法伪代码(Pseudocode)是一种非正式的,相似于英语构造的,用于形容模块结构图的语言。能够采纳伪代码的形式来形容增加用户、删除用户、查问用户三个算法。增加用户的伪代码如下: input(student)if student in studentList print "Student exsit"else add student in studentList print "Add student success"删除用户的伪代码如下: input(student)if student in studentList remove student from studentList print "Remove student success"else print "Student not exsit"查问用户的伪代码如下: if student in studentList output studentListelse print "No student exsit"伪代码构造清晰、代码简略、可读性好,并且相似自然语言。介于自然语言与编程语言之间。以编程语言的书写模式指明算法职能。应用伪代码,不必拘泥于具体实现。相比程序语言(例如Java、C++、C等等)它更相似自然语言。它尽管不是规范的语言,却能够将整个算法运行过程的构造用靠近自然语言的模式(能够应用任何一种你相熟的文字,要害是把程序的意思表达出来)形容进去。 4. 程序语言形容算法程序语言形容算法,实际上就是用程序语言实现算法。不同的编程语言其语法不尽相同。以下是采纳Java语言的形式来形容增加用户、删除用户、查问用户三个算法。 import java.util.ArrayList;import java.util.List;public class StudentInfoManageSystem { private List<Student> studentList = new ArrayList<>(); public void addStudent(Student student) { // 如果曾经增加了过该用户的信息,则提醒用户。 // 否则将用户信息增加到零碎中,并给出提醒。 if (studentList.contains(student)) { System.out.println("Student exsit"); } else { studentList.add(student); System.out.println("Add student success"); } } public void removeStudent(Student student) { // 如果用户信息不存在于零碎中,则提醒用户。 // 否则将用户信息从零碎中删除,并给出提醒。 if (studentList.contains(student)) { studentList.remove(student); System.out.println("Remove student success"); } else { System.out.println("Student not exsit"); } } public List<Student> getStudentList() { // 如果零碎中不存在用户,则提醒用户。 // 否则将用户信息查问进去返回,并将用户信息打印进去。 if (studentList.isEmpty()) { System.out.println("No student exsit"); } else { for (Student s : studentList) { System.out.format("Student info: name %s, age %d, phone %s, address %s%n", s.getName(), s.getAge(), s.getPhoneNumer(), s.getAddress()); } } return studentList; }}为了演示上述算法,还须要一个利用入口。咱们用StudentInfoManageSystemDemo类来示意利用主程序,代码如下: ...

May 19, 2023 · 2 min · jiezi

关于java:通过Java程序将Excel转换为PDF文档格式

Excel广泛应用于商业、教育等泛滥畛域,具备丰盛的数据处理和剖析性能,包含计算、图表、排序、筛选、数据透视表等。在解决大型数据内容时,Excel相对是最佳工具。但如果要将解决好的数据内容进行保留和传输的话,转换为PDF文档格局或者更加牢靠。PDF文档的稳固布局能够防止数据内容被随便更改,即便是在屡次传输后也能保证数据的准确性。将Excel转换为PDF的工具有很多。这里我将介绍如何通过编程的办法来实现该性能。以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 文件,点击确认,将其导入到我的项目中。 将整个工作簿转换为PDF代码解释:首先,通过调用Workbook类的构造函数创立一个Workbook对象,并应用loadFromFile()办法从指定的门路加载Excel文件。接着,通过调用setSheetFitToPage()办法设置工作表适应页面,以便更好地进行PDF文件转换。最初,应用saveToFile()办法将生成的PDF文件保留到指定的地位。 示例代码:import com.spire.xls.FileFormat;import com.spire.xls.Workbook;public class ConvertExcelToPdf { public static void main(String[] args) { //创立Workbook 实例并加载示例文档 Workbook workbook = new Workbook(); workbook.loadFromFile("C:\\Users\\Administrator\\Desktop\\Sample.xlsx"); //转换时设置工作表适应页面 workbook.getConverterSetting().setSheetFitToPage(true); //保留为PDF文档格局 workbook.saveToFile("output/ExcelToPdf.pdf", FileFormat.PDF); }}效果图: 将特定工作表转换为PDF代码解释:首先通过调用Workbook类的构造函数创立一个Workbook对象,并应用loadFromFile()办法从指定的门路加载Excel文件。接下来,应用setSheetFitToWidth()办法调整工作表以适宜页面大小,而后应用getWorksheets()办法从工作表列表中获取第一个工作表,并应用saveToPdf()办法保留转换后的PDF文件。 示例代码:import com.spire.xls.Workbook;import com.spire.xls.Worksheet;public class ConvertWorksheetToPdf { public static void main(String[] args) { //创立Workbook 实例并加载示例文档 Workbook workbook = new Workbook(); workbook.loadFromFile("C:\\Users\\Administrator\\Desktop\\Sample.xlsx"); //转换时设置工作表适应宽度 workbook.getConverterSetting().setSheetFitToWidth(true); //获取第一个工作表 Worksheet worksheet = workbook.getWorksheets().get(0); //保留为PDF文档格局 worksheet.saveToPdf("output/WorksheetToPdf.pdf"); }}效果图: ...

May 19, 2023 · 1 min · jiezi

关于java:异常体系与项目实践

程序式暗影:为什么不报错?一、简介在程序开发的过程中,异样解决素来都是一个简单的维度,无论是老手还是经验老到的选手,在编码时都会面对各种异常情况; 程序中的异样能够反映零碎的缺点和待优化的点,并且是无奈完全避免的,如何解决异样和升高异样呈现的频率,是零碎品质的根底保障; 随着分布式架构的风行,各种简单的申请链路给异样解决带来了微小的麻烦,须要全面的监控来定位起因,能力疾速的优化和解决; 二、异样体系不论是JDK根底,还是各类组件,在源码中都波及大量的异样封装,从而准确的反映出形容信息,先来看看Java中的异样体系根底; Throwable:是所有谬误「Error」和异样「Exception」的超类, Error:通常是底层的不可复原的类,此类谬误个别都比较严重,JVM将终止其运行的线程; Exception:程序本身能够捕捉并且能够预处理的异样,例如捕捉解决或者抛出; 针对「编译器」来说,异样又分为「查看」异样和「非查看」异样; 查看异样:即编译时异样,在编译期间就会被编译器查验到的异样,这类异样要么捕捉解决要么抛出,否则就会报编译谬误; 非查看异样:即运行时异样,在编译期间不会被编译器查验到的异样,这类异样只有在程序运行的时候,才会有可能被抛出; 三、异样用法1、应用细节Java异样解决关键字,别离是:「try」可能抛异样的代码块,「catch」捕捉异样、「finally」必须执行的代码块、「throw」办法内抛指定异样、「throws」办法申明抛多个异样; public class UseExe01 { public static void main(String[] args) { try { strStm (); ioStm(); } catch (NullPointerException e) { System.out.println("空指针异样:"+e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.out.println("IO流异样:"+e.getMessage()); e.printStackTrace(); } catch (Exception e) { System.out.println("异样:"+e.getMessage()); e.printStackTrace(); } finally { System.out.println("execute...finally"); } } public static void ioStm () throws FileNotFoundException { new FileInputStream(new File("file_path")); } public static String strStm () throws NullPointerException { Object object = new Object() ; return object.getClass().getName() ; }}案例剖析 ...

May 19, 2023 · 3 min · jiezi

关于java:使用开源时序数据库-GreptimeDB-存储开源实时监控-HertzBeat-的指标度量数据

应用开源时序数据库 GreptimeDB 存储开源实时监控 HertzBeat 的指标度量数据什么是 GreptimeDBGreptimeDB 是一款开源、分布式、云原生时序数据库,交融时序数据处理和剖析。欠缺的生态系统,反对大量凋谢协定,与 MySQL/PostreSQL/PromQL/OpenTSDB 等兼容,学习成本低,开箱即用。时序、剖析混合负载,反对高并发的读/写;原生反对 PromQL, 反对 SQL/Python 进行弱小的库内剖析。高效存储与计算,通过对象存储和高数据压缩率实现超低的存储老本。内置数据分析解决方案,防止将数据复制到内部数据仓库。分布式、高牢靠与高可用,通过解耦的云原生架构,轻松独立地扩大每个模块。通过可配置的正本和主动的故障转移机制,确保数据的可靠性和可用性。Cloud: GreptimePlay https://greptime.com/playground 什么是 HertzBeatHertzBeat 一个领有弱小自定义监控能力,无需 Agent 的开源实时监控告警工具。集 监控+告警+告诉 All in one,反对对应用服务,数据库,操作系统,中间件,云原生,网络等监控,阈值告警告诉一步到位。更自由化的阈值规定(计算表达式),邮件 Discord Slack Telegram 钉钉 微信 飞书 短信 Webhook 等形式及时送达。将Http,Jmx,Ssh,Snmp,Jdbc等协定标准可配置化,只需在浏览器配置YML监控模版就能应用这些协定去自定义采集想要的指标。HertzBeat的弱小自定义,多类型反对,易扩大,低耦合,心愿能帮忙开发者和中小团队疾速搭建自有监控零碎。Cloud: TanCloud https://console.tancloud.cn/ GreptimeDB & HertzBeat上面内容咱们会通过一步一步的模式演示 HertzBeat 如何联合 GreptimeDB 作为存储端来存储收集到的指标数据。装置部署 GreptimeDB具体能够参考 官网文档 Docker 装置 GreptimeDB$ docker run -p 4000-4004:4000-4004 \ -p 4242:4242 -v "$(pwd)/greptimedb:/tmp/greptimedb" \ --name greptime \ greptime/greptimedb:0.2.0 standalone start \ --http-addr 0.0.0.0:4000 \ --rpc-addr 0.0.0.0:4001-v "$(pwd)/greptimedb:/tmp/greptimedb" 为 greptimeDB 数据目录本地长久化挂载,倡议将$(pwd)/greptimedb替换为您想指定寄存的理论本地目录应用$ docker ps | grep greptime查看 GreptimeDB 是否启动胜利装置部署 HertzBeat具体能够参考 官网文档 ...

May 18, 2023 · 1 min · jiezi

关于java:高危WebLogic-Server-远程代码执行漏洞复现及攻击拦截-CVE202321839

破绽简介 Oracle WebLogic Server是一个对立的可扩大平台,用于在本地和云端开发、部署和运行企业应用程序,例如 Java。WebLogic Server提供了Java Enterprise Edition (EE)和Jakarta EE的牢靠、成熟和可扩大的实现。 WebLogic是美商Oracle的次要产品之一,是商业市场上次要的Java利用服务器软件之一,是世界上第一个胜利商业化的J2EE应用服务器,目前已推出到14c版。而此产品也延长出WebLogic Portal, WebLogic Integration等企业用的中间件,以及OEPE开发工具。 近日,Oracle WebLogic Server被检测到近程代码执行破绽(CVE-2023-21839),该破绽容许未经身份验证的近程攻击者通过T3/IIOP协定网络拜访并毁坏WebLogic服务器,胜利利用此破绽可导致要害数据的未受权拜访或间接获取WebLogic服务器权限。 影响版本 WebLogic_Server = 12.2.1.3.0WebLogic_Server = 12.2.1.4.0WebLogic_Server = 14.1.1.0.0 修复计划更新Oracle WebLogic Server官网最新补丁:https://www.oracle.com/security-alerts/cpujan2023.html 环境搭建 下载地址:https://www.oracle.com/middleware/technologies/weblogic-serve...(依据官网装置阐明装置即可)https://github.com/vulhub/vulhub一键搭建破绽复现 应用以下工具进行复现 https://github.com/4ra1n/CVE-2023-21839https://github.com/WhiteHSBG/JNDIExploit发动攻打申请:新建/tmp/1.txt文件 新建胜利开启rasp后发动攻打:申请被拦挡 堆栈信息为: 破绽剖析 在../wlserver/server/lib下执行java -jar wljarbuilder.jar生成wlfullclient.jar OpaqueReference接口的对象从 WLContext 中检索时,由 getReferent() 返回对象当近程对象继承自OpaqueReference时,客户端在对该对象进行JNDI查找并获取的时候,服务器端实际上是通过调用近程对象的getReferent()办法来获取该对象的理论援用。因为ForeignOpaqueReference继承OpaqueReference,所以在近程查问该对象的时候,调用的将会是ForeignOpaqueReference.getReferent办法在后续的进行lookup操作之前会查看 JNDI 环境是否已正确配置后拜访近程资源,次要是对jndiEnvironment和remoteJNDIName进行逻辑判断。因为this.remoteJNDIName为private类可利用反射来赋值而this.jndiEnvironment只有不空,就能对InitialContext进行初始化,所以this.jndiEnvironment也能够应用反射的形式进行赋值。将jndiEnvironment和remoteJNDIName批改为期望值即可实现攻打。之后即可通过retVal=context.lookup(evalMacros(this.remoteJNDIName))的实现jndi注入攻打。因为rasp探针hook了javax.naming.InitialContext.lookup的办法,当进行lookup查找jndi地址时便会间接触发拦挡。 云鲨计划 应用云鲨RASP,无需额定配置规定,即可实现对该破绽的天然免疫防护。 Refrence https://xz.aliyun.com/t/12297https://github.com/4ra1n/CVE-202...https://docs.oracle.com/html/E80373_03/weblogic/jndi/OpaqueRe...https://www.anquanke.com/post/id/287753 对于云鲨RASP 悬镜云鲨RASP助力企业构建利用平安爱护体系、搭建利用平安研运闭环,将踊跃防御能力注入业务利用中,实现利用平安自免疫。详情欢送拜访云鲨RASP官网https://rasp.xmirror.cn/

May 18, 2023 · 1 min · jiezi

关于java:由于锁超时让我发现了parallelStream并行流的关于线程上下文的一个坑

就我之前因为在解决jpa长久化对象上下文(文:https://segmentfault.com/a/1190000043581830)时,parallelStream并行流给我的印象就是会读不到父线程的上下文的,所以应该在父线程里的事务和在parallelStream里的事务应该是辨别的,而不是共用同一个事务的,然而明天因为一个锁超时的问题,发现并没有那么简略,上面咱们一步一步来验证。 首先说下我锁超时的场景:具体的业务我不讲了,就说下伪代码 @PostMapping("/saveUser")@Transactionalpublic void saveUser(@RequestBody List<Complex> list) { list.parallelStream().forEach(complex->{ Integer appId = complex.getAppId(); Integer userId = complex.getUserId(); GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); String sql = "insert ignore into open_app_user (app_id, open_id, user_status, creator, modifier, create_time, modify_time, status, version) values ("+appId+","+userId+",0,1,1,now(),now(),1,1)"; int id = jdbcTemplate.update(con -> con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS), keyHolder); }); //todo 业务逻辑...}这里我有个批量保留的逻辑,须要先保留一个两头表open_app_user表(该表app_id和open_id是联结惟一键)取得id,拿到用户的open_app_user_id后再进行其余业务逻辑,这里按我原来的了解是尽管我在controller的办法上加了@Transactional注解,然而parallelStream里的事务应该都是独立的,不会是同一个事务,所以即便有数据反复,第一个线程插入后,第二个线程也只会插入失败(不会报错,因为我加了ignore),所以即便并行也不会有问题的,然而却产生了锁超时的问题。 查看锁超时以及定位的操作能够看我后面的文章,通过查找mysql的 select * from information_schema.INNODB_TRX;select * from performance_schema.data_lock_waits;select * from performance_schema.data_locks;定位到了这里,然而我也百思不得其解,为啥会锁超时呢,这里应该都是马上执行就马上开释了啊,难道是其中的事务没有提交? 因为当初都是spring的申明式事务管理,spring是在有@Transactional注解的状况下,执行完了才提交事务,在没有@Transactional注解的状况下,每个办法都差不多能够了解成原子,比方我下面的jdbcTemplate.update()这个办法就是一个事务,执行完了就间接提交事务了。 因为spring是把事务上下文放在ThreadLocal里了,次要是用TransactionSynchronizationManager这个类来治理,所以我写了一个demo来进行验证 @GetMapping("/get")@Transactionalpublic String get() { List<Complex> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(new Complex(1, 1)); } list.parallelStream().forEach(complex->{ Map<Object, Object> resourceMap = TransactionSynchronizationManager.getResourceMap(); System.err.println("count:"+resourceMap.size()); Integer appId = complex.getAppId(); Integer userId = complex.getUserId(); String sql = "insert ignore into open_app_user (app_id, open_id, user_status, creator, modifier, create_time, modify_time, status, version) values ("+appId+","+userId+",0,1,1,now(),now(),1,1)"; int update = jdbcTemplate.update(sql); }); return "hello, world! ";}乏味的事件产生了,我在正文掉@Transactional注解时,代码里resourceMap.size()返回的内容是居然不一样,因为我的list有10条记录,差不多就是10个并行,然而我的输入却是: ...

May 18, 2023 · 1 min · jiezi

关于java:基于-Web-的作物生长监控系统的

拜访【WRITE-BUG数字空间】_[内附残缺源码和文档] 本毕业设计在对 A 基地进行调研的根底上。设计并开发了一套基于 Web 的作物成长监控零碎,该零碎由软件和硬件两局部组成。硬件局部采纳了已开发好的多点温湿度采集零碎,软件局部采纳 Java 开发语言、HTML、CSS、JavaScript 等前端语言以及 SSM(SpringMVC + Spring + MyBatis)框架整合和 MySQL 数据库治理技术进行开发。零碎实现了实时推送性能、站点地图展现性能、HTTP 协定爬取农业新闻性能、数据查问性能、温湿度数据分析性能、角色及权限治理性能和站点的创立、 一、摘 要在农业生产流动中,温度和湿度是影响农作物成长的重要因素。因而,对农作物成长的温湿度监测显得尤为重要。随着互联网技术的飞速发展,“互联网 + 农业”已成为促成农业规模化生产的新动力,采纳“互联网 + 农业”的生产模式能无效的优化生产构造,进步生产品质,使农业生产搭上互联网慢车势在必行。 本毕业设计在对 A 基地进行调研的根底上。设计并开发了一套基于 Web 的作物成长监控零碎,该零碎由软件和硬件两局部组成。硬件局部采纳了已开发好的多点温湿度采集零碎,软件局部采纳 Java 开发语言、HTML、CSS、JavaScript 等前端语言以及 SSM(SpringMVC + Spring + MyBatis)框架整合和 MySQL 数据库治理技术进行开发。零碎实现了实时推送性能、站点地图展现性能、HTTP 协定爬取农业新闻性能、数据查问性能、温湿度数据分析性能、角色及权限治理性能和站点的创立、导入及导出性能。为了不便保护和版本迭代,零碎采纳接口开发模式,并引入 Log4j 日志工具将零碎运行过程和用户操作过程保留到本地。心愿此零碎。 本零碎在实现设计和测试后,零碎运行稳固,界面敌对,能无效地进步农业生产的效率,能够达到优化的目标。 关键词:农业;治理平台;Java;MySQL;Web 软件;性能; 二、ABSTRACTIn agricultural production activities, some crops are demanding on the growth environment, and for most crops, the appropriate temperature has more or less impact on their growth and yield.At the same time, with the rapid development of Internet technology, "Internet + agriculture" mode is expected to become a new management platform for large-scale producers, making agricultural production in the Internet environment.Therefore, the implementation of the production mode of "Internet + agriculture" to optimize the production environment can improve the controllability and convenience of the production process. ...

May 18, 2023 · 2 min · jiezi

关于java:java-cron踩坑

想要定时运行工作,能够采纳实现ApplicationRunner和cron的形式进行。然而,cron这种形式服务启动的时候不会运行(如果你的表达式外面不是具体工夫,而是距离多少分钟或者多少小时)。而ApplicationRunner每次启动都会先运行一下,上面简略看一下成果。 一.cron形式 1.在启动类退出@EnableScheduling,用于开启定时工作性能 2.简略的示例 @Componentpublic class CronTask { /** * 每分钟执行一次 */ @Scheduled(cron="0 */1 * * * ?") public void execute() { System.out.println("CronTask工作执行"); }}二.实现ApplicationRunner接口方式 简略示例: @Componentpublic class ApplicationRunnerTask implements ApplicationRunner { /** * 每分钟执行一次 * @param args * @throws Exception */ @Override public void run(ApplicationArguments args) throws Exception { while(true){ try{ System.out.println("ApplicationRunnerTask工作执行"); Thread.sleep(1000 * 60); }catch(Exception e){ System.out.println("Exception:" + e); } } }}三.运行比照差别 能够看到ApplicationRunnerTask先打印,而cronTask前面才打印。因为cronTask会在整分,整时打印(取决于你设置的是隔多久)。例如我示例设置的是每分钟打印,如果我程序是17点18分19秒启动,那么cronTask须要到17点19分0秒才打印。而ApplicationRunnerTask是服务一启动就打印,不存在期待的问题。

May 18, 2023 · 1 min · jiezi

关于java:24个写出漂亮代码的小技巧

「Java学习 + 面试指南」: javaguide.cn (一份涵盖大部分 Java 程序员所须要把握的外围常识)这篇文章我会总结一些实用的有助于进步代码品质的倡议,内容较多,倡议珍藏! 内容概览: 提取通用解决逻辑注解、反射和动静代理是 Java 语言中的利器,应用切当的话,能够大大简化代码编写,并进步代码的可读性、可维护性和可扩展性。 咱们能够利用 注解 + 反射 和 注解+动静代理 来提取类、类属性或者类办法通用解决逻辑,进而防止反复的代码。尽管可能会带来一些性能损耗,但与其带来的益处相比还是十分值得的。 通过 注解 + 反射 这种形式,能够在运行时动静地获取类的信息、属性和办法,并对它们进行通用解决。比如说在通过 Spring Boot 中通过注解验证接口输出的数据就是这个思维的使用,咱们通过注解来标记须要验证的参数,而后通过反射获取属性的值,并进行相应的验证。 @Data@Builder@AllArgsConstructor@NoArgsConstructorpublic class PersonRequest { @NotNull(message = "classId 不能为空") private String classId; @Size(max = 33) @NotNull(message = "name 不能为空") private String name; @Pattern(regexp = "(^Man$|^Woman$|^UGM$)", message = "sex 值不在可选范畴") @NotNull(message = "sex 不能为空") private String sex; @Region private String region; @PhoneNumber(message = "phoneNumber 格局不正确") @NotNull(message = "phoneNumber 不能为空") private String phoneNumber;}相干浏览:一坨一坨的 if/else 参数校验,终于被 SpringBoot 参数校验组件整洁净了! 。 ...

May 18, 2023 · 9 min · jiezi

关于java:ArrayList中foreach循环中增添删除导致ConcurrentModificationException

一、应用背景在阿里巴巴开发手册中,有这样一条规定:不要在foreach循环里进行add和remove操作(这里指的是List的add和remove操作),否则会抛出ConcurrentModificationException。remove元素请应用iterator。 二、源码1.咱们晓得foreach是语法糖,他实质还是iterator进行的循环,因而上面的代码和应用foreach循环是一样的。在循环外面咱们应用“谬误”操作,应用List的add办法进行操作,会抛出ConcurrentModificationException ArrayList<String> arrayList = new ArrayList<>(); arrayList.add("apple"); Iterator<String> iterator = arrayList.iterator(); while(iterator.hasNext()){ String value = iterator.next(); if("apple".equals(value)){ arrayList.add("orange"); } }三、源码解析1.arrayList.iterator();①返回Itr类,并将modcount的值赋值给一个变量expectedModCount,其中modcount示意List理论被增删的次数,expectedModCount示意该迭代器冀望被增删的次数,当新建Itr类的时候会给他赋初始值,只有通过该迭代器进行值的增删才会批改该值 2.iterator.next();①在调用迭代器的next办法时,他会进行查看,比拟modCount和expectedModCount的值,如果不相等,Concurrent 四、总结1.modCount和expectedModeCount不统一才会抛出ConcurrentModificationException。当咱们调用List的remove办法时,他只会批改modCount的值;当咱们调用iterator的remove办法,他会将modCount的值赋值给expectedModeCount2.modCount和expectedModeCount是属于fast-fail机制,用于多线程中,当进行遍历的时候,有其余线程批改值的时候就会进行查看五、解决办法1.应用一般for循环进行操作2.在循环中应用iterator进行操作3.应用stream流进行过滤4.应用fast-saft平安的类,如ConCurrentLinkedQueue

May 18, 2023 · 1 min · jiezi

关于java:什么是浏览器-cookies-里的-JSessionID

在Web开发中,JSessionID是一个重要的概念,它与浏览器Cookies密切相关。为了更好地了解JSessionID,咱们须要先理解一些对于Cookies的背景常识。 Cookies是一种存储在用户计算机上的小型文本文件,用于在浏览器和Web服务器之间传递信息。它们被宽泛用于跟踪和保护用户的会话状态,以及存储用户的偏好设置和其余相干数据。通过在浏览器中存储Cookies,Web服务器能够在用户拜访同一网站时辨认用户并提供个性化的服务。 JSessionID是一个特定类型的Cookies,用于跟踪用户会话。它是由Java Servlet标准定义的一种机制,用于在用户与Java Web应用程序之间放弃会话状态。JSessionID在用户拜访Java Web应用程序时由Web服务器调配,并以Cookies的模式存储在用户的浏览器中。 JSessionID的作用是惟一标识用户的会话。当用户首次拜访一个Java Web应用程序时,Web服务器会为该用户生成一个惟一的JSessionID,并将其作为Cookies发送给浏览器。浏览器在随后的每个申请中都会将JSessionID蕴含在HTTP头中的Cookies字段中发送回服务器。通过这种形式,Web服务器能够辨认用户的会话并与之前的申请进行关联。 JSessionID通常用于以下几个方面: 会话跟踪:JSessionID容许Web应用程序在用户拜访不同页面或发送不同申请时放弃会话状态。服务器能够依据JSessionID辨认用户,并将用户的数据与其相关联。这对于跟踪用户的登录状态、购物车内容或其余个性化信息十分重要。安全性:JSessionID能够用于实现一些安全措施,如避免会话劫持攻打。通过应用平安的JSessionID生成算法,能够使攻击者难以伪造无效的会话标识。负载平衡:在大型Web应用程序中,可能会有多个服务器解决用户申请。JSessionID能够帮忙负载均衡器将用户的申请路由到正确的服务器,以便放弃会话的一致性。须要留神的是,JSessionID是与Java Web应用程序相干的特定概念。在其余Web开发框架中,可能应用不同的会话标识机制。但总体而言,这些会话标识的目标都是为了实现会话跟踪和状态治理。 总结来说,JSessionID是一种用于跟踪用户会话的Cookies。它容许Web服务器在用户拜访Java Web应用程序时辨认用户身份。

May 18, 2023 · 1 min · jiezi

关于java:critters-开发包的使用案例分享

Critters 是一个 Node.js 模块,它的次要作用是将 CSS 和 JavaScript 代码嵌入到 HTML 文件中,以缩小浏览器对外部资源的申请次数。应用 Critters 能够将所有的 CSS 和 JavaScript 代码内联到 HTML 中,使得 HTML 文件变得更加简洁,同时也能够进步页面加载速度,从而晋升用户体验。上面咱们来具体介绍一下 Critters 的作用和应用办法。 作用Critters 次要有以下几个作用: 内联 CSS 和 JavaScript 代码:将 CSS 和 JavaScript 代码内联到 HTML 文件中,缩小内部资源的申请次数,从而进步页面加载速度。反对异步 JavaScript 代码:能够将异步 JavaScript 代码标记为 async,以保障其正确加载并执行。反对挪动端:能够针对挪动端进行优化,将不必要的代码从 HTML 中移除,以减小文件大小。可定制化:反对自定义配置,能够依据须要对内联的 CSS 和 JavaScript 代码进行压缩、优化等解决。应用办法上面咱们来介绍一下如何在 Node.js 环境下应用 Critters。首先,须要通过 npm 装置该包: npm install critters装置实现后,就能够在代码中引入并应用 Critters 了。上面是一个简略的示例: const fs = require('fs');const critters = require('critters');// 读取 HTML 文件const html = fs.readFileSync('index.html', 'utf8');// 将 CSS 和 JavaScript 代码内联到 HTML 中const result = critters.inline(html);// 将后果输入到文件fs.writeFileSync('index.min.html', result, 'utf8');下面的示例代码中,咱们首先应用 Node.js 的 fs 模块读取了一个 HTML 文件。而后,应用 critters.inline() 办法将该 HTML 文件中的 CSS 和 JavaScript 代码内联到 HTML 中。最初,应用 fs.writeFileSync() 办法将后果写入到一个新的 HTML 文件中。 ...

May 18, 2023 · 1 min · jiezi

关于java:100经典Java面试题及答案解析

面向对象编程(OOP) Java是一个反对并发、基于类和面向对象的计算机编程语言。上面列出了面向对象软件开发的长处: 代码开发模块化,更易保护和批改。 代码复用。 加强代码的可靠性和灵活性。 减少代码的可了解性。 面向对象编程有很多重要的个性,比方:封装,继承,多态和形象。上面的章节咱们会一一剖析这些个性。 封装 封装给对象提供了暗藏外部个性和行为的能力。对象提供一些能被其余对象拜访的办法来扭转它外部的数据。在Java当中,有3种修饰符:public,private和protected。每一种修饰符给其余的位于同一个包或者不同包上面对象赋予了不同的拜访权限。 上面列出了应用封装的一些益处: 通过暗藏对象的属性来爱护对象外部的状态。 进步了代码的可用性和可维护性,因为对象的行为能够被独自的扭转或者是扩大。 禁止对象之间的不良交互进步模块化。 参考这个文档获取更多对于封装的细节和示例。 多态 多态是编程语言给不同的底层数据类型做雷同的接口展现的一种能力。一个多态类型上的操作能够利用到其余类型的值下面。 继承 继承给对象提供了从基类获取字段和办法的能力。继承提供了代码的重用行,也能够在不批改类的状况下给现存的类增加新个性。 形象 形象是把想法从具体的实例中分离出来的步骤,因而,要依据他们的性能而不是实现细节来创立类。Java反对创立只暴漏接口而不蕴含办法实现的形象的类。这种形象技术的次要目标是把类的行为和实现细节分来到。 形象和封装的不同点 形象和封装是互补的概念。一方面,形象关注对象的行为。另一方面,封装关注对象行为的细节。个别是通过暗藏对象外部状态信息做到封装,因而,封装能够看成是用来提供形象的一种策略。 常见的Java问题 1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个能够执行Java字节码的虚拟机过程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成容许应用程序能够运行在任意的平台,而不须要程序员为每一个平台独自重写或者是从新编译。Java虚拟机让这个变为可能,因为它晓得底层硬件平台的指令长度和其余个性。 2.JDK和JRE的区别是什么? Java运行时环境(JRE)是将要执行Java程序的Java虚拟机。它同时也蕴含了执行applet须要的浏览器插件。Java开发工具包(JDK)是残缺的Java软件开发包,蕴含了JRE,编译器和其余的工具(比方:JavaDoc,Java调试器),能够让开发者开发、编译、执行Java应用程序。 3.”static”关键字是什么意思?Java中是否能够笼罩(override)一个private或者是static的办法? “static”关键字表明一个成员变量或者是成员办法能够在没有所属的类的实例变量的状况下被拜访。 Java中static办法不能被笼罩,因为办法笼罩是基于运行时动静绑定的,而static办法是编译时动态绑定的。static办法跟类的任何实例都不相干,所以概念上不实用。 4.是否能够在static环境中拜访非static变量? static变量在Java中是属于类的,它在所有的实例中的值是一样的。当类被Java虚拟机载入的时候,会对static变量进行初始化。如果你的代码尝试不必实例来拜访非static的变量,编译器会报错,因为这些变量还没有被创立进去,还没有跟任何实例关联上。 5.Java反对的数据类型有哪些?什么是主动拆装箱? Java语言反对的8中根本数据类型是: byte short int long float double boolean char 主动装箱是Java编译器在根本数据类型和对应的对象包装类型之间做的一个转化。比方:把int转化成Integer,double转化成double,等等。反之就是主动拆箱。 6.Java中的办法笼罩(Overriding)和办法重载(Overloading)是什么意思? Java中的办法重载产生在同一个类外面两个或者是多个办法的办法名雷同然而参数不同的状况。与此绝对,办法笼罩是说子类从新定义了父类的办法。办法笼罩必须有雷同的办法名,参数列表和返回类型。笼罩者可能不会限度它所笼罩的办法的拜访。 7.Java中,什么是构造函数?什么是构造函数重载?什么是复制构造函数? 当新对象被创立的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的状况下,Java编译器会为这个类创立一个默认的构造函数。 Java中构造函数重载和办法重载很类似。能够为一个类创立多个构造函数。每一个构造函数必须有它本人惟一的参数列表。 Java不反对像C++中那样的复制构造函数,这个不同点是因为如果你不本人写构造函数的状况下,Java不会创立默认的复制构造函数。 8.Java反对多继承么? 不反对,Java不反对多继承。每个类都只能继承一个类,然而能够实现多个接口。 9.接口和抽象类的区别是什么? Java提供和反对创立抽象类和接口。它们的实现有共同点,不同点在于: 接口中所有的办法隐含的都是形象的。而抽象类则能够同时蕴含形象和非形象的办法。 类能够实现很多个接口,然而只能继承一个抽象类 类如果要实现一个接口,它必须要实现接口申明的所有办法。然而,类能够不实现抽象类申明的所有办法,当然,在这种状况下,类也必须得申明成是形象的。 抽象类能够在不提供接口办法实现的状况下实现接口。 Java接口中申明的变量默认都是final的。抽象类能够蕴含非final的变量。 Java接口中的成员函数默认是public的。抽象类的成员函数能够是private,protected或者是public。 接口是相对形象的,不能够被实例化。抽象类也不能够被实例化,然而,如果它蕴含main办法的话是能够被调用的。 也能够参考JDK8中抽象类和接口的区别 10.什么是值传递和援用传递? 对象被值传递,意味着传递了对象的一个正本。因而,就算是扭转了对象正本,也不会影响源对象的值。 对象被援用传递,意味着传递的并不是理论的对象,而是对象的援用。因而,内部对援用对象所做的扭转会反映到所有的对象上。 Java线程 11.过程和线程的区别是什么? 过程是执行着的应用程序,而线程是过程外部的一个执行序列。一个过程能够有多个线程。线程又叫做轻量级过程。 12.创立线程有几种不同的形式?你喜爱哪一种?为什么? ...

May 18, 2023 · 3 min · jiezi

关于java:解读-Java-云原生实践中的内存问题

Java 凭借着本身沉闷的开源社区和欠缺的生态劣势,在过来的二十几年始终是最受欢迎的编程语言之一。步入云原生时代,蓬勃发展的云原生技术开释云计算红利,推动业务进行云原生化革新,减速企业数字化转型。 然而 Java 的云原生转型之路面临着微小的挑战,Java 的运行机制和云原生个性存在着诸多矛盾。企业借助云原生技术进行深层次老本优化,资源老本治理被回升到前所未有的高度。私有云上资源按量免费,用户对资源用量非常敏感。在内存应用方面,基于 Java 虚拟机的执行机制使得任何 Java 程序都会有固定的根底内存开销,相比 C++/Golang 等原生语言,Java 利用占用的内存微小,被称为“内存吞噬者”,因而 Java 利用上云更加低廉。并且利用集成到云上之后零碎复杂度减少,普通用户对云上 Java 利用内存没有清晰的意识,不晓得如何为利用合理配置内存,呈现 OOM 问题时也很难排障,遇到了许多问题。 残缺内容请点击下方链接查看: https://developer.aliyun.com/article/1155826?utm_content=g_10... 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

May 18, 2023 · 1 min · jiezi

关于java:javasynchronizeReentrantLock

背景: 并发同步两巨头.后者有兄弟ReentrantReadWriteLock/StampedLock, 前者独生子区别:机制区别:synchronize是jvm解决细节逻辑,可重入,操作的是对象头里的mark word,mark word 里有锁类型(无锁/轻量级锁/偏差锁/分量极锁)和持有锁的线程.jvm优化后,就有了缩分类和锁降级.不偏心锁.jvm保护阻塞线程列表.ReentrantLock:对一个int进行cas操作来获取/开释锁区别:细节区别:前者毋庸手动开释,代码快完结jvm开释.后者要手动开释锁,个别的代码构造是现lock,再try-cache-finally,在finnally里unlock.后者有更多的操作,比方tryLock,不论有无获取胜利,都返回,还能够查问期待队列的列表,条件锁等.后者能够设置是否偏心锁,前者肯定是 非颁布平锁.后者反对打断和超时操作,前者不反对.

May 18, 2023 · 1 min · jiezi

关于java:java-lambda表达式-回调函数

java应用lambda表达式做回调函数,定义一个interface写一个办法即可(如果一个接口只有一个形象办法(包含继承的),该接口是一个函数接口,函数接口能够应用lambda表达式实现),lambda表达式函数外部能够获取内部变量,会保留堆栈信息 源码Callback.java public interface Callback{ void onCompletion();}Test.java public class Test implements Runnable { BlockingDeque<Callback> queue = new LinkedBlockingDeque<>(); void init(){ Thread thread = new Thread(this,"Test"); thread.start(); } void sendAsync(Callback callback){ queue.add(callback); } @Override public void run() { while (true){ try { Thread.sleep(10); Callback callback = queue.take(); callback.onCompletion(); } catch (InterruptedException e) { e.printStackTrace(); } } }}TestObject.java public class TestObject { public String getVal() { return val; } public void setVal(String val) { this.val = val; } private String val;}Main.java ...

May 18, 2023 · 1 min · jiezi

关于java:javaAQSAbstractQueuedSynchronizer

背景:锁的目标是 让不平安的多线程操作变得平安.计划就是一个一个的来.锁的概念是 让内部(线程)进不去,只能有钥匙的线程能够进去. 那就还须要有一个 管理者,这个管理者 须要确定哪个线程先进去,以及当先进去的人进去后,从排队的线程外面选一个再进去. 这个管理者,被独自定义成AQS, AQS是多线程竞争资源的管理者,从名称翻译的话,是协调器.利用场景:如果要自定义锁,个别做法是在这个锁的类外面,定义继承AQS的实现类,依据自定义锁的逻辑,实现独占锁和共享锁的相干办法即可.例如Reentrantock就是这么做的根本逻辑:抽象类AbstractQueuedSynchronizer里有一个int类型的状态字段state,应用这个字段来定义以后锁的状态,比方0示意还没有线程获取到锁,1示意有一个线程获取到锁,大于1示意是共享锁,且以后领有该共享锁的线程数是state

May 18, 2023 · 1 min · jiezi

关于java:一天吃透Java面试八股文

Java的特点Java是一门面向对象的编程语言。面向对象和面向过程的区别参考下一个问题。 Java具备平台独立性和移植性。 Java有一句口号:Write once, run anywhere,一次编写、到处运行。这也是Java的魅力所在。而实现这种个性的正是Java虚拟机JVM。已编译的Java程序能够在任何带有JVM的平台上运行。你能够在windows平台编写代码,而后拿到linux上运行。只有你在编写完代码后,将代码编译成.class文件,再把class文件打成Java包,这个jar包就能够在不同的平台上运行了。Java具备稳健性。 Java是一个强类型语言,它容许扩大编译时查看潜在类型不匹配问题的性能。Java要求显式的办法申明,它不反对C格调的隐式申明。这些严格的要求保障编译程序能捕获调用谬误,这就导致更牢靠的程序。异样解决是Java中使得程序更持重的另一个特色。异样是某种相似于谬误的异样条件呈现的信号。应用try/catch/finally语句,程序员能够找到出错的解决代码,这就简化了出错解决和复原的工作。Java是如何实现跨平台的?Java是通过JVM(Java虚拟机)实现跨平台的。 JVM能够了解成一个软件,不同的平台有不同的版本。咱们编写的Java代码,编译后会生成.class 文件(字节码文件)。Java虚拟机就是负责将字节码文件翻译成特定平台下的机器码,通过JVM翻译成机器码之后能力运行。不同平台下编译生成的字节码是一样的,然而由JVM翻译成的机器码却不一样。 只有在不同平台上装置对应的JVM,就能够运行字节码文件,运行咱们编写的Java程序。 因而,运行Java程序必须有JVM的反对,因为编译的后果不是机器码,必须要通过JVM的翻译能力执行。 本文曾经收录到Github仓库,该仓库蕴含计算机根底、Java根底、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等外围知识点,欢送star~ Github地址 如果拜访不了Github,能够拜访码云地址。 码云地址 Java 与 C++ 的区别Java 是纯正的面向对象语言,所有的对象都继承自 java.lang.Object,C++ 兼容 C ,岂但反对面向对象也反对面向过程。Java 通过虚拟机从而实现跨平台个性, C++ 依赖于特定的平台。Java 没有指针,它的援用能够了解为平安指针,而 C++ 具备和 C 一样的指针。Java 反对主动垃圾回收,而 C++ 须要手动回收。Java 不反对多重继承,只能通过实现多个接口来达到雷同目标,而 C++ 反对多重继承。JDK/JRE/JVM三者的关系JVM 英文名称(Java Virtual Machine),就是咱们耳熟能详的 Java 虚拟机。Java 可能跨平台运行的外围在于 JVM 。 所有的java程序会首先被编译为.class的类文件,这品种文件能够在虚拟机上执行。也就是说class文件并不间接与机器的操作系统交互,而是通过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地零碎执行。 针对不同的零碎有不同的 jvm 实现,有 Linux 版本的 jvm 实现,也有Windows 版本的 jvm 实现,然而同一段代码在编译后的字节码是一样的。这就是Java可能跨平台,实现一次编写,多处运行的起因所在。 JRE 英文名称(Java Runtime Environment),就是Java 运行时环境。咱们编写的Java程序必须要在JRE能力运行。它次要蕴含两个局部,JVM 和 Java 外围类库。 JRE是Java的运行环境,并不是一个开发环境,所以没有蕴含任何开发工具,如编译器和调试器等。 如果你只是想运行Java程序,而不是开发Java程序的话,那么你只须要装置JRE即可。 最初给大家分享一个Github仓库,下面有大彬整顿的300多本经典的计算机书籍PDF,包含C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,能够star一下,下次找书间接在下面搜寻,仓库继续更新中~ ...

May 18, 2023 · 10 min · jiezi

关于java:什么是反射它有什么用

在 Java 中,反射是指在运行时检查和操作类、接口、字段、办法等程序结构的能力。通过反射,能够在运行时获取类的信息,创立类的实例,调用类的办法,拜访和批改类的字段等。 反射实现先定义一个须要被反射的类对象 User: public class User { public String name = "张三"; private int age = 18; public void publicMethod() { System.out.println("do public method"); } private void privateMethod() { System.out.println("do private method"); } public static void staticMethod() { System.out.println("do static method"); }}1.反射执行公共办法通过反射实现公共办法的调用,次要分为以下 3 步: // 1.反射失去对象Class<?> clazz = Class.forName("User");// 2.失去办法Method method = clazz.getDeclaredMethod("publicMethod");// 3.执行一般办法method.invoke(clazz.getDeclaredConstructor().newInstance());其中第 3 步,如果是 JDK 9 之前的版本应用以下代码代替: method.invoke(clazz.newInstance());JDK 9 之后,应用 Class.newInstance() 办法被弃用了。 2.反射执行公有办法// 1.反射失去对象Class<?> clazz = Class.forName("User");// 2.失去办法Method method = clazz.getDeclaredMethod("publicMethod");// 失去公有办法Method privateMethod = clazz.getDeclaredMethod("privateMethod");// 设置公有办法可拜访privateMethod.setAccessible(true);// 执行公有办法privateMethod.invoke(clazz.getDeclaredConstructor().newInstance());3.反射执行静态方法// 1.反射失去对象Class<?> clazz = Class.forName("User");// 2.失去办法Method method = clazz.getDeclaredMethod("publicMethod");// 失去静态方法Method staticMethod = clazz.getDeclaredMethod("staticMethod");// 执行静态方法staticMethod.invoke(clazz);4.反射失去公共属性值// 反射失去对象Class<?> clazz = Class.forName("User");// 失去公共属性Field field = clazz.getDeclaredField("name");// 失去属性值String name = (String) field.get( clazz.getDeclaredConstructor().newInstance());// 打印属性值System.out.println("name -> " + name);5.反射失去公有属性值// 反射失去对象Class<?> clazz = Class.forName("User");// 失去公有属性Field privateField = clazz.getDeclaredField("age");// 设置公有属性可拜访privateField.setAccessible(true);// 失去属性值int age = (int) privateField.get( clazz.getDeclaredConstructor().newInstance());// 打印属性值System.out.println("age -> " + age);应用场景反射的应用场景有很多,以下是比拟常见的几种反射的应用场景: ...

May 18, 2023 · 1 min · jiezi

关于java:Java-新的生态型应用开发框架Solon-v2214-发布

Java 新的生态型利用开发框架,Solon :更快、更小、更简略。从零开始构建,有本人的标准规范与凋谢生态: 150多个生态插件,能够满足各种场景开发大量的国产框架适配,能够为应用软件国产化提供更好反对绝对于 Spring Boot 和 Spring Cloud 的我的项目:启动快 5 ~ 10 倍。 (更快)qps 高 2~ 3 倍。 (更高)运行时内存节俭 1/3 ~ 1/2。 (更少)打包能够放大到 1/2 ~ 1/10;比方,300Mb 的变成了 23Mb。 (更小)同时反对 jdk8, jdk11, jdk17, jdk20。似曾相识的体验,入门更简略,迁徙很不便:@Controllerpublic class App { public static void main(String[] args) { Solon.start(App.class, args, app->{ //手写模式 app.get("/", ctx -> ctx.outputAsJson("{message:'Hello world!'}")) }); } //注解模式 @Get @Socket @Mapping("/hello") public String hello(String name) { return String.format("Hello %s!", name); }}本次更新:减少 afterInjection() 对注入的检测及非必须注入的反对减少 @Bean demo(...) 对注入的检测及非必须注入的反对减少 okhttp 原生编译反对配置减少 solon.scheduling.quartz 原生编译反对配置减少 water-solon-cloud-plugin 原生编译反对配置减少 solon.aot 性能总体上实现(细节优需优化)减少 VarGater::check 接口,用于在容器启动时做收集检测减少 Router::caseSensitive 接口,用于设定辨别大小写调整 solon.test 减少代理类的字段注入调整 solon.proxy.apt 的代理生成能力,转移到 solon.aot调整 solon aot 时,勾销 Runtime.getRuntime().addShutdownHook调整 solon cloud 在 aot 时不做注册解决调整 mybatis 适配的环境id规定放弃也数据源bean同名调整 Fastjson2Serializer 减少外部的上下文复用调整 solon 路径分析器增加辨别大小写的管制调整 solon-maven-plugin 打包时,排除 provided 的包;反对配置 include 和 exclude 配置调整 sa-token-solon-plugin 全局过滤器的 BeforeAuth 认证设为不受 includeList 与 excludeList 的限度,所有申请都会进入修复 native 运行时,可能呈现找不到资源文件而报错mybatis-flex 升为 1.2.0wood 升为 1.1.1我的项目仓库:gitee:https://gitee.com/noear/solongithub:https://github.com/noear/solon

May 17, 2023 · 1 min · jiezi

关于java:从萌芽到巨人-揭秘Rod-Johnson与Spring框架的故事

前言 在这个充斥创意和技术谋求的世界中,有一个名为 Spring 的框架,它孕育了有数翻新和胜利的故事。这是一个对于继续进化和超越自我的故事,一个激励人心的旅程,由一位富裕远见的程序员和他的团队引领着。从最后的概念到现在的成熟框架,Spring 经验了无数次改革和改良,最终成为了 Java 开发畛域的珍宝。 让咱们踏上一段不平庸的旅程,穿梭时光的长河,见证 Spring 框架从雏形到辉煌的转变。感触到创始人 Rod Johnson 对简化开发的保持,以及团队一直拓展和改善的致力。与此同时,咱们将理解到 Spring 框架如何为咱们带来了有限可能和创造力的开释。让咱们启程,一起摸索 Spring 框架的奇观! Rod Johnson Rod Johnson 是一位驰名的计算机科学家和软件开发专家,已经在多个出名公司负责 Java 开发和架构师的职位。他是 Spring 框架的创始人之一,也是一位 Java 世界的传奇巨匠和神级人物。他在畛域驱动设计、企业级利用架构和 Java 开发方面有着丰盛的教训和深厚的专业知识。更令人吃惊的是在回到软件开发畛域之前,他在悉尼大学不仅取得了计算机学位,同时还取得了音乐学学位。 Spring 前身 在 2002 年之前,企业级 Java 应用程序的开发须要依赖于轻便的 EJB 组件。这些组件过于简单,难以了解,不不便测试,且使开发过程迟缓和难以保护。在这个期间,Rod Johnson 尝试找到一种更轻量级的办法来开发企业级 Java 应用程序,这种办法应该更加简略、灵便和易于保护。在他的钻研中,他提出了一种基于 POJO 的模型,这个模型的核心思想是,应该让业务逻辑代码更加简略,并将它们从容器的繁琐治理中解脱进去。这种基于 POJO 的开发模式为 Spring 框架奠定了根底。 2002 年,他出版了一本名为《Expert One-on-One J2EE》的书,其中批评了过后风行的 Java EE 和 EJB 技术计划,认为它们过于简单、臃肿和低效,并提出了一种基于一般 Java 类和依赖注入(DI)的更简略和灵便的解决方案。他在书中提供了一些根底代码,用来实现这种解决方案。因为我的项目的根包命名为 com.interface21,所以也被称为 interface21,这就是 Spring 的前身。 ...

May 17, 2023 · 2 min · jiezi

关于java:SpringMVC的请求与响应

SpringMVC的申请与响应 SpringMVC的申请和响应SpringMVC的数据响应springMVC的数据响应-数据响应形式SpringMVC的数据响应-页面跳转-返回字符串类型springMVC的数据响应-页面跳转-返回ModelAndView模式springMVC的数据响应-页面跳转-返回ModelAndVIew模式SpringMVC的数据响应-页面跳转-返回ModelAndView回写数据-间接回写字符串回写数据-间接回写json格局字符串回写数据-返回对象或者汇合回写数据-返回汇合或者对象回写数据-知识点小结SpringMVC的申请11取得申请参数-申请参数类型12取得申请参数-取得基本参数类型13取得申请参数-取得POJO类型参数14取得申请参数-取得数组类型参数15 取得汇合类型参数16 动态拜访资源的开启17 配置全局乱码过滤器18 参数绑定注解@RequestParam19 Restful格调的参数的获取20 自定义类型的转换器21 取得Servlet相干API22 取得申请头参数SpringMVC的数据响应01-SpringMVC的数据响应-数据响应形式(了解)1) 页面跳转间接返回字符串通过ModelAndView对象返回2) 回写数据间接返回字符串返回对象或汇合02-SpringMVC的数据响应-页面跳转-返回字符串模式(利用)03-SpringMVC的数据响应-页面跳转-返回ModelAndView模式1(利用)在Controller中办法返回ModelAndView对象,并且设置视图名称@RequestMapping(value="/quick2") public ModelAndView save2(){ /* Model:模型 作用封装数据 View:视图 作用展现数据 */ ModelAndView modelAndView = new ModelAndView(); //设置模型数据 modelAndView.addObject("username","itcast"); //设置视图名称 modelAndView.setViewName("success"); return modelAndView;}04-SpringMVC的数据响应-页面跳转-返回ModelAndView模式2(利用)n在Controller中办法形参上间接申明ModelAndView,无需在办法中本人创立,在办法中间接应用该对象设置视图,同样能够跳转页面 @RequestMapping(value="/quick3")public ModelAndView save3(ModelAndView modelAndView){ modelAndView.addObject("username","itheima"); modelAndView.setViewName("success"); return modelAndView;}@RequestMapping(value="/quick4") public String save4(Model model){ model.addAttribute("username","博学谷"); return "success";}05-SpringMVC的数据响应-页面跳转-返回ModelAndView3(利用)在Controller办法的形参上能够间接应用原生的HttpServeltRequest对象,只需申明即可@RequestMapping(value="/quick5")public String save5(HttpServletRequest request){ request.setAttribute("username","酷丁鱼"); return "success";}06-SpringMVC的数据响应-回写数据-间接回写字符串(利用)通过SpringMVC框架注入的response对象,应用response.getWriter().print(“hello world”) 回写数据,此时不须要视图跳转,业务办法返回值为void将须要回写的字符串间接返回,但此时须要通过@ResponseBody注解告知SpringMVC框架,办法返回的字符串不是跳转是间接在http响应体中返回@RequestMapping(value="/quick7")@ResponseBody //告知SpringMVC框架 不进行视图跳转 间接进行数据响应public String save7() throws IOException { return "hello itheima";}@RequestMapping(value="/quick6")public void save6(HttpServletResponse response) throws IOException { response.getWriter().print("hello itcast");}07-SpringMVC的数据响应-回写数据-间接回写json格局字符串(利用)@RequestMapping(value="/quick8")@ResponseBodypublic String save8() throws IOException { return "{\"username\":\"zhangsan\",\"age\":18}";}手动拼接json格局字符串的形式很麻烦,开发中往往要将简单的java对象转换成json格局的字符串,咱们能够应用web阶段学习过的json转换工具jackson进行转换,通过jackson转换json格局字符串,回写字符串@RequestMapping(value="/quick9")@ResponseBodypublic String save9() throws IOException { User user = new User(); user.setUsername("lisi"); user.setAge(30); //应用json的转换工具将对象转换成json格局字符串在返回 ObjectMapper objectMapper = new ObjectMapper(); String json = objectMapper.writeValueAsString(user); return json;}08-SpringMVC的数据响应-回写数据-返回对象或汇合(利用)通过SpringMVC帮忙咱们对对象或汇合进行json字符串的转换并回写,为处理器适配器配置音讯转换参数,指定应用jackson进行对象或汇合的转换,因而须要在spring-mvc.xml中进行如下配置:<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> </list> </property></bean>@RequestMapping(value="/quick10")@ResponseBody//冀望SpringMVC主动将User转换成json格局的字符串public User save10() throws IOException { User user = new User(); user.setUsername("lisi2"); user.setAge(32); return user;}09-SpringMVC的数据响应-回写数据-返回对象或汇合2(利用)在办法上增加@ResponseBody就能够返回json格局的字符串,然而这样配置比拟麻烦,配置的代码比拟多,因而,咱们能够应用mvc的注解驱动代替上述配置<mvc:annotation-driven/>在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。应用<mvc:annotation-driven />主动加载 RequestMappingHandlerMapping(解决映射器)和RequestMappingHandlerAdapter( 处 理 适 配 器 ),可用在Spring-xml.xml配置文件中应用<mvc:annotation-driven />代替注解处理器和适配器的配置。同时应用<mvc:annotation-driven />默认底层就会集成jackson进行对象或汇合的json格局字符串的转换10-SpringMVC的数据响应-常识要点小结(了解,记忆)1) 页面跳转间接返回字符串通过ModelAndView对象返回2) 回写数据间接返回字符串HttpServletResponse 对象间接写回数据,HttpServletRequest对象带回数据,Model对象带回数据或者@ResponseBody将字符串数据写回返回对象或汇合@ResponseBody+<mvc:annotation-driven/>SpringMVC的申请11-SpringMVC的申请-取得申请参数-申请参数类型(了解)客户端申请参数的格局是:name=value&name=value……服务器端要取得申请的参数,有时还须要进行数据的封装,SpringMVC能够接管如下类型的参数根本类型参数POJO类型参数数组类型参数汇合类型参数12-SpringMVC的申请-取得申请参数-取得根本类型参数(利用)Controller中的业务办法的参数名称要与申请参数的name统一,参数值会主动映射匹配。并且能主动做类型转换;主动的类型转换是指从String向其余类型的转换http://localhost:8080/itheima_springmvc1/quick9?username=zhangsan&age=12@RequestMapping(value="/quick11") @ResponseBody public void save11(String username,int age) throws IOException { System.out.println(username); System.out.println(age); }13-SpringMVC的申请-取得申请参数-取得POJO类型参数(利用)Controller中的业务办法的POJO参数的属性名与申请参数的name统一,参数值会主动映射匹配。package com.itheima.domain;public class User { private String username; private int age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", age=" + age + '}'; }}@RequestMapping(value="/quick12") @ResponseBody public void save12(User user) throws IOException { System.out.println(user); }14-SpringMVC的申请-取得申请参数-取得数组类型参数(利用)Controller中的业务办法数组名称与申请参数的name统一,参数值会主动映射匹配。@RequestMapping(value="/quick13") @ResponseBody public void save13(String[] strs) throws IOException { System.out.println(Arrays.asList(strs)); }15-SpringMVC的申请-取得申请参数-取得汇合类型参数1(利用)取得汇合参数时,要将汇合参数包装到一个POJO中才能够。<form action="${pageContext.request.contextPath}/user/quick14" method="post"> <%--表明是第一个User对象的username age--%> <input type="text" name="userList[0].username"><br/> <input type="text" name="userList[0].age"><br/> <input type="text" name="userList[1].username"><br/> <input type="text" name="userList[1].age"><br/> <input type="submit" value="提交"> </form>package com.itheima.domain;import java.util.List;public class VO { private List<User> userList; public List<User> getUserList() { return userList; } public void setUserList(List<User> userList) { this.userList = userList; } @Override public String toString() { return "VO{" + "userList=" + userList + '}'; }}@RequestMapping(value="/quick14") @ResponseBody public void save14(VO vo) throws IOException { System.out.println(vo); }16-SpringMVC的申请-取得申请参数-取得汇合类型参数2(利用)当应用ajax提交时,能够指定contentType为json模式,那么在办法参数地位应用@RequestBody能够间接接管汇合数据而无需应用POJO进行包装<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script> <script> var userList = new Array(); userList.push({username:"zhangsan",age:18}); userList.push({username:"lisi",age:28}); $.ajax({ type:"POST", url:"${pageContext.request.contextPath}/user/quick15", data:JSON.stringify(userList), contentType:"application/json;charset=utf-8" }); </script>@RequestMapping(value="/quick15") @ResponseBody public void save15(@RequestBody List<User> userList) throws IOException { System.out.println(userList); }17-SpringMVC的申请-取得申请参数-动态资源拜访的开启(利用)当有动态资源须要加载时,比方jquery文件,通过谷歌开发者工具抓包发现,没有加载到jquery文件,起因是SpringMVC的前端控制器DispatcherServlet的url-pattern配置的是/,代表对所有的资源都进行过滤操作,咱们能够通过以下两种形式指定放行动态资源:•在spring-mvc.xml配置文件中指定放行的资源 <mvc:resources mapping="/js/**"location="/js/"/>•应用<mvc:default-servlet-handler/>标签<!--开发资源的拜访--> <!--<mvc:resources mapping="/js/**" location="/js/"/> <mvc:resources mapping="/img/**" location="/img/"/>--> <mvc:default-servlet-handler/>18-SpringMVC的申请-取得申请参数-配置全局乱码过滤器(利用)当post申请时,数据会呈现乱码,咱们能够设置一个过滤器来进行编码的过滤。<!--配置全局过滤的filter--> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>19-SpringMVC的申请-取得申请参数-参数绑定注解@RequestParam(利用)当申请的参数名称与Controller的业务办法参数名称不统一时,就须要通过@RequestParam注解显示的绑定<form action="${pageContext.request.contextPath}/quick16" method="post"> <input type="text" name="name"><br> <input type="submit" value="提交"><br></form>@RequestMapping(value="/quick16") @ResponseBody public void save16(@RequestParam(value="name",required = false,defaultValue = "itcast") String username) throws IOException { System.out.println(username); }20-SpringMVC的申请-取得申请参数-Restful格调的参数的获取(利用)Restful是一种软件架构格调、设计格调,而不是规范,只是提供了一组设计准则和约束条件。次要用于客户端和服务器交互类的软件,基于这个格调设计的软件能够更简洁,更有档次,更易于实现缓存机制等。Restful格调的申请是应用“url+申请形式”示意一次申请目标的,HTTP 协定外面四个示意操作形式的动词如下:GET:用于获取资源POST:用于新建资源PUT:用于更新资源DELETE:用于删除资源例如:/user/1 GET : 失去 id = 1 的 user/user/1 DELETE: 删除 id = 1 的 user/user/1 PUT: 更新 id = 1 的 user/user POST: 新增 user上述url地址/user/1中的1就是要取得的申请参数,在SpringMVC中能够应用占位符进行参数绑定。地址/user/1能够写成/user/{id},占位符{id}对应的就是1的值。在业务办法中咱们能够应用@PathVariable注解进行占位符的匹配获取工作。http://localhost:8080/itheima_springmvc1/quick17/zhangsan@RequestMapping(value="/quick17/{name}")@ResponseBody public void save17(@PathVariable(value="name") String username) throws IOException { System.out.println(username); }21-SpringMVC的申请-取得申请参数-自定义类型转换器(利用)SpringMVC 默认曾经提供了一些罕用的类型转换器,例如客户端提交的字符串转换成int型进行参数设置。然而不是所有的数据类型都提供了转换器,没有提供的就须要自定义转换器,例如:日期类型的数据就须要自定义转换器。public class DateConverter implements Converter<String, Date> { public Date convert(String dateStr) { //将日期字符串转换成日期对象 返回 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date date = null; try { date = format.parse(dateStr); } catch (ParseException e) { e.printStackTrace(); } return date; }}@RequestMapping(value="/quick18") @ResponseBody public void save18(Date date) throws IOException { System.out.println(date); }22-SpringMVC的申请-取得申请参数-取得Servlet相干API(利用)SpringMVC反对应用原始ServletAPI对象作为控制器办法的参数进行注入,罕用的对象如下:HttpServletRequestHttpServletResponseHttpSession@RequestMapping(value="/quick19") @ResponseBody public void save19(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException { System.out.println(request); System.out.println(response); System.out.println(session); }23-SpringMVC的申请-取得申请参数-取得申请头信息(利用)应用@RequestHeader能够取得申请头信息,相当于web阶段学习的request.getHeader(name)@RequestHeader注解的属性如下:value:申请头的名称required:是否必须携带此申请头@RequestMapping(value="/quick20") @ResponseBody public void save20(@RequestHeader(value = "User-Agent",required = false) String user_agent) throws IOException { System.out.println(user_agent); }应用@CookieValue能够取得指定Cookie的值@CookieValue注解的属性如下:value:指定cookie的名称required:是否必须携带此cookie @RequestMapping(value="/quick21") @ResponseBody public void save21(@CookieValue(value = "JSESS

May 17, 2023 · 3 min · jiezi

关于java:JAXB-依赖包问题

java17环境下,为应用JAXB的性能,须要引入依赖: <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>3.0.2</version> </dependency>只需引入一份dependency即可,依附传递依赖,会引入其它jar

May 17, 2023 · 1 min · jiezi

关于java:Java从入门到实践编程转Java的真实学习记录Java中级

【Java从入门到实际】编程大神转Java的实在学习记录--Java中级第六局部:异样解决 解决异样:try - catch - finally 抛出异样:throws,throw throws与throw这两个关键字靠近,不过意义不一样,有如下区别: throws 呈现在办法申明上,而throw通常都呈现在办法体内。throws 示意出现异常的一种可能性,并不一定会产生这些异样;throw则是抛出了异样,执行throw则肯定抛出了某个异样对象异样分类: 1、可查异样CheckedException,如果不解决,编译器不让通过 2、非可查异样(运行时异样RuntimeException、谬误Error) Throwable类:Exception和Error都继承了该类。所以在捕获的时候,也能够应用Throwable进行捕获。异样分Error和Exception,Exception里又分运行时异样和可查异样 自定义异样:继承自Exception 抛出自定义异样 第七局部:I/O 第八局部:Lambda 根本应用 办法援用 聚合操作 第九局部:多线程 三种实现形式:继承线程类、Runnable接口、匿名类 常见线程办法 sleep 以后线程暂停 join 退出到以后线程中 setPriority 线程优先级 yield 长期暂停 setDaemon 守护线程 线程同步 线程平安汇合 死锁 线程交互:Object办法,wait、notify和notifyAll。须要联合synchronized应用 线程池:相似生产者消费者,生产的对象是一个个可能运行的工作 筹备一个工作容器一次性启动10个 消费者线程刚开始工作容器是空的,所以线程都wait在下面。直到一个内部线程往这个工作容器中扔了一个“工作”,就会有一个消费者线程被唤醒notify这个消费者线程取出“工作”,并且执行这个工作,执行结束后,持续期待下一次工作的到来。如果短时间内,有较多的工作退出,那么就会有多个线程被唤醒,去执行这些工作。Lock对象 原子拜访

May 17, 2023 · 1 min · jiezi

关于java:SpringBoot中如何优雅的使用多线程

在 SpringBoot 利用中,常常会遇到在一个接口中,同时做事件1,事件2,事件3,如果同步执行的话,则本次接口工夫取决于事件1 2 3执行工夫之和;如果三件事同时执行,则本次接口工夫取决于事件1 2 3执行工夫最长的那个,正当应用多线程,能够大大缩短接口工夫。那么在 SpringBoot 利用中如何优雅的应用多线程呢? 疾速应用SpringBoot利用中须要增加@EnableAsync注解,来开启异步调用,个别还会配置一个线程池,异步的办法交给特定的线程池实现,如下: @Configuration@EnableAsyncpublic class AsyncConfiguration { @Bean("doSomethingExecutor") public Executor doSomethingExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 外围线程数:线程池创立时候初始化的线程数 executor.setCorePoolSize(10); // 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过外围线程数的线程 executor.setMaxPoolSize(20); // 缓冲队列:用来缓冲执行工作的队列 executor.setQueueCapacity(500); // 容许线程的闲暇工夫60秒:当超过了外围线程之外的线程在闲暇工夫达到之后会被销毁 executor.setKeepAliveSeconds(60); // 线程池名的前缀:设置好了之后能够不便咱们定位解决工作所在的线程池 executor.setThreadNamePrefix("do-something-"); // 缓冲队列满了之后的回绝策略:由调用线程解决(个别是主线程) executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); executor.initialize(); return executor; }}AsyncService @Slf4j@Servicepublic class AsyncService { // 指定应用beanname为doSomethingExecutor的线程池 @Async("doSomethingExecutor") public String doSomething(String message) { log.info("do something, message={}", message); try { Thread.sleep(1000); } catch (InterruptedException e) { log.error("do something error: ", e); } return message; }}AsyncController ...

May 17, 2023 · 2 min · jiezi

关于java:MaxCompute怎么像java一样处理循环呢

能够应用SQL语言来循环遍历数据并执行解决。具体而言,能够应用以下形式实现循环: 应用子查问来获取须要遍历的数据汇合。应用函数和运算符来执行迭代操作。罕用的函数和运算符包含:a. ROW_NUMBER() OVER():用于为每一行数据调配一个惟一的编号。b. LEAD() 和 LAG():用于获取以后行下一行和上一行的数据。c. IF() 和 CASE WHEN THEN ELSE END:用于在循环中进行条件分支。d. WHILE 循环:在两个 SELECT 语句之间应用 WHILE 循环来实现循环逻辑。残缺内容请点击下方链接查看: https://developer.aliyun.com/ask/497038?utm_content=g_1000371989 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

May 17, 2023 · 1 min · jiezi

关于java:Java中的正则表达式详解

文章和代码曾经归档至【Github仓库:https://github.com/timerring/java-tutorial 】或者【AIShareLab】回复 java 也可获取。正则表达式为什么要学习正则表达式极速体验正则表达式威力 提取文章中所有的英文单词提取文章中所有的数字提取文章中所有的英文单词和数字提取百度热榜题目论断:正则表达式是解决文本的利器 package com.hspedu.regexp;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 体验正则表达式的威力,给咱们文本处理带来哪些便当 */public class Regexp_ { public static void main(String[] args) { //假设,编写了爬虫,从百度页面失去如下文本// String content = "1995年,互联网的蓬勃发展给了Oak机会。业界为了使死板、枯燥的" +// "动态网页可能“灵便”起来,急需一种软件技术来开发一种程序,这种程序能够通" +// "过网络流传并且可能跨平台运行。于是,世界各大IT企业为此纷纷投入了大量的" +// "人力、物力和财力。这个时候,Sun公司想起了那个被搁置起来很久的Oak,并且" +// "从新扫视了那个用软件编写的试验平台,因为它是依照嵌入式零碎硬件平台体系结" +// "构进行编写的,所以十分小,特地实用于网络上的传输零碎,而Oak也是一种精简的" +// "语言,程序十分小,适宜在网络上传输。Sun公司首先推出了能够嵌入网页并且能够" +// "伴随网页在网络上传输的Applet(Applet是一种将小程序嵌入到网页中进行执行的技术)," +// "并将Oak更名为Java(在申请注册商标时,发现Oak曾经被人应用了,再想了一系列" +// "名字之后,最终,应用了提议者在喝一杯Java咖啡时无心提到的Java词" +// "语)。5月23日,Sun公司在Sun world会议上正式发" +// "布Java和HotJava浏览器。IBM、Apple、DEC、Adobe、HP、Oracle、Netscape和微软" +// "等各大公司都纷纷进行了本人的相干开发我的项目,竞相购买了Java应用许可证,并为本人的产" +// "品开发了相应的Java平台";// String content = "<div class=\"cr-content new-pmd\">\n" +// " \n" +// "<div class=\"FYB_RD\">\n" +// " <div class=\"cr-title c-gap-bottom-xsmall\" title=\"百度热榜\">\n" +// " <span class=\"c-color-t\">百度热榜</span>\n" +// " <div class=\"opr-toplist1-update opr-toplist1-link\" data-click=\"{fm:'beha'}\" style=\"position:relative;top:-1px;\">\n" +// " <a class=\"OP_LOG_BTN toplist-refresh-btn c-font-normal c-color-gray2\" href=\"javascript:void(0);\" style=\"text-decoration:none;\">\n" +// " <i class=\"c-icon opr-toplist1-hot-refresh-icon\">&#xe619;</i><span>换一换</span>\n" +// " </a>\n" +// " </div>\n" +// " </div>\n" +// " <table class=\"c-table opr-toplist1-table\">\n" +// " <tbody >\n" +// " <tr class=\"toplist1-tr\">\n" +// " \n" +// " <td class=\"toplist1-td opr-toplist1-link\">\n" +// " <span class=\"toplist1-hot c-index-single toplist1-hot-top toplist1-hot-0 c-index-single-hot1 \" style=\"opacity:1;\">\n" +// " 1\n" +// " </span>\n" +// " <a target=\"_blank\" title=\"印度累计确诊病例已超2000万例\" href=\"/s?wd=%E5%8D%B0%E5%BA%A6%E7%B4%AF%E8%AE%A1%E7%A1%AE%E8%AF%8A%E7%97%85%E4%BE%8B%E5%B7%B2%E8%B6%852000%E4%B8%87%E4%BE%8B&rsv_idx=2&tn=baiduhome_pg&usm=3&ie=utf-8&rsv_cq=%E5%91%A8%E6%98%9F%E9%A9%B0&rsv_dl=0_right_fyb_pchot_20811_01&rsv_pq=959254a60034f017&oq=%E5%91%A8%E6%98%9F%E9%A9%B0&rsv_t=abf2fwdknQ1VTZk3EzyT0N5%2FpcQzkjPt5GRZchjVdppW7k8B8oI6R5IL3T0myEMmjxXM&rsf=dd45f07d69719294a2ea6117b312f1d7_1_10_1\" class=\"c-font-medium c-color-t opr-toplist1-subtitle\">\n" +// " 印度累计确诊病例已超2000万例\n" +// " </a>\n" +// " </td>\n" +// " <td class=\"toplist1-right-num toplist1-td c-color-gray\" style=\"line-height:20px;position:relative;top:2px;\">473万</td>\n" +// " </tr>\n" +// " <tr class=\"toplist1-tr\">\n" + </tbody> </table>\n" +// " </div>"; String content = "公有地址(Private address)属于非注册地址,专门为组织机构外部应用。\n" + "以下列出留用的外部公有地址\n" + "A类 10.0.0.0--10.255.255.255\n" + "B类 172.16.0.0--172.31.255.255\n" + "C类 192.168.0.0--192.168.255.255"; //提取文章中所有的英文单词 //提取文章中所有的数字 //提取文章中所有的英文单词和数字 //提取百度热榜 题目 //(1). 传统办法. 应用遍历形式,代码量大,效率不高 //(2). 正则表达式技术 //1. 先创立一个Pattern对象 , 模式对象, 能够了解成就是一个正则表达式对象 //Pattern pattern = Pattern.compile("[a-zA-Z]+"); //Pattern pattern = Pattern.compile("[0-9]+"); //Pattern pattern = Pattern.compile("([0-9]+)|([a-zA-Z]+)"); //Pattern pattern = Pattern.compile("<a target=\"_blank\" title=\"(\\S*)\""); Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+\\.\\d+"); //2. 创立一个匹配器对象 //了解: 就是 matcher 匹配器依照 pattern(模式/款式), 到 content 文本中去匹配 //找到就返回true, 否则就返回false int no = 0; Matcher matcher = pattern.matcher(content); //3. 能够开始循环匹配 while (matcher.find()) { //匹配内容,文本,放到 m.group(0) System.out.println("找到: " + (++no) + " " +matcher.group(0)); } }}再提出几个问题给你一个字符串(或文章).请你找出所有四个数字连在一起的子串?给你一个字符串(或文章),请你找出所有四个数字连在一起的子串,并且这四个数字要满足:第一位与第四位雷同,第二位与第三位雷同,比方1221,5775请验证输出的邮件,是否合乎电子邮件格局.请验证输出的手机号,是否合乎手机号格局解决之道-正则表达式为了解决上述问题,Java提供了正则表达式技术,专门用于解决相似文本问题简略的说:正则表达式是对字符串执行模式匹配的技术。正则表达式: regular expression => RegExp正则表达式根本介绍介绍一个正则表达式,就是用某种模式去匹配字符串的一个公式。正则表达式不是只有java才有,实际上很多编程语言都反对正则表达式进行字符串操作正则表达式底层实现实例剖析为让大家对正则表达式底层实现有一个直观的映象,给大家举个实例给你一段字符串(文本), 请找出所有四个数字连在一起的子串, 比方:应该找到1998 1999 3443 9889 ===> 剖析底层实现 ...

May 17, 2023 · 11 min · jiezi

关于java:聊一聊适配器模式

接口不能用?行,我帮你适配一、概述适配器模式(Adapter),是23种设计模式中的结构型模式之一;它就像咱们电脑上接口不够时,须要用到的拓展坞,起到转接的作用。它能够将新的性能和原先的性能连接起来,使因为需要变动导致不能用的性能,从新利用起来。 上图的Mac上,只有两个typec接口,当咱们须要用到USB、网线、HDMI等接口时,这就不够用了,所以咱们须要一个拓展坞来减少电脑的接口 言归正传,上面来理解下适配器模式中的角色:请求者(client)、指标角色(Target)、源角色(Adaptee)、适配器角色(Adapter),这四个角色是保障这个设计模式运行的要害。 client:须要应用适配器的对象,不须要关怀适配器外部的实现,只对接指标角色。Target:指标角色,和client间接对接,定义了client须要用到的性能。Adaptee:须要被进行适配的对象。Adapter:适配器,负责将源对象转化,给client做适配。二、入门案例适配器模式也分两种:对象适配器、类适配器。其实两种形式的区别在于,适配器类中的实现,类适配器是通过继承源对象的类,对象适配器是援用源对象的类。 当然两种形式各有优缺点,咱别离来说下; 类适配器:因为采纳继承模式,在适配器中能够重写Adaptee原有的办法,使得适配器能够更加灵便;然而有局限性,Java是单继承模式,所以适配器类只能继承Adaptee,不能在额定继承其余类,也导致Target类只能是接口。 对象适配器:这个模式躲避了单继承的劣势,将Adaptee类用援用的形式传递给Adapter,这样能够传递的是Adaptee对象自身及其子类对象,相比类适配器更加的凋谢;然而也正是因为这种开放性,导致须要本人从新定义Adaptee,减少额定的操作。 类适配器UML图 对象适配器UML图 上面,是联合下面电脑的场景,写的一个入门案例,别离是四个类:Client、Adaptee、Adapter、Target,代表了适配器模式中的四种角色。 /** * @author 往事如风 * @version 1.0 * @date 2023/5/9 15:54 * @description:源角色 */public class Adaptee { /** * 须要被适配的适配的性能 * 以Mac笔记本的typec接口举例 */ public void typeC() { System.out.println("我只是一个typeC接口"); }}/** * @author 往事如风 * @version 1.0 * @date 2023/5/9 15:57 * @description:指标接口 */public interface Target { /** * 定义一个转接性能的入口 */ void socket();}/** * @author 往事如风 * @version 1.0 * @date 2023/5/9 16:00 * @description:适配器 */public class Adapter extends Adaptee implements Target { /** * 实现适配性能 * 以Mac的拓展坞为例,拓展更多的接口:usb、typc、网线插口... */ @Override public void socket() { typeC(); System.out.println("新增usb插口。。。"); System.out.println("新增网线插口。。。"); System.out.println("新增typec插口。。。"); }}/** * @author 往事如风 * @version 1.0 * @date 2023/5/9 15:52 * @description:请求者 */public class Client { public static void main(String[] args) { Target target = new Adapter(); target.socket(); }}这个案例比较简单,仅仅是一个入门的demo,也是类适配器模式的案例,采纳继承模式。在对象适配器模式中,区别就是Adapter这个适配器类,采纳的是组合模式,上面是对象适配器模式中Adapter的代码; ...

May 17, 2023 · 4 min · jiezi

关于java:腾讯开源的-3-个-GitHub-项目足够良心

1、零碎清理工具去年腾讯开源了一个零碎清理工具:腾讯柠檬清理,该软件能够系统性解决 macOS 设施空间问题。 重点聚焦清理性能,对上百款软件提供定制化的清理计划,提供业余的清理倡议,帮忙用户轻松实现一键式的清理。 次要性能包含:深度扫描清理、大文件清理、反复文件清理、类似照片清理、浏览器隐衷清理、利用卸载、开启启动项治理、自定义状态栏展现信息。 开源地址:https://github.com/Tencent/lemon-cleaner 2、开源的 Markdown 编辑器Cherry Markdown Editor 是一款 Javascript Markdown 编辑器,具备开箱即用、轻量简洁、易于扩大等特点,它能够运行在浏览器或服务端(NodeJs). 当 Cherry Markdown 编辑器反对的语法不满足开发者需要时,能够疾速的进行二次开发或性能扩大。 同时,CherryMarkdown编辑器应该由纯JavaScript实现,不应该依赖 Angular、Vue、React 等框架技术,框架只提供容器环境即可。 开源地址:https://github.com/Tencent/cherry-markdown举荐一个开源收费的 Spring Boot 最全教程: https://github.com/javastacks/spring-boot-best-practice反对 Markdown 语法 表格反对 图标 多光标批量编辑 3、代码平安指南面向开发人员梳理的代码平安指南,旨在梳理 API 层面的危险点并提供详实可行的平安编码方案。该代码平安指南可用于开发人员日常参考或者批改破绽时进行修复指引。 开源地址:https://github.com/Tencent/secguide 近期热文举荐: 1.1,000+ 道 Java面试题及答案整顿(2022最新版) 2.劲爆!Java 协程要来了。。。 3.Spring Boot 2.x 教程,太全了! 4.别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!! 5.《Java开发手册(嵩山版)》最新公布,速速下载! 感觉不错,别忘了顺手点赞+转发哦!

May 16, 2023 · 1 min · jiezi

关于java:Java-向PDF中添加图像水印

水印个别用于标注文档的版权信息、作者、所属机构或者文档属性等。不同于文本批注等,文字水印是绘制到页面中的元素,所以不会被轻易删除。因而,水印也是一种很好的防伪伎俩。水印又分为文本水印和图片水印两种。之前曾经介绍过向PDF中增加文本水印的办法。这次,我将分享通过Java代码给PDF文档增加图像水印的具体方法和示例代码。应用到的工具是Free Spire.PDF 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/repository/maven-public/</url> </repository></repositories><dependencies> <dependency> <groupId>e-iceblue</groupId> <artifactId>spire.pdf.free</artifactId> <version>5.1.0</version> </dependency></dependencies>办法二:如果您没有应用 maven,则能够从此链接下载Free Spire.PDF for Java,找到lib文件夹下的Spire.Pdf.jar并进行解压;而后在IDEA中创立一个新我的项目,顺次点击“文件”(File),“我的项目构造”(Project Structure),“组件”(Modules),“依赖项”(Dependencies),再点击右方绿色“+”下的第一个选项“JAR文件或门路”(JARs or Directories),找到解压后的Spire.Pdf.jar 文件,点击确认,将其导入到我的项目中。 单个图像水印代码介绍:首先,创立一个新的PdfDocument对象。接着,应用loadFromFile()办法从磁盘上载入PDF文档和要嵌入的图片。而后,循环遍历所有页面以插入水印。对于每个页面,获取页面的宽度和高度,并设置图片的透明度和初始坐标。应用drawImage()办法在页面的两头地位绘制水印图片。最初,应用saveToFile()办法指定要保留的文件名和文件格式,并将批改后的PDF文档保留在磁盘上。 残缺代码:import com.spire.pdf.PdfDocument;import com.spire.pdf.PdfPageBase;import com.spire.pdf.graphics.PdfImage;public class insertSingleImageWatermark { public static void main(String[] args) { //创立PdfDocument类的对象 PdfDocument pdf = new PdfDocument(); //载入PDF文档 pdf.loadFromFile("sample.pdf"); //载入图片 PdfImage image = PdfImage.fromFile("image.png"); //获取图片的宽度和高度用于计算插入水印的初始坐标 int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); //循环遍历所有页面以插入水印 for (int i = 0; i < pdf.getPages().getCount(); i++) { //获取一个页面 PdfPageBase page = pdf.getPages().get(i); //获取该页面的宽度和高度,用于计算插入水印的初始坐标 float pageWidth = (float) (page.getActualSize().getWidth()); float pageHeight = (float) (page.getActualSize().getHeight()); //设置水印图片的透明度 page.getCanvas().setTransparency(0.3f); //在页面的两头地位绘制水印图片 page.getCanvas().drawImage(image, pageWidth/2 - imageWidth/2, pageHeight/2 - imageHeight/2, imageWidth, imageHeight); } //保存文档 pdf.saveToFile("result1.pdf"); }}效果图: ...

May 16, 2023 · 1 min · jiezi

关于java:AREX-Agent-源码解读之全链路跟踪和-Mock-数据读写

AREX 是一款开源的自动化测试工具,通过 Java Agent 字节码注入技术,在生产环境录制和存储申请、应答数据,随后在测试环境回放申请和注入 Mock 数据,存储新的应答,以此来达到主动录制、主动回放、主动比对,为接口回归测试提供便当。在进行数据采集时,同一个申请,会采集下来多条数据(如 Request/Response、其它服务调用的申请响应等),AREX 通过链路跟踪将这些数据串联起来,并做为一个残缺的测试用例。本文将深刻解读 AREX Agent 中对于全链路跟踪和 Mock 数据读写的源码。 AREX 的链路跟踪相似于 OpenTelemetry,上面就先简略介绍一下 OpenTelemetry 中如何实现全链路跟踪。 OpenTelemetry 的全链路跟踪的实现OpenTelemetry 是一种用于分布式系统的开源观测性工具,其全链路跟踪的实现依赖于上下文(Context)流传机制, 数据流传依照场景分为过程内流传和分布式流传两类。在过程内流传中,上下文对象在一个服务外部传递 Trace,绝对比较简单。而在分布式流传中,Context propagation 在不同的服务之间传递上下文信息。 上下文(Context)在 OpenTelemetry 中,context 是一个蕴含键值对的数据结构,例如线程或循环程序,用于在申请处理过程中传递数据。在每种编程语言中,OpenTelemetry 都提供了一个上下文对象,例如在 Java 中,OpenTelemetry 应用 ThreadLocal 来存储上下文;在 Go 中,OpenTelemetry 应用 context 包来存储上下文;在 Node.js 中,OpenTelemetry 应用 async_hooks 包来存储上下文;在 Python 中,OpenTelemetry 应用 threading.local 来存储上下文。在 C++ 中,OpenTelemetry 应用 Boost.Context 库来实现上下文的治理。 Context 可用于存储跟踪(Tracing)、日志(Logging)和指标(Metrics)数据等信号,并且能够通过 API 进行拜访,通过调用这些 API 能够拜访整个上下文对象,这意味着 Tracing、Logging 和 Metrics 信号是互相集成的,在整个上下文中共享数据。例如,如果同时启用了 Tracing 和 Metrics 信号,记录一个 Metrics 能够主动创立一个 Tracing 范例。Logging 也是如此:如果有的话,Logging 会主动绑定到以后的 Tracing。 ...

May 16, 2023 · 5 min · jiezi

关于java:java锁类型及其升级流程

1, 背景:加锁(重量级锁)是一种阻塞期待的行为, 在某些场景下,能够用别的计划来代替阻塞,晋升cpu利用率,让cpu不必在那闲着2,重入锁场景:某线程在持有某锁时, 再次申请该锁,这种场景下,产生了 偏差锁. 偏差锁是第一次桎梏时的锁的类型.这个第一步的逻辑是,从锁对象头的mark word里判断以后锁是否偏差锁,且持有锁的线程是否以后线程,如果是,则锁胜利.如果否, 则批改mark word里的锁类型 ,改为轻量级锁3,当获取到锁之后执行的工作耗时较低时,比方对某个变量自增,其余的竞争锁能够让cpu循环屡次尝试竞争锁,这个行为就是自旋, 此时的锁类型 是轻量级锁.4,当获取到锁之后执行的工作耗时较高时,其余线程自旋肯定次数后,发现依然没取得锁, 此时,就将 mark word里的锁类型升级成 重量级锁. 从此, 有线程想竞争该锁,只有CAS竞争失败, 就只能阻塞了. 参考:https://blog.csdn.net/qq_45795744/article/details/123493673?s...

May 16, 2023 · 1 min · jiezi

关于java:RedisLua同步锁

Redis+Lua同步锁Jedis配置@Configuration@Getter@Setter@Slf4j@ConfigurationProperties(prefix = "jedis")public class JedisConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.password}") private String password; private int timeout; private int maxTotal; private int maxIdle; private int minIdle; @Bean public JedisPool jedisPool() { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxIdle(maxIdle); jedisPoolConfig.setMinIdle(minIdle); jedisPoolConfig.setMaxTotal(maxTotal); JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password); log.info("JedisPool连贯胜利:" + host + "\t" + port); return jedisPool; }}Jedis工具类→获取jedis@Componentpublic class JedisUtil { @Resource private JedisPool jedisPool; /** * 获取Jedis资源 */ public Jedis getJedis() { return jedisPool.getResource(); } /** * 开释Jedis连贯 */ public void close(Jedis jedis) { if (jedis != null) { jedis.close(); } }}redis 锁工具类public class RedisLockUtil { private static final Long RELEASE_SUCCESS = 1L; private static final String PREFIX = "API_LOCK_"; /** * 开释分布式锁 * * @param jedis * @param lockKey * @param valve * @return boolean * @author ll * @date 2023/02/09 14:31 */ public static boolean unLock(Jedis jedis, String lockKey, String valve) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(PREFIX + lockKey), Collections.singletonList(PREFIX + valve)); if (RELEASE_SUCCESS.equals(result)) { return true; } return false; } /** * 加分布式锁 * * @param jedis * @param lockKey * @param valve * @param timeout * @return boolean * @author ll * @date 2023/02/09 14:31 */ public static boolean lock(Jedis jedis, String lockKey, String valve, int timeout) { String script = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then" + " redis.call('expire',KEYS[1],ARGV[2]) return 1 else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(PREFIX + lockKey), Lists.newArrayList(PREFIX + valve, String.valueOf(timeout))); //判断是否胜利 if (RELEASE_SUCCESS.equals(result)) { return true; } return false; }}加锁示例(jedis+lua)@Slf4j@Componentpublic class InterfaceEventListener { @Resource private JedisUtil jedisUtil; @Value("${jedis.lock.cycle-number}") private int cycleNumber; @Value("${jedis.lock.expire-time}") private int expireTime; @Value("${jedis.lock.sleep-time}") private int sleepTime; @Value("${spring.redis.database}") private int database; public void onApplicationEvent(InterfaceEvent event) { Jedis jedis = jedisUtil.getJedis(); jedis.select(database); boolean unLock = false; boolean lock; int currentNumber = 0; try { do { lock = RedisLockUtil.lock(jedis, "lockKey", "valve", expireTime); if (lock) { try { //todo 加锁的代码 } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } finally { unLock = RedisLockUtil.unLock(jedis, detectCode, detectCode); } } currentNumber++; Thread.sleep(sleepTime); } while (!unLock && currentNumber < cycleNumber); } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage()); } finally { jedisUtil.close(jedis); } } }

May 16, 2023 · 2 min · jiezi

关于java:如何在华为云-Code-Arts-上搭建-Android-应用

华为云软件开发生产线 CodeArts 是集华为研发实际、前沿研发理念、先进研发工具为一体的研发云平台,面向开发者提供研发工具服务,让软件开发简略高效。本试验通过示例我的项目 “HelloWorld”,为实验者提供云上开发操作领导。  我的项目介绍 项目名称:HelloWord我的项目简介: 在 Android 中,Hello World 示例由 IDE 生成,并与最先进的最佳实际捆绑在一起。作者:chiuki开源地址: https://github.com/chiuki/android-hello-world开源证书:Apache License 2.0开发语言:Java(100.0%)构建环境:Gradle_Wrapper JDK1.8部署环境:Android我的项目示例:  您将播种相熟应用华为云软件开发生产线 CodeArts,通过本试验,您将可能:应用华为云软件开发生产线 CodeArts 实现代码仓库治理;应用华为云软件开发生产线 CodeArts 实现编译构建。 试验筹备1、注册账号、实名认证注册华为云账号、实名认证,如果您已领有华为账号且已通过实名认证,可间接体验。若您还没有通过实名认证的账号,可通过下方领导,实现集体或企业账号的实名认证。企业账号 如何实现实名认证集体账号 如何实现实名认证2、 点我去开明 CodeArts 体验套餐 (如已开通过 CodeArts 套餐,此步能够跳过。) 开明流程示例截图:   创立我的项目点进 CodeArts 我的项目首页 ,来到新建我的项目操作界面,如下图所示:   创立我的项目流程及示例截图鼠标悬停在 "Scrum" 上,点击 “选用”。  点击标注的 “Scrum” 区域,创立 “Scrum” 类型我的项目,参数如下:① 我的项目设置模板:Scrum,② 项目名称:自定义,③ 其余:默认,如下图:  点击 “确定” 后会跳转到 Backlog 列表治理页,如下图: 创立代码仓库 创立我的项目实现后会主动跳转进入我的项目,点击 “代码”-“代码托管”,(如有新个性弹窗,点击 “立刻体验”,如没有弹窗弹出,请疏忽)。  点击 “一般新建”-“导入内部仓库” 的门路创立代码仓库,如下图所示:  在导入内部仓库页,按如下填写内部仓库信息:源仓库地址: https://codehub.devcloud.cn-north-4.huaweicloud.com/kfwdxm_ch...源仓库拜访权限:不须要用户名 / 明码勾选 “我已浏览并批准 《隐衷政策申明》 和 《CodeArts 服务应用申明》”点击 “下一步” 按钮。 ...

May 16, 2023 · 1 min · jiezi

关于java:史上最全-Activiti-学习教程一文搞定最强工作流引擎

一、工作流介绍1.1 概念工作流(Workflow),就是通过计算机对业务流程自动化执行治理。它次要解决的是“使在多个参与者之间依照某种预约义的规定主动进行传递文档、信息或工作的过程,从而实现某个预期的业务指标,或者促使此指标的实现”。 1.2 工作流零碎一个软件系统中具备工作流的性能,咱们把它称为工作流零碎,一个零碎中工作流的性能是什么?就是对系统的业务流程进行自动化治理,所以工作流是建设在业务流程的根底上,所以一个软件的系统核心基本上还是零碎的业务流程,工作流只是帮助进行业务流程治理。即便没有工作流业务零碎也能够开发运行,只不过有了工作流能够更好的治理业务流程,进步零碎的可扩展性。 1.3 实用行业消费品行业,制造业,电信服务业,银证险等金融服务业,物流服务业,物业服务业,物业管理,大中型进出口贸易公司,政府事业机构,研究院所及教育服务业等,特地是大的跨国企业和集团公司。 1.4 具体利用1、要害业务流程: 订单、报价解决、合同审核、客户电话解决、供应链治理等 2、行政治理类: 出差申请、加班申请、销假申请、用车申请、各种办公用品申请、购买申请、日报周报等但凡原来手工流转解决的行政表单。 3、人事管理类: 员工培训安顿、绩效考评、职位变动解决、员工档案信息管理等。 4、财务相干类: 付款申请、应收款解决、日常报销解决、出差报销、估算和打算申请等。 5、客户服务类: 客户信息管理、客户投诉、申请解决、售后服务治理等。 6、非凡服务类: ISO系列对应流程、品质治理对应流程、产品数据信息管理、贸易公司报关解决、物流公司货物跟踪解决等各种通过表单逐渐手工流转实现的工作均可利用工作流软件主动标准地施行。 1.5 实现形式在没有专门的工作流引擎之前,咱们之前为了实现流程管制,通常的做法就是采纳状态字段的值来跟踪流程的变动状况。这样不同角色的用户,通过状态字段的取值来决定记录是否显示。 针对有权限能够查看的记录,以后用户依据本人的角色来决定审批是否合格的操作。如果合格将状态字段设置一个值,来代表合格;当然如果不合格也须要设置一个值来代表不合格的状况。 这是一种最为原始的形式。通过状态字段尽管做到了流程管制,然而当咱们的流程产生变更的时候,这种形式所编写的代码也要进行调整。 那么有没有业余的形式来实现工作流的治理呢?并且能够做到业务流程变动之后,咱们的程序能够不必扭转,如果能够实现这样的成果,那么咱们的业务零碎的适应能力就失去了极大晋升。 举荐一个开源收费的 Spring Boot 最全教程: https://github.com/javastacks/spring-boot-best-practice二、Activiti7概述2.1 介绍Alfresco软件在2010年5月17日发表Activiti业务流程治理(BPM)开源我的项目的正式启动,其首席架构师由业务流程治理BPM的专家 Tom Baeyens负责,Tom Baeyens就是原来jbpm的架构师,而jbpm是一个十分有名的工作流引擎,当然activiti也是一个工作流引擎。 Activiti是一个工作流引擎, activiti能够将业务零碎中简单的业务流程抽取进去,应用专门的建模语言BPMN2.0进行定义,业务流程依照事后定义的流程进行执行,实现了零碎的流程由activiti进行治理,缩小业务零碎因为流程变更进行系统升级革新的工作量,从而进步零碎的健壮性,同时也缩小了零碎开发保护老本。 官方网站:https://www.activiti.org/ 经验的版本: 目前最新版本:Activiti7.0.0.Beta2.1.1 BPMBPM(Business Process Management),即业务流程治理,是一种规范化的结构端到端的业务流程,以继续的进步组织业务效率。常见商业治理教育如EMBA、MBA等均将BPM蕴含在内。 2.1.2 BPM软件BPM软件就是依据企业中业务环境的变动,推动人与人之间、人与零碎之间以及零碎与零碎之间的整合及调整的经营办法与解决方案的IT工具。 通过BPM软件对企业外部及内部的业务流程的整个生命周期进行建模、自动化、治理监控和优化,使企业老本升高,利润得以大幅晋升。 BPM软件在企业中应用领域宽泛,但凡有业务流程的中央都能够BPM软件进行治理,比方企业人事办公治理、洽购流程治理、公文审批流程治理、财务管理等。 2.1.3 BPMNBPMN(Business Process Model AndNotation)- 业务流程模型和符号 是由BPMI(BusinessProcess Management Initiative)开发的一套规范的业务流程建模符号,应用BPMN提供的符号能够创立业务流程。 2004年5月公布了BPMN1.0标准.BPMI于2005年9月并入OMG(The Object Management Group对象治理组织)组织。OMG于2011年1月公布BPMN2.0的最终版本。 具体倒退历史如下: BPMN 是目前被各 BPM 厂商宽泛承受的 BPM 规范。Activiti 就是应用 BPMN 2.0 进行流程建模、流程执行治理,它包含很多的建模符号,比方:Event ...

May 16, 2023 · 8 min · jiezi

关于java:Java-中-ArrayList-和-LinkedList-有什么区别

在Java中,ArrayList和LinkedList是两种常见的汇合类。它们都实现了List接口,提供了相似数组的性能,能够存储任意类型的对象。尽管它们都能够实现雷同的性能,然而它们的底层实现形式有所不同,因而在性能和用处上也存在一些差别。 ArrayListArrayList是一个基于数组实现的动静数组,它能够主动扩大容量以包容新的元素。在ArrayList中,元素存储在一个Object数组中,能够通过索引拜访数组中的元素。 底层原理ArrayList底层应用数组实现,每个ArrayList实例都蕴含一个Object类型的数组elementData,用于存储元素。当ArrayList中的元素数量超过数组容量时,ArrayList会主动扩容,创立一个新的数组,并将原数组中的元素复制到新数组中。 private transient Object[] elementData;在ArrayList中,增加元素的操作能够分为两种状况: 如果数组容量足够,间接将元素增加到数组开端。如果数组容量有余,须要先对数组进行扩容,而后将元素增加到数组开端。public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true;}private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity);}private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity);}在ArrayList中,删除元素的操作能够分为两种状况: ...

May 16, 2023 · 2 min · jiezi

关于java:什么是Java中的阻塞队列它有什么作用

在Java中,阻塞队列是一种非凡的队列,它能够在队列为空或队列已满时阻塞增加或移除元素的操作。阻塞队列通常用于多线程编程中,能够帮忙咱们更加不便地进行线程通信和合作。在本文中,我将从面试的角度,具体解说Java中的阻塞队列的概念、作用和实现形式,并提供相干的代码示例。 概念在Java中,阻塞队列是一种非凡的队列,它能够在队列为空或队列已满时阻塞增加或移除元素的操作。阻塞队列通常包含以下几个办法: put(E e):将元素e增加到队列中,如果队列已满,则阻塞期待直到队列有闲暇地位。take():从队列中移除并返回元素,如果队列为空,则阻塞期待直到队列中有元素。offer(E e, long timeout, TimeUnit unit):将元素e增加到队列中,在超时工夫内期待队列有闲暇地位,如果超时依然没有闲暇地位,则返回false。poll(long timeout, TimeUnit unit):从队列中移除并返回元素,在超时工夫内期待队列中有元素,如果超时依然没有元素,则返回null。阻塞队列的作用是帮忙咱们更加不便地进行线程通信和合作。在多线程编程中,线程之间须要进行通信和合作,例如生产者线程向队列中增加元素,消费者线程从队列中取出元素等。应用阻塞队列能够简化线程通信和合作的逻辑,并缩小线程之间的竞争和抵触。 实现形式在Java中,阻塞队列能够通过两种形式实现:手动实现和应用Java规范库。 手动实现阻塞队列的手动实现通常包含以下步骤: 创立一个数组或链表作为队列存储元素。应用一个计数器记录队列中元素的数量。在put()办法中,如果队列已满,则阻塞期待直到队列有闲暇地位,并在队列中增加元素。在take()办法中,如果队列为空,则阻塞期待直到队列中有元素,并从队列中移除并返回元素。以下是一个手动实现的阻塞队列示例代码: public class BlockingQueue<E> { private final Object[] items; private int count; private int putIndex; private int takeIndex; public BlockingQueue(int capacity) { items = new Object[capacity]; } public synchronized void put(E e) throws InterruptedException { while (count == items.length) { wait(); } items[putIndex] = e; putIndex = (putIndex + 1) % items.length; count++; notifyAll(); } public synchronized E take() throws InterruptedException { while (count == 0) { wait(); } E e = (E) items[takeIndex]; takeIndex = (takeIndex + 1) % items.length; count--; notifyAll(); return e; }}在这个示例中,咱们实现了一个BlockingQueue类,用于存储元素,并增加了put()和take()办法用于增加和移除元素。在put()办法中,如果队列已满,则调用wait()办法将线程阻塞,直到队列有闲暇地位。在增加元素后,调用notifyAll()办法告诉其余线程能够从队列中移除元素。在take()办法中,如果队列为空,则调用wait()办法将线程阻塞,直到队列中有元素。在移除元素后,调用notifyAll()办法告诉其余线程能够向队列中增加元素。 ...

May 16, 2023 · 1 min · jiezi

关于java:什么是-Java-中的-AOP面向切面编程如何使用它来实现横切关注点

AOP(Aspect-oriented programming,面向切面编程),是一种编程思维和技术,旨在将横切关注点和主业务逻辑拆散,使得零碎更容易扩大和保护。在 Java 中,AOP 次要通过代理模式和动静字节码生成实现。本文将介绍 AOP 的基本概念、实现原理以及如何应用 AOP 来实现横切关注点。 AOP 的基本概念在传统的面向对象编程中,次要关注的是对象的行为和属性。面向对象编程通过封装、继承和多态等机制,将零碎分解成多个独立的对象,并通过对象之间的交互来实现业务逻辑。然而,在理论开发中,业务逻辑往往会波及到一些与业务自身无关的横切关注点,如日志记录、安全检查、事务管理等。这些横切关注点并不属于主业务逻辑,然而它们会分布在整个零碎中,使得零碎难以扩大和保护。 AOP 的呈现正是为了解决这个问题。AOP 将横切关注点和主业务逻辑拆散,通过横向切割零碎进行模块化设计,将横切关注点封装成切面,通过切面来实现对主业务逻辑的加强。这样,零碎就能够更容易地扩大和保护,同时也进步了代码的复用性和可维护性。 AOP 的实现原理在 Java 中,AOP 次要通过代理模式和动静字节码生成实现。代理模式是一种常见的设计模式,它能够为一个对象提供一个代理对象,通过代理对象来管制对原对象的拜访。在 AOP 中,代理对象能够拦挡对指标对象的办法调用,并在办法调用前、后或抛出异样时执行一些额定的操作,如记录日志、查看安全性、进行事务管理等。 在 Java 中,代理模式次要有两种实现形式:动态代理和动静代理。动态代理是在编译期间生成代理类,代理类和指标类之间的关系是固定的。而动静代理是在运行期间生成代理类,代理类和指标类之间的关系是动静的。Java 中的动静代理次要通过反射和 InvocationHandler 接口实现。 动静代理的实现原理如下: 定义一个接口和实现类定义一个接口和实现类,其中实现类是指标对象。 实现 InvocationHandler 接口实现 InvocationHandler 接口,该接口中有一个 invoke() 办法,该办法在代理对象调用指标办法时被调用。在该办法中,咱们能够在指标办法调用前后执行一些额定的操作。 获取代理对象通过 Proxy 类的静态方法 newProxyInstance() 获取代理对象。该办法须要传入一个类加载器、一个接口数组和一个 InvocationHandler 对象。在办法中,会通过反射动静生成代理类,并返回代理对象。 应用 AOP 实现横切关注点应用 AOP 实现横切关注点须要分为以下几个步骤: 第一:定义切面 定义一个切面类,该类中蕴含了切点和加强办法。切点定义了哪些办法须要被拦挡,而加强办法定义了在拦挡办法前后须要执行的操作。 第二:配置切面 在配置文件中配置切面,指定切点和加强办法。 第三:创立代理对象 通过 AOP 框架创立代理对象,代理对象会主动将切面织入到指标对象中,从而实现对指标对象的加强。 上面是一个应用 Spring AOP 实现横切关注点的示例代码: 定义切面 @Component@Aspectpublic class LogAspect { @Pointcut("execution(* com.example.service.*.*(..))") public void pointcut() {} @Before("pointcut()") public void before(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println("办法 " + methodName + " 开始执行..."); } @AfterReturning("pointcut()") public void afterReturning(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println("办法 " + methodName + " 执行胜利!"); } @AfterThrowing(value = "pointcut()", throwing = "ex") public void afterThrowing(JoinPoint joinPoint, Exception ex) { String methodName = joinPoint.getSignature().getName(); System.out.println("办法 " + methodName + " 执行失败,异样信息:" + ex.getMessage()); }}在该切面中,定义了一个切点,该切点匹配了 com.example.service 包中的所有办法。同时,切面中还定义了三个加强办法:Before、AfterReturning 和 AfterThrowing。Before 办法在指标办法调用前执行,用于记录办法开始执行的日志;AfterReturning 办法在指标办法执行胜利后执行,用于记录办法执行胜利的日志;AfterThrowing 办法在指标办法抛出异样时执行,用于记录办法执行失败的日志。 ...

May 16, 2023 · 1 min · jiezi

关于java:Java数据库项目之满汉楼

文章和代码曾经归档至【Github仓库:https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。程序框架图 代码实现数据库-- 创立满汉楼的数据库CREATE DATABASE mhl-- 创立表 employee 表 (主键id, empId, name, pwd, job, 如果须要能够本人加字段等)#用户表CREATE TABLE employee ( id INT PRIMARY KEY AUTO_INCREMENT, #自增 empId VARCHAR(50) UNIQUE NOT NULL DEFAULT '',#员工号 pwd CHAR(32) NOT NULL DEFAULT '',#明码md5 NAME VARCHAR(50) NOT NULL DEFAULT '',#姓名 job VARCHAR(50) NOT NULL DEFAULT '' #岗位)CHARSET=utf8; DROP TABLE employee#增加测试数据INSERT INTO employee VALUES(NULL, '6668612', MD5('123456'), '张三丰', '经理');INSERT INTO employee VALUES(NULL, '6668622', MD5('123456'),'小龙女', '服务员');INSERT INTO employee VALUES(NULL, '6668633', MD5('123456'), '张无忌', '收银员');INSERT INTO employee VALUES(NULL, '666666', MD5('123456'), '老韩', '经理');SELECT * FROM employee;SELECT * FROM employee WHERE empId='666666' AND pwd=MD5('123456')-- 创立diningTable 表(id, state , orderName, orderTel ....)CREATE TABLE diningTable ( id INT PRIMARY KEY AUTO_INCREMENT, #自增, 示意餐桌编号 state VARCHAR(20) NOT NULL DEFAULT '',#餐桌的状态 orderName VARCHAR(50) NOT NULL DEFAULT '',#预订人的名字 orderTel VARCHAR(20) NOT NULL DEFAULT '')CHARSET=utf8; #测试数据INSERT INTO diningTable VALUES(NULL, '空','','');INSERT INTO diningTable VALUES(NULL, '空','','');INSERT INTO diningTable VALUES(NULL, '空','','');SELECT * FROM diningTableSELECT * FROM diningTableSELECT * FROM diningTable WHERE id = 1UPDATE diningTable SET state='空', orderName='', orderTel='' WHERE id=1-- 创立menu表(id, name, type, price)#菜谱CREATE TABLE menu ( id INT PRIMARY KEY AUTO_INCREMENT, #自增主键,作为菜谱编号(惟一) NAME VARCHAR(50) NOT NULL DEFAULT '',#菜品名称 TYPE VARCHAR(50) NOT NULL DEFAULT '', #菜品品种 price DOUBLE NOT NULL DEFAULT 0#价格)CHARSET=utf8; #测试数据INSERT INTO menu VALUES(NULL, '八宝饭', '主食', 10);INSERT INTO menu VALUES(NULL, '叉烧包', '主食', 20);INSERT INTO menu VALUES(NULL, '宫保鸡丁', '热菜', 30);INSERT INTO menu VALUES(NULL, '山药拨鱼', '凉菜', 14);INSERT INTO menu VALUES(NULL, '银丝卷', '甜食', 9);INSERT INTO menu VALUES(NULL, '水煮鱼', '热菜', 26);INSERT INTO menu VALUES(NULL, '甲鱼汤', '汤类', 100);INSERT INTO menu VALUES(NULL, '鸡蛋汤', '汤类', 16);SELECT * FROM menu;#同学们能够独自创立一张表,示意菜品的类别#减少表 bill 账单表(id, billId, menuId, nums, billDate, money, state, diningTableId )#账单流水, 思考能够离开结账, 并思考未来别离统计各个不同菜品的销售状况CREATE TABLE bill ( id INT PRIMARY KEY AUTO_INCREMENT, #自增主键 billId VARCHAR(50) NOT NULL DEFAULT '',#账单号能够依照本人规定生成 UUID menuId INT NOT NULL DEFAULT 0,#菜品的编号, 也能够应用外键 nums INT NOT NULL DEFAULT 0,#份数 money DOUBLE NOT NULL DEFAULT 0, #金额 diningTableId INT NOT NULL DEFAULT 0, #餐桌 billDate DATETIME NOT NULL ,#订单日期 state VARCHAR(50) NOT NULL DEFAULT '' # 状态 '未结账' , '曾经结账', '挂单','现金','支付宝','坏账')CHARSET=utf8;SELECT * FROM bill;select * from billSELECT * FROM menu WHERE id = 1UPDATE diningTable SET state=? WHERE id=?SELECT * FROM diningTable-- 查出某个餐桌是否有未结账的账单select * from bill where diningTableId=1 and state = '未结账' limit 0, 1Java`-- src |-- com | `-- hspedu | `-- mhl | |-- dao | | |-- BasicDAO.java | | |-- BillDAO.java | | |-- DiningTableDAO.java | | |-- EmployeeDAO.java | | |-- MenuDAO.java | | `-- MultiTableDAO.java | |-- domain | | |-- Bill.java | | |-- DiningTable.java | | |-- Employee.java | | |-- Menu.java | | `-- MultiTableBean.java | |-- service | | |-- BillService.java | | |-- DiningTableService.java | | |-- EmployeeService.java | | `-- MenuService.java | |-- utils | | |-- JDBCUtilsByDruid.java | | `-- Utility.java | `-- view | `-- MHLView.java `-- druid.propertiessrc/com/hspedu/mhl/dao/BasicDAO.java ...

May 16, 2023 · 16 min · jiezi

关于java:不是单例的单例巧用ClassLoader

本文通过如何将一个单例类实例化两次的案例,用代码实际来引入 Java 类加载器相干的概念与工作机制。了解并熟练掌握相干常识之后能够扩宽解决问题的思路,另辟蹊径,达到目标。背景单例模式是最罕用的设计模式之一。其目标是保障一个类在过程中仅有一个实例,并提供一个它的全局拜访形式。那什么场景下一个过程里须要单例类的两个对象呢?很显著这毁坏了单例模式的设计初衷。 这里举例一个我司的非凡场景: RPC 的调用标准是每个业务集群里只能有一个调用方,如果一个业务节点曾经实例化了一个客户端,就无奈再实例化另一个。这个标准的目标是让一个集群对立个调用方,不便服务数据的收集、展现、告警等操作。 一个我的项目有多个集群,多个项目组保护,各个集群都有一个独特特点,须要调用雷同的 RPC 服务。如果严格依照上述 RPC 标准的话,每一个集群都须要申请一个本人调用方,每一个调用方都申请雷同的 RPC 服务。这样做齐全没有问题,只是雷同的工作会被各个集群都做一遍,并且生成了多个 RPC 的调用方。 最终计划是将雷同的逻辑代码打包成一个专用 jar 包,而后其余集群引入这个包就能解决咱们上述的问题。这么做的话就碰到了 RPC 标准中的束缚问题,jar 包里的专用逻辑会调用 RPC 服务,那么势必会有一个 RPC 的专用调用方。咱们的业务代码里也会有本人业务须要调用的其余 RPC 服务,这个调用方和 jar 包里的调用方就抵触了,只能有一个调用方会被胜利初始化,另一个则会报错。这个场景是不是就要实例化两个单例模式的对象呢。 有相干教训的读者可能会想到,能不能把各个集群中雷同的工作抽取进去,做成一个相似网关的集群,而后各个集群再来调用这个专用集群,这样同一个工作也不会被做多遍,RPC 的调用方也被整合成了一个。这个计划也是很好的,思考到一些客观因素,最终并没有抉择这种形式。 实例化两个单例类咱们假如下述单例类代码是 RPC 的调用 Client: public class RPCClient { private static BaseClient baseClient; private volatile static RPCClient instance; static { baseClient = BaseClient.getBaseClient(); } private RPCClient() { System.out.println("结构 Client"); } public String callRpc() { return "callRpc success"; } public static RPCClient getClient() { if (instance == null) { synchronized (RPCClient.class) { if (instance == null) { instance = new RPCClient(); } } } return instance; }}public class BaseClient { ... private BaseClient() { System.out.println("结构 BaseClient"); } ...}这个单例 Client 有一点点不同,就是有一个动态属性 baseClient,BaseClient 也是一个简略的单例类,构造方法里有一些打印操作,不便后续察看。baseClient 属性通过动态代码块来赋值。 ...

May 15, 2023 · 4 min · jiezi

关于java:MySQL-驱动中虚引用-GC-耗时优化与源码分析

本文要点:一种优雅解决 MySQL 驱动中虚援用导致 GC 耗时较长问题的解决办法虚援用的作用与应用场景MySQL 驱动源码中的虚援用剖析背景 在之前文章中写过 MySQL JDBC 驱动中的虚援用导致 JVM GC 耗时较长的问题(能够看这里),在驱动代码(mysql-connector-java 5.1.38版本)中 NonRegisteringDriver 类有个虚援用汇合 connectionPhantomRefs 用于存储所有的数据库连贯,NonRegisteringDriver.trackConnection 办法负责把新创建的连贯放入汇合,虚援用随着工夫积攒越来越多,导致 GC 时解决虚援用的耗时较长,影响了服务的吞吐量: public ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) throws SQLException { ... NonRegisteringDriver.trackConnection(this); ...}public class NonRegisteringDriver implements Driver { ...  protected static final ConcurrentHashMap<ConnectionPhantomReference, ConnectionPhantomReference> connectionPhantomRefs = new ConcurrentHashMap();   protected static void trackConnection(com.mysql.jdbc.Connection newConn) {        ConnectionPhantomReference phantomRef = new ConnectionPhantomReference((ConnectionImpl)newConn, refQueue);        connectionPhantomRefs.put(phantomRef, phantomRef);   } ...} 尝试缩小数据库连贯的生成速度,来升高虚援用的数量,然而成果并不现实。最终的解决方案是通过反射获取虚援用汇合,利用定时工作来定期清理汇合,防止 GC 解决虚援用耗时较长。 ...

May 15, 2023 · 3 min · jiezi

关于java:SpringBoot-使用-SaToken-完成注解鉴权功能

注解鉴权 —— 优雅的将鉴权与业务代码拆散。本篇咱们将介绍在 Sa-Token 中如何通过注解实现权限校验。 Sa-Token 是一个轻量级 java 权限认证框架,次要解决登录认证、权限认证、单点登录、OAuth2、微服务网关鉴权 等一系列权限相干问题。Gitee 开源地址:https://gitee.com/dromara/sa-token一、Sa-Token 鉴权注解一览Sa-Token 为咱们提供的鉴权注解包含但不限于以下: @SaCheckLogin: 登录校验 —— 只有登录之后能力进入该办法。@SaCheckRole("admin"): 角色校验 —— 必须具备指定角色标识能力进入该办法。@SaCheckPermission("user:add"): 权限校验 —— 必须具备指定权限能力进入该办法。@SaCheckSafe: 二级认证校验 —— 必须二级认证之后能力进入该办法。@SaCheckBasic: HttpBasic校验 —— 只有通过 Basic 认证后能力进入该办法。@SaCheckDisable("comment"):账号服务封禁校验 —— 校验以后账号指定服务是否被封禁。@SaIgnore:疏忽校验 —— 示意被润饰的办法或类无需进行注解鉴权和路由拦截器鉴权。首先在我的项目中引入 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 的全局拦截器注册到你我的项目中。 以SpringBoot2.0为例,新建配置类SaTokenConfigure.java @Configurationpublic class SaTokenConfigure implements WebMvcConfigurer { // 注册 Sa-Token 拦截器,关上注解式鉴权性能 @Override public void addInterceptors(InterceptorRegistry registry) { // 注册 Sa-Token 拦截器,关上注解式鉴权性能 registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**"); }}保障此类被springboot启动类扫描到即可。 ...

May 15, 2023 · 3 min · jiezi

关于java:Spring-Boot-Nacos-实现不停服发布

最近,因为业务属性比拟重要,对服务公布提出了更高的要求,心愿能实现不停服公布。目前,团队所有我的项目曾经实现基于K8s容器化部署,服务注册发现基于Nacos,故本文基于该两前提下进行探讨。 基于该架构下,须要解决如下几个问题: K8s Java 利用实现滚动公布,如果新服务不失常的状况下,不将新服务公布下来,且旧服务不下线服务从Nacos上被动下线,让流量不再流入K8s 滚动公布K8s 已人造反对滚动公布的机制,只须要简略的配置就能够实现咱们的要求,如下是具体配置摘要,我将从上到下进行阐明。 apiVersion: apps/v1kind: Deploymentmetadata: labels: app: example-service name: example-servicespec: #正本数量 replicas: {{.pod_replicas}} selector: matchLabels: app: example-service minReadySeconds: 30 #设置降级延迟时间15秒,期待15秒后降级 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 #降级过程中最多能够比原先设置多出的POD数量 maxUnavailable: 0 template: metadata: labels: app: example-service monitortype: backend spec: #以下内容为可选,容器调度策略,保障同一deployment的多个正本位于不同的机器上,避免单节点挂掉导致服务不可用,因为波及到要与运维沟通资源状况,无奈间接给予固定配置。 affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - example-service topologyKey: kubernetes.io/hostname containers: - image: example-service:latest imagePullPolicy: IfNotPresent name: example-service lifecycle: preStop: exec: command: - curl - '-XPOST' - '127.0.0.1:8080/actuator/shutdown' readinessProbe: # 就绪探针 httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 30 # 提早加载工夫 periodSeconds: 10 # 重试工夫距离 timeoutSeconds: 1 # 超时工夫设置 successThreshold: 1 # 衰弱阈值 failureThreshold: 3 # 不衰弱阈值 livenessProbe: # 存活探针 httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 30 # 提早加载工夫 periodSeconds: 10 # 重试工夫距离 timeoutSeconds: 1 # 超时工夫设置 successThreshold: 1 # 衰弱阈值 failureThreshold: 3 # 不衰弱阈值 ports: - containerPort: 8080 name: backend protocol: TCP envFrom: - configMapRef: #寄存公共环境变量,比方:数据库,redis,nacos等连贯信息,每个我的项目的各个微服务根本都是一样的。 name: pub-cm - configMapRef: #寄存个性化配置,对于个别的服务,除了公共变量外,会波及其余援用信息。 name: example-service-cm env: - name: POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name resources: #设定以下是设定服务资源依据你的我的项目理论状况来 limits: # limits是代表的资源下限,服务能耗费的资源下限 cpu: {{.pod_cpu_limit}} #{limits_cpu}(必须),目前默认单位为m,如果申请一核则为1024m,以此类推,默认则为500m memory: {{.pod_memory_limit}} #{limits_mem}(必须),目前默认单位为Mi,如果申请1G内存则为1024Mi,以此类推,默认则为2048Mi requests: # requests是服务所需最小的启动资源,设置后如果node达不到这个资源要求就会部署失败 cpu: {{.pod_cpu_request}} #{requests_cpu}(必须),目前默认单位为m,如果申请一核则为1024m,以此类推,默认则为250m memory: {{.pod_memory_request}} #{requests_mem}(必须),目前默认单位为Mi,如果申请1G内存则为1024Mi,以此类推,默认则为500Mi # 以下为必须选项,我的项目做日志采集 volumeMounts: - name: host-time readOnly: true mountPath: /etc/localtime - name: example-service-log mountPath: /home/logs # 如果接入日志必须存在容器内/home/logs文件夹下寄存日志文件 subPathExpr: $(POD_NAME) volumes: - name: example-service-log hostPath: path: /home/logs type: DirectoryOrCreate - name: host-time hostPath: path: /etc/localtime type: '' imagePullSecrets: # 写死,前提是要执行这个凭证创立命令 - name: harborha-secret001fe---apiVersion: policy/v1beta1kind: PodDisruptionBudget #设置pod最小可用数量metadata: name: example-service-pdbspec: minAvailable: 50% selector: matchLabels: app: example-serviceRollingUpdate 用于配置服务滚动降级的策略,maxSurge设置降级过程中最多能够比原先设置多出的POD数量。 ...

May 15, 2023 · 2 min · jiezi

关于java:从3s到25ms看看京东的接口优化技巧确实很优雅

大家好,最近看到京东云的一位大佬分享的接口优化计划,感觉挺不错的,拿来即用。倡议珍藏一波或者整顿到本人的笔记本中,随时查阅! 起源:https://toutiao.io/posts/0kwkbbt 上面是注释。 一、背景针对老我的项目,去年做了许多降本增效的事件,其中发现最多的就是接口耗时过长的问题,就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化的通用计划。 二、接口优化计划总结1.批处理批量思维:批量操作数据库,这个很好了解,咱们在循环插入场景的接口中,能够在批处理执行实现后一次性插入或更新数据库,防止屡次 IO。 //for循环单笔入库list.stream().forEatch(msg->{ insert();});//批量入库batchInsert();2. 异步解决异步思维:针对耗时比拟长且不是后果必须的逻辑,咱们能够思考放到异步执行,这样能升高接口耗时。 例如一个理财的申购接口,入账和写入申购文件是同步执行的,因为是 T+1 交易,前面这两个逻辑其实不是后果必须的,咱们并不需要关注它的实时后果,所以咱们思考把入账和写入申购文件改为异步解决。如图所示: 至于异步的实现形式,能够用线程池,也能够用音讯队列,还能够用一些调度工作框架。 举荐一个开源收费的 Spring Boot 最全教程: https://github.com/javastacks/spring-boot-best-practice3. 空间换工夫一个很好了解的空间换工夫的例子是正当应用缓存,针对一些频繁应用且不频繁变更的数据,能够提前缓存起来,须要时间接查缓存,防止频繁地查询数据库或者反复计算。 须要留神的事,这里用了正当二字,因为空间换工夫也是一把双刃剑,须要综合思考你的应用场景,毕竟缓存带来的数据一致性问题也挺令人头疼。 这里的缓存能够是 R2M,也能够是本地缓存、memcached,或者 Map。 举一个股票工具的查问例子: 因为策略轮动的调仓信息,每周只更新一次,所以原来的调接口就去查库的逻辑并不合理,而且拿到调仓信息后,须要通过简单计算,最终得出回测收益和跑赢沪深指数这些咱们想要的后果。如果咱们把查库操作和计算结果放入缓存,能够节俭很多的执行工夫。如图: 4. 预处理也就是预取思维,就是提前要把查问的数据,提前计算好,放入缓存或者表中的某个字段,用的时候会大幅提高接口性能。跟下面那个例子很像,然而关注点不同。 举个简略的例子:理财产品,会有依据净值计算年化收益率的数据展现需要,利用净值去套用年化收益率计算公式计算的逻辑咱们能够采纳预处理,这样每一次接口调用间接取对应字段就能够了。 5. 池化思维咱们都用过数据库连接池,线程池等,这就是池思维的体现,它们解决的问题就是防止反复创建对象或创立连贯,能够反复利用,防止不必要的损耗,毕竟创立销毁也会占用工夫。 池化思维蕴含但并不局限于以上两种,总的来说池化思维的实质是预调配与循环应用,明确这个原理后,咱们即便是在做一些业务场景的需要时,也能够利用起来。 比方:对象池 6. 串行改并行串行就是,以后执行逻辑必须等上一个执行逻辑完结之后才执行,并行就是两个执行逻辑互不烦扰,所以并行相对来说就比拟节省时间,当然是建设在没有后果参数依赖的前提下。 比方,理财的持仓信息展现接口,咱们既须要查问用户的账户信息,也须要查问商品信息和 banner 位信息等等来渲染持仓页,如果是串行,基本上接口耗时就是累加的。如果是并行,接口耗时将大大降低。 如图: 7. 索引加索引能大大提高数据查问效率,这个在接口设计之出也会思考到,这里不再多赘述,随着需要的迭代,咱们重点整顿一下索引不失效的一些场景,心愿对小伙伴们有所帮忙。 具体不失效场景不再一一举例,前面有工夫的话,独自整顿一下。 8. 防止大事务所谓大事务问题,就是运行工夫较长的事务,因为事务统一不提交,会导致数据库连贯被占用,影响到别的申请拜访数据库,影响别的接口性能。 举个例子: @Transactional(value ="taskTransactionManager", propagation =Propagation.REQUIRED, isolation =Isolation.READ_COMMITTED, rollbackFor ={RuntimeException.class,Exception.class}) publicBasicResultpurchaseRequest(PurchaseRecordrecord){ BasicResult result =newBasicResult(); //插入账户工作 taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_account.type(),TaskEnum.Account_bizType.purchase_request.type())); //插入同步工作 taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_sync.type(),TaskEnum.Sync_bizType.purchase.type())); //插入影像件上传工作 taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_sync.type(),TaskEnum.Sync_bizType.cert.type())); result.setInfo(ResultInfoEnum.SUCCESS); return result; }下面这块代码次要是申购申请实现后,执行一系列的后续操作,如果当初新增申购实现后,发送 push 告诉用户的需要。很有可能咱们会在前面间接追加,如下图所示:事务中嵌套 RPC 调用,即非 DB 操作,这些非 DB 操作如果耗时较大的话,可能会呈现大事务问题。大数据引发的问题次要有:死锁、接口超时、主从提早等。 ...

May 15, 2023 · 1 min · jiezi

关于java:JDBC和数据库连接池

文章和代码曾经归档至【Github仓库:https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。JDBC 概述根本介绍JDBC为拜访不同的数据库提供了对立的接口,为使用者屏蔽了细节问题。Java程序员应用JDBC,能够连贯任何提供了JDBC驱动程序的数据库系统,从而实现对数据库的各种操作。JDBC的基本原理图[重要!] 模仿JDBCpackage com.hspedu.jdbc.myjdbc;/** * 咱们规定的jdbc接口(办法) */public interface JdbcInterface { //连贯 public Object getConnection() ; //crud public void crud(); //敞开连贯 public void close();}package com.hspedu.jdbc.myjdbc;/** * mysql 数据库实现了jdbc接口 [模仿] 【mysql厂商开发】 */public class MysqlJdbcImpl implements JdbcInterface{ @Override public Object getConnection() { System.out.println("失去 mysql 的连贯"); return null; } @Override public void crud() { System.out.println("实现 mysql 增删改查"); } @Override public void close() { System.out.println("敞开 mysql 的连贯"); }}package com.hspedu.jdbc.myjdbc;/** * @author 韩顺平 * @version 1.0 * 模仿oracle数据库实现 jdbc */public class OracleJdbcImpl implements JdbcInterface { @Override public Object getConnection() { System.out.println("失去 oracle的连贯 降级"); return null; } @Override public void crud() { System.out.println("实现 对oracle的增删改查"); } @Override public void close() { System.out.println("敞开 oracle的连贯"); }}package com.hspedu.jdbc.myjdbc;import java.io.FileInputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;import java.util.Properties;import java.util.Scanner;public class TestJDBC { public static void main(String[] args) throws Exception { //实现对mysql的操作 JdbcInterface jdbcInterface = new MysqlJdbcImpl(); jdbcInterface.getConnection(); //通过接口来调用实现类[动静绑定] jdbcInterface.crud(); jdbcInterface.close(); //实现对oracle的操作 System.out.println("=============================="); jdbcInterface = new OracleJdbcImpl(); jdbcInterface.getConnection(); //通过接口来调用实现类[动静绑定] jdbcInterface.crud(); jdbcInterface.close(); }}JDBC 带来的益处如果Java间接拜访数据库(示意图) ...

May 15, 2023 · 20 min · jiezi

关于java:云原生背景下如何配置-JVM-内存

背景前段时间业务研发反馈说是他的利用内存使用率很高,导致频繁的重启,让我排查下是怎么回事; 在这之前我也没怎么在意过这个问题,正好这次排查剖析的过程做一个记录。 首先我查看了监控面板里的 Pod 监控: 发现的确是快满了,而此时去查看利用的 JVM 占用状况却只有30%左右;阐明并不是利用内存满了导致 JVM 的 OOM,而是 Pod 的内存满了,导致 Pod 的内存溢出,从而被 k8s 杀掉了。 而 k8s 为了维持利用的正本数量就得重启一个 Pod,所以看起来就是利用运行一段时间后就被重启。 而这个利用配置的是 JVM 8G,容器申请的内存是16G,所以 Pod 的内存占用看起来也就 50% 左右。 容器的原理在解决这个问题之前还是先简略理解下容器的运行原理,因为在 k8s 中所有的利用都是运行在容器中的,而容器实质上也是运行在宿主机上的一个个常常而已。 但咱们应用 Docker 的时候会感觉每个容器启动的利用之间互不烦扰,从文件系统、网络、CPU、内存这些都能齐全隔离开来,就像两个运行在不同的服务器中的利用。 其实这一点也不是啥黑科技,Linux 早就反对 2.6.x 的版本就曾经反对 namespace 隔离了,应用 namespace 能够将两个过程齐全隔离。 仅仅将资源隔离还不够,还须要限度对资源的应用,比方 CPU、内存、磁盘、带宽这些也得做限度;这点也能够应用 cgroups 进行配置。 它能够限度某个过程的资源,比方宿主机是 4 核 CPU,8G 内存,为了爱护其余容器,必须给这个容器配置应用下限:1核 CPU,2G内存。 这张图就很清晰的示意了 namespace 和 cgroups 在容器技术中的作用,简略来说就是: namespace 负责隔离cgroups 负责限度在 k8s 中也有对应的提现: resources: requests: memory: 1024Mi cpu: 0.1 limits: memory: 1024Mi cpu: 4这个资源清单示意该利用至多须要为一个容器调配一个 0.1 核和 1024M 的资源,CPU 的最高下限为 4 个外围。 ...

May 15, 2023 · 1 min · jiezi

关于java:Spring-Boot-配置文件总结

前言Spring Boot 中提供一个全局的配置文件:application.properties,这个配置文件的作用就是,容许咱们通过这个配置文件去批改 Spring Boot 主动配置的默认值。 Spring Boot 反对两种格局的配置文件:application.properties 和 application.yml。 yml 等同于 yaml,写法看集体喜爱,我喜爱写成 application.yml 不同后缀不同写法application.properties 和 application.yml ,它们的区别在于语法不同,但实质上是一样的。application.properties 应用键值对的形式来配置,而 application.yml 应用缩进和冒号的形式来配置。 propertiesproperties 作为后缀的配置文件,语法是这样的:key = value,如果有多级配置项,则是 first.second.third = value。 key=valuefirst.second.third=value示例: 定义属性:key=valuegame.name=GTA5这里的 key 和 game.name 都是属性名称,而 value 和 GTA5 是属性的值。 定义 List:game.list=GTA5,NBA2K,AC这里的 game.list 这个列表蕴含了 3 个元素。 定义 Map:game.map.key1=value1game.map.key2=value2这里的 game.map 是一个 Map,这个 Map 蕴含了两个元素,key1 映射到 value1,key2 映射到 value2 援用已定义的属性:game.name=GTA5# 援用下面已定义的属性great.game=${game.name}yml (yaml)yml 作为后缀的配置文件,语法是这样的:key: value。应用冒号代替等号,同时冒号前面须要跟上一个空格符,不可省略。 key: valuefirst: second: third: value示例: 定义属性:key: valuegame: name: GTA5定义 List:game: list: - GTA5 - NBA2K - AC定义 Map:game: map: key1: value1 key2: value2援用已定义的属性:game: name: GTA5great: game: @{game.name}不同环境下切换不同的配置文件个别我的项目中在不同环境下都有不同的配置,还是以这个 Tomcat 的端口号为例: ...

May 14, 2023 · 3 min · jiezi

关于java:一天吃透SpringCloud面试八股文

1、什么是Spring Cloud ?Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序,提供与内部零碎的集成。Spring cloud Task,一个生命周期短暂的微服务框架,用于疾速构建执行无限数据处理的应用程序。 Spring Cloud各个微服务之间为什么要用http交互?难道不慢吗?Spring Cloud是一个为散布式微服务架构构建应用程序的开发工具箱,是Spring Boot的扩大,通过各种微服务组件的集成,极大地简化了微服务应用程序的构建和开发。在分布式系统中,各个微服务之间的通信是十分重要的,而HTTP作为通信协议具备普遍性和可扩展性,是Spring Cloud微服务架构中支流的通信形式。 只管应用HTTP作为微服务之间的通信协议存在肯定的网络开销,然而这种不可避免的网络开销远低于咱们所能失去的益处。应用HTTP通信能够实现松耦合和异步通信,微服务之间能够彼此独立地进行开发和测试,单个微服务的故障不会影响整个零碎的运行,也能够反对各种不同的技术栈之间的互操作性。 另外,应用HTTP作为通信协议还具备优良的可扩展性。HTTP协定定义了不同的申请办法(例如 GET、POST、DELETE 等),不同申请办法的扩大格局也很灵便,能够用来传递各种类型的数据和格局,同时HTTP协定反对缓存,缩小重复性的数据传输和带宽开销。 当然,为了进步微服务之间的通信效率,咱们也能够通过一些优化伎俩来缩小HTTP协定的网络开销。例如,应用数据压缩和缓存技术来压缩和缓存申请和响应,缩小网络数据传输量和响应工夫;应用负载平衡技术来正当地调配申请和响应,防止单个微服务呈现性能瓶颈;应用高速缓存技术来缓存申请和响应,防止反复的申请和响应等等。 因而,Spring Cloud各个微服务之间应用HTTP交互是一个比拟成熟的抉择。尽管它可能存在一些网络开销,然而在理论利用中,这种开销是能够优化和管制的,甚至能够进步零碎的可扩展性和可靠性。 本文曾经收录到Github仓库,该仓库蕴含计算机根底、Java根底、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等外围知识点,欢送star~ Github地址 Github地址 如果拜访不了Github,能够拜访码云地址。 码云地址 2、什么是微服务?微服务架构是一种架构模式或者说是一种架构格调,它提倡将繁多应用程序划分为一组小的服务,每个服务运行在其独立的本人的过程中,服务之间互相协调、互相配合,为用户提供最终价值。服务之间采纳轻量级的通信机制相互沟通(通常是基于HTTP的RESTful API),每个服务都围绕着具体的业务进行构建,并且可能被独立的构建在生产环境、类生产环境等。另外,应防止对立的、集中式的服务管理机制,对具体的一个服务而言,应依据业务上下文,抉择适合的语言、工具对其进行构建,能够有一个十分轻量级的集中式治理来协调这些服务,能够应用不同的语言来编写服务,也能够应用不同的数据存储。 艰深地来讲: 微服务就是一个独立的职责繁多的服务应用程序。在 intellij idea 工具外面就是用maven开发的一个个独立的module,具体就是应用springboot 开发的一个小的模块,解决繁多业余的业务逻辑,一个模块只做一个事件。 微服务强调的是服务大小,关注的是某一个点,具体解决某一个问题/落地对应的一个服务利用,能够看做是idea 外面一个 module。 3、Spring Cloud有什么劣势应用 Spring Boot 开发散布式微服务时,咱们面临以下问题 与分布式系统相干的复杂性-这种开销包含网络问题,提早开销,带宽问题,平安问题。服务发现-服务发现工具治理群集中的流程和服务如何查找和相互交谈。它波及一个服务目录,在该目录中注册服务,而后可能查找并连贯到该目录中的服务。冗余-分布式系统中的冗余问题。负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,地方处理单元,或磁盘驱动器的散布。性能-问题 因为各种经营开销导致的性能问题。部署复杂性-Devops 技能的要求。4、微服务之间如何独立通信的?同步通信:dobbo通过 RPC 近程过程调用、springcloud通过 REST 接口json调用等。 异步:音讯队列,如:RabbitMq、ActiveM、Kafka等音讯队列。 5、 什么是服务熔断?什么是服务降级?熔断机制是应答雪崩效应的一种微服务链路爱护机制。当某个微服务不可用或者响应工夫太长时,会进行服务降级,进而熔断该节点微服务的调用,疾速返回“谬误”的响应信息。当检测到该节点微服务调用响应失常后复原调用链路。在Spring Cloud框架里熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的情况,当失败的调用到肯定阈值,缺省是5秒内调用20次,如果失败,就会启动熔断机制。 服务降级,个别是从整体负荷思考。就是当某个服务熔断之后,服务器将不再被调用,此时客户端能够本人筹备一个本地的fallback回调,返回一个缺省值。这样做,尽管程度降落,但好歹可用,比间接挂掉强。 Hystrix相干注解@EnableHystrix:开启熔断 @HystrixCommand(fallbackMethod=”XXX”),申明一个失败回滚处理函数XXX,当被注解的办法执行超时(默认是1000毫秒),就会执行fallback函数,返回谬误提醒。 6、 请说说Eureka和zookeeper 的区别?Zookeeper保障了CP,Eureka保障了AP。 A:高可用 C:一致性 P:分区容错性 1.当向注册核心查问服务列表时,咱们能够容忍注册核心返回的是几分钟以前的信息,但不能容忍间接down掉不可用。也就是说,服务注册性能对高可用性要求比拟高,但zk会呈现这样一种状况,当master节点因为网络故障与其余节点失去分割时,残余节点会从新选leader。问题在于,选取leader工夫过长,30 ~ 120s,且选取期间zk集群都不可用,这样就会导致选取期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会产生的事,尽管服务可能复原,然而漫长的选取工夫导致的注册长期不可用是不能容忍的。 ...

May 14, 2023 · 2 min · jiezi

关于java:一不小心你就掉进了Spring延迟初始化的坑

前言 书接上回,之前咱们有聊到 Spring 的提早初始化机制,是什么,有什么作用。明天跟各位大佬分享一下,我在应用 Spring 提早初始化踩过的一些坑。 List<坑> 坑列表 = new ArrayList<>(2); 首先,让咱们回顾一下 Spring 提早初始化的概念。在 Spring 中,提早初始化指的是将 Bean 的实例化推延到第一次被应用时,而不是在应用程序启动时就立刻创立所有的 Bean。这种提早加载的机制能够进步应用程序的性能和资源利用率。 坑 1. 提早加载生效,被非提早初始化的 Bean 注入了。代码演示: @Lazy@Componentpublic class MyBean { public MyBean() { System.out.println("My bean init success."); }}1、 应用构造函数注入 @Servicepublic class MyService { private MyBean myBean; public MyService(MyBean myBean) { this.myBean = myBean; } public void exec() { System.out.println("exec suc"); }}2、 @Resource 注入 @Servicepublic class MyService { @Resource private MyBean myBean; public void exec() { System.out.println("exec suc"); }}3、 @Autowired 注入 ...

May 14, 2023 · 2 min · jiezi

关于java:Java-内存模型

之前始终把 Java内存模型 和 JVM内存构造 搞混。 其实两者是不同的货色。 Java内存模型(Java Memory Model,JMM) 定义了 java 运行时如何与硬件内存进行交互,比方规定了一个线程如何看到其余内存批改后共享变量的值。一些高级个性也建设在JMM的根底上,比方volatile 关键字。 而 JVM 内存构造, 定义了 JVM 内存是如何划分的。 上面咱们介绍JMM。并从三个方面介绍: 为什么,是什么,解决了什么 JMM为什么要有Java内存模型咱们都晓得一台根本的计算机有 CPU 和 内存 两个货色。 CPU负责计算, 内存负责存储运行的程序和数据。 每次CPU计算时它会通过地址总线(Address Bus)向内存发送一个地址信号,指定要读取内存单元的地址。 而后进行期待。 之后内存将数据通过数据总线返回给CPU, CPU会将数据加载到寄存器中解决。而后将后果存储回内存。 但随着计算机性能的倒退,CPU的计算速度越来越快。这个期待的工夫(即内存读写的速度)相比计算的工夫变得越来越长,CPU就无奈及时取得须要的数据,导致性能降落。 为了放慢运行的速度,加了一个CPU 高速缓存。每次须要读取数据的时候,先从内存读取到CPU缓存中,CPU再从CPU缓存中读取。因为CPU高速缓存则间接集成在CPU外部,与CPU之间的间隔更近,因而访问速度大大放慢了。 实际上会分为 一级缓存、二级缓存、和三级缓存,并且会有多核CPU。如下图 在多核CPU的状况下,每个CPU都有本人的高速缓存,而它们又共享同一块主内存。 就会产生缓存一致性问题。 比方, 初始化 a = 0; 线程a执行 a = a + 1; 线程b执行 a = a + 1; 多核CPU下可能会产生上面这种状况: CPU1 执行线程a, 从内存读取 a 为0, 存到高速缓存中。CPU2 执行线程b, 从内存读取 a 为0, 存到高速缓存中。CPU1 进行运算,得出后果 1,写回内存 i 的值为 1。CPU2 进行运算,得出后果 1,写回内存 i 的值为 1。而在咱们看来,正确后果应该是2. ...

May 14, 2023 · 2 min · jiezi

关于java:大公司为什么禁止SpringBoot项目使用Tomcat

前言在SpringBoot框架中,咱们应用最多的是Tomcat,这是SpringBoot默认的容器技术,而且是内嵌式的Tomcat。同时,SpringBoot也反对Undertow容器,咱们能够很不便的用Undertow替换Tomcat,而Undertow的性能和内存应用方面都优于Tomcat,那咱们如何应用Undertow技术呢?本文将为大家细细解说。 SpringBoot中的Tomcat容器SpringBoot能够说是目前最火的Java Web框架了。它将开发者从沉重的xml拯救了进去,让开发者在几分钟内就能够创立一个残缺的Web服务,极大的进步了开发者的工作效率。Web容器技术是Web我的项目必不可少的组成部分,因为任Web我的项目都要借助容器技术来运行起来。在SpringBoot框架中,咱们应用最多的是Tomcat,这是SpringBoot默认的容器技术,而且是内嵌式的Tomcat。 SpringBoot设置Undertow对于Tomcat技术,Java程序员应该都十分相熟,它是Web利用最罕用的容器技术。咱们最早的开发的我的项目根本都是部署在Tomcat下运行,那除了Tomcat容器,SpringBoot中咱们还能够应用什么容器技术呢?没错,就是题目中的Undertow容器技术。SrpingBoot曾经齐全继承了Undertow技术,咱们只须要引入Undertow的依赖即可,如下图所示。举荐:最全面的Java面试网站 配置好当前,咱们启动应用程序,发现容器曾经替换为Undertow。那咱们为什么须要替换Tomcat为Undertow技术呢? 本文曾经收录到Github仓库,该仓库蕴含计算机根底、Java根底、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等外围知识点,欢送star~ Github地址 如果拜访不了Github,能够拜访gitee地址。 gitee地址 Tomcat与Undertow的优劣比照Tomcat是Apache基金下的一个轻量级的Servlet容器,反对Servlet和JSP。Tomcat具备Web服务器特有的性能,包含 Tomcat治理和管制平台、安全局治理和Tomcat阀等。Tomcat自身蕴含了HTTP服务器,因而也能够视作独自的Web服务器。然而,Tomcat和ApacheHTTP服务器不是一个货色,ApacheHTTP服务器是用C语言实现的HTTP Web服务器。Tomcat是完全免费的,深受开发者的青睐。 Undertow是Red Hat公司的开源产品, 它齐全采纳Java语言开发,是一款灵便的高性能Web服务器,反对阻塞IO和非阻塞IO。因为Undertow采纳Java语言开发,能够间接嵌入到Java我的项目中应用。同时, Undertow齐全反对Servlet和Web Socket,在高并发状况下体现十分杰出。 咱们在雷同机器配置下压测Tomcat和Undertow,失去的测试后果如下所示:QPS测试后果比照: Tomcat Undertow 内存应用比照: Tomcat Undertow 通过测试发现,在高并发零碎中,Tomcat相对来说比拟弱。在雷同的机器配置下,模仿相等的申请数,Undertow在性能和内存应用方面都是最优的。并且Undertow新版本默认应用长久连贯,这将会进一步提高它的并发吞吐能力。所以,如果是高并发的业务零碎,Undertow是最佳抉择。 最初SpingBoot中咱们既能够应用Tomcat作为Http服务,也能够用Undertow来代替。Undertow在高并发业务场景中,性能优于Tomcat。所以,如果咱们的零碎是高并发申请,无妨应用一下Undertow,你会发现你的零碎性能会失去很大的晋升。 好货色应该要分享进去!我把本人学习计算机多年以来的书籍分享进去了,汇总到一个计算机经典编程书籍仓库了,一共300多本,包含C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,能够star一下,下次找书间接在下面搜寻,仓库继续更新中~ Github地址

May 14, 2023 · 1 min · jiezi

关于java:Java补充之MySQL入门必备知识

文章和代码曾经归档至【Github仓库:https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。零根底学MySQL解决之道文件、数据库为了解决上述问题,应用更加利于治理数据的东东-数据库,它能更无效的治理数据。 举一个生活化的案例阐明:如果说图书馆是保留书籍的,那么数据库就是保留数据的。 MySQL 数据库的装置和配置mysql5.5 mysql5.6 mysqI5.7(稳固) mysql8 更高版本 应用命令行窗口连贯MYSQL 数据库mysql -h主机名-P端口-u用户名-p明码登录前,保障服务启动 net stop mysql服务名 net start mysql服务名 操作示意图 Navicat介绍: 图形化MySQL 管理软件 SQLyog数据库三层构造所谓装置Mysql数据库,就是在主机装置一个数据库管理系统(DBMS),这个管理程序能够治理多个数据库。DBMS(database manage system)。一个数据库中能够创立多个表,以保留数据(信息)。数据库管理系统(DBMS)、数据库和表的关系如图所示;示意图。 数据在数据库中的存储形式 SQL 语句分类DDL:数据定义语句[create表,库...] DML:数据操作语句[减少insert,批改update,删除 delete] DQL:数据查问语句[select ] DCL:数据管制语句[治理数据库: 比方用户权限 grant revoke ] 创立数据库 CHARACTER SET:指定数据库采纳的字符集,如果不指定字符集,默认utf8COLLATE:指定数据库字符集的校对规定(罕用的utf8 bin[辨别大小写]utf8_general_ci[不辨别大小写] 留神默认是 utf8 general_ci )# 演示数据库的操作#创立一个名称为db01的数据库。[图形化和指令 演示]#应用指令创立数据库CREATE DATABASE db01;#删除数据库指令DROP DATABASE db01#创立一个应用utf8字符集的hsp_db02数据库CREATE DATABASE db02 CHARACTER SET utf8#创立一个应用utf8字符集,并带校对规定的hsp_db03数据库CREATE DATABASE db03 CHARACTER SET utf8 COLLATE utf8_bin#校对规定 utf8_bin 辨别大小 默认utf8_general_ci 不辨别大小写#上面是一条查问的sql , select 查问 * 示意所有字段 FROM 从哪个表#WHERE 从哪个字段 NAME = 'tom' 查问名字是tomSELECT * FROM t1 WHERE NAME = 'tom'查看、删除数据库显示数据库语句: ...

May 12, 2023 · 34 min · jiezi

关于java:Java-向Excel中写入数组

在编辑Excel文档时,除了借助办公软件手动在工作表中输出数据外,也能够以编程的形式来进行此项操作。以Java编程为例。通过应用免费版的Free Spire.XLS for Java库,能够凭借代码,轻松高效地向Excel写入一维和二维数组。相干的示例代码和代码阐明已在下方给出。 程序环境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 文件,点击确认,将其导入到我的项目中。 代码解释:导入JAR包后,先创立一个新的Workbook对象。而后应用getWorksheets()办法获取Excel文档中的第一个工作表,接着应用insertArray()办法将一维或二维数组插入到工作表中。此代码首先插入一维数组,而后再插入二维数组。最初,应用saveToFile()办法指定要保留的文件名和文件格式,并将Excel文档保留在磁盘上。 示例代码:import com.spire.xls.ExcelVersion;import com.spire.xls.Workbook;import com.spire.xls.Worksheet;public class InsertArray { public static void main(String[] args) { //创立Workbook对象 Workbook wb = new Workbook(); //获取第一张工作表 Worksheet sheet = wb.getWorksheets().get(0); //定义一维数据 String[] oneDimensionalArray = new String[]{"姓名", "年龄", "性别", "职位"}; //将数组从指定单个格开始写入工作表,true示意纵向写入,设置为false为横向写入 sheet.insertArray(oneDimensionalArray, 1, 1, true); //定义二维数组 String[][] twoDimensionalArray = new String[][]{ {"姓名", "年龄", "性别", "职位"}, {"张三", "20", "男", "经理"}, {"李四", "21", "男", "副经理"}, {"王五", "22", "男", "员工"} }; //从指定单元格开始写入二维数组到工作表 sheet.insertArray(twoDimensionalArray, 1, 3); //保存文档 wb.saveToFile("InsertArrays.xlsx", ExcelVersion.Version2016); }}效果图: ...

May 12, 2023 · 1 min · jiezi

关于java:使用注解Validated效验VO参数是否合规

一:引入依赖包 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>二:在注解里标记分明规定 @Datapublic class Test01VO { @NotNull(message = "ID不能为空") private Integer id; @Min(0) @Max(5) private Integer score; private String content;}三:在Controller里应用@Validated注解 @PostMapping("/test01") public String test(@Validated @RequestBody Test01VO test01vo) { System.out.print("test>>>>>>>>>"+test01vo.getId()); return "success"; }四:调用接口验证是否失效参数: { "id": "", "score": 5}返回参数异样: { "code": 410, "msg": "ID不能为空; ", "data": null, "traceId": null}参数: { "id": "1", "score": "10"}返回参数异样: { "code": 410, "msg": "must be less than or equal to 5; ", "data": null, "traceId": null}参数: ...

May 12, 2023 · 1 min · jiezi

关于java:线程池的使用

例如: private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2, Runtime.getRuntime().availableProcessors() * 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ptyadapter-qd-%d").build());这段代码次要是定义了一个线程池 EXECUTOR_SERVICE 以及创立该线程池的一些参数和属性。 线程池是一种常见的治理线程的技术,它可能无效的控制线程的数量、复用线程、治理线程的生命周期和优化线程的性能等等。在该代码中,指定了线程池的总容量为 CPU 核数的两倍,应用的队列类型为 LinkedBlockingQueue,它是一个基于链表实现的无界阻塞队列,能够存储任意数量的元素。队列中的工作会期待线程池中闲暇的线程去执行,如果没有闲暇线程则会始终阻塞,期待有闲暇线程后再去执行。 该线程池中的线程都被标记为守护线程(daemon=true),即当主线程完结时,这些子线程也会随之完结。线程的名称采纳了相似于 ptyadapter-qd-1 这样的命名形式,数字局部是线程池内的线程计数器值。 具体参数的含意如下: corePoolSize:线程池中保留的最小线程数。maximumPoolSize:线程池中容许存在的最大线程数。keepAliveTime:线程池中超过 corePoolSize 线程数目的闲暇线程在终止之前期待新工作的最长工夫。unit:keepAliveTime 工夫单位。workQueue:用于贮存期待执行工作的队列,其中可寄存有限个元素。threadFactory:线程池中创立新线程的线程工厂。这段代码的作用是在初始化时创立一个线程池,用于并发解决一些耗时的工作,并且该线程池具备较好的性能和容错机制。咱们能够通过调用 EXECUTOR_SERVICE.submit() 办法来提交一个工作到该线程池中,该线程池会依据理论状况来调度和执行这个工作。这种做法能够无效地进步程序的并发性能,并且不会像间接创立线程一样造成过多的线程资源节约。 while (true) { list.forEach((key, value) ->{ Future<?> future = EXECUTOR_SERVICE.submit(() -> { if ("2".equals(value)) { return; } if ("1".equals(value)) { return; } // 结构http申请 BufferedReader reader = null; VoucherRetionVo efmVouBillRelation = new VoucherRetionVo(); efmVouBillRelation.setIpConfig(key); efmVouBillRelation.setMaxNum(size.get()); try { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.writeValueAsString(efmVouBillRelation); String url = "http://" + key + "/pty/online/gz"; URL requestUrl = new URL(url); HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection(); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/json"); connection.setDoOutput(true); connection.getOutputStream().write(objectMapper.writeValueAsString(efmVouBillRelation).getBytes()); reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); } catch (Exception e) { LOG.error("拜访谬误请查看", e); } finally { if (null != reader) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } if (size.get() == 0) { LOG.info("工作实现,上班"); return; } size.getAndDecrement(); }); taskList.add(future); }); for (Future<?> future : taskList) { future.get(120, TimeUnit.SECONDS); } //达到要求完结循环 if (size.get() == 0) { LOG.info("工作实现,上班"); break; } }这段代码蕴含一个有限循环,其中蕴含了线程池的调用,用于并发解决一些工作。 ...

May 12, 2023 · 2 min · jiezi

关于java:动力节点杜聚宾老师Spring6学习笔记3Spring的入门程序

官网地址:[https://spring.io/] 官网地址(中文):http://spring.p2hp.com/ 关上Spring官网后,能够看到Spring Framework,以及通过Spring Framework衍生的其它框架,把Spring Framework,下载下来。 docs:spring框架的API帮忙文档 libs:spring框架的jar文件(用spring框架就是用这些jar包) schema:spring框架的XML配置文件相干的束缚文件 3.2 Spring的jar文件 关上libs目录,会看到很多jar包: spring-core-5.3.9.jar:字节码(这个是撑持程序运行的jar包)spring-core-5.3.9-javadoc.jar:代码中的正文spring-core-5.3.9-sources.jar:源码 咱们来看一下spring框架都有哪些jar包: JAR文件形容spring-aop-5.3.9.jar这个jar 文件蕴含在利用中应用Spring 的AOP 个性时所需的类spring-aspects-5.3.9.jar提供对AspectJ的反对,以便能够不便的将面向切面的性能集成进IDE中spring-beans-5.3.9.jar这个jar 文件是所有利用都要用到的,它蕴含拜访配置文件、创立和治理bean 以及进行Inversion ofControl / Dependency Injection(IoC/DI)操作相干的所有类。如果利用只需根本的IoC/DI 反对,引入spring-core.jar 及spring-beans.jar 文件就能够了。spring-context-5.3.9.jar这个jar 文件为Spring 外围提供了大量扩大。能够找到应用Spring ApplicationContext个性时所需的全副类,JDNI 所需的全副类,instrumentation组件以及校验Validation 方面的相干类。spring-context-indexer-5.3.9.jar尽管类门路扫描十分快,然而Spring外部存在大量的类,增加此依赖,能够通过在编译时创立候选对象的动态列表来进步大型应用程序的启动性能。spring-context-support-5.3.9.jar用来提供Spring上下文的一些扩大模块,例如实现邮件服务、视图解析、缓存、定时任务调度等spring-core-5.3.9.jarSpring 框架根本的外围工具类。Spring 其它组件要都要应用到这个包里的类,是其它组件的根本外围,当然你也能够在本人的利用零碎中应用这些工具类。spring-expression-5.3.9.jarSpring表达式语言。spring-instrument-5.3.9.jarSpring3.0对服务器的代理接口。spring-jcl-5.3.9.jarSpring的日志模块。JCL,全称为"Jakarta Commons Logging",也可称为"Apache Commons Logging"。spring-jdbc-5.3.9.jarSpring对JDBC的反对。spring-jms-5.3.9.jar这个jar包提供了对JMS 1.0.2/1.1的反对类。JMS是Java音讯服务。属于JavaEE标准之一。spring-messaging-5.3.9.jar为集成messaging api和音讯协定提供反对spring-orm-5.3.9.jarSpring集成ORM框架的反对,比方集成hibernate,mybatis等。spring-oxm-5.3.9.jar为支流O/X Mapping组件提供了对立层形象和封装,OXM是Object Xml Mapping。对象和XML之间的互相转换。spring-r2dbc-5.3.9.jarReactive Relational Database Connectivity (关系型数据库的响应式连贯) 的缩写。这个jar文件是Spring对r2dbc的反对。spring-test-5.3.9.jar对Junit等测试框架的简略封装。spring-tx-5.3.9.jar为JDBC、Hibernate、JDO、JPA、Beans等提供的统一的申明式和编程式事务管理反对。spring-web-5.3.9.jarSpring集成MVC框架的反对,比方集成Struts等。spring-webflux-5.3.9.jarWebFlux是 Spring5 增加的新模块,用于 web 的开发,性能和 SpringMVC 相似的,Webflux 应用以后一种比拟流程响应式编程呈现的框架。spring-webmvc-5.3.9.jarSpringMVC框架的类库spring-websocket-5.3.9.jarSpring集成WebSocket框架时应用留神:如果你只是想用Spring的IoC性能,仅须要引入:spring-context即可。将这个jar包增加到classpath当中。如果采纳maven只须要引入context的依赖即可。 <!--Spring6的正式版公布之前,这个仓库地址是须要的--><repositories> <repository> <id>repository.spring.milestone</id> <name>Spring Milestone Repository</name> <url>https://repo.spring.io/milestone</url> </repository></repositories><dependencies> <!--spring context依赖:应用的是6.0.0-M2里程碑版--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.0-M2</version> </dependency></dependencies>3.3 第一个Spring程序 ...

May 12, 2023 · 3 min · jiezi

关于java:存下吧Spring高频面试题总结

Spring是什么?Spring是一个轻量级的管制反转(IoC)和面向切面(AOP)的容器框架。 Spring的长处通过管制反转和依赖注入实现松耦合。反对面向切面的编程,并且把利用业务逻辑和零碎服务离开。通过切面和模板缩小样板式代码。申明式事务的反对。能够从枯燥繁冗的事务管理代码中解脱进去,通过申明式形式灵便地进行事务的治理,进步开发效率和品质。不便集成各种优良框架。外部提供了对各种优良框架的间接反对(如:Hessian、Quartz、MyBatis等)。不便程序的测试。Spring反对Junit4,增加注解便能够测试Spring程序。Spring 用到了哪些设计模式?1、简略工厂模式:BeanFactory就是简略工厂模式的体现,依据传入一个惟一标识来取得 Bean 对象。 @Overridepublic Object getBean(String name) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name);}2、工厂办法模式:FactoryBean就是典型的工厂办法模式。spring在应用getBean()调用取得该bean时,会主动调用该bean的getObject()办法。每个 Bean 都会对应一个 FactoryBean,如 SqlSessionFactory 对应 SqlSessionFactoryBean。 3、单例模式:一个类仅有一个实例,提供一个拜访它的全局拜访点。Spring 创立 Bean 实例默认是单例的。 4、适配器模式:SpringMVC中的适配器HandlerAdatper。因为利用会有多个Controller实现,如果须要间接调用Controller办法,那么须要先判断是由哪一个Controller解决申请,而后调用相应的办法。当减少新的 Controller,须要批改原来的逻辑,违反了开闭准则(对批改敞开,对扩大凋谢)。 为此,Spring提供了一个适配器接口,每一种 Controller 对应一种 HandlerAdapter 实现类,当申请过去,SpringMVC会调用getHandler()获取相应的Controller,而后获取该Controller对应的 HandlerAdapter,最初调用HandlerAdapter的handle()办法解决申请,实际上调用的是Controller的handleRequest()。每次增加新的 Controller 时,只须要减少一个适配器类就能够,无需批改原有的逻辑。 罕用的处理器适配器:SimpleControllerHandlerAdapter,HttpRequestHandlerAdapter,AnnotationMethodHandlerAdapter。 // Determine handler for the current request.mappedHandler = getHandler(processedRequest);HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());public class HttpRequestHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) {//handler是被适配的对象,这里应用的是对象的适配器模式 return (handler instanceof HttpRequestHandler); } @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler) handler).handleRequest(request, response); return null; }}5、代理模式:spring 的 aop 应用了动静代理,有两种形式JdkDynamicAopProxy和Cglib2AopProxy。 ...

May 11, 2023 · 6 min · jiezi

关于java:面试精灵Java后端靠谱强大的面试题网站稳拿offer

面试精灵:一个给力的Java后端面试题网站。 网址:https://offer.skyofit.com 这套题实在、高频、全面、有具体答案、保你稳过面试,让你成为offer收割机。题目包含:Java根底、多线程、JVM、数据库、Redis、Shiro、Spring、SpringBoot、MyBatis、MQ、ELK、分布式、SpringCloud、设计模式、线上问题排查等。 面试的痛点你要跳槽时是否遇到过如下问题? 1.没有题库,不晓得如何开始温习2.有题库,但题目超级多,基本看不完3.背完题库中的面试题了,却发现面试官的问题大部分都不在题库中,导致面试老是挂,拿不到offer 此面试题的特点这是一套实在、靠谱的题目。它的特点是: 实在、靠谱(这套题是我在几十场面试中被面试官问到的问题)精选、高频(数量适合,很快就能看完)有难度和频率的标记(焦急跳槽的能够只看频率为三颗星及以上的题目)很弱小,面试官的问题根本都在这套题里(看过这套题的敌人都说,面试时85%以上的题目都在这些题目里,成为了offer收割机)此面试题的适用人群此网站蕴含从简略到艰难、从高频到低频的题目,适宜所有Java求职者,包含:应届生、转行的、三年以内教训的、三到五年教训的、五到十年教训的等。 此面试题的威力看过此网站的敌人和共事加入了面试后说,他们面试被问到的问题大部分(85%以上)都在这个网站里。 我在面试时也常常会遇到这种状况:95%的题目在此网站中,我对答如流,不晓得面试官是否会狐疑泄题了。这些面试也都很稳地拿到了offer。 难度与频率这套面试题采纳五角星来评判题目的难度和被问到的频率,最高为五颗星。 如果是三年以上的教训,只看难度为三颗星及以上的题目即可。如果是一两年教训,看集体程度,程度好些的能够看一颗星到五颗星所有题目(我晓得有这样的敌人:尽管教训少,但爱学习,一两年的教训领有普通人四五年的技术能力)。 网站截图首页 题目总览 题目详情

May 11, 2023 · 1 min · jiezi

关于java:实现高并发秒杀的-7-种方式写的太好了建议收藏

1.引言高并发场景在现场的日常工作中很常见,特地是在互联网公司中,这篇文章就来通过秒杀商品来模仿高并发的场景。文章开端会附上文章的所有代码、脚本和测试用例。 本文环境: SpringBoot 2.5.7 + MySQL 8.0 X + MybatisPlus + Swagger2.9.2模仿工具: Jmeter模仿场景: 减库存->创立订单->模仿领取2.商品秒杀-超卖在开发中,对于上面的代码,可能很相熟:在Service外面加上@Transactional事务注解和Lock锁。 Spring Boot 根底就不介绍了,举荐看这个收费教程: https://github.com/javastacks/spring-boot-best-practice管制层:Controller @ApiOperation(value="秒杀实现形式——Lock加锁")@PostMapping("/start/lock")public Result startLock(long skgId){ try { log.info("开始秒杀形式一..."); final long userId = (int) (new Random().nextDouble() * (99999 - 10000 + 1)) + 10000; Result result = secondKillService.startSecondKillByLock(skgId, userId); if(result != null){ log.info("用户:{}--{}", userId, result.get("msg")); }else{ log.info("用户:{}--{}", userId, "哎呦喂,人也太多了,请稍后!"); } } catch (Exception e) { e.printStackTrace(); } finally { } return Result.ok();}业务层:Service @Override@Transactional(rollbackFor = Exception.class)public Result startSecondKillByLock(long skgId, long userId) { lock.lock(); try { // 校验库存 SecondKill secondKill = secondKillMapper.selectById(skgId); Integer number = secondKill.getNumber(); if (number > 0) { // 扣库存 secondKill.setNumber(number - 1); secondKillMapper.updateById(secondKill); // 创立订单 SuccessKilled killed = new SuccessKilled(); killed.setSeckillId(skgId); killed.setUserId(userId); killed.setState((short) 0); killed.setCreateTime(new Timestamp(System.currentTimeMillis())); successKilledMapper.insert(killed); // 模仿领取 Payment payment = new Payment(); payment.setSeckillId(skgId); payment.setSeckillId(skgId); payment.setUserId(userId); payment.setMoney(40); payment.setState((short) 1); payment.setCreateTime(new Timestamp(System.currentTimeMillis())); paymentMapper.insert(payment); } else { return Result.error(SecondKillStateEnum.END); } } catch (Exception e) { throw new ScorpiosException("异样了个乖乖"); } finally { lock.unlock(); } return Result.ok(SecondKillStateEnum.SUCCESS);}对于下面的代码应该没啥问题吧,业务办法上加事务,在解决业务的时候加锁。 ...

May 11, 2023 · 7 min · jiezi

关于java:6000字讲透ElasticSearch-索引设计

ElasticSearch 索引设计 在MySQL中数据库设计十分重要,同样在ES中数据库设计也是十分重要的概述咱们创立索引就像创立表构造一样,必须十分谨慎的,索引如果创立不好前面会呈现各种各样的问题索引设计的重要性索引创立后,索引的分片只能通过_split和_shrink接口对其进行成倍的减少和缩减次要是因为es的数据是通过_routing调配到各个分片下面的,所以实质上是不举荐去扭转索引的分片数量的,因为这样都会对数据进行从新的挪动。 还有就是索引只能新增字段,不能对字段进行批改和删除,不足灵活性,所以每次都只能通过_reindex重建索引了,还有就是一个分片的大小以及所以分片数量的多少重大影响到了索引的查问和写入性能,所以可想而知,设计一个好的索引可能缩小前期的运维治理和进步不少性能,所以后期对索引的设计是相当的重要的。 基于工夫的Index设计Index设计时要思考的第一件事,就是基于工夫对Index进行宰割,即每隔一段时间产生一个新的Index这样设计的目标因为事实世界的数据是随着工夫的变动而一直产生的,切分治理能够取得足够的灵活性和更好的性能 如果数据都存储在一个Index中,很难进行扩大和调整,因为Elasticsearch中Index的某些设置在创立时就设定好了,是不能更改的,比方Primary Shard的个数。 而依据工夫来切分Index,则能够实现肯定的灵活性,既能够在数据量过大时及时调整Shard个数,也能够及时响应新的业务需要。 大多数业务场景下,客户对数据的申请都会命中在最近一段时间上,通过切分Index,能够尽可能的防止扫描不必要的数据,进步性能。 工夫距离依据下面的剖析,天然是工夫越短越能放弃灵活性,然而这样做就会导致产生大量的Index,而每个Index都会耗费资源来保护其元信息的,因而须要在灵活性、资源和性能上做衡量常见的距离有小时、天、周和月:先思考总共要存储多久的数据,而后选一个既不会产生大量Index又可能满足肯定灵活性的距离,比方你须要存储6个月的数据,那么一开始抉择“周”这个距离就会比拟适合。思考业务增长速度:如果业务增长的特地快,比方上周产生了1亿数据,这周就增长到了10亿,那么就须要调低这个距离来保障有足够的弹性能应答变动。如何实现宰割切分行为是由客户端(数据的写入端)发动的,依据工夫距离与数据产生工夫将数据写入不同的Index中,为了易于辨别,会在Index的名字中加上对应的工夫标识创立新Index这件事,能够是客户端被动发动一个创立的申请,带上具体的Settings、Mappings等信息,然而可能会有一个工夫错位,即有新数据写入时新的Index还没有建好,Elasticsearch提供了更优雅的形式来实现这个动作,即Index Template 分片设计所谓分片设计,就是如何设定主分片的个数看上去只是一个数字而已,兴许在很多场景下,即便不设定也不会有问题(ES7默认是1个主分片一个正本分片),然而如果不提前思考,一旦出问题就可能导致系统性能降落、不可拜访、甚至无奈复原,换句话说,即便应用默认值,也应该是通过足够的评估后作出的决定,而非拍脑袋定的。 限度分片大小单个Shard的存储大小不超过30GBElastic专家依据经验总结进去大家普遍认为30GB是个适合的上限值,实际中发现单个Shard过大(超过30GB)会导致系统不稳固。 其次,为什么不能超过30GB?次要是思考Shard Relocate过程的负载,咱们晓得,如果Shard不平衡或者局部节点故障,Elasticsearch会做Shard Relocate,在这个过程中会搬移Shard,如果单个Shard过大,会导致CPU、IO负载过高进而影响零碎性能与稳定性。 评估分片数量单个Index的Primary Shard个数 = k * 数据节点个数在保障第一点的前提下,单个Index的Primary Shard个数不宜过多,否则相干的元信息与缓存会耗费过多的系统资源,这里的k,为一个较小的整数值,倡议取值为1,2等,整数倍的关系能够让Shard更好地均匀分布,能够充沛的将申请扩散到不同节点上。 小索引设计对于很小的Index,能够只调配1~2个Primary Shard的有些状况下,Index很小,兴许只有几十、几百MB左右,那么就不必依照第二点来调配了,只调配1~2个Primary Shard是能够,不必纠结。 应用索引模板就是把曾经创立好的某个索引的参数设置(settings)和索引映射(mapping)保留下来作为模板,在创立新索引时,指定要应用的模板名,就能够间接重用曾经定义好的模板中的设置和映射Elasticsearch基于与索引名称匹配的通配符模式将模板利用于新索引,也就是说通过索引进行匹配,看看新建的索引是否合乎索引模板,如果合乎,就将索引模板的相干设置利用到新的索引,如果同时合乎多个索引模板呢,这里须要对参数priority进行比拟,这样会抉择priority大的那个模板进行创立索引。 在创立索引模板时,如果匹配有蕴含的关系,或者雷同,则必须设置priority为不同的值,否则会报错,索引模板也是只有在新创建的时候起到作用,批改索引模板对现有的索引没有影响,同样如果在索引中设置了一些设置或者mapping都会笼罩索引模板中雷同的设置或者mapping 索引模板的用处索引模板个别用在工夫序列相干的索引中。也就是说, 如果你须要每距离肯定的工夫就建设一次索引,你只须要配置好索引模板,当前就能够间接应用这个模板中的设置,不必每次都设置settings和mappings. 创立索引模板COPYPUT _index_template/logstash-village{ "index_patterns": [ "logstash-village-*" // 能够通过"logstash-village-*"来适配创立的索引 ], "template": { "settings": { "number_of_shards": "3", //指定模板分片数量 "number_of_replicas": "2" //指定模板正本数量 }, "aliases": { "logstash-village": {} //指定模板索引别名 }, "mappings": { //设置映射 "dynamic": "strict", //禁用动静映射 "properties": { "@timestamp": { "type": "date", "format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss" }, "@version": { "doc_values": false, "index": "false", "type": "integer" }, "name": { "type": "keyword" }, "province": { "type": "keyword" }, "city": { "type": "keyword" }, "area": { "type": "keyword" }, "addr": { "type": "text", "analyzer": "ik_smart" }, "location": { "type": "geo_point" }, "property_type": { "type": "keyword" }, "property_company": { "type": "text", "analyzer": "ik_smart" }, "property_cost": { "type": "float" }, "floorage": { "type": "float" }, "houses": { "type": "integer" }, "built_year": { "type": "integer" }, "parkings": { "type": "integer" }, "volume": { "type": "float" }, "greening": { "type": "float" }, "producer": { "type": "keyword" }, "school": { "type": "keyword" }, "info": { "type": "text", "analyzer": "ik_smart" } } } }}模板参数上面是创立索引模板的一些参数参数名称参数介绍index_patterns必须配置,用于在创立期间匹配索引名称的通配符(*)表达式数组template可选配置,能够抉择包含别名、映射或设置配置composed_of可选配置,组件模板名称的有序列表。组件模板按指定的程序合并,这意味着最初指定的组件模板具备最高的优先级priority可选配置,创立新索引时确定索引模板优先级的优先级。抉择具备最高优先级的索引模板。如果未指定优先级,则将模板视为优先级为0(最低优先级)version可选配置,用于内部治理索引模板的版本号_meta可选配置,对于索引模板的可选用户元数据,可能有任何内容映射配置下面咱们配置了映射模板,然而咱们用到了映射,上面咱们说下映射什么是映射在创立索引时,能够事后定义字段的类型(映射类型)及相干属性数据库建表的时候,咱们DDL根据个别都会指定每个字段的存储类型,例如:varchar、int、datetime等,目标很明确,就是更准确的存储数据,避免数据类型格局凌乱,在Elasticsearch中也是这样,创立索引的时候个别也须要指定索引的字段类型,这种形式称为映射(Mapping) ...

May 11, 2023 · 3 min · jiezi

关于java:EntityPOVOBODTO的区别记录

一、Entity(与数据库表构造统一)实体,和PO的性能相似,和数据表一一对应,一个Entity对应一张表,Entity里的每一个字段,与数据库绝对应 二、VO(用于反馈数据给前端)View Object对应页面显示的数据对象,能够和表对应,也能够不对应。管制层与视图层进行传输替换 三、PO(临时不太了解)Persistent Object长久化对象,跟数据库导入记录数据一一对应的映射关系。一个PO对应一个表或多个表联结查问, Entity是一个非凡的PO 四、BO(临时不太了解)Business object业务对象、一个简单的业务,往往蕴含多个小业务。例如,一个订单信息BO,可能蕴含,1.订单根底信息(购买人,工夫,状态等根底信息) 2.订单领取信息 3.订单优惠券信息 4.订单收货信息 5.订单售后信息 6.订单退款信息等。把一个个订单信息对应一个个PO,组装到一起是BO. 五、DTO(用于内部服务,内部API接口等)Data Transfer Object数据传输对象,服务之间数据传输对象,仅仅包含调用方想要的数据对象,能够由PO、Entity转换失去。 POJO(Plain Ordinary Java Object无规则简略Java对象)不与数据库打交道的简略对象,POJO是DTO/BO/VO的统称 信息起源:https://blog.csdn.net/sinat_16998945/article/details/124664505

May 11, 2023 · 1 min · jiezi

关于java:动力节点杜聚宾老师Spring6学习笔记2Spring概述

2.1 Spring简介 Spring是一个开源框架,它由Rod Johnson创立。它是为了解决企业应用开发的复杂性而创立的。从简略性、可测试性和松耦合的角度而言,任何Java利用都能够从Spring中受害。Spring是一个轻量级的管制反转(IoC)和面向切面(AOP)的容器框架。Spring最后的呈现是为了解决EJB臃肿的设计,以及难以测试等问题。Spring为简化开发而生,让程序员只需关注外围业务的实现,尽可能的不再关注非业务逻辑代码(事务管制,平安日志等)。 2.2 Spring8大模块 留神:Spring5版本之后是8个模块。在Spring5中新增了WebFlux模块。 Spring Core模块这是Spring框架最根底的局部,它提供了依赖注入(DependencyInjection)特色来实现容器对Bean的治理。外围容器的次要组件是 BeanFactory,BeanFactory是工厂模式的一个实现,是任何Spring利用的外围。它应用IoC将利用配置和依赖从理论的利用代码中分离出来。 Spring Context模块如果说外围模块中的BeanFactory使Spring成为容器的话,那么上下文模块就是Spring成为框架的起因。这个模块扩大了BeanFactory,减少了对国际化(I18N)音讯、事件流传、验证的反对。另外提供了许多企业服务,例如电子邮件、JNDI拜访、EJB集成、近程以及时序调度(scheduling)服务。也包含了对模版框架例如Velocity和FreeMarker集成的反对 Spring AOP模块Spring在它的AOP模块中提供了对面向切面编程的丰盛反对,Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过应用 Spring AOP,不必依赖组件,就能够将申明性事务管理集成到应用程序中,能够自定义拦截器、切点、日志等操作。 Spring DAO模块提供了一个JDBC的形象层和异样层次结构,打消了繁缛的JDBC编码和数据库厂商特有的错误代码解析,用于简化JDBC。 Spring ORM模块Spring提供了ORM模块。Spring并不试图实现它本人的ORM解决方案,而是为几种风行的ORM框架提供了集成计划,包含Hibernate、JDO和iBATIS SQL映射,这些都听从 Spring 的通用事务和 DAO 异样层次结构。 Spring Web MVC模块Spring为构建Web利用提供了一个性能全面的MVC框架。尽管Spring能够很容易地与其它MVC框架集成,例如Struts,但Spring的MVC框架应用IoC对管制逻辑和业务对象提供了齐全的拆散。 Spring WebFlux模块Spring Framework 中蕴含的原始 Web 框架 Spring Web MVC 是专门为 Servlet API 和 Servlet 容器构建的。反应式堆栈 Web 框架 Spring WebFlux 是在 5.0 版的前期增加的。它是齐全非阻塞的,反对反应式流(Reactive Stream)背压,并在Netty,Undertow和Servlet 3.1+容器等服务器上运行。 Spring Web模块Web 上下文模块建设在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文,提供了Spring和其它Web框架的集成,比方Struts、WebWork。还提供了一些面向服务反对,例如:实现文件上传的multipart申请。 2.3 Spring特点 轻量 从大小与开销两方面而言Spring都是轻量的。残缺的Spring框架能够在一个大小只有1MB多的JAR文件里公布。并且Spring所需的解决开销也是微不足道的。Spring是非侵入式的:Spring利用中的对象不依赖于Spring的特定类。管制反转 Spring通过一种称作管制反转(IoC)的技术促成了松耦合。当利用了IoC,一个对象依赖的其它对象会通过被动的形式传递进来,而不是这个对象本人创立或者查找依赖对象。你能够认为IoC与JNDI相同——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象申请就被动将依赖传递给它。面向切面 Spring提供了面向切面编程的丰盛反对,容许通过拆散利用的业务逻辑与零碎级服务(例如审计(auditing)和事务(transaction)治理)进行内聚性的开发。利用对象只实现它们应该做的——实现业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的零碎级关注点,例如日志或事务反对。容器 ...

May 11, 2023 · 1 min · jiezi

关于java:动力节点杜聚宾老师Spring6学习笔记1-Spring启示录

浏览以下代码: package com.powernode.oa.controller;import com.powernode.oa.service.UserService;import com.powernode.oa.service.impl.UserServiceImpl;public class UserController { private UserService userService = new UserServiceImpl(); public void login(){ String username = "admin"; String password = "123456"; boolean success = userService.login(username, password); if (success) { // 登录胜利 } else { // 登录失败 } }}package com.powernode.oa.service.impl;import com.powernode.oa.bean.User;import com.powernode.oa.dao.UserDao;import com.powernode.oa.dao.impl.UserDaoImplForMySQL;import com.powernode.oa.service.UserService;public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoImplForMySQL(); public boolean login(String username, String password) { User user = userDao.selectByUsernameAndPassword(username, password); if (user != null) { return true; } return false; }}package com.powernode.oa.dao.impl;import com.powernode.oa.bean.User;import com.powernode.oa.dao.UserDao;public class UserDaoImplForMySQL implements UserDao { public User selectByUsernameAndPassword(String username, String password) { // 连贯MySQL数据库,依据用户名和明码查问用户信息 return null; }}能够看出,UserDaoImplForMySQL中次要是连贯MySQL数据库进行操作。如果更换到Oracle数据库上,则须要再提供一个UserDaoImplForOracle,如下: ...

May 11, 2023 · 1 min · jiezi

关于java:Java反射详解

文章和代码曾经归档至【Github仓库:https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。反射(reflection)一个需要引出反射依据配置文件 re.properties 指定信息,创立Cat对象并调用办法hi classfullpath = com.hspedu.Catmethod = hi这样的需要在学习框架时特地多,即通过内部文件配置,在不批改源码状况下。来控制程序,也合乎设计模式的ocp准则(开闭准则:不批改源码,扩容性能)。package com.hspedu.reflection.question;import com.hspedu.Cat;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Properties;/** * 反射问题的引入 */@SuppressWarnings({"all"})public class ReflectionQuestion { public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //依据配置文件 re.properties 指定信息, 创立Cat对象并调用办法hi //传统的形式 new 对象 -》 调用办法// Cat cat = new Cat();// cat.hi(); ===> cat.cry() 批改源码. //咱们尝试做一做 -> 明确反射 //1. 应用Properties 类, 能够读写配置文件 Properties properties = new Properties(); properties.load(new FileInputStream("src\\re.properties")); String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat" String methodName = properties.get("method").toString();//"hi" System.out.println("classfullpath=" + classfullpath); System.out.println("method=" + methodName); //2. 创建对象 , 传统的办法,行不通 =》 反射机制 //new classfullpath(); // classfullpath 这是一个字符串,而正规应该new 类名() //3. 应用反射机制解决 //(1) 加载类, 返回Class类型的对象cls Class cls = Class.forName(classfullpath); //(2) 通过 cls 失去你加载的类 com.hspedu.Cat 的对象实例 Object o = cls.newInstance(); System.out.println("o的运行类型=" + o.getClass()); //运行类型 //(3) 通过 cls 失去你加载的类 com.hspedu.Cat 的 methodName"hi" 的办法对象 // 即:在反射中,能够把办法视为对象(万物皆对象) Method method1 = cls.getMethod(methodName); //(4) 通过method1 调用办法: 即通过办法对象来实现调用办法 System.out.println("============================="); method1.invoke(o); //传统办法 对象.办法() , 反射机制 办法.invoke(对象) }}反射机制Java Reflection反射机制容许程序在执行期借助于 Reflection API 获得任何类的外部信息(比方成员变量,结构器,成员办法等等),并能操作对象的属性及办法。反射在设计模式和框架底层都会用到。加载完类之后,在堆中就产生了一个Class类型的对象( 一个类只有一个Class对象),这个对象蕴含了类的残缺构造信息。通过这个对象失去类的构造。这个Class对象就像一面镜子,透过这个镜子看到类的构造,所以,形象的称之为:反射。类比: ...

May 11, 2023 · 10 min · jiezi

关于java:在-IDEA-中创建-Spring-Boot-项目的方式详细步骤教程

开发环境以下是我的开发环境 JDK 1.8Maven 3.6.3IDEA 2019(2019 无所畏惧,即便当初曾经 2023 年了哈哈哈)应用 Maven 的形式创立 Spring Boot 我的项目上面的内容可能会因 IDEA 版本不同,而有些选项不同,然而大同小异。 1. 关上 IDEA点击 Create New Project 2. 点击 Maven点击右边的 Maven,默认抉择你的 JDK,而后点击 Next。 3. 输出我的项目信息输出你的项目名称、存储地位、组等信息,搞定后点击 Finish 实现。 4. 开启主动导入依赖性能实现 Maven 我的项目的创立,接着点击 Enable Auto-Import,开启主动导入依赖性能。 5. 增加 Spring Boot 所需依赖关上我的项目根目录下的 pom.xml 文件,增加如下依赖 <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.god23bin</groupId> <artifactId>spring-boot-made-by-maven-demo</artifactId> <version>1.0-SNAPSHOT</version> <!-- 引入 Spring Boot 对立版本父项目管理依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> </parent> <dependencies> <!-- Spring Web 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies></project>这里增加的依赖是 Spring Boot 对立 2.1.3 版本的父项目管理依赖,接着增加了 Spring Web 依赖项。 ...

May 10, 2023 · 2 min · jiezi

关于java:在-IDEA-中创建-Java-Web-项目的方式详细步骤教程

开发环境以下是我的开发环境 JDK 1.8Maven 3.6.3Tomcat 9.0IDEA 2019(2019 无所畏惧,即便当初曾经 2023 年了哈哈哈)最原始的 Java Web 我的项目上面的内容可能会因 IDEA 版本不同,而有些选项不同,然而大同小异。 1. 关上 IDEA点击 Create New Project 2. 点击 Java Enterprise点击左侧 Java Enterprise ,默认选项如下图所示。找到 Web Application,勾选上,同时勾上 Create web.xml。点击 Next 进入下一步。 3. 输出我的项目信息输出项目名称和我的项目存储的地位,下方的配置默认就能够。接着点击 Finish 实现创立。 4. 欠缺我的项目构造到这步,曾经胜利创立了 Web 我的项目了,目录构造如下图,在 Eclipse 中,web 目录的名称是 WebContent 。src 目录寄存 Java 后端代码,web 目录寄存前端代码。 咱们能够在 web 目录下创立 css,js,image,page 这几个目录,别离寄存对应的文件,其中 page 用于寄存前端页面文件,蕴含 JSP 页面。 在 web/WEB-INF 目录下,寄存着咱们的 web.xml 配置文件,在该目录下,咱们创立一个 lib 目录,用来寄存我的项目须要的依赖包,比方 servlet、jstl 等。 ...

May 10, 2023 · 2 min · jiezi

关于java:给你的项目启动提提速Lazy-Initialization

前言 在一个名为种花家的小镇上,生存着一群酷爱编程的人。他们致力于构建出高效、可保护的软件系统,而 Spring Boot 框架成为了他们的不二之选。这个小镇上的人们每天都在用 Spring Boot 框架发明着令人瞩目的应用程序。 然而,随着工夫的推移,他们的应用程序变得越来越宏大,蕴含了许多不同的模块和组件。在应用程序启动的时候,所有的 bean 都会被一次性初始化,这导致了一个令人头疼的问题:启动工夫变得越来越长了。 小镇的居民们开始感到困扰。他们意识到,无论是在开发环境还是在生产环境中,启动工夫的长短都间接关系到他们的工作效率和用户体验。于是,他们寻找一种解决方案,心愿可能在保障应用程序失常运行的同时,缩小启动工夫的开销。 正当大家纠结不已时,一个编程少侠呈现了。他名叫不一样的科技宅,他通知大家,有一种叫做"提早初始化"的策略,能够帮忙他们解决这个问题。 据说,提早初始化可能将 bean 的初始化推延到第一次应用时进行,而不是在应用程序启动时立刻初始化。这样一来,只有当某个 bean 真正被须要时,才会进行初始化,防止了不必要的资源耗费和工夫开销。 是什么? 提早初始化(Lazy Initialization)是一种在须要时才创立或加载对象的策略,以缩小启动工夫和资源耗费。在 Spring 中,提早初始化容许将 Bean 的创立推延到第一次拜访该 Bean 时才进行,而不是在应用程序启动时立刻创立。 有啥用?节俭资源 当应用程序中存在大量的 bean 时,立刻初始化所有 bean 可能会占用大量的内存和解决工夫。通过提早初始化,只有在须要应用 bean 时才会进行初始化,能够防止不必要的资源耗费。 放慢启动工夫 提早初始化能够缩小应用程序启动工夫,因为只有在须要时才会加载和初始化 bean。对于那些在应用程序启动时可能不会应用的较大或简单的 bean,提早初始化能够显著放慢启动工夫。 解决循环依赖 Spring 容器能够治理 bean 之间的依赖关系。当存在循环依赖时,提早初始化能够帮忙解决这个问题。通过提早初始化,Spring 容器能够在运行时一一解析和满足 bean 之间的依赖,而不是在初始化阶段发现无奈解决的循环依赖。 如何实现?Spring Boot 中实现提早初始化 Bean,能够采取以下四种办法: 对于应用注解配置的 Bean,能够在 Bean 的定义上应用 @Lazy 注解来实现提早初始化。示例: @Lazy@Componentpublic class MyBean { // Bean 的定义}对于应用 Java 配置类的形式,能够在 @Bean 注解上应用 @Lazy 注解,以实现提早初始化。示例: ...

May 10, 2023 · 2 min · jiezi

关于java:2023Java该怎么样进行学习学到什么地方可以找到工作

尽管Java行业依然十分凋敝和倒退,然而竞争也的确十分强烈。因为Java是一门十分风行的编程语言,因而有很多人都想学习它并进入这个行业。此外,许多公司也更偏向于雇佣具备丰盛教训和技能的Java开发人员。因而,如果你想在Java行业找到一份工作,你须要具备肯定的教训和常识,并一直进步本人的技能程度。你能够通过加入培训课程、实际我的项目、参加开源社区等形式一直晋升本人的能力。此外,你也能够通过建设本人的我的项目和教训来减少本人的竞争力。 所以2023Java该怎么样进行学习,以及学到什么境地能够找到工作。 一、Java学习的趋势1.Java的新版本Java的新版本的公布速度越来越快,Java 9、Java 10、Java 11等版本曾经公布。在将来的几年里,Java的新版本将持续公布,Java 17、Java 18等版本也将会公布。因而,在学习Java时须要关注最新的版本和个性,以及把握这些新个性的应用办法。 2.微服务架构微服务架构曾经成为当今最风行的利用架构之一,Java在微服务架构中的利用也越来越宽泛。在将来的几年中,微服务架构将持续倒退,Java将持续在微服务架构中表演重要角色。因而,在学习Java时,须要理解微服务架构的概念和实际,并把握Java在微服务架构中的利用办法。 3.云计算云计算曾经成为当今最热门的技术之一,Java也在云计算中表演重要角色。在将来的几年中,云计算将持续倒退,Java在云计算中的利用也将持续扩大。因而,在学习Java时,须要学习云计算的相干概念和实际,并把握Java在云计算中的利用办法。 4.大数据处理大数据处理曾经成为当今最重要的技术之一,Java也在大数据处理中表演重要角色。在将来的几年中,大数据处理将持续倒退,Java在大数据处理中的利用也将持续扩大。因而,在学习Java时,须要学习大数据处理的相干概念和实际,并把握Java在大数据处理中的利用办法。 5.人工智能人工智能曾经成为当今最热门的技术之一,Java也在人工智能中表演重要角色。在将来的几年中,人工智能将持续倒退,Java在人工智能中的利用也将持续扩大。因而,在学习Java时,须要学习人工智能的相干概念和实际,并把握Java在人工智能中的利用办法。 二、Java学习的办法11.学习Java编程语言基础知识在学习Java时,首先要学习Java编程语言的基础知识,如语法、数据类型、控制流、数组等。能够通过Java官网文档、Java编程思维等经典书籍进行学习。 2.学习Java Web开发框架Java Web开发框架是Java利用开发中最罕用的框架之一,如Spring、Spring Boot、MyBatis等。能够通过官网文档、视频教程、网上的开源我的项目等进行学习。 3.学习数据库设计和SQL语言数据库设计和SQL语言是Java利用开发中必不可少的局部,如MySQL、Oracle等。能够通过官网文档、视频教程、练习我的项目等进行学习。 4.练习我的项目实战练习我的项目实战能够坚固学习成绩,能够通过参加开源我的项目或者本人设计并实现一个我的项目来坚固学习成绩。 5.加入培训课程和认证考试加入培训课程和认证考试能够减速学习过程,同时也能够减少本人的待业竞争力。Java认证考试包含Java SE、Java EE、Java ME等多个方向。 三、Java待业市场Java是寰球最风行的编程语言之一,具备宽泛的应用领域和待业市场。在将来的几年中,Java待业市场将持续扩充,Java程序员也将持续成为最热门的职业之一。 1.待业畛域Java程序员能够在各种畛域中找到工作,包含企业应用开发、金融行业、电子商务、互联网、游戏开发、挪动利用开发等。 2.待业岗位Java程序员能够从事多种岗位,如Java开发工程师、Java架构师、Java项目经理、Java技术顾问等。 3.待业前景Java程序员的待业前景非常广阔,从高级到高级的岗位都有很多就业机会。在将来的几年中,随着Java的广泛应用和行业的倒退,Java程序员的待业前景将持续保持良好。 四、如何找到Java工作1.在招聘网站上寻找工作能够在招聘网站上寻找Java相干的工作,如智联招聘、拉钩、猎聘等。 2.通过社交媒体找工作能够通过社交媒体寻找Java相干的工作,如LinkedIn、微博等。 3.通过猎头找工作能够通过猎头寻找Java相干的工作,在猎头公司中抉择业余的Java猎头。 4.加入招聘会加入招聘会能够理解当地的Java工作状况,也能够面对面与招聘方交换。 5.承受举荐和介绍能够承受举荐和介绍,这是找工作的一种无效形式。 五、Java学习办法能够通过以下几种办法来学习: 学习Java编程语言基础知识,如语法、数据类型、控制流、数组等。能够通过Java官网文档、Java编程思维等经典书籍进行学习。学习Java Web开发框架,如Spring、Spring Boot、MyBatis等。能够通过官网文档、视频教程、网上的开源我的项目等进行学习。学习数据库设计和SQL语言,如MySQL、Oracle等。能够通过官网文档、视频教程、练习我的项目等进行学习。练习我的项目实战,能够通过参加开源我的项目或者本人设计并实现一个我的项目来坚固学习成绩。同时,以下是一些比拟好的Java后端学习教程资源: Java官网文档:https://docs.oracle.com/en/java/Java编程思维:https://book.douban.com/subject/2130190/Spring官网文档:https://spring.io/docsMyBatis官网文档:https://mybatis.org/mybatis-3/zh/index.html阿里巴巴Java开发手册:https://github.com/alibaba/p3cB站Java后端学习路线:https://www.bilibili.com/read/cv6395168六、总结Java是一门十分重要的编程语言,对于想要从事软件开发行业的人来说,学习Java是必不可少的。在将来的几年中,Java的应用领域将持续扩充,Java程序员也将持续成为最热门的职业之一。因而,学习Java并把握Java的利用办法,将有助于拓展本人的待业前景。

May 10, 2023 · 1 min · jiezi

关于java:聊聊那些年我们实现java-AOP几种常见套路

前言有肯定开发教训的同学对AOP应该很理解吧,如果不理解,能够先查看如下文章进行科普一下https://baike.baidu.com/item/AOP/1332219?fr=aladdin,再来浏览本文。 示例前置筹备注: 本示例基于springboot进行演示 1、在我的项目pom引入aop的GAV <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>2、编写业务服务@Servicepublic class EchoService { @CostTimeRecoder public void echo(String message){ System.out.println("echo ->" + message); }}3、编写aspect切面@Aspectpublic class EchoAspect { @Before(value = "execution(* com.github.lybgeek.aop.service.EchoService.echo(..))") public void before(JoinPoint joinPoint){ System.out.println("USE AOP BY ASPECT WITH ARGS: " + Arrays.toString(joinPoint.getArgs())); }}实现AOP的常见套路1、在编译期阶段实现AOP办法一:通过aspectj-maven-plugin插件在编译期进行织入在我的项目的pom引入如下内容 <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> <plugin> <groupId>com.nickwongdev</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.12.6</version> <configuration> <complianceLevel>${java.version}</complianceLevel> <source>${java.version}</source> <target>${java.version}</target> <encoding>${project.encoding}</encoding> </configuration> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin> </plugins></build><dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.5</version> </dependency></dependencies>通过执行如下maven命令 ,进行我的项目编译 ...

May 10, 2023 · 2 min · jiezi

关于java:Java实现多用户即时通信系统

文章和代码曾经归档至【Github仓库:https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。我的项目波及我的项目框架设计java面向对象编程网络编程多线程IO流Mysql/应用汇合充当内存数据库我的项目开发流程 需要剖析用户登录拉取在线用户列表无异样退出(客户端、服务端)私聊群聊发文件服务器推送新闻性能实现-用户登录性能阐明 因为还没有学习数据库,咱们人为规定用户名/id = 100, 明码123456 就能够登录,其它用户不能登录前面应用HashMap模仿数据库,能够多个用户登录。 一个客户端也会有多个线程与服务端来分割。 性能实现-拉取在线用户列表 性能实现-无异样退出略 性能实现-私聊 性能实现-群聊略 性能阐明-发文件 性能实现-服务器推送新闻 客户端`-- com `-- hspedu |-- qqclient | |-- service | | |-- ClientConnectServerThread.java | | |-- FileClientService.java | | |-- ManageClientConnectServerThread.java | | |-- MessageClientService.java | | `-- UserClientService.java | |-- utils | | `-- Utility.java | `-- view | `-- QQView.java `-- qqcommon |-- Message.java |-- MessageType.java `-- User.javaQQView package com.hspedu.qqclient.view;import com.hspedu.qqclient.service.FileClientService;import com.hspedu.qqclient.service.MessageClientService;import com.hspedu.qqclient.service.UserClientService;import com.hspedu.qqclient.utils.Utility;/** * 客户端的菜单界面 */@SuppressWarnings("all")public class QQView { private boolean loop = true; //管制是否显示菜单 private String key = ""; // 接管用户的键盘输入 private UserClientService userClientService = new UserClientService();//对象是用于登录服务/注册用户 private MessageClientService messageClientService = new MessageClientService();//对象用户私聊/群聊. private FileClientService fileClientService = new FileClientService();//该对象用户传输文件 public static void main(String[] args) { new QQView().mainMenu(); System.out.println("客户端退出零碎....."); } //显示主菜单 private void mainMenu() { while (loop) { System.out.println("===========欢送登录网络通信零碎==========="); System.out.println("\t\t 1 登录零碎"); System.out.println("\t\t 9 退出零碎"); System.out.print("请输出你的抉择: "); key = Utility.readString(1); //依据用户的输出,来解决不同的逻辑 switch (key) { case "1": System.out.print("请输出用户号: "); String userId = Utility.readString(50); System.out.print("请输出密 码: "); String pwd = Utility.readString(50); //这里就比拟麻烦了, 须要到服务端去验证该用户是否非法 //这里有很多代码, 咱们这里编写一个类 UserClientService[用户登录/注册] if (userClientService.checkUser(userId, pwd)) { //还没有写完, 先把整个逻辑买通.... System.out.println("===========欢送 (用户 " + userId + " 登录胜利) ==========="); //进入到二级菜单 while (loop) { System.out.println("\n=========网络通信零碎二级菜单(用户 " + userId + " )======="); System.out.println("\t\t 1 显示在线用户列表"); System.out.println("\t\t 2 群发音讯"); System.out.println("\t\t 3 私聊音讯"); System.out.println("\t\t 4 发送文件"); System.out.println("\t\t 9 退出零碎"); System.out.print("请输出你的抉择: "); key = Utility.readString(1); switch (key) { case "1": //这里老师筹备写一个办法,来获取在线用户列表 userClientService.onlineFriendList(); break; case "2": System.out.println("请输出想对大家说的话: "); String s = Utility.readString(100); messageClientService.sendMessageToAll(s, userId); break; case "3": System.out.print("请输出想聊天的用户号(在线): "); String getterId = Utility.readString(50); System.out.print("请输出想说的话: "); String content = Utility.readString(100); //编写一个办法,将音讯发送给服务器端 messageClientService.sendMessageToOne(content, userId, getterId); break; case "4": System.out.print("请输出你想把文件发送给的用户(在线用户): "); getterId = Utility.readString(50); System.out.print("请输出发送文件的门路(模式 d:\\xx.jpg)"); String src = Utility.readString(100); System.out.print("请输出把文件发送到对应的门路(模式 d:\\yy.jpg)"); String dest = Utility.readString(100); fileClientService.sendFileToOne(src,dest,userId,getterId); break; case "9": //调用办法,给服务器发送一个退出零碎的message userClientService.logout(); loop = false; break; } } } else { //登录服务器失败 System.out.println("=========登录失败========="); } break; case "9": loop = false; break; } } }}com/hspedu/qqcommon/Message.java ...

May 10, 2023 · 14 min · jiezi