9、阿里云短信
9.1、阿里云短信服务
9.1.1、使用RAM子用户
9.1.1.1、进入子用户管理页面


9.1.1.2、添加用户

9.1.1.3、获取子用户key
AccessKeyId, AccessKeySecret
9.1.1.4、设置用户权限
授权:AliyunDysmsFullAccess

9.1.2、开通短信服务
9.1.2.1、开通


9.1.2.2、添加签名

9.1.2.3、添加模板


9.1.2.4、套餐
free.aliyun.com

9.1.2.5、快速学习

9.1.3、测试短信发送
9.1.3.1、查找使用示例

9.1.3.2、测试短信发送


9.1.3.3、查看发送结果
短信服务->业务统计->发送记录查询
9.2、创建短信微服务
9.2.1、需求


9.2.2、创建项目
9.2.2.1、创建模块
service-sms
9.2.2.2、配置 pom.xml
<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-base</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok用来简化实体类:需要安装lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--阿里云短信-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
</dependencies>
9.2.2.3、application.yml
resources目录下创建文件
server:
port: 8120 # 服务端口
spring:
profiles:
active: dev # 环境设置
application:
name: service-sms # 服务名
#spring:
redis:
host: 192.168.100.100
port: 6379
database: 0
password: 123456 #默认为空
timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
lettuce:
pool:
max-active: 20 #最大连接数,负值表示没有限制,默认8
max-wait: -1 #最大阻塞等待时间,负值表示没限制,默认-1
max-idle: 8 #最大空闲连接,默认8
min-idle: 0 #最小空闲连接,默认0
#阿里云短信
aliyun:
sms:
region-id: cn-hangzhou
key-id: 你的keyid
key-secret: 你的keysecret
template-code: 你的短信模板code
sign-name: 你的短信模板签名
9.2.2.4、logback-spring.xml
9.2.2.5、创建SpringBoot启动类
package com.atguigu.srb.sms;
@SpringBootApplication
@ComponentScan({"com.atguigu.srb", "com.atguigu.common"})
public class ServiceSmsApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceSmsApplication.class, args);
}
}
9.2.3、自定义配置
9.2.3.1、从配置文件读取常量
创建常量读取工具类:SmsProperties.java
package com.atguigu.srb.sms.util;
@Setter
@Getter //idea2020.2.3版配置文件自动提示需要这个
@Component
//注意prefix要写到最后一个 "." 符号之前
//调用setter为成员赋值
@ConfigurationProperties(prefix = "aliyun.sms")
public class SmsProperties implements InitializingBean {
private String regionId;
private String keyId;
private String keySecret;
private String templateCode;
private String signName;
public static String REGION_Id;
public static String KEY_ID;
public static String KEY_SECRET;
public static String TEMPLATE_CODE;
public static String SIGN_NAME;
//当私有成员被赋值后,此方法自动被调用,从而初始化常量
@Override
public void afterPropertiesSet() throws Exception {
REGION_Id = regionId;
KEY_ID = keyId;
KEY_SECRET = keySecret;
TEMPLATE_CODE = templateCode;
SIGN_NAME = signName;
}
}
Idea报告如下错误信息(不影响程序的编译和运行):

解决方案参考文档:

解决步骤:
- step1:添加依赖
<!-- 配置文件处理器 -->
<!--让自定义的配置在application.yaml进行自动提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
- step2:启动processor

-
step3:重新编译模块
-
step4:这样就可以在yml文件中有自定义配置的提示信息啦
9.2.3.2、测试工具类
创建测试类 UtilsTests,测试配置信息是否能正常获取
package com.atguigu.srb.sms;
@SpringBootTest
@RunWith(SpringRunner.class)
public class UtilsTests {
@Test
public void testProperties(){
System.out.println(SmsProperties.KEY_ID);
System.out.println(SmsProperties.KEY_SECRET);
System.out.println(SmsProperties.REGION_Id);
}
}
9.2.4、发送短信
9.2.4.1、短信发送业务
接口:创建 SmsService
package com.atguigu.srb.sms.service;
public interface SmsService {
void send(String mobile, String templateCode, Map<String,Object> param);
}
实现:创建 SmsServiceImpl
package com.atguigu.srb.sms.service.impl;
@Service
@Slf4j
public class SmsServiceImpl implements SmsService {
@Override
public void send(String mobile, String templateCode, Map<String,Object> param) {
//创建远程连接客户端对象
DefaultProfile profile = DefaultProfile.getProfile(
SmsProperties.REGION_Id,
SmsProperties.KEY_ID,
SmsProperties.KEY_SECRET);
IAcsClient client = new DefaultAcsClient(profile);
//创建远程连接的请求参数
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
request.putQueryParameter("RegionId", SmsProperties.REGION_Id);
request.putQueryParameter("PhoneNumbers", mobile);
request.putQueryParameter("SignName", SmsProperties.SIGN_NAME);
request.putQueryParameter("TemplateCode", templateCode);
Gson gson = new Gson();
String json = gson.toJson(param);
request.putQueryParameter("TemplateParam", json);
try {
//使用客户端对象携带请求对象发送请求并得到响应结果
CommonResponse response = client.getCommonResponse(request);
boolean success = response.getHttpResponse().isSuccess();
//ALIYUN_RESPONSE_FAIL(-501, "阿里云响应失败"),
Assert.isTrue(success, ResponseEnum.ALIYUN_RESPONSE_FAIL);
String data = response.getData();
HashMap<String, String> resultMap = gson.fromJson(data, HashMap.class);
String code = resultMap.get("Code");
String message = resultMap.get("Message");
log.info("阿里云短信发送响应结果:");
log.info("code:" + code);
log.info("message:" + message);
//ALIYUN_SMS_LIMIT_CONTROL_ERROR(-502, "短信发送过于频繁"),//业务限流
Assert.notEquals("isv.BUSINESS_LIMIT_CONTROL", code, ResponseEnum.ALIYUN_SMS_LIMIT_CONTROL_ERROR);
//ALIYUN_SMS_ERROR(-503, "短信发送失败"),//其他失败
Assert.equals("OK", code, ResponseEnum.ALIYUN_SMS_ERROR);
} catch (ServerException e) {
log.error("阿里云短信发送SDK调用失败:");
log.error("ErrorCode=" + e.getErrCode());
log.error("ErrorMessage=" + e.getErrMsg());
throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR , e);
} catch (ClientException e) {
log.error("阿里云短信发送SDK调用失败:");
log.error("ErrorCode=" + e.getErrCode());
log.error("ErrorMessage=" + e.getErrMsg());
throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR , e);
}
}
}
9.2.4.2、引入工具类
guigu-common中创建util包,引入工具类:
RandomUtils.java:生成四位或六位的验证码
RegexValidateUtils.java:常用正则表达式验证,这里提供了手机号码验证
9.2.4.3、创建controller
创建controller.api包,创建类ApiSmsController
package com.atguigu.srb.sms.controller.api;
@RestController
@RequestMapping("/api/sms")
@Api(tags = "短信管理")
@CrossOrigin //跨域
@Slf4j
public class ApiSmsController {
@Resource
private SmsService smsService;
@Resource
private RedisTemplate redisTemplate;
@ApiOperation("获取验证码")
@GetMapping("/send/{mobile}")
public R send(
@ApiParam(value = "手机号", required = true)
@PathVariable String mobile){
//MOBILE_NULL_ERROR(-202, "手机号不能为空"),
Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);
//MOBILE_ERROR(-203, "手机号不正确"),
Assert.isTrue(RegexValidateUtils.checkCellphone(mobile), ResponseEnum.MOBILE_ERROR);
//生成验证码
String code = RandomUtils.getFourBitRandom();
//组装短信模板参数
Map<String,Object> param = new HashMap<>();
param.put("code", code);
//发送短信
smsService.send(mobile, SmsProperties.TEMPLATE_CODE, param);
//将验证码存入redis
redisTemplate.opsForValue().set("srb:sms:code:" + mobile, code, 5, TimeUnit.MINUTES);
return R.ok().message("短信发送成功");
}
}
9.2.5、配置Swagger
9.2.5.1、添加配置
service-base中添加网站端api的配置
@Bean
public Docket apiConfig(){
return new Docket(DocumentationType.SWAGGER_2)
.groupName("api")
.apiInfo(apiInfo())
.select()
//只显示admin路径下的页面
.paths(Predicates.and(PathSelectors.regex("/api/.*")))
.build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("尚融宝-API文档")
.description("本文档描述了尚融宝接口")
.version("1.0")
.contact(new Contact("Helen", "http://atguigu.com", "55317332@qq.com"))
.build();
}
9.2.5.2、测试
测试正确发送
测试手机号码不正确
测试业务限流
10、分布式文件系统-阿里云OSS
10.1、阿里云存储OSS
10.1.1、开通“对象存储OSS”服务
为了解决海量数据存储与弹性扩容,项目中我们采用云存储的解决方案- 阿里云OSS。
10.1.1.1、开通“对象存储OSS”服务


10.1.1.2、进入管理控制台

10.1.2、控制台使用
10.1.2.1、创建Bucket
命名:srb-file
读写权限:公共读
10.1.2.2、上传默认头像
创建文件夹avatar,上传默认的用户头像

10.1.3、使用RAM子用户
10.1.3.1、进入子用户管理页面


10.1.3.2、添加用户

10.1.3.3、获取子用户key
AccessKeyId, AccessKeySecret
10.1.3.4、设置用户权限
AliyunOSSFullAccess

10.2、使用SDK访问OSS
10.2.1、使用SDK
在OSS的概览页右下角找到“Bucket管理”,点击“OSS学习路径”

点击“Java SDK”进入SDK开发文档

10.2.2、创建测试项目
10.2.2.1、创建Maven项目
com.atguigu
aliyun-oss
10.2.2.2、配置pom

<dependencies>
<!--aliyunOSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
10.2.3、测试用例
10.2.3.1、创建Bucket

package com.atguigu.aliyunoss;
public class OSSTest {
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "your endpoint";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
String accessKeyId = "your accessKeyId";
String accessKeySecret = "your accessKeySecret";
String bucketName = "srb-file";
@Test
public void testCreateBucket() {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 创建存储空间。
ossClient.createBucket(bucketName);
// 关闭OSSClient。
ossClient.shutdown();
}
}
10.2.3.2、判断bucket是否存在
@Test
public void testExist() {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
boolean exists = ossClient.doesBucketExist(bucketName);
System.out.println(exists);
// 关闭OSSClient。
ossClient.shutdown();
}
10.2.3.3、设置bucket访问权限
@Test
public void testAccessControl() {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 设置存储空间的访问权限为:公共读。
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
// 关闭OSSClient。
ossClient.shutdown();
}
10.3、创建OSS微服务
10.3.1、新建云存储微服务
10.3.1.1、创建模块
service-oss
10.3.1.2、配置pom.xml
<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-base</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok用来简化实体类:需要安装lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--aliyunOSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!-- 日期工具栏依赖 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!--让自定义的配置在application.yaml进行自动提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
10.3.1.3、配置application.yml
server:
port: 8130 # 服务端口
spring:
profiles:
active: dev # 环境设置
application:
name: service-oss # 服务名
aliyun:
oss:
endpoint: 你的endponit
keyId: 你的阿里云keyid
keySecret: 你的阿里云keysecret
bucketName: srb-file
10.3.1.4、logback-spring.xml
修改日志路径为 srb_log/oss
10.3.1.5、创建启动类
创建ServiceOssApplication.java
package com.atguigu.srb.oss;
@SpringBootApplication
@ComponentScan({"com.atguigu.srb", "com.atguigu.common"})
public class ServiceOssApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceOssApplication.class, args);
}
}
10.3.1.6、启动项目
10.3.2、实现文件上传
10.3.2.1、从配置文件读取常量
创建常量读取工具类:OssProperties.java
package com.atguigu.srb.oss.util;
@Setter
@Getter
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class OssProperties implements InitializingBean {
private String endpoint;
private String keyId;
private String keySecret;
private String bucketName;
public static String ENDPOINT;
public static String KEY_ID;
public static String KEY_SECRET;
public static String BUCKET_NAME;
//当私有成员被赋值后,此方法自动被调用,从而初始化常量
@Override
public void afterPropertiesSet() throws Exception {
ENDPOINT = endpoint;
KEY_ID = keyId;
KEY_SECRET = keySecret;
BUCKET_NAME = bucketName;
}
}
10.3.2.2、文件上传业务
创建Service接口:FileService.java
package com.atguigu.srb.oss.service;
public interface FileService {
/**
* 文件上传至阿里云
*/
String upload(InputStream inputStream, String module, String fileName);
}
实现:FileServiceImpl.java
参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流

package com.atguigu.srb.oss.service.impl;
@Service
public class FileServiceImpl implements FileService {
/**
* 文件上传至阿里云
*/
@Override
public String upload(InputStream inputStream, String module, String fileName) {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(
OssProperties.ENDPOINT,
OssProperties.KEY_ID,
OssProperties.KEY_SECRET);
//判断oss实例是否存在:如果不存在则创建,如果存在则获取
if(!ossClient.doesBucketExist(OssProperties.BUCKET_NAME)){
//创建bucket
ossClient.createBucket(OssProperties.BUCKET_NAME);
//设置oss实例的访问权限:公共读
ossClient.setBucketAcl(OssProperties.BUCKET_NAME, CannedAccessControlList.PublicRead);
}
//构建日期路径:avatar/2019/02/26/文件名
String folder = new DateTime().toString("yyyy/MM/dd");
//文件名:uuid.扩展名
fileName = UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf("."));
//文件根路径
String key = module + "/" + folder + "/" + fileName;
//文件上传至阿里云
ossClient.putObject(OssProperties.BUCKET_NAME, key, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
//阿里云文件绝对路径
return "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT + "/" + key;
}
}
10.3.2.3、控制层
创建controller.api:FileController.java
package com.atguigu.srb.oss.controller.api;
@Api(tags = "阿里云文件管理")
@CrossOrigin //跨域
@RestController
@RequestMapping("/api/oss/file")
public class FileController {
@Resource
private FileService fileService;
/**
* 文件上传
*/
@ApiOperation("文件上传")
@PostMapping("/upload")
public R upload(
@ApiParam(value = "文件", required = true)
@RequestParam("file") MultipartFile file,
@ApiParam(value = "模块", required = true)
@RequestParam("module") String module) {
try {
InputStream inputStream = file.getInputStream();
String originalFilename = file.getOriginalFilename();
String uploadUrl = fileService.upload(inputStream, module, originalFilename);
//返回r对象
return R.ok().message("文件上传成功").data("url", uploadUrl);
} catch (IOException e) {
throw new BusinessException(ResponseEnum.UPLOAD_ERROR, e);
}
}
}
10.3.2.4、Swagger测试
10.3.3、实现文件删除
10.3.3.1、业务层
Service接口:FileService.java
/**
* 根据路径删除文件
* @param url
*/
void removeFile(String url);
实现:FileServiceImpl.java
/**
* 根据路径删除文件
* @param url
*/
@Override
public void removeFile(String url) {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(
OssProperties.ENDPOINT,
OssProperties.KEY_ID,
OssProperties.KEY_SECRET);
//文件名(服务器上的文件路径)
String host = "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT + "/";
String objectName = url.substring(host.length());
// 删除文件。
ossClient.deleteObject(OssProperties.BUCKET_NAME, objectName);
// 关闭OSSClient。
ossClient.shutdown();
}
10.3.3.2、控制层
@ApiOperation("删除OSS文件")
@DeleteMapping("/remove")
public R remove(
@ApiParam(value = "要删除的文件路径", required = true)
@RequestParam("url") String url) {
fileService.removeFile(url);
return R.ok().message("删除成功");
}
本文章参考B站 尚硅谷《尚融宝》Java微服务分布式金融项目,仅供个人学习使用,部分内容为本人自己见解,与尚硅谷无关。
475

被折叠的 条评论
为什么被折叠?



