正文
文:何晓杰
本文原创,转载请注明作者及出处
利用 LanguageTool 来实现语法或拼写的检查是一件很方便的事情,以下内容展示了如何部署一个 LanguageTool 的 Servlet。
首先 clone 代码:
git clone [email protected]:languagetool-org/languagetool.git
由于项目很大,clone 需要比较久,完成后我们可以编译它:
$ mvn clean test
$ ./build.sh languagetool-standalone package -DskipTests
取决于网速,编译可能会花 5~30 分钟,编译完成后,可以在 languagetool-standalone/target/LanguageTool-4.0-SNAPSHOT
目录下找到编译结果。
编译结果包含了 languagetool.jar
, languagetool-server.jar
, languagetool-commandline.jar
这三个文件,以及一大堆其他的东西。
此时即可用以下命令来进行测试,如果编译结果正确,那么可以直接运行起一个带窗口的校验工具,也可以运行一个命令行的工具:
$ echo "I was do book a tickt last night" | java -jar languagetool-commandline.jar -l en-US -m en --json -
上面的句子有语法和拼写的错误,不要在意,是故意写错供查的,这个代码将会返回检查结果:
{
"software": {
"name": "LanguageTool",
"version": "4.0-SNAPSHOT",
"buildDate": "2017-11-15 13:25",
"apiVersion": 1,
"status": ""
},
"warnings": {
"incompleteResults": false
},
"language": {
"name": "English (US)",
"code": "en-US"
},
"matches": [
{
"message": "Consider using a past participle here: \"done\".",
"shortMessage": "Possible agreement error",
"replacements": [
{
"value": "done"
}
],
"offset": 6,
"length": 2,
"context": {
"text": "I was do book a tickt last night ",
"offset": 6,
"length": 2
},
"rule": {
"id": "BEEN_PART_AGREEMENT",
"subId": "1",
"description": "Agreement: 'been' or 'was' + past tense",
"issueType": "grammar",
"category": {
"id": "GRAMMAR",
"name": "Grammar"
}
}
},
{
"message": "Possible spelling mistake found",
"shortMessage": "Spelling mistake",
"replacements": [
{
"value": "ticket"
},
{
"value": "tick"
},
{
"value": "ticks"
},
{
"value": "tic kt"
},
{
"value": "tick t"
}
],
"offset": 16,
"length": 5,
"context": {
"text": "I was do book a tickt last night ",
"offset": 16,
"length": 5
},
"rule": {
"id": "MORFOLOGIK_RULE_EN_US",
"description": "Possible spelling mistake",
"issueType": "misspelling",
"category": {
"id": "TYPOS",
"name": "Possible Typo"
}
}
}
]
}
这样先证明了编译结果的正确与可用。接下去就要写一个简单的 Servlet,把 LanguageTool 封装进去使用,关于 Servlet 的开发就不再赘述了。
建立 Servlet 项目后,将所有 lib 下的文件,连同三个主要 jar 包一起复制到 WEB-INF/lib
内,然后在 Servlet 文件内编写以下代码:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
JLanguageTool lt = new JLanguageTool(Languages.getLanguageForShortCode("en-US"));
List<RuleMatch> list = lt.check(request.getParameter("text"));
String s = "";
for (RuleMatch rm: list) {
s += String.format("message => %s, from => %d, to => %d<br>", rm.getMessage(), rm.getFromPos(), rm.getToPos());
}
response.setContentType("text/plain");
PrintWriter pw = response.getWriter();
pw.write(s);
}
看起来很简单,编译通过,但是实际运行的时候,会报一个奇怪的错误:
'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 包。
$ zip -r languages.jar META-INF/ org/
这样就得到一个 languages.jar,把它拷到 WEB-INF/lib
内,就可以在 Servlet 内直接引用了,以上错误也得到了解决。同时,我们还可以把代码写得更简单:
JLanguageTool lt = new JLanguageTool(new AmericanEnglish());
最后,可以用 curl 来进行测试,证明我们的服务器的确已经正常工作了:
$ curl -d "text=I was do book a tickt last night" "http://localhost:8080/demo"
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说起