Lucene - это библиотека для реализации высокоскоростного полнотекстового поиска с открытым исходным кодом, написанная полностью на Java. Вопреки некоторым ожиданиям и заблуждениям Lucene не является законченным приложением - это просто библиотека, которую можно (нужно) использовать для реализации поиска в приложениях, а каких именно - web, desktop и т.д. не имеет значения. Проект активно развивается и поддерживается, кроме того, есть хорошие порты на другие языки программирования - а это уже о многом говорит в пользу проекта вцелом.
В этом цикле статей мы поэтапно рассмотрим основные возможности Lucene на примере реализации законченного web-приложения - системы поиска для реального и уже давно существующего сайта. Поскольку, как уже было упомянуто ранее, Lucene написана на Java, то наше приложение будет тоже написано на Java и реализовано в виде Servlet, хостится всё это добро будет на Jetty.
В проекте будет несколько подпроектов, поэтому предлагаю сразу воспользоваться мульти-модульностью Maven, где в корне намечается общая зависимость от Lucene. Начнём с сервера:
~$ cd lucene-tutorial/
~$ tree
.
├── pom.xml
└── server
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── server
│ │ └── SearchServlet.java
│ └── webapp
│ └── WEB-INF
│ └── web.xml
└── static.war
7 directories, 5 files
pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tutorial.lucene</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>6.0.0</version>
</dependency>
</dependencies>
<modules>
<module>server</module>
</modules>
</project>
server/pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>tutorial.lucene</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>server</artifactId>
<packaging>war</packaging>
<name>Lucene Tutorial Server</name>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.8.v20160314</version>
<configuration>
<webApp>
<contextPath>/search</contextPath>
</webApp>
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.maven.plugin.JettyWebAppContext">
<war>${project.basedir}/static.war</war> -->
<contextPath>/</contextPath>
</contextHandler>
</contextHandlers>
</configuration>
</plugin>
</plugins>
</build>
</project>
Имеется готовый статический сайт, для которого мы будем разрабатывать поиск в виде архива static.war. Мы возьмём некогда топовый в гугле сайт по ключевым словам Семь Чудес Света. Получить контент сайта можно с помощью Linux'овой утититы wget:
wget -r http://www.turismy.com/
Динамический контент будет генерироваться сервлетом, который будет предоставлять возможность поиска по сайту, разрабатываться он будет поэтапно. Для Servlet явно указан маршрут - /search в то время как статический контент в находится в корне сайта. Для начала реализуем очень простой сервлет, который отдаст какую-то элементарную информацию из Lucene:
server/src/main/webapp/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:web="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.4">
<servlet>
<servlet-name>search</servlet-name>
<servlet-class>server.SearchServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>search</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
server/src/main/java/server/SearchServlet.java
package server;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.lucene.util.Version;
public class SearchServlet extends HttpServlet {
@Override
public void doGet(final HttpServletRequest req, final HttpServletResponse res)
throws ServletException, IOException {
final PrintWriter out = res.getWriter();
final String luceneVersions = Arrays.toString(Version.class.getFields());
out.println("<HTML>");
out.println("<BODY>");
out.println(luceneVersions.replace(",", "<br />"));
out.println("</BODY>");
out.println("</HTML>");
out.close();
}
}
Сборка и первый запуск
~$ apt install maven default-jdk
~$ mvn -v
Apache Maven 3.3.9
Java version: 1.8.0_03-Ubuntu, vendor: Oracle Corporation
~$ sudo netstat -tulpn | grep -q 8080 && echo 'port 8080 is busy !'
~$ mvn clean -pl server/ jetty:run
Теперь у нас в системе есть подопытный сайт http://localhost:8080/ с которым мы и будем работать далее, где первым делом проиндексируем содержимое нашего сайта.