Development of Data Solr search engine based on SpringBoot
About Apache Solr
Solr is an open source search server based on Lucene Java, which is easy to add to Web applications. Solr provides layer search (i.e., statistics), hit and eye-catching display, and supports multiple output formats (including XML/XSLT and JSON). It is easy to install and configure, and comes with an HTTP based management interface. You can use Solr's excellent basic search function, or you can extend it to meet the needs of the enterprise. Solr features include:
- Advanced full text search capabilities
- Optimized for high-throughput network traffic
- Standards based on open interfaces (XML and HTTP)
- Integrated HTML management interface
- Scalability - ability to effectively replicate to another Solr search server
- Use XML configuration for flexibility and adaptability
- Extensible plug-in system
- Supports English, German, China, Japan, France and many major languages
The relationship between Apache Solr and Lucene
Solr and Lucene do not compete against each other. On the contrary, Solr depends on Lucene, because the core technology of Solr is implemented by Apache Lucene. In short, Solr is the server of Lucene. It should be noted that Solr does not simply encapsulate Lucene. Most of the functions it provides are different from Lucene.
Apache Solr related directory description
Structure description of Solr package
- bin: solr related running script
- docs: relevant API reference documents, wiki materials, etc
- licenses: solr related certificates are stored
- contrib: jar package of solr related extension
- dist: store the JAR file, WAR file and the JAR file that Solr relies on after Solr build.
- example: is an installed Jetty middleware, including some sample data and Solr configuration information.
- example/etc: Jetty's configuration file.
- example/multicore: used to place multiple Solr home directories when Slor multicore is installed.
- example/solr: the home directory of Solr by default.
- example/example-DIH: example of database as index data source
- example/webapps: Solr's WAR file is deployed here.
- src: Solr related source code.
- src/java: the Java source of Slor.
- src/scripts: some Unix bash shell scripts that are useful when large products are released.
- src/solrj: the Java client of Solr.
- src/test: Solr's test source and test file.
- src/webapp: Solr web management interface. The Jsp files of the management interface are all placed under web/admin /. You can modify these files according to your needs.
Solr home directory structure description
- bin: it is recommended to put the cluster replication script in this directory.
- conf: place the configuration file.
- conf/schema.xml: the indexed schema contains the field type definition and its associated parsers.
- conf/solrconfig.xml: This is Solr's main configuration file.
- conf/xslt: contains many xslt files, which can convert the query results of Solr's XML to a specific format, such as Atom/RSS.
- Data: place index data generated by Lucene.
- lib: place optional JAR files, such as plug-ins for Slor extension, which will be loaded when Solr starts.
Chapter 1: build Apache Solr development environment
Preparation steps: Tomcat 8 and above, JDK7 and above, solr5.5.4
- Unzip the Solr package, and copy the folder webapp under solr-5.5.4 \ Solr \
- Copy all the jar packages of solr-5.5.4\server\lib\ext in the Solr package to the Tomcat\ webapps\solr\WEB-INF\lib directory
- Copy solr-5.5.4\ server\resources \log4j.properties from Solr package to Tomcat\ webapps\solr\WEB-INF directory
- Create a solr home directory (the user can decide according to the operating system), and copy all the files except bin in the solr compression package under the example directory D: \ solr home directory, as shown in the figure:
- Open web.xml under Tomcat/webapps/solr/WEB-INF and add the following configuration content (the content is commented out in the initial state):
<env-entry> <env-entry-name>solr/home</env-entry-name> <env-entry-value>D:/solr_home</env-entry-value> <env-entry-type>java.lang.String</env-entry-type> </env-entry> Change the content in < env entry value > to your Solr home path, here is D: / Solr? Home This configuration is mainly to establish the relationship between tomcat and solr. Its function is to let tomcat find the solr directory you have configured.
- Start tomcat and input the following URL from the address bar: http://localhost:8080/solr, the following interface will appear:
Chapter 2: Apache Solr imports data from MySQL database
-
Import solr's own data import package and put it into lib under Web inf of solr project in tomcat
Add the Lib package in the directory of collection1, and copy the package needed for data import to lib
Including mysql package -
Open solrconfig.xml in Solr? Home on disk and add the following code
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"> <lst name="defaults"> <str name="config">data-config.xml</str> </lst> </requestHandler>
-
Create a data-config.xml file in the same level directory, and add the following
<?xml version="1.0" encoding="UTF-8" ?> <dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/mydb" user="root" password="root" /> <document name="userinfo"> <entity name="userinfo" query="select id,name,address,birthday,age from userinfo "> <field column="ID" name="user_id" /> <field column="NAME" name="user_name" /> <field column="ADDRESS" name="user_address" /> <field column="BIRTHDAY" name="user_birthday" /> <field column="AGE" name="user_age" /> </entity> </document> </dataConfig>
Note:
Document: document representing search engine
Entity: indicates the corresponding entity class
Query: executed SQL query statement
field: the domain corresponding to search engine
Column: the column corresponding to the database
Name: domain name corresponding to search engine
-
Configure the following code under schema.xml in the same level directory, and configure the one-to-one correspondence between the fields and fields of the database.
<field name="user_id" type="int" indexed="true" stored="true"/> <field name="user_name" type="string" indexed="true" stored="true"/> <field name="user_address" type="string" indexed="true" stored="true"/> <field name="user_birthday" type="date" indexed="true" stored="true"/> <field name="user_age" type="int" indexed="true" stored="true"/>
Chapter 3: Apache Solr configures Chinese word breaker
1. The Chinese word breaker uses Lucene analysts smartcn as the word breaker of Apache Solr, and copies the jar package to webapps Solr under tomcat
In the lib of WEB-INF in the project.
2. Open the managed schema file of conf under the configured collection1 in the configured Solr? Home directory and add the following code
<!-- Add Chinese word breaker --> <dynamicField name="*_txt_cn" type="text_cn" indexed="true" stored="true"/> <fieldType name="text_cn" class="solr.TextField"> <analyzer class="org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer"/> </fieldType>
Start the console, enter http://localhost:8080/solr from the address bar, and the following interface will appear:
Chapter 4: using spring boot to build solr development environment
The project directory structure is as follows:
Step 1: configure the property file of SpringBoot
spring.data.solr.host=http://localhost:8081/solr spring.thymeleaf.cache=false spring.thymeleaf.encoding=utf-8 spring.thymeleaf.mode=HTML spring.thymeleaf.suffix=.html
Step 2: write the entity class corresponding to Apache Solr
package com.sudojava.springboot_solr.domain; import org.apache.solr.client.solrj.beans.Field; public class Product { @Field private String id; @Field private String price; @Field private String title; @Field private String pic_url; @Field private String selling_price; @Field private String sales_volume; @Field private String coupon_title; @Override public String toString() { return "Product{" + "id='" + id + '\'' + ", price='" + price + '\'' + ", title='" + title + '\'' + ", pic_url='" + pic_url + '\'' + ", selling_price='" + selling_price + '\'' + ", sales_volume='" + sales_volume + '\'' + ", coupon_title='" + coupon_title + '\'' + '}'; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPic_url() { return pic_url; } public void setPic_url(String pic_url) { this.pic_url = pic_url; } public String getSelling_price() { return selling_price; } public void setSelling_price(String selling_price) { this.selling_price = selling_price; } public String getSales_volume() { return sales_volume; } public void setSales_volume(String sales_volume) { this.sales_volume = sales_volume; } public String getCoupon_title() { return coupon_title; } public void setCoupon_title(String coupon_title) { this.coupon_title = coupon_title; } }
Step 3: write the Service and implementation class of the product query list
package com.sudojava.springboot_solr.service; import com.sudojava.springboot_solr.domain.Product; import java.util.List; public interface ProductService { public List<Product> searchProductByName(String title); }
package com.sudojava.springboot_solr.service; import com.sudojava.springboot_solr.common.StringTrim; import com.sudojava.springboot_solr.domain.Product; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Consumer; @Service public class ProductServiceImp implements ProductService { @Autowired private SolrClient client; @Override public List<Product> searchProductByName(String title) { SolrQuery query = new SolrQuery(); query.setQuery("title:" + title); query.set("df", "title");//Set the domain of the query query.setHighlight(true); //Set highlighted labels query.setHighlightSimplePre("<font color=\"red\">"); query.setHighlightSimplePost("</font>"); query.addHighlightField("title"); query.setHighlightFragsize(150);//Highlighted Title Length query.setHighlightSnippets(1);//To obtain the number of highlighted segments, the general search terms may be distributed in different positions in the article, and they are located in a certain length of //The statement is a fragment, which is 1 by default, but sometimes it needs to take out several more fragments according to business needs QueryResponse response; List<Product> list = new ArrayList<>(); try { response = client.query("collection1", query); Map<String, Map<String, List<String>>> highlighting = response.getHighlighting(); if (response.getStatus() == 0) { response.getResults().forEach(new Consumer<SolrDocument>() { @Override public void accept(SolrDocument entries) { Product product = new Product(); product.setId(StringTrim.trim(entries.get("id"))); product.setCoupon_title(StringTrim.trim(entries.get("coupon_title"))); product.setPic_url(StringTrim.trim(entries.get("pic_url"))); product.setPrice(StringTrim.trim(entries.get("price"))); product.setSales_volume(StringTrim.trim(entries.get("sales_volume"))); product.setSelling_price(StringTrim.trim(entries.get("selling_price"))); Map<String, List<String>> map = highlighting.get(entries.get("id")); List<String> result = map.get("title"); if (result != null && result.size() > 0) { product.setTitle(StringTrim.trim(result.get(0))); } else { product.setTitle(StringTrim.trim(entries.get("title"))); } list.add(product); } }); } } catch (SolrServerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return list; } }
Step 4: write the Controller class, Index initialization page and tool class for product retrieval
package com.sudojava.springboot_solr.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class IndexController { @RequestMapping(value = "/",method = RequestMethod.GET) public String index(){ return "/index"; } }
package com.sudojava.springboot_solr.controller; import com.sudojava.springboot_solr.domain.Product; import com.sudojava.springboot_solr.service.ProductService; 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 java.util.List; @Controller public class ProductSearchController { @Autowired private ProductService service; @RequestMapping(value = "/search", method = RequestMethod.POST) public String searchProduct(String title, Model model) { System.out.println("---title-->>"+title); List<Product> list = service.searchProductByName(title); System.out.println("----->>" + list); model.addAttribute("list", list); return "/index"; } }
package com.sudojava.springboot_solr.common; public class StringTrim { public static String trim(Object str) { if (null == str) { str = ""; } return str.toString(); } }
Step 5: write the query interface and display the data with the Thymeleaf template engine
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Solr Query product interface</title> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/> <!--Introduce CSS style--> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/> <style> .mainCSS { margin: 0 auto; width: 1050px; } * { padding: 0; margin: 5px; list-style: none; } html, body { width: 100%; } #wrap { width: 1050px; margin: 0 auto; } #wrap ul { width: 100%; background-color: lightgray; box-sizing: border-box; } #wrap li { width: 200px; float: left; border: 1px solid #000; box-sizing: border-box; } #wrap li img { width: 95%; } </style> </head> <body> <div class="mainCSS"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">Solr Query product interface</h3> </div> <div class="panel-body"> <form class="form-inline" method="post" action="/search" role="form"> <div class="form-group"> <label class="sr-only" for="name"></label> <input type="text" class="form-control" size="120" name="title" id="name" placeholder="Please enter the search content"/> </div> <button type="submit" class="btn btn-default">search Cable</button> </form> </div> </div> </div> <div id="wrap"> <ul th:each="pro:${list}"> <li> <img th:src="${pro.pic_url}" alt=""/> <h5></h5> <p> <strong>Introduction:</strong><span th:utext="${pro.title}"><span/> </p> <p style="text-decoration: line-through;color: red;"> <strong>Original price:</strong><span th:text="${pro.price}"></span> </p> <p><strong>Selling price:</strong><span th:text="${pro.selling_price}"></span> </p> <p><strong>Sales volume:</strong><span th:text="${pro.sales_volume}"></span> </p> </li> </ul> </div> </body> </html>
Chapter 5: using SolrClient to add, delete, and modify Solr's index library
This chapter is mainly about unit testing Solr's index library using MockMVC integrated unit testing.
The test steps are as follows:
Step 1: define the operation interface and implementation class for Solr
package com.sudojava.springboot_solr.service; import com.sudojava.springboot_solr.domain.Product; import java.util.List; public interface ProductService { public List<Product> searchProductByName(String title); public int addProduct(Product product); public int deleteProduct(String id); }
package com.sudojava.springboot_solr.service; import com.sudojava.springboot_solr.common.StringTrim; import com.sudojava.springboot_solr.domain.Product; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.UpdateResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Consumer; @Service public class ProductServiceImp implements ProductService { @Autowired private SolrClient client; @Override public int addProduct(Product product) { //The first way to add index SolrInputDocument document = new SolrInputDocument(); document.addField("id", product.getId()); document.addField("coupon_title", product.getCoupon_title()); document.addField("pic_url", product.getPic_url()); document.addField("price", product.getPrice()); document.addField("sales_volume", product.getSales_volume()); document.addField("selling_price", product.getSelling_price()); UpdateResponse response = null; try { response = client.add("collection1",document); if (response.getStatus()==0) { client.commit("collection1"); } } catch (SolrServerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return response.getStatus(); } @Override public int deleteProduct(String id) { UpdateResponse response = null; try { response = client.deleteById("collection1",id); if (response.getStatus()==0) { client.commit("collection1"); } } catch (SolrServerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return response.getStatus(); } @Override public List<Product> searchProductByName(String title) { SolrQuery query = new SolrQuery(); query.setQuery("title:" + title); query.set("df", "title");//Set the domain of the query query.setHighlight(true); //Set highlighted labels query.setHighlightSimplePre("<font color=\"red\">"); query.setHighlightSimplePost("</font>"); query.addHighlightField("title"); query.setHighlightFragsize(150);//Highlighted Title Length query.setHighlightSnippets(1);//To obtain the number of highlighted segments, the general search terms may be distributed in different positions in the article, and they are located in a certain length of //The statement is a fragment, which is 1 by default, but sometimes it needs to take out several more fragments according to business needs QueryResponse response; List<Product> list = new ArrayList<>(); try { response = client.query("collection1", query); Map<String, Map<String, List<String>>> highlighting = response.getHighlighting(); if (response.getStatus() == 0) { response.getResults().forEach(new Consumer<SolrDocument>() { @Override public void accept(SolrDocument entries) { Product product = new Product(); product.setId(StringTrim.trim(entries.get("id"))); product.setCoupon_title(StringTrim.trim(entries.get("coupon_title"))); product.setPic_url(StringTrim.trim(entries.get("pic_url"))); product.setPrice(StringTrim.trim(entries.get("price"))); product.setSales_volume(StringTrim.trim(entries.get("sales_volume"))); product.setSelling_price(StringTrim.trim(entries.get("selling_price"))); Map<String, List<String>> map = highlighting.get(entries.get("id")); List<String> result = map.get("title"); if (result != null && result.size() > 0) { product.setTitle(StringTrim.trim(result.get(0))); } else { product.setTitle(StringTrim.trim(entries.get("title"))); } list.add(product); } }); } } catch (SolrServerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return list; } }
Solr also supports the insertion of indexed entity classes
@Override public int addProduct(Product product) { //The first way to add index // SolrInputDocument document = new SolrInputDocument(); // document.addField("id", product.getId()); // document.addField("coupon_title", product.getCoupon_title()); // document.addField("pic_url", product.getPic_url()); // document.addField("price", product.getPrice()); // document.addField("sales_volume", product.getSales_volume()); // document.addField("selling_price", product.getSelling_price()); UpdateResponse response = null; try { response = client.addBean("collection1",product); if (response.getStatus()==0) { client.commit("collection1"); } } catch (SolrServerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return response.getStatus(); }
Step 3: create added and deleted Controller controller
package com.sudojava.springboot_solr.controller; import com.sudojava.springboot_solr.domain.Product; import com.sudojava.springboot_solr.service.ProductService; 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 org.springframework.web.servlet.ModelAndView; import java.util.List; @Controller public class ProductSearchController { @Autowired private ProductService service; @RequestMapping(value = "/search", method = RequestMethod.POST) public ModelAndView searchProduct(String title) { System.out.println("---title-->>" + title); ModelAndView modelAndView = new ModelAndView(); List<Product> list = service.searchProductByName(title); modelAndView.addObject("list", list); modelAndView.setViewName("/index"); return modelAndView; } @RequestMapping(value = "/add", method = RequestMethod.POST) public String addProduct(Product product, Model model) { int flag = service.addProduct(product); System.out.println("-------->>"+flag); model.addAttribute("flag", "addProduct is success!!!" + flag); return "/index"; } @RequestMapping(value = "/delete", method = RequestMethod.POST) public String deleteProduct(String id, Model model) { int flag = service.deleteProduct(id); System.out.println("-------->>"+flag); model.addAttribute("flag", "deleteProduct is success!!!" + flag); return "/index"; } }
Step 4: create unit test class for test operation
package com.sudojava.springboot_solr; import com.sudojava.springboot_solr.common.StringTrim; import com.sudojava.springboot_solr.domain.Product; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.context.WebApplicationContext; import java.io.IOException; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @SpringBootTest public class SpringbootSolrApplicationTests { private MockMvc mockMvc; @Autowired private WebApplicationContext context; @Before public void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } @Test public void searchProduct() throws Exception{ mockMvc.perform(MockMvcRequestBuilders.post("/search") .param("title","Women's wear") ) .andDo(MockMvcResultHandlers.print()); } @Test public void deleteProduct() throws Exception{ mockMvc.perform(MockMvcRequestBuilders.post("/delete") .param("id","10010234") ) .andDo(MockMvcResultHandlers.print()); } @Test public void add() throws Exception { Product product = new Product(); product.setId("10010234"); product.setTitle("Clothes are on sale"); product.setSelling_price("1000"); product.setSales_volume("200"); product.setPrice("100"); product.setCoupon_title("Very good. www"); product.setPic_url("http://img1.tbcdn.cn/tfscom/i1/TB1qBvJOXXXXXcwapXXXXXXXXXX_!!0-item_pic.jpg_450x10000.jpg"); // LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>(); // map.add("id", product.getId()); // map.add("coupon_title", product.getCoupon_title()); // map.add("pic_url", product.getPic_url()); // map.add("price", product.getPrice()); // map.add("sales_volume", product.getSales_volume()); // map.add("selling_price", product.getSelling_price()); mockMvc.perform(MockMvcRequestBuilders.post("/add"). param("id", product.getId()). param("coupon_title", product.getCoupon_title()). param("pic_url", product.getPic_url()). param("price", product.getPrice()). param("sales_volume", product.getSales_volume()). param("selling_price", product.getSelling_price()) ) .andDo(MockMvcResultHandlers.print()); } }
Chapter 6: Solr data query based on SpringBoot JPA
This chapter mainly introduces the JPA specification of Solr query in SpringBoot. Spring data provided by spring family is applicable to relational database and nosql database
For example, spring data JPA, spring data Hadoop, spring data mongodb, Spring Data Solr, etc.
Their common feature is to provide us with framework code. spring Data can automatically create the implementation class and custom query of entity dao without us defining it, which simplifies the operation of dao layer.
It is worth noting that if you use the Spring Data Solr operation, you must add a label to the entity class corresponding to Solr
import org.apache.solr.client.solrj.beans.Field; import org.springframework.data.solr.core.mapping.SolrDocument; @SolrDocument(solrCoreName = "collection1") public class Product { .......Ellipsis code.... }
Step 1: declare an interface to inherit the solrcudrepository interface
package com.sudojava.springboot_solr.repository; import com.sudojava.springboot_solr.domain.Product; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.solr.repository.SolrCrudRepository; public interface ProductRepository extends SolrCrudRepository<Product,String> { Page<Product> findByTitle(String title, Pageable pageable); }
Step 2: declare the corresponding JPA Service, ServiceImp, and Controller classes respectively
package com.sudojava.springboot_solr.jpa; import com.sudojava.springboot_solr.domain.Product; import org.springframework.data.domain.Page; public interface ProductJPAService { Page<Product> findByTitle(String title); public void addProduct(Product product); public void deleteProductByID(String id); }
package com.sudojava.springboot_solr.jpa; import com.sudojava.springboot_solr.domain.Product; import com.sudojava.springboot_solr.repository.ProductRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; @Service public class ProductJPAServiceImp implements ProductJPAService { @Autowired private ProductRepository repository; @Override public Page<Product> findByTitle(String title) { return repository.findByTitle(title, PageRequest.of(1,6)); } @Override public void addProduct(Product product) { repository.save(product); } @Override public void deleteProductByID(String id) { repository.deleteById(id); } }
package com.sudojava.springboot_solr.jpa; import com.sudojava.springboot_solr.domain.Product; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class ProductJPASearchController { @Autowired private ProductJPAService service; //Do paging @RequestMapping(value = "/jpa/search", method = RequestMethod.POST) public String search(String title, Model model) { Page<Product> page = service.findByTitle(title); model.addAttribute("products", page.getContent()); model.addAttribute("page", page); return "/index"; } @RequestMapping(value = "/jpa/add", method = RequestMethod.POST) public String add(Product product) { service.addProduct(product); return "/index"; } @RequestMapping(value = "/jpa/delete", method = RequestMethod.POST) public String delete(String id) { service.deleteProductByID(id); return "/index"; } }
Step 4: declare the unit test class
package com.sudojava.springboot_solr; import com.sudojava.springboot_solr.common.StringTrim; import com.sudojava.springboot_solr.domain.Product; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.context.WebApplicationContext; import java.io.IOException; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @SpringBootTest public class SpringbootSolrApplicationTests { private MockMvc mockMvc; @Autowired private WebApplicationContext context; @Before public void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } @Test public void searchProduct() throws Exception{ mockMvc.perform(MockMvcRequestBuilders.post("/jpa/search") .param("title","Women's wear") ) .andDo(MockMvcResultHandlers.print()); } @Test public void deleteProduct() throws Exception{ mockMvc.perform(MockMvcRequestBuilders.post("/delete") .param("id","10010234") ) .andDo(MockMvcResultHandlers.print()); } @Test public void add() throws Exception { Product product = new Product(); product.setId("10010234"); product.setTitle("Clothes are on sale"); product.setSelling_price("1000"); product.setSales_volume("200"); product.setPrice("100"); product.setCoupon_title("Very good. www"); product.setPic_url("http://img1.tbcdn.cn/tfscom/i1/TB1qBvJOXXXXXcwapXXXXXXXXXX_!!0-item_pic.jpg_450x10000.jpg"); // LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>(); // map.add("id", product.getId()); // map.add("coupon_title", product.getCoupon_title()); // map.add("pic_url", product.getPic_url()); // map.add("price", product.getPrice()); // map.add("sales_volume", product.getSales_volume()); // map.add("selling_price", product.getSelling_price()); mockMvc.perform(MockMvcRequestBuilders.post("/jpa/add"). param("id", product.getId()). param("coupon_title", product.getCoupon_title()). param("pic_url", product.getPic_url()). param("price", product.getPrice()). param("sales_volume", product.getSales_volume()). param("selling_price", product.getSelling_price()) ) .andDo(MockMvcResultHandlers.print()); } }