由于之前搞过这方面的,利用netty 实现tcp socket,加密采用对称加密 DES(加密数据),非对称加密RSA(加密DES私钥)这方面的流程,所以这次比较方便。
部分代码如下:
AES工具类
AES 相关信息
AES加密密钥:QWZWSXEDCRFVWGBH
AES加密模式:CBC
AES加密填充模式:PKCS7
appId:570baedcda1111e9a46cd4ae52635598
package com.zhetang.netty; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.Security; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/7/12 * Time: 10:59 * Description: No Description */ public class AESpkcs7paddingUtil { /** * 密钥算法 */ private static final String KEY_ALGORITHM = "AES"; /** * 加密/解密算法 / 工作模式 / 填充方式 * Java 6支持PKCS5Padding填充方式 * Bouncy Castle支持PKCS7Padding填充方式 */ private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding"; /** * 偏移量,只有CBC模式才需要 */ private final static String ivParameter = "QAZWSXEDCRFVTGBH"; /** * AES要求密钥长度为128位或192位或256位,java默认限制AES密钥长度最多128位 */ public static String sKey="" ; /** * 编码格式 */ public static final String ENCODING = "utf-8"; static { //如果是PKCS7Padding填充方式,则必须加上下面这行 Security.addProvider(new BouncyCastleProvider()); } /** * AES加密 * @param source 源字符串 * @param key 密钥 * @return 加密后的密文 * @throws Exception */ public static String encrypt(String source, String key) throws Exception { byte[] sourceBytes = source.getBytes(ENCODING); byte[] keyBytes = key.getBytes(ENCODING); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC"); IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(ENCODING)); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM),iv); byte[] decrypted = cipher.doFinal(sourceBytes); return Base64.encodeBase64String(decrypted); } /** * AES解密 * @param encryptStr 加密后的密文 * @param key 密钥 * @return 源字符串 * @throws Exception */ public static String decrypt(String encryptStr, String key) throws Exception { byte[] sourceBytes = Base64.decodeBase64(encryptStr); byte[] keyBytes = key.getBytes(ENCODING); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC"); IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(ENCODING)); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM),iv); byte[] decoded = cipher.doFinal(sourceBytes); return new String(decoded, ENCODING); } public static void main(String[] args) throws Exception { // String key = "1234567890123456"; String content = "{"dataId":"90134c28c31b49ea85e17bb90ff32eef","enterpriseId":"320710050","gatewayId":"32071005001","collectTime":"20180615123456","isConnectDataSource":true,"reportType":"report","datas":[{"quotaId":"320710050024G0004QT002","value":123.0},{"quotaId":"320710050024G0004QT002","value":123.0}]}"; String key = "QAZWSXEDCRFVTGBH"; byte[] iv = key.getBytes(); // 加密 long lStart = System.currentTimeMillis(); String enString = AESpkcs7paddingUtil.encrypt(content,key); System.out.println("加密后的字串是:" + enString); long lUseTime = System.currentTimeMillis() - lStart; System.out.println("加密耗时:" + lUseTime + "毫秒"); // 解密 lStart = System.currentTimeMillis(); String DeString = AESpkcs7paddingUtil.decrypt(enString,key); System.out.println("解密后的字串是:" + DeString); lUseTime = System.currentTimeMillis() - lStart; System.out.println("解密耗时:" + lUseTime + "毫秒"); } }
TCP 客户端
package com.zhetang.netty; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/4/22 * Time: 17:27 * Description: No Description */ @Component public class AlarmClient { @Scheduled(cron = "0/5 * * * * ?") public static void init()throws Exception{ NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); try { //创建bootstrap对象,配置参数 Bootstrap bootstrap = new Bootstrap(); //设置线程组 bootstrap.group(eventExecutors) //设置客户端的通道实现类型 .channel(NioSocketChannel.class) //使用匿名内部类初始化通道 .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //添加客户端通道的处理器 ch.pipeline().addLast(new AlarmClientHandler()); } }); System.out.println("客户端准备就绪,随时可以起飞~"); //连接服务端 ChannelFuture channelFuture = bootstrap.connect("ip",port).sync(); //对通道关闭进行监听 channelFuture.channel().closeFuture().sync(); } finally { //关闭线程组 eventExecutors.shutdownGracefully(); } } public static void main(String[] args) throws Exception { NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); try { //创建bootstrap对象,配置参数 Bootstrap bootstrap = new Bootstrap(); //设置线程组 bootstrap.group(eventExecutors) //设置客户端的通道实现类型 .channel(NioSocketChannel.class) //使用匿名内部类初始化通道 .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //添加客户端通道的处理器 ch.pipeline().addLast(new AlarmClientHandler()); } }); System.out.println("客户端准备就绪,随时可以起飞~"); //连接服务端 ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8082).sync(); //对通道关闭进行监听 channelFuture.channel().closeFuture().sync(); } finally { //关闭线程组 eventExecutors.shutdownGracefully(); } } }
AlarmClientHandler
package com.zhetang.netty; import com.alibaba.fastjson.JSON; import com.zhetang.influxdb.utils.InfluxDBUtil; import com.zhetang.mapper.mysqlMapper.AlarmHisTimeMapper; import com.zhetang.mapper.mysqlMapper.AlarmRealTimeMapper; import com.zhetang.mapper.mysqlMapper.PointOpcDataMapper; import com.zhetang.mapper.mysqlMapper.QysjProdBaseUserMapper; import com.zhetang.model.dto.city.CityAlarmDTO; import com.zhetang.model.dto.city.CityAlarmDataDTO; import com.zhetang.model.mysql.zw.AlarmHisTime; import com.zhetang.model.mysql.zw.AlarmRealTime; import com.zhetang.model.mysql.zw.PointOpcData; import com.zhetang.model.vo.city.CityRealTimeVO; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.util.CharsetUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import tk.mybatis.mapper.entity.Example; import javax.annotation.PostConstruct; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/7/13 * Time: 15:34 * Description: 园区->市平台 报警数据 alarm_his_time(当前根据时间筛选) alarm_real_time(全查) */ @Component @Slf4j public class AlarmClientHandler extends SimpleChannelInboundHandler<ByteBuf> { private ScheduledExecutorService scheduledExecutorService; @Autowired private InfluxDBUtil influxDBUtil; @Autowired private AlarmRealTimeMapper alarmRealTimeMapper; @Autowired PointOpcDataMapper pointOpcDataMapper; @Autowired private AlarmHisTimeMapper alarmHisTimeMapper; @Autowired QysjProdBaseUserMapper qysjProdBaseUserMapper; private static AlarmClientHandler alarmClientHandler; private static String aseKey ="QAZWSXEDCRFVTGBH"; private static String appId ="570baedcda1111e9a46cd4ae52635598"; private static String alarmServiceId ="WARN_DATA"; //****编码 private static String XHSHENTERPRISECODE = "320710050"; //网关编码 private static String XHSHGATEWAY = "32071005001"; private static String reportType ="report"; //qysj_prod_user_id **** private static String XHSH="****有限公司"; private static String HIGHALARMLEVEL="高限报警"; private static String LOEWALARMLEVEL="低限报警"; long initialDelay = 1; long period = 1; private long realtime_timeInterval = 1000 * 60 * 5; private long warn_timeInterval = 1000; @PostConstruct public void init() { alarmClientHandler = this; alarmClientHandler.influxDBUtil = this.influxDBUtil; alarmClientHandler.pointOpcDataMapper = this.pointOpcDataMapper; alarmClientHandler.alarmRealTimeMapper =this.alarmRealTimeMapper; alarmClientHandler.alarmHisTimeMapper= this.alarmHisTimeMapper; alarmClientHandler.qysjProdBaseUserMapper = this.qysjProdBaseUserMapper; } @Override public void channelActive(ChannelHandlerContext ctx){ AlarmRealTimeMapper alarmRealTimeMapper = alarmClientHandler.alarmRealTimeMapper; InfluxDBUtil influxDBUtil = alarmClientHandler.influxDBUtil; AlarmHisTimeMapper alarmHisTimeMapper = alarmClientHandler.alarmHisTimeMapper; PointOpcDataMapper pointOpcDataMapper = alarmClientHandler.pointOpcDataMapper; QysjProdBaseUserMapper qysjProdBaseUserMapper = alarmClientHandler.qysjProdBaseUserMapper; CityAlarmDTO cityAlarmDTO = new CityAlarmDTO(); List<CityAlarmDataDTO> cityAlarmDataDTOList = new ArrayList<>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); Example example = new Example(AlarmHisTime.class); example.createCriteria().andEqualTo("responsibleUnit",XHSH); List<AlarmRealTime> alarmRealTimes = alarmRealTimeMapper.selectByExample(example); //实时插入超上限报警,超下限报警 List<CityAlarmDataDTO> overAlarmDataDTOList = setRealTimeValue(alarmRealTimes, cityAlarmDataDTOList); //实时插入消警数据 List<CityAlarmDataDTO> allAlarmDataList = cancleAlarm(alarmRealTimes, overAlarmDataDTOList); cityAlarmDTO.setDataId(UUID.randomUUID().toString().replaceAll("-","")); cityAlarmDTO.setEnterpriseId(XHSHENTERPRISECODE); cityAlarmDTO.setGatewayId(XHSHGATEWAY); cityAlarmDTO.setCollectTime(sdf.format(new Date())); cityAlarmDTO.setIsConnectDataSource(true); cityAlarmDTO.setReportType(reportType); //插入报警数据集合 cityAlarmDTO.setAlarms(allAlarmDataList); //市平台中间数据 String jsonString = JSON.toJSONString(cityAlarmDTO); try{ //封装市平台返回数据 String encrypt = AESpkcs7paddingUtil.encrypt(jsonString, aseKey); CityRealTimeVO cityRealTimeVO = new CityRealTimeVO(); cityRealTimeVO.setAppId(appId); cityRealTimeVO.setDataId(cityAlarmDTO.getDataId()); cityRealTimeVO.setServiceId(alarmServiceId); cityRealTimeVO.setData(encrypt); String returnJson = JSON.toJSONString(cityRealTimeVO); log.info(cityAlarmDTO.toString()); System.out.println(returnJson); if(ObjectUtils.allNotNull(cityAlarmDTO.getAlarms(),cityAlarmDTO.getEnterpriseId(),cityAlarmDTO.getGatewayId())){ ctx.writeAndFlush(Unpooled.copiedBuffer(returnJson+"@@", CharsetUtil.UTF_8)); } } catch (Exception e){ e.printStackTrace(); ctx.close(); } } /** * 封装市平台中间返回值 * @param alarmRealTimes * @param cityAlarmDataDTOList */ List<CityAlarmDataDTO> setRealTimeValue(List<AlarmRealTime> alarmRealTimes, List<CityAlarmDataDTO> cityAlarmDataDTOList){ AlarmRealTimeMapper alarmRealTimeMapper = alarmClientHandler.alarmRealTimeMapper; InfluxDBUtil influxDBUtil = alarmClientHandler.influxDBUtil; AlarmHisTimeMapper alarmHisTimeMapper = alarmClientHandler.alarmHisTimeMapper; PointOpcDataMapper pointOpcDataMapper = alarmClientHandler.pointOpcDataMapper; QysjProdBaseUserMapper qysjProdBaseUserMapper = alarmClientHandler.qysjProdBaseUserMapper; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); if(!CollectionUtils.isEmpty(alarmRealTimes)){ alarmRealTimes.stream().filter(p->p != null).forEach(p->{ Optional<AlarmRealTime> first = alarmRealTimeMapper.listAlarmRealByUnique(p.getUnique()).stream().filter(m -> ObjectUtils.allNotNull(m)).findFirst(); AlarmRealTime alarmRealTime = first.isPresent() ? first.get() : null; Optional.ofNullable(alarmRealTime).ifPresent(s->{ PointOpcData pointOpcData = pointOpcDataMapper.selectBySensor(s.getUnique()); if(ObjectUtils.allNotNull(pointOpcData,pointOpcData.getCityQuotaId())){ CityAlarmDataDTO cityAlarmDataDTO = new CityAlarmDataDTO(); Date startTime = p.getStartTime(); cityAlarmDataDTO.setAlarmTime(sdf.format(startTime)); cityAlarmDataDTO.setQuotaId(pointOpcData.getCityQuotaId()); Map map = influxDBUtil.selectInfkyxdb(s.getUnique()); cityAlarmDataDTO.setValue(Float.parseFloat(map.get("value").toString())); //报警类型 String alarmType = getAlarmType(p.getAlarmLevel()); cityAlarmDataDTO.setAlarmType(alarmType); //报警阈值 String thresholdRage = getThresholdRage(pointOpcData); String[] thresholdArray = thresholdRage.split("-"); if(thresholdArray.length>1){ if(HIGHALARMLEVEL.equals(p.getAlarmLevel())){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[1])); } if(LOEWALARMLEVEL.equals(p.getAlarmLevel())){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[0])); } } if(thresholdArray.length==1){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[0])); } cityAlarmDataDTOList.add(cityAlarmDataDTO); } }); }); } return cityAlarmDataDTOList; } /** * 设置histime value * @param alarmHisTimes * @param cityAlarmDataDTOList * @return */ List<CityAlarmDataDTO> setHisTimeValue(List<AlarmHisTime> alarmHisTimes, List<CityAlarmDataDTO> cityAlarmDataDTOList){ AlarmRealTimeMapper alarmRealTimeMapper = alarmClientHandler.alarmRealTimeMapper; InfluxDBUtil influxDBUtil = alarmClientHandler.influxDBUtil; AlarmHisTimeMapper alarmHisTimeMapper = alarmClientHandler.alarmHisTimeMapper; PointOpcDataMapper pointOpcDataMapper = alarmClientHandler.pointOpcDataMapper; QysjProdBaseUserMapper qysjProdBaseUserMapper = alarmClientHandler.qysjProdBaseUserMapper; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); if(!CollectionUtils.isEmpty(alarmHisTimes)){ alarmHisTimes.stream().filter(p->p != null).forEach(p->{ Optional<AlarmHisTime> first = alarmHisTimeMapper.listAlarmHisByUnique(p.getUnique()).stream().filter(m -> ObjectUtils.allNotNull(m)).findFirst(); AlarmHisTime alarmHisTime = first.isPresent() ? first.get() : null; Optional.ofNullable(alarmHisTime).ifPresent(s->{ PointOpcData pointOpcData = pointOpcDataMapper.selectBySensor(s.getUnique()); if(ObjectUtils.allNotNull(pointOpcData,pointOpcData.getCityQuotaId())){ CityAlarmDataDTO cityAlarmDataDTO = new CityAlarmDataDTO(); Date startTime = p.getStartTime(); cityAlarmDataDTO.setAlarmTime(sdf.format(startTime)); cityAlarmDataDTO.setQuotaId(pointOpcData.getCityQuotaId()); Map map = influxDBUtil.selectInfkyxdb(s.getUnique()); cityAlarmDataDTO.setValue(Float.parseFloat(map.get("value").toString())); //报警类型 String alarmType = getAlarmType(p.getAlarmLevel()); cityAlarmDataDTO.setAlarmType(alarmType); //报警阈值 String thresholdRage = getThresholdRage(pointOpcData); String[] thresholdArray = thresholdRage.split("-"); if(thresholdArray.length>1){ if(HIGHALARMLEVEL.equals(p.getAlarmLevel())){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[1])); } if(LOEWALARMLEVEL.equals(p.getAlarmLevel())){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[0])); } } if(thresholdArray.length==1){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[0])); } cityAlarmDataDTOList.add(cityAlarmDataDTO); } }); }); } return cityAlarmDataDTOList; } /** * 获取消警数据 * @param cityAlarmDataDTOList * @return */ List<CityAlarmDataDTO> cancleAlarm( List<AlarmRealTime> alarmRealTimes, List<CityAlarmDataDTO> cityAlarmDataDTOList){ AlarmRealTimeMapper alarmRealTimeMapper = alarmClientHandler.alarmRealTimeMapper; InfluxDBUtil influxDBUtil = alarmClientHandler.influxDBUtil; AlarmHisTimeMapper alarmHisTimeMapper = alarmClientHandler.alarmHisTimeMapper; PointOpcDataMapper pointOpcDataMapper = alarmClientHandler.pointOpcDataMapper; QysjProdBaseUserMapper qysjProdBaseUserMapper = alarmClientHandler.qysjProdBaseUserMapper; Date date = new Date(); List<AlarmHisTime> cancleAlarmList = null; SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd"); String formatDate = sdf.format(date); List<AlarmHisTime> alarmHisTimes = alarmHisTimeMapper.listAlarmHisByCreatedTime(formatDate,XHSH); if(! CollectionUtils.isEmpty(alarmHisTimes)){ //获取当日消警数据,且此消警数据已经不再报警 cancleAlarmList = alarmHisTimes.stream().filter(p -> ObjectUtils.allNotNull(p.getUnique(), p.getGmtCreatedOn())) .map(p -> { List<String> RealTimeList = alarmRealTimes.stream().map(m -> m.getUnique()) .filter(d -> !p.getUnique().equals(d)).collect(Collectors.toList()); if (RealTimeList != null && RealTimeList.size() > 0) { return p; } return null; }).collect(Collectors.toList()); } List<CityAlarmDataDTO> cityAlarmDataDTOList1 = setHisTimeValue(cancleAlarmList, cityAlarmDataDTOList); return cityAlarmDataDTOList1; } /** * 报警类型 * @param alarmLevel * @return */ String getAlarmType(String alarmLevel){ switch (alarmLevel){ case "高限报警": return "alarmhi:alarm"; case "低限报警": return "alarmlo:alarm"; default: return null; } } /** * 报警阈值区间 * @param pointOpcDataVO * @return */ String getThresholdRage(PointOpcData pointOpcDataVO){ String zc = null; if(ObjectUtils.allNotNull(pointOpcDataVO)){ if(pointOpcDataVO.getFour()!=null && !"".equals(pointOpcDataVO.getFour())){ zc = pointOpcDataVO.getFour() ; } if(pointOpcDataVO.getFive()!=null && !"".equals(pointOpcDataVO.getFive())){ if("".equals(zc)){ zc =pointOpcDataVO.getFive() ; }else{ zc = zc +"-"+pointOpcDataVO.getFive() ; } } } return zc; } @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { log.info("Client received: " + msg.toString(CharsetUtil.UTF_8)); ctx.close(); log.info("当前通道已关闭!!!"); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { log.info("client 异常!!!!"); cause.printStackTrace(); ctx.close(); } public String getXmlPublicKey() { // ras公钥 String rasPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCB0vo8UhGB5uGkZlcupo+NmcAg8jz4Th+CmLtBKp4EBFof3io1LBXTzaQ7KIFnvhJRQahbm/IZInibBrHQbmQzAoK9417fAGFBeZ1Zb4O9pfb5Nsu5cXsyD/pgJJ8IW4xuIrPSMXCU5jnQJjyAKRnPoASY4UPi4k60PYT4JvFdlQIDAQAB"; //DES密钥 (8字节) String desKey = "wQNC2380"; //DES加密数据 //RSA加密key RSAPublicKey publicKey = null; try { publicKey = RSAUtil.getPublicKey(rasPublicKey); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } String xmlPublicKey = RSAUtil.publicEncrypt(desKey, publicKey); return xmlPublicKey; } }
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.hainei</groupId> <artifactId>netty_test</artifactId> <version>0.0.1-SNAPSHOT</version> <name>netty_test</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>commons-httpclient</groupId> <artifactId>commons-httpclient</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>6.5.4</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.20.Final</version> </dependency> <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </dependency> <dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>[7.6.0, 7.6.99]</version> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> </dependency> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.4</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.11</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.junit/com.springsource.org.junit --> <dependency> <groupId>org.junit</groupId> <artifactId>com.springsource.org.junit</artifactId> <version>4.9.0</version> <scope>test</scope> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>dysmsapi20170525</artifactId> <version>[2.0.0,3.0.0)</version> </dependency> <dependency> <groupId>com.tencentcloudapi</groupId> <artifactId>tencentcloud-sdk-java</artifactId> <version>3.1.270</version><!-- 注:这里只是示例版本号,请获取并替换为 最新的版本号 --> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
1111