当前位置 博文首页 > 阳阳的博客:【SpringBoot】教你写个QQ机器人(3)让你的机器人

    阳阳的博客:【SpringBoot】教你写个QQ机器人(3)让你的机器人

    作者:[db:作者] 时间:2021-08-15 10:03

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? 教你写个QQ机器人(3)让你的机器人学会垃圾分类


    事前废话

    自从上海实行垃圾分类后,上海老百姓生活于水生火热之中,如今战火蔓延到了苏州,身为正义化身的我,决定让我的机器人学会垃圾分类。

    我们的需求:用户输入垃圾分类+垃圾后,机器人返回该垃圾的分类类型。

    例如:用户输入垃圾分类+湿纸巾? ? ? ?机器人返回湿纸巾属于干垃圾(其它垃圾)


    事中准备

    垃圾分类查询api:垃圾分类查询

    SpringBoot中网络请求工具RestTemplate

    Jsoup,抓取网页中特定的值

    Redis,为了加快查询效率

    MySQL,将查询后的数据存入数据库


    开干

    在上一节【JAVA】教你写个QQ机器人(2)搭建项目框架中,handleReceiveMsg方法依据消息类型,调用了handlerPrivateMsg方法。其中该类的sendPrivateMsg方法用于发送私聊消息,发送的目标对象QQ与消息实体被封装在PrivateMsg中。

    public class PrivateMsgServiceImpl implements PrivateMsgService {
    
        @Autowired
        RestTemplate restTemplate;
    
        @Autowired
        RubbishService rubbishService;
    
    
        @Override
        public Result sendPrivateMsg(PrivateMsg msg) {
            Result result = restTemplate.postForObject(URL + SEND_PRIVATE_MSG, msg, Result.class);
            return result;
        }
        
        public ReplyMsg handlePrivateMsg(ReceiveMsg receiveMsg) {
            String raw_message = receiveMsg.getRaw_message();
            if (raw_message.contains("垃圾分类+")) {
                String type = rubbishService.handleRubbishType(raw_message);
                ReplyMsg replyMsg = new ReplyMsg();
                replyMsg.setReply(type);
                return replyMsg;
            }
            return null;
        }
    
    }

    如果用户输入其他消息,即不包含“垃圾分类+”的消息,机器人默认不回应消息。

    下面看rubbishServiceImpl中的handleRubbisType方法

        public String handleRubbishType(String raw_message) {
            StringBuilder returnMsg = new StringBuilder();
            String name = raw_message.split("\\+")[1];
            Rubbish rubbish = getRubbishByName(name);
            if (null == rubbish) {
                returnMsg.append("暂未查找到该垃圾的分类" + "\n");
            } else {
                returnMsg.append(name + "属于" + rubbish.getType());
            }
            return returnMsg.toString();
        }

    name为截取到的垃圾的名称,调用getRubbishByName方法获得垃圾类型。该方法会先在Redis缓存中查找,没有再去数据中查找,没有再去请求api,有的话就存入数据库与Redis中,下次再查询相同的垃圾直接从缓存中返回。

        @Override
        public Rubbish getRubbishByName(String name) {
            Rubbish rubbish = null;
            //首先在redis中查找
            rubbish = getRubbishFromRedis(name);
            //System.out.println("查询redis");
            if (rubbish == null) {
                //再去数据库中查找
                rubbish = getRubbishFromDB(name);
                //System.out.println("查询数据库");
                if (rubbish == null) {
                    rubbish = getRubbishFromAPI(name);
                    //System.out.println("查询api");
                }
    
            }
            return rubbish;
        }
    
        public Rubbish getRubbishFromRedis(String name) {
            Rubbish rubbish = (Rubbish) redisTemplate.opsForValue().get(name);
            return rubbish;
        }
    
        public Rubbish getRubbishFromDB(String name) {
            QueryWrapper<Rubbish> rubbishQW = new QueryWrapper<>();
            rubbishQW.eq("name", name);
            Rubbish rubbish = rubbishMapper.selectOne(rubbishQW);
            saveRubbishFromDBIntoRedis(rubbish);
            return rubbish;
        }
    
        public Rubbish getRubbishFromAPI(String name) {
            String type = null;
            try {
                name = URLEncoder.encode(name, "UTF-8");
                String body = restTemplate.getForEntity(URLConst.GET_RUBBISH_TYPE + name, String.class).getBody();
                Document document = Jsoup.parse(body);
                //定位到row
                Element element = document.select("div[class=row]").get(2);
                Elements select = element.select("div").select("h1").select("span");
                String preType = select.text();
                if (preType == null || !preType.contains("属于")) {
                    return null;
                }
                type = select.get(2).text();
                name = URLDecoder.decode(name, "UTF-8");
            } catch (Exception e) {
                //e.printStackTrace();
                return null;
            }
            Rubbish rubbish = new Rubbish(name, type);
            saveRubbishFromAPTIntoDB(rubbish);
            saveRubbishFromDBIntoRedis(rubbish);
            return rubbish;
        }
    
        public boolean saveRubbishFromAPTIntoDB(Rubbish rubbish) {
            if (rubbish == null) {
                return false;
            }
            int line = rubbishMapper.insert(rubbish);
            return line > 0;
        }
    
        public boolean saveRubbishFromDBIntoRedis(Rubbish rubbish) {
            if (rubbish == null) {
                return false;
            }
            redisTemplate.opsForValue().set(rubbish.getName(), rubbish);
            return true;
        }

    好了到这里,垃圾分类的整个流程已经走完了,下面我先替你们尝试一下。


    完事

    唉这很舒服,下一节预告:让你的机器人学会看妹子!!!

    cs