1.sql数据表建立:
一开始使用varchar型的,后来感觉不行,只有重新写成int 自增的,自增在数据库里设置吧
CREATE TABLE CHATMAN_KNOWLEDGE(
K_ID INTEGER NOT NULL,
QUESTION VARCHAR(2000),
ANSWER VARCHAR(8000),
CATEGORY INT,
PRIMARY KEY(K_ID)
);
alter tablle CHATMAN_KNOWLEDGE
add id INTEGER ;
CREATE TABLE CHATMAN_KNSUB(
KN_ID INTEGER identity(1,1) primary key, --主键自增长
K_ID INTEGER,
ANSWER VARCHAR(8000)
/*PRIMARY KEY(KN_ID)*/
)
CREATE TABLE CHATMAN_JOKE(
J_ID VARCHAR(32),
CONTENT VARCHAR(5000),
PRIMARY KEY(J_ID)
)
CREATE TABLE CHATMAN_CHAT_LOG(
CL_ID VARCHAR(32) NOT NULL,
W_ID VARCHAR(100) NOT NULL,
CREATE_TIME DATETIME,
REG_MSG VARCHAR(2000),
RESP_MSG VARCHAR(2000),
CHAT_CATEGORY INT,
PRIMARY KEY(CL_ID)
)
2.数据库crud
3.服务chatService
package com.dm.wx.service;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Random;
import com.dm.chatman.domain.ChatLog;
import com.dm.chatman.domain.Knowledge;
import com.dm.chatman.service.ChatLogService;
import com.dm.chatman.service.JokeService;
import com.dm.chatman.service.KnowledgeService;
import com.dm.chatman.service.KnsubService;
import com.dm.core.service.BaseService;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
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.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.wltea.analyzer.lucene.IKAnalyzer;
import org.apache.lucene.util.Version;
import java.io.File;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 15-5-25
* Time: 上午6:21
* To change this template use File | Settings | File Templates.
*/
@Service("wxChatService")
@Transactional(isolation = Isolation.READ_COMMITTED, readOnly = true, rollbackFor = Throwable.class)
public class ChatService extends BaseService {
@Autowired
@Qualifier("chatmanKnowledgeService")
private KnowledgeService knowledgeService;
@Autowired
@Qualifier("chatmanJokeService")
private JokeService jokeService;
@Autowired
@Qualifier("chatmanChatLogService")
private ChatLogService chatLogService;
@Autowired
@Qualifier("chatmanKnsubService")
private KnsubService knsubService;
public static String getIndexDir() {
// 得到.class文件所在路径(WEB-INF/classes/)
String classpath = ChatService.class.getResource("/").getPath();
// 将classpath中的%20替换为空格
classpath = classpath.replaceAll("%20", " ");
// 索引存储位置:WEB-INF/classes/index/
return classpath + "index/";
}
/**
* 创建索引
*/
public void createIndex() throws Exception{
// 取得问答知识库中的所有记录
List<Knowledge> knowledgeList = knowledgeService.list();
Directory directory = null;
IndexWriter indexWriter = null;
try {
directory = FSDirectory.open(new File(getIndexDir()));
IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_46, new IKAnalyzer(true));
indexWriter = new IndexWriter(directory, iwConfig);
Document doc = null;
// 遍历问答知识库创建索引
for (Knowledge knowledge : knowledgeList) {
doc = new Document();
// 对question进行分词存储
doc = new Document();
// 对question进行分词存储
doc.add(new TextField("question", knowledge.getQuestion(), Store.YES));
// 对id、answer和category不分词存储
doc.add(new IntField("id", knowledge.getK_id(), Store.YES));
doc.add(new StringField("answer", knowledge.getAnswer(), Store.YES));
doc.add(new IntField("category", knowledge.getCategory(), Store.YES));
indexWriter.addDocument(doc);
}
indexWriter.close();
directory.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 从索引文件中根据问题检索答案
*
* @param content
* @return Knowledge
*/
@SuppressWarnings("deprecation")
private static Knowledge searchIndex(String content) {
Knowledge knowledge = null;
try {
Directory directory = FSDirectory.open(new File(getIndexDir()));
IndexReader reader = IndexReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
// 使用查询解析器创建Query
QueryParser questParser = new QueryParser(Version.LUCENE_46, "question", new IKAnalyzer(true));
Query query = questParser.parse(QueryParser.escape(content));
// 检索得分最高的文档
TopDocs topDocs = searcher.search(query, 1);
if (topDocs.totalHits > 0) {
knowledge = new Knowledge();
ScoreDoc[] scoreDoc = topDocs.scoreDocs;
for (ScoreDoc sd : scoreDoc) {
Document doc = searcher.doc(sd.doc);
knowledge.setK_id(doc.getField("id").numericValue().intValue());
knowledge.setQuestion(doc.get("question"));
knowledge.setAnswer(doc.get("answer"));
knowledge.setCategory(doc.getField("category").numericValue().intValue());
}
}
reader.close();
directory.close();
} catch (Exception e) {
knowledge = null;
e.printStackTrace();
}
return knowledge;
}
/**
* 聊天方法(根据question返回answer)
*
* @param openId 用户的OpenID
* @param createTime 消息创建时间
* @param question 用户上行的问题
* @return answer
*/
public String chat(String openId, String createTime, String question) throws Exception{
String answer = null;
int chatCategory = 0;
Knowledge knowledge = searchIndex(question);
// 找到匹配项
if (null != knowledge) {
// 笑话
if (2 == knowledge.getCategory()) {
answer = jokeService.querymyJoke().getContent();
chatCategory = 2;
}
// 上下文
else if (3 == knowledge.getCategory()) {
// 判断上一次的聊天类别
int category = chatLogService.getLastCategory(openId).getChat_category();
// 如果是笑话,本次继续回复笑话给用户
if (2 == category) {
answer = jokeService.querymyJoke().getContent();
chatCategory = 2;
} else {
answer = knowledge.getAnswer();
chatCategory = knowledge.getCategory();
}
}
// 普通对话
else {
answer = knowledge.getAnswer();
// 如果答案为空,根据知识id从问答知识分表中随机获取一条
if ("".equals(answer))
answer = knsubService.getKnowledSub(knowledge.getK_id()).getAnswer();
chatCategory = 1;
}
}
// 未找到匹配项
else {
answer = getDefaultAnswer();
chatCategory = 0;
}
// 保存聊天记录
ChatLog chatLog = new ChatLog();
chatLog.setW_id(openId);
chatLog.setCreate_time(new Date());
chatLog.setReg_msg(question);
chatLog.setResp_msg(answer);
chatLog.setChat_category(chatCategory);
chatLogService.create(chatLog);
return answer;
}
/**
* 随机获取一个默认的答案
*
* @return
*/
private static String getDefaultAnswer() {
String []answer = {
"要不我们聊点别的?",
"恩?你到底在说什么呢?",
"没有听懂你说的,能否换个说法?",
"虽然不明白你的意思,但我却能用心去感受",
"听的我一头雾水,阁下的知识真是渊博呀,膜拜~",
"真心听不懂你在说什么,要不你换种表达方式如何?",
"哎,我小学语文是体育老师教的,理解起来有点困难哦",
"是世界变化太快,还是我不够有才?为何你说话我不明白?"
};
return answer[getRandomNumber(answer.length)];
}
/**
* 随机生成 0~length-1 之间的某个值
*
* @return int
*/
private static int getRandomNumber(int length) {
Random random = new Random();
return random.nextInt(length);
}
}
4.配置索引
private ChatService chatService;
public void init(ServletConfig config) throws ServletException {
System.out.print("初始化servelt成功");
File indexDir = new File(ChatService.getIndexDir());
// 如果索引目录不存在则创建索引
if (!indexDir.exists()) {
try{
chatService.createIndex();
}catch (Exception e){
System.out.print("创建索引异常");
}
}
this.config = config;
}
5.设置web.xnl每次首先加载
<servlet>
<servlet-name>coreServlet</servlet-name>
<servlet-class>com.dm.wx.HttpServletProxy</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<!--<servlet>-->
<!--<servlet-name>coreServlet</servlet-name>-->
<!--<servlet-class>com.dm.wx.controller.CoreServlet</servlet-class>-->
<!--</servlet>-->
<servlet-mapping>
<servlet-name>coreServlet</servlet-name>
<url-pattern>/coreServlet</url-pattern>
</servlet-mapping>
6.添加和修改数据表,删除索引,重新启动就可以加载添加的数据索引了,自动化查询时挺有用的。
大家可参考我的博客:
我的博客:115.159.110.224
我的微信公众号:my528xx
公众号二维码: