项目7:实现短信的发送和验证
1.对gulimall-common补充
2.短信验证的流程(aliyun的sms)
3.具体接口的编写(新建微服务service-sms)
4.上传和删除文件流程(aliyun的oss)
5.具体接口的编写(新建微服务service-oos)
未更新
项目7:实现短信的发送和验证
1.引入工具包
①gulimall-common和service-base放什么?
- gulimall-common写全局用的工具包
全局异常处理
全局返回值
工具包(生成随机数,校验手机号) - service-base写服务的配置
redis配置类序列化的方式
swagger文档生成分组
②生成四位或六位随机数
package com.atguigu.common.util;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
/**
* 生成四位和六位的随机数字
*/
public class RandomUtils {
private static final Random random = new Random();
private static final DecimalFormat fourdf = new DecimalFormat("0000");
private static final DecimalFormat sixdf = new DecimalFormat("000000");
public static String getFourBitRandom() {
return fourdf.format(random.nextInt(10000));
}
public static String getSixBitRandom() {
return sixdf.format(random.nextInt(1000000));
}
/**
* 给定数组,抽取n个数据
* @param list
* @param n
* @return
*/
public static ArrayList getRandom(List list, int n) {
Random random = new Random();
HashMap<Object, Object> hashMap = new HashMap<Object, Object>();
// 生成随机数字并存入HashMap
for (int i = 0; i < list.size(); i++) {
int number = random.nextInt(100) + 1;
hashMap.put(number, i);
}
// 从HashMap导入数组
Object[] robjs = hashMap.values().toArray();
ArrayList r = new ArrayList();
// 遍历数组并打印数据
for (int i = 0; i < n; i++) {
r.add(list.get((int) robjs[i]));
System.out.print(list.get((int) robjs[i]) + "\t");
}
System.out.print("\n");
return r;
}
}
③校验手机号码正确
package com.atguigu.common.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 使用正则表达式进行表单验证
*/
public class RegexValidateUtils {
static boolean flag = false;
static String regex = "";
public static boolean check(String str, String regex) {
try {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
flag = matcher.matches();
} catch (Exception e) {
flag = false;
}
return flag;
}
/**
* 验证邮箱
*
* @param email
* @return
*/
public static boolean checkEmail(String email) {
String regex = "^\\w+[-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$ ";
return check(email, regex);
}
/**
* 验证手机号码
*
* 移动号码段:139、138、137、136、135、134、150、151、152、157、158、159、182、183、187、188、147
* 联通号码段:130、131、132、136、185、186、145
* 电信号码段:133、153、180、189
*
* @param cellphone
* @return
*/
public static boolean checkCellphone(String cellphone) {
String regex = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$";
return check(cellphone, regex);
}
/**
* 验证固话号码
*
* @param telephone
* @return
*/
public static boolean checkTelephone(String telephone) {
String regex = "^(0\\d{2}-\\d{8}(-\\d{1,4})?)|(0\\d{3}-\\d{7,8}(-\\d{1,4})?)$";
return check(telephone, regex);
}
/**
* 验证传真号码
*
* @param fax
* @return
*/
public static boolean checkFax(String fax) {
String regex = "^(0\\d{2}-\\d{8}(-\\d{1,4})?)|(0\\d{3}-\\d{7,8}(-\\d{1,4})?)$";
return check(fax, regex);
}
/**
* 验证QQ号码
*
* @param QQ
* @return
*/
public static boolean checkQQ(String QQ) {
String regex = "^[1-9][0-9]{4,} $";
return check(QQ, regex);
}
}
④补充错误代码-501阿里云响应失败
2.短信验证的流程(aliyun的sms)
注意:将每个微服务的日志写到改成其下面的包
<property name="log.path" value="F:/Project_shangrongbao/java/srb/srb-log/core" />
<property name="log.path" value="F:/Project_shangrongbao/java/srb/srb-log/oss" />
<property name="log.path" value="F:/Project_shangrongbao/java/srb/srb-log/sms" />
①申请aliyun短信服务
- 需要申请签名
- 需要申请模板
- 需要有访问的key-id和key-secret(访问aliyun的api)
②短信验证流程
- 前端写手机号码,单击发送验证码
- 后端进行处理(接收手机号码参数)
验证手机号码是否正确
生成验证码
通过aliyun发送验证码给手机号码
将验证码存入redis
返回结果 - aliyun发送验证码
利用账号密码签名模板
利用手机号发送的验证码
远程连接aliyun控制台并发送验证码
返回响应结果 - 注意:
异常处理时,抛出自定义异常,在返回异常结果的同时也会打印异常跟踪栈
3.具体接口的编写(新建微服务service-sms)
①引入pom
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>srb</artifactId>
<groupId>com.atguigu</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-sms</artifactId>
<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-base</artifactId>
<version>1.0-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>
<!-- 配置文件处理器 -->
<!--让自定义的配置在application.yaml进行自动提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
主启动
package com.atguigu.srb.sms;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
//项目直接的互相调用,可以直接扫描到(不要写到具体包下,写到项目下即可)
@ComponentScan({"com.atguigu.srb","com.atguigu.common"})
public class ServiceSmsApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceSmsApplication.class, args);
}
}
②编写具体的配置application.yml
server:
port: 8120 # 服务端口
spring:
profiles:
active: dev # 环境设置
application:
name: service-sms # 服务名
#spring:
redis:
host: localhost
port: 6379
database: 0
timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
#连接池的连接
lettuce:
pool:
max-active: 20 #最大连接数,负值表示没有限制,默认8
max-wait: -1 #最大阻塞等待时间,负值表示没限制,默认-1
max-idle: 8 #最大空闲连接,默认8
min-idle: 0 #最小空闲连接,默认0
#阿里云短信
aliyun:
sms:
region-id:
key-id:
key-secret:
template-code:
sign-name:
写日志配置文章来源:https://www.toymoban.com/news/detail-418749.html
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--标志位,区分不同的应用程序-->
<contextName>atguiguSrb</contextName>
<!-- 日志的输出目录 -->
<property name="log.path" value="F:/Project_shangrongbao/java/srb/srb-log" />
<!--控制台日志格式:彩色日志-->
<!-- magenta:洋红 -->
<!-- boldMagenta:粗红-->
<!-- cyan:青色 -->
<!-- white:白色 -->
<!-- magenta:洋红 -->
<property name="CONSOLE_LOG_PATTERN"
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) %highlight([%-5level]) %green(%logger) %msg%n"/>
<!--文件日志格式-->
<property name="FILE_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n" />
<!--编码-->
<property name="ENCODING"
value="UTF-8" />
<!-- 控制台日志 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- 文件日志 -->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${log.path}/log.log</file>
<append>true</append>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!--名称即为包名了,其包下面的文件都会被日志记录器管理-->
<!--file和console都打印-->
<!--环境配置了此不用配置-->
<!-- 日志记录器 -->
<!--<logger name="com.atguigu" level="INFO">-->
<!--<appender-ref ref="CONSOLE" />-->
<!--<appender-ref ref="FILE" />-->
<!--</logger>-->
<!--设置滚动日志,时间的滚动策略-->
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 要区别于其他的appender中的文件名字 -->
<file>${log.path}/log-rolling.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
<!-- 设置滚动日志记录的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-rolling-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--归档日志文件保留的最大数量-->
<maxHistory>15</maxHistory>
<!--包含上size,防止一天的日志文件过大,超过下面的大小,再分-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1024kb</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<!--多环境配置-->
<!-- 开发环境和测试环境 -->
<!--name和application.yml配合使用-->
<springProfile name="dev,test">
<logger name="com.atguigu" level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING_FILE" />
</logger>
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<logger name="com.atguigu" level="ERROR">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING_FILE" />
</logger>
</springProfile>
</configuration>
③创建能够读取配置文件的util
package com.atguigu.srb.sms.util;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
//没有自动感知,即会发生上面的 spring boot configurtion annotation processor not found in classpath
//
@Setter
@Getter //idea2020.2.3版配置文件自动提示需要这个
@Component
//InitializingBean接口里面的抽象方法为设置properties完成之后自动调用的方法
//注意prefix要写到最后一个 "." 符号之前
//调用setter为成员赋值
@ConfigurationProperties(prefix = "aliyun.sms")
public class SmsProperties implements InitializingBean {
//spring自动根据application.yml赋值给下面值,即自动将_格式转换为驼峰
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;
}
}
注意spring-boot-configuration-processor包即用来在xml中自动提示有前缀的配置,需要配合在idea中如下配置
文章来源地址https://www.toymoban.com/news/detail-418749.html
④写controller
package com.atguigu.srb.sms.controller.api;
import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.R;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.common.util.RandomUtils;
import com.atguigu.common.util.RegexValidateUtils;
import com.atguigu.srb.sms.service.SmsService;
import com.atguigu.srb.sms.util.SmsProperties;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@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("短信发送成功");
}
}
⑤service层
package com.atguigu.srb.sms.service;
import java.util.Map;
public interface SmsService {
//手机号,模板的编号,模板的参数
void send(String mobile, String templateCode, Map<String,Object> param);
}
package com.atguigu.srb.sms.service.impl;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.atguigu.common.exception.Assert;
import com.atguigu.common.exception.BusinessException;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.sms.service.SmsService;
import com.atguigu.srb.sms.util.SmsProperties;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@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);
}
}
}
4.上传和删除文件流程(aliyun的oss)
①申请oss服务
- bucket名称
- endpoint地域网址
(读写权限为公共读) - 访问oss文件地址为
http://buctet名称.endpoint/文件 - 文件设计:module+日期+UUID.后缀名
②微服务远程调用
- 利用id和密码
- 利用bucketname和endpoint
- 上传文件
利用id和密码和endpoint获取到连接
前端上传文件后后端获取文件然后根据文件获取到输入流,上传文件到bucketname,指明文件名和输入流
5.具体接口的编写(新建微服务service-oos)
①引入pom和主启动
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>srb</artifactId>
<groupId>com.atguigu</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-oss</artifactId>
<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-base</artifactId>
<version>1.0-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>
</project>
package com.atguigu.srb.oss;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan({"com.atguigu.srb", "com.atguigu.common"})
public class ServiceOssApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceOssApplication.class, args);
}
}
②编写yml和xml
server:
port: 8130 # 服务端口
spring:
profiles:
active: dev # 环境设置
application:
name: service-oss # 服务名
aliyun:
oss:
endpoint:
keyId:
keySecret:
bucketName:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--标志位,区分不同的应用程序-->
<contextName>atguiguSrb</contextName>
<!-- 日志的输出目录 -->
<property name="log.path" value="F:/Project_shangrongbao/java/srb/srb-log/oss" />
<!--控制台日志格式:彩色日志-->
<!-- magenta:洋红 -->
<!-- boldMagenta:粗红-->
<!-- cyan:青色 -->
<!-- white:白色 -->
<!-- magenta:洋红 -->
<property name="CONSOLE_LOG_PATTERN"
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) %highlight([%-5level]) %green(%logger) %msg%n"/>
<!--文件日志格式-->
<property name="FILE_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n" />
<!--编码-->
<property name="ENCODING"
value="UTF-8" />
<!-- 控制台日志 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- 文件日志 -->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${log.path}/log.log</file>
<append>true</append>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!--名称即为包名了,其包下面的文件都会被日志记录器管理-->
<!--file和console都打印-->
<!--环境配置了此不用配置-->
<!-- 日志记录器 -->
<!--<logger name="com.atguigu" level="INFO">-->
<!--<appender-ref ref="CONSOLE" />-->
<!--<appender-ref ref="FILE" />-->
<!--</logger>-->
<!--设置滚动日志,时间的滚动策略-->
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 要区别于其他的appender中的文件名字 -->
<file>${log.path}/log-rolling.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
<!-- 设置滚动日志记录的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-rolling-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--归档日志文件保留的最大数量-->
<maxHistory>15</maxHistory>
<!--包含上size,防止一天的日志文件过大,超过下面的大小,再分-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1024kb</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<!--多环境配置-->
<!-- 开发环境和测试环境 -->
<!--name和application.yml配合使用-->
<springProfile name="dev,test">
<logger name="com.atguigu" level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING_FILE" />
</logger>
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<logger name="com.atguigu" level="ERROR">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING_FILE" />
</logger>
</springProfile>
</configuration>
③编写util绑定属性
package com.atguigu.srb.oss.util;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@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;
}
}
④编写controller层
package com.atguigu.srb.oss.controller.api;
import com.atguigu.common.exception.BusinessException;
import com.atguigu.common.result.R;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.oss.service.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
@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();
//返回的为上传的url地址
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);
}
}
@ApiOperation("删除OSS文件")
@DeleteMapping("/remove")
public R remove(
@ApiParam(value = "要删除的文件路径", required = true)
@RequestParam("url") String url) {
fileService.removeFile(url);
return R.ok().message("删除成功");
}
}
⑤编写service层
package com.atguigu.srb.oss.service;
import java.io.InputStream;
public interface FileService {
/**
* 文件上传至阿里云
*/
//module是放到哪个文件夹下,filename是文件名
String upload(InputStream inputStream, String module, String fileName);
/**
* 根据路径删除文件
* @param url
*/
void removeFile(String url);
}
package com.atguigu.srb.oss.service.impl;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.atguigu.srb.oss.service.FileService;
import com.atguigu.srb.oss.util.OssProperties;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.UUID;
@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的Bucket实例是否存在:如果不存在则创建,如果存在则获取
if(!ossClient.doesBucketExist(OssProperties.BUCKET_NAME)){
//创建bucket
ossClient.createBucket(OssProperties.BUCKET_NAME);
//设置oss实例的访问权限:公共读
ossClient.setBucketAcl(OssProperties.BUCKET_NAME, CannedAccessControlList.PublicRead);
}
//avatar为module
//构建日期路径: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;
}
/**
* 根据路径删除文件
* @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();
}
}
未更新
未更新
未更新
未更新
未更新
未更新
未更新
未更新
未更新
到了这里,关于项目7:(aliyun)实现短信的发送和验证微服务和上传文件删除文件微服务的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!