最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringCloud-Alibaba之OSS對象存儲服務(wù)使用詳解

 更新時間:2026年03月29日 10:41:31   作者:A塵埃  
這篇文章主要介紹了SpringCloud-Alibaba之OSS對象存儲服務(wù)使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

阿里云的OSS服務(wù)進(jìn)行云端的文件存儲

用戶認(rèn)證需要上傳圖片、首頁輪播需要上傳圖片,OSS分布式文件服務(wù)系統(tǒng)可以提供服務(wù)。

  • 一般項(xiàng)目使用OSS對象存儲服務(wù),主要是對圖片、文件、音頻等對象集中式管理權(quán)限控制,管理數(shù)據(jù)生命周期等等,提供上傳,下載,預(yù)覽,刪除等功能。
  • 通過OSS部署前端項(xiàng)目

一、依賴

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>aliyun-oss-spring-boot-starter</artifactId>
</dependency>

二、在配置文件中配置

OSS 服務(wù)對應(yīng)的 accessKey、secretKey 和 endpoint

alibaba.cloud.access-key=your-ak
alibaba.cloud.secret-key=your-sk
alibaba.cloud.oss.endpoint=***

阿里云 accessKey、secretKey 為例,獲取方式如下

①、在阿里云控制臺界面,單擊右上角頭像,選擇 accesskeys,或者直接登錄用戶信息管理界面:

②、獲取 accessKey、secretKey:

如果使用了阿里云 STS服務(wù) 進(jìn)行短期訪問權(quán)限管理,則除了 accessKey、secretKey、endpoint 以外,還需配置 securityToken

③、創(chuàng)建Bucket

進(jìn)入Bucket,上傳文件,可以查看上傳文件的詳情(URL用來訪問該文件)

三、注入OSSClient并進(jìn)行文件上傳下載等操作

大量文件對象操作的場景。

@Service
public class YourService{
	
	@Autowired
	private OSSClient ossClient;

	public void saveFile(){
		//下載文件到本地
		ossClient.getObject(new GetObejctRequest(bucketName,objectName),new File("pathOfYourLocalFile"));
	}
}

如果是僅僅讀取文件對象內(nèi)容,OSS Starter也支持以Resource方式讀取文件

①、在應(yīng)用的 /src/main/resources/application.properties 中添加基本配置信息和 OSS 配置

spring.application.name=oss-example
server.port=18084
alibaba.cloud.access-key=your-ak
alibaba.cloud.secret-key=your-sk
alibaba.cloud.oss.endpoint=***

②、通過IDE直接啟動或者編譯打包后啟動應(yīng)用

  • IDE直接啟動:找到主類 OSSApplication,執(zhí)行 main 方法啟動應(yīng)用
  • 打包編譯后啟動,執(zhí)行 mvn clean package 將工程編譯打包;執(zhí)行 java -jar oss-example.jar啟動應(yīng)用應(yīng)用啟動后會自動在 OSS 上創(chuàng)建一個名為 aliyun-spring-boot-test 的 Bucke
@Value("oss://aliyun-spring-boot/oss-test")
private Resource file;

//文件內(nèi)容讀取
StreamUtils.copyToString(file.getInputStream(),Charset.forName(CharEncoding.UTF_8));

上傳或下載文件

#使用 curl 調(diào)用上傳接口 upload。該接口會上傳 classpath 下的的 oss-test.json 文件。文件內(nèi)容是一段 json:
curl http://localhost:18084/upload

#使用 curl 調(diào)用下載接口 download。該接口會下載剛才用 upload 接口上傳的 oss-test.json 文件,并打印文件內(nèi)容到結(jié)果中:
curl http://localhost:18084/download

在OSS上驗(yàn)證結(jié)果

登陸OSS控制臺,可以看到左側(cè) Bucket 列表新增一個名字為aliyun-spring-boot-test的 Bucket。

單擊aliyun-spring-boot-test Bucket,選擇 文件管理 頁簽,發(fā)現(xiàn)上傳的 oss-test 文件。上傳的 objectName 為oss-test.json。目錄和文件以’/'符號分割。

實(shí)戰(zhàn)操作

一、導(dǎo)入依賴

<!--阿里云OSS依賴-->
<dependency>
	<groupId>com.aliyun.oss</groupId>
	<artifactId>aliyun-sdk-oss</artifactId>
</dependency>

<!--日期工具欄依賴-->
<dependency>
	<groupId>joda-time</groupId>
	<artifactId>joda-time</artifactId>
</dependency>

配置文件application.properties

server.port=8205
spring.application.name=service-oss

spring.jackson.data-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

spring.redis.host=192.168.44.165
spring.redis.port=6379
spring.redis.database=0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1

#最大阻塞等待時間(附屬表示沒限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848


aliyun.oss.accessKeyId=
aliyun.oss.secret=
@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)//無需加載數(shù)據(jù)庫
@EnableDiscoveryClient
@ComponentScan(basePackages={"com.michael"})
public class ServiceOssApplication{
	public static void main(String[] args){
		SpringApplication.run(ServiceOssApplication.class,args);
	}
}

二、網(wǎng)關(guān)模塊gateway中進(jìn)行對上傳oss模塊進(jìn)行配置

spring.cloud.gateway.routes[4].id=service-oss
spring.cloud.gateway.routes[4].uri=lb://service-oss
spring.cloud.gateway.routes[4].predicates=Path=/*/oss/**

三、文件流的方式上傳

Controller

@RestController
@RequestMapping("/api/oss/file")
public class FileApiController{

	@Autowired
	private FileService fileService;
	
	//將本地文件上傳到阿里云
	@PostMapping("fileUpload")
	public Result fileUpLoad(MultipartFile file){//SpringMVC中的,可以得到要上傳的內(nèi)容
		
		//返回上傳后的路徑
		String url = fileService.upload(file);
		return Result.ok(url);
	}
}

Service

public interface FileService{
	String upload(MultipartFile file);
}
@Service
public class FileServiceImpl implements FileService{
	
	@Override
	public String upload(MultipartFile file){
	
		//以下變量可以設(shè)置到配置文件中,然后通過工具類讀取
		String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
		String accessKeyId = "";
		String accessKeySecret = "";
		String bucket = "";
		
		//創(chuàng)建OSSClient實(shí)例
		OSS occClient = new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);
		
		//上傳文件流
		try{
			InputStream inputStream = file.getInputStream();//從Controller中獲取用戶上傳的文件流
			String fileName = file.getOriginalFilename();//獲取文件名稱(包括路徑)
			
			/**
				由于同名原因會導(dǎo)致文件上傳的覆蓋問題,后上傳的覆蓋前上傳的
			*/
			//采用uuid生成唯一值,添加到文件名稱里(并且將里面的-用空串表示)
			String uuid = UUID.randomUUID().toString().replaceAll("-","");
			fileName = uuid+fileName;
			
			//按照日期創(chuàng)建文件夾,上傳到創(chuàng)建文件夾的里面(joda-time日期工具依賴)
			String timeUrl = new DateTime().toString("yyyy/MM/dd");
			fileName = timeUrl + "/" + fileName;
			

			ossClient.putObject(bucket,fileName,inputStream);

			//關(guān)閉OSSClient
			ossClient.shutdown();

			//上傳之后的路徑,可以從阿里云工作臺的文件詳情獲取
			String url = "https://"+bucketName+"."+endpoint+"/"+fileName;
			return url;
		}catch(IOException e){
			e.printStackTrace();
		}
		
	}
}

基于AmazonS3實(shí)現(xiàn) Spring Boot Starter

Amazon Simple Storage Service(Amazon S3,Amazon簡便存儲服務(wù))是 AWS 最早推出的云服務(wù)之一,經(jīng)過多年的發(fā)展,S3 協(xié)議在對象存儲行業(yè)事實(shí)上已經(jīng)成為標(biāo)準(zhǔn)。

  • 提供了統(tǒng)一的接口 REST/SOAP 來統(tǒng)一訪問任何數(shù)據(jù)
  • 對 S3 來說,存在里面的數(shù)據(jù)就是對象名(鍵),和數(shù)據(jù)(值)
  • 不限量,單個文件最高可達(dá) 5TB,可動態(tài)擴(kuò)容
  • 高速。每個 bucket 下每秒可達(dá) 3500 PUT/COPY/POST/DELETE 或 5500 GET/HEAD 請求
  • 具備版本,權(quán)限控制能力
  • 具備數(shù)據(jù)生命周期管理能力

阿里云OSS兼容S3

七牛云對象存儲兼容S3

騰訊云COS兼容S3

Minio兼容S3

今天使用的是阿里云OSS對接阿里云OSS的SDK

后天我們使用的是騰訊COS對接是騰訊云COS,我們何不直接對接AmazonS3實(shí)現(xiàn)呢,這樣后續(xù)不需要調(diào)整代碼,只需要去各個云服務(wù)商配置就好了。

一、創(chuàng)建一個SpringBoot項(xiàng)目

添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 -->
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-s3</artifactId>
    <version>${aws.version}</version>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-core</artifactId>
    <version>${hutool.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>

二、配置文件OssProperties

oss.endpoint=xxx
oss.accessKey=xxx
oss.secretKey=xxx

@ConfigurationProperties(prefix = “oss”):將配置文件中oss開頭的屬性綁定到此對象中

@Data
@ConfigurationProperties(prefix = "oss")
public class OssProperties{
	
	   /**
     * 對象存儲服務(wù)的URL
     */
    private String endpoint;

    /**
     * 區(qū)域
     */
    private String region;

    /**
     * true path-style nginx 反向代理和S3默認(rèn)支持 pathStyle模式 {http://endpoint/bucketname}
     * false supports virtual-hosted-style 阿里云等需要配置為 virtual-hosted-style 模式{http://bucketname.endpoint}
     * 只是url的顯示不一樣
     */
    private Boolean pathStyleAccess = true;

    /**
     * Access key
     */
    private String accessKey;

    /**
     * Secret key
     */
    private String secretKey;

    /**
     * 最大線程數(shù),默認(rèn):100
     */
    private Integer maxConnections = 100;
}

三、創(chuàng)建接口OssTemplate

public interface OssTemplate{
	
	void createBucket(String bucketName);//創(chuàng)建bucket
	
	List<Bucket> getAllBuckets();//獲取所有的bucket
	
	void removeBucket(String bucketName);//通過bucket名稱刪除bucket

	//上傳文件
	void putObject(String bucketName, String objectName, InputStream stream, String contextType) throws Exception;

	void putObject(String bucketName, String objectName, InputStream stream) throws Exception;
	
	//獲取文件
	S3Object getObject(String bucketName, String objectName);

	//獲取對象的url
	String getObjectURL(String bucketName, String objectName, Integer expires);
	
	//通過bucketName和objectName刪除對象
	void removeObject(String bucketName, String objectName) throws Exception;
	 
	//根據(jù)文件前置查詢文件
	List<S3ObjectSummary> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive);
}
@RequiredArgsConstructor
public class OssTemplateImpl implements OssTemplate{
	
	private final AmazonS3 amazonS3;

	//創(chuàng)建Bucket
	@Override
	@SneakyThrows
	public void createBucket(String bucketName){
		if ( !amazonS3.doesBucketExistV2(bucketName) ) {
            amazonS3.createBucket((bucketName));
        }
	}

	//獲取所有的buckets
	@Override
    @SneakyThrows
    public List<Bucket> getAllBuckets() {
        return amazonS3.listBuckets();
    }

	//通過Bucket名稱刪除Bucket
	@Override
    @SneakyThrows
    public void removeBucket(String bucketName) {
        amazonS3.deleteBucket(bucketName);
    }

	//上傳對象
	@Override
    @SneakyThrows
    public void putObject(String bucketName, String objectName, InputStream stream, String contextType) {
        putObject(bucketName, objectName, stream, stream.available(), contextType);
    }

	@Override
    @SneakyThrows
    public void putObject(String bucketName, String objectName, InputStream stream) {
        putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");
    }

	//通過bucketName和objectName獲取對象
	@Override
    @SneakyThrows
    public S3Object getObject(String bucketName, String objectName) {
        return amazonS3.getObject(bucketName, objectName);
    }

	//獲取對象的url
	@Override
    @SneakyThrows
    public String getObjectURL(String bucketName, String objectName, Integer expires) {
        Date date = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, expires);
        URL url = amazonS3.generatePresignedUrl(bucketName, objectName, calendar.getTime());
        return url.toString();
    }

	//通過bucketName和objectName刪除對象
	@Override
    @SneakyThrows
    public void removeObject(String bucketName, String objectName) {
        amazonS3.deleteObject(bucketName, objectName);
    }

	//根據(jù)bucketName和prefix獲取對象集合
	@Override
    @SneakyThrows
    public List<S3ObjectSummary> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
        ObjectListing objectListing = amazonS3.listObjects(bucketName, prefix);
        return objectListing.getObjectSummaries();
    }

	@SneakyThrows
    private PutObjectResult putObject(String bucketName, String objectName, InputStream stream, long size,
                                     String contextType)  {

        byte[] bytes = IOUtils.toByteArray(stream);
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(size);
        objectMetadata.setContentType(contextType);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        // 上傳
        return amazonS3.putObject(bucketName, objectName, byteArrayInputStream, objectMetadata);

    }
}
}

四、創(chuàng)建OssAutoConfiguration

OssAutoConfiguration:自動裝配配置類,自動裝配的bean有AmazonS3和OssTemplate

@Configuration
@RequiredArgsConstructor //lomnok的注解,替代@Autowired
@EnableConfigurationProperties(OssProperties.class) //自動裝配我們的配置類
public class OssAutoConfiguration{
	
	@Bean
	@ConditionalOnMissingBean//bean被注冊之后,注冊相同類型的bean,就不會成功,它會保證你的bean只有一個,即你的實(shí)例只有一個。多個會報錯
	public AmazonS3 ossClient(OssProperties ossProperties){
		
		//客戶端配置,主要是全局的配置信息
		ClientConfiguration cientConfiguration = new ClientConfiguration();
		clientConfiguration.setMaxConnections(ossProperties.getMaxConnections());
		
		//url以及region配置
		AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder
			.EndpointConfiguration(ossProperties.getEndpoint(), ossProperties.getRegion());

		//憑證配置
		AWSCredentials awsCredentials = new BasicAWSCredentials(ossProperties.getAccessKey(),
                ossProperties.getSecretKey());
        AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
		
		// build amazonS3Client客戶端
        return AmazonS3Client.builder().withEndpointConfiguration(endpointConfiguration)
                .withClientConfiguration(clientConfiguration).withCredentials(awsCredentialsProvider)
                .disableChunkedEncoding().withPathStyleAccessEnabled(ossProperties.getPathStyleAccess()).build();
	}

	@Bean
	@ConditionalOnBean(AmazonS3.class)//當(dāng)給定的在bean存在時,則實(shí)例化當(dāng)前Bean
	public OssTemplate ossTemplate(AmazonS3 amazonS3){
		return new OssTemplateImpl(amazonS3);
	}
}

五、ClientConfiguration對象

客戶端配置,主要是全局的配置信息

六、創(chuàng)建spring.factories

在resources目錄下新增META-INF包,下面新建spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.qing.oss.OssAutoConfiguration

七、執(zhí)行install打包到本地倉庫

把springboot工程的啟動類,配置文件干掉,干掉Test包。

最重要的是干掉pom文件的spring-boot-maven-plugin,要不然install報錯。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

這樣我們的一個oss-spring-boot-starter就完成了

執(zhí)行install打包成jar到我們的本地倉庫

到我們的本地倉庫就能看到我們的oss-spring-boot-starter

八、測試

創(chuàng)建一個spring-boot工程當(dāng)作我們的測試工程

①、pom文件新增我們的oss-spring-boot-starter依賴

<properties>
    <oss.version>0.0.1-SNAPSHOT</oss.version>
</properties>
<dependency>
    <groupId>com.qing</groupId>
    <artifactId>oss-spring-boot-starter</artifactId>
    <version>${oss.version}</version>
</dependency>

刷新maven后可以看到我們依賴加進(jìn)來了。

解決打包沒有注釋的問題

可以發(fā)現(xiàn)我們的依賴沒有注釋沒有Javadoc注釋,在oss-string-boot-starter的pom文件下加入下面插件,重新install一下就好了。

<build>
        <plugins>
            <!-- 在打好的jar包中保留javadoc注釋,實(shí)際會另外生成一個xxxxx-sources.jar -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

在我們的測試項(xiàng)目里面刷新一下maven可以看到已經(jīng)帶注釋了

配置文件添加oss-spring-boot-starter所需要的配置

阿里云,騰訊cos,七牛云,minio等等的配置。

以Minio為例

oss.endpoint=xxx
oss.accessKey=xxx
oss.secretKey=xxx

編寫測試方法

@SpringBootTest
class TestOssSpringBpptStarterApplicationTests {
    @Autowired
    private OssTemplate ossTemplate;

    @Test
    void contextLoads() {
        ossTemplate.createBucket("oss02");
    }

}

到我的Minio中查看發(fā)現(xiàn)測試成功。

Controller

@Slf4j
@RestController
@RequestMapping("/oss")
public class OSSController{
	
	//上傳服務(wù)
	@PostMapping("/upload")
	public Response<Map<String,String>> upload(@RequestParam MultipartFile file, @RequestParam(required = false) String ossType)
									throws IOException {
		
		OSSTypeEnum ossTypeEnum = OSSTypeEnum.ALIYUN;//阿里云
		if(StringUtils.isNotEmpty(ossType)){
			ossTypeEnum = Enum.valueOf(OSSTypeEnum.class,ossType);
		}

		String originalFilename = file.getOriginalFilename();
		InputStream inputStream = file.getInputStream();
		final OSSTypeEnum finalOssTypeEnum = ossTypeEnum;

		Optional<OSSService> optional = OSSContext.getBeans(OSSService.class).stream()//通過spring上下文獲取
										.filter(item -> item.support(finalOssTypeEnum))
										.findFirst();
		
		//com.google.guava:guava:20.0
		Map<String,String> result = Maps.newConcurrentMap();
		if(optional.isPresent()){
			String url = optional.get().uploadStream(inputStream,priginalFilename);
			log.info("文件上傳的URL = {}", url);
			result.put("name",originalFilename);
			result.put("url",url);
		}else{
			return Response.toError(ResponseStatus.Code.FAIL_CODE, "未找到可用的云服務(wù)器");
		}

		return Reponse.toResponse(result);
	}
	
	//下載服務(wù)(參數(shù):文件路徑、文件名稱、云服務(wù)器類型、響應(yīng)流)
	@ReqeustMapping("/download")
	public void download(@RequestParam(required = false) String ossKey,
						@RequestParam(required = false) String fileName,
                        @RequestParam(required = false) String ossType,
                         HttpServletResponse response)throws Exception{
		
		//得到要下載的文件
		String suffix = ossKey.substring(ossKey.lastIndexOf("."));
		//hutool-all:4.1.14
		String transFilename = DateUtil.formatDate(new Date()) + "-" + fileName + suffix;
		
		//設(shè)置響應(yīng)頭
		response.setContentType("application/octet-stream");
		response.setCharacterEncoding("UTF-8");
		response.setHeader("content-disposition", "attachment;filename=" + URLUtil.encode(transFilename, "UTF-8"));
		
		final OSSTypeEnum finalOssTypeEnum = Enum.valueOf(OSSTypeEnum.class, ossType);
		Optional<OSSService> optional = OSSContext.getBeans(OSSService.class).stream()
										.filter(item -> item.support(finalOssTypeEnum)).findFirst();
		if(optional.isPresent()){
			//文件輸入流
			InputStream in = optional.get().download(ossKey);
			//創(chuàng)建輸出流
			OutputStream out = response.getOutputStram();
			FileUtil.write(in,out);
		}
	}
}

Service接口

public interface OSSService {

    /**
     * 支持ossType 類型
     *
     * @param ossType OSSType枚舉
     * @return true 支持
     */
    boolean support(final OSSTypeEnum ossType);

    /**
     * 上傳文件
     *
     * @param is       文件流
     * @param fileName 文件名稱
     * @return 上傳的文件路徑
     */
    String uploadStream(final InputStream is, final String fileName);


    /**
     * 上傳文件
     *
     * @param file     源文件
     * @param fileName 文件名稱
     * @return 上傳的文件路徑
     */
    String uploadFile(final File file, final String fileName);

    /**
     * 字節(jié)數(shù)組上傳
     *
     * @param data     字節(jié)數(shù)組
     * @param fileName 文件名
     * @return 上傳的文件路徑
     */
    String uploadToByte(final byte[] data, final String fileName);

    /**
     * 根據(jù)文件key下載獲取文件流
     *
     * @param ossKey 文件key
     * @return
     */
    InputStream download(final String ossKey);
}
@Service("ALIYUN")
@Slf4j
public class AliyunServiceImpl implements OSSService{
	
	@Autowired(required = false)
	private OSS oss;//aliyun-sdk-oss:3.1.0 

	@Value("${alibaba.cloud.bucket}")
	private String bucket;//桶

	@Override
	public boolean support(final OSSTypeEnum ossType){
		return OSSTypeEnum.ALIYUN.equals(ossType);
	}

	@Override
	public String uploadStream(final InputStream is,final String fileName){
		
		String url = null;
		String tempFileName = fileName;

		try{
			String suffix = tempFileName.substring(tempFileName.lastIndexOf(SConsts.POINT) + IConsts.ONE);
			
			//上傳的文件key
			tempFileName = suffix + SConsts.SLASH
                    + DateUtils.format(DateUtils.dateTime(), DateUtils.NORM_DATE_PATTERN)
                    + SConsts.SLASH + tempFileName;
			//創(chuàng)建上傳Object的Metadata  aliyun-sdk-oss:3.1.0
			ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(is.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(FileUtil.getContentType(SConsts.POINT + suffix));
            objectMetadata.setContentDisposition("inline;filename=" + tempFileName);
			
			oss.putObject(bucket, tempFileName, is, objectMetadata);

			// 獲取oss 文件地址
            url = oss.generatePresignedUrl(bucket, tempFileName, 
            								new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10)).toString();

            log.info("上傳后的地址 url = {}", url);
		}catch(Exception e){
			log.error("上傳文件失敗");
		}
		return url;
	}

	@Override
    public String uploadFile(final File file, final String fileName) {
        try {
            return this.uploadStream(new FileInputStream(file), fileName);
        } catch (FileNotFoundException e) {
            log.error("源文件不存在,文件名稱 fileName = {}", fileName);
        }
        return null;
    }

    @Override
    public String uploadToByte(final byte[] data, final String fileName) {
        return this.uploadStream(new ByteArrayInputStream(data), fileName);
    }

    @Override
    public InputStream download(final String ossKey) {

        OSSObject ossObject = oss.getObject(bucket, ossKey);
        return ossObject.getObjectContent();
    }
}
@Service("QINIU")
@Slf4j
@EnableConfigurationProperties(QiniuProperties.class)
public class QiniuServiceImpl implements OSSService {

    @Autowired(required = false)
    private UploadManager uploadManager;
    @Autowired(required = false)
    private Auth auth;
    @Autowired(required = false)
    private QiniuProperties qiniuProperties;

    @Override
    public boolean support(final OSSTypeEnum ossType) {
        return OSSTypeEnum.QINIU.equals(ossType);
    }

    @Override
    public String uploadStream(InputStream is, String fileName) {
        try {

            String key = qiniuProperties.getBucket() + '/' + DateUtils.format(LocalDateTime.now(), DateUtils.NORM_DATE_PATTERN) + "/" + fileName;
            Response response = uploadManager.put(is, key, this.getToken(), null, null);
            if (response.isOK()) {
                DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
                return putRet.key;
            }

        } catch (QiniuException e) {
            throw new RuntimeException("上傳文件失敗");
        }
        return null;
    }

    @Override
    public String uploadFile(File file, String fileName) {

        if (!file.exists()) {
            throw new RuntimeException("上傳的文件不存在");
        }
        try {
            return this.uploadStream(new FileInputStream(file), fileName);
        } catch (FileNotFoundException e) {
            log.error("文件不存在");
        }
        return null;
    }


    @Override
    public String uploadToByte(byte[] data, String fileName) {
        try {
            Response response = uploadManager.put(data, fileName, this.getToken());
            if (response.isOK()) {
                DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
                return putRet.key;
            }
        } catch (QiniuException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public InputStream download(String ossKey) {

        try {
            String encodedFileName = URLEncoder.encode(ossKey, "utf-8").replace("+", "%20");
            String publicUrl = String.format("%s/%s", qiniuProperties.getEndpoint(), encodedFileName);
            String url = auth.privateDownloadUrl(publicUrl, 3600); //1小時,可以自定義鏈接過期時間

            return FileUtil.getRemoteFile(url);
        } catch (Exception e) {
            log.error("獲取文件流失敗");
        }
        return null;
    }

    /**
     * 獲取上傳token
     *
     * @return 上傳token
     */
    private String getToken() {
        return auth.uploadToken(qiniuProperties.getBucket());
    }

}

七牛

<dependency>
    <groupId>com.qiniu</groupId>
    <artifactId>qiniu-java-sdk</artifactId>
    <version>[7.2.0, 7.2.99]</version>
</dependency>

工具類

//七牛文件上傳
public class QiniuUpload{
	
	private static final String URL = "http://pp7x7b2mm.bkt.clouddn.com/";

	/**
     * 上傳文件
     *
     * @param file   上傳的文件
     * @param folder 文件路徑
     * @return 文件全路徑
     */
    public static String uploadToFile(File file, String folder) {
        return URL + UploadConfiguration.uploadFile(file, folder);
    }

    /**
     * 數(shù)據(jù)流文件上傳
     *
     * @param is       輸入流
     * @param fileName 上傳文件名
     * @return 文件全路徑
     */
    public static String uploadToStream(InputStream is, String fileName) {
        return URL + UploadConfiguration.uploadStream(is, fileName);
    }

    /**
     * 字節(jié)數(shù)組上傳
     *
     * @param data     字節(jié)數(shù)組
     * @param fileName 文件名
     * @return 文件全路徑
     */
    public static String uploadToByte(byte[] data, String fileName) {
        return URL + UploadConfiguration.uploadToByte(data, fileName);
    }
	
}
//七牛存儲配置
class UploadConfiguration {

    /**
     * 獲取上傳的token值
     */
    private static String getToken() {

        Auth auth = Auth.create(SysConfigMap.get(SysConfigKeys.QINIU_ACCESS_KEY), SysConfigMap.get(SysConfigKeys.QINIU_SECRET_KEY));

        return auth.uploadToken(SysConfigMap.get(SysConfigKeys.QINIU_BUCKET));
    }


    /**
     * 獲取設(shè)置的UploadManager配置中心
     */
    private static UploadManager getUploadManager() {
        Configuration configuration = new Configuration(Region.region0());
        return new UploadManager(configuration);
    }

    static String uploadStream(InputStream is, String fileName) {
        UploadManager uploadManager = UploadConfiguration.getUploadManager();
        try {

            String key = SysConfigMap.get(SysConfigKeys.QINIU_BUCKET) + '/' + DateUtils.format(LocalDateTime.now(), DateUtils.NORM_DATE_PATTERN) + "/" + fileName;
            Response response = uploadManager.put(is, key, UploadConfiguration.getToken(), null, null);
            if (response.isOK()) {
                DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
                return putRet.key;
            }

        } catch (QiniuException e) {
            throw new RuntimeException("上傳文件失敗");
        }
        return null;
    }

    static String uploadFile(File file, String folder) {
        UploadManager uploadManager = UploadConfiguration.getUploadManager();

        if (!file.exists()) {
            throw new RuntimeException("上傳的文件不存在");
        }
        StringBuilder builder = new StringBuilder();
        if (!StringUtils.isNullOrEmpty(folder)) {
            builder.append(folder);
        }
        builder.append(file.getName());

        try {
            Response response = uploadManager.put(file, builder.toString(), UploadConfiguration.getToken());
            if (response.isOK()) {
                return JSON.parseObject(response.bodyString(), DefaultPutRet.class).key;
            }

        } catch (QiniuException e) {
            throw new RuntimeException("上傳文件失敗");
        }
        return null;
    }

    /**
     * 字節(jié)數(shù)組上傳
     *
     * @param data     字節(jié)數(shù)組
     * @param fileName 文件名
     */
    static String uploadToByte(byte[] data, String fileName) {
        UploadManager uploadManager = UploadConfiguration.getUploadManager();
        try {
            Response response = uploadManager.put(data, fileName, UploadConfiguration.getToken());
            if (response.isOK()) {
                DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
                return putRet.key;
            }
        } catch (QiniuException e) {
            e.printStackTrace();
        }
        return null;
    }
}

阿里云

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>aliyun-oss-spring-boot-starter</artifactId>
</dependency>

騰訊云

<dependency>
    <groupId>com.tencentcloudapi</groupId>
    <artifactId>tencentcloud-sdk-java</artifactId>
    <version>3.1.162</version>
</dependency>

OSS項(xiàng)目實(shí)戰(zhàn)

①、Controller

  • @HasPermissions(“sys:oss:config”) 注解配合切面
  • ValidatorUtils工具類
@RestController
@RequestMapping("system/oss")
public class OssController extends BaseController {

    private final static String KEY = CloudConstant.CLOUD_STORAGE_CONFIG_KEY;

    @Autowired
    private IOssService ossService;

    @Autowired
    private IConfigService configService;
	
	//云存儲配置信息
	@ReqeustMapping("config")
	@HasPermissions("sys:oss:config")
	public CloudStorageConfig config(){
		
		String jsonConfig = configService.selectConfigByKey(CloudConstant.CLOUD_STORAGE_CONFIG_KEY);
		
		//獲取云存儲配置信息(fastjson-1.2.74字符串轉(zhuǎn)換成對象)
		CloudStorageConfig config = JSON.parseObject(jsonConfig,CloudStorageConfig.class); 
		return config;
	}

	//保存云存儲配置信息
	@RequestMapping("saveConfig")
    @HasPermissions("sys:oss:config")
    public R SaveConfig(){
		
		//校驗(yàn)類型
		ValidatorUtils.validateEntity(config);
		if (config.getType() == CloudService.QINIU.getValue()) {
            // 校驗(yàn)七牛數(shù)據(jù)
            ValidatorUtils.validateEntity(config, QiniuGroup.class);
        } else if (config.getType() == CloudService.ALIYUN.getValue()) {
            // 校驗(yàn)阿里云數(shù)據(jù)
            ValidatorUtils.validateEntity(config, AliyunGroup.class);
        } else if (config.getType() == CloudService.QCLOUD.getValue()) {
            // 校驗(yàn)騰訊云數(shù)據(jù)
            ValidatorUtils.validateEntity(config, QcloudGroup.class);
        }
        return toAjax(configService.updateValueByKey(KEY, new Gson().toJson(config)));
	}
}

注解@HasPermissions(“sys:oss:config”) 和權(quán)限

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HasPermissions {
    String value();
}
@Aspect
@Component
@Slf4j
public class PreAuthorizeAspect {

    @Autowired
    private IMenuService sysMenuService;
	
	@Around("@annotation(com.ruoyi.system.auth.annotation.HasPermissions)")
	public Object around(ProceedingJoinPoint point)throws Throwable{
		
		Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();//獲取切點(diǎn)(注解修飾的)方法

		//根據(jù)方法,獲取注解類型
		HasPermissions annotation = method.getAnnotation(HasPermissions.class);
        if (annotation == null) {
            return point.proceed();
        }
        
        String authority = new StringBuilder(annotation.value()).toString();//sys:oss:config
        if(has(authority)){
        	return point.proceed();
        }else{
        	throw new ForbiddenException();
        }
	}

	private boolean has(String authority){
		
		//用超管賬號方便測試
		HttpServletRequest request = ServletUtils.getRequest();
		String tmpUserKey = request.getHeader(Constants.CURRENT_ID);//current_id
        if (Optional.ofNullable(tmpUserKey).isPresent()) {
            Long userId = Long.valueOf(tmpUserKey);
            log.debug("userid:{}", userId);
            if (userId == 1L) {
                return true;
            }
            return sysMenuService.selectPermsByUserId(userId).stream().anyMatch(authority::equals);
        }
		return false;
	}
}

工具類

/**
 * 客戶端工具類
 *
 * @author ruoyi
 */
public class ServletUtils {
    /**
     * 獲取String參數(shù)
     */
    public static String getParameter(String name) {
        return getRequest().getParameter(name);
    }

    /**
     * 獲取String參數(shù)
     */
    public static String getParameter(String name, String defaultValue) {
        return Convert.toStr(getRequest().getParameter(name), defaultValue);
    }

    /**
     * 獲取Integer參數(shù)
     */
    public static Integer getParameterToInt(String name) {
        return Convert.toInt(getRequest().getParameter(name));
    }

    /**
     * 獲取Integer參數(shù)
     */
    public static Integer getParameterToInt(String name, Integer defaultValue) {
        return Convert.toInt(getRequest().getParameter(name), defaultValue);
    }

    /**
     * 獲取request
     */
    public static HttpServletRequest getRequest() {
        return getRequestAttributes().getRequest();
    }

    /**
     * 獲取response
     */
    public static HttpServletResponse getResponse() {
        return getRequestAttributes().getResponse();
    }

    /**
     * 獲取session
     */
    public static HttpSession getSession() {
        return getRequest().getSession();
    }

    public static ServletRequestAttributes getRequestAttributes() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        return (ServletRequestAttributes) attributes;
    }

    /**
     * 將字符串渲染到客戶端
     *
     * @param response 渲染對象
     * @param string   待渲染的字符串
     * @return null
     */
    public static String renderString(HttpServletResponse response, String string) {
        try {
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(string);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 是否是Ajax異步請求
     *
     * @param request
     */
    public static boolean isAjaxRequest(HttpServletRequest request) {
        String accept = request.getHeader("accept");
        if (accept != null && accept.indexOf("application/json") != -1) {
            return true;
        }

        String xRequestedWith = request.getHeader("X-Requested-With");
        if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) {
            return true;
        }

        String uri = request.getRequestURI();
        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) {
            return true;
        }

        String ajax = request.getParameter("__ajax");
        if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) {
            return true;
        }
        return false;
    }
}

/**
	hibernate-validator校驗(yàn)工具類
*/
public class ValidatorUtils{
	
	private static Validator validator;

	static{
		//validation-api-2.0.1.Final
		validator = Validation.buildDefaultValidatorFactory().getValidator();
	}

	/**
     * 校驗(yàn)對象
     *
     * @param object 待校驗(yàn)對象
     * @param groups 待校驗(yàn)的組
     * @throws BaseException 校驗(yàn)不通過,則報BaseException異常
     */
	public static void validateEntity(Object object, Class<?>... groups)throws BaseException{
		
		Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) {
            ConstraintViolation<Object> constraint = (ConstraintViolation<Object>) constraintViolations.iterator()
                    .next();
            throw new BaseException(constraint.getMessage());
        }
	}
}

查詢權(quán)限的業(yè)務(wù)

  • 主鍵緩存@RedisCache(key = “user_perms”, fieldKey = “#userId”)
/**
 * 菜單 業(yè)務(wù)層處理
 *
 * @author ruoyi
 */
@Service
public class MenuServiceImpl implements IMenuService {

    public static final String PREMISSION_STRING = "perms[\"{0}\"]";

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    /**
     * 根據(jù)用戶查詢菜單
     *
     * @param user 用戶信息
     * @return 菜單列表
     */
    @Override
    public List<Menu> selectMenusByUser(User user) {
        List<Menu> menus = new LinkedList<>();
        // 管理員顯示所有菜單信息
        if (User.isAdmin(user.getUserId())) {
            menus = menuMapper.selectMenuNormalAll();
        } else {
            menus = menuMapper.selectMenusByUserId(user.getUserId());
        }
        return menus;
    }

    /**
     * 查詢菜單集合
     *
     * @return 所有菜單信息
     */
    @Override
    public List<Menu> selectMenuList(Menu menu) {
        return menuMapper.selectMenuList(menu);
    }

    /**
     * 查詢菜單集合
     *
     * @return 所有菜單信息
     */
    @Override
    @DataScope(parkAlias = "m")
    public List<Menu> selectMenuAll() {
        return menuMapper.selectMenuAll();
    }

    /**
     * 根據(jù)用戶ID查詢權(quán)限
     *
     * @param userId 用戶ID
     * @return 權(quán)限列表
     */
    @Override
    @RedisCache(key = "user_perms", fieldKey = "#userId")
    public Set<String> selectPermsByUserId(Long userId) {
        List<String> perms = menuMapper.selectPermsByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (String perm : perms) {
            if (StringUtils.isNotEmpty(perm)) {
                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
            }
        }
        return permsSet;
    }

    @Override
    public List<Menu> selectMenuIdsByRoleId(Long roleId) {
        return menuMapper.selectMenuIdsByRoleId(roleId);
    }

    /**
     * 根據(jù)角色I(xiàn)D查詢菜單
     *
     * @param role 角色對象
     * @return 菜單列表
     */
    @Override
    public List<Ztree> roleMenuTreeData(Role role) {
        Long roleId = role.getRoleId();
        List<Ztree> ztrees = new ArrayList<Ztree>();
        List<Menu> menuList = menuMapper.selectMenuAll();
        if (StringUtils.isNotNull(roleId)) {
            List<String> roleMenuList = menuMapper.selectMenuTree(roleId);
            ztrees = initZtree(menuList, roleMenuList, true);
        } else {
            ztrees = initZtree(menuList, null, true);
        }
        return ztrees;
    }

    /**
     * 查詢所有菜單
     *
     * @return 菜單列表
     */
    @Override
    public List<Ztree> menuTreeData() {
        List<Menu> menuList = menuMapper.selectMenuAll();
        List<Ztree> ztrees = initZtree(menuList);
        return ztrees;
    }

    /**
     * 查詢系統(tǒng)所有權(quán)限
     *
     * @return 權(quán)限列表
     */
    @Override
    public LinkedHashMap<String, String> selectPermsAll() {
        LinkedHashMap<String, String> section = new LinkedHashMap<>();
        List<Menu> permissions = menuMapper.selectMenuAll();
        if (StringUtils.isNotEmpty(permissions)) {
            for (Menu menu : permissions) {
                section.put(menu.getMenuName(), MessageFormat.format(PREMISSION_STRING, menu.getPerms()));
            }
        }
        return section;
    }

    /**
     * 對象轉(zhuǎn)菜單樹
     *
     * @param menuList 菜單列表
     * @return 樹結(jié)構(gòu)列表
     */
    public List<Ztree> initZtree(List<Menu> menuList) {
        return initZtree(menuList, null, false);
    }

    /**
     * 對象轉(zhuǎn)菜單樹
     *
     * @param menuList     菜單列表
     * @param roleMenuList 角色已存在菜單列表
     * @param permsFlag    是否需要顯示權(quán)限標(biāo)識
     * @return 樹結(jié)構(gòu)列表
     */
    public List<Ztree> initZtree(List<Menu> menuList, List<String> roleMenuList, boolean permsFlag) {
        List<Ztree> ztrees = new ArrayList<Ztree>();
        boolean isCheck = StringUtils.isNotNull(roleMenuList);
        for (Menu menu : menuList) {
            Ztree ztree = new Ztree();
            ztree.setId(menu.getMenuId());
            ztree.setpId(menu.getParentId());
            ztree.setName(transMenuName(menu, roleMenuList, permsFlag));
            ztree.setTitle(menu.getMenuName());
            if (isCheck) {
                ztree.setChecked(roleMenuList.contains(menu.getMenuId() + menu.getPerms()));
            }
            ztrees.add(ztree);
        }
        return ztrees;
    }

    public String transMenuName(Menu menu, List<String> roleMenuList, boolean permsFlag) {
        StringBuffer sb = new StringBuffer();
        sb.append(menu.getMenuName());
        if (permsFlag) {
            sb.append("<font color=\"#888\">&nbsp;&nbsp;&nbsp;" + menu.getPerms() + "</font>");
        }
        return sb.toString();
    }

    /**
     * 刪除菜單管理信息
     *
     * @param menuId 菜單ID
     * @return 結(jié)果
     */
    @Override
    public int deleteMenuById(Long menuId) {
        return menuMapper.deleteMenuById(menuId);
    }

    /**
     * 根據(jù)菜單ID查詢信息
     *
     * @param menuId 菜單ID
     * @return 菜單信息
     */
    @Override
    public Menu selectMenuById(Long menuId) {
        return menuMapper.selectMenuById(menuId);
    }

    /**
     * 查詢子菜單數(shù)量
     *
     * @param parentId 父級菜單ID
     * @return 結(jié)果
     */
    @Override
    public int selectCountMenuByParentId(Long parentId) {
        return menuMapper.selectCountMenuByParentId(parentId);
    }

    /**
     * 查詢菜單使用數(shù)量
     *
     * @param menuId 菜單ID
     * @return 結(jié)果
     */
    @Override
    public int selectCountRoleMenuByMenuId(Long menuId) {
        return roleMenuMapper.selectCountRoleMenuByMenuId(menuId);
    }

    /**
     * 新增保存菜單信息
     *
     * @param menu 菜單信息
     * @return 結(jié)果
     */
    @Override
    public int insertMenu(Menu menu) {
        return menuMapper.insertMenu(menu);
    }

    /**
     * 修改保存菜單信息
     *
     * @param menu 菜單信息
     * @return 結(jié)果
     */
    @Override
    public int updateMenu(Menu menu) {
        return menuMapper.updateMenu(menu);
    }

    /**
     * 校驗(yàn)菜單名稱是否唯一
     *
     * @param menu 菜單信息
     * @return 結(jié)果
     */
    @Override
    public String checkMenuNameUnique(Menu menu) {
        Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
        Menu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
        if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) {
            return UserConstants.MENU_NAME_NOT_UNIQUE;
        }
        return UserConstants.MENU_NAME_UNIQUE;
    }

    /**
     * 根據(jù)父節(jié)點(diǎn)的ID獲取所有子節(jié)點(diǎn)
     *
     * @param list     分類表
     * @param parentId 傳入的父節(jié)點(diǎn)ID
     * @return String
     */
    public List<Menu> getChildPerms(List<Menu> list, int parentId) {
        List<Menu> returnList = new ArrayList<Menu>();
        for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext(); ) {
            Menu t = (Menu) iterator.next();
            // 一、根據(jù)傳入的某個父節(jié)點(diǎn)ID,遍歷該父節(jié)點(diǎn)的所有子節(jié)點(diǎn)
            if (t.getParentId() == parentId) {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 遞歸列表
     *
     * @param list
     * @param t
     */
    private void recursionFn(List<Menu> list, Menu t) {
        // 得到子節(jié)點(diǎn)列表
        List<Menu> childList = getChildList(list, t);
        t.setChildren(childList);
        for (Menu tChild : childList) {
            if (hasChild(list, tChild)) {
                // 判斷是否有子節(jié)點(diǎn)
                Iterator<Menu> it = childList.iterator();
                while (it.hasNext()) {
                    Menu n = (Menu) it.next();
                    recursionFn(list, n);
                }
            }
        }
    }

    /**
     * 得到子節(jié)點(diǎn)列表
     */
    private List<Menu> getChildList(List<Menu> list, Menu t) {
        List<Menu> tlist = new ArrayList<Menu>();
        Iterator<Menu> it = list.iterator();
        while (it.hasNext()) {
            Menu n = (Menu) it.next();
            if (n.getParentId().longValue() == t.getMenuId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判斷是否有子節(jié)點(diǎn)
     */
    private boolean hasChild(List<Menu> list, Menu t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }
}

②、實(shí)體類

/**
 * 云存儲配置信息
 *
 * @author jack
 */
@Data
public class CloudStorageConfig implements Serializable {
    private static final long serialVersionUID = 9035033846176792944L;

    // 類型 1:七牛 2:阿里云 3:騰訊云
    @Range(min = 1, max = 3, message = "類型錯誤")//hibernate-validator-6.1.6.Final
    private Integer type;

    // 七牛綁定的域名(validation-api-2.0.1.Final)
    @NotBlank(message = "七牛綁定的域名不能為空", groups = QiniuGroup.class)
    @URL(message = "七牛綁定的域名格式不正確", groups = QiniuGroup.class)
    private String qiniuDomain;

    // 七牛路徑前綴
    private String qiniuPrefix;

    // 七牛ACCESS_KEY  (validation-api-2.0.1.Final)
    @NotBlank(message = "七牛AccessKey不能為空", groups = QiniuGroup.class)
    private String qiniuAccessKey;

    // 七牛SECRET_KEY
    @NotBlank(message = "七牛SecretKey不能為空", groups = QiniuGroup.class)
    private String qiniuSecretKey;

    // 七牛存儲空間名
    @NotBlank(message = "七??臻g名不能為空", groups = QiniuGroup.class)
    private String qiniuBucketName;

    // 阿里云綁定的域名(hibernate-validator-6.1.6.Final)
    @NotBlank(message = "阿里云綁定的域名不能為空", groups = AliyunGroup.class)
    @URL(message = "阿里云綁定的域名格式不正確", groups = AliyunGroup.class)
    private String aliyunDomain;

    // 阿里云路徑前綴
    @Pattern(regexp = "^[^(/|\\)](.*[^(/|\\)])?$", message = "阿里云路徑前綴不能'/'或者'\'開頭或者結(jié)尾", groups = AliyunGroup.class)
    private String aliyunPrefix;

    // 阿里云EndPoint
    @NotBlank(message = "阿里云EndPoint不能為空", groups = AliyunGroup.class)
    private String aliyunEndPoint;

    // 阿里云AccessKeyId
    @NotBlank(message = "阿里云AccessKeyId不能為空", groups = AliyunGroup.class)
    private String aliyunAccessKeyId;

    // 阿里云AccessKeySecret
    @NotBlank(message = "阿里云AccessKeySecret不能為空", groups = AliyunGroup.class)
    private String aliyunAccessKeySecret;

    // 阿里云BucketName
    @NotBlank(message = "阿里云BucketName不能為空", groups = AliyunGroup.class)
    private String aliyunBucketName;

    // 騰訊云綁定的域名
    @NotBlank(message = "騰訊云綁定的域名不能為空", groups = QcloudGroup.class)
    @URL(message = "騰訊云綁定的域名格式不正確", groups = QcloudGroup.class)
    private String qcloudDomain;

    // 騰訊云路徑前綴
    private String qcloudPrefix;

    // 騰訊云SecretId
    @NotBlank(message = "騰訊云SecretId不能為空", groups = QcloudGroup.class)
    private String qcloudSecretId;

    // 騰訊云SecretKey
    @NotBlank(message = "騰訊云SecretKey不能為空", groups = QcloudGroup.class)
    private String qcloudSecretKey;

    // 騰訊云BucketName
    @NotBlank(message = "騰訊云BucketName不能為空", groups = QcloudGroup.class)
    private String qcloudBucketName;

    // 騰訊云COS所屬地區(qū)
    @NotBlank(message = "所屬地區(qū)不能為空", groups = QcloudGroup.class)
    private String qcloudRegion;

}

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 關(guān)于Maven構(gòu)建命令使用詳解

    關(guān)于Maven構(gòu)建命令使用詳解

    Maven構(gòu)建命令詳解:mvnclean、mvncompile、mvntest、mvnpackage、mvninstall、mvndeploy及其他常用命令,幫助開發(fā)者高效管理項(xiàng)目構(gòu)建流程
    2025-02-02
  • Spring Security方法鑒權(quán)的實(shí)現(xiàn)

    Spring Security方法鑒權(quán)的實(shí)現(xiàn)

    在Spring Security中,主要有兩種鑒權(quán)方式,一個是基于web請求的鑒權(quán),一個是基于方法的鑒權(quán),本文就來介紹一下Spring Security方法鑒權(quán)的實(shí)現(xiàn),感興趣的可以了解一下
    2023-12-12
  • springdata jpa使用Example快速實(shí)現(xiàn)動態(tài)查詢功能

    springdata jpa使用Example快速實(shí)現(xiàn)動態(tài)查詢功能

    這篇文章主要介紹了springdata jpa使用Example快速實(shí)現(xiàn)動態(tài)查詢功能,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 詳解Springboot事務(wù)管理

    詳解Springboot事務(wù)管理

    本篇文章主要介紹了詳解Springboot事務(wù)管理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Leetcode常見鏈表問題及代碼示例

    Leetcode常見鏈表問題及代碼示例

    這篇文章主要介紹了Leetcode常見鏈表問題及代碼示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • spring boot與spring mvc的區(qū)別及功能介紹

    spring boot與spring mvc的區(qū)別及功能介紹

    這篇文章主要介紹了spring boot與spring mvc的區(qū)別是什么以及spring boot和spring mvc功能介紹,感興趣的朋友一起看看吧
    2018-02-02
  • SpringBoot中獲取profile的方法詳解

    SpringBoot中獲取profile的方法詳解

    這篇文章主要介紹了springboot獲取profile的操作,文中的示例代碼講解詳細(xì),具有很好的參考價值,希望對大家有所幫助
    2022-04-04
  • JAVA多線程間通訊常用實(shí)現(xiàn)方法解析

    JAVA多線程間通訊常用實(shí)現(xiàn)方法解析

    這篇文章主要介紹了JAVA多線程間通訊常用實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • Java使用JSqlParser解析SQL語句實(shí)戰(zhàn)總結(jié)

    Java使用JSqlParser解析SQL語句實(shí)戰(zhàn)總結(jié)

    JSqlParser?是一個用于解析?SQL?語句的?Java?庫,支持多種?SQL?方言,可以靈活操作?SQL?語句,并且易于集成到?Java?項(xiàng)目中,本文給大家介紹Java使用JSqlParser解析SQL語句實(shí)戰(zhàn)總結(jié),感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • Java使用CompletableFuture實(shí)現(xiàn)異步編程

    Java使用CompletableFuture實(shí)現(xiàn)異步編程

    在現(xiàn)代 Java 開發(fā)中,異步編程是一項(xiàng)重要技能,而 CompletableFuture 是從 Java 8 開始提供的一個功能強(qiáng)大的工具,用于簡化異步任務(wù)的編寫和組合,本文將詳細(xì)介紹 CompletableFuture 的基本使用和一些常見的應(yīng)用場景,需要的朋友可以參考下
    2025-01-01

最新評論

临武县| 青岛市| 金华市| 宁德市| 屏边| 广河县| 巴林左旗| 彩票| 新安县| 噶尔县| 怀远县| 新竹市| 大港区| 东台市| 会同县| 崇仁县| 安顺市| 镶黄旗| 体育| 建瓯市| 彭州市| 安宁市| 临海市| 辽宁省| 佛教| 武川县| 乌什县| 抚宁县| 黑水县| 湖北省| 泌阳县| 双桥区| 乌鲁木齐县| 宜兰市| 铜陵市| 金秀| 长寿区| 石狮市| 工布江达县| 巧家县| 扶余县|