Здесь мы создадим пример веб-приложения Spring Boot с механизмом шаблонов Hibernate Search Thymeleaf и развернем его как WAR для Wildfly 10.1.
Используемые технологии:
, Spring Boot 1.5.6.RELEASE
, Java 8
, Hibernate Search 5.6.1.Final
, Встроенный Tomcat, Wildfly 8.1 Final
1. Структура проекта
Стандартная структура проекта Maven
Изображение://wp-content/uploads/2017/09/spring-boot-hibernate-search-example.png[изображение]
1. Зависимости проекта
pom.xml
<?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>com.techfou</groupId> <artifactId>spring-boot-web-wildfly-search</artifactId> <version>0.0.1</version> <packaging>war</packaging> <name>techfou-wildfly-spring-boot</name> <description>Spring Boot Web Hibernate Search Example</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <logback.version>1.1.9</logback.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- Comment out if deploy as WAR file <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-search-engine --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-engine</artifactId> <version>5.6.1.Final</version> <exclusions> <exclusion> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-search-orm --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId> <version>5.6.1.Final</version> <exclusions> <exclusion> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.3.0.Final</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.9</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layout>WAR</layout> <executable>true</executable> <mainClass>com.mkyong.WildflySpringBootApplication</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
2. Модель
Для этого примера приложения мы создаем веб-сайт, который позволяет вам искать редкие бейсбольные карточки. Итак, мы делаем нашу модель бейсбольной карточкой и комментируем поля для поиска.
BaseballCard.java
package com.mkyong.model; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Indexed; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Indexed @Entity public class BaseballCard { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Field private String name; @Field private String rarityLevel; @Field private int year; //getters n setters }
3. Хранилище
Здесь у нас есть Spring Data
CrudRepository
для модели BaseballCard, которая позволит нам выполнять необходимые функции создания и чтения.
BaseballCardRepository.java
package com.mkyong.dao; import org.springframework.data.repository.CrudRepository; import com.mkyong.model.BaseballCard; public interface BaseballCardRepository extends CrudRepository<BaseballCard,Long> { }
4. Поиск в спящем режиме
HibernateSearchService.java
package com.mkyong.service; import com.mkyong.model.BaseballCard; import org.apache.lucene.search.Query; import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.Search; import org.hibernate.search.query.dsl.QueryBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import java.util.List; @Service public class HibernateSearchService { @Autowired private final EntityManager centityManager; @Autowired public HibernateSearchService(EntityManager entityManager) { super(); this.centityManager = entityManager; } public void initializeHibernateSearch() { try { FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(centityManager); fullTextEntityManager.createIndexer().startAndWait(); } catch (InterruptedException e) { e.printStackTrace(); } } @Transactional public List<BaseballCard> fuzzySearch(String searchTerm) { FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(centityManager); QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(BaseballCard.class).get(); Query luceneQuery = qb.keyword().fuzzy().withEditDistanceUpTo(1).withPrefixLength(1).onFields("name") .matching(searchTerm).createQuery(); javax.persistence.Query jpaQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, BaseballCard.class); //execute search List<BaseballCard> BaseballCardList = null; try { BaseballCardList = jpaQuery.getResultList(); } catch (NoResultException nre) { ;//do nothing } return BaseballCardList; } }
Это настраивает HibernateSearchService для доступности.
HibernateSearchConfiguration.java
package com.mkyong; import javax.persistence.EntityManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.mkyong.service.HibernateSearchService; @EnableAutoConfiguration @Configuration public class HibernateSearchConfiguration { @Autowired private EntityManager bentityManager; @Bean HibernateSearchService hibernateSearchService() { HibernateSearchService hibernateSearchService = new HibernateSearchService(bentityManager); hibernateSearchService.initializeHibernateSearch(); return hibernateSearchService; } }
5. Сервис для модели
Это простой сервис, который добавляет три карты в хранилище для нашего примера. Для демонстрации принципов программирования SOLID существует отдельный интерфейс сервиса.
CardService.java
package com.mkyong.service; public interface CardService { void addCards(); }
CardServiceImpl.java
package com.mkyong.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.mkyong.dao.BaseballCardRepository; import com.mkyong.model.BaseballCard; @Service public class CardServiceImpl implements CardService { @Autowired BaseballCardRepository cardrepository; BaseballCard TedWilliams = new BaseballCard(); BaseballCard BobGibson = new BaseballCard(); BaseballCard HonusWagner = new BaseballCard(); public void addCards() { TedWilliams.setName("Ted Williams"); TedWilliams.setYear(1954); TedWilliams.setRarityLevel("Very Rare"); cardrepository.save(TedWilliams); BobGibson.setName("Bob Gibson"); BobGibson.setYear(1959); BobGibson.setRarityLevel("Very Rare"); cardrepository.save(BobGibson); HonusWagner.setName("Honus Wagner"); HonusWagner.setYear(1909); HonusWagner.setRarityLevel("Rarest"); cardrepository.save(HonusWagner); System.out.println("Cards have been added : " + cardrepository.findAll()); } }
6. Контроллер
Контроллер отвечает за подключение внутренних служб к нашему шаблону Thymeleaf.
CardController.java
package com.mkyong.controller; import com.mkyong.model.BaseballCard; import com.mkyong.service.CardService; import com.mkyong.service.HibernateSearchService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import java.util.List; @Controller public class CardController { @Autowired private HibernateSearchService searchservice; @Autowired private CardService cardservice; @RequestMapping(value = "/", method = RequestMethod.GET) public String search(@RequestParam(value = "search", required = false) String q, Model model) { List<BaseballCard> searchResults = null; try { cardservice.addCards(); searchResults = searchservice.fuzzySearch(q); } catch (Exception ex) { //here you should handle unexpected errors //... //throw ex; } model.addAttribute("search", searchResults); return "index"; } }
7. Конфигурация
Теперь нам нужно настроить поиск Thymeleaf и Hibernate.
application.properties
#================================== # = Thymeleaf configurations #================================== spring.thymeleaf.check-template-location=true spring.thymeleaf.prefix=classpath:/templates/spring.thymeleaf.suffix=.html spring.thymeleaf.content-type=text/html spring.thymeleaf.cache=false server.contextPath=/#=================================== #= # Specify the Lucene Directory spring.jpa.properties.hibernate.search.default.directory__provider = filesystem # Using the filesystem DirectoryProvider you also have to specify the default # base directory for all indexes spring.jpa.properties.hibernate.search.default.indexBase = indexpath
8. Шаблон Thymeleaf
Для нашего шаблона Thymeleaf у нас есть две цели: позволить пользователю искать и отображать результаты поиска после завершения поиска.
К счастью, Thymeleaf имеет условные операторы, которые позволяют нам отображать результаты, если пользовательский поиск возвращает элементы.
index.html
<!DOCTYPE html> <html lang="en"> <head> <!-- META SECTION --> <title>Mkyong Wildfly Example</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <!-- END META SECTION --> <!-- BEGIN STYLE --> <style> table, th, td { border: 1px solid black; padding: 1px; } </style> <!-- END STYLE --> </head> <body> <form action="#" th:action="@{/}" th:object="${search}"> <label for="search__input">Search:</label> <input name="search" id="search"> </input> <div th:if="${not #lists.isEmpty(search)}"> <h2>Search Results</h2> <table> <thead> <tr> <th>ID</th> <th>name</th> <th>rarity level</th> <th>year</th> </tr> </thead> <tbody> <tr th:each="search : ${search}"> <td th:text="${search.id}">Text ...</td> <td th:text="${search.name}">Text ...</td> <td th:text="${search.rarityLevel}">Text ...</td> <td th:text="${search.year}">Text...</td> </tr> </tbody> </table> </div> </form> </body> </html>
9. SpringBootApplication
WildflySpringBootApplication.java
package com.mkyong; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class WildflySpringBootApplication { public static void main(String[]args) { SpringApplication.run(WildflySpringBootApplication.class, args); } }
10. Демо
Запустите Spring Boot Application со встроенным контейнером Tomcat по умолчанию.
$ mvn spring-boot:run
Доступ http://localhost : 8080/
Изображение://wp-content/uploads/2017/09/spring-boot-hibernate-search-demo1.png[изображение]
Я выполнил поиск "Ted", и результаты отображаются в таблице, http://localhost : 8080/? Search = ted
Изображение://wp-content/uploads/2017/09/spring-boot-hibernate-search-demo2.png[изображение]
11. Развернуть WAR-файл в Wildfly
Wildfly - это сервер приложений с открытым исходным кодом JBoss. Wildfly можно загрузить с их% E2% 80% 9 официальный сайт
11.1 Исключить встроенный контейнер Tomcat.
pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency>
11.2 Расширяет
SpringBootServletInitializer
WildflySpringBootApplication.java
package com.mkyong; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; @SpringBootApplication public class WildflySpringBootApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(WildflySpringBootApplication.class); } public static void main(String[]args) { SpringApplication.run(WildflySpringBootApplication.class, args); } }
11.3. Постройте Maven и скопируйте файл WAR в JBoss Wildfly и запустите его
Терминал
$ mvn package
11.4 Соображения для Wildfly 10
Для Wildfly 10 нам нужно внести дополнительные изменения из-за технологий, которые поставляются вместе с ней. В нашем случае мы используем Hibernate Search, который упакован в Wildfly 10.
Для пользователей Wildfly 10 необходимо создать файл
persistence.xml
и ввести:
persistence.xml
wildfly.jpa.hibernate.search.module = none
Готово.
Скачать исходный код
Загрузите его - ссылка://wp-content/uploads/2017/09/spring-boot-hibernate-search-example.zip[spring-boot-hibernate-search-example.zip](24 КБ)
Рекомендации
Поиск 5.6 Документация], https://spring.io/blog/2014/03/07/deploying-spring-boot-applications [Deploying
Spring Boot Applications], http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html [Thymeleaf
+ Весна], ссылка://spring-boot/spring-boot-deploy-war-file-to-tomcat/[Spring Boot
-
Развернуть WAR-файл в Tomcat]
ссылка://тег/hibernate-поиск/[поиск hibernate]ссылка://tag/spring-boot/[spring boot]ссылка://tag/wildfly/[wildfly]