2025年 的存档
202512 月29

AI:用 Antigravity 开发了一个 WordPress 反垃圾评论插件,别说功能还挺全

提示词

制作一款 wordpress 6.9 版本下的反垃圾评论插件,插件名称 wizspam,支持根据关键词过滤、IP地址过滤,支持对关键词、IP的管理等功能。

WizSpam – WordPress 反垃圾评论插件

一款功能强大的 WordPress 反垃圾评论插件,支持基于关键词和 IP 地址的智能过滤。

功能特性

🔑 关键词过滤

  • 支持多种匹配方式:部分匹配、完全匹配、正则表达式
  • 可视化管理关键词列表
  • 批量导入导出关键词
  • 支持启用/禁用单个关键词

🌐 IP 地址过滤

  • 黑名单模式:拦截指定 IP
  • 白名单模式:只允许指定 IP
  • 支持 IP 段匹配(通配符和 CIDR 格式)
  • 为每个 IP 添加备注说明

📊 统计和日志

  • 实时统计拦截数据
  • 按类型和时间查看拦截趋势
  • 详细的拦截日志记录
  • 支持日志筛选和分页

⚙️ 灵活配置

  • 自定义垃圾评论处理方式
  • 可配置拦截提示消息
  • 自动清理过期日志
  • 完全的中文界面

使用指南

添加关键词

  1. 进入 WordPress 后台 > WizSpam > 关键词管理
  2. 在”添加新关键词”表单中输入关键词
  3. 选择匹配方式:
    • 部分匹配:评论内容包含该关键词即拦截
    • 完全匹配:只有完整单词匹配才拦截
    • 正则表达式:使用正则表达式进行高级匹配
  4. 点击”添加关键词”

添加 IP 地址

  1. 进入 WordPress 后台 > WizSpam > IP地址管理
  2. 在”添加新IP地址”表单中输入 IP
  3. 支持的格式:
    • 单个 IP:192.168.1.100
    • IP 段(通配符):192.168.1.*
    • IP 段(CIDR):192.168.1.0/24
  4. 选择列表类型(黑名单/白名单)
  5. 可选添加备注说明
  6. 点击”添加IP地址”

配置插件

  1. 进入 WordPress 后台 > WizSpam > 插件设置
  2. 配置以下选项:
    • 垃圾评论处理方式:标记为垃圾/移至回收站/直接删除
    • IP过滤模式:黑名单模式/白名单模式
    • 显示拦截提示:是否向被拦截用户显示消息
    • 日志保留天数:自动清理过期日志

查看统计

  1. 进入 WordPress 后台 > WizSpam > 统计概览
  2. 查看最近 7 天的拦截统计
  3. 查看拦截类型分布
  4. 查看每日拦截趋势
  5. 查看最近拦截记录

查看日志

  1. 进入 WordPress 后台 > WizSpam > 拦截日志
  2. 可按类型筛选日志(关键词/IP)
  3. 支持分页浏览
  4. 可清空所有历史日志

PS:有需要的可以评论留下 Email,我会免费发送给你~~

202512 月24

Ubuntu 24:php8.0 快速升级到php8.5

1. 更新系统并接入 PPA 源

Ondřej Surý 的 PPA 是 Debian/Ubuntu 生态中最权威的 PHP 源,它会第一时间同步 PHP 8.5.x 的稳定版。

<code>sudo apt update
sudo apt install -y software-properties-common
# 添加 PPA 源(如果已添加则会自动跳过)
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update

2. 安装 PHP 8.5 核心及其组件

为了确保你的业务能正常运行,除了安装核心包,还需要安装常用的扩展(以替代 8.0 版本的扩展):

<code># 安装 PHP 8.5 核心、FPM 及常用扩展
sudo apt install -y php8.5 php8.5-cli php8.5-fpm php8.5-common php8.5-mysql \
php8.5-xml php8.5-curl php8.5-mbstring php8.5-zip php8.5-gd php8.5-intl

3. 切换默认 PHP 版本

安装后,系统内会并存多个 PHP 版本。你需要将命令行默认指向 8.5:

<code># 切换 CLI 版本
sudo update-alternatives --set php /usr/bin/php8.5

# 验证版本
php -v

4. 更新 Web 服务器配置

如果你使用的是 Nginx,需要手动修改站点配置文件(通常在 /etc/nginx/sites-enabled/):

  1. 找到 fastcgi_pass 这一行。
  2. 将路径从旧版本修改为新版本:
    • 旧:fastcgi_pass unix:/run/php/php8.0-fpm.sock;
    • 新:fastcgi_pass unix:/run/php/php8.5-fpm.sock;
  3. 测试并重启 Nginx:Bashsudo nginx -t && sudo systemctl restart nginx

5. (可选) 清理旧版本

确认网站运行无误后,可以删除 PHP 8.0 以节省 磁盘空间:

<code>sudo apt purge php8.0*
sudo apt autoremove -y
20259 月9

尝试找回比特币密钥文件的密码

背景:2013年比特币兴起的时候,注册了比特币官网账号及钱包,从TB等处买了少量BTC,大概有0.02个吧,当时助记词存在硬盘上,N年来电脑换了好几个,最终由于Thinkpad X1 SSD硬盘挂了(见文章:https://wizzer.cn/archives/3552),导致历史备份文件永久丢失。最近从邮箱中找到了当时钱包的备份文件,wallet.aes.json 但密钥文件使用密码加密了,尝试了一堆常用密码,都不对(不知道当时脑子咋想了,弄那么复杂的密码干啥),于是尝试破解密码。

1、破解软件工具 BTCRecover

这个工具主要通过海量的密码词典,进行匹配,看是否有可能匹配的密码组合:

 python btcrecover.py --wallet wallet.aes.json --passwordlist weakpass.txt --no-dupchecks

–no-dupchecks 关闭重复猜测检查以节省内存

2、下载弱密码字典文件 https://weakpass.com

3、根据自己的密码习惯生成密码

import itertools
import random

def generate_passwords(base_string, max_length=5):
    # 生成所有可能的字符组合,允许任意顺序
    base_list = list(base_string)
    for length in range(1, max_length + 1):
        for combo in itertools.product(base_list, repeat=length):
            # 生成大小写的所有组合
            for case in itertools.product(*[(char.lower(), char.upper()) for char in combo]):
                yield ''.join(case)

def save_to_file(passwords, filename):
    with open(filename, 'w') as file:
        for password in passwords:
            file.write(password + '\n')

if __name__ == "__main__":
    base_string = 'abcdefg123456'
    max_length = 11  # 可以根据需要调整
    passwords = generate_passwords(base_string, max_length)
    save_to_file(passwords, 'passwords.txt')
    print(f"生成的密码已保存到 passwords.txt")

然而,使用了weakpass网站的上十亿密码组合,依旧没有匹配到我的密码……

尝试用生成密码的方式找回密码中……

20255 月9

飞牛OS:挂载群晖文件夹到本地,实现备份文件到群晖



<strong>1. 创建凭据文件</strong>

sudo mkdir -p /root/.smbcredentials
sudo bash -c 'echo "username=u" > /root/.smbcredentials/wizzer'
sudo bash -c 'echo "password=p" >> /root/.smbcredentials/wizzer'
sudo chmod 600 /root/.smbcredentials/wizzer

<strong>2. 创建挂载点目录</strong>
sudo mkdir -p /vol2/1000/Photo/wizzer

3. 配置 /etc/fstab

编辑 /etc/fstab 文件,添加以下内容:

//10.10.10.10/homes/wizzer/Photos/MobileBackup /vol2/1000/Photo/wizzer cifs credentials=/root/.smbcredentials/wizzer,file_mode=0777,dir_mode=0777,uid=1000,gid=1000,forceuid,forcegid,_netdev 0 0

4. 测试配置

sudo mount -a

注意事项

  1. _netdev 选项确保在网络就绪后再进行挂载
  2. 凭据文件权限必须设置为 600,确保安全性
  3. 确保目标目录存在且有正确的权限
  4. 如果遇到问题,请检查网络连接和凭据信息是否正确

参数说明

  • file_mode=0777:设置文件权限
  • dir_mode=0777:设置目录权限
  • uid=1000,gid=1000:设置用户和组 ID
  • forceuid,forcegid:强制使用指定的用户和组 ID
  • _netdev:等待网络就绪后再挂载

这样配置后,系统重启时会自动挂载 SMB 共享,无需手动操作。

20253 月4

Java:解压jar后反编译,修改后重新打包更新jar


mkdir tmp
cd tmp
# 解压jar主包
jar xf ../main.jar

# 编译lib文件夹下某子jar依赖包, 生成class文件,使用classpath加载依赖包
javac -cp "../*:." com/budwk/Demo.java

# 将class文件打包到jar包中
jar uf demo.jar com/budwk/Demo.class

# 手动覆盖新的 demo.jar 包

# 不能使用这个更新命令,会导致jar包被二次压缩
# jar uf ../main.jar lib/demo.jar

# 使用0这个参数,将解压文件打包到jar包中
jar cfM0 ../main.jar *
20252 月11

nutz:postgresql 中 PostGIS的几何数据类型处理

 @Column
    @ColDefine(customType = "GEOGRAPHY(Point,4326)", adaptor = PsqlPointAdaptor.class)
    @ApiModelProperty(description = "坐标")
    private String geomPoint;//值格式为"POINT(经度 纬度)"
import net.postgis.jdbc.PGgeometry;
import net.postgis.jdbc.geometry.Point;
import org.nutz.dao.jdbc.ValueAdaptor;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

public class PsqlPointAdaptor implements ValueAdaptor {
    @Override
    public Object get(ResultSet rs, String colName) throws SQLException {
        return rs.getObject(colName);
    }

    @Override
    public void set(PreparedStatement stat, Object obj, int index)  throws SQLException{
        if (null == obj) {
            stat.setNull(index, Types.NULL);
        } else {
            String pointStr = (String) obj;
            Point point = new Point(pointStr);
            PGgeometry pgGeometry = new PGgeometry(point);
            stat.setObject(index, pgGeometry, Types.OTHER);
        }
    }
}
    <properties>
        <postgis-jdbc.version>2024.1.0</postgis-jdbc.version>
    </properties>
    <dependencies>
        <!-- PostGIS扩展类型 -->
        <dependency>
            <groupId>net.postgis</groupId>
            <artifactId>postgis-jdbc</artifactId>
            <version>${postgis-jdbc.version}</version>
        </dependency>

20251 月21

通过 certbot 自动部署ssl证书

Let`s Encrypt 证书自动获取和部署

sudo apt install certbot python3-certbot-nginx

sudo certbot --nginx

sudo systemctl reload nginx

sudo certbot renew --dry-run
20251 月20

dwg 文件转换为 shp 并发布为图层

1、ArgGIS 按图层分别导出shp

原始没有坐标系,要手动配准:

投影坐标 4524 CGCS2000_3_Degree_GK_Zone_36

2、GeoServer

1)创建工作区

2)数据存储-添加新的数据存储-选择文件夹 Directory of spatial files (shapefiles) 

3)图层-添加新的资源-选择要发布的文件-Native Bounding Box 从数据中计算

20251 月3

解决方法:个推推送离线消息到华为手机不显示问题(或只能收到2次消息)

问题1:只能收到APP在线时推送的消息,离线消息收不到

问题2:一台设备一天只能收到2次消息推送

解决方法:

1、uniapp 要正确获取clientId,并且APP要获取通知权限

bindPushCid() {       
           var timer = setTimeout(function() {
                plus.push.getClientInfoAsync(function(info) {
                    if (info.clientid) {
                        // 绑定到后台用户
                        updateGetuiClientId(info.clientid);
                        clearInterval(timer);
                    }
                }, function(e) {
                    console.log(JSON.stringify(e));
                })
            }, 1000)
        },
permissionPush(){
            let platform = uni.getSystemInfoSync().platform
            if (platform == 'android') {
                /* 获取当前手机是否有通知权限 */
                // let main = plus.android.runtimeMainActivity();
                // let pkName = main.getPackageName();
                // console.log("是否有通知权限pkName",pkName);
                // let NotificationManagerCompat = plus.android.importClass("android.support.v4.app.NotificationManagerCompat");
                //  console.log("是否有通知权限NotificationManagerCompat",NotificationManagerCompat);
                // let packageNames = NotificationManagerCompat.from(main);

                var main = plus.android.runtimeMainActivity();
                var NotificationManagerCompat = plus.android.importClass("androidx.core.app.NotificationManagerCompat");
                        let packageNames = NotificationManagerCompat.from(main);
                let pkName = main.getPackageName();
                if (!packageNames.areNotificationsEnabled()) { //手机没有开启通知的权限
                    uni.showModal({
                        title: '通知权限',
                        content: '通知权限暂未开启',
                        cancelText: '暂不开启',
                        confirmText: '前往开启',
                         success: function (res) {
                                if (res.confirm) {
                                      let uid = main.getApplicationInfo().plusGetAttribute("uid");
                                      let Intent = plus.android.importClass('android.content.Intent');
                                      let Build = plus.android.importClass("android.os.Build");
                                      let intent = '';
                                      //android 8.0引导  
                                      if (Build.VERSION.SDK_INT >= 26) {
                                        intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
                                        intent.putExtra('android.provider.extra.APP_PACKAGE', pkName);
                                      } else if (Build.VERSION.SDK_INT >= 21) { //android 5.0-7.0  
                                        intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
                                        intent.putExtra("app_package", pkName);
                                        intent.putExtra("app_uid", uid);
                                      } else { //(<21)其他--跳转到该应用管理的详情页
                                        let Settings = plus.android.importClass("android.provider.Settings");
                                        let Uri = plus.android.importClass("android.net.Uri");
                                        intent = new Intent();
                                        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                        let uri = Uri.fromParts("package", main.getPackageName(), null);
                                        intent.setData(uri);
                                      }
                                      // 跳转到该应用的系统通知设置页  
                                      main.startActivity(intent);

                                } else if (res.cancel) {
                                    console.log('用户点击取消');
                                }
                            },
                        fail: () => {},
                        complete: () => {}
                    });
                }
            }
        }

2、华为开发者后台,申请“自分类权益”,以便解除通知条数限制,现在申请很简单,提交示例和截图,系统直接审核通过

3、厂家参数要注意细节

因为importance和category参数,调试很久

        Map<String, Map<String, Object>> options = new HashMap<>();
        Map<String, Object> oop = new HashMap<>();
        oop.put("/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
        oop.put("/message/android/notification/badge/add_num", 1);
        oop.put("/message/android/notification/importance", "NORMAL");
        oop.put("/message/android/category", "WORK");
        options.put("HW", oop);
        ups.setOptions(options);

4、服务端完整代码

package com.budwk.app;

import com.getui.push.v2.sdk.ApiHelper;
import com.getui.push.v2.sdk.GtApiConfiguration;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.CommonEnum;
import com.getui.push.v2.sdk.dto.req.Audience;
import com.getui.push.v2.sdk.dto.req.AudienceDTO;
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
import com.getui.push.v2.sdk.dto.req.message.harmony.HarmonyDTO;
import com.getui.push.v2.sdk.dto.req.message.harmony.HarmonyNotification;
import com.getui.push.v2.sdk.dto.res.TaskIdDTO;
import com.gexin.rp.sdk.base.IPushResult;
import com.gexin.rp.sdk.base.impl.AppMessage;
import com.gexin.rp.sdk.base.impl.ListMessage;
import com.gexin.rp.sdk.base.impl.SingleMessage;
import com.gexin.rp.sdk.base.impl.Target;
import com.gexin.rp.sdk.exceptions.RequestException;
import com.gexin.rp.sdk.http.IGtPush;
import com.gexin.rp.sdk.template.*;
import com.gexin.rp.sdk.template.style.Style0;
import lombok.extern.slf4j.Slf4j;
import org.nutz.json.Json;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class GeTuiUtil {

    private static String appId;
    private static String appKey;
    private static String masterSecret;
    private static String host;
    private static Long OfflineExpireTime;
    private static String logo;
    private static boolean isRing;
    private static boolean isVibrate;
    private static boolean isClearable;
    private static int transmissionType;

    private static PushApi pushApi;

    // 初始化个推的系统app参数
    static {
        appId = "";
        appKey = "";
        masterSecret = "";
        host = "http://sdk.open.api.igexin.com/apiex.htm";
        OfflineExpireTime = 259200000L;
        logo = "icon.png";
        isRing = true;
        isVibrate = true;
        isClearable =true;
        transmissionType = 1;

        System.setProperty("http.maxConnections", "200");
        GtApiConfiguration apiConfiguration = new GtApiConfiguration();
        //填写应用配置
        apiConfiguration.setAppId(appId);
        apiConfiguration.setAppKey(appKey);
        apiConfiguration.setMasterSecret(masterSecret);
        // 接口调用前缀,请查看文档: 接口调用规范 -> 接口前缀
        apiConfiguration.setDomain("https://restapi.getui.com/v2/");
        // 实例化ApiHelper对象,用于创建接口对象
        ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
        // 创建对象,建议复用。目前有PushApi、StatisticApi、UserApi
        pushApi = apiHelper.creatApi(PushApi.class);

    }

    public static Map<String, Object> sendSingleNew(String title, String content, String cid) {
        PushDTO<Audience> pushDTO = new PushDTO<Audience>();
        pushDTO.setRequestId(System.currentTimeMillis() + "");

        buildPushMessage(title, content, pushDTO);

        Audience audience = new Audience();
        pushDTO.setAudience(audience);
        audience.addCid(cid);
        ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushToSingleByCid(pushDTO);
        log.info("sendSingleNew result :" + Json.toJson(apiResult));
        Map<String, Object> result = new HashMap<>();
        result.put("code", apiResult.getCode());
        if (apiResult.isSuccess()) {
            result.put("data", apiResult.getData());
        } else {
            result.put("msg", apiResult.getMsg());
        }
        return result;
    }

    public static void main(String[] args) {
        String title = "你有新的待办任务";
        String content = "任务内容:测" + System.currentTimeMillis();
        String cid = "77336b3d6d136da0cf56e288a7462949";
        Map<String, Object> stringObjectMap = sendSingleNew(title, content, cid);

//        List<String> cids = new ArrayList<>();
//        cids.add(cid);
//        Map<String, Object> stringObjectMap = sendBatchNew(title, content, cids);

//        Map<String, Object> stringObjectMap = sendAllClientNew(title, content);
//
    }

    private static PushMessage buildPushMessage(String title, String content, PushDTO pushDTO) {

        PushMessage pushMessage = new PushMessage();
        pushDTO.setPushMessage(pushMessage);
        GTNotification notification = new GTNotification();
        pushMessage.setNotification(notification);
        notification.setTitle(title);
        notification.setBody(content);
        notification.setBadgeAddNum("1");
        notification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);
        notification.setSlotType("2");
        notification.setCategory("CATEGORY_REMINDER");

        PushChannel pushChannel = new PushChannel();
        pushDTO.setPushChannel(pushChannel);

        AndroidDTO androidDTO = new AndroidDTO();
        pushChannel.setAndroid(androidDTO);
        Ups ups = new Ups();
        androidDTO.setUps(ups);
        ThirdNotification thirdNotification = new ThirdNotification();
        ups.setNotification(thirdNotification);
        thirdNotification.setTitle(title);
        thirdNotification.setBody(content);
        thirdNotification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);

        Map<String, Map<String, Object>> options = new HashMap<>();
        Map<String, Object> oop = new HashMap<>();
        oop.put("/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
        oop.put("/message/android/notification/badge/add_num", 1);
        oop.put("/message/android/notification/importance", "NORMAL");
        oop.put("/message/android/category", "WORK");
        options.put("HW", oop);
        ups.setOptions(options);

        HarmonyDTO harmonyDTO = new HarmonyDTO();
        pushChannel.setHarmony(harmonyDTO);
        HarmonyNotification harmonyNotification = new HarmonyNotification();
        harmonyDTO.setNotification(harmonyNotification);
        harmonyNotification.setTitle(title);
        harmonyNotification.setBody(content);
        harmonyNotification.setCategory("CATEGORY_REMINDER");
        harmonyNotification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);
        return pushMessage;
    }

    private static Map<String, Object> send(AbstractTemplate template, List<String> cids) {
        if (cids == null || cids.size() == 0) {
            // 给appId下所有人发
            return sendAllClient(template);
        }
        if (cids.size() == 1) {
            // 单发
            Map<String, Object> result = sendSingle(template, cids.get(0));
            return result;
        } else {
            // 群发
            Map<String, Object> result = sendBatch(template, cids);
            return result;
        }
    }

    private static Map<String, Object> sendNew(String title, String content, List<String> cids) {
        log.info("进入推送信息:" + title);
        if (cids == null || cids.size() == 0) {
            // 给appId下所有人发
            Map<String, Object> stringObjectMap = sendAllClientNew(title, content);
            log.info("APP群推发送返回结果:" + Json.toJson(stringObjectMap));
            return stringObjectMap;
        }
        if (cids.size() == 1) {
            // 单发
            Map<String, Object> result = sendSingleNew(title, content, cids.get(0));
            log.info("单推发送返回结果:" + Json.toJson(result));
            return result;
        } else {
            // 群发
            Map<String, Object> result = sendBatchNew(title, content, cids);
            log.info("群推发送返回结果:" + Json.toJson(result));
            return result;
        }
    }

    /**
     * @Description 发送通知模板消息
     * @Author daitao
     * @version 1.0
     * @Date 2019/4/24 17:57
     * @Param title:消息标题
     * @Param content:消息内容
     * @Param cids: 1、null或size==0:表示给appId下所有人发
     * 2、size为1:单发
     * 3、size大于1:群发
     * @Return map类型, 可能为null,例如:"{result=ok, contentId=OSL-0424_y2LxEeM6hvA0yhTqa77qw4,
     * details={"c85fa1218fe4c54652a77bef22726fb0":"TokenMD5Error",
     * "a5800ff27659a5258b8ba86e4e1d7c87":"successed_online"
     * }
     * }"
     * result==ok,发送成功,details里面是每个cid对应的发送结果,包含successed表示成功,其他失败
     */
    public static Map<String, Object> sendNotification(String title, String content, List<String> cids) {
        NotificationTemplate template = buildNotificationTemplate(title, content);
        return send(template, cids);
    }

    public static Map<String, Object> sendNotificationNew(String title, String content, List<String> cids) {
        return sendNew(title, content, cids);
    }

    /**
     * @param
     * @param template
     * @param msgItem
     * @return
     * @throws
     * @author daitao
     * @version 1.0
     * @description 个推单发
     * @date 2019/4/12
     **/
    private static Map<String, Object> sendSingle(AbstractTemplate template, String cid) {
        IGtPush push = new IGtPush(host, appKey, masterSecret);
        SingleMessage message = new SingleMessage();
        message.setOffline(true);
        // 离线有效时间,单位为毫秒,可选
        message.setOfflineExpireTime(OfflineExpireTime);
        message.setData(template);
        // 可选,1为wifi,0为不限制网络环境。根据手机处于的网络情况,决定是否下发
        message.setPushNetWorkType(0);
        Target target = new Target();
        target.setAppId(appId);
        target.setClientId(cid);
        IPushResult ret;
        try {
            ret = push.pushMessageToSingle(message, target);
        } catch (RequestException e) {
            e.printStackTrace();
            ret = push.pushMessageToSingle(message, target, e.getRequestId());
        }
        return ret.getResponse();
    }

    /**
     * @param
     * @param template
     * @param msgItem
     * @return
     * @throws
     * @author daitao
     * @version 1.0
     * @description 个推单发
     * @date 2019/4/12
     **/
    private static Map<String, Object> sendBatch(AbstractTemplate template, List<String> cids) {
        // 配置返回每个用户返回用户状态,可选
        System.setProperty("gexin_pushList_needDetails", "true");
        IGtPush push = new IGtPush(host, appKey, masterSecret);
        // 通知透传模板
        ListMessage message = new ListMessage();
        message.setData(template);
        // 设置消息离线,并设置离线时间
        message.setOffline(true);
        // 离线有效时间,单位为毫秒,可选
        message.setOfflineExpireTime(OfflineExpireTime);
        // taskId用于在推送时去查找对应的message
        String taskId = push.getContentId(message);
        List<Target> targets = handleTargets(cids);
        IPushResult ret = push.pushMessageToList(taskId, targets);
        return ret.getResponse();
    }

    private static Map<String, Object> sendBatchNew(String title, String content, List<String> cids) {
        Map<String, Object> result = new HashMap<>();

        PushDTO<String> pushDTO = new PushDTO<String>();
        pushDTO.setRequestId(System.currentTimeMillis() + "");
        buildPushMessage(title, content, pushDTO);

        ApiResult<TaskIdDTO> createResult = pushApi.createMsg(pushDTO);
        log.info("sendBatchNew createResult :" + Json.toJson(createResult));
        result.put("code", createResult.getCode());
        if (createResult.isSuccess()) {
            result.put("data", createResult.getData());
            TaskIdDTO taskIdDTO = createResult.getData();
            AudienceDTO pushBatchDTO = new AudienceDTO();
            pushBatchDTO.setTaskid(taskIdDTO.getTaskId());
            Audience audience = new Audience();
            audience.setCid(cids);
            pushBatchDTO.setAudience(audience);
            ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushListByCid(pushBatchDTO);
            log.info("sendBatchNew apiResult :" + Json.toJson(apiResult));
            result.put("code", apiResult.getCode());
            if (apiResult.isSuccess()) {
                result.put("data", apiResult.getData());
            } else {
                result.put("msg", apiResult.getMsg());
            }
        } else {
            result.put("msg", createResult.getMsg());
        }
        return result;
    }

    private static List<Target> handleTargets(List<String> cids) {
        List<Target> targets = new ArrayList<>();
        for (String cid : cids) {
            Target target = new Target();
            target.setAppId(appId);
            target.setClientId(cid);
            targets.add(target);
        }
        return targets;
    }

    private static NotificationTemplate buildNotificationTemplate(String title, String content) {
        NotificationTemplate template = new NotificationTemplate();
        // 设置APPID与APPKEY
        template.setAppId(appId);
        template.setAppkey(appKey);
        template.setTransmissionType(transmissionType);
        Style0 style = new Style0();
        // 设置通知栏标题与内容
        style.setTitle(title);
        style.setText(content);
        // 配置通知栏图标
        style.setLogo(logo);
        // 配置通知栏网络图标
        style.setLogoUrl("");
        // 设置通知是否响铃,震动,或者可清除
        style.setRing(isRing);
        style.setVibrate(isVibrate);
        style.setClearable(isClearable);
        template.setStyle(style);
        return template;
    }

    /**
     * @Description
     * @Author daitao
     * @version 1.0
     * @Date 2019/4/24 17:57
     * @Param cids: 1、null或size==0:表示给appId下所有人发
     * 2、size为1:单发
     * 3、size大于1:群发
     * @Return
     * @Exception
     */
    public static Map<String, Object> sendLinkTemplate(String title, String content, String openUrl, List<String> cids) {
        LinkTemplate template = buildLinkTemplate(title, content, openUrl);
        return send(template, cids);
    }

    private static LinkTemplate buildLinkTemplate(String title, String content, String openUrl) {
        LinkTemplate template = new LinkTemplate();
        // 设置APPID与APPKEY
        template.setAppId(appId);
        template.setAppkey(appKey);
        Style0 style = new Style0();
        // 设置通知栏标题与内容
        style.setTitle(title);
        style.setText(content);
        // 配置通知栏图标
        style.setLogo(logo);
        // 配置通知栏网络图标
        style.setLogoUrl("");
        // 设置通知是否响铃,震动,或者可清除
        style.setRing(isRing);
        style.setVibrate(isVibrate);
        style.setClearable(isClearable);
        template.setStyle(style);
        // 设置打开的网址地址
        template.setUrl(openUrl);
        return template;
    }

    /**
     * @Description
     * @Author daitao
     * @version 1.0
     * @Date 2019/4/24 17:57
     * @Param cids: 1、null:表示给appId下所有人发
     * 2、size为1:单发
     * 3、size大于1:群发
     * @Return
     * @Exception
     */
    public static Map<String, Object> sendNotyPopLoadTemplate(String title, String content,
                                                              String popTitle, String popContent, String downloadTitle, String downloadIcon, String downloadUrl, List<String> cids) {
        NotyPopLoadTemplate template = buildNotyPopLoadTemplate(title, content, popTitle, popContent, downloadTitle, downloadIcon, downloadUrl);
        return send(template, cids);
    }

    /**
     * @param title         消息标题
     * @param content       消息内容
     * @param popTitle      弹框标题
     * @param popContent    弹框内容
     * @param downloadTitle 下载标题
     * @param downloadIcon  下载图标
     * @param downloadUrl   下载的url资源地址
     * @return
     */
    private static NotyPopLoadTemplate buildNotyPopLoadTemplate(String title, String content,
                                                                String popTitle, String popContent, String downloadTitle, String downloadIcon, String downloadUrl
    ) {
        NotyPopLoadTemplate template = new NotyPopLoadTemplate();
        // 设置APPID与APPKEY
        template.setAppId(appId);
        template.setAppkey(appKey);
        Style0 style = new Style0();
        // 设置通知栏标题与内容
        style.setTitle(title);
        style.setText(content);
        // 配置通知栏图标
        style.setLogo(logo);
        // 配置通知栏网络图标
        style.setLogoUrl("");
        // 设置通知是否响铃,震动,或者可清除
        style.setRing(isRing);
        style.setVibrate(isVibrate);
        style.setClearable(isClearable);
        template.setStyle(style);
        // 设置弹框标题与内容
        template.setPopTitle(popTitle);
        template.setPopContent(popContent);
        // 设置弹框显示的图片
        template.setPopImage("");
        template.setPopButton1("下载");
        template.setPopButton2("取消");
        // 设置下载标题
        template.setLoadTitle(downloadTitle);
        template.setLoadIcon(downloadIcon);
        //设置下载地址
        template.setLoadUrl(downloadUrl);
        return template;
    }

    /**
     * @Description
     * @Author daitao
     * @version 1.0
     * @Date 2019/4/24 17:57
     * @Param cids: 1、null:表示给appId下所有人发
     * 2、size为1:单发
     * 3、size大于1:群发
     * @Return
     * @Exception
     */
    public static Map<String, Object> sendTransmissionTemplate(String title, String content, List<String> cids) {
        TransmissionTemplate template = buildTransmissionTemplate(title, content);
        return send(template, cids);
    }

    /**
     * 安卓推送透传消息模板
     *
     * @param title
     * @param content
     * @return
     */
    private static TransmissionTemplate buildTransmissionTemplate(String title, String content) {
        TransmissionTemplate template = new TransmissionTemplate();
        template.setAppId(appId);
        template.setAppkey(appKey);
        // 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动
        template.setTransmissionType(transmissionType);
        template.setTransmissionContent(content);
        return template;
    }

    /**
     * @param oldTaskId 指定需要撤回消息对应的taskId
     * @param force     客户端没有找到对应的taskid,是否把对应appid下所有的通知都撤回
     * @Description
     * @Author daitao
     * @version 1.0
     * @Date 2019/4/24 17:57
     * @Param cids: 1、null:表示给appId下所有人发
     * 2、size为1:单发
     * 3、size大于1:群发
     * @Return
     * @Exception
     */
    public static Map<String, Object> sendRevokeTemplate(String oldTaskId, boolean force, List<String> cids) {
        RevokeTemplate template = getRevokeTemplate(oldTaskId, force);
        return send(template, cids);
    }

    /**
     * 获取撤回模板
     *
     * @param oldTaskId 指定需要撤回消息对应的taskId
     * @param force     客户端没有找到对应的taskid,是否把对应appid下所有的通知都撤回
     * @return
     */
    private static RevokeTemplate getRevokeTemplate(String oldTaskId, boolean force) {
        RevokeTemplate template = new RevokeTemplate();
        template.setAppId(appId);// 应用appid
        template.setAppkey(appKey);// 应用appkey
        template.setOldTaskId(oldTaskId);
        return template;
    }

    /**
     * 发个应用的所有客户端
     *
     * @param template
     * @return
     */
    private static Map<String, Object> sendAllClient(AbstractTemplate template) {
        IGtPush push = new IGtPush(host, appKey, masterSecret);
        // 定义"点击链接打开通知模板",并设置标题、内容、链接
        List<String> appIds = new ArrayList<String>();
        appIds.add(appId);
        // 定义"AppMessage"类型消息对象,设置消息内容模板、发送的目标App列表、是否支持离线发送、以及离线消息有效期(单位毫秒)
        AppMessage message = new AppMessage();
        message.setData(template);
        message.setAppIdList(appIds);
        message.setOffline(true);
        message.setOfflineExpireTime(OfflineExpireTime);
        IPushResult ret = push.pushMessageToApp(message);
        return ret.getResponse();
    }

    private static Map<String, Object> sendAllClientNew(String title, String content) {
        PushDTO<String> pushDTO = new PushDTO<String>();
        pushDTO.setRequestId(System.currentTimeMillis() + "");
        pushDTO.setAudience("all");

        buildPushMessage(title, content, pushDTO);

        ApiResult<TaskIdDTO> apiResult = pushApi.pushAll(pushDTO);

        Map<String, Object> result = new HashMap<>();
        log.info("sendAllClientNew result :" + Json.toJson(apiResult));
        result.put("code", apiResult.getCode());
        if (apiResult.isSuccess()) {
            result.put("data", apiResult.getData());
        } else {
            result.put("msg", apiResult.getMsg());
        }
        return result;
    }
}

pom.xml

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--个推-->
        <dependency>
            <groupId>com.gexin.platform</groupId>
            <artifactId>gexin-rp-sdk-http</artifactId>
            <version>4.1.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.gexin.platform</groupId>
            <artifactId>gexin-rp-sdk-base</artifactId>
            <version>4.0.0.26</version>
        </dependency>
        <dependency>
            <groupId>com.gexin.platform</groupId>
            <artifactId>gexin-rp-sdk-template</artifactId>
            <version>4.0.0.20</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.gexin.platform/gexin-rp-fastjson -->
        <!-- https://mvnrepository.com/artifact/com.getui.push/restful-sdk -->
        <dependency>
            <groupId>com.getui.push</groupId>
            <artifactId>restful-sdk</artifactId>
            <version>1.0.6.0</version>
        </dependency>

        <dependency>
            <groupId>com.gexin.platform</groupId>
            <artifactId>gexin-rp-fastjson</artifactId>
            <version>1.0.0.1</version>
        </dependency>

仓库

<repository>
            <id>getui</id>
            <url>http://mvn.gt.getui.com/nexus/content/repositories/releases/</url>
        </repository>