SpringBoot+Mybatis+LayUI微信公众号自动给女朋友推送专属浪漫早安问候-续集①+

十年前,你爱我,我逃避不见,十年后,我爱你,你不在身边。人生的错过就是如此。一刹便是永远,追悔也是纪念。

1、前言

码不停蹄,前端代码重构了,优化了部分功能,微信消息定时推送自动化平台再次升级归来,增加了古诗句,农历日期,24节气显示等数据。下面让我们展开描述基础使用吧,包括关键代码呈现等。

2、推送效果

在这里插入图片描述

3、平台地址

点击跳转
访问地址:https://www.rucoding.cn/

在这里插入图片描述

4、注册步骤

4.1、注册登录

平台注册登录访问地址:点击跳转

4.2、扫码登录

点击扫码登录

在这里插入图片描述
在这里插入图片描述

4.3、选择推荐模板或者自定义模板

模板=手机查收的效果

如下操作图示:按需确认选择自己的模板,复制对应内容,粘贴到模板内容,提交后会生成模板ID。
在这里插入图片描述

4.4、开始填写基础信息&&测试

表单基础信息填写,标注星号*都是必填项的,但如果模板没展示对应内容,可随意选择填写。

在这里插入图片描述

模板ID复制粘贴:
复制第三步4.3生成的模板ID

在这里插入图片描述

点击推送测试,查看推送效果

在这里插入图片描述

4.5、设置每天定时推送

在这里插入图片描述

启动定时推送

在这里插入图片描述

5、系统设计与实现

5.1、开发环境

平台代码是基于SpringBoot+Mybatis+LayUI开发的,同时,定时推送任务整合了XXL-JOB。

类型内容
开发语言Java
框架Spring Boot
前端LayUI
任务调度XXL-JOB
JDK版本JDK1.8
数据库MySQL 5.7
数据库工具Navicat15
开发软件IDEA
Maven包Maven3.6.1
浏览器谷歌浏览器

Spring Boot是Spring Framework的一个子项目,它是一个快速构建基于Spring的应用程序的框架。Spring Boot旨在简化Spring应用程序的配置和部署过程,让开发人员能够更专注于业务逻辑的实现而不是繁琐的配置。它提供了自动配置和起步依赖项的功能,通过这些功能,可以轻松地集成和使用各种Spring模块和第三方库。Spring Boot还内置了一个内嵌的Web服务器,可以轻松地将我们的应用程序打包为独立的可执行JAR文件,使部署变得非常简单。

MyBatis是一个开源的持久层框架,它是在Java中使用的一种对象关系映射(ORM)框架。它允许我们通过XML或注解的方式将SQL查询语句映射到Java对象,从而实现了数据库操作和Java对象的映射。相比其他ORM框架,MyBatis更加灵活,因为我们可以直接编写SQL查询,这对于复杂的查询和性能优化非常有利。MyBatis支持多种数据库,并且可以与Spring框架无缝集成,因此在Spring Boot项目中使用MyBatis非常方便。

LayUI是一款简单易用的前端UI框架,它基于HTML、CSS和JavaScript构建。它的设计目标是提供一套轻量级的界面组件和交互体验,使得前端开发变得更加快速和简单。LayUI具有丰富的UI组件,如表格、表单、弹出层、导航、按钮等,同时也支持响应式设计,使得我们的Web应用程序在不同设备上都能有很好的显示效果。LayUI的文档和示例都非常清晰,使得前端开发者可以迅速上手并构建出漂亮的用户界面。

XXL-JOB是一款开源的分布式任务调度平台,旨在解决大规模分布式任务调度问题。该平台提供了动态任务调度、任务管理、任务执行日志、分片广播任务、失败重试等功能,以及报警监控和多种任务触发方式。XXL-JOB的易用性和灵活性使其成为许多企业和项目中首选的任务调度框架。

5.2、平台界面
①、平台首页

在这里插入图片描述

②、模板选择

在这里插入图片描述

③、定时任务

在这里插入图片描述

5.3、部分代码

用户-前端控制器

 @OperLog(operModule = "用户管理", operType = "克隆", operDesc = "数据克隆")
    @PostMapping("dataClone")
    @ResponseBody
    public Result<String> dataClone(@RequestBody SysUser user, Map<String, Object> map) {
        if (user.getId() == null) {
            // 设置创建者姓名
            user.setCreateUser("");
            user.setCreateTime(new Date());
            Integer cloneOperTotal = userService.getCloneOperTotal(user.getAppId());
            if (cloneOperTotal > 5) {
                return ResultUtil.fail("数据条数已达上限哦!");
            } else {
                // 保存用户
                boolean result = userService.save(user);
                if (!result) {
                    return ResultUtil.fail("添加失败!");
                }
            }
        }
        return ResultUtil.ok();
    }

    @OperLog(operModule = "推送信息", operType = "推送", operDesc = "数据推送")
    @PostMapping("sendMsg")
    @ResponseBody
    @RequestLimit(maxCount = 6) //频控30min内限制请求6次
    public Result<String> sendMsg(@RequestBody SysUser user, Map<String, Object> map) {
        String result = userService.sendMsg(user);
        return ResultUtil.ok(result);

    }


    @OperLog(operModule = "用户管理", operType = "删除", operDesc = "删除用户")
    @PostMapping("remove")
    @ResponseBody
    public Result<String> remove(@RequestParam Integer id) {
        // 1.删除用户与角色的关联记录
        Map<String, Object> param = new HashMap<>();
        param.put("user_id", id);
        roleUserService.removeByMap(param);
        // 2.删除用户
        if (!userService.removeById(id)) {
            return ResultUtil.fail("删除失败!");
        }
        return ResultUtil.ok();
    }

    @GetMapping("info/{userId}")
    public String selectInfo(Map<String, Object> map, @PathVariable(required = true) Integer userId) {
        SysUser user = userService.getById(userId);
        map.put("user", user);
        return "user/info";
    }

    // 根据用户Id查询其拥有的角色
    @GetMapping("/getRoles/{userId}")
    @ResponseBody
    public List<SysRole> getRoles(@PathVariable Integer userId) {
        List<SysRole> roles = userService.selectRolesByUserId(userId);

        return roles;
    }

    // 保存用户角色
    @OperLog(operModule = "用户管理", operType = "修改", operDesc = "分配角色")
    @PostMapping("saveRole")
    @ResponseBody
    public Result<String> saveRole(@RequestParam Integer userId, @RequestParam(value = "roleIds[]") Integer[] roleIds) {
        userService.saveRole(userId, Arrays.asList(roleIds));
        return ResultUtil.ok();
    }

频控:规定时间段内接口访问次数限制

/*
 * @author      :xiaoixan
 * @date        :2023/04/02 21:42
 * @class       :RequestLimitAspect
 * @description :统计规定时间段内接口访问次数限制
 * @version     :1.0
 **/
@Slf4j
@Aspect
@Component
public class RequestLimitAspect {

    @Autowired
    private RedisTemplate redisTemplate;

//    @Before("within(@org.springframework.web.bind.annotation.RestController *) && @annotation(requestLimit)")
    @Before("within(@org.springframework.stereotype.Controller *) && @annotation(requestLimit)")
    public void requestLimit(final JoinPoint joinPoint, RequestLimit requestLimit) throws RequestLimitException {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        SysUser user = (SysUser) request.getSession().getAttribute("userSession");
        String ip = request.getRemoteAddr();
        String uri = request.getRequestURI().toString();
        String url = request.getRequestURL().toString();
        String key = user.getUsername() + "-request-limit-" + url;
        long count = redisTemplate.opsForValue().increment(key, 1);
        if (count == 1) {
            redisTemplate.expire(key, requestLimit.timeout(), TimeUnit.MILLISECONDS);
        }
        if (count > requestLimit.maxCount()) {
            String error = "用户:" + (user.getUsername()) + ":HTTP请求【" + url + "】超过了限定的访问次数【" + requestLimit.maxCount() + "】";
            log.error(error);
            throw new RequestLimitException(error);
        }
    }
}

天气接口-工具类

/**
 * 获取天气数据-对接天行数据接口
 *
 * @author Rucoding
 */
public class TianXingWeatherUtil {

    public static Result getWeather() {
        Result result = new Result();
        String tianapi_data = "";
        try {
            URL url = new URL( "https://apis.tianapi.com/tianqi/index");
            HttpURLConnection  conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setDoOutput(true);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            OutputStream outputStream = conn.getOutputStream();
            String content = "key=" + PushConfigure.getRainbowKey() + "&type=1" + "&city=101020100";
            outputStream.write(content.getBytes());
            conn.getOutputStream().flush();
            conn.getOutputStream().close();
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader (inputStream,"utf-8");
            BufferedReader bufferedReader = new BufferedReader (inputStreamReader);
            StringBuilder tianapi = new StringBuilder();
            String temp = null;
            while ( null != (temp = bufferedReader.readLine())){
                tianapi.append(temp);
            }
            tianapi_data = tianapi.toString();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONObject json = JSONObject.parseObject(tianapi_data);
        int code = json.getInteger("code");
        String msg = json.getString("msg");
        JSONObject resultJSONObject = json.getJSONObject("result");
        TianXingWeather weather = null;
        if (resultJSONObject != null) {
            weather = new TianXingWeather();
            weather.setWeather(resultJSONObject.getString("weather"));
            weather.setHighest(resultJSONObject.getString("highest"));
            weather.setLowest(resultJSONObject.getString("lowest"));
            weather.setWindsc(resultJSONObject.getString("windsc"));
            weather.setWind(resultJSONObject.getString("wind"));
            weather.setWindspeed(resultJSONObject.getString("windspeed"));
            weather.setSunrise(resultJSONObject.getString("sunrise"));
            weather.setSunset(resultJSONObject.getString("sunset"));
            weather.setTips(resultJSONObject.getString("tips"));
            weather.setDate(resultJSONObject.getString("date"));
            weather.setWeek(resultJSONObject.getString("week"));
            weather.setReal(resultJSONObject.getString("real"));
            weather.setArea(resultJSONObject.getString("area"));
            weather.setProvince(resultJSONObject.getString("province"));
        } else {
            System.out.println("The 'weather' key does not exist in the result JSON object.");
        }
        result.setCode(String.valueOf(code));
        result.setData(weather);
        return result;
    }
}

/**
 * 早安心语接口调用
 *
 * @author cws
 */
public class TianQiMoriningUtil {

    public static Result getMoriningWords() {
        String tianapi_data = "";
        try {
            URL url = new URL("https://apis.tianapi.com/zaoan/index");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setDoOutput(true);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            OutputStream outputStream = conn.getOutputStream();
            String content = "key=" + PushConfigure.getRainbowKey();
            outputStream.write(content.getBytes());
            conn.getOutputStream().flush();
            conn.getOutputStream().close();

            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            StringBuilder tianapi = new StringBuilder();
            String temp;
            while ((temp = bufferedReader.readLine()) != null) {
                tianapi.append(temp);
            }
            tianapi_data = tianapi.toString();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            return createErrorResult("天行数据接口调用出错:" + e.getMessage());
        }
        JSONObject jsonObject = JSONObject.parseObject(tianapi_data);
        if (jsonObject == null) {
            return createErrorResult("天行数据接口返回为空,请检查接口地址!");
        }

        String code = jsonObject.getString("code");
        if (!"200".equals(code)) {
            String msg = jsonObject.getString("msg");
            return createErrorResult("天行数据接口调用报错: " + msg);
        }

        String content = jsonObject.getJSONObject("result").getString("content");
        if (content == null || content.isEmpty()) {
            return createErrorResult("天行数据接口返回数据为空!");
        }

        String data = content;
        return createSuccessResult(code, data);
    }

    private static Result createErrorResult(String message) {
        Result result = new Result();
        result.setCode("500");
        result.setMessage(message);
        return result;
    }

    private static Result createSuccessResult(String code, String data) {
        Result result = new Result();
        result.setCode(code);
        result.setData(data);
        return result;
    }
}

6、附言

当初相遇,犹如《登鹳雀楼》般高高在上,注定是一段美好缘分。如今你们牵手共行,犹如《青玉案·元夕》般情意绵绵,缱绻依偎。

愿你们的爱情如《如梦令》般如梦如幻,甜蜜入心。像《诉衷情·花谢花飞花满天》一般,情话绵绵,美好不绝。

愿你们的相爱,如同《浣溪沙》般清新纯净,细水长流。愿你们的思念,如同《声声慢》般温柔入耳,念念不忘。

无论岁月如何变迁,愿你们的情意如《钗头凤·世情薄》一样厚重,心心相印。如《夜泊牛渚怀古》般,回忆往昔,唯美不减。

愿你们的相守,如《浪淘沙令·席上送张仲固帅》般坚定不移,相伴一生。如《长相思·山一程》般,情深意长,相思无尽。

愿你们的未来,如同《南乡子·登京口北固亭有怀》般美丽迷人,幸福永恒。愿你们的爱情,如《夜雨寄北》般真挚深情,永不凋零。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java智慧阁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值