用Lucene建立搜索索引

本文是我们名为“ Apache Lucene基础知识 ”的学院课程的一部分。

在本课程中,您将了解Lucene。 您将了解为什么这样的库很重要,然后了解Lucene中搜索的工作方式。 此外,您将学习如何将Lucene Search集成到您自己的应用程序中,以提供强大的搜索功能。 在这里查看 !

目录

1.简介 2.了解索引操作
2.1倒排索引 2.2字段类型 2.3细分 2.4文件编号 2.5搜索索引
3.创建索引 4.基本索引操作
4.1核心索引类 4.2将数据添加到索引
5.文件和领域
5.1文件 5.2领域 5.3在Lucene中增强文档

1.简介

该索引是利用Lucene的任何组件的核心。 就像书籍的索引一样,它组织所有数据,以便可以快速访问。 索引由包含一个或多个字段的文档组成。 文档和字段可以代表我们选择的任何内容,但一个常见的隐喻是:文档表示数据库表中的条目,而字段类似于表中的字段。

2.了解索引操作

让我们看一下Lucene搜索索引的图形表示。

图1

图1

简而言之,当Lucene对文档进行索引时,它会将其分解为许多术语。 然后,它将术语存储在索引文件中,其中每个术语与包含该术语的文档相关联。 我们可以把它当作一个哈希表。 术语是使用分析器生成的,该分析器将每个单词的词根都提取出来。 发出查询时,将通过用于构建索引的同一分析器来处理该查询,然后使用该分析器在索引中查找匹配项。 这提供了与查询匹配的文档列表。

现在,让我们看一下整个Lucene搜索过程。

基本概念是索引,文档,字段和术语。

  1. 索引包含文档的集合。
  2. 文档是字段的集合。
  3. 字段是术语的集合。
  4. 术语是成对的字符串<field,term-string>。

2.1倒排索引

索引存储有关术语的统计信息,以使基于术语的搜索更加高效。 Lucene的索引属于称为反向索引的索引族。 这是因为它可以长期列出包含它的文档。 这与文档中列出术语的自然关系相反。

2.2字段类型

在Lucene中,可以存储字段,在这种情况下,它们的文本将以非反转的方式按字面意义存储在索引中。 反转的字段称为索引。 字段可以被存储和被索引。

可以将字段的文本标记为要索引的术语,或者可以将字段的文本从字面上用作要索引的术语。 大多数字段都是标记化的,但有时对于某些标识符字段按字面意义进行索引很有用。

2.3细分

Lucene索引可以由多个子索引或段组成。 每个段都是完全独立的索引,可以分别进行搜索。 索引按以下方式演变:

  1. 为新添加的文档创建新的细分。
  2. 合并现有的细分。
  3. 搜索可能涉及多个段和/或多个索引,每个索引可能由一组段组成。

2.4文件编号

在内部,Lucene通过整数文档号引用文档。 添加到索引的第一个文档编号为零,并且随后添加的每个文档的编号都比前一个大。

请注意,文档编号可能会更改,因此在将这些编号存储在Lucene之外时应格外小心。 特别是,在以下情况下数字可能会更改:

存储在每个段中的数字仅在该段内是唯一的,并且必须进行转换才能在更大的上下文中使用它们。 标准技术是根据该段中使用的数字范围为每个段分配一个值范围。 要将文档编号从段转换为外部值,需要添加段的基本文档编号。 要将外部值转换回特定于细分的值,可以通过外部值所在的范围来标识细分,然后减去细分的基值。 例如,可以合并两个五个文档的段,以便第一个段的基值为零,第二个为五个。 第二段的文档三的外部值为8。

删除文档后,在编号中会留出空白。 随着索引通过合并的发展,这些最终被删除。 合并段时删除已删除的文档。 因此,新合并的段在编号上没有间隙。

2.5搜索索引

搜索索引由javascript函数定义。 它以类似于视图的地图功能的方式运行在所有文档上,并定义了搜索可查询的字段。 搜索索引是数据库的一种变体。 它与RDBMS相似,因为它需要快速查找密钥,但是大部分数据驻留在辅助存储上。

3.创建索引

到目前为止,我们已经看到了Lucene索引的所有组成部分。 在本节中,我们将使用Lucene索引创建文档索引。

考虑一个项目,学生在其中提交年度杂志文章。 输入控制台包含学生姓名,文章标题,文章类别和文章正文的选项。 我们假设该项目正在网络上运行并且可以通过它进行访问。 要为这篇文章建立索引,我们需要文章本身,作者的姓名,撰写日期,文章的主题,文章的标题以及文件所在的URL。 利用这些信息,我们可以构建一个程序,该程序可以正确索引文章以使其易于查找。

让我们看一下我们类的基本框架,包括我们将需要的所有导入。

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits; import java.util.Date; public class ArticleIndexer { }

我们需要添加的第一件事是将文章转换为Document对象的方法。

为此,我们将使用方法createDocument()

private Document createDocument(String article, String author,String title, String topic,String url, Date dateWritten) { Document document = new Document();document.add(Field.Text("author", author));document.add(Field.Text("title", title));document.add(Field.Text("topic", topic));document.add(Field.UnIndexed("url", url));document.add(Field.Keyword("date", dateWritten));document.add(Field.UnStored("article", article));return document;}

首先,我们创建一个新的Document对象。 接下来要做的是将文章的不同部分添加到Document 。 我们为每个部分提供的名称完全是任意的,并且像HashMap键一样工作。 使用的名称必须是String 。 Document的add方法将采用一个Field对象,该对象是使用Field类提供的静态方法之一构建的。 提供了四种将Field对象添加到Document的方法。

Field.Keyword –数据已存储并建立索引,但未标记化。 这对于应保留不变的数据(例如日期)最有用。 实际上,Field.Keyword可以将Date对象作为输入。

Field.Text –数据被存储,索引和标记化。 Field.Text字段不应用于诸如文章本身之类的大量数据,因为索引将变得非常大,因为它将包含文章的完整副本以及标记化的版本。

Field.UnStored –不存储数据,但对其进行索引和标记化。 大量数据(例如文章的文本)应放置在未存储的索引中。

Field.UnIndexed –数据已存储但未建立索引或标记化。 它与要与搜索结果一起返回的数据一起使用,但实际上不会在该数据上进行搜索。 在我们的示例中,由于我们不允许搜索URL,因此没有理由对其进行索引,但是我们希望在找到搜索结果后将其返回给我们。

现在我们有了一个Document对象,我们需要获得一个IndexWriter来将此Document写入索引。

String indexDirectory = "lucene-index"; private void indexDocument(Document document) throws Exception {Analyzer analyzer  = new StandardAnalyzer();IndexWriter writer = new IndexWriter(indexDirectory, analyzer, false);writer.addDocument(document);writer.optimize();writer.close();}

我们首先创建StandardAnalyzer ,然后使用分析器创建IndexWriter 。 在构造函数中,我们必须指定索引将驻留的目录。 构造函数末尾的布尔值告诉IndexWriter是创建新索引还是添加到现有索引。 在将新文档添加到现有索引时,我们将指定false。 然后,我们将Document添加到索引。 最后,我们优化然后关闭索引。 如果要添加多个Document对象,则应始终进行优化,然后在将所有Document对象都添加到索引之后关闭索引。

现在,我们只需要添加一种将各个部分组合在一起的方法即可。

为了驱动索引​​操作,我们将编写一个indexArticle()一些参数的方法indexArticle()

public void indexArticle(String article, String author,String title, String topic,String url, Date dateWritten)throws Exception {Document document = createDocument(article, author,title, topic,url, dateWritten);indexDocument(document);}

对文章运行该文章会将其添加到索引中。 将IndexWriter构造函数中的布尔值更改为true会创建一个索引,因此我们应该在第一次创建索引时以及每次要从头开始重建索引时使用它。 现在我们已经构建了索引,我们需要在索引中搜索文章。

索引存储为单个目录中的一组文件。

索引由任意数量的独立段组成,这些段存储有关已索引文档子集的信息。 每个段都有自己的术语词典,术语词典索引和文档存储(存储的字段值)。 所有段数据都存储在_xxxxx.cfs文件中,其中xxxxx是段名称。

创建索引段文件后,将无法对其进行更新。 新文档将添加到新段中。 删除的文档仅在可选的.del文件中标记为已删除。

4.基本索引操作

索引数据

Lucene让我们可以索引文本格式的任何可用数据。 Lucene几乎可以用于任何数据源,只要可以从中提取文本信息即可。 我们可以使用Lucene对存​​储在HTML文档,Microsoft Word文档,PDF文件等中的数据进行索引和搜索。 索引数据的第一步是使其以简单文本格式可用。 可以使用自定义解析器和数据转换器。

索引过程

索引编制是将文本数据转换为便于快速搜索的格式的过程。 一个简单的类比是您在书末找到的索引:该索引将您指向书中出现的主题的位置。

Lucene将输入数据存储在称为反向索引的数据结构中,该数据结构作为一组索引文件存储在文件系统或内存中。 大多数Web搜索引擎使用反向索引。 它使用户可以执行快速的关键字查找,并找到与给定查询匹配的文档。 在将文本数据添加到索引之前,它需要由分析器处理(使用分析过程)。

分析

分析将文本数据转换为基本的搜索单位,称为术语。 在分析过程中,文本数据会经历多种操作:提取单词,删除常用单词,忽略标点符号,将单词简化为词根形式,将单词更改为小写字母等。分析仅在建立索引和查询解析之前进行。 分析将文本数据转换为标记,并将这些标记作为术语添加到Lucene索引中。

Lucene带有各种内置分析器,例如SimpleAnalyzerStandardAnalyzerStopAnalyzerSnowballAnalyzer等。 它们在标记文本和应用过滤器的方式上有所不同。 由于分析会在索引编制之前删除单词,因此会减小索引大小,但会对查询处理的精度产生负面影响。 通过使用Lucene提供的基本构建块创建自定义分析器,可以对分析过程进行更多控制。 表1显示了一些内置分析仪及其处理数据的方式。

4.1核心索引类

目录

代表索引文件存储位置的抽象类。 通常主要使用两个子类:

FSDirectory —目录的实现,在实际的文件系统中存储索引。 这对于大索引很有用。

RAMDirectory —将所有索引存储在内存中的实现。 这适用于较小的索引,这些索引可以完全加载到内存中,并在应用程序终止时销毁。 由于索引保存在内存中,因此速度相对较快。

分析仪

如所讨论的,分析器负责预处理文本数据并将其转换为存储在索引中的令牌。 IndexWriter接受用于对数据建立索引之前对其进行标记化的分析器。 为了正确地为文本建立索引,您应该使用适合需要被索引的文本语言的分析器。

默认分析器适用于英语。 Lucene沙箱中还有其他一些分析器,包括中文,日文和韩文的分析器。

IndexDeletionPolicy

用于实现自定义从索引目录中删除过时提交的策略的接口。 默认的删除策略是KeepOnlyLastCommitDeletionPolicy ,它仅保留最新的提交,并在完成新提交后立即删除所有先前的提交。

索引作家

创建或维护索引的类。 它的构造函数接受一个布尔值,该布尔值确定是创建新索引还是打开现有索引。 它提供了添加,删除或更新索引中文档的方法。

对索引所做的更改最初会在内存中进行缓冲,并定期刷新到索引目录。 IndexWriter公开了几个字段,这些字段控制索引在内存中的缓冲方式以及如何将其写入磁盘。 除非调用IndexWriter的commit或close方法,否则对IndexReader不到对索引所做的更改。 IndexWriter为目录创建一个锁定文件,以防止索引同时更新导致索引损坏。 IndexWriter允许用户指定可选的索引删除策略。

4.2将数据添加到索引

将文本数据添加到索引涉及两个类。

字段表示在搜索中查询或检索的一条数据。 Field类封装一个字段名称及其值。 Lucene提供了一些选项来指定是否需要对字段进行索引或分析以及是否需要存储其值。 在创建字段实例时可以传递这些选项。 下表显示了字段元数据选项的详细信息。

选项 描述
Field.Store.Yes 用于存储字段的值。 适用于显示搜索结果的字段,例如文件路径和URL。
Field.Store.No 字段值未存储-例如,电子邮件正文。
Field.Index.No 适用于未搜索的字段-通常与存储的字段(例如文件路径)一起使用。
Field.Index.ANALYZED 用于索引但未分析的字段。 它完整​​地保留了字段的原始值,例如日期和个人名称。
Field.Index.NOT_ANALYZED 用于索引但未分析的字段。 它完整​​地保留了字段的原始值,例如日期和个人名称。

字段元数据选项的详细信息

而文档是字段的集合。 Lucene还支持增强文档和字段,如果要重视某些索引数据,这是一个有用的功能。 为文本文件建立索引包括将文本数据包装在字段中,创建文档,使用字段填充文本,以及使用IndexWriter将文档添加到索引中。

5.文件和领域

如您先前所见,文档是索引和搜索过程的单元。

5.1文件

文档是一组字段。 每个字段都有一个名称和一个文本值。 字段可以与文档一起存储,在这种情况下,它会随文档的搜索命中一起返回。 因此,每个文档通常应包含一个或多个唯一标识它的存储字段。

您将文档添加到索引,并且在执行搜索之后,您将获得结果列表,它们是文档。 文档只是字段的非结构化集合。

5.2领域

字段是Lucene.net的实际内容所有者:它们基本上是一个哈希表,具有名称和值。 如果我们拥有无限的磁盘空间和无限的处理能力,那就是我们所需要知道的。 但是不幸的是,磁盘空间和处理能力受到限制,因此您不能仅分析所有内容并将其存储到索引中。 但是Lucene.net提供了将字段添加到索引的不同方法。

Lucene提供了四种不同类型的字段供开发人员选择: KeywordUnIndexedUnStoredText 。 您应该使用哪种字段类型取决于您要如何使用该字段及其值。

关键字字段未标记,但被逐字索引并存储在索引中。 此字段适用于原始值应完整保留的字段,例如URL,日期,个人姓名,社会保险号,电话号码等。

未索引字段既没有标记也没有索引,但它们的值存储在逐字索引中。 该字段适用于需要与搜索结果一起显示但绝不会直接搜索其值的字段。 由于未对这种类型的字段建立索引,因此对其进行搜索很慢。 由于此类型的字段的原始值存储在索引中,因此如果存在索引大小的问题,则此类型不适合存储具有非常大值的字段。

未存储字段与未索引字段相反。 此类型的字段已标记并建立索引,但未存储在索引中。 此字段适用于索引大量不需要以其原始形式检索的文本,例如网页正文或任何其他类型的文本文档。

文本字段被标记,索引并存储在索引中。 这意味着可以搜索此类型的字段,但请注意存储为“文本”字段的字段的大小。

如果您回顾一下LuceneIndexExample类,您将看到我使用了Text字段:

document.add(Field.Text("fieldname", text));

如果要更改字段fieldname的类型,我们将调用Field类的其他方法之一:

document.add(Field.Keyword("fieldname", text));

要么

document.add(Field.UnIndexed("fieldname", text));

要么

document.add(Field.UnStored("fieldname", text));

尽管Field.TextField.KeywordField.UnIndexedField.UnStored调用最初看起来像是对构造函数的调用,但它们实际上只是对不同Field类方法的调用。 表1总结了不同的字段类型。

现场方法/类型 代币化 索引 已储存
Field.Keyword(String, String) 没有
Field.UnIndexed(String, String) 没有 没有
Field.UnStored(String, String) 没有
Field.Text(String, String)
Field.Text(String, Reader) 没有

表1:不同字段类型的概述。

5.3在Lucene中增强文档

在“信息检索”中,文档与搜索的相关性通过与查询的相似程度来衡量。 Lucene中实现了几种相似性模型,您可以通过扩展相似性类并使用Lucene保存的索引统计信息来实现自己的相似性模型。 还可以为文档分配静态分数,以表示它们在整个语料库中的重要性,而与正在执行的查询无关,例如其受欢迎程度,评分或PageRank。

在Lucene 4.0之前,您可以通过调用document.setBoost为文档分配静态分数。 在内部,通过将字段的提升因子乘以文档的提升因子,将提升应用于文档的每个字段。 但是,这永远无法正常工作,并且取决于所执行查询的类型,可能根本不会影响文档的排名。

通过在Lucene中添加DocValues,增强文档就像添加NumericDocValuesField并将其用于CustomScoreQuery一样简单, CustomScoreQuery将计算所得的分数乘以“ boost”字段的值。 下面的代码示例说明了如何实现此目的:

// add two documents to the index
Document doc = new Document();
doc.add(new TextField("f", "test document", Store.NO));
doc.add(new NumericDocValuesField("boost", 1L));
writer.addDocument(doc); doc = new Document();
doc.add(new TextField("f", "test document", Store.NO));
doc.add(new NumericDocValuesField("boost", 2L));
writer.addDocument(doc); // search for 'test' while boosting by field 'boost'
Query baseQuery = new TermQuery(new Term("f", "test"));
Query boostQuery = new FunctionQuery(new LongFieldSource("boost"));
Query q = new CustomScoreQuery(baseQuery, boostQuery);
searcher.search(q, 10);

通过编写一个简单的公式,新的Expressions模块也可以用于增强文档,如下所示。 尽管它比使用CustomScoreQuery更为冗长,但它通过计算更复杂的公式(例如sqrt(_score)+ ln(boost))变得微不足道。

Expression expr = JavascriptCompiler.compile("_score * boost");
SimpleBindings bindings = new SimpleBindings();
bindings.add(new SortField("_score", SortField.Type.SCORE));
bindings.add(new SortField("boost", SortField.Type.LONG));
Sort sort = new Sort(expr.getSortField(bindings, true));
searcher.search(baseQuery, null, 10, sort);

既然Lucene允许在不重新索引文档的情况下更新NumericDocValuesField ,那么您可以将频繁更改的字段(受欢迎程度,评分,价格,最后修改时间…)并入提升因子中,而无需每次对其中任何一个更改时都重新索引文档。

翻译自: https://www.javacodegeeks.com/2015/09/building-a-search-index-with-lucene.html

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

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

相关文章

《鸿蒙理论知识03》HarmonyOS概述之系统安全

在搭载 HarmonyOS 的分布式终端上,可以保证“正确的人,通过正确的设备,正确地使 用数据”。 通过“分布式多端协同身份认证”来保证“正确的人”。 通过“在分布式终端上构筑可信运行环境”来保证“正确的设备”。 通过“分布式数据在跨终端流动的过程中,对数据进行分类分…

Shell基础学习(六) 流程控制

1、if if的语法格式 if conditon thencommand1command2commandn fi 2、if else if conditon thencommand1command2commandn elsecommand1command2commandn fi 3、if elseif else if conditon thencommand1command2commandn else if conditoncommand1command2commandn elsecomma…

《鸿蒙理论知识04》HarmonyOS概述之系统定义

目录 系统定位 技术架构 系统服务层 框架层 系统定位 HarmonyOS 是一款“面向未来”、面向全场景(移动办公、运动健康、社交通信、媒体 娱乐等)的分布式操作系统。在传统的单设备系统能力的基础上,HarmonyOS 提出了基 于同一套系统能力、适配多种终端形态的分布式理念,…

jQuery on 绑定的事件触发多次

jquery用on绑定事件&#xff0c;在代码执行过程中&#xff0c;可能会遇到多次执行的情况。 解决方案是在on的事件前面加上一个off&#xff0c;再on。 $(#btnBind).off(click).on(click,function () {alert(123); });$("#xxx").off(keydown).focus().on(keydown,funct…

twitter api_Java应用程序上的Twitter API

twitter api是否曾想过将推文附加到Java应用程序&#xff1f; 我为此寻找了最好的API&#xff0c;很幸运&#xff0c;我找到了它&#xff01; http://twitter4j.org/ 一个简单的方法&#xff1a; 我们需要做的第一件事是在您的Twitter帐户中创建一个应用程序&#xff0c;为其授…

《鸿蒙理论知识05》HarmonyOS概述之下载与安装软件

DevEco Studio 支持 Windows 和 macOS 系统,下面将针对两种操作系统的软件安装方式 进行介绍。 目录 Windows 环境 macOS 环境 Windows 环境 运行环境要求 为保证 DevEco Studio 正常运行,建议您的电脑配置满足如下要求:  操作系统:Windows10 64 位  内存:8GB …

网络编程释疑之:单台服务器上的并发TCP连接数可以有多少

曾几何时我们还在寻求网络编程中C10K问题的解决方案&#xff0c;但是现在从硬件和操作系统支持来看单台服务器支持上万并发连接已经没有多少挑战性了。我们先假设单台服务器最多只能支持万级并发连接&#xff0c;其实对绝大多数应用来说已经远远足够了&#xff0c;但是对于一些…

垂直和水平装饰

装饰器模式是在不更改其接口的情况下向对象添加功能的最佳方法之一。 我经常使用可组合装饰器&#xff0c;并且总是会问自己在功能列表必须可配置时如何正确设计它们。 我不确定我的答案是否正确&#xff0c;但是这里有一些值得深思的地方。 公寓&#xff08;1960&#xff09;…

cygwin配置git

对于windows用户来说&#xff0c;使用git bash经常会出现乱码情况&#xff0c;那么一款优质高尚的软件&#xff0c;值得推荐一下了&#xff0c;那就是cygwin 下载cygwin后&#xff0c;在安装过程中&#xff0c;安装git&#xff0c;安装vim编辑器 然后会在安装目录下看到类linux…

《鸿蒙理论知识06》HarmonyOS概述之应用开发基础知识

目录 APP Ability 库文件 资源文件 配置文件 pack.info HAR APP HarmonyOS 的应用软件包以 APP Pack(Application Package)形式发布

C#中FuncT,TResult的用法和Lambda表达式

在C#3.0中引用了Limbda表达式&#xff0c;Limbda表达式实际上就是一个方法&#xff0c;只不过该方法是匿名方法&#xff08;即没有名称的方法&#xff09;代码片段&#xff1a; Func<int,string,string> t(int x, string b) > (x.ToString() b);就等于如下&#xff1…

前端代码规范网址导航(总结)

在大公司代码规范是非常重要的一件事情,多人协作,还有代码评审。所以能写出漂亮的代码非常重要。 这就好比你自己在家,无论是穿大裤衩子,还是背心,甚至是光膀子,都没人管你。但你要出门去约会,就要把最好的一面展现给别人。这是对别人的尊重,也是给自己的背书。所以遵…

SCI/EI期刊投稿 Reply Letter 常用格式总结

SCI/EI期刊投稿Reply Letter常用格式总结整个论文投稿的过程中&#xff0c;会遇到各种问题&#xff0c;需要我们向主编询问或是回复。下面主要总结了responses to the comments&#xff0c;以及催稿信的模板。1、回复信&#xff08;Response Letter&#xff09;在期刊投稿中&am…

rabbitmq 传递文件_RabbitMQ:计划邮件传递

rabbitmq 传递文件本月初&#xff0c;我在ComoRichWeb上的RabbitMQ上做了一个演讲&#xff0c;与会人员提出的一个问题是“是否可以发布一条消息供以后使用&#xff1f;” 我回答说&#xff0c;就我所知&#xff0c;这是不可能的&#xff0c;但是可能会有一些技巧来实现它。 好…

《01》ECMAScript 6 简介

ECMAScript 6.0&#xff08;以下简称 ES6&#xff09;是 JavaScript 语言的下一代标准&#xff0c;已经在 2015 年 6 月正式发布了。它的目标&#xff0c;是使得 JavaScript 语言可以用来编写复杂的大型应用程序&#xff0c;成为企业级开发语言。 目录 1.ECMAScript 和 JavaScr…

BZOJ4562: [Haoi2016]食物链

Description 如图所示为某生态系统的食物网示意图&#xff0c;据图回答第1小题现在给你n个物种和m条能量流动关系&#xff0c;求其中的食物链条数。物种的名称为从1到n编号M条能量流动关系形如a1 b1a2 b2a3 b3......am-1 bm-1am bm其中ai bi表示能量从物种ai流向物种bi,注意单独…

JLupin Next Server乍一看

JEE基础结构现在有了一个新的管理解决方案– JLupin Next Server。 它为应用程序实现提供了另一种方法。 它提供什么&#xff1f; 用于实现JEE应用程序的现有解决方案受到限制。 通过新的应用程序管理方式&#xff0c;JLupin Next Server打破了所有障碍。 JEE的足迹 良好实践…

《02》let 和 const 命令

目录 1.let命令 基本用法 暂时性死区 不允许重复声明 2.块级作用域 3.const 命令 基本用法 本质 1.let命令 基本用法 ES6 新增了let命令&#xff0c;用来声明变量。它的用法类似于var&#xff0c;但是所声明的变量&#xff0c;只在let命令所在的代码块内有效。 <…

在线支付模块小结

一、概述 在所有的电子商务网站中都提供了在线支付功能&#xff0c;用户可以将在网上选购的商品生成订单后通过网站提供的在线支付功能进行结算。网站开发者可以直接使用银行提供的接口实现在线支付&#xff0c;也可以使用第三方支付平台来实现。使用银行接口需要自行开发程序&…

《03》JavaScript编码风格

探讨如何将 ES6 的新语法&#xff0c;运用到编码实践之中&#xff0c;与传统的 JavaScript 语法结合在一起&#xff0c;写出合理的、易于阅读和维护的JavaScript 风格规范代码。 目录 1.块级作用域 &#xff08;1&#xff09;let 取代 var &#xff08;2&#xff09;全局常量…