首页
关于
Search
1
sql的注入原因和解决办法
134 阅读
2
SpringBoot整合腾讯云存储COS及基本使用,增删改查......
108 阅读
3
深究contains方法
100 阅读
4
多线程概述
73 阅读
5
学习的第一个注解@WebServlet - JavaWeb
73 阅读
默认分类
Java
C/C++
Mysql
JavaWeb
SpringBoot
算法
前端
Search
标签搜索
Spring
HTTP
Java
JavaWeb
IOC
mybatis
腾讯云
COS
云存储
CDN
achong
累计撰写
25
篇文章
累计收到
2
条评论
首页
栏目
默认分类
Java
C/C++
Mysql
JavaWeb
SpringBoot
算法
前端
页面
关于
搜索到
25
篇与
achong
的结果
2023-04-11
SpringBoot整合腾讯云存储COS及基本使用,增删改查......
本次测试环境基于JDK1.8、SpringBoot,依赖由Maven管理。本文章对腾讯云官方的api文档进行了测试,且略有改进,并适当添加注释。1、环境配置腾讯云存储对应的JDK文档页面https://cloud.tencent.com/document/product/436/10199先引入API相关依赖<dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>5.6.97</version> </dependency>在resource资源目录下配置相关文件,存储腾讯云密钥和云存储的基本信息config.properties### 腾讯云 # 密钥 qcloud.secretId=AKID********xtSLn5XWDI86bm qcloud.secretKey=d1I********1vd6 # cos配置 # region,桶存在的区域 qcloud.region=ap-shanghai # bucketName,即桶的名字 qcloud.bucketName=test-1200000000 # 访问域名 qcloud.Domain=https://test-1200000000.cos.ap-shanghai.myqcloud.com/在config类里配置相关Bean@Configuration public class Configure { /** * 该Bean用于读取资源目录下的config.properties文件 */ @Bean("cosConfig") public Properties cosConfig(){ Properties properties = new Properties(); try(InputStream is = ClassLoader.getSystemResourceAsStream("config.properties")) { properties.load(is); } catch (IOException e) { throw new RuntimeException(e); } return properties; } /** * 注册一个配置好的COS客户端 */ @Bean("cosClient") public COSClient createCOSClient(){ // 读取配置文件获取密钥 Properties properties = cosConfig(); String secretId = properties.getProperty("qcloud.secretId"); String secretKey = properties.getProperty("qcloud.secretKey"); String sessionToken = "TOKEN"; // 传入密钥 BasicSessionCredentials credentials = new BasicSessionCredentials(secretId, secretKey, sessionToken); COSCredentials cosCredentials = new BasicCOSCredentials(secretId, secretKey); // 设置bucket的地域 Region region = new Region(properties.getProperty("qcloud.region")); ClientConfig clientConfig = new ClientConfig(region); // 设置https clientConfig.setHttpProtocol(HttpProtocol.https); // 可选:设置socket读取超时,默认30s clientConfig.setSocketTimeout(5*1000); // 可选:设置建立连接超时时间,默认30s clientConfig.setConnectionTimeout(5*1000); // 如果需要的话,设置 http 代理,ip 以及 port //clientConfig.setHttpProxyIp("httpProxyIp"); //clientConfig.setHttpProxyPort(80); // 生成cos客户端 COSClient cosClient = new COSClient(cosCredentials, clientConfig); return cosClient; } }云存储的增删改查皆由COSClient 类来发起请求和接收接口。根据腾讯云的文档可知:COSClient 是线程安全的类,允许多线程访问同一实例。 因为实例内部维持了一个连接池,创建多个实例可能导致程序资源耗尽。请确保程序生命周期内实例只有一个,且在不再需要使用时,调用 COSClient.shutdown() 方法将其关闭。如果需要新建实例,请先将之前的实例关闭。推荐一个进程里只使用一个 COSClient,在程序全部结束退出时才调用 COSClient.shutdown()。所以将COSClient 交给spring管理刚刚好,因为spring管理的Bean默认是单实例的。2、上传文件文件上传:对象存储中本身没有文件夹和目录的概念,文件的完整路径用Key和Value表示,例如有一个文件的完整路径是/2023/04/11/1.png,此时,“/2023/04/11/”是Key,“1.png”是Value。 @Resource public Properties cosConfig; @Resource private COSClient cosClient; /** * 使用简单接口上传,文件类型 */ @Test public void cosClientUploadFile(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); File file = new File("1.webp"); String KV = "/test/" + file.getName(); /** * 参数1:桶名称 * 参数2:上传后存放的完整路径。完整路径+文件名 * 参数3:要上传的文件 */ // PutObjectRequest 用于设置请求信息 PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, KV, file); try{ // 如果这里没有发生异常,则表示本次请求操作成功。 // PutObjectResult 类用于返回结果信息 PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest); System.out.println(putObjectResult.getRequestId()); } catch (CosServiceException e) { e.printStackTrace(); } catch (CosClientException e) { e.printStackTrace(); } // 确认本进程不再使用 cosClient 实例之后,关闭之 cosClient.shutdown(); }流上传:/** * 使用简单接口上传,流类型 * 上传的源是一个 InputStream 类型(和其子类型)的流实例。 */ @Test public void cosClientUploadStream(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); File file = new File("1.webp"); String KV = "test/" + file.getName(); try(FileInputStream fis = new FileInputStream(file)) { // ObjectMetadata 类用于记录对象的元信息 ObjectMetadata objectMetadata = new ObjectMetadata(); PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, KV, fis, objectMetadata); PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest); System.out.println(putObjectResult.getRequestId()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 确认本进程不再使用 cosClient 实例之后,关闭之 cosClient.shutdown(); }3、下载文件从指定桶下载文件@Test public void cosLoadTest(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); /** * 创建一个get请求 * 参数1:桶名称 * 参数2:文件的key */ GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, "test/2.png"); File downloadFile = new File("11.jpg"); try { /** * 返回一个异步结果 Download, 可同步的调用 waitForCompletion 等待下载结束, 成功返回 void, 失败抛出异常 * 下载的文件回存入downloadFile中 */ Download download = transferManager.download(getObjectRequest, downloadFile); download.waitForCompletion(); } catch (CosServiceException e) { e.printStackTrace(); } catch (CosClientException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } transferManager.shutdownNow(true); }4、删除文件从指定桶删除文件@Test public void deleteCOSFile(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); String key = "test/1.jpg"; cosClient.deleteObject(bucketName, key); }5、查询文件只有批量顺序查询,没有单个查询单次批量查询官方的说法是列出第一页对象,第一页的数量可以设置,但是最大1000.很简陋,且查出来的数据是无序的。 @Test public void queryList1(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); // new一个专门的请求对象 ListObjectsRequest listObjectsRequest = new ListObjectsRequest(); // 设置bucketName名称 listObjectsRequest.setBucketName(bucketName); // 设置列出的对象名以prefix为前缀,可找出文件名前缀相同的对象 listObjectsRequest.setPrefix(""); // 设置最大列出多少个对象,一次listObject最大支持1000 listObjectsRequest.setMaxKeys(10); /** * 发起请求,并保存列出的结果 * 成功:返回 ObjectListing 类型, 包含所有的成员, 以及 nextMarker,是上一批列表中的最后一个对象的名字 * 失败:抛出异常 CosClientException 或者 CosServiceException。详情请参见 异常处理。 */ ObjectListing objectListing = null; try { objectListing = cosClient.listObjects(listObjectsRequest); }catch (CosServiceException e){ e.printStackTrace(); }catch (CosClientException e){ e.printStackTrace(); } // object summary表示此次列出的对象列表 List<COSObjectSummary> cosObjectSummaries = objectListing.getObjectSummaries(); System.out.println("本次列出数据条数为:" + cosObjectSummaries.size()); for (COSObjectSummary cosObjectSummary : cosObjectSummaries) { // 对象的 key String key = cosObjectSummary.getKey(); // 对象的 etag String etag = cosObjectSummary.getETag(); // 对象的长度 long fileSize = cosObjectSummary.getSize(); // 对象的存储类型 String storageClasses = cosObjectSummary.getStorageClass(); System.out.println(cosConfig.getProperty("qcloud.Domain") + key + ", " + etag + ", " + fileSize + ", " + storageClasses); } cosClient.shutdown(); }多次批量查询同样简陋,查出来的数据也是无序的。但是可以循环查询全部数据。代码解读: 请求流程都在do-while里完成,即先查一遍,然后再判断是否未查完。如未查完则携带标记继续循环查询。 由客户端cosClient发起的查询请求会返回一个列表对象objectListing,该对象有一个方法objectListing.isTruncated()可以判断本次查询的列表的后面是否还有数据,如果有,该方法会返回true,然后用objectListing.getNextMarker()方法可以获取下一次标记,其实就是本次结果列表的最后一条数据的key,然后将这个key标记设置到请求对象里面,下次查询复用这个对象即可。 下次开始发送请求时,listObjectsRequest对象将会携带上一次标记,然后该次请求就会从该标记位置开始返回数据,如此循环往复,就可以查完全部数据。 @Test public void queryList2(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); boolean flag = false; String netMarker = ""; do { // 每次循环开始时,先设置循环标记为false,等本次请求发现没有列完时,再设置回true,让while继续循环。 flag = false; ListObjectsRequest listObjectsRequest = new ListObjectsRequest(); // 设置bucketName名称 listObjectsRequest.setBucketName(bucketName); // 设置列出的对象名以prefix为前缀 listObjectsRequest.setPrefix(""); // 设置最大列出多少个对象,一次listObject最大支持1000 listObjectsRequest.setMaxKeys(10); // 设置标记位置 listObjectsRequest.setMarker(netMarker); ObjectListing objectListing = null; try { objectListing = cosClient.listObjects(listObjectsRequest); }catch (CosServiceException e){ e.printStackTrace(); }catch (CosClientException e){ e.printStackTrace(); } // 打印出结果列表里的对象 List<COSObjectSummary> cosObjectSummaries = objectListing.getObjectSummaries(); System.out.println("本次列出数据条数为:" + cosObjectSummaries.size()); for (COSObjectSummary cosObjectSummary : cosObjectSummaries) { // 对象的 key String key = cosObjectSummary.getKey(); // 对象的 etag String etag = cosObjectSummary.getETag(); // 对象的长度 long fileSize = cosObjectSummary.getSize(); // 对象的存储类型 String storageClasses = cosObjectSummary.getStorageClass(); System.out.println(cosConfig.getProperty("qcloud.Domain") + key + ", " + etag + ", " + fileSize + ", " + storageClasses); } // 判断是否查完 if (objectListing.isTruncated()){ // 表示还没有列完,被截断了 // 这里的返回值是一个字符串,具体是本次结果集的最后一条数据的key netMarker = objectListing.getNextMarker(); System.out.println(netMarker); flag = true; } }while (flag); cosClient.shutdown(); }6、列出指定目录下的目录及文件 只能查到下面一级,如果想查深一点,可以获取到目录的时候再递归查询目录 @Test public void queryList3(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); ListObjectsRequest listObjectsRequest = new ListObjectsRequest(); // 设置bucketName listObjectsRequest.setBucketName(bucketName); // 这里填要列出的目录的相对 bucket 的路径 listObjectsRequest.setPrefix("/test/"); // delimiter 表示目录的截断符, 例如:设置为 / 则表示对象名遇到 / 就当做一级目录) listObjectsRequest.setDelimiter("/"); // 设置最大遍历出多少个对象, 一次 listobject 最大支持1000 listObjectsRequest.setMaxKeys(100); // 保存每次列出的结果 ObjectListing objectListing = null; do { try{ // 发起请求 objectListing = cosClient.listObjects(listObjectsRequest); } catch (CosServiceException e) { e.printStackTrace(); return; } catch (CosClientException e) { e.printStackTrace(); return; } // 这里保存列出来的子目录 List<String> commonPrefixes = objectListing.getCommonPrefixes(); System.out.println("目录"); for (String commonPrefix : commonPrefixes) { System.out.println(commonPrefix); } // 这里保存列出的对象列表 List<COSObjectSummary> cosObjectSummaries = objectListing.getObjectSummaries(); System.out.println("对象"); for (COSObjectSummary cosObjectSummary : cosObjectSummaries) { // 对象的 key String key = cosObjectSummary.getKey(); System.out.println(key); } // 标记下一次开始的位置 String nextMarker = objectListing.getNextMarker(); listObjectsRequest.setMarker(nextMarker); }while (objectListing.isTruncated()); }7、判断文件是否存在 @Test public void isExistFile(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); String key = "/test/2.png"; try { boolean result = cosClient.doesObjectExist(bucketName, key); if (result){ System.out.println("存在"); }else { System.out.println("不存在"); } }catch (CosServiceException e){ e.printStackTrace(); }catch (CosClientException e){ e.printStackTrace(); } }8、查询对象的元数据 @Test public void queryObjectMetaData(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); String key = "/test/2.png"; try { ObjectMetadata objectMetadata = cosClient.getObjectMetadata(bucketName, key); System.out.println(objectMetadata.getCrc64Ecma()); System.out.println(objectMetadata.getLastModified()); System.out.println(objectMetadata.getETag()); System.out.println(objectMetadata.getRequestId()); }catch (CosServiceException e){ e.printStackTrace(); }catch (CosClientException e){ e.printStackTrace(); } cosClient.shutdown(); }9、修改对象元数据 /** * 修改对象元数据 * 修改对象元数据利用了复制对象的接口,在复制过程中设置新的元数据。 * 使用复制对象接口,在复制过程中设置新的元数据。在复制接口中仅仅修改元数据,不会执行对象数据的复制。 */ @Test public void changeObjectMetaData(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); String key = "/test/2.png"; // 获取当前的对象元数据 ObjectMetadata objectMetadata = cosClient.getObjectMetadata(bucketName, key); // 修改对象元数据必须设置 replaced objectMetadata.setHeader("x-cos-metadata-directive", "Replaced"); // 设置新的对象元数据 // 注意:Content-Disposition 、自定义元数据或者其他有中文的头域值,在设置前请先调用 UrlEncoderUtils.encode(String) 编码,避免签名问题 objectMetadata.setHeader("x-cos-storage-class", "STANDARD_IA"); objectMetadata.setContentType("text/plain"); /** * copyObjectRequest:拷贝文件请求 * * 重点: * 参数1: 源 Bucket region。默认值:与当前 clientConfig 的 region 一致,表示同地域拷贝 * 参数23:表示源文件得桶名称和key。 * 参数45:表示目的桶和key。 * 如果参数23和参数45相同,则是修改操作。相当于linux命令中,用mv给文件改名。 */ Region region = new Region(cosConfig.getProperty("qcloud.region")); CopyObjectRequest copyObjectRequest = new CopyObjectRequest(region, bucketName, key, bucketName, key); copyObjectRequest.setNewObjectMetadata(objectMetadata); try { CopyObjectResult copyObjectResult = cosClient.copyObject(copyObjectRequest); System.out.println(copyObjectResult.getRequestId()); } catch (CosServiceException e) { e.printStackTrace(); } catch (CosClientException e) { e.printStackTrace(); } cosClient.shutdown(); }10、获取对象的访问远程URL根据key,获得一个完整的可远程访问的该文件的URL。https://abc-1200000000.cos.ap-shanghai.myqcloud.com/test/2.png其实域名是固定且可知的,在控制台的桶信息里看到,本身就知道完整Key,可以直接本地拼接URL,不需要再一次查询。 @Test public void getURL(){ String bucketName = cosConfig.getProperty("qcloud.bucketName"); String key = "/test/2.png"; URL url = cosClient.getObjectUrl(bucketName, key); System.out.println(url); }
2023年04月11日
108 阅读
0 评论
0 点赞
2023-03-03
Spring组件扫描原理 - 基础版
以下代码只是基本的组件扫描功能。全是Java的基础知识。类加载器、反射、注解、文件和文件夹操作、String的处理、集合。public static void main(String[] args) { Map<String, Object> beanMap = new HashMap<>(); // 1、需要扫描的目录 String packageName = "cn.qqwer.achong.IOC.bean"; // 2、将包名转换为路径格式 String packagePath = packageName.replaceAll("\\.","/"); // cn/qqwer/achong/IOC/bean // 3、通过系统加载器获取本地资源路径,返回一个URL对象 URL url = ClassLoader.getSystemClassLoader().getResource(packagePath); // 4、得到绝对路径 String path = url.getPath(); // 5、根据绝对路径得到file对象 File file = new File(path); // 6、获取路径下的所有类文件,获得数组 File[] files = file.listFiles(); // 7、开始逐个处理 Arrays.stream(files).forEach(f -> { // 8、拼接类文件的全包名 String className = packageName + "." +f.getName().split("\\.")[0]; // cn.qqwer.achong.IOC.bean.User try { // 9、根据类的全路径,获取类本身 Class<?> aClass = Class.forName(className); // 10、判断此类是否标记Component注解 if (aClass.isAnnotationPresent(Component.class)){ Component annotation = aClass.getAnnotation(Component.class); // 11、如果有注解、再继续判断@Component是否有值,即是否为bean设置ID String id = annotation.value(); if ("".equals(annotation.value())){ String simpleName = aClass.getSimpleName(); // 12、如果没为bean设置id,则将类文件名设置为bean的ID,类名首字母需转小写 if (!Character.isLowerCase(simpleName.charAt(0))){ id = new StringBuilder().append(Character.toLowerCase(simpleName.charAt(0))).append(simpleName.substring(1)).toString(); } } // 13、最好,将对象new出,并放到一个Map中。 Object obj = aClass.newInstance(); beanMap.put(id, obj); } } catch (Exception e) { throw new RuntimeException(e); } }); //输出map查看结果 System.out.println(beanMap); }
2023年03月03日
12 阅读
0 评论
0 点赞
2023-02-19
对文本框监听事件的优化,时间换性能。
正常情况下,js对文本框控件正常的监听是这样子的。// 对id为 #content 的控件添加文本修改事件 $(document).on("input propertychange","#content",function(res){ var newValue = $("#content").val(); console.log(newValue) }); 可以正常监听文本的变化。但是,太过灵敏了,某些情况下可能不适合。 比如这样一个需求:网页有一个实时同步功能的文本框,文本框内的数据需要实时发送到服务器存储,以便下一次展现。 在打字的情况下,每按下一个字母,都会触发一次文本修改。如果修改监听的回调函数里面是向服务器发送请求的话,即使用户在正常的字的情况下,对服务器来说像是遭受CC攻击了一样,频率太快了。 所以,我对代码进行了改进,时间精度换性能。var n = 0; $(document).on("input propertychange", "#content", function(res){ // 设置文本框监听 var nn = ++n; setTimeout(function(){ if (n != nn) return; UpData(); }, 1000); }); 通过对比文本修改次数来判断需不需要向服务器发送数据。上面代码中定义了两个变量,一个变量n在外面记录 回调函数 文本变化的次数;另一个临时变量nn记录在 回调函数 执行的那一刻文本变化次数。在 回调函数 里用setTimeout来定时2秒执行一个函数,1秒后,如果内外两个记录文本修改次数的变量相同,则向服务器发送数据,否则直接结束本次执行。 如此循环往复,当用户真正停下来,或者用户暂停撰写时,才往服务器发送本次修改的文本。虽然文本不是真正的实时发送,但是慢一两秒对这个需求来说不是很重要。所以说是时间换性能。
2023年02月19日
10 阅读
0 评论
0 点赞
2023-02-14
动态SQL:解决insert时的不确定字段
记录一个真实情况。有这样一个需求:前端传进一个实体对象,后端需要将其存储。此时应该这样写:controller:public ReturnInfo regUri(Url url){ ...... }mapper: <insert id="insertUrl" parameterType="url"> INSERT INTO url_info(uri, data, create_time, expiration_time) VALUE (#{uri}, #{data}, #{createTime}, #{expirationTime}); </insert>但是,其中有一个属性可能是null,比如,在现在的实体中,expirationTime这个过期时间参数可以为空。这时候可以使用mybatis的动态sql功能的 if标签 对其进行判断,根据expirationTime这个属性的有无来修改sql语句。 <insert id="insertUrl" parameterType="url"> INSERT INTO url_info(uri,data, create_time <if test="expirationTime != null and expirationTime != ''"> , expiration_time </if> ) VALUE (#{uri},#{data}, #{createTime} <if test="expirationTime != null and expirationTime != ''"> , #{expirationTime} </if> ); </insert>使用<if></if>标签可以根据实体属性,判断标签里的内容是否拼接进sql语句中。
2023年02月14日
26 阅读
0 评论
0 点赞
2022-10-27
SpringBoot集成腾讯云短信JDK,实现短信发送!!!
腾讯云原文地址,原文更详细,我下面的代码略有修改,只保留了与发送短信相关的代码。https://cloud.tencent.com/document/product/382/43194#.E5.8F.91.E9.80.81.E7.9F.AD.E4.BF.A1腾讯云短信控制台: https://console.cloud.tencent.com/smsv2 短信签名、模板ID、短信应用ID项目pom文件引入腾讯云短信接口的sdk <dependency> <groupId>com.tencentcloudapi</groupId> <artifactId>tencentcloud-sdk-java</artifactId> <!-- go to https://search.maven.org/search?q=tencentcloud-sdk-java and get the latest version. --> <!-- 请到https://search.maven.org/search?q=tencentcloud-sdk-java查询所有版本,最新版本如下 --> <version>3.1.612</version> </dependency>配置tencentCloud.properties文件在resources目录下,用于保存腾讯云的用户API密钥tencent.cloud.secretId=AKc6Si**********BtQmvtiMo5me5S tencent.cloud.secretKey=NYWIuK**********spdIE1fPW tencent.cloud.sdkAppId=短信应用ID tencent.cloud.signName=短信签名内容 tencent.cloud.templateId=模板 ID创建一个实体类,用于读取密钥与短信相关配置@Component @Data @PropertySource(value = "classpath:tencentCloud.properties", encoding = "UTF-8") @ConfigurationProperties(prefix = "tencent.cloud") public class TencentCloudProperties { // 腾讯云账户密钥对 private String secretId; private String secretKey; // 短信应用ID private String sdkAppId ; // 短信签名内容 private String signName ; // 模板 ID private String templateId ; }将发送短信相关代码封装成一个工具类 经过封装后,调用该方法时只需传入手机号码和验证码,事后会返回SDK的一个短信发送结果封装类SendSmsResponse。package com.achong.utils; import com.achong.bean.TencentCloudProperties; import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.sms.v20210111.SmsClient; // 注意 SendSmsRequest 和 SendSmsResponse 是在同一个包下 import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest; import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class SMSUtils { @Autowired private TencentCloudProperties tencentCloudProperties; /** * 发送短信 post请求 */ public SendSmsResponse sendSMS(String phone, String verCode){ System.out.println("=========================================="); System.out.println(tencentCloudProperties.toString()); System.out.println("=========================================="); // 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey。 Credential cred = new Credential(tencentCloudProperties.getSecretId(), tencentCloudProperties.getSecretKey()); /* 实例化要请求产品的client对象 * 第一个参数是认证对象 * 第二个参数是地域信息,可以直接填写字符串ap-guangzhou,支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */ SmsClient client = new SmsClient(cred, "ap-guangzhou"); // 实例化一个请求对象,根据调用的接口和实际情况,可以进一步设置请求参数 SendSmsRequest request = new SendSmsRequest(); /** * 以下是填充请求信息 */ /* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId,示例如1400006666 */ // 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看 request.setSmsSdkAppId(tencentCloudProperties.getSdkAppId()); /* 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名 */ // 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看 request.setSignName(tencentCloudProperties.getSignName()); /* 模板 ID: 必须填写已审核通过的模板 ID */ // 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看 request.setTemplateId(tencentCloudProperties.getTemplateId()); /* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */ String[] templateParamSet = {verCode}; request.setTemplateParamSet(templateParamSet); /* 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号] * 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号 */ String[] phoneNumberSet = {"86" + phone}; request.setPhoneNumberSet(phoneNumberSet); /* 通过 client 对象调用 SendSms 方法发起请求。注意请求方法名与请求对象是对应的 * 返回的 response 是一个 SendSmsResponse 类的实例,与请求对象对应 */ SendSmsResponse response = null; try { response = client.SendSms(request); } catch (TencentCloudSDKException e) { e.printStackTrace(); } // 输出json格式的字符串回包 System.out.println(SendSmsResponse.toJsonString(response)); //方法将返回 短信发送结果 的对象 return response; } } 创建Controller调用上面封装的工具类发送短信进行测试。package com.achong.controller; import com.achong.utils.SMSUtils; import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class SendSMSController { @Autowired private SMSUtils smsUtils; @RequestMapping("/sendSms") public void sendSms(String phone){ if (phone == null || phone == "" || phone.length() != 11) { System.out.println("手机号错误"); return; } // 本地生成四位数验证码,短信位数可调整 10000 的位数 String code = (int)((Math.random() * 9 + 1) * 10000) + ""; // 调用工具类发送短信,参数分别是 手机号码 和 验证码。 SendSmsResponse response = smsUtils.sendSMS(phone, code); // 格式化打印输出短信发送结果 System.out.println(SendSmsResponse.toJsonString(response)); // 拿到 短信发送结果 里的 Code 字段,该字段表示 短信是否发送成功 String status = response.getSendStatusSet()[0].getCode(); if ("Ok".equals(status)){ System.out.println("发送成功,状态码:"+status); }else { System.out.println("发送失败,状态码:"+status); } } } 浏览器测试访问地址:http://localhost:8080/sendSms?phone=17310101010发送成功后,页面会返回短信发送结果,格式为 JSON字符串,其中Code字段为短信发送结果,成功则该字段为Ok,否则是其他错误信息。该字段可以作为判断短信发送是否成功的依据。 { "SendStatusSet": [{ "SerialNo": "3369:76164835516668596094641947", 发送流水号。 "PhoneNumber": "+8617310101010", 手机号码,E.164标准,+[国家或地区码][手机号] ,示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号。 "Fee": 1, 计费条数 "SessionContext": "", 用户 session 内容。 "Code": "Ok", 短信请求错误码 "Message": "send success", 短信请求错误码描述。 "IsoCode": "CN" 国家码或地区码,例如 CN、US 等,对于未识别出国家码或者地区码,默认返回 DEF }], "RequestId": "b9a8468f-12bb-4985-bda7-5592d56f98bd" }
2022年10月27日
57 阅读
0 评论
2 点赞
1
2
...
5