2019/7/5 18:05 未完待续.....(其实是下班了,回去再写)
目前项目的目录(可能会有所改动),详细代码见我的GithubSunAlwaysOnline/kq
以下是我用到的依赖
MyBatis-plus:是MyBatis的增强版,封装了一些常用的sql方法,我们设置可以不用在dao、service与mapper文件编写方法。
Redis:内存型数据库,我把查询出来的垃圾分类存储在Redis中,提高查询效率。
Jsoup:请求外部的垃圾分类接口时,返回的是Html页面,因此需要对页面进行抓取数据。
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE
com.sun
kq
1.0
kq
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
com.baomidou
mybatis-plus-boot-starter
3.0.1
mysql
mysql-connector-java
5.1.38
org.springframework.boot
spring-boot-starter-data-redis
org.jsoup
jsoup
1.11.3
org.springframework.boot
spring-boot-maven-plugin
配置MyBatis-plus与RestTemplate(SpringBoot中用来发送HTTP请求)
MybatisPlusConfig.java(分页暂时没用到,但在数据量过多时会用到,先给配置上)
package com.sun.kq.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.sun.kq.dao")
public class MybatisPlusConfig {
/**
* 分页插件
*
* @return PaginationInterceptor
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
paginationInterceptor.setDialectType(DbType.MYSQL.getDb());
return paginationInterceptor;
}
/**
* 逻辑删除插件
*
* @return LogicSqlInjector
*/
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
}
RestTemplateConfig.java
package com.sun.kq.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* RestTemplate配置类
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//ms
factory.setConnectTimeout(15000);//ms
return factory;
}
}
常量类(主要保存请求地址)
URLConst.java
package com.sun.kq.constant;
public class URLConst {
/**
* HTTP服务器地址
*/
public static final String URL = "http://127.0.0.1:5700";
/**
* 发送私聊消息
*/
public static final String SEND_PRIVATE_MSG = "/send_private_msg";
/**
* 获取群列表
*/
public static final String GET_GROUP_LIST = "/get_group_list";
/**
* 获取该垃圾的分类,后面加垃圾名称的URL编码
*/
public static final String GET_RUBBISH_TYPE = "https://lajifenleiapp.com/sk/";
}
编写消息上报的接口,用来接收QQ里收到的消息
MsgController.java(主要是看/receive接口)
/msg/receive接口我们在插件中已经配置过,酷Q收到消息后,cqhhtp插件调用其sdk获取消息,然后像本机的8080/msg/receive接口上报酷Q收到的消息,这种方式实现了跨语言使用酷Q的方式。
package com.sun.kq.controller;
import com.sun.kq.model.PrivateMsg;
import com.sun.kq.model.ReplyMsg;
import com.sun.kq.model.Result;
import com.sun.kq.service.MsgService;
import com.sun.kq.service.PrivateMsgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/msg")
public class MsgController {
@Autowired
MsgService msgService;
/**
* 消息上报接口
*
* @param request
*/
@RequestMapping("/receive")
public ReplyMsg receive(HttpServletRequest request) {
return msgService.receive(request);
}
}
MsgService.java
package com.sun.kq.service;
import com.sun.kq.model.PrivateMsg;
import com.sun.kq.model.ReplyMsg;
import com.sun.kq.model.Result;
import javax.servlet.http.HttpServletRequest;
public interface MsgService {
/**
* 接收消息(私聊、群、讨论组、其他)并响应
*
* @param request
* @return
*/
ReplyMsg receive(HttpServletRequest request);
}
他的实现类MsgServiceImpl.java(主要看recevie方法)
package com.sun.kq.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.kq.entity.Keyword;
import com.sun.kq.entity.Rubbish;
import com.sun.kq.model.PrivateMsg;
import com.sun.kq.model.ReceiveMsg;
import com.sun.kq.model.ReplyMsg;
import com.sun.kq.model.Result;
import com.sun.kq.service.*;
import com.sun.kq.util.KeywordsUtil;
import com.sun.kq.util.MsgUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.stream.Collectors;
import static com.sun.kq.constant.URLConst.*;
@Service
public class MsgServiceImpl implements MsgService {
@Autowired
RestTemplate restTemplate;
@Autowired
RubbishService rubbishService;
@Autowired
KeywordService keywordService;
@Autowired
PrivateMsgService privateMsgService;
@Autowired
GroupMsgService groupMsgService;
@Override
public ReplyMsg receive(HttpServletRequest request) {
String msg = null;
try {
msg = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
System.out.println(msg);
} catch (IOException e) {
e.printStackTrace();
}
if (msg == null) {
return null;
}
//解析收到的消息
ReceiveMsg receiveMsg = null;
try {
receiveMsg = new ObjectMapper().readValue(msg, ReceiveMsg.class);
} catch (IOException e) {
e.printStackTrace();
}
return handleReceiveMsg(receiveMsg);
}
/**
* 由收到的讨论组消息的内容转发给特定的方法(暂时用不到,先留着)
*
* @param receiveMsg
*/
private ReplyMsg handleDiscussMsg(ReceiveMsg receiveMsg) {
return null;
}
/**
* 由收到的消息类型转发给特定的方法
*
* @param receiveMsg
*/
private ReplyMsg handleReceiveMsg(ReceiveMsg receiveMsg) {
String post_type = receiveMsg.getPost_type();
switch (post_type) {
case "message":
//收到消息
String message_type = receiveMsg.getMessage_type();
switch (message_type) {
case "private":
//私聊消息
return privateMsgService.handlePrivateMsg(receiveMsg);
case "group":
//群消息
return groupMsgService.handleGroupMsg(receiveMsg);
case "discuss":
return handleDiscussMsg(receiveMsg);
}
break;
case "notice":
//群、讨论组变动等通知类事件
break;
case "request":
//加好友请求、加群请求/邀请
break;
case "meta_event":
//生命周期元事件
//可以初始化缓存
//keywordService.getAllDataIntoCache();
break;
}
return null;
}
}
上方代码中,直接用一行代码获取请求中的数据,接着用jackson中ObjectMapper类来解析生成ReceiveMsg对象,然后转交给handleReceiveMsg方法,handleReceiveMsg方法依据消息类型(私聊、群聊等)转交给不同的方法进行处理。
privateMsgService.handlePrivateMsg方法的内容见下一节教你写个QQ机器人(3)