Apache OpenNLP 2.5.12 构建并运行示例应用指南

Apache OpenNLP 2.5.12 构建并运行示例应用指南(Java API 使用示例):从零创建 Maven 工程、阿里云镜像配置、完整 pom.xml 与示例源码(TokenizerME 分词 / POSTaggerME 词性标注 / TokenNameFinder 命名实体识别)、编译运行命令与真实回显,含 JVM 堆限制与 FAQ,全程实测。

Apache OpenNLPApache OpenNLP2026/10/12

Apache OpenNLP 2.5.12 构建并运行示例应用指南

目标:从零构建并运行一个基于 Apache OpenNLP 2.5.12 的 Java 示例应用(Maven 工程 + Java API),串联完成分词(TokenizerME)、词性标注(POSTaggerME)、命名实体识别(TokenNameFinder)三类 NLP 任务。给出 Maven 镜像配置、完整 pom.xml、示例 Java 源码、编译与运行命令及真实回显。所有命令与输出均在 Ubuntu 22.04.5 + JDK 17 + OpenNLP 2.5.12 环境实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(jammy)
  • Java:OpenJDK 17.0.20.1
  • 构建工具:Apache Maven 3.6.3
  • OpenNLP 版本:2.5.12(依赖 org.apache.opennlp:opennlp-tools:2.5.12)
  • 示例工程目录:/root/opennlp-demo/
  • 模型目录:/opt/opennlp/models/(en-token.bin、opennlp-en-ud-ewt-pos-1.3-2.5.4.bin、en-ner-person.bin)
  • 演示账号:root

二、前置条件

已按《Ubuntu 22.04 安装 Apache OpenNLP 2.5.12 指南》完成安装:

  • JDK 17 与 Maven 3.6.3 可用(java -version、mvn -version 正常回显);
  • OpenNLP 2.5.12 安装于 /opt/opennlp-2.5.12;
  • 模型文件已下载至 /opt/opennlp/models/。

验证命令:

java -version
mvn -version
ls -l /opt/opennlp/models/en-token.bin /opt/opennlp/models/opennlp-en-ud-ewt-pos-1.3-2.5.4.bin /opt/opennlp/models/en-ner-person.bin

三、工程结构

标准 Maven 布局,仅一个 pom 与一个主类:

opennlp-demo/
├── pom.xml
└── src/main/java/demo/OpenNlpDemo.java
mkdir -p /root/opennlp-demo/src/main/java/demo

四、Maven 镜像配置

国内网络环境为加速依赖下载,在 ~/.m2/settings.xml 配置阿里云公共镜像(实测依赖下载走该镜像):

mkdir -p /root/.m2
cat > /root/.m2/settings.xml <<'EOF'
<settings>
  <mirrors>
    <mirror>
      <id>aliyun</id>
      <mirrorOf>central</mirrorOf>
      <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
  </mirrors>
</settings>
EOF

五、完整 pom.xml

pom 声明 opennlp-tools 2.5.12 依赖,并通过 exec-maven-plugin 执行主类:

<?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>demo</groupId>
    <artifactId>opennlp-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.opennlp</groupId>
            <artifactId>opennlp-tools</artifactId>
            <version>2.5.12</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <mainClass>demo.OpenNlpDemo</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

六、示例源码

创建 /root/opennlp-demo/src/main/java/demo/OpenNlpDemo.java,完成三步:TokenizerME 分词 → POSTaggerME 词性标注 → TokenNameFinder 命名实体识别:

package demo;

import opennlp.tools.namefind.NameFinderME;
import opennlp.tools.namefind.TokenNameFinderModel;
import opennlp.tools.postag.POSModel;
import opennlp.tools.postag.POSTaggerME;
import opennlp.tools.tokenize.TokenizerME;
import opennlp.tools.tokenize.TokenizerModel;
import opennlp.tools.util.Span;

import java.io.FileInputStream;
import java.util.Arrays;

public class OpenNlpDemo {

    public static void main(String[] args) throws Exception {
        String text = "Pierre Vinken, 61 years old, will join the board as a nonexecutive director on November 29. Mr. Vinken is chairman of Elsevier N.V., the Dutch publishing group. Alice Smith works at Google in New York.";

        // 1) TokenizerME:学习型分词器(模型 en-token.bin)
        TokenizerModel tokenModel = new TokenizerModel(new FileInputStream("/opt/opennlp/models/en-token.bin"));
        TokenizerME tokenizer = new TokenizerME(tokenModel);
        String[] tokens = tokenizer.tokenize(text);
        System.out.println("=== TokenizerME 分词结果 ===");
        System.out.println(String.join(" | ", tokens));

        // 2) POSTaggerME:词性标注(输出 token_TAG,模型为 UD 词性模型)
        POSModel posModel = new POSModel(new FileInputStream("/opt/opennlp/models/opennlp-en-ud-ewt-pos-1.3-2.5.4.bin"));
        POSTaggerME tagger = new POSTaggerME(posModel);
        String[] tags = tagger.tag(tokens);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < tokens.length; i++) {
            if (i > 0) {
                sb.append(' ');
            }
            sb.append(tokens[i]).append('_').append(tags[i]);
        }
        System.out.println("=== POSTaggerME 词性标注(token_TAG)===");
        System.out.println(sb);

        // 3) TokenNameFinder:命名实体识别(人名 person,模型 en-ner-person.bin)
        TokenNameFinderModel nerModel = new TokenNameFinderModel(new FileInputStream("/opt/opennlp/models/en-ner-person.bin"));
        NameFinderME finder = new NameFinderME(nerModel);
        Span[] spans = finder.find(tokens);
        double[] probs = finder.probs(spans);
        System.out.println("=== TokenNameFinder 人名识别 ===");
        for (int i = 0; i < spans.length; i++) {
            Span span = spans[i];
            String entity = String.join(" ", Arrays.copyOfRange(tokens, span.getStart(), span.getEnd()));
            System.out.println("类型=" + span.getType() + " 概率=" + probs[i] + " 实体=" + entity);
        }
    }
}

💡 说明:三个模型分别来自安装指南中的传统 demo 模型站(en-token.bin、en-ner-person.bin)与 Apache 官方 UD 模型(opennlp-en-ud-ewt-pos-1.3-2.5.4.bin);词性标注输出为 UD 标签集(PROPN/NOUN/AUX 等)。

七、编译与运行

编译(实测成功,退出码 0,无任何输出):

export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
cd /root/opennlp-demo
mvn -q clean compile

运行(UTF-8 环境,限制示例 JVM 堆为 256 MB):

export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 MAVEN_OPTS="-Xms256m -Xmx256m"
cd /root/opennlp-demo
mvn -q exec:java

八、运行结果解读

程序真实输出(退出码 0):

SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.
=== TokenizerME 分词结果 ===
Pierre | Vinken | , | 61 | years | old | , | will | join | the | board | as | a | nonexecutive | director | on | November | 29 | . | Mr. | Vinken | is | chairman | of | Elsevier | N.V. | , | the | Dutch | publishing | group | . | Alice | Smith | works | at | Google | in | New | York | .
=== POSTaggerME 词性标注(token_TAG)===
Pierre_PROPN Vinken_PROPN ,_PUNCT 61_NUM years_NOUN old_ADJ ,_PUNCT will_AUX join_VERB the_DET board_NOUN as_ADP a_DET nonexecutive_ADJ director_NOUN on_ADP November_PROPN 29_NUM ._PUNCT Mr._PROPN Vinken_PROPN is_AUX chairman_NOUN of_ADP Elsevier_ADJ N.V._PROPN ,_PUNCT the_DET Dutch_PROPN publishing_VERB group_NOUN ._PUNCT Alice_PROPN Smith_PROPN works_VERB at_ADP Google_PROPN in_ADP New_ADJ York_PROPN ._PUNCT
=== TokenNameFinder 人名识别 ===
类型=person 概率=0.9445758431440533 实体=Pierre Vinken
类型=person 概率=0.9593189992179502 实体=Alice Smith

结果解读:

  • TokenizerME:把整句切成 41 个 token;Mr.、N.V. 等含缩写点的词被保留为单个 token(与 SimpleTokenizer 的切法不同,详见《Apache OpenNLP 2.5.12 常用工具与 API 详解》篇)。
  • POSTaggerME:为每个 token 标注 UD 词性——PROPN(专有名词)、NOUN(名词)、VERB(动词)、AUX(助动词)、DET(限定词)、ADP(介词)、ADJ(形容词)、NUM(数词)、PUNCT(标点)。
  • TokenNameFinder:识别出 2 个人名实体——Pierre Vinken(person,概率 0.945)、Alice Smith(person,概率 0.959)。
  • 首行三条 SLF4J(W) 仅表示 classpath 未绑定 SLF4J 日志实现(NOP logger),不影响任何功能。

九、注意事项

⚠️ 注意:

  1. 示例进程堆内存用 MAVEN_OPTS="-Xms256m -Xmx256m" 限制;生产环境按内存规划调整。
  2. 词性标注模型与分词模型来自不同模型站(UD 与传统 demo),标签体系不同不影响示例运行,但训练/评测时须保持标签集一致。
  3. 模型文件用绝对路径加载(new TokenizerModel(new FileInputStream(...)) 即上文源码中的用法);更多 API 类与用法见《Apache OpenNLP 2.5.12 常用工具与 API 详解》篇。

十、常见问题

Q1:mvn 下载依赖失败 / 超时? 检查 /root/.m2/settings.xml 的阿里云镜像是否生效(mirrorOf 为 central);必要时删除 ~/.m2/repository 重新拉取。

Q2:运行报 FileNotFoundException? 模型路径不存在。确认 /opt/opennlp/models/ 下存在 en-token.bin、opennlp-en-ud-ewt-pos-1.3-2.5.4.bin、en-ner-person.bin 三个文件。

Q3:输出中文乱码? OpenNLP 模型面向英文。运行前 export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8,保证管道与终端 UTF-8。

Q4:内存占用偏高? 示例已用 MAVEN_OPTS="-Xms256m -Xmx256m" 限制 JVM 堆;如需复核实际生效堆参数,另开终端执行 ps -ef | grep [j]ava | grep -o "\-Xmx[^ ]*",应看到 -Xmx256m(⚠️ 说明:MAVEN_OPTS 注入为实测运行方式,ps 抓取为通用核对命令,本次未单独保存该场景回显)。

Q5:SLF4J 告警影响使用吗? 不影响。SLF4J(W): No SLF4J providers were found. 表示未绑定日志实现,程序照常运行;如需日志输出可引入 slf4j-simple 等实现。

十一、参考链接

  • Apache OpenNLP 官方文档:https://opennlp.apache.org/docs/
  • opennlp-tools 依赖坐标:org.apache.opennlp:opennlp-tools:2.5.12(Maven Central)
  • Apache OpenNLP 下载目录:https://dlcdn.apache.org/opennlp/
  • demo 模型站:https://opennlp.sourceforge.net/models-1.5/