diff --git a/.gitignore b/.gitignore
index cab51707f19bcf13408d692de3f658d41ec6a5ab..67bfb3065590b5e145c824abbf4ae12d6697b2f3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,6 @@
.idea
*.iml
.DS_Store
+/.settings/
+/.classpath
+/.project
diff --git a/README.md b/README.md
index 506e966cefa03fc78cb2c61ae6ce674af9f4e86f..a92f0e098a60e8e3dda6bc4771a1c95754ce91e3 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
#beetl-bbs
-在社区被黑掉好,决定用java做一个社区,技术使用springboot+beetl+beetsql
+在社区被黑掉好,决定用java做一个社区,技术使用springboot2.3+beetl+beetsql
## 安装
@@ -20,6 +20,12 @@
* maven install 生成的war包部署到服务器上
+## 切换搜索引擎
+
+默认自带luncense,以管理员登录后, 点击初始化引擎。
+
+如果需要使用ES作为帖子搜索引擎
+
* 安装elastic search 作为全文搜索:下载 https://www.elastic.co/cn/downloads/elasticsearch (截止当前测试ES版本7.2.0 通过),进入bin目录,调用elasticsearch 启动
* 安装elastic search 分词:进入bin目录,运行 ./elasticsearch-plugin install analysis-smartcn。然后重新启动elasticsearch
diff --git a/install-mysql-update.sql b/install-mysql-update.sql
index 035cbcda7660638fee77cb4ea4f42d0b84259cca..444456a9ffa721118da8dd0a881cbdddfa1a3149 100644
--- a/install-mysql-update.sql
+++ b/install-mysql-update.sql
@@ -1,11 +1,3 @@
--- ----------------------------
--- 老版本2.0 升级用
--- ----------------------------
-ALTER TABLE `bbs`.`bbs_post`
-ADD COLUMN `pros` INT(11) NULL DEFAULT 0 COMMENT '' AFTER `update_time`,
-ADD COLUMN `cons` INT(11) NULL DEFAULT 0 COMMENT '' AFTER `pros`,
-ADD COLUMN `is_accept` INT(11) NULL DEFAULT 0 COMMENT '' AFTER `cons`;
-
-- ----------------------------
diff --git a/install-mysql.sql b/install-mysql.sql
index ac9f2c62d166c5b0ecfc8cb8720516bb04a501ce..1fff7fca0399b6c57e4781e886b1bc04d3509a2b 100644
--- a/install-mysql.sql
+++ b/install-mysql.sql
@@ -93,27 +93,6 @@ INSERT INTO `bbs_post` VALUES ('217', '69', '4', '
什么时候讲?
', '2016-07-13 14:37:49', '\0', null, '0', '0', '0');
INSERT INTO `bbs_post` VALUES ('219', '69', '4', '
', '2016-07-13 14:43:51', '\0', null, '0', '0', '0');
INSERT INTO `bbs_post` VALUES ('220', '70', '95', '打发第三方\r\n', '2016-12-06 20:31:04', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('221', '70', '95', '### **李宗翰**', '2016-12-06 20:32:32', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('225', '59', '95', '发布2', '2016-12-10 22:44:52', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('226', '59', '95', '发布三', '2016-12-10 22:44:58', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('227', '59', '95', '发布四', '2016-12-10 22:45:50', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('228', '59', '95', '发布无', '2016-12-10 22:45:56', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('229', '59', '95', '发布六', '2016-12-10 22:46:03', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('230', '59', '95', '发布六', '2016-12-10 22:57:22', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('231', '59', '95', 'dfsdf sfsdf ', '2016-12-10 23:17:02', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('232', '59', '95', 'sdfsf ', '2016-12-10 23:17:27', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('233', '59', '95', 'sdfsf ', '2016-12-10 23:19:00', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('234', '59', '95', 'dfdsf ', '2016-12-11 00:08:16', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('235', '59', '95', 'df ', '2016-12-11 00:08:19', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('237', '59', '95', 'dsfsdfs\r\ndsfdsfsd\r\n[sdfsffdf](http://163.com \"sdfsffdf\")\r\nsdfsdf\r\n## dfdfdfdfdf\r\n', '2016-12-11 15:49:39', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('241', '59', '1', '
', '2016-12-26 21:46:13', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('242', '59', '1', 'sdfsdfsdf
', '2016-12-26 21:46:21', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('243', '59', '95', '的说法是否
public static void main(String[] args){\r\n \r\n }
', '2016-12-26 22:01:13', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('262', '74', '95', '测试我的新手
', '2017-10-26 19:00:45', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('263', '74', '95', '测试我的新功能
', '2017-10-26 19:01:19', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('264', '75', '95', 'beetl 是最好的模板语言 !!
', '2018-01-24 20:09:15', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('265', '76', '95', '作为中国国家主席,习近平在繁忙的公务活动中,不仅展示了他的睿智严谨,还留下了许多风趣幽默的言行。Most people have only seen the serious side of Chinese President Xi Jinping. But he also makes time for some lighthearted moments despite his packed daily schedule. Not only is Xi a statesman, he is also a football fan, a world traveler and occasionally a historian.客串文化讲解员 Witty interpreter“你们看,我的祖先很魁梧吧。
作为中国国家主席,习近平在繁忙的公务活动中,不仅展示了他的睿智严谨,还留下了许多风趣幽默的言行。Most people have only seen the serious side of Chinese President Xi Jinping. But he also makes time for some lighthearted moments despite his packed daily schedule. Not only is Xi a statesman, he is also a football fan, a world traveler and occasionally a historian.客串文化讲解员 Witty interpreter“你们看,我的祖先很魁梧吧。
', '2018-01-24 20:14:06', '\0', null, '0', '0', '0');
-INSERT INTO `bbs_post` VALUES ('266', '77', '95', 'abc沙发上是否sdfsdf
', '2018-01-24 20:18:29', '\0', null, '0', '0', '0');
-- ----------------------------
-- Table structure for bbs_reply
diff --git a/pom.xml b/pom.xml
index 090c6ca60e011553b9ac05707cb8c565fd6158dc..5579bd5595e321ad73f6e81646490613bd1c1dfe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,28 +3,29 @@
4.0.0
com.ibeetl
bbs
- 2.3.0
+ 2.4.0
war
org.springframework.boot
spring-boot-starter-parent
- 2.2.0.RELEASE
+ 2.3.2.RELEASE
com.ibeetl.bbs.BbsMain
- 1.2.17.RELEASE
- 1.2.62
- 1.12.1
+ 1.2.30.Beetl.RELEASE
+ 3.3.9-RELEASE
+ 1.2.70
+ 1.13.1
1.8
3.9
- 2.8.0
- 4.5.10
- 1.18.10
+ 2.8.1
+ 4.5.12
+ 1.18.12
4.12
@@ -55,6 +56,11 @@
beetl-framework-starter
${beetl-starter.version}
+
+ com.ibeetl
+ sql-springboot-starter
+ ${beetlsql-starter.version}
+
junit
junit
@@ -107,6 +113,39 @@
${lombok.version}
provided
+
+
+
+ org.apache.lucene
+ lucene-core
+ 8.5.2
+
+
+ org.apache.lucene
+ lucene-queryparser
+ 8.5.2
+
+
+ org.apache.lucene
+ lucene-analyzers-common
+ 8.5.2
+
+
+ com.janeluo
+ ikanalyzer
+ 2012_u6
+
+
+ com.huaban
+ jieba-analysis
+ 1.0.2
+
+
+ org.apache.lucene
+ lucene-highlighter
+ 8.5.2
+
+
diff --git a/src/main/java/com/ibeetl/bbs/SearchTest.java b/src/main/java/com/ibeetl/bbs/SearchTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a906e91275f9af5c5029b80e197fd71dc2c5632
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/SearchTest.java
@@ -0,0 +1,89 @@
+package com.ibeetl.bbs;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+
+
+import com.ibeetl.bbs.lucene.LuceneService;
+import com.ibeetl.bbs.lucene.dto.ik.IKAnalyzer5x;
+import com.ibeetl.bbs.lucene.dto.jieba.JiebaAnalyzer;
+
+public class SearchTest {
+
+ public static void main(String[] args) throws IOException {
+
+// test1() ;
+ test2();
+ }
+
+
+ public static void test2() {
+ LuceneService service = new LuceneService();
+// service.get
+
+ }
+
+ public static void test1() throws IOException {
+ String etext = "Analysis is one of the main causes of slow indexing. Simply put, ";
+ // String chineseText = "张三说的确实在理。";
+ String chineseText = "我的新书,我买了一本书,厉害了我的国一经播出,受到各方好评,强烈激发了国人的爱国之情、自豪感!";
+
+ LuceneService service = new LuceneService();
+
+ // IKAnalyzer 细粒度切分
+ try (Analyzer ik = new IKAnalyzer5x(false);) {
+ TokenStream ts = ik.tokenStream("content", etext);
+ System.out.println("IKAnalyzer中文分词器 细粒度切分,英文分词效果:");
+ doToken(ts);
+ ts = ik.tokenStream("content", chineseText);
+ System.out.println("IKAnalyzer中文分词器 细粒度切分,中文分词效果:");
+ doToken(ts);
+ }
+ // IKAnalyzer 智能切分
+ try (Analyzer ik = new IKAnalyzer5x(true);) {
+ TokenStream ts = ik.tokenStream("content", etext);
+ System.out.println("IKAnalyzer中文分词器 智能切分,英文分词效果:");
+ doToken(ts);
+ ts = ik.tokenStream("content", chineseText);
+ System.out.println("IKAnalyzer中文分词器 智能切分,中文分词效果:");
+ doToken(ts);
+ }
+
+ // JiebaAnalyzer 细粒度切分
+ try (Analyzer jieba = new JiebaAnalyzer(false);) {
+ TokenStream ts = jieba.tokenStream("content", etext);
+ System.out.println("JiebaAnalyzer中文分词器 细粒度切分,英文分词效果:");
+ doToken(ts);
+ ts = jieba.tokenStream("content", chineseText);
+ System.out.println("JiebaAnalyzer中文分词器 细粒度切分,中文分词效果:");
+ doToken(ts);
+ }
+ // JiebaAnalyzer 智能切分
+ try (Analyzer jieba = new JiebaAnalyzer(true);) {
+ TokenStream ts = jieba.tokenStream("content", etext);
+ System.out.println("JiebaAnalyzer中文分词器 智能切分,英文分词效果:");
+ doToken(ts);
+ ts = jieba.tokenStream("content", chineseText);
+ System.out.println("JiebaAnalyzer中文分词器 智能切分,中文分词效果:");
+ doToken(ts);
+ }
+ }
+ private static void doToken(TokenStream ts) throws IOException {
+ ts.reset();
+ CharTermAttribute cta = ts.getAttribute(CharTermAttribute.class);
+ while (ts.incrementToken()) {
+ System.out.print(cta.toString() + "|");
+ }
+ System.out.println();
+ ts.end();
+ ts.close();
+ }
+
+}
diff --git a/src/main/java/com/ibeetl/bbs/Test.java b/src/main/java/com/ibeetl/bbs/Test.java
deleted file mode 100644
index 5241c7c0afad5d9241da8d6d34227b56f878fa6e..0000000000000000000000000000000000000000
--- a/src/main/java/com/ibeetl/bbs/Test.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.ibeetl.bbs;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.List;
-
-import org.beetl.sql.core.ClasspathLoader;
-import org.beetl.sql.core.ConnectionSource;
-import org.beetl.sql.core.Interceptor;
-import org.beetl.sql.core.SQLLoader;
-import org.beetl.sql.core.SQLManager;
-import org.beetl.sql.core.UnderlinedNameConversion;
-import org.beetl.sql.core.db.MySqlStyle;
-import org.beetl.sql.ext.DebugInterceptor;
-import org.beetl.sql.ext.gen.GenConfig;
-import org.beetl.sql.ext.gen.GenFilter;
-
-import com.ibeetl.bbs.model.BbsUser;
-
-
-public class Test {
-
- public static void main(String[] args) throws Exception {
- MySqlStyle style = new MySqlStyle();
-
- MySqlConnectoinSource cs = new MySqlConnectoinSource();
- SQLLoader loader = new ClasspathLoader("/sql");
- SQLManager sql = new SQLManager(style,loader,cs,new UnderlinedNameConversion(), new Interceptor[]{new DebugInterceptor()});
-// sql.genPojoCodeToConsole("project");
-
-
-// GenConfig cfg = new GenConfig();
-// cfg.setPreferDate(true);
-// sql.genALL("com.ibeetl.bbs.model", cfg, new GenFilter(){
-// public boolean accept(String tableName){
-// if(tableName.startsWith("bbs_message")){
-// return true;
-// }else{
-// return false;
-// }
-//// return false; //全部生成,当心覆盖
-// }
-// });
-
-
- BbsUser bbsUser = sql.unique(BbsUser.class, 1);
- System.out.println(bbsUser.getBalance());
-
-
- }
-
-
- static class MySqlConnectoinSource implements ConnectionSource {
-
- private Connection _getConn(){
- String driver = MysqlDBConfig.driver;
- String dbName = MysqlDBConfig.dbName;
- String password = MysqlDBConfig.password;
- String userName = MysqlDBConfig.userName;
- String url = MysqlDBConfig.url;
- Connection conn = null;
- try {
- Class.forName(driver);
- conn = DriverManager.getConnection(url, userName,
- password);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return conn;
- }
-
- public Connection getMaster() {
- return _getConn();
- }
-
- public Connection getConn(String sqlId, boolean isUpdate, String sql, List paras) {
- return _getConn();
- }
-
-
-
- public boolean isTransaction() {
- // TODO Auto-generated method stub
- return false;
- }
-
- public Connection getSlave() {
- return this.getMaster();
- }
-
- public void forceBegin(boolean isMaster) {
- // TODO Auto-generated method stub
-
- }
-
- public void forceEnd() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Connection getMetaData() {
- // TODO Auto-generated method stub
- return null;
- }
-
-
-
-
- }
-
- static class MysqlDBConfig {
- public static String driver = "com.mysql.jdbc.Driver";
- public static String dbName = "bbs";
- public static String password = "123456";
- public static String userName = "root";
- public static String url = "jdbc:mysql://127.0.0.1:3306/" + dbName+"?useUnicode=true&characterEncoding=UTF-8";
-
- }
-
-
-}
diff --git a/src/main/java/com/ibeetl/bbs/action/AdminController.java b/src/main/java/com/ibeetl/bbs/action/AdminController.java
index 7c877c4b3fe9ec14ada336d13964ea273ae4ae50..3e872d38d43712f52a8d64e300c8fc1103650c7d 100644
--- a/src/main/java/com/ibeetl/bbs/action/AdminController.java
+++ b/src/main/java/com/ibeetl/bbs/action/AdminController.java
@@ -1,32 +1,35 @@
package com.ibeetl.bbs.action;
+import java.util.Objects;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.beetl.sql.core.SQLManager;
+import org.beetl.sql.core.engine.PageQuery;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
import com.alibaba.fastjson.JSONObject;
import com.ibeetl.bbs.common.WebUtils;
-import com.ibeetl.bbs.es.annotation.EsEntityType;
+import com.ibeetl.bbs.es.annotation.EntityType;
import com.ibeetl.bbs.es.annotation.EsIndexType;
import com.ibeetl.bbs.es.annotation.EsOperateType;
-import com.ibeetl.bbs.es.service.EsService;
+import com.ibeetl.bbs.es.service.SearchService;
import com.ibeetl.bbs.model.BbsPost;
import com.ibeetl.bbs.model.BbsReply;
import com.ibeetl.bbs.model.BbsTopic;
import com.ibeetl.bbs.model.BbsUser;
import com.ibeetl.bbs.service.BBSService;
import com.ibeetl.bbs.service.BbsUserService;
+
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
-import org.beetl.sql.core.SQLManager;
-import org.beetl.sql.core.engine.PageQuery;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.Objects;
/**
* @author darren
@@ -45,12 +48,12 @@ public class AdminController {
BBSService bbsService;
BbsUserService userService;
SQLManager sql;
- EsService esService;
+ SearchService searchService;
@ResponseBody
@PostMapping("/topic/nice/{id}")
- @EsIndexType(entityType = EsEntityType.BbsTopic, operateType = EsOperateType.UPDATE)
+ @EsIndexType(entityType = EntityType.BbsTopic, operateType = EsOperateType.UPDATE)
public JSONObject editNiceTopic(@PathVariable int id) {
JSONObject result = new JSONObject();
if (!webUtils.isAdmin()) {
@@ -70,7 +73,7 @@ public class AdminController {
@ResponseBody
@PostMapping("/topic/up/{id}")
- @EsIndexType(entityType = EsEntityType.BbsTopic, operateType = EsOperateType.UPDATE)
+ @EsIndexType(entityType = EntityType.BbsTopic, operateType = EsOperateType.UPDATE)
public JSONObject editUpTopic(@PathVariable int id) {
JSONObject result = new JSONObject();
if (!webUtils.isAdmin()) {
@@ -91,7 +94,7 @@ public class AdminController {
@ResponseBody
@PostMapping("/topic/delete/{id}")
- @EsIndexType(entityType = EsEntityType.BbsTopic, operateType = EsOperateType.DELETE)
+ @EsIndexType(entityType = EntityType.BbsTopic, operateType = EsOperateType.DELETE)
public JSONObject deleteTopic(@PathVariable int id) {
JSONObject result = new JSONObject();
if (!webUtils.isAdmin()) {
@@ -108,7 +111,7 @@ public class AdminController {
@ResponseBody
@PostMapping("/topic/deleteUser/{id}")
- @EsIndexType(entityType = EsEntityType.BbsTopic, operateType = EsOperateType.DELETE)
+ @EsIndexType(entityType = EntityType.BbsTopic, operateType = EsOperateType.DELETE)
public JSONObject deleteTopicOwner(@PathVariable int id) {
JSONObject result = new JSONObject();
if (!webUtils.isAdmin()) {
@@ -149,7 +152,7 @@ public class AdminController {
*/
@ResponseBody
@RequestMapping("/post/update")
- @EsIndexType(entityType = EsEntityType.BbsPost, operateType = EsOperateType.UPDATE)
+ @EsIndexType(entityType = EntityType.BbsPost, operateType = EsOperateType.UPDATE)
public JSONObject updatePost(BbsPost post) {
JSONObject result = new JSONObject();
result.put("err", 1);
@@ -175,7 +178,7 @@ public class AdminController {
*/
@ResponseBody
@RequestMapping("/post/delete/{id}")
- @EsIndexType(entityType = EsEntityType.BbsPost, operateType = EsOperateType.DELETE)
+ @EsIndexType(entityType = EntityType.BbsPost, operateType = EsOperateType.DELETE)
public JSONObject deletePost(@PathVariable int id) {
JSONObject result = new JSONObject();
BbsPost post = sql.unique(BbsPost.class, id);
@@ -193,7 +196,7 @@ public class AdminController {
@ResponseBody
@PostMapping("/reply/delete/{id}")
- @EsIndexType(entityType = EsEntityType.BbsReply, operateType = EsOperateType.DELETE)
+ @EsIndexType(entityType = EntityType.BbsReply, operateType = EsOperateType.DELETE)
public JSONObject deleteReply(@PathVariable int id) {
JSONObject result = new JSONObject();
@@ -221,9 +224,9 @@ public class AdminController {
result.put("err", 1);
result.put("msg", "呵呵~~");
} else {
- esService.initIndex();
+ searchService.initIndex();
result.put("err", 0);
- result.put("msg", "ES初始化成功");
+ result.put("msg", "文章索引初始化成功");
}
return result;
}
diff --git a/src/main/java/com/ibeetl/bbs/action/BBSController.java b/src/main/java/com/ibeetl/bbs/action/BBSController.java
index d869ab7ddbc2d5e6d9640e862b95b7d9ff5e9c7c..b4f4f1c01e2e5f0c66015ffc958a41c8e3775587 100644
--- a/src/main/java/com/ibeetl/bbs/action/BBSController.java
+++ b/src/main/java/com/ibeetl/bbs/action/BBSController.java
@@ -1,41 +1,59 @@
package com.ibeetl.bbs.action;
+import java.io.File;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.lang3.StringUtils;
+import org.beetl.sql.core.SQLManager;
+import org.beetl.sql.core.engine.PageQuery;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.Cache.ValueWrapper;
+import org.springframework.cache.CacheManager;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
import com.alibaba.fastjson.JSONObject;
import com.ibeetl.bbs.common.WebUtils;
import com.ibeetl.bbs.config.BbsConfig;
import com.ibeetl.bbs.config.CaffeineConfig;
-import com.ibeetl.bbs.es.annotation.EsEntityType;
+import com.ibeetl.bbs.es.annotation.EntityType;
import com.ibeetl.bbs.es.annotation.EsIndexType;
import com.ibeetl.bbs.es.annotation.EsOperateType;
-import com.ibeetl.bbs.es.service.EsService;
+import com.ibeetl.bbs.es.service.SearchService;
import com.ibeetl.bbs.es.vo.IndexObject;
-import com.ibeetl.bbs.model.*;
+import com.ibeetl.bbs.model.BbsMessage;
+import com.ibeetl.bbs.model.BbsModule;
+import com.ibeetl.bbs.model.BbsPost;
+import com.ibeetl.bbs.model.BbsReply;
+import com.ibeetl.bbs.model.BbsTopic;
+import com.ibeetl.bbs.model.BbsUser;
import com.ibeetl.bbs.service.BBSService;
import com.ibeetl.bbs.util.AddressUtil;
import com.ibeetl.bbs.util.DateUtil;
import com.ibeetl.bbs.util.Functions;
+
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
-import org.apache.commons.lang3.StringUtils;
-import org.beetl.sql.core.SQLManager;
-import org.beetl.sql.core.engine.PageQuery;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.cache.Cache;
-import org.springframework.cache.Cache.ValueWrapper;
-import org.springframework.cache.CacheManager;
-import org.springframework.stereotype.Controller;
-import org.springframework.util.FileCopyUtils;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.io.File;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
@Controller
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@@ -48,7 +66,7 @@ public class BBSController {
BBSService bbsService;
WebUtils webUtils;
Functions functionUtil;
- EsService esService;
+ SearchService searchService;
CacheManager cacheManager;
BbsConfig bbsConfig;
HttpServletRequest request;
@@ -69,7 +87,7 @@ public class BBSController {
} else {
view = "/lucene/lucene.html";
//查询索引
- PageQuery searcherKeywordPage = this.esService.getQueryPage(keyword, p.orElse(1));
+ PageQuery searcherKeywordPage = this.searchService.getQueryPage(keyword, p.orElse(1));
request.setAttribute("searcherPage", searcherKeywordPage);
request.setAttribute("pageName", keyword);
request.setAttribute("resultnum", searcherKeywordPage.getTotalRow());
@@ -107,7 +125,7 @@ public class BBSController {
}
@GetMapping({"/topic/{id}", "/topic/{id}/{p}"})
- @EsIndexType(entityType = EsEntityType.BbsTopic, operateType = EsOperateType.UPDATE)
+ @EsIndexType(entityType = EntityType.BbsTopic, operateType = EsOperateType.UPDATE)
public String topic(@PathVariable Integer id, @PathVariable Optional p) {
PageQuery query = new PageQuery(p.orElse(1));
query.setPara("topicId", id);
@@ -143,8 +161,8 @@ public class BBSController {
*/
@ResponseBody
@PostMapping("/topic/save")
- @EsIndexType(entityType = EsEntityType.BbsTopic, operateType = EsOperateType.ADD, key = "tid")
- @EsIndexType(entityType = EsEntityType.BbsPost, operateType = EsOperateType.ADD, key = "pid")
+ @EsIndexType(entityType = EntityType.BbsTopic, operateType = EsOperateType.ADD, key = "tid")
+ @EsIndexType(entityType = EntityType.BbsPost, operateType = EsOperateType.ADD, key = "pid")
public JSONObject saveTopic(BbsTopic topic, BbsPost post, String code, String title, String postContent) {
//@TODO, 防止频繁提交
BbsUser user = webUtils.currentUser();
@@ -220,7 +238,7 @@ public class BBSController {
@ResponseBody
@PostMapping("/post/save")
- @EsIndexType(entityType = EsEntityType.BbsPost, operateType = EsOperateType.ADD)
+ @EsIndexType(entityType = EntityType.BbsPost, operateType = EsOperateType.ADD)
public JSONObject savePost(BbsPost post) {
JSONObject result = new JSONObject();
result.put("err", 1);
@@ -253,7 +271,7 @@ public class BBSController {
*/
@ResponseBody
@PostMapping("/reply/save")
- @EsIndexType(entityType = EsEntityType.BbsReply, operateType = EsOperateType.ADD)
+ @EsIndexType(entityType = EntityType.BbsReply, operateType = EsOperateType.ADD)
public JSONObject saveReply(BbsReply reply) {
JSONObject result = new JSONObject();
result.put("err", 1);
@@ -267,7 +285,6 @@ public class BBSController {
reply.setPostId(reply.getPostId());
reply.setCreateTime(new Date());
bbsService.saveReply(reply);
- reply.set("bbsUser", user);
reply.setUser(user);
result.put("msg", "评论成功!");
result.put("err", 0);
@@ -329,7 +346,7 @@ public class BBSController {
*/
@PostMapping("/post/support/{postId}")
@ResponseBody
- @EsIndexType(entityType = EsEntityType.BbsPost, operateType = EsOperateType.UPDATE)
+ @EsIndexType(entityType = EntityType.BbsPost, operateType = EsOperateType.UPDATE)
public JSONObject updatePostSupport(@PathVariable Integer postId, @RequestParam Integer num) {
JSONObject result = new JSONObject();
result.put("err", 1);
@@ -369,7 +386,7 @@ public class BBSController {
*/
@PostMapping("/user/post/accept/{postId}")
@ResponseBody
- @EsIndexType(entityType = EsEntityType.BbsPost, operateType = EsOperateType.UPDATE)
+ @EsIndexType(entityType = EntityType.BbsPost, operateType = EsOperateType.UPDATE)
public JSONObject updatePostAccept(@PathVariable Integer postId) {
JSONObject result = new JSONObject();
result.put("err", 1);
diff --git a/src/main/java/com/ibeetl/bbs/config/SearchConfig.java b/src/main/java/com/ibeetl/bbs/config/SearchConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a0b8693f42d2ad2ca816bf1cd181b47903c31ee
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/config/SearchConfig.java
@@ -0,0 +1,28 @@
+package com.ibeetl.bbs.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.ibeetl.bbs.es.service.EsService;
+import com.ibeetl.bbs.es.service.SearchService;
+import com.ibeetl.bbs.lucene.LuceneService;
+
+
+@Configuration
+public class SearchConfig {
+
+
+ @Bean
+ @ConditionalOnProperty(prefix = "search" , name = "type",havingValue = "es",matchIfMissing = false)
+ public SearchService getEs() {
+ return new EsService();
+ }
+
+ @Bean
+ @ConditionalOnProperty(prefix = "search" , name = "type",havingValue = "lucene",matchIfMissing = false)
+ public SearchService getLucene() {
+ return new LuceneService();
+ }
+
+}
diff --git a/src/main/java/com/ibeetl/bbs/dao/BbsModuleDao.java b/src/main/java/com/ibeetl/bbs/dao/BbsModuleDao.java
index b452474fdc321c609fae47ca1a77e087d4ea7a1b..ee961ca978c1af757197e2fed4f07f1f2d78f3b4 100644
--- a/src/main/java/com/ibeetl/bbs/dao/BbsModuleDao.java
+++ b/src/main/java/com/ibeetl/bbs/dao/BbsModuleDao.java
@@ -1,8 +1,8 @@
package com.ibeetl.bbs.dao;
-import org.beetl.sql.core.mapper.BaseMapper;
import com.ibeetl.bbs.model.BbsModule;
+import org.beetl.sql.mapper.BaseMapper;
public interface BbsModuleDao extends BaseMapper {
diff --git a/src/main/java/com/ibeetl/bbs/dao/BbsPostDao.java b/src/main/java/com/ibeetl/bbs/dao/BbsPostDao.java
index 50b5e2b52de93aa8d44cc8a83a95bc5662891224..03e65ee9c73864bc0500a3db5df288fcd5269f83 100644
--- a/src/main/java/com/ibeetl/bbs/dao/BbsPostDao.java
+++ b/src/main/java/com/ibeetl/bbs/dao/BbsPostDao.java
@@ -1,22 +1,23 @@
package com.ibeetl.bbs.dao;
import com.ibeetl.bbs.model.BbsPost;
-import org.beetl.sql.core.annotatoin.Sql;
-import org.beetl.sql.core.annotatoin.SqlStatement;
-import org.beetl.sql.core.annotatoin.SqlStatementType;
+
import org.beetl.sql.core.engine.PageQuery;
-import org.beetl.sql.core.mapper.BaseMapper;
+import org.beetl.sql.mapper.BaseMapper;
+import org.beetl.sql.mapper.annotation.Param;
+import org.beetl.sql.mapper.annotation.Sql;
+import org.beetl.sql.mapper.annotation.Update;
import java.util.Date;
public interface BbsPostDao extends BaseMapper {
- @SqlStatement(type = SqlStatementType.SELECT)
+
void getPosts(PageQuery query);
- @SqlStatement(params = "topicId")
- void deleteByTopicId(int topicId);
+ @Update
+ void deleteByTopicId(@Param("topicId") int topicId);
- @Sql(value = "select max(create_time) from bbs_post where user_id=? order by id desc ", returnType = Date.class)
+ @Sql(value = "select max(create_time) from bbs_post where user_id=? order by id desc ")
Date getLatestPostDate(int userId);
}
diff --git a/src/main/java/com/ibeetl/bbs/dao/BbsReplyDao.java b/src/main/java/com/ibeetl/bbs/dao/BbsReplyDao.java
index 28386cfae460405c626a8f5038d82ed25ad1d4dc..dfcee21ef4c5f6068ee9161f29436a6e1b9d9b7e 100644
--- a/src/main/java/com/ibeetl/bbs/dao/BbsReplyDao.java
+++ b/src/main/java/com/ibeetl/bbs/dao/BbsReplyDao.java
@@ -1,18 +1,18 @@
package com.ibeetl.bbs.dao;
import com.ibeetl.bbs.model.BbsReply;
-import org.beetl.sql.core.annotatoin.SqlStatement;
-import org.beetl.sql.core.mapper.BaseMapper;
+import org.beetl.sql.mapper.BaseMapper;
+import org.beetl.sql.mapper.annotation.Param;
+import org.beetl.sql.mapper.annotation.Update;
+
import java.util.List;
public interface BbsReplyDao extends BaseMapper {
- @SqlStatement(params = "postId")
- List allReply(Integer postId);
-
- @SqlStatement(params = "topicId")
- void deleteByTopicId(int topicId);
- @SqlStatement(params = "postId")
- void deleteByPostId(int postId);
+ List allReply(@Param("postId") Integer postId);
+ @Update
+ void deleteByTopicId(@Param("topicId") int topicId);
+ @Update
+ void deleteByPostId(@Param("postId") int postId);
}
diff --git a/src/main/java/com/ibeetl/bbs/dao/BbsTopicDao.java b/src/main/java/com/ibeetl/bbs/dao/BbsTopicDao.java
index 0b40ec1a526a68e37771eb045ba36652f03e5dd1..d677bd0c4f129d7ec5c6d8868a475db2d39cc323 100644
--- a/src/main/java/com/ibeetl/bbs/dao/BbsTopicDao.java
+++ b/src/main/java/com/ibeetl/bbs/dao/BbsTopicDao.java
@@ -1,9 +1,11 @@
package com.ibeetl.bbs.dao;
import com.ibeetl.bbs.model.BbsTopic;
-import org.beetl.sql.core.annotatoin.Sql;
+
import org.beetl.sql.core.engine.PageQuery;
-import org.beetl.sql.core.mapper.BaseMapper;
+import org.beetl.sql.mapper.BaseMapper;
+import org.beetl.sql.mapper.annotation.Sql;
+
import java.util.Date;
import java.util.List;
diff --git a/src/main/java/com/ibeetl/bbs/dao/BbsUserDao.java b/src/main/java/com/ibeetl/bbs/dao/BbsUserDao.java
index 08ff990370a9cebbf933dc5fe4e4789c7625dcfa..ce432dd12ce4c35114e72e8863d29eec84bbb404 100644
--- a/src/main/java/com/ibeetl/bbs/dao/BbsUserDao.java
+++ b/src/main/java/com/ibeetl/bbs/dao/BbsUserDao.java
@@ -1,8 +1,9 @@
package com.ibeetl.bbs.dao;
import com.ibeetl.bbs.model.BbsUser;
-import org.beetl.sql.core.annotatoin.Sql;
-import org.beetl.sql.core.mapper.BaseMapper;
+import org.beetl.sql.mapper.BaseMapper;
+import org.beetl.sql.mapper.annotation.Sql;
+
import java.util.List;
diff --git a/src/main/java/com/ibeetl/bbs/es/annotation/EsEntityType.java b/src/main/java/com/ibeetl/bbs/es/annotation/EntityType.java
similarity index 73%
rename from src/main/java/com/ibeetl/bbs/es/annotation/EsEntityType.java
rename to src/main/java/com/ibeetl/bbs/es/annotation/EntityType.java
index 389f5336748dcf0f334048b0fb1da2d974ff4839..fd411227646ac82183dd9b8af4413d98f415f933 100644
--- a/src/main/java/com/ibeetl/bbs/es/annotation/EsEntityType.java
+++ b/src/main/java/com/ibeetl/bbs/es/annotation/EntityType.java
@@ -1,5 +1,5 @@
package com.ibeetl.bbs.es.annotation;
-public enum EsEntityType {
+public enum EntityType {
BbsTopic, BbsPost, BbsReply
}
diff --git a/src/main/java/com/ibeetl/bbs/es/annotation/EsIndexType.java b/src/main/java/com/ibeetl/bbs/es/annotation/EsIndexType.java
index 8e7cc3fd555fb4ba4d5c46ce05917a2040498f8f..1f3143730ed220c907660a39c5f272d81d71c8f3 100644
--- a/src/main/java/com/ibeetl/bbs/es/annotation/EsIndexType.java
+++ b/src/main/java/com/ibeetl/bbs/es/annotation/EsIndexType.java
@@ -20,7 +20,7 @@ import java.lang.annotation.Target;
@Repeatable(EsIndexs.class)
public @interface EsIndexType {
- EsEntityType entityType(); //实体类型
+ EntityType entityType(); //实体类型
EsOperateType operateType(); //操作类型
diff --git a/src/main/java/com/ibeetl/bbs/es/config/AOPConfig.java b/src/main/java/com/ibeetl/bbs/es/config/AOPConfig.java
index 091a2b22b3f3d6cd0766b2d005a0208c19b7ea15..e598f248b83d1f22c726377655a1b56e44adb067 100644
--- a/src/main/java/com/ibeetl/bbs/es/config/AOPConfig.java
+++ b/src/main/java/com/ibeetl/bbs/es/config/AOPConfig.java
@@ -1,17 +1,13 @@
package com.ibeetl.bbs.es.config;
-import com.alibaba.fastjson.JSONObject;
-import com.ibeetl.bbs.es.annotation.EsFallback;
-import com.ibeetl.bbs.es.annotation.EsIndexType;
-import com.ibeetl.bbs.es.annotation.EsOperateType;
-import com.ibeetl.bbs.es.entity.BbsIndex;
-import com.ibeetl.bbs.es.service.EsService;
-import com.ibeetl.bbs.es.vo.EsIndexTypeData;
-import com.ibeetl.bbs.util.EsUtil;
-import lombok.AccessLevel;
-import lombok.RequiredArgsConstructor;
-import lombok.experimental.FieldDefaults;
-import lombok.extern.slf4j.Slf4j;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
@@ -24,9 +20,19 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.web.servlet.ModelAndView;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.*;
+import com.alibaba.fastjson.JSONObject;
+import com.ibeetl.bbs.es.annotation.EsFallback;
+import com.ibeetl.bbs.es.annotation.EsIndexType;
+import com.ibeetl.bbs.es.annotation.EsOperateType;
+import com.ibeetl.bbs.es.entity.BbsIndex;
+import com.ibeetl.bbs.es.service.SearchService;
+import com.ibeetl.bbs.es.vo.EsIndexTypeData;
+import com.ibeetl.bbs.util.EsUtil;
+
+import lombok.AccessLevel;
+import lombok.RequiredArgsConstructor;
+import lombok.experimental.FieldDefaults;
+import lombok.extern.slf4j.Slf4j;
@Configuration
@Aspect
@@ -35,7 +41,7 @@ import java.util.*;
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class AOPConfig {
- EsService esService;
+ SearchService searchService;
/**
@@ -67,7 +73,7 @@ public class AOPConfig {
if (id == null) {
log.error(target.getClass().getName() + "$" + method.getName() + ":未获取到主键,无法更新索引");
} else {
- BbsIndex bbsIndex = esService.createBbsIndex(index.entityType(), id);
+ BbsIndex bbsIndex = searchService.createBbsIndex(index.entityType(), id);
String md5Id = EsUtil.getEsKey(bbsIndex.getTopicId(), bbsIndex.getPostId(), bbsIndex.getReplyId());
EsIndexTypeData data = new EsIndexTypeData(index.entityType(), index.operateType(), md5Id);
typeDatas.add(data);
@@ -108,7 +114,7 @@ public class AOPConfig {
//更新索引
for (EsIndexTypeData esIndexTypeData : typeDatas) {
- esService.editEsIndex(esIndexTypeData.getEntityType(), esIndexTypeData.getOperateType(), esIndexTypeData.getId());
+ searchService.editEsIndex(esIndexTypeData.getEntityType(), esIndexTypeData.getOperateType(), esIndexTypeData.getId());
}
return o;
diff --git a/src/main/java/com/ibeetl/bbs/es/entity/BbsIndex.java b/src/main/java/com/ibeetl/bbs/es/entity/BbsIndex.java
index 74df92378ff0fb44b93e96c76dee396feab9ea12..23d7768d7d594150632b73d16ae41b9c35a6fe34 100644
--- a/src/main/java/com/ibeetl/bbs/es/entity/BbsIndex.java
+++ b/src/main/java/com/ibeetl/bbs/es/entity/BbsIndex.java
@@ -1,13 +1,15 @@
package com.ibeetl.bbs.es.entity;
+import java.util.Date;
+
+import com.ibeetl.bbs.es.annotation.EntityType;
import com.ibeetl.bbs.util.EsUtil;
+
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldDefaults;
-import java.util.Date;
-
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@NoArgsConstructor
@@ -26,6 +28,8 @@ public class BbsIndex {
Integer isAccept = 0;//0:未采纳,1:采纳
Integer pv = 0;//访问量
+ EntityType entityType;
+
public String getId() {
if (this.id == null) {
this.id = EsUtil.getEsKey(topicId, postId, replyId);
diff --git a/src/main/java/com/ibeetl/bbs/es/service/EsService.java b/src/main/java/com/ibeetl/bbs/es/service/EsService.java
index 0702a8a9d03a53924f21fde1e5f3ed1e45807c21..39e05e40ab1e05fb31048124be713d7cf7f1516f 100644
--- a/src/main/java/com/ibeetl/bbs/es/service/EsService.java
+++ b/src/main/java/com/ibeetl/bbs/es/service/EsService.java
@@ -1,20 +1,13 @@
package com.ibeetl.bbs.es.service;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import com.ibeetl.bbs.es.annotation.EsEntityType;
-import com.ibeetl.bbs.es.annotation.EsFallback;
-import com.ibeetl.bbs.es.annotation.EsOperateType;
-import com.ibeetl.bbs.es.config.EsConfig;
-import com.ibeetl.bbs.es.entity.BbsIndex;
-import com.ibeetl.bbs.es.vo.IndexObject;
-import com.ibeetl.bbs.model.*;
-import com.ibeetl.bbs.service.BBSService;
-import lombok.AccessLevel;
-import lombok.RequiredArgsConstructor;
-import lombok.experimental.FieldDefaults;
-import lombok.extern.slf4j.Slf4j;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.fluent.Executor;
import org.apache.http.client.fluent.Request;
@@ -23,26 +16,40 @@ import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.engine.PageQuery;
+import org.beetl.sql.core.page.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.JSONPath;
+import com.ibeetl.bbs.es.annotation.EntityType;
+import com.ibeetl.bbs.es.annotation.EsFallback;
+import com.ibeetl.bbs.es.annotation.EsOperateType;
+import com.ibeetl.bbs.es.config.EsConfig;
+import com.ibeetl.bbs.es.entity.BbsIndex;
+import com.ibeetl.bbs.es.vo.IndexObject;
+import com.ibeetl.bbs.model.BbsModule;
+import com.ibeetl.bbs.model.BbsPost;
+import com.ibeetl.bbs.model.BbsReply;
+import com.ibeetl.bbs.model.BbsTopic;
+import com.ibeetl.bbs.model.BbsUser;
+import com.ibeetl.bbs.service.BBSService;
-@Service
-@RequiredArgsConstructor(onConstructor_ = @Autowired)
-@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
+import lombok.extern.slf4j.Slf4j;
+
+//@Service
@Slf4j
-public class EsService {
+public class EsService implements SearchService{
+ @Autowired
BBSService bbsService;
+ @Autowired
SQLManager sqlManager;
+ @Autowired
EsConfig esConfig;
+ @Autowired
GroupTemplate beetlTemplate;
Executor executor = Executor.newInstance();
@@ -51,7 +58,7 @@ public class EsService {
* 公共操作方法
*/
@EsFallback
- public void editEsIndex(EsEntityType entityType, EsOperateType operateType, Object id) {
+ public void editEsIndex(EntityType entityType, EsOperateType operateType, Object id) {
if (operateType == EsOperateType.ADD || operateType == EsOperateType.UPDATE) {
BbsIndex bbsIndex = this.createBbsIndex(entityType, (Integer) id);
if (bbsIndex != null) {
@@ -62,7 +69,7 @@ public class EsService {
}
}
- public void editEsIndexFallback(EsEntityType entityType, EsOperateType operateType, Object id) {
+ public void editEsIndexFallback(EntityType entityType, EsOperateType operateType, Object id) {
}
/**
@@ -88,10 +95,10 @@ public class EsService {
*/
private void batchSaveBbsIndex(Class clazz) {
int curPage = 1;
- int pageSize = 500;
+ long pageSize = 500;
while (true) {
- int startRow = 1 + (curPage - 1) * pageSize;
+ long startRow = 1 + (curPage - 1) * pageSize;
List list = sqlManager.all(clazz, startRow, pageSize);
if (list != null && list.size() > 0) {
List indexList = new ArrayList<>();
@@ -131,18 +138,18 @@ public class EsService {
/**
* 创建索引对象
*/
- public BbsIndex createBbsIndex(EsEntityType entityType, Integer id) {
+ public BbsIndex createBbsIndex(EntityType entityType, Integer id) {
BbsIndex bbsIndex = null;
- if (entityType == EsEntityType.BbsTopic) {
+ if (entityType == EntityType.BbsTopic) {
BbsTopic topic = bbsService.getTopic(id);
BbsPost firstPost = bbsService.getFirstPost(topic.getId());
bbsIndex = new BbsIndex(topic.getId(), null, null, topic.getUserId(), topic.getContent(), topic.getCreateTime(), 0, 0, firstPost != null ? firstPost.getIsAccept() : 0, topic.getPv());
- } else if (entityType == EsEntityType.BbsPost) {
+ } else if (entityType == EntityType.BbsPost) {
BbsPost post = bbsService.getPost(id);
BbsTopic topic = bbsService.getTopic(post.getTopicId());
bbsIndex = new BbsIndex(post.getTopicId(), post.getId(), null, post.getUserId(), post.getContent(), post.getCreateTime(), post.getPros(), post.getCons(), post.getIsAccept(), topic.getPv());
- } else if (entityType == EsEntityType.BbsReply) {
+ } else if (entityType == EntityType.BbsReply) {
BbsReply reply = bbsService.getReply(id);
bbsIndex = new BbsIndex(reply.getTopicId(), reply.getPostId(), reply.getId(), reply.getUserId(), reply.getContent(), reply.getCreateTime(), 0, 0, 0, 0);
}
@@ -158,7 +165,7 @@ public class EsService {
*/
private void saveBbsIndex(BbsIndex bbsIndex) {
try {
- executor.execute(Request.Post(esConfig.getContentUrl() + bbsIndex)
+ executor.execute(Request.Put(esConfig.getContentUrl()+bbsIndex.getId())
.bodyString(JSON.toJSONString(bbsIndex), ContentType.APPLICATION_JSON))
.discardContent();
} catch (Exception e) {
@@ -206,9 +213,15 @@ public class EsService {
List indexObjectList = new ArrayList<>();
JSONObject root = JSON.parseObject(result);
- JSONObject hits = root.getJSONObject("hits");
- long total = hits.getLongValue("total");
- JSONArray arrays = hits.getJSONArray("hits");
+ Object totalObj = JSONPath.eval(root, "$.hits.total");
+ long total;
+ if (totalObj instanceof JSONObject) {
+ //兼容ES7(最后测试通过版本:v)
+ total = ((JSONObject) totalObj).getLongValue("value");
+ } else {
+ total = Long.parseLong(totalObj.toString());
+ }
+ JSONArray arrays = (JSONArray) JSONPath.eval(root, "$.hits.hits");
for (int i = 0; i < arrays.size(); i++) {
JSONObject node = arrays.getJSONObject(i);
double score = node.getDoubleValue("_score");
@@ -265,7 +278,7 @@ public class EsService {
String kw = keyword.trim().replaceAll("?\\w+[^>]>", "");
PageQuery pageQuery = new PageQuery<>(pageNumber, pageSize);
- PageQuery postPage = bbsService.queryPostByContent(kw, pageNumber, pageSize);
+ PageResult postPage = bbsService.queryPostByContent(kw, pageNumber, pageSize);
List indexObjects = Optional.ofNullable(postPage.getList())
.orElse(Collections.emptyList())
.stream()
diff --git a/src/main/java/com/ibeetl/bbs/es/service/SearchService.java b/src/main/java/com/ibeetl/bbs/es/service/SearchService.java
new file mode 100644
index 0000000000000000000000000000000000000000..859d0ea2fb141e000fc20c4b87f14f1709214231
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/es/service/SearchService.java
@@ -0,0 +1,53 @@
+package com.ibeetl.bbs.es.service;
+
+import org.beetl.sql.core.engine.PageQuery;
+
+import com.ibeetl.bbs.es.annotation.EntityType;
+import com.ibeetl.bbs.es.annotation.EsOperateType;
+import com.ibeetl.bbs.es.entity.BbsIndex;
+import com.ibeetl.bbs.es.vo.IndexObject;
+
+
+public interface SearchService {
+
+ /**
+ * 公共操作方法
+ */
+
+ public void editEsIndex(EntityType entityType, EsOperateType operateType, Object id);
+
+ public default void editEsIndexFallback(EntityType entityType, EsOperateType operateType, Object id) {
+ throw new RuntimeException("操作失败");
+ }
+
+ /**
+ * 重构索引
+ */
+ public void initIndex() ;
+
+ public default void initIndexFallback() {
+ throw new RuntimeException("操作失败");
+ }
+
+ /**
+ * 创建索引对象
+ */
+ public BbsIndex createBbsIndex(EntityType entityType, Integer id) ;
+
+ /**
+ * 创建所有并返回搜索结果
+ */
+ public PageQuery getQueryPage(String keyword, int p) ;
+
+ public default PageQuery getQueryPageFallback(String keyword, int p){
+ if (p <= 0) {
+ p = 1;
+ }
+ int pageNumber = p;
+ long pageSize = PageQuery.DEFAULT_PAGE_SIZE;
+ PageQuery pageQuery = new PageQuery<>(pageNumber, pageSize);
+ return pageQuery;
+ }
+
+
+}
diff --git a/src/main/java/com/ibeetl/bbs/es/vo/EsIndexTypeData.java b/src/main/java/com/ibeetl/bbs/es/vo/EsIndexTypeData.java
index 38db7567e01e8484d114cc6cf004e91709571686..fb69a77494f7a246b8258d778a72db822a9e5045 100644
--- a/src/main/java/com/ibeetl/bbs/es/vo/EsIndexTypeData.java
+++ b/src/main/java/com/ibeetl/bbs/es/vo/EsIndexTypeData.java
@@ -1,7 +1,8 @@
package com.ibeetl.bbs.es.vo;
-import com.ibeetl.bbs.es.annotation.EsEntityType;
+import com.ibeetl.bbs.es.annotation.EntityType;
import com.ibeetl.bbs.es.annotation.EsOperateType;
+
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -19,7 +20,7 @@ import lombok.experimental.FieldDefaults;
@NoArgsConstructor
public class EsIndexTypeData {
- EsEntityType entityType; //实体类型
+ EntityType entityType; //实体类型
EsOperateType operateType; //操作类型
Object id; //获取主键
diff --git a/src/main/java/com/ibeetl/bbs/lucene/LuceneService.java b/src/main/java/com/ibeetl/bbs/lucene/LuceneService.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd09b0f29cd65e0abc40c4006f9c446242a8157f
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/lucene/LuceneService.java
@@ -0,0 +1,613 @@
+package com.ibeetl.bbs.lucene;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.file.Path;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexOptions;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryparser.classic.QueryParser;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.search.highlight.Fragmenter;
+import org.apache.lucene.search.highlight.Highlighter;
+import org.apache.lucene.search.highlight.QueryScorer;
+import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
+import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.beetl.sql.core.SQLManager;
+import org.beetl.sql.core.engine.PageQuery;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.system.ApplicationHome;
+import org.springframework.stereotype.Service;
+
+import com.ibeetl.bbs.es.annotation.EntityType;
+import com.ibeetl.bbs.es.annotation.EsOperateType;
+import com.ibeetl.bbs.es.entity.BbsIndex;
+import com.ibeetl.bbs.es.service.SearchService;
+import com.ibeetl.bbs.es.vo.IndexObject;
+import com.ibeetl.bbs.lucene.dto.ik.IKAnalyzer5x;
+import com.ibeetl.bbs.lucene.dto.jieba.JiebaAnalyzer;
+import com.ibeetl.bbs.model.BbsModule;
+import com.ibeetl.bbs.model.BbsPost;
+import com.ibeetl.bbs.model.BbsReply;
+import com.ibeetl.bbs.model.BbsTopic;
+import com.ibeetl.bbs.model.BbsUser;
+import com.ibeetl.bbs.service.BBSService;
+import com.ibeetl.bbs.util.ExecutorUtil;
+
+import lombok.extern.slf4j.Slf4j;
+
+//@Service
+@Slf4j
+public class LuceneService implements SearchService {
+
+ @Autowired
+ private BBSService bbsService;
+ @Autowired
+ private SQLManager sqlManager;
+
+ private Directory directory = null;
+ private Analyzer analyzerUseSmart = null;
+ private Analyzer analyzerNotUseSmart = null;
+ private String indexDer = "/lucene";// 索引存放目录
+
+ private Analyzer getAnalyzerUseSmart() {
+ if (analyzerUseSmart == null) {
+ synchronized (this) {
+ if (analyzerUseSmart == null) {
+ // analyzer = new SmartChineseAnalyzer();//中文分词器
+ // 创建IKAnalyzer中文分词对象
+// analyzerUseSmart = new IKAnalyzer5x(true);
+ analyzerUseSmart = new JiebaAnalyzer(true);
+ }
+ }
+ }
+ return analyzerUseSmart;
+ }
+
+ private Analyzer getAnalyzerNotUseSmart() {
+ if (analyzerNotUseSmart == null) {
+ synchronized (this) {
+ if (analyzerNotUseSmart == null) {
+ // analyzer = new SmartChineseAnalyzer();//中文分词器
+ // 创建IKAnalyzer中文分词对象
+ analyzerNotUseSmart = new IKAnalyzer5x(false);
+// analyzerNotUseSmart = new JiebaAnalyzer(false);
+ }
+ }
+ }
+ return analyzerNotUseSmart;
+ }
+
+ private Directory getDirectory() throws IOException {
+ if (directory == null) {
+ synchronized (this) {
+ if (directory == null) {
+ ApplicationHome home = new ApplicationHome(getClass());
+ File jarFile = home.getSource();
+ String rootPath = jarFile.getParentFile().getAbsolutePath();
+ File indexrepository_file = new File(rootPath + this.indexDer);
+
+ Path path = indexrepository_file.toPath();
+ directory = FSDirectory.open(path);
+ }
+ }
+
+ }
+ return directory;
+ }
+
+ /**
+ * 公共操作方法
+ */
+ public void editEsIndex(EntityType entityType, EsOperateType operateType, Object id) {
+ if (operateType == EsOperateType.ADD || operateType == EsOperateType.UPDATE) {
+ BbsIndex bbsIndex = this.createBbsIndex(entityType, (Integer) id);
+ if (bbsIndex != null) {
+ this.saveBbsIndex(bbsIndex);
+ }
+ } else if (operateType == EsOperateType.DELETE) {
+ this.deleteBbsIndex((String) id);
+ }
+ }
+
+ /**
+ * 重构索引
+ */
+ public void initIndex() {
+ IndexWriter indexWriter = null;
+ try {
+ // 创建一个分析器对象
+ // 创建一个IndexwriterConfig对象
+ IndexWriterConfig config = new IndexWriterConfig(getAnalyzerNotUseSmart());
+ // 创建一个IndexWriter对象,对于索引库进行写操作
+ indexWriter = new IndexWriter(getDirectory(), config);
+ // 删除以前的索引
+ indexWriter.deleteAll();
+
+ indexWriter.commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ try {
+ indexWriter.rollback();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ } finally {
+ try {
+ indexWriter.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ batchSaveBbsIndex(BbsTopic.class);
+ batchSaveBbsIndex(BbsPost.class);
+ batchSaveBbsIndex(BbsReply.class);
+ }
+
+ /**
+ * 批量插入索引
+ */
+ private void batchSaveBbsIndex(Class clazz) {
+ int curPage = 1;
+ long pageSize = 500;
+
+ while (true) {
+ long startRow = 1 + (curPage - 1) * pageSize;
+ List list = sqlManager.all(clazz, startRow, pageSize);
+ if (list != null && list.size() > 0) {
+ List indexList = new ArrayList<>();
+ for (T t : list) {
+ BbsIndex bbsIndex = null;
+
+ if (t instanceof BbsTopic) {
+ BbsTopic topic = (BbsTopic) t;
+ BbsPost firstPost = bbsService.getFirstPost(topic.getId());
+ bbsIndex = new BbsIndex(topic.getId(), null, null, topic.getUserId(), topic.getContent(),
+ topic.getCreateTime(), 0, 0, firstPost != null ? firstPost.getIsAccept() : 0,
+ topic.getPv());
+ bbsIndex.setEntityType(EntityType.BbsTopic);
+ } else if (t instanceof BbsPost) {
+ BbsPost post = (BbsPost) t;
+ BbsTopic topic = bbsService.getTopic(post.getTopicId());
+ if(topic!=null){
+ bbsIndex = new BbsIndex(post.getTopicId(), post.getId(), null, post.getUserId(),
+ post.getContent(), post.getCreateTime(), post.getPros(), post.getCons(),
+ post.getIsAccept(), topic.getPv());
+ bbsIndex.setEntityType(EntityType.BbsPost);
+ }
+
+ } else if (t instanceof BbsReply) {
+ BbsReply reply = (BbsReply) t;
+ bbsIndex = new BbsIndex(reply.getTopicId(), reply.getPostId(), reply.getId(), reply.getUserId(),
+ reply.getContent(), reply.getCreateTime(), 0, 0, 0, 0);
+ bbsIndex.setEntityType(EntityType.BbsReply);
+ }
+ if (bbsIndex == null) {
+ log.error("未定义类型转换");
+ } else {
+ indexList.add(bbsIndex);
+ }
+
+ }
+ saveBbsIndexList(indexList);
+ curPage++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ /**
+ * 创建索引对象
+ */
+ public BbsIndex createBbsIndex(EntityType entityType, Integer id) {
+
+ BbsIndex bbsIndex = null;
+ if (entityType == EntityType.BbsTopic) {
+ BbsTopic topic = bbsService.getTopic(id);
+ BbsPost firstPost = bbsService.getFirstPost(topic.getId());
+ bbsIndex = new BbsIndex(topic.getId(), null, null, topic.getUserId(), topic.getContent(),
+ topic.getCreateTime(), 0, 0, firstPost != null ? firstPost.getIsAccept() : 0, topic.getPv());
+ } else if (entityType == EntityType.BbsPost) {
+ BbsPost post = bbsService.getPost(id);
+ BbsTopic topic = bbsService.getTopic(post.getTopicId());
+ bbsIndex = new BbsIndex(post.getTopicId(), post.getId(), null, post.getUserId(), post.getContent(),
+ post.getCreateTime(), post.getPros(), post.getCons(), post.getIsAccept(), topic.getPv());
+ } else if (entityType == EntityType.BbsReply) {
+ BbsReply reply = bbsService.getReply(id);
+ bbsIndex = new BbsIndex(reply.getTopicId(), reply.getPostId(), reply.getId(), reply.getUserId(),
+ reply.getContent(), reply.getCreateTime(), 0, 0, 0, 0);
+ }
+
+ if (bbsIndex == null) {
+ log.error("未定义类型转换");
+ } else {
+ bbsIndex.setEntityType(entityType);
+ }
+ return bbsIndex;
+ }
+
+ /**
+ * 保存或更新索引
+ */
+ private void saveBbsIndex(BbsIndex bbsIndex) {
+ List bbsIndexList = new ArrayList<>();
+ bbsIndexList.add(bbsIndex);
+ saveBbsIndexList(bbsIndexList);
+ }
+
+ /**
+ * 保存或更新索引,异步线程池执行
+ */
+ private void saveBbsIndexList(List bbsIndexList) {
+ ExecutorUtil.LUCENE_EXECUTOR_POOL.execute(new Runnable() {
+
+ @Override
+ public void run() {
+
+ IndexWriter indexWriter = null;
+ try {
+ // 创建一个分析器对象
+ // 创建一个IndexwriterConfig对象
+ IndexWriterConfig config = new IndexWriterConfig(getAnalyzerUseSmart());
+ // 创建一个IndexWriter对象,对于索引库进行写操作
+ indexWriter = new IndexWriter(getDirectory(), config);
+ // 删除以前的索引
+ // indexWriter.deleteAll();
+
+ for (BbsIndex t : bbsIndexList) {
+ // 创建一个Document对象
+ Document document = new Document();
+
+ Field contentField = null;
+
+ if (StringUtils.isBlank(t.getContent())) { // 如果为空结束该次循环
+ continue;
+ }
+
+ // 向Document对象中添加域信息
+ // 参数:1、域的名称;2、域的值;3、是否存储;
+ contentField = new TextField("content", labelformat(t.getContent()), Store.YES);
+
+ Field id = new StringField("id", t.getId(),Store.YES);
+
+ // storedFiled默认存储
+ Field topicIdField = new StoredField("topicId", t.getTopicId());
+ if (t.getPostId() != null) {
+ Field postIdField = new StoredField("postId", t.getPostId());
+ document.add(postIdField);
+ }
+ if (t.getReplyId() != null) {
+ Field replyIdField = new StoredField("replyId", t.getReplyId());
+ document.add(replyIdField);
+ }
+ Field indexTypeField = new StoredField("indexType", t.getEntityType().ordinal() + 1);
+ Field createTimeField = new StoredField("createTime", t.getCreateTime().getTime());
+ Field pvField = new StoredField("pv", t.getPv());
+
+ // 将域添加到document对象中
+ document.add(id);
+ document.add(topicIdField);
+ document.add(indexTypeField);
+ document.add(contentField);
+ document.add(createTimeField);
+ document.add(pvField);
+
+ // 将信息写入到索引库中
+ indexWriter.updateDocument(new Term("id", t.getId()), document);
+ }
+
+ // 刷新
+ indexWriter.flush();
+ indexWriter.commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ try {
+ indexWriter.rollback();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ } finally {
+ try {
+ indexWriter.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ }
+ });
+
+ }
+
+ private List getDocumentList(IndexReader reader, Query query) {
+ List list = new ArrayList<>();
+ try {
+ IndexSearcher searcher = new IndexSearcher(reader);
+ // 搜索:第一个参数:查询语句对象 第二个参数:指定显示记录数
+ TopDocs search = searcher.search(query, Integer.MAX_VALUE);
+ // 从搜索结果对象中获取结果集
+ ScoreDoc[] scoreDocs = search.scoreDocs;
+ for (ScoreDoc scoreDoc : scoreDocs) {
+ // 获取Id
+ int docId = scoreDoc.doc;
+ // 通过文档ID从硬盘上获取文档
+ Document document = reader.document(docId);
+ list.add(document);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return list;
+ }
+
+ /**
+ * 删除索引,异步处理
+ */
+ private void deleteBbsIndex(String id) {
+ ExecutorUtil.LUCENE_EXECUTOR_POOL.execute(new Runnable() {
+
+ @Override
+ public void run() {
+ IndexWriter indexWriter = null;
+ try {
+ // 创建一个分析器对象
+ // 创建一个IndexwriterConfig对象
+ IndexWriterConfig config = new IndexWriterConfig(getAnalyzerUseSmart());
+ // 创建一个IndexWriter对象,对于索引库进行写操作
+ indexWriter = new IndexWriter(getDirectory(), config);
+
+ indexWriter.deleteDocuments(new Term("id", id));
+
+ indexWriter.commit();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ try {
+ indexWriter.rollback();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ } finally {
+ try {
+ indexWriter.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+ });
+
+ }
+
+ /**
+ * 创建所有并返回搜索结果
+ */
+ public PageQuery getQueryPage(String keyword, int p) {
+ if (p <= 0) {
+ p = 1;
+ }
+ int pageNumber = p;
+ Integer pageSize = Integer.parseInt(PageQuery.DEFAULT_PAGE_SIZE + "");
+
+ if (keyword != null) {
+ keyword = this.string2Json(keyword);
+ }
+ if (pageSize == 0)
+ pageSize = 10;
+ IndexReader indexReader = null;
+ PageQuery pageQuery = null;
+ List searchResults = new ArrayList<>();
+ try {
+ // 打开索引库
+ indexReader = DirectoryReader.open(getDirectory());
+ // 创建一个IndexSearcher对象
+ IndexSearcher indexSearcher = new IndexSearcher(indexReader);
+ // 建立查询解析器
+ // 第一个参数是要查询的字段;
+ // 第二个参数是分析器Analyzer
+ QueryParser parser = new QueryParser("content", getAnalyzerUseSmart());
+ // 创建一个查询对象
+ // 特殊字符转义
+ keyword = QueryParser.escape(keyword);
+ // 根据传进来的par查找
+ Query query = parser.parse(keyword);
+ // 执行查询
+ // 返回的最大值,在分页的时候使用
+ // TopDocs topDocs = indexSearcher.search(query, 5);
+
+ // 获取上一页的最后一个元素
+ ScoreDoc lastSd = getLastScoreDoc(pageNumber, pageSize, query, indexSearcher);
+ // 通过最后一个元素去搜索下一页的元素
+ TopDocs topDocs = indexSearcher.searchAfter(lastSd, query, pageSize);
+
+ // 高亮显示
+ Highlighter highlighter = addStringHighlighter(query);
+
+ // 取查询结果总数量
+ // System.out.println("总共的查询结果:" + topDocs.totalHits);
+ // 查询结果,就是documentID列表
+ for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
+ // 取对象document的对象id
+ int docID = scoreDoc.doc;
+ // 相关度得分
+ float score = scoreDoc.score;
+ // 根据ID去document对象
+ Document document = indexSearcher.doc(docID);
+ String content = stringFormatHighlighterOut(getAnalyzerNotUseSmart(), highlighter, document, "content");
+
+ BbsTopic topic = bbsService.getTopic(Integer.valueOf(document.get("topicId")));
+ if (topic == null) {
+ continue;
+ }
+ BbsUser user = topic.getUser();
+ BbsModule module = topic.getModule();
+
+ if (document.get("indexType").equals("1")) { // 主题贴
+ BbsPost firstPost = bbsService.getFirstPost(topic.getId());
+
+ searchResults.add(new IndexObject(topic.getId(), topic.getIsUp(), topic.getIsNice(), user,
+ new Date(Long.valueOf(document.get("createTime"))), topic.getPostCount(), topic.getPv(),
+ module, content, firstPost != null ? firstPost.getContent() : "", 1, score));
+ } else if (document.get("indexType").equals("2")) { // 回复贴
+ searchResults.add(new IndexObject(topic.getId(), topic.getIsUp(), topic.getIsNice(), user,
+ new Date(Long.valueOf(document.get("createTime"))), topic.getPostCount(), topic.getPv(),
+ module, topic.getContent(), content, 2, score));
+ }
+ }
+
+ pageQuery = new PageQuery<>(pageNumber, null);
+ pageQuery.setPageSize(pageSize);
+ pageQuery.setTotalRow(Integer.parseInt(topDocs.totalHits.value + ""));
+ Collections.sort(searchResults, new Comparator() {
+
+ @Override
+ public int compare(IndexObject o1, IndexObject o2) {
+ return Double.valueOf(o2.getScore()).compareTo(Double.valueOf(o1.getScore()));
+ }
+ });
+ pageQuery.setList(searchResults);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ indexReader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return pageQuery;
+ }
+
+ /**
+ * JSON字符串特殊字符处理
+ */
+ private String string2Json(String s) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ switch (c) {
+ case '\"':
+ sb.append("\\\"");
+ break;
+ case '\\':
+ sb.append("\\\\");
+ break;
+ case '/':
+ sb.append("\\/");
+ break;
+ case '\b':
+ sb.append("\\b");
+ break;
+ case '\f':
+ sb.append("\\f");
+ break;
+ case '\n':
+ sb.append("\\n");
+ break;
+ case '\r':
+ sb.append("\\r");
+ break;
+ case '\t':
+ sb.append("\\t");
+ break;
+ default:
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 根据页码和分页大小获取上一次的最后一个scoredoc
+ *
+ * @param currentPage
+ * @param pageSize
+ * @param query
+ * @param searcher
+ * @return ScoreDoc
+ * @throws IOException
+ */
+ private ScoreDoc getLastScoreDoc(Integer currentPage, Integer pageSize, Query query, IndexSearcher searcher)
+ throws IOException {
+ if (currentPage == 1)
+ return null;// 如果是第一页就返回空
+ int num = pageSize * (currentPage - 1);// 获取上一页的最后数量
+ TopDocs tds = searcher.search(query, num);
+ return tds.scoreDocs[num - 1];
+ }
+
+ /**
+ * 设置字符串高亮
+ *
+ * @param query
+ * @return
+ */
+ private Highlighter addStringHighlighter(Query query) {
+ // 算分
+ QueryScorer scorer = new QueryScorer(query);
+ // 显示得分高的片段
+ Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
+ // 设置标签内部关键字的颜色
+ // 第一个参数:标签的前半部分;第二个参数:标签的后半部分。
+ SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("", "");
+ // 第一个参数是对查到的结果进行实例化;第二个是片段得分(显示得分高的片段,即摘要)
+ Highlighter highlighter = new Highlighter(simpleHTMLFormatter, scorer);
+ // 设置片段
+ highlighter.setTextFragmenter(fragmenter);
+ return highlighter;
+ }
+
+ private String stringFormatHighlighterOut(Analyzer analyzer, Highlighter highlighter, Document document,
+ String field) throws Exception {
+ String fieldValue = document.get(field);
+ if (fieldValue != null) {
+ // 把全部得分高的摘要给显示出来
+ // 第一个参数是对哪个参数进行设置;第二个是以流的方式读入
+ TokenStream tokenStream = analyzer.tokenStream(field, new StringReader(fieldValue));
+ // 获取最高的片段
+ return highlighter.getBestFragment(tokenStream, fieldValue);
+ }
+ return null;
+ }
+
+ /**
+ * 转译a标签
+ *
+ * @param content
+ * @return
+ */
+ private String labelformat(String content) {
+ if (StringUtils.isBlank(content))
+ return "";
+ return content.replaceAll("", "</a>");
+ }
+}
diff --git a/src/main/java/com/ibeetl/bbs/lucene/dto/ik/IKAnalyzer5x.java b/src/main/java/com/ibeetl/bbs/lucene/dto/ik/IKAnalyzer5x.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd0c382b9d1dac9da75f07871654593392e085ef
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/lucene/dto/ik/IKAnalyzer5x.java
@@ -0,0 +1,54 @@
+package com.ibeetl.bbs.lucene.dto.ik;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.Tokenizer;
+
+public class IKAnalyzer5x extends Analyzer{
+
+ private boolean useSmart;
+
+ public boolean useSmart() {
+ return useSmart;
+ }
+
+ public void setUseSmart(boolean useSmart) {
+ this.useSmart = useSmart;
+ }
+
+ /**
+ * IK分词器Lucene Analyzer接口实现类
+ *
+ * 默认细粒度切分算法
+ */
+ public IKAnalyzer5x(){
+ this(false);
+ }
+
+ /**
+ * IK分词器Lucene Analyzer接口实现类
+ *
+ * @param useSmart 当为true时,分词器进行智能切分
+ */
+ public IKAnalyzer5x(boolean useSmart){
+ super();
+ this.useSmart = useSmart;
+ }
+
+
+ /**
+ protected TokenStreamComponents createComponents(String fieldName, final Reader in) {
+ Tokenizer _IKTokenizer = new IKTokenizer(in , this.useSmart());
+ return new TokenStreamComponents(_IKTokenizer);
+ }
+ **/
+
+
+ /**
+ * 重写最新版本的createComponents
+ * 重载Analyzer接口,构造分词组件
+ */
+ @Override
+ protected TokenStreamComponents createComponents(String fieldName) {
+ Tokenizer _IKTokenizer = new IKTokenizer5x(this.useSmart());
+ return new TokenStreamComponents(_IKTokenizer);
+ }
+}
diff --git a/src/main/java/com/ibeetl/bbs/lucene/dto/ik/IKTokenizer5x.java b/src/main/java/com/ibeetl/bbs/lucene/dto/ik/IKTokenizer5x.java
new file mode 100644
index 0000000000000000000000000000000000000000..f7ca76aa532e9a4215e7547dccfa5b7088824910
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/lucene/dto/ik/IKTokenizer5x.java
@@ -0,0 +1,93 @@
+package com.ibeetl.bbs.lucene.dto.ik;
+
+import java.io.IOException;
+
+import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
+import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
+import org.wltea.analyzer.core.IKSegmenter;
+import org.wltea.analyzer.core.Lexeme;
+
+public class IKTokenizer5x extends Tokenizer{
+
+
+ //IK分词器实现
+ private IKSegmenter _IKImplement;
+
+ //词元文本属性
+ private final CharTermAttribute termAtt;
+ //词元位移属性
+ private final OffsetAttribute offsetAtt;
+ //词元分类属性(该属性分类参考org.wltea.analyzer.core.Lexeme中的分类常量)
+ private final TypeAttribute typeAtt;
+ //记录最后一个词元的结束位置
+ private int endPosition;
+
+
+ /**
+ public IKTokenizer(Reader in , boolean useSmart){
+ super(in);
+ offsetAtt = addAttribute(OffsetAttribute.class);
+ termAtt = addAttribute(CharTermAttribute.class);
+ typeAtt = addAttribute(TypeAttribute.class);
+ _IKImplement = new IKSegmenter(input , useSmart);
+ }**/
+
+ /**
+ * Lucene 5.x Tokenizer适配器类构造函数
+ * 实现最新的Tokenizer接口
+ * @param useSmart
+ */
+ public IKTokenizer5x(boolean useSmart){
+ super();
+ offsetAtt = addAttribute(OffsetAttribute.class);
+ termAtt = addAttribute(CharTermAttribute.class);
+ typeAtt = addAttribute(TypeAttribute.class);
+ _IKImplement = new IKSegmenter(input , useSmart);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.lucene.analysis.TokenStream#incrementToken()
+ */
+ @Override
+ public boolean incrementToken() throws IOException {
+ //清除所有的词元属性
+ clearAttributes();
+ Lexeme nextLexeme = _IKImplement.next();
+ if(nextLexeme != null){
+ //将Lexeme转成Attributes
+ //设置词元文本
+ termAtt.append(nextLexeme.getLexemeText());
+ //设置词元长度
+ termAtt.setLength(nextLexeme.getLength());
+ //设置词元位移
+ offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition());
+ //记录分词的最后位置
+ endPosition = nextLexeme.getEndPosition();
+ //记录词元分类
+ typeAtt.setType(nextLexeme.getLexemeTypeString());
+ //返会true告知还有下个词元
+ return true;
+ }
+ //返会false告知词元输出完毕
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.lucene.analysis.Tokenizer#reset(java.io.Reader)
+ */
+ @Override
+ public void reset() throws IOException {
+ super.reset();
+ _IKImplement.reset(input);
+ }
+
+ @Override
+ public final void end() {
+ // set final offset
+ int finalOffset = correctOffset(this.endPosition);
+ offsetAtt.setOffset(finalOffset, finalOffset);
+ }
+}
diff --git a/src/main/java/com/ibeetl/bbs/lucene/dto/jieba/JiebaAnalyzer.java b/src/main/java/com/ibeetl/bbs/lucene/dto/jieba/JiebaAnalyzer.java
new file mode 100644
index 0000000000000000000000000000000000000000..377cf712b047dc9714e0e9ca442bada7c5f6b3ca
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/lucene/dto/jieba/JiebaAnalyzer.java
@@ -0,0 +1,110 @@
+package com.ibeetl.bbs.lucene.dto.jieba;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Locale;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.CharArraySet;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.core.StopFilter;
+import org.springframework.util.ResourceUtils;
+
+import com.huaban.analysis.jieba.JiebaSegmenter;
+import com.huaban.analysis.jieba.WordDictionary;
+
+public class JiebaAnalyzer extends Analyzer{
+
+ private static final String DEFAULT_STOPWORD_FILE = "stopwords.txt";
+ private final CharArraySet stopWords;
+
+ private JiebaSegmenter.SegMode segMode;
+
+ private boolean useSmart;
+
+ public boolean useSmart() {
+ return useSmart;
+ }
+
+ public void setUseSmart(boolean useSmart) {
+ this.useSmart = useSmart;
+ }
+
+ public JiebaAnalyzer(){
+ this(false);
+ }
+
+ public JiebaAnalyzer(boolean useSmart){
+ super();
+ this.useSmart = useSmart;
+ this.segMode = useSmart?JiebaSegmenter.SegMode.INDEX:JiebaSegmenter.SegMode.SEARCH;
+ this.stopWords = new CharArraySet(128, true);
+ File file;
+ try {
+ file = ResourceUtils.getFile("classpath:"+DEFAULT_STOPWORD_FILE);
+ init(file.getParent());
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * use for add user dictionary and stop words,
+ * user dictionary need with .dict suffix, stop words with file name: stopwords.txt
+ * @param userDictPath
+ */
+ public void init(String userDictPath){
+ if ( ! StringUtils.isEmpty(userDictPath)){
+ File file = new File(userDictPath);
+ if (file.exists()){
+ //load stop words from userDictPath with name stopwords.txt, one word per line.
+ loadStopWords(Paths.get(userDictPath, DEFAULT_STOPWORD_FILE) , Charset.forName("UTF-8"));
+ }
+ }
+ }
+
+ /**
+ * load stop words from path
+ * @param userDict stop word path, one word per line
+ * @param charset
+ */
+ private void loadStopWords(Path userDict, Charset charset) {
+ try {
+ BufferedReader br = Files.newBufferedReader(userDict, charset);
+ int count = 0;
+ while (br.ready()) {
+ String line = br.readLine();
+ if (! StringUtils.isEmpty(line)){
+ stopWords.add(line);
+ ++count;
+ }
+ }
+ System.out.println(String.format(Locale.getDefault(), "%s: load stop words total:%d!", userDict.toString(), count));
+ br.close();
+ }
+ catch (IOException e) {
+ System.err.println(String.format(Locale.getDefault(), "%s: load stop words failure!", userDict.toString()));
+ }
+ }
+
+ @Override
+ protected TokenStreamComponents createComponents(String s) {
+ final Tokenizer tokenizer = new JiebaTokenizer(segMode);
+ TokenStream result = tokenizer;
+
+ if (!stopWords.isEmpty()) {
+ result = new StopFilter(result, stopWords);
+ }
+
+ return new TokenStreamComponents(tokenizer, result);
+ }
+}
diff --git a/src/main/java/com/ibeetl/bbs/lucene/dto/jieba/JiebaTokenizer.java b/src/main/java/com/ibeetl/bbs/lucene/dto/jieba/JiebaTokenizer.java
new file mode 100644
index 0000000000000000000000000000000000000000..90ceaef9613ac382649bdb0ac69bb9a1326c1024
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/lucene/dto/jieba/JiebaTokenizer.java
@@ -0,0 +1,128 @@
+package com.ibeetl.bbs.lucene.dto.jieba;
+
+import java.io.IOException;
+import java.text.BreakIterator;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
+import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
+import org.apache.lucene.analysis.util.SegmentingTokenizerBase;
+import org.apache.lucene.util.AttributeFactory;
+
+import com.huaban.analysis.jieba.JiebaSegmenter;
+import com.huaban.analysis.jieba.SegToken;
+
+public class JiebaTokenizer extends SegmentingTokenizerBase {
+ /** used for breaking the text into sentences */
+ private static final BreakIterator sentenceProto = BreakIterator.getSentenceInstance(Locale.ROOT);
+
+ private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
+ private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
+ private final TypeAttribute typeAtt = addAttribute(TypeAttribute.class);
+
+ /** Jieba Segmenter and tokens */
+ private final JiebaSegmenter wordSegmenter = new JiebaSegmenter();
+ private Iterator tokens;
+
+ /** jieba segMode */
+ private final JiebaSegmenter.SegMode segMode;
+
+ /** record field sentence offset */
+ private int sentenceStart = 0;
+ private int sentenceEnd = 0;
+
+ /**
+ * used for sentence witch length > 1024
+ * if sentence length greater than 1024, setNextSentence method parameter sentenceStart will be 0
+ * fieldIdCounter is filed id counter,
+ * curFieldId
+ * */
+ private long fieldIdCounter = 0;
+ private static long MAX_FIELD_ID=1000000;
+ private long curFieldId = 0;
+ private int fieldOffset = 0;
+
+
+ /** Creates a new JiebaTokenizer */
+ public JiebaTokenizer(JiebaSegmenter.SegMode segMode) {
+ super(sentenceProto);
+ this.segMode = segMode;
+ }
+
+ /** Creates a new JiebaTokenizer, supplying the AttributeFactory */
+ public JiebaTokenizer(JiebaSegmenter.SegMode segMode, AttributeFactory factory) {
+ super(factory, (BreakIterator)sentenceProto.clone());
+ this.segMode = segMode;
+ }
+
+ @Override
+ protected void setNextSentence(int sentenceStart, int sentenceEnd) {
+ if (curFieldId != fieldIdCounter){//after reset, new field start.
+ curFieldId = fieldIdCounter;
+
+ this.sentenceStart = sentenceStart;
+ this.sentenceEnd = sentenceEnd;
+ }else{//field not change
+ if (sentenceStart == 0){
+ fieldOffset = this.sentenceEnd;
+ }
+
+ this.sentenceStart = sentenceStart + fieldOffset;
+ this.sentenceEnd = sentenceEnd + fieldOffset;
+ }
+
+ String sentence = new String(buffer, sentenceStart, sentenceEnd - sentenceStart);
+ List segTokenList = wordSegmenter.process(sentence, segMode);
+
+ //need order SegTokens by startOffset
+ Collections.sort(segTokenList, new Comparator() {
+ /**
+ * @return a negative integer, zero, or a positive integer as the
+ * first argument is less than, equal to, or greater than the
+ * second.
+ * @param o1
+ * @param o2
+ */
+ @Override
+ public int compare(SegToken o1, SegToken o2) {
+ return o1.startOffset - o2.startOffset;
+ }
+ });
+
+ tokens = segTokenList.iterator();
+ }
+
+ @Override
+ protected boolean incrementWord() {
+ if (tokens == null || !tokens.hasNext()) {
+ return false;
+ } else {
+ SegToken token = tokens.next();
+ clearAttributes();
+ termAtt.copyBuffer(token.word.toCharArray(), 0, token.word.length());
+ int startOffset = sentenceStart + token.startOffset;
+ int endOffset = sentenceStart + token.endOffset;
+
+ offsetAtt.setOffset(startOffset, endOffset);
+ typeAtt.setType("word");
+ return true;
+ }
+ }
+
+ @Override
+ public void reset() throws IOException {
+ super.reset();
+
+ fieldIdCounter = (++fieldIdCounter % MAX_FIELD_ID);
+
+ tokens = null;
+ sentenceStart = 0;
+ sentenceEnd = 0;
+ fieldOffset = 0;
+ }
+}
diff --git a/src/main/java/com/ibeetl/bbs/model/BbsMessage.java b/src/main/java/com/ibeetl/bbs/model/BbsMessage.java
index 3aa7098d3fdd11a4777a1173ff62d2fd820f781e..91673a3aaa92dbf2b41605876067e9e3c5a8286b 100644
--- a/src/main/java/com/ibeetl/bbs/model/BbsMessage.java
+++ b/src/main/java/com/ibeetl/bbs/model/BbsMessage.java
@@ -3,6 +3,7 @@ package com.ibeetl.bbs.model;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
+import org.beetl.sql.annotation.entity.AutoID;
/*
*
@@ -11,6 +12,7 @@ import lombok.experimental.FieldDefaults;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class BbsMessage {
+ @AutoID
Integer id;
Integer status;
Integer topicId;
diff --git a/src/main/java/com/ibeetl/bbs/model/BbsPost.java b/src/main/java/com/ibeetl/bbs/model/BbsPost.java
index 46b6e597854f6c80be8f8c157ea00f4fec2bcb8f..0e0b498030acd6dc848ed4405b39bbff1827925a 100644
--- a/src/main/java/com/ibeetl/bbs/model/BbsPost.java
+++ b/src/main/java/com/ibeetl/bbs/model/BbsPost.java
@@ -4,7 +4,10 @@ import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.FieldDefaults;
+import org.beetl.sql.annotation.entity.AutoID;
import org.beetl.sql.core.TailBean;
+import org.beetl.sql.fetch.annotation.Fetch;
+import org.beetl.sql.fetch.annotation.FetchOne;
import java.util.Date;
import java.util.List;
@@ -16,8 +19,9 @@ import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
+@Fetch
public class BbsPost extends TailBean {
-
+ @AutoID
Integer id;
Integer hasReply;
Integer topicId;
@@ -32,5 +36,9 @@ public class BbsPost extends TailBean {
List replys;
+ @FetchOne("userId")
+ BbsUser bbsUser;
+ @FetchOne("topicId")
+ BbsTopic bbsTopic;
}
diff --git a/src/main/java/com/ibeetl/bbs/model/BbsReply.java b/src/main/java/com/ibeetl/bbs/model/BbsReply.java
index deffc7dee4a207629807d524eb6dc45fc5922d9c..47019527b0e041667a389349bac16d131eda4d30 100644
--- a/src/main/java/com/ibeetl/bbs/model/BbsReply.java
+++ b/src/main/java/com/ibeetl/bbs/model/BbsReply.java
@@ -4,7 +4,10 @@ import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.FieldDefaults;
+import org.beetl.sql.annotation.entity.AutoID;
import org.beetl.sql.core.TailBean;
+import org.beetl.sql.fetch.annotation.Fetch;
+import org.beetl.sql.fetch.annotation.FetchOne;
import java.util.Date;
@@ -15,14 +18,18 @@ import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
+@Fetch
public class BbsReply extends TailBean{
-
+ @AutoID
Integer id;
Integer postId;
Integer topicId;
Integer userId;
String content;
Date createTime;
+
+ @FetchOne("userId")
BbsUser user;
+ @FetchOne("topicId")
BbsTopic topic;
}
diff --git a/src/main/java/com/ibeetl/bbs/model/BbsTopic.java b/src/main/java/com/ibeetl/bbs/model/BbsTopic.java
index 87622481739b010ddd2f1cfb57c36775f9050668..46212f8cd726c97715381375a2250668d24675ce 100644
--- a/src/main/java/com/ibeetl/bbs/model/BbsTopic.java
+++ b/src/main/java/com/ibeetl/bbs/model/BbsTopic.java
@@ -4,7 +4,10 @@ import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.FieldDefaults;
+import org.beetl.sql.annotation.entity.AutoID;
import org.beetl.sql.core.TailBean;
+import org.beetl.sql.fetch.annotation.Fetch;
+import org.beetl.sql.fetch.annotation.FetchOne;
import java.util.Date;
@@ -15,8 +18,10 @@ import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
+@Fetch
public class BbsTopic extends TailBean {
+ @AutoID
Integer id;
Integer emotion;
Integer isNice;
@@ -28,6 +33,8 @@ public class BbsTopic extends TailBean {
Integer userId;
String content;
Date createTime;
+ @FetchOne("userId")
BbsUser user;
+ @FetchOne("moduleId")
BbsModule module;
}
diff --git a/src/main/java/com/ibeetl/bbs/model/BbsUser.java b/src/main/java/com/ibeetl/bbs/model/BbsUser.java
index 299f7e21df68461d17cfce407e47705618f0191e..420d1788d7ae68e0a82a0b89207b57bbd1665548 100644
--- a/src/main/java/com/ibeetl/bbs/model/BbsUser.java
+++ b/src/main/java/com/ibeetl/bbs/model/BbsUser.java
@@ -5,6 +5,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldDefaults;
+import org.beetl.sql.annotation.entity.AutoID;
import org.beetl.sql.core.TailBean;
import java.util.Date;
@@ -18,6 +19,7 @@ import java.util.Date;
@FieldDefaults(level = AccessLevel.PRIVATE)
@NoArgsConstructor
public class BbsUser extends TailBean {
+ @AutoID
Integer id;
Integer level;
Integer score;
diff --git a/src/main/java/com/ibeetl/bbs/service/BBSService.java b/src/main/java/com/ibeetl/bbs/service/BBSService.java
index 67ee175db6edfe8602fb48109f2461ba08915b42..f4720ad91fd3b35079e5a6d28d10b679e98dfd3b 100644
--- a/src/main/java/com/ibeetl/bbs/service/BBSService.java
+++ b/src/main/java/com/ibeetl/bbs/service/BBSService.java
@@ -7,6 +7,7 @@ import com.ibeetl.bbs.model.BbsReply;
import com.ibeetl.bbs.model.BbsTopic;
import com.ibeetl.bbs.model.BbsUser;
import org.beetl.sql.core.engine.PageQuery;
+import org.beetl.sql.core.page.PageResult;
import java.util.Date;
import java.util.List;
@@ -81,6 +82,6 @@ public interface BBSService {
BbsModule getModule(Integer id);
- PageQuery queryPostByContent(String keyWord, long pageNum, long pageSize);
+ PageResult queryPostByContent(String keyWord, long pageNum, long pageSize);
}
diff --git a/src/main/java/com/ibeetl/bbs/service/impl/BBSServiceImpl.java b/src/main/java/com/ibeetl/bbs/service/impl/BBSServiceImpl.java
index 274d9f83d5f0be37768189dbea5e988f38cbf647..9a1b565e42c7ad7620583c111f16421c33cd2c26 100644
--- a/src/main/java/com/ibeetl/bbs/service/impl/BBSServiceImpl.java
+++ b/src/main/java/com/ibeetl/bbs/service/impl/BBSServiceImpl.java
@@ -19,6 +19,7 @@ import lombok.experimental.FieldDefaults;
import org.apache.commons.lang3.StringUtils;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.engine.PageQuery;
+import org.beetl.sql.core.page.PageResult;
import org.beetl.sql.core.query.LambdaQuery;
import org.beetl.sql.core.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
@@ -101,7 +102,7 @@ public class BBSServiceImpl implements BBSService {
List list = sql.template(msg);
if (list.isEmpty()) {
msg.setStatus(status);
- sql.insert(msg, true);
+ sql.insert(msg);
return msg;
} else {
msg = list.get(0);
@@ -141,7 +142,7 @@ public class BBSServiceImpl implements BBSService {
return query;
}
- @Cacheable(cacheNames = "bbsPostPage", keyGenerator = "pageQueryKeyGenerator")
+// @Cacheable(cacheNames = "bbsPostPage", keyGenerator = "pageQueryKeyGenerator")
@Override
public PageQuery getPosts(PageQuery query) {
postDao.getPosts(query);
@@ -178,11 +179,11 @@ public class BBSServiceImpl implements BBSService {
public void saveTopic(BbsTopic topic, BbsPost post, BbsUser user) {
topic.setUserId(user.getId());
topic.setCreateTime(new Date());
- topicDao.insert(topic, true);
+ topicDao.insert(topic);
post.setUserId(user.getId());
post.setTopicId(topic.getId());
post.setCreateTime(new Date());
- postDao.insert(post, true);
+ postDao.insert(post);
gitUserService.addTopicScore(user.getId());
}
@@ -206,7 +207,7 @@ public class BBSServiceImpl implements BBSService {
@CacheEvict(cacheNames = {"bbsPost", "bbsPostPage", "bbsFirstPost", "bbsLatestPost"}, allEntries = true)
public void savePost(BbsPost post, BbsUser user) {
post.setUserId(user.getId());
- postDao.insert(post, true);
+ postDao.insert(post);
gitUserService.addPostScore(user.getId());
}
@@ -214,7 +215,7 @@ public class BBSServiceImpl implements BBSService {
@CacheEvict(cacheNames = {"bbsReply", "bbsPostPage"}, allEntries = true)
@Override
public void saveReply(BbsReply reply) {
- replyDao.insert(reply, true);
+ replyDao.insert(reply);
gitUserService.addReplayScore(reply.getUserId());
}
@@ -306,7 +307,7 @@ public class BBSServiceImpl implements BBSService {
@Override
@Cacheable(cacheNames = "fallbackQuery", key = "#keyWord.concat(#pageNum)")
- public PageQuery queryPostByContent(String keyWord, long pageNum, long pageSize) {
+ public PageResult queryPostByContent(String keyWord, long pageNum, long pageSize) {
LambdaQuery query = sql.lambdaQuery(BbsPost.class);
if (StringUtils.isNotBlank(keyWord)) {
query.andLike(BbsPost::getContent, String.format("%%%s%%", keyWord));
diff --git a/src/main/java/com/ibeetl/bbs/service/impl/BbsUserServiceImpl.java b/src/main/java/com/ibeetl/bbs/service/impl/BbsUserServiceImpl.java
index 41ce75d0b27921df6c7ea39c4f39db4dd37ce896..e261affee543962b6b69429a7243c9085a6a5332 100644
--- a/src/main/java/com/ibeetl/bbs/service/impl/BbsUserServiceImpl.java
+++ b/src/main/java/com/ibeetl/bbs/service/impl/BbsUserServiceImpl.java
@@ -45,7 +45,7 @@ public class BbsUserServiceImpl implements BbsUserService {
@Override
public BbsUser setUserAccount(BbsUser user) {
- userDao.insert(user, true);
+ userDao.insert(user);
return user;
}
diff --git a/src/main/java/com/ibeetl/bbs/util/ExecutorUtil.java b/src/main/java/com/ibeetl/bbs/util/ExecutorUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac16b34f38b02d28cf9965ab01a0d3ba4acb1d1a
--- /dev/null
+++ b/src/main/java/com/ibeetl/bbs/util/ExecutorUtil.java
@@ -0,0 +1,17 @@
+package com.ibeetl.bbs.util;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class ExecutorUtil {
+
+ /**单线程*/
+ public static final ExecutorService LUCENE_EXECUTOR_POOL = new ThreadPoolExecutor(
+ 1,1,30, TimeUnit.SECONDS,
+ new ArrayBlockingQueue<>(1000000),
+ new ThreadPoolExecutor.AbortPolicy());
+
+
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 197d588a443d8cd77d339f558df11de952f10516..86713a35f4ae5aca6035ff6429a35c85a9a0f982 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,14 +1,15 @@
server:
- port: 8080
+ port: 8081
servlet.contextPath: /bbs
spring.datasource:
- url: jdbc:mysql://127.0.0.1:3306/bbs?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
+ url: jdbc:mysql://127.0.0.1:13306/bbs?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
username: root
- password: abcd1234
+ password: 12345678
driver-class-name: com.mysql.cj.jdbc.Driver
-
+#搜索方式:es,lucene
+search.type: lucene
#Elasticsearch
#spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
@@ -19,10 +20,13 @@ elasticsearch.bbs:
content-search-url: http://127.0.0.1:9200/bbs/content/_search
beetl.suffix: html
-beetl-beetlsql.dev: true
-beetlsql:
- mutiple.datasource: dataSource
- ds.dataSource.basePackage: com.ibeetl.bbs.dao
+
+beetlsql: sqlManager1
+beetlsql.sqlManager1:
+ ds: dataSource
+ basePackage: com.ibeetl.bbs.dao
+ daoSuffix: Dao
+
bbs.user:
diff --git a/src/main/resources/sql/bbsModule.md b/src/main/resources/sql/bbsModule.md
index 71b487fd26e842acdf8d72da217a9ef54c4d8564..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/src/main/resources/sql/bbsModule.md
+++ b/src/main/resources/sql/bbsModule.md
@@ -1,30 +0,0 @@
-sample
-===
-* 注释
-
- select #use("cols")# from bbs_module where #use("condition")#
-
-cols
-===
-
- id,name,detail,turn
-
-updateSample
-===
-
- `id`=#id#,`name`=#name#,`detail`=#detail#,`turn`=#turn#
-
-condition
-===
-
- 1 = 1
- @if(!isEmpty(name)){
- and `name`=#name#
- @}
- @if(!isEmpty(detail)){
- and `detail`=#detail#
- @}
- @if(!isEmpty(turn)){
- and `turn`=#turn#
- @}
-
diff --git a/src/main/resources/sql/bbsPost.md b/src/main/resources/sql/bbsPost.md
index e86f3df83cea68fb917ccbd952cb29e12219d695..4e96f91e521b6b1319acfe816ac0b41c672a746a 100644
--- a/src/main/resources/sql/bbsPost.md
+++ b/src/main/resources/sql/bbsPost.md
@@ -1,60 +1,21 @@
getPosts
===
select
- @pageTag(){
+ -- @pageTag(){
*
- @}
+ -- @}
from bbs_post where true
- @if(!isEmpty(topicId)){
- and `topic_id`=#topicId#
- @}
- @if(!isEmpty(isAdmin)){
+ -- @if(!isEmpty(topicId)){
+ and `topic_id`=#{topicId}
+ -- @}
+ -- @if(!isEmpty(isAdmin)){
order by id desc
- @}
- @ orm.single({"userId":"id"},"BbsUser");
- @ orm.single({"topicId":"id"},"BbsTopic");
+ -- @}
+
deleteByTopicId
===
- delete from bbs_post where `topic_id`=#topicId#
+ delete from bbs_post where `topic_id`=#{topicId}
-sample
-===
-* 注释
-
- select #use("cols")# from bbs_post where #use("condition")#
-
-cols
-===
-
- id,topic_id,user_id,content,create_time,has_reply,update_time
-
-updateSample
-===
-
- `id`=#id#,`topic_id`=#topicId#,`user_id`=#userId#,`content`=#content#,`create_time`=#createTime#,`has_reply`=#hasReply#,`update_time`=#updateTime#
-
-condition
-===
-
- 1 = 1
- @if(!isEmpty(topicId)){
- and `topic_id`=#topicId#
- @}
- @if(!isEmpty(userId)){
- and `user_id`=#userId#
- @}
- @if(!isEmpty(content)){
- and `content`=#content#
- @}
- @if(!isEmpty(createTime)){
- and `create_time`=#createTime#
- @}
- @if(!isEmpty(hasReply)){
- and `has_reply`=#hasReply#
- @}
- @if(!isEmpty(updateTime)){
- and `update_time`=#updateTime#
- @}
diff --git a/src/main/resources/sql/bbsReply.md b/src/main/resources/sql/bbsReply.md
index 3df705e8569a45edaab12e271185afc1d2f3d211..58aa38dae64d16915e09770d232c5ada6e131ad8 100644
--- a/src/main/resources/sql/bbsReply.md
+++ b/src/main/resources/sql/bbsReply.md
@@ -2,55 +2,18 @@ allReply
===
select *
from bbs_reply where true
- @if(!isEmpty(postId)){
- and `post_id`=#postId#
- @}
- @if(!isEmpty(isAdmin)){
+ -- @if(!isEmpty(postId)){
+ and `post_id`=#{postId}
+ -- @}
+ -- @if(!isEmpty(isAdmin)){
order by id desc
- @}
- @ orm.single({"userId":"id"},"BbsUser");
+ -- @}
deleteByTopicId
===
- delete from bbs_reply where `topic_id`=#topicId#
+ delete from bbs_reply where `topic_id`=#{topicId}
deleteByPostId
===
- delete from bbs_reply where `post_id`=#postId#
-sample
-===
-* 注释
-
- select #use("cols")# from bbs_reply where #use("condition")#
-
-cols
-===
-
- id,topic_id,post_id,user_id,content,create_time
-
-updateSample
-===
-
- `id`=#id#,`topic_id`=#topicId#,`post_id`=#postId#,`user_id`=#userId#,`content`=#content#,`create_time`=#createTime#
-
-condition
-===
-
- 1 = 1
- @if(!isEmpty(topicId)){
- and `topic_id`=#topicId#
- @}
- @if(!isEmpty(postId)){
- and `post_id`=#postId#
- @}
- @if(!isEmpty(userId)){
- and `user_id`=#userId#
- @}
- @if(!isEmpty(content)){
- and `content`=#content#
- @}
- @if(!isEmpty(createTime)){
- and `create_time`=#createTime#
- @}
-
+ delete from bbs_reply where `post_id`=#{postId}
diff --git a/src/main/resources/sql/bbsTopic.md b/src/main/resources/sql/bbsTopic.md
index 5f1f0c5dfbd2e67f479ddebd3089e349663e1ff6..a00758b84d5e8bde168b34c600aa361eb8bbeb6a 100644
--- a/src/main/resources/sql/bbsTopic.md
+++ b/src/main/resources/sql/bbsTopic.md
@@ -1,55 +1,55 @@
queryTopic
===
select
- @pageTag(){
+ -- @pageTag(){
t.*,m.name module_name,u.user_name user_name
- @}
+ -- @}
FROM bbs_topic t left join bbs_module m
on t.module_id = m.id left join bbs_user u on t.user_id=u.id
where true
- @var type = type!"normal";
- @if(!isEmpty(moduleId)){
- and `module_id`=#moduleId#
- @}
- @if(!isEmpty(keyword)){
- and content like #'%'+keyword+'%'#
- @}
- @if("normal" == type){
+ -- @var type = type!"normal";
+ -- @if(!isEmpty(moduleId)){
+ and `module_id`=#{moduleId}
+ -- @}
+ -- @if(!isEmpty(keyword)){
+ and content like #{'%'+keyword+'%'}
+ -- @}
+ -- @if("normal" == type){
order by is_up desc,create_time desc
- @}
- @if("hot" == type){
+ -- @}
+ -- @if("hot" == type){
order by pv desc
- @}
- @if("nice" == type){
+ -- @}
+ -- @if("nice" == type){
and is_nice=true order by create_time desc
- @}
+ -- @}
queryMyMessageTopic
===
SELECT t.* FROM bbs_message m left join bbs_topic t
- on m.topic_id= t.id where m.user_id=#userId# and status = 1
+ on m.topic_id= t.id where m.user_id=#{userId} and status = 1
queryMyMessageTopicCount
===
SELECT count(1) from bbs_message m
- where m.user_id=#userId# and status = 1
+ where m.user_id=#{userId} and status = 1
queryHotTopic
===
select
- @pageTag(){
+ -- @pageTag(){
*
- @}
+ -- @}
from bbs_topic order by pv desc
queryNiceTopic
===
select
- @pageTag(){
+ -- @pageTag(){
*
- @}
+ -- @}
from bbs_topic where is_nice=true order by create_time desc
getTopicAndPostCount
@@ -57,7 +57,7 @@ getTopicAndPostCount
* 根据id查找topic和拥有的post数量
- select t.*,(select count(1) from bbs_post where topic_id=#id#) post_count from bbs_topic t where t.id =#id#
+ select t.*,(select count(1) from bbs_post where topic_id=#{id}) post_count from bbs_topic t where t.id =#{id}
getParticipantUserId
@@ -65,23 +65,18 @@ getParticipantUserId
* 查询某个帖子的参与恩,包含post和reply俩种,用于群发通知
- select user_id from bbs_post where topic_id = #topicId#
+ select user_id from bbs_post where topic_id = #{topicId}
union
- select user_id from bbs_post where topic_id= #topicId#
+ select user_id from bbs_post where topic_id= #{topicId}
getTopic
===
*查询主题帖
- SELECT * FROM bbs_topic WHERE id= #topicId#
-
- @orm.single({"userId":"id"},"BbsUser",{"alias":"user"});
-
- @orm.single({"moduleId":"id"},"BbsModule",{"alias":"module"});
-
+ SELECT * FROM bbs_topic WHERE id= #{topicId}
diff --git a/src/main/resources/sql/bbsUser.md b/src/main/resources/sql/bbsUser.md
index b720d979d99b5f3ca85ad09ae408e993a4e2fc86..f9e97877ac1367be59a8388fa39df5e4960c5e2f 100644
--- a/src/main/resources/sql/bbsUser.md
+++ b/src/main/resources/sql/bbsUser.md
@@ -4,13 +4,13 @@ getScoreTop
* 得到积分最高的前N个用户
- select * from bbs_user order by score desc limit #max#
+ select * from bbs_user order by score desc limit #{max}
getLeveTop
===
- select * from bbs_user order by level desc,score desc limit #max#
+ select * from bbs_user order by level desc,score desc limit #{max}
diff --git a/src/main/resources/stopwords.txt b/src/main/resources/stopwords.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b2f417745ea3d1fc08b7e4ceee02811683df7d75
--- /dev/null
+++ b/src/main/resources/stopwords.txt
@@ -0,0 +1,1492 @@
+
+?
+、
+。
+“
+”
+《
+》
+!
+!
+,
+,
+:
+:
+;
+?
+-
+(
+)
+(
+)
+·
+--
+……
+/
+.
+|
+——
+‘
+’
+□
+【
+】
+A
+B
+C
+D
+啊
+阿
+哎
+哎呀
+哎哟
+唉
+俺
+俺们
+按
+按照
+吧
+吧哒
+把
+罢了
+被
+本
+本着
+比
+比方
+比如
+鄙人
+彼
+彼此
+边
+别
+别的
+别说
+并
+并且
+不比
+不成
+不单
+不但
+不独
+不管
+不光
+不过
+不仅
+不拘
+不论
+不怕
+不然
+不如
+不特
+不惟
+不问
+不只
+朝
+朝着
+趁
+趁着
+乘
+冲
+除
+除此之外
+除非
+除了
+此
+此间
+此外
+从
+从而
+出
+打
+待
+但
+但是
+当
+当着
+到
+得
+的
+的话
+等
+等等
+地
+第
+叮咚
+对
+对于
+多
+多少
+而
+而况
+而且
+而是
+而外
+而言
+而已
+尔后
+反过来
+反过来说
+反之
+非但
+非徒
+否则
+嘎
+嘎登
+刚
+刚刚
+该
+赶
+个
+各
+各个
+各位
+各种
+各自
+给
+根据
+跟
+故
+故此
+固然
+关于
+管
+归
+果然
+果真
+过
+哈
+哈哈
+呵
+和
+何
+何处
+何况
+何时
+嘿
+哼
+哼唷
+呼哧
+乎
+哗
+还是
+还有
+换句话说
+换言之
+或
+或是
+或者
+极了
+及
+及其
+及至
+即
+即便
+即或
+即令
+即若
+即使
+几
+几时
+己
+既
+既然
+既是
+继而
+加之
+假如
+假若
+假使
+鉴于
+将
+较
+较之
+叫
+接着
+结果
+借
+紧接着
+进而
+尽
+尽管
+经
+经过
+就
+就是
+就是说
+据
+具体地说
+具体说来
+开始
+开外
+靠
+咳
+可
+可见
+可是
+可以
+况且
+啦
+来
+来着
+离
+例如
+哩
+连
+连同
+两者
+了
+临
+另
+另外
+另一方面
+论
+嘛
+吗
+慢说
+漫说
+冒
+么
+每
+每当
+们
+莫若
+某
+某个
+某些
+拿
+哪
+哪边
+哪儿
+哪个
+哪里
+哪年
+哪怕
+哪天
+哪些
+哪样
+那
+那边
+那儿
+那个
+那会儿
+那里
+那么
+那么些
+那么样
+那时
+那些
+那样
+乃
+乃至
+呢
+能
+你
+你们
+您
+宁
+宁可
+宁肯
+宁愿
+哦
+呕
+啪达
+旁人
+呸
+凭
+凭借
+其
+其次
+其二
+其他
+其它
+其一
+其余
+其中
+却
+去
+起
+起见
+起见
+岂但
+恰恰相反
+前后
+前者
+且
+然而
+然后
+然则
+让
+人家
+任
+任何
+任凭
+如
+如此
+如果
+如何
+如其
+如若
+如上所述
+若
+若非
+若是
+啥
+上下
+尚且
+设若
+设使
+甚而
+甚么
+甚至
+省得
+时候
+十分
+什么
+什么样
+使得
+是
+是的
+首先
+谁
+谁知
+顺
+顺着
+似的
+虽
+虽然
+虽说
+虽则
+随
+随着
+所
+所以
+他
+他们
+他人
+它
+它们
+她
+她们
+倘
+倘或
+倘然
+倘若
+倘使
+腾
+替
+通过
+同
+同时
+哇
+万一
+往
+望
+为
+为何
+为了
+为什么
+为着
+喂
+嗡嗡
+我
+我们
+呜
+呜呼
+乌乎
+无论
+无宁
+毋宁
+嘻
+吓
+相对而言
+像
+向
+向着
+嘘
+呀
+焉
+沿
+沿着
+要
+要不
+要不然
+要不是
+要么
+要是
+也
+也罢
+也好
+一一
+———
+一般
+一边
+一会儿
+一旦
+一定
+一点点
+一方面
+一面
+一来
+一起
+一切
+一下
+一下子
+一样
+一些
+一则
+一直
+依
+依照
+矣
+以
+以便
+以及
+以免
+以至
+以至于
+以致
+抑或
+因
+因此
+因而
+因为
+哟
+用
+由
+由此可见
+由于
+有
+有的
+有关
+有些
+又
+于
+于是
+于是乎
+与
+与此同时
+与否
+与其
+越是
+云云
+哉
+再说
+再者
+在
+在下
+咱
+咱们
+则
+怎
+怎么
+怎么办
+怎么样
+怎样
+咋
+照
+照着
+者
+这
+这边
+这儿
+这个
+这会儿
+这就是说
+这里
+这么
+这么点儿
+这么些
+这么样
+这时
+这些
+这样
+正如
+吱
+之
+之类
+之所以
+之一
+只是
+只限
+只要
+只有
+至
+至于
+诸位
+着
+着呢
+自
+自从
+自个儿
+自各儿
+自己
+自家
+自身
+综上所述
+总的来看
+总的来说
+总的说来
+总而言之
+总之
+纵
+纵令
+纵然
+纵使
+遵照
+作为
+兮
+呃
+呗
+咚
+咦
+喏
+啐
+喔唷
+嗬
+嗯
+嗳
+上
+下
+不
+不再
+不同
+不少
+一
+二
+两
+三
+四
+五
+六
+七
+八
+九
+十
+个人
+中
+之前
+之后
+之外
+之间
+也许
+人
+前
+前天
+今天
+今年
+明天
+明年
+后天
+去年
+从来
+令
+以下
+以前
+以后
+以往
+以来
+份
+件
+伏
+众
+众多
+会
+位
+做
+停
+顶
+先
+先前
+全
+公司
+公斤
+其实
+内
+已
+再
+小
+大
+还
+里
+都
+部
+遍
+道
+说
+第一
+第二
+第三
+第四
+第五
+第六
+第七
+第八
+第九
+第十
+只
+后
+太
+大家
+女
+男
+看
+新浪
+年
+很
+才
+时
+更
+最
+本报
+讯
+记者
+演
+片
+一
+一下
+一些
+一切
+一则
+一天
+一定
+一方面
+一旦
+一时
+一来
+一样
+一次
+一片
+一直
+一致
+一般
+一起
+一边
+一面
+万一
+上下
+上升
+上去
+上来
+上述
+上面
+下列
+下去
+下来
+下面
+不一
+不久
+不仅
+不会
+不但
+不光
+不单
+不变
+不只
+不可
+不同
+不够
+不如
+不得
+不怕
+不惟
+不成
+不拘
+不敢
+不断
+不是
+不比
+不然
+不特
+不独
+不管
+不能
+不要
+不论
+不足
+不过
+不问
+与
+与其
+与否
+与此同时
+专门
+且
+两者
+严格
+严重
+个
+个人
+个别
+中小
+中间
+丰富
+临
+为
+为主
+为了
+为什么
+为什麽
+为何
+为着
+主张
+主要
+举行
+乃
+乃至
+么
+之
+之一
+之前
+之后
+之後
+之所以
+之类
+乌乎
+乎
+乘
+也
+也好
+也是
+也罢
+了
+了解
+争取
+于
+于是
+于是乎
+云云
+互相
+产生
+人们
+人家
+什么
+什么样
+什麽
+今后
+今天
+今年
+今後
+仍然
+从
+从事
+从而
+他
+他人
+他们
+他的
+代替
+以
+以上
+以下
+以为
+以便
+以免
+以前
+以及
+以后
+以外
+以後
+以来
+以至
+以至于
+以致
+们
+任
+任何
+任凭
+任务
+企图
+伟大
+似乎
+似的
+但
+但是
+何
+何况
+何处
+何时
+作为
+你
+你们
+你的
+使得
+使用
+例如
+依
+依照
+依靠
+促进
+保持
+俺
+俺们
+倘
+倘使
+倘或
+倘然
+倘若
+假使
+假如
+假若
+做到
+像
+允许
+充分
+先后
+先後
+先生
+全部
+全面
+兮
+共同
+关于
+其
+其一
+其中
+其二
+其他
+其余
+其它
+其实
+其次
+具体
+具体地说
+具体说来
+具有
+再者
+再说
+冒
+冲
+决定
+况且
+准备
+几
+几乎
+几时
+凭
+凭借
+出去
+出来
+出现
+分别
+则
+别
+别的
+别说
+到
+前后
+前者
+前进
+前面
+加之
+加以
+加入
+加强
+十分
+即
+即令
+即使
+即便
+即或
+即若
+却不
+原来
+又
+及
+及其
+及时
+及至
+双方
+反之
+反应
+反映
+反过来
+反过来说
+取得
+受到
+变成
+另
+另一方面
+另外
+只是
+只有
+只要
+只限
+叫
+叫做
+召开
+叮咚
+可
+可以
+可是
+可能
+可见
+各
+各个
+各人
+各位
+各地
+各种
+各级
+各自
+合理
+同
+同一
+同时
+同样
+后来
+后面
+向
+向着
+吓
+吗
+否则
+吧
+吧哒
+吱
+呀
+呃
+呕
+呗
+呜
+呜呼
+呢
+周围
+呵
+呸
+呼哧
+咋
+和
+咚
+咦
+咱
+咱们
+咳
+哇
+哈
+哈哈
+哉
+哎
+哎呀
+哎哟
+哗
+哟
+哦
+哩
+哪
+哪个
+哪些
+哪儿
+哪天
+哪年
+哪怕
+哪样
+哪边
+哪里
+哼
+哼唷
+唉
+啊
+啐
+啥
+啦
+啪达
+喂
+喏
+喔唷
+嗡嗡
+嗬
+嗯
+嗳
+嘎
+嘎登
+嘘
+嘛
+嘻
+嘿
+因
+因为
+因此
+因而
+固然
+在
+在下
+地
+坚决
+坚持
+基本
+处理
+复杂
+多
+多少
+多数
+多次
+大力
+大多数
+大大
+大家
+大批
+大约
+大量
+失去
+她
+她们
+她的
+好的
+好象
+如
+如上所述
+如下
+如何
+如其
+如果
+如此
+如若
+存在
+宁
+宁可
+宁愿
+宁肯
+它
+它们
+它们的
+它的
+安全
+完全
+完成
+实现
+实际
+宣布
+容易
+密切
+对
+对于
+对应
+将
+少数
+尔后
+尚且
+尤其
+就
+就是
+就是说
+尽
+尽管
+属于
+岂但
+左右
+巨大
+巩固
+己
+已经
+帮助
+常常
+并
+并不
+并不是
+并且
+并没有
+广大
+广泛
+应当
+应用
+应该
+开外
+开始
+开展
+引起
+强烈
+强调
+归
+当
+当前
+当时
+当然
+当着
+形成
+彻底
+彼
+彼此
+往
+往往
+待
+後来
+後面
+得
+得出
+得到
+心里
+必然
+必要
+必须
+怎
+怎么
+怎么办
+怎么样
+怎样
+怎麽
+总之
+总是
+总的来看
+总的来说
+总的说来
+总结
+总而言之
+恰恰相反
+您
+意思
+愿意
+慢说
+成为
+我
+我们
+我的
+或
+或是
+或者
+战斗
+所
+所以
+所有
+所谓
+打
+扩大
+把
+抑或
+拿
+按
+按照
+换句话说
+换言之
+据
+掌握
+接着
+接著
+故
+故此
+整个
+方便
+方面
+旁人
+无宁
+无法
+无论
+既
+既是
+既然
+时候
+明显
+明确
+是
+是否
+是的
+显然
+显著
+普通
+普遍
+更加
+曾经
+替
+最后
+最大
+最好
+最後
+最近
+最高
+有
+有些
+有关
+有利
+有力
+有所
+有效
+有时
+有点
+有的
+有着
+有著
+望
+朝
+朝着
+本
+本着
+来
+来着
+极了
+构成
+果然
+果真
+某
+某个
+某些
+根据
+根本
+欢迎
+正在
+正如
+正常
+此
+此外
+此时
+此间
+毋宁
+每
+每个
+每天
+每年
+每当
+比
+比如
+比方
+比较
+毫不
+没有
+沿
+沿着
+注意
+深入
+清楚
+满足
+漫说
+焉
+然则
+然后
+然後
+然而
+照
+照着
+特别是
+特殊
+特点
+现代
+现在
+甚么
+甚而
+甚至
+用
+由
+由于
+由此可见
+的
+的话
+目前
+直到
+直接
+相似
+相信
+相反
+相同
+相对
+相对而言
+相应
+相当
+相等
+省得
+看出
+看到
+看来
+看看
+看见
+真是
+真正
+着
+着呢
+矣
+知道
+确定
+离
+积极
+移动
+突出
+突然
+立即
+第
+等
+等等
+管
+紧接着
+纵
+纵令
+纵使
+纵然
+练习
+组成
+经
+经常
+经过
+结合
+结果
+给
+绝对
+继续
+继而
+维持
+综上所述
+罢了
+考虑
+者
+而
+而且
+而况
+而外
+而已
+而是
+而言
+联系
+能
+能否
+能够
+腾
+自
+自个儿
+自从
+自各儿
+自家
+自己
+自身
+至
+至于
+良好
+若
+若是
+若非
+范围
+莫若
+获得
+虽
+虽则
+虽然
+虽说
+行为
+行动
+表明
+表示
+被
+要
+要不
+要不是
+要不然
+要么
+要是
+要求
+规定
+觉得
+认为
+认真
+认识
+让
+许多
+论
+设使
+设若
+该
+说明
+诸位
+谁
+谁知
+赶
+起
+起来
+起见
+趁
+趁着
+越是
+跟
+转动
+转变
+转贴
+较
+较之
+边
+达到
+迅速
+过
+过去
+过来
+运用
+还是
+还有
+这
+这个
+这么
+这么些
+这么样
+这么点儿
+这些
+这会儿
+这儿
+这就是说
+这时
+这样
+这点
+这种
+这边
+这里
+这麽
+进入
+进步
+进而
+进行
+连
+连同
+适应
+适当
+适用
+逐步
+逐渐
+通常
+通过
+造成
+遇到
+遭到
+避免
+那
+那个
+那么
+那么些
+那么样
+那些
+那会儿
+那儿
+那时
+那样
+那边
+那里
+那麽
+部分
+鄙人
+采取
+里面
+重大
+重新
+重要
+鉴于
+问题
+防止
+阿
+附近
+限制
+除
+除了
+除此之外
+除非
+随
+随着
+随著
+集中
+需要
+非但
+非常
+非徒
+靠
+顺
+顺着
+首先
+高兴
+是不是
+说说
+索尼
+n1
+ap
+xba
+大法
\ No newline at end of file
diff --git a/src/main/resources/templates/common/layout.html b/src/main/resources/templates/common/layout.html
index 909fb8f2a37fcb3cf08544cacf10f157240cea9e..9a4bad10752cb93111b356a3d0c595ef9f20d7f2 100644
--- a/src/main/resources/templates/common/layout.html
+++ b/src/main/resources/templates/common/layout.html
@@ -110,7 +110,7 @@
你已有${_user.score}积分
等级:${level(_user.level)}
@if(isAdmin){
- 初始化ES索引
+ 初始化文章索引
@}
给我的回复
diff --git a/src/main/resources/templates/common/replyItem.html b/src/main/resources/templates/common/replyItem.html
index d90e4bebe4233402d5dcedcebf67b3bfa9cd44e2..448aeef1e8bdebe7ec4aaf1c6e2297f703caaa7a 100644
--- a/src/main/resources/templates/common/replyItem.html
+++ b/src/main/resources/templates/common/replyItem.html
@@ -1,5 +1,5 @@
@if(showbtn){
@}
-${reply.bbsUser.userName}
+${reply.user.userName}
:${reply.content,xss}(${printTime(reply.createTime)})
\ No newline at end of file
diff --git a/src/main/resources/templates/lucene/lucene.html b/src/main/resources/templates/lucene/lucene.html
index fc42a11ddd83950d2e559271d096b75091e891bf..3f71ea6f6d39459d1c7fa3a877dbe2cbb422abf7 100644
--- a/src/main/resources/templates/lucene/lucene.html
+++ b/src/main/resources/templates/lucene/lucene.html
@@ -42,7 +42,7 @@
@if(isAdmin){
-
+
精华
置顶
删除
@@ -55,4 +55,22 @@
@}
<#page query="${searcherPage}"/>
+
@}