详解Spring Boot 中使用 Java API 调用 lucene

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎

全文检索概述

比如,我们一个文件夹中,或者一个磁盘中有很多的文件,记事本、world、Excel、pdf,我们想根据其中的关键词搜索包含的文件。例如,我们输入Lucene,所有内容含有Lucene的文件就会被检查出来。这就是所谓的全文检索。

因此,很容易的我们想到,应该建立一个关键字与文件的相关映射,盗用ppt中的一张图,很明白的解释了这种映射如何实现。

倒排索引

有了这种映射关系,我们就来看看Lucene的架构设计。

下面是Lucene的资料必出现的一张图,但也是其精髓的概括。

我们可以看到,Lucene的使用主要体现在两个步骤:

1 创建索引,通过IndexWriter对不同的文件进行索引的创建,并将其保存在索引相关文件存储的位置中。

2 通过索引查寻关键字相关文档。

在Lucene中,就是使用这种“倒排索引”的技术,来实现相关映射。

Lucene数学模型

文档、域、词元

文档是Lucene搜索和索引的原子单位,文档为包含一个或者多个域的容器,而域则是依次包含“真正的”被搜索的内容,域值通过分词技术处理,得到多个词元。

For Example,一篇小说(斗破苍穹)信息可以称为一个文档,小说信息又包含多个域,例如:标题(斗破苍穹)、作者、简介、最后更新时间等等,对标题这个域采用分词技术又可以得到一个或者多个词元(斗、破、苍、穹)。

Lucene文件结构

层次结构

index
一个索引存放在一个目录中

segment
一个索引中可以有多个段,段与段之间是独立的,添加新的文档可能产生新段,不同的段可以合并成一个新段

document
文档是创建索引的基本单位,不同的文档保存在不同的段中,一个段可以包含多个文档

field
域,一个文档包含不同类型的信息,可以拆分开索引

term
词,索引的最小单位,是经过词法分析和语言处理后的数据。

正向信息

按照层次依次保存了从索引到词的包含关系:index-->segment-->document-->field-->term。

反向信息

反向信息保存了词典的倒排表映射:term-->document

IndexWriter
lucene中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用。

Analyzer
分析器,主要用于分析搜索引擎遇到的各种文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。

Directory
索引存放的位置;lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。

Document
文档;Document相当于一个要进行索引的单元,任何可以想要被索引的文件都必须转化为Document对象才能进行索引。

Field
字段。

IndexSearcher
是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具;

Query
查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。

QueryParser
是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。

Hits
在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在lucene中,搜索的结果的集合是用Hits类的实例来表示的。

测试用例

Github 代码

代码我已放到 Github ,导入spring-boot-lucene-demo 项目

github spring-boot-lucene-demo

添加依赖

<!--对分词索引查询解析-->
<dependency>
  <groupId>org.apache.lucene</groupId>
  <artifactId>lucene-queryparser</artifactId>
  <version>7.1.0</version>
</dependency>

<!--高亮 -->
<dependency>
  <groupId>org.apache.lucene</groupId>
  <artifactId>lucene-highlighter</artifactId>
  <version>7.1.0</version>
</dependency>

<!--smartcn 中文分词器 SmartChineseAnalyzer smartcn分词器 需要lucene依赖 且和lucene版本同步-->
<dependency>
  <groupId>org.apache.lucene</groupId>
  <artifactId>lucene-analyzers-smartcn</artifactId>
  <version>7.1.0</version>
</dependency>

<!--ik-analyzer 中文分词器-->
<dependency>
  <groupId>cn.bestwu</groupId>
  <artifactId>ik-analyzers</artifactId>
  <version>5.1.0</version>
</dependency>

<!--MMSeg4j 分词器-->
<dependency>
  <groupId>com.chenlb.mmseg4j</groupId>
  <artifactId>mmseg4j-solr</artifactId>
  <version>2.4.0</version>
  <exclusions>
    <exclusion>
      <groupId>org.apache.solr</groupId>
      <artifactId>solr-core</artifactId>
    </exclusion>
  </exclusions>
</dependency>

配置 lucene

private Directory directory;

private IndexReader indexReader;

private IndexSearcher indexSearcher;

@Before
public void setUp() throws IOException {
  //索引存放的位置,设置在当前目录中
  directory = FSDirectory.open(Paths.get("indexDir/"));

  //创建索引的读取器
  indexReader = DirectoryReader.open(directory);

  //创建一个索引的查找器,来检索索引库
  indexSearcher = new IndexSearcher(indexReader);
}

@After
public void tearDown() throws Exception {
  indexReader.close();
}

**
 * 执行查询,并打印查询到的记录数
 *
 * @param query
 * @throws IOException
 */
public void executeQuery(Query query) throws IOException {

  TopDocs topDocs = indexSearcher.search(query, 100);

  //打印查询到的记录数
  System.out.println("总共查询到" + topDocs.totalHits + "个文档");
  for (ScoreDoc scoreDoc : topDocs.scoreDocs) {

    //取得对应的文档对象
    Document document = indexSearcher.doc(scoreDoc.doc);
    System.out.println("id:" + document.get("id"));
    System.out.println("title:" + document.get("title"));
    System.out.println("content:" + document.get("content"));
  }
}

/**
 * 分词打印
 *
 * @param analyzer
 * @param text
 * @throws IOException
 */
public void printAnalyzerDoc(Analyzer analyzer, String text) throws IOException {

  TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text));
  CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
  try {
    tokenStream.reset();
    while (tokenStream.incrementToken()) {
      System.out.println(charTermAttribute.toString());
    }
    tokenStream.end();
  } finally {
    tokenStream.close();
    analyzer.close();
  }
}

创建索引

@Test
public void indexWriterTest() throws IOException {
  long start = System.currentTimeMillis();

  //索引存放的位置,设置在当前目录中
  Directory directory = FSDirectory.open(Paths.get("indexDir/"));

  //在 6.6 以上版本中 version 不再是必要的,并且,存在无参构造方法,可以直接使用默认的 StandardAnalyzer 分词器。
  Version version = Version.LUCENE_7_1_0;

  //Analyzer analyzer = new StandardAnalyzer(); // 标准分词器,适用于英文
  //Analyzer analyzer = new SmartChineseAnalyzer();//中文分词
  //Analyzer analyzer = new ComplexAnalyzer();//中文分词
  //Analyzer analyzer = new IKAnalyzer();//中文分词

  Analyzer analyzer = new IKAnalyzer();//中文分词

  //创建索引写入配置
  IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);

  //创建索引写入对象
  IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);

  //创建Document对象,存储索引

  Document doc = new Document();

  int id = 1;

  //将字段加入到doc中
  doc.add(new IntPoint("id", id));
  doc.add(new StringField("title", "Spark", Field.Store.YES));
  doc.add(new TextField("content", "Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎", Field.Store.YES));
  doc.add(new StoredField("id", id));

  //将doc对象保存到索引库中
  indexWriter.addDocument(doc);

  indexWriter.commit();
  //关闭流
  indexWriter.close();

  long end = System.currentTimeMillis();
  System.out.println("索引花费了" + (end - start) + " 毫秒");
}

响应

17:58:14.655 [main] DEBUG org.wltea.analyzer.dic.Dictionary - 加载扩展词典:ext.dic
17:58:14.660 [main] DEBUG org.wltea.analyzer.dic.Dictionary - 加载扩展停止词典:stopword.dic
索引花费了879 毫秒

删除文档

@Test
public void deleteDocumentsTest() throws IOException {
  //Analyzer analyzer = new StandardAnalyzer(); // 标准分词器,适用于英文
  //Analyzer analyzer = new SmartChineseAnalyzer();//中文分词
  //Analyzer analyzer = new ComplexAnalyzer();//中文分词
  //Analyzer analyzer = new IKAnalyzer();//中文分词

  Analyzer analyzer = new IKAnalyzer();//中文分词

  //创建索引写入配置
  IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);

  //创建索引写入对象
  IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);

  // 删除title中含有关键词“Spark”的文档
  long count = indexWriter.deleteDocuments(new Term("title", "Spark"));

  // 除此之外IndexWriter还提供了以下方法:
  // DeleteDocuments(Query query):根据Query条件来删除单个或多个Document
  // DeleteDocuments(Query[] queries):根据Query条件来删除单个或多个Document
  // DeleteDocuments(Term term):根据Term来删除单个或多个Document
  // DeleteDocuments(Term[] terms):根据Term来删除单个或多个Document
  // DeleteAll():删除所有的Document

  //使用IndexWriter进行Document删除操作时,文档并不会立即被删除,而是把这个删除动作缓存起来,当IndexWriter.Commit()或IndexWriter.Close()时,删除操作才会被真正执行。

  indexWriter.commit();
  indexWriter.close();

  System.out.println("删除完成:" + count);
}

响应

删除完成:1

更新文档

/**
 * 测试更新
 * 实际上就是删除后新增一条
 *
 * @throws IOException
 */
@Test
public void updateDocumentTest() throws IOException {
  //Analyzer analyzer = new StandardAnalyzer(); // 标准分词器,适用于英文
  //Analyzer analyzer = new SmartChineseAnalyzer();//中文分词
  //Analyzer analyzer = new ComplexAnalyzer();//中文分词
  //Analyzer analyzer = new IKAnalyzer();//中文分词

  Analyzer analyzer = new IKAnalyzer();//中文分词

  //创建索引写入配置
  IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);

  //创建索引写入对象
  IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);

  Document doc = new Document();

  int id = 1;

  doc.add(new IntPoint("id", id));
  doc.add(new StringField("title", "Spark", Field.Store.YES));
  doc.add(new TextField("content", "Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎", Field.Store.YES));
  doc.add(new StoredField("id", id));

  long count = indexWriter.updateDocument(new Term("id", "1"), doc);
  System.out.println("更新文档:" + count);
  indexWriter.close();
}

响应

更新文档:1

按词条搜索

/**
 * 按词条搜索
 * <p>
 * TermQuery是最简单、也是最常用的Query。TermQuery可以理解成为“词条搜索”,
 * 在搜索引擎中最基本的搜索就是在索引中搜索某一词条,而TermQuery就是用来完成这项工作的。
 * 在Lucene中词条是最基本的搜索单位,从本质上来讲一个词条其实就是一个名/值对。
 * 只不过这个“名”是字段名,而“值”则表示字段中所包含的某个关键字。
 *
 * @throws IOException
 */
@Test
public void termQueryTest() throws IOException {

  String searchField = "title";
  //这是一个条件查询的api,用于添加条件
  TermQuery query = new TermQuery(new Term(searchField, "Spark"));

  //执行查询,并打印查询到的记录数
  executeQuery(query);
}

响应

总共查询到1个文档
id:1
title:Spark
content:Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎!

多条件查询

/**
 * 多条件查询
 *
 * BooleanQuery也是实际开发过程中经常使用的一种Query。
 * 它其实是一个组合的Query,在使用时可以把各种Query对象添加进去并标明它们之间的逻辑关系。
 * BooleanQuery本身来讲是一个布尔子句的容器,它提供了专门的API方法往其中添加子句,
 * 并标明它们之间的关系,以下代码为BooleanQuery提供的用于添加子句的API接口:
 *
 * @throws IOException
 */
@Test
public void BooleanQueryTest() throws IOException {

  String searchField1 = "title";
  String searchField2 = "content";
  Query query1 = new TermQuery(new Term(searchField1, "Spark"));
  Query query2 = new TermQuery(new Term(searchField2, "Apache"));
  BooleanQuery.Builder builder = new BooleanQuery.Builder();

  // BooleanClause用于表示布尔查询子句关系的类,
  // 包 括:
  // BooleanClause.Occur.MUST,
  // BooleanClause.Occur.MUST_NOT,
  // BooleanClause.Occur.SHOULD。
  // 必须包含,不能包含,可以包含三种.有以下6种组合:
  //
  // 1.MUST和MUST:取得连个查询子句的交集。
  // 2.MUST和MUST_NOT:表示查询结果中不能包含MUST_NOT所对应得查询子句的检索结果。
  // 3.SHOULD与MUST_NOT:连用时,功能同MUST和MUST_NOT。
  // 4.SHOULD与MUST连用时,结果为MUST子句的检索结果,但是SHOULD可影响排序。
  // 5.SHOULD与SHOULD:表示“或”关系,最终检索结果为所有检索子句的并集。
  // 6.MUST_NOT和MUST_NOT:无意义,检索无结果。

  builder.add(query1, BooleanClause.Occur.SHOULD);
  builder.add(query2, BooleanClause.Occur.SHOULD);

  BooleanQuery query = builder.build();

  //执行查询,并打印查询到的记录数
  executeQuery(query);
}

响应

总共查询到1个文档
id:1
title:Spark
content:Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎!

匹配前缀

/**
 * 匹配前缀
 * <p>
 * PrefixQuery用于匹配其索引开始以指定的字符串的文档。就是文档中存在xxx%
 * <p>
 *
 * @throws IOException
 */
@Test
public void prefixQueryTest() throws IOException {
  String searchField = "title";
  Term term = new Term(searchField, "Spar");
  Query query = new PrefixQuery(term);

  //执行查询,并打印查询到的记录数
  executeQuery(query);
}

响应

总共查询到1个文档
id:1
title:Spark
content:Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎!

短语搜索

/**
 * 短语搜索
 * <p>
 * 所谓PhraseQuery,就是通过短语来检索,比如我想查“big car”这个短语,
 * 那么如果待匹配的document的指定项里包含了"big car"这个短语,
 * 这个document就算匹配成功。可如果待匹配的句子里包含的是“big black car”,
 * 那么就无法匹配成功了,如果也想让这个匹配,就需要设定slop,
 * 先给出slop的概念:slop是指两个项的位置之间允许的最大间隔距离
 *
 * @throws IOException
 */
@Test
public void phraseQueryTest() throws IOException {

  String searchField = "content";
  String query1 = "apache";
  String query2 = "spark";

  PhraseQuery.Builder builder = new PhraseQuery.Builder();
  builder.add(new Term(searchField, query1));
  builder.add(new Term(searchField, query2));
  builder.setSlop(0);
  PhraseQuery phraseQuery = builder.build();

  //执行查询,并打印查询到的记录数
  executeQuery(phraseQuery);
}

响应

总共查询到1个文档
id:1
title:Spark
content:Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎!

相近词语搜索

/**
 * 相近词语搜索
 * <p>
 * FuzzyQuery是一种模糊查询,它可以简单地识别两个相近的词语。
 *
 * @throws IOException
 */
@Test
public void fuzzyQueryTest() throws IOException {

  String searchField = "content";
  Term t = new Term(searchField, "大规模");
  Query query = new FuzzyQuery(t);

  //执行查询,并打印查询到的记录数
  executeQuery(query);
}

响应

总共查询到1个文档
id:1
title:Spark
content:Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎!

通配符搜索

/**
 * 通配符搜索
 * <p>
 * Lucene也提供了通配符的查询,这就是WildcardQuery。
 * 通配符“?”代表1个字符,而“*”则代表0至多个字符。
 *
 * @throws IOException
 */
@Test
public void wildcardQueryTest() throws IOException {
  String searchField = "content";
  Term term = new Term(searchField, "大*规模");
  Query query = new WildcardQuery(term);

  //执行查询,并打印查询到的记录数
  executeQuery(query);
}

响应

总共查询到1个文档
id:1
title:Spark
content:Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎!

分词查询

/**
 * 分词查询
 *
 * @throws IOException
 * @throws ParseException
 */
@Test
public void queryParserTest() throws IOException, ParseException {
  //Analyzer analyzer = new StandardAnalyzer(); // 标准分词器,适用于英文
  //Analyzer analyzer = new SmartChineseAnalyzer();//中文分词
  //Analyzer analyzer = new ComplexAnalyzer();//中文分词
  //Analyzer analyzer = new IKAnalyzer();//中文分词

  Analyzer analyzer = new IKAnalyzer();//中文分词

  String searchField = "content";

  //指定搜索字段和分析器
  QueryParser parser = new QueryParser(searchField, analyzer);

  //用户输入内容
  Query query = parser.parse("计算引擎");

  //执行查询,并打印查询到的记录数
  executeQuery(query);
}

响应

总共查询到1个文档
id:1
title:Spark
content:Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎!

多个 Field 分词查询

/**
 * 多个 Field 分词查询
 *
 * @throws IOException
 * @throws ParseException
 */
@Test
public void multiFieldQueryParserTest() throws IOException, ParseException {
  //Analyzer analyzer = new StandardAnalyzer(); // 标准分词器,适用于英文
  //Analyzer analyzer = new SmartChineseAnalyzer();//中文分词
  //Analyzer analyzer = new ComplexAnalyzer();//中文分词
  //Analyzer analyzer = new IKAnalyzer();//中文分词

  Analyzer analyzer = new IKAnalyzer();//中文分词

  String[] filedStr = new String[]{"title", "content"};

  //指定搜索字段和分析器
  QueryParser queryParser = new MultiFieldQueryParser(filedStr, analyzer);

  //用户输入内容
  Query query = queryParser.parse("Spark");

  //执行查询,并打印查询到的记录数
  executeQuery(query);
}

响应

总共查询到1个文档
id:1
title:Spark
content:Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎!

中文分词器

/**
 * IKAnalyzer 中文分词器
 * SmartChineseAnalyzer smartcn分词器 需要lucene依赖 且和lucene版本同步
 *
 * @throws IOException
 */
@Test
public void AnalyzerTest() throws IOException {
  //Analyzer analyzer = new StandardAnalyzer(); // 标准分词器,适用于英文
  //Analyzer analyzer = new SmartChineseAnalyzer();//中文分词
  //Analyzer analyzer = new ComplexAnalyzer();//中文分词
  //Analyzer analyzer = new IKAnalyzer();//中文分词

  Analyzer analyzer = null;
  String text = "Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎";

  analyzer = new IKAnalyzer();//IKAnalyzer 中文分词
  printAnalyzerDoc(analyzer, text);
  System.out.println();

  analyzer = new ComplexAnalyzer();//MMSeg4j 中文分词
  printAnalyzerDoc(analyzer, text);
  System.out.println();

  analyzer = new SmartChineseAnalyzer();//Lucene 中文分词器
  printAnalyzerDoc(analyzer, text);
}

三种分词响应

apache
spark
专为
大规模
规模
模数
数据处理
数据
处理
而设
设计
快速
通用
计算
引擎
apache
spark
是
专为
大规模
数据处理
而
设计
的
快速
通用
的
计算
引擎
apach
spark
是
专
为
大规模
数据
处理
而
设计
的
快速
通用
的
计算
引擎

高亮处理

/**
 * 高亮处理
 *
 * @throws IOException
 */
@Test
public void HighlighterTest() throws IOException, ParseException, InvalidTokenOffsetsException {
  //Analyzer analyzer = new StandardAnalyzer(); // 标准分词器,适用于英文
  //Analyzer analyzer = new SmartChineseAnalyzer();//中文分词
  //Analyzer analyzer = new ComplexAnalyzer();//中文分词
  //Analyzer analyzer = new IKAnalyzer();//中文分词

  Analyzer analyzer = new IKAnalyzer();//中文分词

  String searchField = "content";
  String text = "Apache Spark 大规模数据处理";

  //指定搜索字段和分析器
  QueryParser parser = new QueryParser(searchField, analyzer);

  //用户输入内容
  Query query = parser.parse(text);

  TopDocs topDocs = indexSearcher.search(query, 100);

  // 关键字高亮显示的html标签,需要导入lucene-highlighter-xxx.jar
  SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>");
  Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));

  for (ScoreDoc scoreDoc : topDocs.scoreDocs) {

    //取得对应的文档对象
    Document document = indexSearcher.doc(scoreDoc.doc);

    // 内容增加高亮显示
    TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(document.get("content")));
    String content = highlighter.getBestFragment(tokenStream, document.get("content"));

    System.out.println(content);
  }

}

响应

<span style='color:red'>Apache</span> <span style='color:red'>Spark</span> 是专为<span style='color:red'>大规模数据处理</span>而设计的快速通用的计算引擎!

代码我已放到 Github ,导入spring-boot-lucene-demo 项目

github spring-boot-lucene-demo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解SpringBoot配置连接池

    内置的连接池 目前spring Boot中默认支持的连接池有dbcp,dbcp2, tomcat, hikari三种连接池. 数据库连接可以使用DataSource池进行自动配置. 由于Tomcat数据源连接池的性能和并发,在tomcat可用时,我们总是优先使用它. 如果HikariCP可用,我们将使用它. 如果Commons DBCP可用,我们将使用它,但在生产环境不推荐使用它. 最后,如果Commons DBCP2可用,我们将使用它. 以上的几种连接池,可以通过在配置application文

  • Spring boot 默认静态资源路径与手动配置访问路径的方法

    在application.propertis中配置 ##端口号 server.port=8081 ##默认前缀 spring.mvc.view.prefix=/ ## 响应页面默认后缀 spring.mvc.view.suffix=.html # 默认值为 /** spring.mvc.static-path-pattern=/** # 这里设置要指向的路径,多个使用英文逗号隔开,默认值为 classpath:/META-INF/resources/,classpath:/resources/,

  • springboot实现拦截器之验证登录示例

    整理文档,搜刮出一个springboot实现拦截器之验证登录示例,稍微整理精简一下做下分享. 添加jar包,这个jar包不是必须的,只是在拦截器里用到了,如果不用的话,完全可以不引入 <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.5</version> </dep

  • 如何把spring boot项目部署到tomcat容器中

    把spring-boot项目按照平常的web项目一样发布到tomcat容器下 一.修改打包形式 在pom.xml里设置 <packaging>war</packaging> 二.移除嵌入式tomcat插件 在pom.xml里找到spring-boot-starter-web依赖节点,在其中添加如下代码, <dependency> <groupId>org.springframework.boot</groupId> <artifactId&

  • Spring boot实现热部署的两种方式详解

    热部署是什么 大家都知道在项目开发过程中,常常会改动页面数据或者修改数据结构,为了显示改动效果,往往需要重启应用查看改变效果,其实就是重新编译生成了新的 Class 文件,这个文件里记录着和代码等对应的各种信息,然后 Class 文件将被虚拟机的 ClassLoader 加载. 而热部署正是利用了这个特点,它监听到如果有 Class 文件改动了,就会创建一个新的 ClaassLoader 进行加载该文件,经过一系列的过程,最终将结果呈现在我们眼前. 类加载机制 Java 中的类经过编译器可以把代

  • 详解SpringBoot文件上传下载和多文件上传(图文)

    最近在学习SpringBoot,以下是最近学习整理的实现文件上传下载的Java代码: 1.开发环境: IDEA15+ Maven+JDK1.8 2.新建一个maven工程: 3.工程框架 4.pom.xml文件依赖项 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation

  • 详解eclipse下创建第一个spring boot项目

    spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者.也就是说,Spring Boot是为了简化Spring开发而生,主要思想是降低spring的入门,使得新手可以以最快的速度让程序在spring框架下跑起来. 今天我们就来创建

  • SpringBoot定时任务两种(Spring Schedule 与 Quartz 整合 )实现方法

    前言 最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Schedule 可以帮助我们实现简单的定时任务功能. 下面说一下两种方式在Spring Boot 项目中的使用. Spring Schedule 实现定时任务 Spring Schedule 实现定时任务有两种方式 1. 使用XML配置定时任务, 2. 使用 @Scheduled 注解. 因为是Spring Boot 项目 可能尽量避免使用XML配置的形式,

  • springboot与mybatis整合实例详解(完美融合)

    简介 从 Spring Boot 项目名称中的 Boot 可以看出来,Spring Boot 的作用在于创建和启动新的基于 Spring 框架的项目.它的目的是帮助开发人员很容易的创建出独立运行和产品级别的基于 Spring 框架的应用.Spring Boot 会选择最适合的 Spring 子项目和第三方开源库进行整合.大部分 Spring Boot 应用只需要非常少的配置就可以快速运行起来. Spring Boot 包含的特性如下: 创建可以独立运行的 Spring 应用. 直接嵌入 Tomc

  • 详解Spring Boot 中使用 Java API 调用 lucene

    Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言).Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎 全文检索概述 比如,我们一个文件夹中,或者一个磁盘中有很多的文件,记事本.world.Excel.pdf,我们

  • 详解Spring Boot中使用Flyway来管理数据库版本

    如果没有读过上面内容的读者,有兴趣的可以一阅.在上面的使用JdbcTemplate一文中,主要通过spring提供的JdbcTemplate实现对用户表的增删改查操作.在实现这个例子的时候,我们事先在MySQL中创建了用户表.创建表的过程我们在实际开发系统的时候会经常使用,但是一直有一个问题存在,由于一个系统的程序版本通过git得到了很好的版本控制,而数据库结构并没有,即使我们通过Git进行了语句的版本化,那么在各个环境的数据库中如何做好版本管理呢?下面我们就通过本文来学习一下在Spring B

  • 详解spring boot中使用JdbcTemplate

    本文将介绍如何将spring boot 与 JdbcTemplate一起工作. Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中. JdbcTemplate 是在JDBC API基础上提供了更抽象的封装,并提供了基于方法注解的事务管理能力. 通过使用SpringBoot自动配置功能并代替我们自动配置beans. 数据源配置 在maven中,我们需要增加spring-boot-starter-jdbc

  • 详解Spring Boot中使用@Scheduled创建定时任务

    我们在编写Spring Boot应用中经常会遇到这样的场景,比如:我需要定时地发送一些短信.邮件之类的操作,也可能会定时地检查和监控一些标志.参数等. 创建定时任务 在Spring Boot中编写定时任务是非常简单的事,下面通过实例介绍如何在Spring Boot中创建定时任务,实现每过5秒输出一下当前时间. 在Spring Boot的主类中加入@EnableScheduling注解,启用定时任务的配置 @SpringBootApplication @EnableScheduling publi

  • 详解Spring Boot中使用AOP统一处理Web请求日志

    在spring boot中,简单几步,使用spring AOP实现一个拦截器: 1.引入依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframewo

  • 详解Spring Boot 中实现定时任务的两种方式

    在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Quartz ,Spring Boot 源自 Spring+SpringMVC ,因此天然具备这两个 Spring 中的定时任务实现策略,当然也支持 Quartz,本文我们就来看下 Spring Boot 中两种定时任务的实现方式. @Scheduled 使用 @Scheduled 非常容易,直接创建一个

  • 详解Spring Boot中MyBatis的使用方法

    orm框架的本质是简化编程中操作数据库的编码,发展到现在基本上就剩两家了,一个是宣称可以不用写一句SQL的hibernate,一个是可以灵活调试动态sql的mybatis,两者各有特点,在企业级系统开发中可以根据需求灵活使用.发现一个有趣的现象:传统企业大都喜欢使用hibernate,互联网行业通常使用mybatis. hibernate特点就是所有的sql都用Java代码来生成,不用跳出程序去写(看)sql,有着编程的完整性,发展到最顶端就是spring data jpa这种模式了,基本上根据

  • 详解Spring Boot中如何自定义SpringMVC配置

    目录 前言 一.SpringBoot 中 SpringMVC 配置概述 二.WebMvcConfigurerAdapter 抽象类 三.WebMvcConfigurer 接口 四.WebMvcConfigurationSupport 类-自定义配置 五.WebMvcAutoConfiguration 配置类 – 自动化配置 六.@EnableWebMvc 注解 七.总结 前言 在 Spring Boot 框架中只需要在项目中引入 spring-boot-starter-web 依赖,Spring

  • 详解Spring Boot中Controller用法

    Controller Controller是SpringBoot里最基本的组件,他的作用是把用户提交来的请求通过对URL的匹配,分配个不同的接收器,再进行处理,然后向用户返回结果.他的重点就在于如何从HTTP请求中获得信息,提取参数,并分发给不同的处理服务. 基本组成 一个最经典的Controller应该大概长这样: package com.example.demo.controller; import org.springframework.stereotype.Controller; imp

  • 详解Spring Boot中初始化资源的几种方式

    假设有这么一个需求,要求在项目启动过程中,完成线程池的初始化,加密证书加载等功能,你会怎么做?如果没想好答案,请接着往下看.今天介绍几种在Spring Boot中进行资源初始化的方式,帮助大家解决和回答这个问题. CommandLineRunner 定义初始化类 MyCommandLineRunner 实现 CommandLineRunner 接口,并实现它的 run() 方法,在该方法中编写初始化逻辑 注册成Bean,添加 @Component注解即可 示例代码如下: @Component p

随机推荐