refactor: 移除 RabbitMQ 和 Elasticsearch 相关功能

This commit is contained in:
xiongxiaoyang 2023-04-14 10:10:09 +08:00
parent 68b3458c30
commit 282bc7b707
11 changed files with 285 additions and 863 deletions

View File

@ -27,24 +27,6 @@
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>${jest.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<!--aliyunOSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
@ -70,14 +52,6 @@
</dependency>
<!--引入redisson分布式锁-->
<!-- <dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
</dependency>-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>

View File

@ -7,18 +7,16 @@ import com.java2nb.novel.entity.BookCategory;
import com.java2nb.novel.entity.BookComment;
import com.java2nb.novel.entity.BookIndex;
import com.java2nb.novel.service.BookContentService;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.vo.BookCommentVO;
import com.java2nb.novel.vo.BookSettingVO;
import com.java2nb.novel.vo.BookSpVO;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.vo.BookVO;
import io.github.xxyopen.model.page.PageBean;
import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder;
import io.github.xxyopen.model.resp.RestResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@ -37,14 +35,8 @@ public class BookController extends BaseController {
private final BookService bookService;
private final RabbitTemplate rabbitTemplate;
private final Map<String, BookContentService> bookContentServiceMap;
@Value("${spring.rabbitmq.enable}")
private Integer enableMq;
/**
* 查询首页小说设置列表数据
*/
@ -89,7 +81,8 @@ public class BookController extends BaseController {
* 分页搜索
*/
@GetMapping("searchByPage")
public RestResult<?> searchByPage(BookSpVO bookSP, @RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "20") int pageSize) {
public RestResult<?> searchByPage(BookSpVO bookSP, @RequestParam(value = "curr", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "20") int pageSize) {
return RestResult.ok(bookService.searchByPage(bookSP, page, pageSize));
}
@ -106,7 +99,8 @@ public class BookController extends BaseController {
* 查询小说排行信息
*/
@GetMapping("listRank")
public RestResult<List<Book>> listRank(@RequestParam(value = "type", defaultValue = "0") Byte type, @RequestParam(value = "limit", defaultValue = "30") Integer limit) {
public RestResult<List<Book>> listRank(@RequestParam(value = "type", defaultValue = "0") Byte type,
@RequestParam(value = "limit", defaultValue = "30") Integer limit) {
return RestResult.ok(bookService.listRank(type, limit));
}
@ -115,11 +109,7 @@ public class BookController extends BaseController {
*/
@PostMapping("addVisitCount")
public RestResult<Void> addVisitCount(Long bookId) {
if (enableMq == 1) {
rabbitTemplate.convertAndSend("ADD-BOOK-VISIT-EXCHANGE", null, bookId);
} else {
bookService.addVisitCount(bookId, 1);
}
return RestResult.ok();
}
@ -131,7 +121,8 @@ public class BookController extends BaseController {
Map<String, Object> data = new HashMap<>(2);
data.put("bookIndexCount", bookService.queryIndexCount(bookId));
BookIndex bookIndex = bookService.queryBookIndex(lastBookIndexId);
String lastBookContent = bookContentServiceMap.get(bookIndex.getStorageType()).queryBookContent(bookId,lastBookIndexId).getContent();
String lastBookContent = bookContentServiceMap.get(bookIndex.getStorageType())
.queryBookContent(bookId, lastBookIndexId).getContent();
if (lastBookContent.length() > 42) {
lastBookContent = lastBookContent.substring(0, 42);
}
@ -152,7 +143,9 @@ public class BookController extends BaseController {
* 分页查询书籍评论列表
*/
@GetMapping("listCommentByPage")
public RestResult<PageBean<BookCommentVO>> listCommentByPage(@RequestParam("bookId") Long bookId, @RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize) {
public RestResult<PageBean<BookCommentVO>> listCommentByPage(@RequestParam("bookId") Long bookId,
@RequestParam(value = "curr", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "5") int pageSize) {
return RestResult.ok(bookService.listCommentByPage(null, bookId, page, pageSize));
}
@ -181,7 +174,10 @@ public class BookController extends BaseController {
* 目录页
*/
@GetMapping("/queryIndexList")
public RestResult<PageBean<BookIndex>> indexList(Long bookId, @RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize, @RequestParam(value = "orderBy", defaultValue = "index_num desc") String orderBy) {
public RestResult<PageBean<BookIndex>> indexList(Long bookId,
@RequestParam(value = "curr", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "5") int pageSize,
@RequestParam(value = "orderBy", defaultValue = "index_num desc") String orderBy) {
return RestResult.ok(PageBuilder.build(bookService.queryIndexList(bookId, orderBy, page, pageSize)));
}

View File

@ -1,6 +1,5 @@
package com.java2nb.novel.page;
package com.java2nb.novel.controller;
import com.java2nb.novel.controller.BaseController;
import com.java2nb.novel.core.bean.UserDetails;
import com.java2nb.novel.core.utils.ThreadLocalUtil;
import com.java2nb.novel.entity.*;
@ -12,15 +11,12 @@ import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@ -34,9 +30,6 @@ import java.util.concurrent.ThreadPoolExecutor;
@Controller
public class PageController extends BaseController {
@Value("${content.save.path}")
private String fileSavePath;
private final BookService bookService;
private final NewsService newsService;
@ -55,7 +48,8 @@ public class PageController extends BaseController {
}
@RequestMapping("{module}/{url}.html")
public String module2(@PathVariable("module") String module, @PathVariable("url") String url, HttpServletRequest request) {
public String module2(@PathVariable("module") String module, @PathVariable("url") String url,
HttpServletRequest request) {
if (request.getRequestURI().startsWith("/author")) {
//访问作者专区
@ -75,7 +69,8 @@ public class PageController extends BaseController {
}
@RequestMapping("{module}/{classify}/{url}.html")
public String module3(@PathVariable("module") String module, @PathVariable("classify") String classify, @PathVariable("url") String url) {
public String module3(@PathVariable("module") String module, @PathVariable("classify") String classify,
@PathVariable("url") String url) {
return module + "/" + classify + "/" + url;
}
@ -86,9 +81,11 @@ public class PageController extends BaseController {
@RequestMapping(path = {"/", "/index", "/index.html"})
public String index(Model model) {
//加载小说首页小说基本信息线程
CompletableFuture<Map<Byte, List<BookSettingVO>>> bookCompletableFuture = CompletableFuture.supplyAsync(bookService::listBookSettingVO, threadPoolExecutor);
CompletableFuture<Map<Byte, List<BookSettingVO>>> bookCompletableFuture = CompletableFuture.supplyAsync(
bookService::listBookSettingVO, threadPoolExecutor);
//加载首页新闻线程
CompletableFuture<List<News>> newsCompletableFuture = CompletableFuture.supplyAsync(newsService::listIndexNews, threadPoolExecutor);
CompletableFuture<List<News>> newsCompletableFuture = CompletableFuture.supplyAsync(newsService::listIndexNews,
threadPoolExecutor);
model.addAttribute("bookMap", bookCompletableFuture.get());
model.addAttribute("newsList", newsCompletableFuture.get());
return ThreadLocalUtil.getTemplateDir() + "index";
@ -126,7 +123,8 @@ public class PageController extends BaseController {
return book;
}, threadPoolExecutor);
//加载小说评论列表线程
CompletableFuture<PageBean<BookCommentVO>> bookCommentPageBeanCompletableFuture = CompletableFuture.supplyAsync(() -> {
CompletableFuture<PageBean<BookCommentVO>> bookCommentPageBeanCompletableFuture = CompletableFuture.supplyAsync(
() -> {
PageBean<BookCommentVO> bookCommentVOPageBean = bookService.listCommentByPage(null, bookId, 1, 5);
log.debug("加载小说评论列表线程结束");
return bookCommentVOPageBean;
@ -148,7 +146,6 @@ public class PageController extends BaseController {
return books;
}, threadPoolExecutor);
model.addAttribute("book", bookCompletableFuture.get());
model.addAttribute("firstBookIndexId", firstBookIndexIdCompletableFuture.get());
model.addAttribute("recBooks", recBookCompletableFuture.get());
@ -176,7 +173,8 @@ public class PageController extends BaseController {
*/
@SneakyThrows
@RequestMapping("/book/{bookId}/{bookIndexId}.html")
public String bookContent(@PathVariable("bookId") Long bookId, @PathVariable("bookIndexId") Long bookIndexId, HttpServletRequest request, Model model) {
public String bookContent(@PathVariable("bookId") Long bookId, @PathVariable("bookIndexId") Long bookIndexId,
HttpServletRequest request, Model model) {
//加载小说基本信息线程
CompletableFuture<Book> bookCompletableFuture = CompletableFuture.supplyAsync(() -> {
//查询书籍
@ -194,7 +192,8 @@ public class PageController extends BaseController {
}, threadPoolExecutor);
//加载小说上一章节信息线程该线程在加载小说章节信息线程执行完毕后才执行
CompletableFuture<Long> preBookIndexIdCompletableFuture = bookIndexCompletableFuture.thenApplyAsync((bookIndex) -> {
CompletableFuture<Long> preBookIndexIdCompletableFuture = bookIndexCompletableFuture.thenApplyAsync(
(bookIndex) -> {
//查询上一章节目录ID
Long preBookIndexId = bookService.queryPreBookIndexId(bookId, bookIndex.getIndexNum());
log.debug("加载小说上一章节信息线程结束");
@ -202,7 +201,8 @@ public class PageController extends BaseController {
}, threadPoolExecutor);
//加载小说下一章节信息线程该线程在加载小说章节信息线程执行完毕后才执行
CompletableFuture<Long> nextBookIndexIdCompletableFuture = bookIndexCompletableFuture.thenApplyAsync((bookIndex) -> {
CompletableFuture<Long> nextBookIndexIdCompletableFuture = bookIndexCompletableFuture.thenApplyAsync(
(bookIndex) -> {
//查询下一章目录ID
Long nextBookIndexId = bookService.queryNextBookIndexId(bookId, bookIndex.getIndexNum());
log.debug("加载小说下一章节信息线程结束");
@ -210,14 +210,15 @@ public class PageController extends BaseController {
}, threadPoolExecutor);
//加载小说内容信息线程该线程在加载小说章节信息线程执行完毕后才执行
CompletableFuture<BookContent> bookContentCompletableFuture = bookIndexCompletableFuture.thenApplyAsync((bookIndex) -> {
CompletableFuture<BookContent> bookContentCompletableFuture = bookIndexCompletableFuture.thenApplyAsync(
(bookIndex) -> {
//查询内容
BookContent bookContent = bookContentServiceMap.get(bookIndex.getStorageType()).queryBookContent(bookId, bookIndexId);
BookContent bookContent = bookContentServiceMap.get(bookIndex.getStorageType())
.queryBookContent(bookId, bookIndexId);
log.debug("加载小说内容信息线程结束");
return bookContent;
}, threadPoolExecutor);
//判断用户是否需要购买线程该线程在加载小说章节信息线程执行完毕后才执行
CompletableFuture<Boolean> needBuyCompletableFuture = bookIndexCompletableFuture.thenApplyAsync((bookIndex) -> {
//判断该目录是否收费
@ -241,7 +242,6 @@ public class PageController extends BaseController {
}, threadPoolExecutor);
model.addAttribute("book", bookCompletableFuture.get());
model.addAttribute("bookIndex", bookIndexCompletableFuture.get());
model.addAttribute("preBookIndexId", preBookIndexIdCompletableFuture.get());

View File

@ -1,41 +0,0 @@
package com.java2nb.novel.core.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* elasticsearch搜索引擎配置
* @author xiongxiaoyang
*/
@Configuration
@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "1")
public class EsConfig {
@Value("${spring.elasticsearch.jest.uris}")
private String esUris;
@Bean
public RestHighLevelClient esClient(){
String[] uris = esUris.split(",");
HttpHost[] hosts = new HttpHost[uris.length];
for(int i = 0 ; i < uris.length ; i++){
String uri = uris[i];
String scheme = uri.substring(0,uri.indexOf(":")).trim();
String hostname = uri.substring(uri.indexOf("://")+3,uri.lastIndexOf(":")).trim();
int port = Integer.parseInt(uri.substring(uri.lastIndexOf(":")+1).trim());
hosts[i] = new HttpHost(hostname,port,scheme);
}
return new RestHighLevelClient(
RestClient.builder(hosts));
}
}

View File

@ -1,59 +0,0 @@
package com.java2nb.novel.core.config;
import org.springframework.amqp.core.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 11797
*/
@Configuration
@ConditionalOnProperty(prefix = "spring.rabbitmq", name = "enable", havingValue = "1")
public class RabbitConfig {
/**
* 更新数据库队列
*/
@Bean
public Queue updateDbQueue() {
return new Queue("UPDATE-DB-QUEUE", true);
}
/**
* 更新数据库队列
*/
@Bean
public Queue updateEsQueue() {
return new Queue("UPDATE-ES-QUEUE", true);
}
/**
* 增加点击量交换机
*/
@Bean
public FanoutExchange addVisitExchange() {
return new FanoutExchange("ADD-BOOK-VISIT-EXCHANGE");
}
/**
* 更新搜索引擎队列绑定到增加点击量交换机中
*/
@Bean
public Binding updateEsBinding() {
return BindingBuilder.bind(updateEsQueue()).to(addVisitExchange());
}
/**
* 更新数据库绑定到增加点击量交换机中
*/
@Bean
public Binding updateDbBinding() {
return BindingBuilder.bind(updateDbQueue()).to(addVisitExchange());
}
}

View File

@ -1,107 +0,0 @@
package com.java2nb.novel.core.listener;
import com.java2nb.novel.core.cache.CacheKey;
import com.java2nb.novel.core.cache.CacheService;
import com.java2nb.novel.core.utils.Constants;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.service.SearchService;
import com.java2nb.novel.vo.EsBookVO;
import com.rabbitmq.client.Channel;
import io.searchbox.client.JestClient;
import io.searchbox.core.Index;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import java.text.SimpleDateFormat;
/**
* @author 11797
*/
@Component
@Slf4j
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "spring.rabbitmq", name = "enable", havingValue = "1")
public class BookVisitAddListener {
private final BookService bookService;
private final CacheService cacheService;
private final SearchService searchService;
// private final RedissonClient redissonClient;
/**
* 更新数据库
* 流量削峰每本小说累积10个点击更新一次
*/
@SneakyThrows
@RabbitListener(queues = {"UPDATE-DB-QUEUE"})
public void updateDb(Long bookId, Channel channel, Message message) {
log.debug("收到更新数据库消息:" + bookId);
Thread.sleep(1000 * 2);
//TODO 操作共享资源visitCount集群环境下有线程安全问题引入Redisson框架实现分布式锁
//RLock lock = redissonClient.getLock("visitCount");
//lock.lock();
//目前visitCount不重要数据可丢失暂不实现分布式锁
Integer visitCount = (Integer) cacheService.getObject(CacheKey.BOOK_ADD_VISIT_COUNT+bookId);
if(visitCount == null){
visitCount = 0 ;
}
cacheService.setObject(CacheKey.BOOK_ADD_VISIT_COUNT+bookId,++visitCount);
if(visitCount >= Constants.ADD_MAX_VISIT_COUNT) {
bookService.addVisitCount(bookId,visitCount);
cacheService.del(CacheKey.BOOK_ADD_VISIT_COUNT+bookId);
}
//TODO 操作共享资源visitCount集群环境下有线程安全问题引入Redisson框架实现分布式锁
//lock.unlock();
}
/**
* 更新搜索引擎
* 流量削峰每本小说1个小时更新一次
*/
@RabbitListener(queues = {"UPDATE-ES-QUEUE"})
public void updateEs(Long bookId, Channel channel, Message message) {
log.debug("收到更新搜索引擎消息:" + bookId);
if (cacheService.get(CacheKey.ES_IS_UPDATE_VISIT + bookId) == null) {
cacheService.set(CacheKey.ES_IS_UPDATE_VISIT + bookId, "1", 60 * 60);
try {
Thread.sleep(1000 * 5);
Book book = bookService.queryBookDetail(bookId);
searchService.importToEs(book);
}catch (Exception e){
cacheService.del(CacheKey.ES_IS_UPDATE_VISIT + bookId);
log.error("更新搜索引擎失败"+bookId);
}
}
}
}

View File

@ -1,77 +0,0 @@
package com.java2nb.novel.core.schedule;
import com.java2nb.novel.core.cache.CacheKey;
import com.java2nb.novel.core.cache.CacheService;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.service.SearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* 小说导入搜索引擎
*
* @author Administrator
*/
@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "1")
@Service
@RequiredArgsConstructor
@Slf4j
public class BookToEsSchedule {
private final BookService bookService;
private final CacheService cacheService;
private final SearchService searchService;
/**
* 1分钟导入一次
*/
@Scheduled(fixedRate = 1000 * 60)
public void saveToEs() {
//TODO 引入Redisson框架实现分布式锁
//可以重复更新只是效率可能略有降低所以暂不实现分布式锁
if (cacheService.get(CacheKey.ES_TRANS_LOCK) == null) {
cacheService.set(CacheKey.ES_TRANS_LOCK, "1", 60 * 20);
try {
//查询需要更新的小说
Date lastDate = (Date) cacheService.getObject(CacheKey.ES_LAST_UPDATE_TIME);
if (lastDate == null) {
lastDate = new SimpleDateFormat("yyyy-MM-dd").parse("2020-01-01");
}
List<Book> books = bookService.queryBookByUpdateTimeByPage(lastDate, 100);
for (Book book : books) {
searchService.importToEs(book);
lastDate = book.getUpdateTime();
Thread.sleep(5000);
}
cacheService.setObject(CacheKey.ES_LAST_UPDATE_TIME, lastDate);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
cacheService.del(CacheKey.ES_TRANS_LOCK);
}
}
}

View File

@ -1,27 +0,0 @@
package com.java2nb.novel.service;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.vo.BookSpVO;
import com.java2nb.novel.vo.EsBookVO;
/**
* @author 11797
*/
public interface SearchService {
/**
* 导入到es
* @param book 小说数据
*/
void importToEs(Book book);
/**
* 搜索
* @param params 搜索参数
* @param page 当前页码
* @param pageSize 每页大小
* @return 分页信息
*/
io.github.xxyopen.model.page.PageBean<EsBookVO> searchBook(BookSpVO params, int page, int pageSize);
}

View File

@ -6,7 +6,6 @@ import com.java2nb.novel.core.cache.CacheKey;
import com.java2nb.novel.core.cache.CacheService;
import com.java2nb.novel.core.config.BookPriceProperties;
import com.java2nb.novel.core.enums.ResponseStatus;
import io.github.xxyopen.web.util.BeanUtil;
import com.java2nb.novel.core.utils.Constants;
import com.java2nb.novel.core.utils.StringUtil;
import com.java2nb.novel.entity.Book;
@ -15,7 +14,6 @@ import com.java2nb.novel.mapper.*;
import com.java2nb.novel.service.AuthorService;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.service.FileService;
import com.java2nb.novel.service.SearchService;
import com.java2nb.novel.vo.BookCommentVO;
import com.java2nb.novel.vo.BookSettingVO;
import com.java2nb.novel.vo.BookSpVO;
@ -24,6 +22,7 @@ import io.github.xxyopen.model.page.PageBean;
import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder;
import io.github.xxyopen.util.IdWorker;
import io.github.xxyopen.web.exception.BusinessException;
import io.github.xxyopen.web.util.BeanUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@ -68,9 +67,6 @@ public class BookServiceImpl implements BookService {
@Value("${pic.save.path}")
private String picSavePath;
@Value("${spring.elasticsearch.enable}")
private Integer esEnable;
private final FrontBookSettingMapper bookSettingMapper;
private final FrontBookMapper bookMapper;
@ -89,8 +85,6 @@ public class BookServiceImpl implements BookService {
private final AuthorService authorService;
private final SearchService searchService;
private final FileService fileService;
private final BookPriceProperties bookPriceConfig;
@ -108,7 +102,8 @@ public class BookServiceImpl implements BookService {
//如果首页小说没有被设置则初始化首页小说设置
list = initIndexBookSetting();
}
result = new ObjectMapper().writeValueAsString(list.stream().collect(Collectors.groupingBy(BookSettingVO::getType)));
result = new ObjectMapper().writeValueAsString(
list.stream().collect(Collectors.groupingBy(BookSettingVO::getType)));
cacheService.set(CacheKey.INDEX_BOOK_SETTINGS_KEY, result);
}
return new ObjectMapper().readValue(result, Map.class);
@ -194,7 +189,6 @@ public class BookServiceImpl implements BookService {
@Override
public PageBean<?> searchByPage(BookSpVO params, int page, int pageSize) {
if (params.getUpdatePeriod() != null) {
long cur = System.currentTimeMillis();
long period = params.getUpdatePeriod() * 24 * 3600 * 1000;
@ -202,18 +196,6 @@ public class BookServiceImpl implements BookService {
params.setUpdateTimeMin(new Date(time));
}
if (esEnable == 1) {
try {
return searchService.searchBook(params,page,pageSize);
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
PageHelper.startPage(page, pageSize);
if (StringUtils.isNotBlank(params.getSort())) {
@ -225,7 +207,8 @@ public class BookServiceImpl implements BookService {
@Override
public List<BookCategory> listBookCategory() {
SelectStatementProvider selectStatementProvider = select(BookCategoryDynamicSqlSupport.id, BookCategoryDynamicSqlSupport.name, BookCategoryDynamicSqlSupport.workDirection)
SelectStatementProvider selectStatementProvider = select(BookCategoryDynamicSqlSupport.id,
BookCategoryDynamicSqlSupport.name, BookCategoryDynamicSqlSupport.workDirection)
.from(bookCategory)
.orderBy(BookCategoryDynamicSqlSupport.sort)
.build()
@ -252,7 +235,10 @@ public class BookServiceImpl implements BookService {
PageHelper.startPage(page, pageSize);
}
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.updateTime, BookIndexDynamicSqlSupport.isVip)
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id,
BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum,
BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.updateTime,
BookIndexDynamicSqlSupport.isVip)
.from(bookIndex)
.where(BookIndexDynamicSqlSupport.bookId, isEqualTo(bookId))
.build()
@ -264,7 +250,11 @@ public class BookServiceImpl implements BookService {
@Override
public BookIndex queryBookIndex(Long bookIndexId) {
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.wordCount,BookIndexDynamicSqlSupport.bookPrice, BookIndexDynamicSqlSupport.updateTime, BookIndexDynamicSqlSupport.isVip,BookIndexDynamicSqlSupport.storageType)
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id,
BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum,
BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.wordCount,
BookIndexDynamicSqlSupport.bookPrice, BookIndexDynamicSqlSupport.updateTime,
BookIndexDynamicSqlSupport.isVip, BookIndexDynamicSqlSupport.storageType)
.from(bookIndex)
.where(BookIndexDynamicSqlSupport.id, isEqualTo(bookIndexId))
.build()
@ -310,7 +300,8 @@ public class BookServiceImpl implements BookService {
@Override
public BookContent queryBookContent(Long bookIndexId) {
SelectStatementProvider selectStatement = select(BookContentDynamicSqlSupport.id, BookContentDynamicSqlSupport.content)
SelectStatementProvider selectStatement = select(BookContentDynamicSqlSupport.id,
BookContentDynamicSqlSupport.content)
.from(bookContent)
.where(BookContentDynamicSqlSupport.indexId, isEqualTo(bookIndexId))
.limit(1)
@ -342,7 +333,8 @@ public class BookServiceImpl implements BookService {
break;
}
}
SelectStatementProvider selectStatement = select(id, catId, catName, bookName, lastIndexId, lastIndexName, authorId, authorName, picUrl, bookDesc, wordCount, lastIndexUpdateTime)
SelectStatementProvider selectStatement = select(id, catId, catName, bookName, lastIndexId, lastIndexName,
authorId, authorName, picUrl, bookDesc, wordCount, lastIndexUpdateTime)
.from(book)
.where(wordCount, isGreaterThan(0))
.orderBy(sortSpecification)
@ -355,7 +347,7 @@ public class BookServiceImpl implements BookService {
@Override
public void addVisitCount(Long bookId, Integer visitCount) {
bookMapper.addVisitCount(bookId,visitCount);
bookMapper.addVisitCount(bookId, visitCount);
}
@Override
@ -471,12 +463,13 @@ public class BookServiceImpl implements BookService {
.build()
.render(RenderingStrategies.MYBATIS3);
return bookIndexMapper.selectMany(selectStatement).stream().map(BookIndex::getIndexNum).collect(Collectors.toList());
return bookIndexMapper.selectMany(selectStatement).stream().map(BookIndex::getIndexNum)
.collect(Collectors.toList());
}
@Override
public List<Book> queryNetworkPicBooks(String localPicPrefix, Integer limit) {
return bookMapper.queryNetworkPicBooks(localPicPrefix,limit);
return bookMapper.queryNetworkPicBooks(localPicPrefix, limit);
}
@Override
@ -501,7 +494,8 @@ public class BookServiceImpl implements BookService {
Author author = authorService.queryAuthor(userId);
PageHelper.startPage(page, pageSize);
SelectStatementProvider selectStatement = select(id, bookName, picUrl, catName, visitCount, yesterdayBuy, lastIndexUpdateTime, updateTime, wordCount, lastIndexName, status)
SelectStatementProvider selectStatement = select(id, bookName, picUrl, catName, visitCount, yesterdayBuy,
lastIndexUpdateTime, updateTime, wordCount, lastIndexName, status)
.from(book)
.where(authorId, isEqualTo(author.getId()))
.orderBy(BookDynamicSqlSupport.createTime.descending())
@ -570,7 +564,8 @@ public class BookServiceImpl implements BookService {
.render(RenderingStrategies.MYBATIS3));
//计算价格
int bookPrice = new BigDecimal(wordCount).multiply(bookPriceConfig.getValue()).divide(bookPriceConfig.getWordCount(),0, RoundingMode.DOWN).intValue();
int bookPrice = new BigDecimal(wordCount).multiply(bookPriceConfig.getValue())
.divide(bookPriceConfig.getWordCount(), 0, RoundingMode.DOWN).intValue();
//更新小说目录表
int indexNum = 0;
@ -601,11 +596,10 @@ public class BookServiceImpl implements BookService {
@Override
public List<Book> queryBookByUpdateTimeByPage(Date startDate, int limit) {
return bookMapper.selectMany(select(book.allColumns())
.from(book)
.where(updateTime, isGreaterThan(startDate))
.and(lastIndexId,isNotNull())
.and(lastIndexId, isNotNull())
.orderBy(updateTime)
.limit(limit)
.build()
@ -617,7 +611,7 @@ public class BookServiceImpl implements BookService {
return bookMapper.selectMany(select(id, bookName)
.from(book)
.where(BookDynamicSqlSupport.authorId,isEqualTo(authorId))
.where(BookDynamicSqlSupport.authorId, isEqualTo(authorId))
.build()
.render(RenderingStrategies.MYBATIS3));
}
@ -649,7 +643,8 @@ public class BookServiceImpl implements BookService {
if (book.getAuthorId().equals(authorId)) {
//删除目录表和内容表记录
bookIndexMapper.deleteByPrimaryKey(indexId);
bookContentMapper.delete(deleteFrom(bookContent).where(BookContentDynamicSqlSupport.indexId, isEqualTo(indexId)).build()
bookContentMapper.delete(
deleteFrom(bookContent).where(BookContentDynamicSqlSupport.indexId, isEqualTo(indexId)).build()
.render(RenderingStrategies.MYBATIS3));
//更新总字数
wordCount = wordCount - bookIndex.getWordCount();
@ -658,7 +653,8 @@ public class BookServiceImpl implements BookService {
String lastIndexName = null;
Date lastIndexUpdateTime = null;
List<BookIndex> lastBookIndices = bookIndexMapper.selectMany(
select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.createTime)
select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.indexName,
BookIndexDynamicSqlSupport.createTime)
.from(BookIndexDynamicSqlSupport.bookIndex)
.where(BookIndexDynamicSqlSupport.bookId, isEqualTo(bookId))
.orderBy(BookIndexDynamicSqlSupport.indexNum.descending())
@ -803,8 +799,8 @@ public class BookServiceImpl implements BookService {
int wordCount = StringUtil.getStrValidWordCount(content);
//计算价格
int bookPrice = new BigDecimal(wordCount).multiply(bookPriceConfig.getValue()).divide(bookPriceConfig.getWordCount(),0,RoundingMode.DOWN).intValue();
int bookPrice = new BigDecimal(wordCount).multiply(bookPriceConfig.getValue())
.divide(bookPriceConfig.getWordCount(), 0, RoundingMode.DOWN).intValue();
//更新小说目录表
bookIndexMapper.update(

View File

@ -1,208 +0,0 @@
package com.java2nb.novel.service.impl;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.xxyopen.model.page.PageBean;
import com.java2nb.novel.core.enums.ResponseStatus;
import io.github.xxyopen.util.StringUtil;
import io.github.xxyopen.web.exception.BusinessException;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.vo.BookSpVO;
import com.java2nb.novel.service.SearchService;
import com.java2nb.novel.vo.EsBookVO;
import io.searchbox.client.JestClient;
import io.searchbox.core.Count;
import io.searchbox.core.CountResult;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author 11797
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class SearchServiceImpl implements SearchService {
private final JestClient jestClient;
private final RestHighLevelClient restHighLevelClient;
private final String INDEX = "novel";
@Override
@SneakyThrows
public void importToEs(Book book) {
//导入到ES
EsBookVO esBookVO = new EsBookVO();
BeanUtils.copyProperties(book, esBookVO, "lastIndexUpdateTime");
esBookVO.setLastIndexUpdateTime(new SimpleDateFormat("yyyy/MM/dd HH:mm").format(book.getLastIndexUpdateTime()));
IndexRequest request = new IndexRequest(INDEX);
request.id(book.getId()+"");
request.source(new ObjectMapper().writeValueAsString(esBookVO), XContentType.JSON);
IndexResponse index = restHighLevelClient.index(request, RequestOptions.DEFAULT);
log.debug(index.getResult().toString());
}
@SneakyThrows
@Override
public PageBean<EsBookVO> searchBook(BookSpVO params, int page, int pageSize) {
List<EsBookVO> bookList = new ArrayList<>(0);
//使用搜索引擎搜索
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 构造查询哪个字段
if (StringUtils.isNoneBlank(params.getKeyword())) {
boolQueryBuilder = boolQueryBuilder.must(QueryBuilders.queryStringQuery(params.getKeyword()));
}
// 作品方向
if (params.getWorkDirection() != null) {
boolQueryBuilder.filter(QueryBuilders.termQuery("workDirection", params.getWorkDirection()));
}
// 分类
if (params.getCatId() != null) {
boolQueryBuilder.filter(QueryBuilders.termQuery("catId", params.getCatId()));
}
if (params.getBookStatus() != null) {
boolQueryBuilder.filter(QueryBuilders.termQuery("bookStatus", params.getBookStatus()));
}
if (params.getWordCountMin() == null) {
params.setWordCountMin(0);
}
if (params.getWordCountMax() == null) {
params.setWordCountMax(Integer.MAX_VALUE);
}
boolQueryBuilder.filter(QueryBuilders.rangeQuery("wordCount").gte(params.getWordCountMin()).lte(params.getWordCountMax()));
if (params.getUpdateTimeMin() != null) {
boolQueryBuilder.filter(QueryBuilders.rangeQuery("lastIndexUpdateTime").gte(new SimpleDateFormat("yyyy/MM/dd HH:mm").format(params.getUpdateTimeMin())));
}
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(boolQueryBuilder);
Count count = new Count.Builder().addIndex(INDEX)
.query(searchSourceBuilder.toString()).build();
CountResult results = jestClient.execute(count);
Double total = results.getCount();
// 高亮字段
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("authorName");
highlightBuilder.field("bookName");
highlightBuilder.field("bookDesc");
highlightBuilder.field("lastIndexName");
highlightBuilder.field("catName");
highlightBuilder.preTags("<span style='color:red'>").postTags("</span>");
highlightBuilder.fragmentSize(20000);
searchSourceBuilder.highlighter(highlightBuilder);
//设置排序
if (params.getSort() != null) {
searchSourceBuilder.sort(StringUtil.camelName(params.getSort()), SortOrder.DESC);
}
// 设置分页
searchSourceBuilder.from((page - 1) * pageSize);
searchSourceBuilder.size(pageSize);
// 构建Search对象
Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex(INDEX).build();
log.debug(search.toString());
SearchResult result;
result = jestClient.execute(search);
log.debug(result.getJsonString());
if (result.isSucceeded()) {
Map resultMap = new ObjectMapper().readValue(result.getJsonString(), Map.class);
if (resultMap.get("hits") != null) {
Map hitsMap = (Map) resultMap.get("hits");
if (hitsMap.size() > 0 && hitsMap.get("hits") != null) {
List hitsList = (List) hitsMap.get("hits");
if (hitsList.size() > 0 && result.getSourceAsString() != null) {
JavaType jt = new ObjectMapper().getTypeFactory().constructParametricType(ArrayList.class, EsBookVO.class);
bookList = new ObjectMapper().readValue("[" + result.getSourceAsString() + "]", jt);
if (bookList != null) {
for (int i = 0; i < bookList.size(); i++) {
hitsMap = (Map) hitsList.get(i);
Map highlightMap = (Map) hitsMap.get("highlight");
if (highlightMap != null && highlightMap.size() > 0) {
List<String> authorNameList = (List<String>) highlightMap.get("authorName");
if (authorNameList != null && authorNameList.size() > 0) {
bookList.get(i).setAuthorName(authorNameList.get(0));
}
List<String> bookNameList = (List<String>) highlightMap.get("bookName");
if (bookNameList != null && bookNameList.size() > 0) {
bookList.get(i).setBookName(bookNameList.get(0));
}
List<String> bookDescList = (List<String>) highlightMap.get("bookDesc");
if (bookDescList != null && bookDescList.size() > 0) {
bookList.get(i).setBookDesc(bookDescList.get(0));
}
List<String> lastIndexNameList = (List<String>) highlightMap.get("lastIndexName");
if (lastIndexNameList != null && lastIndexNameList.size() > 0) {
bookList.get(i).setLastIndexName(lastIndexNameList.get(0));
}
List<String> catNameList = (List<String>) highlightMap.get("catName");
if (catNameList != null && catNameList.size() > 0) {
bookList.get(i).setCatName(catNameList.get(0));
}
}
}
}
}
}
}
return new PageBean<>(page, pageSize, total.longValue(), bookList);
}
throw new BusinessException(ResponseStatus.ES_SEARCH_FAIL);
}
}

View File

@ -6,31 +6,6 @@ spring:
active: dev
include: website,alipay,oss,fastdfs
rabbitmq:
enable: 0
host: 127.0.0.1
username: guest
password: guest
virtual-host: /novel-plus
template:
# 缺省的交换机名称此处配置后发送消息如果不指定交换机就会使用这个
exchange: novel.exchange
publisher-confirms: false
elasticsearch:
#是否开启搜索引擎1开启0不开启
enable: 0
jest:
uris: http://192.168.0.105:9200
redisson:
singleServerConfig:
address: 127.0.0.1:6379
jwt:
secret: novel!#20191230
expiration: 604800