微信号:hj-academy

介绍:关注开发者在实际应用中遇到的问题.提供最真实的干货,以技术会友,为广大的开发者提供最直接的交流平台.

部署 LanguageTool 到 Servlet

2017-12-14 18:37 何晓杰

文:何晓杰

本文原创,转载请注明作者及出处


利用 LanguageTool 来实现语法或拼写的检查是一件很方便的事情,以下内容展示了如何部署一个 LanguageTool 的 Servlet。

首先 clone 代码:

 
           
  1. git clone git@github.com:languagetool-org/languagetool.git

由于项目很大,clone 需要比较久,完成后我们可以编译它:

 
           
  1. $ mvn clean test

  2. $ ./build.sh languagetool-standalone package -DskipTests

取决于网速,编译可能会花 5~30 分钟,编译完成后,可以在 languagetool-standalone/target/LanguageTool-4.0-SNAPSHOT 目录下找到编译结果。

编译结果包含了 languagetool.jarlanguagetool-server.jarlanguagetool-commandline.jar 这三个文件,以及一大堆其他的东西。

此时即可用以下命令来进行测试,如果编译结果正确,那么可以直接运行起一个带窗口的校验工具,也可以运行一个命令行的工具:

 
           
  1. $ echo "I was do book a tickt last night" | java -jar languagetool-commandline.jar -l en-US -m en --json -

上面的句子有语法和拼写的错误,不要在意,是故意写错供查的,这个代码将会返回检查结果:

 
           
  1. {

  2.    "software": {

  3.        "name": "LanguageTool",

  4.        "version": "4.0-SNAPSHOT",

  5.        "buildDate": "2017-11-15 13:25",

  6.        "apiVersion": 1,

  7.        "status": ""

  8.    },

  9.    "warnings": {

  10.        "incompleteResults": false

  11.    },

  12.    "language": {

  13.        "name": "English (US)",

  14.        "code": "en-US"

  15.    },

  16.    "matches": [

  17.        {

  18.            "message": "Consider using a past participle here: \"done\".",

  19.            "shortMessage": "Possible agreement error",

  20.            "replacements": [

  21.                {

  22.                    "value": "done"

  23.                }

  24.            ],

  25.            "offset": 6,

  26.            "length": 2,

  27.            "context": {

  28.                "text": "I was do book a tickt last night ",

  29.                "offset": 6,

  30.                "length": 2

  31.            },

  32.            "rule": {

  33.                "id": "BEEN_PART_AGREEMENT",

  34.                "subId": "1",

  35.                "description": "Agreement: 'been' or 'was' + past tense",

  36.                "issueType": "grammar",

  37.                "category": {

  38.                    "id": "GRAMMAR",

  39.                    "name": "Grammar"

  40.                }

  41.            }

  42.        },

  43.        {

  44.            "message": "Possible spelling mistake found",

  45.            "shortMessage": "Spelling mistake",

  46.            "replacements": [

  47.                {

  48.                    "value": "ticket"

  49.                },

  50.                {

  51.                    "value": "tick"

  52.                },

  53.                {

  54.                    "value": "ticks"

  55.                },

  56.                {

  57.                    "value": "tic kt"

  58.                },

  59.                {

  60.                    "value": "tick t"

  61.                }

  62.            ],

  63.            "offset": 16,

  64.            "length": 5,

  65.            "context": {

  66.                "text": "I was do book a tickt last night ",

  67.                "offset": 16,

  68.                "length": 5

  69.            },

  70.            "rule": {

  71.                "id": "MORFOLOGIK_RULE_EN_US",

  72.                "description": "Possible spelling mistake",

  73.                "issueType": "misspelling",

  74.                "category": {

  75.                    "id": "TYPOS",

  76.                    "name": "Possible Typo"

  77.                }

  78.            }

  79.        }

  80.    ]

  81. }

这样先证明了编译结果的正确与可用。接下去就要写一个简单的 Servlet,把 LanguageTool 封装进去使用,关于 Servlet 的开发就不再赘述了。

建立 Servlet 项目后,将所有 lib 下的文件,连同三个主要 jar 包一起复制到 WEB-INF/lib 内,然后在 Servlet 文件内编写以下代码:

 
           
  1. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  2.    JLanguageTool lt = new JLanguageTool(Languages.getLanguageForShortCode("en-US"));

  3.    List<RuleMatch> list = lt.check(request.getParameter("text"));

  4.    String s = "";

  5.    for (RuleMatch rm: list) {

  6.        s += String.format("message => %s, from => %d, to => %d<br>", rm.getMessage(), rm.getFromPos(), rm.getToPos());

  7.    }

  8.    response.setContentType("text/plain");

  9.    PrintWriter pw = response.getWriter();

  10.    pw.write(s);

  11. }

看起来很简单,编译通过,但是实际运行的时候,会报一个奇怪的错误:

 
           
  1. 'en-US' is not a language code known to LanguageTool. Supported language codes are: xx-XX. The list of languages is read from META-INF/org/languagetool/language-module.properties in the Java classpath.

看起来似乎是少复制了 META-INF 里的内容,但是实际上将编译目录内的 META-INF 拷到 Servlet 项目内的任何目录都不行。

经过一番对编译结果的审视,发现编译后的语言全部以 class 的方式,保存在 org/languagetool/language 内,同时还附带大量的 properties 文件。

这样一看,就找到解决问题的方法了,无非就是要多做一个 jar,而原本的编译脚本并不会为我们制作这样一个 jar 包。

 
           
  1. $ zip -r languages.jar META-INF/ org/

这样就得到一个 languages.jar,把它拷到 WEB-INF/lib 内,就可以在 Servlet 内直接引用了,以上错误也得到了解决。同时,我们还可以把代码写得更简单:

 
           
  1. JLanguageTool lt = new JLanguageTool(new AmericanEnglish());

最后,可以用 curl 来进行测试,证明我们的服务器的确已经正常工作了:

 
           
  1. $ curl -d "text=I was do book a tickt last night" "http://localhost:8080/demo"

  2. message => Consider using a past participle here: <suggestion>done</suggestion>., from => 6, to => 8<br>message => Possible spelling mistake found, from => 16, to => 21



技术沙龙推荐

点击下方图片即可阅读



翻译 | 调整JavaScript抽象的迭代方案


翻译 | 产品经理的谈判秘笈


后端服务性能压测实践


从错误码406说起


 
沪江技术学院 更多文章 GIAC全球互联网架构大会最新日程|第二弹 技术沙龙 | 互联网基础架构的蜕变与进化 翻译 | 调整JavaScript抽象的迭代方案 翻译 | 产品经理的谈判秘笈 视频 | 基于Koa2搭建Node.js实战项目教程
猜您喜欢 【一周IT大事件】 12306验证码看瞎网友,锤子推第二代情怀手机 Android 广播相关的都在这儿 Go Hack 17:Killy 日记 毕业这两年 实录|靓汤:SoapUI常见问题解析