系列一、AliyunOSS开通及使用

news2024/11/15 10:16:33

一、对象存储OSS服务开通及配置

1.1、开通OSS

1.2、进入管理控制台

1.3、控制台使用

1.3.1、创建Bucket

命名:20230309-oss

读写权限:公共读

1.3.2、上传默认头像

创建文件夹 avater,上传默认的用户头像

1.4、使用RAM子用户

 

1.4.1、添加用户

登录名称:20230309-oss

访问方式:编程访问

1.4.2、获取子用户的AccessKey ID 、AccessKey Secret

AccessKey ID 、AccessKey Secret

1.4.3、设置用户权限

AliyunOSSFullAccess

 二、Junit测试

2.1、新建普通Maven项目

<dependencies>

	<!--aliyun OSS-->
	<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>
    <dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.18.18</version>
	</dependency>

</dependencies>

2.2、测试

@Slf4j
class OSSTests {

    // 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 = "your bucketName";

    /**
     * 创建Bucket
     */
    @Test
    public void testCreateBucket() {

        // 创建 ossClient 实例
        OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);

        // 创建存储空间
        ossClient.createBucket(bucketName);

        // 关闭 ossClient
        ossClient.shutdown();

        log.info("创建Bucket成功!");

    }

    /**
     * 检查Bucket是否存在
     */
    @Test
    public void testBucketExist() {
        // 创建 ossClient 实例
        OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);
        boolean exist = ossClient.doesBucketExist(bucketName);

        log.info("exist:{}",exist);

        // 关闭 ossClient
        ossClient.shutdown();
    }

    /**
     * 设置Bucket的访问权限
     */
    @Test
    public void testAccessControl() {

        // 创建 ossClient 实例
        OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);

        // 设置存储空间的访问权限为:公共读
        ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);

        // 关闭 ossClient
        ossClient.shutdown();

        log.info("设置Bucket的访问权限成功!");

    }
}

三、微服务

3.1、新建springboot项目

aliyun-oss-sample

<dependencies>

        <!--aliyun OSS-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.10.2</version>
        </dependency>

        <!--工具-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.18</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.9.9</version>
        </dependency>

        <!-- swagger ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-bean-validators</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>
        <!--
            用于解决刷新 swagger-ui 页面,控制台报错 swagger For input string: "" 的问题
            原文链接:https://blog.csdn.net/hkl_Forever/article/details/119639839
        -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.21</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.5.21</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>

3.2、代码整体结构

3.3、application.yml

server:
  port: 9000

spring:
  application:
    name: aliyun-oss-sample

aliyun:
  oss:
    endpoint: your endpoint
    accessKeyId: your accessKeyId
    accessKeySecret: your accessKeySecret
    bucketName: your bucketName

3.4、AliyunOssSampleApplication

package org.star;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class AliyunOssSampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(AliyunOssSampleApplication.class, args);
    }

}

 3.5、org.star.utils/OssProperties

package org.star.utils;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Slf4j
@Data
@Component
//@ConfigurationProperties(prefix = "aliyun.oss")
public class OssProperties implements InitializingBean {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.accessKeyId}")
    private String keyId;
    @Value("${aliyun.oss.accessKeySecret}")
    private String keySecret;
    @Value("${aliyun.oss.bucketName}")
    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 {
        log.info("endpoint:{},keyId:{},keySecret:{},bucketName:{}",endpoint,keyId,keySecret,bucketName);

        ENDPOINT = endpoint;
        KEY_ID = keyId;
        KEY_SECRET = keySecret;
        BUCKET_NAME = bucketName;
    }
}

3.6、org.star.result

3.6.1、ResponseEnum

package org.star.result;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@Getter
@AllArgsConstructor
@ToString
public enum ResponseEnum {

    SUCCESS(0, "成功"),
    ERROR(-1, "服务器内部错误"),

    //-1xx 服务器错误
    BAD_SQL_GRAMMAR_ERROR(-101, "sql语法错误"),
    SERVLET_ERROR(-102, "servlet请求异常"), //-2xx 参数校验
    UPLOAD_ERROR(-103, "文件上传错误"),
    EXPORT_DATA_ERROR(104, "数据导出失败"),


    //-2xx 参数校验
    BORROW_AMOUNT_NULL_ERROR(-201, "借款额度不能为空"),
    MOBILE_NULL_ERROR(-202, "手机号码不能为空"),
    MOBILE_ERROR(-203, "手机号码不正确"),
    PASSWORD_NULL_ERROR(204, "密码不能为空"),
    CODE_NULL_ERROR(205, "验证码不能为空"),
    CODE_ERROR(206, "验证码错误"),
    MOBILE_EXIST_ERROR(207, "手机号已被注册"),
    LOGIN_MOBILE_ERROR(208, "用户不存在"),
    LOGIN_PASSWORD_ERROR(209, "密码错误"),
    LOGIN_LOKED_ERROR(210, "用户被锁定"),
    LOGIN_AUTH_ERROR(-211, "未登录"),


    USER_BIND_IDCARD_EXIST_ERROR(-301, "身份证号码已绑定"),
    USER_NO_BIND_ERROR(302, "用户未绑定"),
    USER_NO_AMOUNT_ERROR(303, "用户信息未审核"),
    USER_AMOUNT_LESS_ERROR(304, "您的借款额度不足"),
    LEND_INVEST_ERROR(305, "当前状态无法投标"),
    LEND_FULL_SCALE_ERROR(306, "已满标,无法投标"),
    NOT_SUFFICIENT_FUNDS_ERROR(307, "余额不足,请充值"),

    PAY_UNIFIEDORDER_ERROR(401, "统一下单错误"),

    ALIYUN_SMS_LIMIT_CONTROL_ERROR(-502, "短信发送过于频繁"),//业务限流
    ALIYUN_SMS_ERROR(-503, "短信发送失败"),//其他失败

    WEIXIN_CALLBACK_PARAM_ERROR(-601, "回调参数不正确"),
    WEIXIN_FETCH_ACCESSTOKEN_ERROR(-602, "获取access_token失败"),
    WEIXIN_FETCH_USERINFO_ERROR(-603, "获取用户信息失败"),
    ;

    //响应状态码
    private Integer code;
    //响应信息
    private String message;

}

3.6.2、R

package org.star.result;

import lombok.Data;


@Data
public class R<T> {
    private Integer code;
    private String message;
    private T data;


    /**
     * 构造函数私有化
     */
    private R(){}

    /**
     * 返回成功结果
     * @return
     */
    public static R ok(){
        R r = new R();
        r.setCode(ResponseEnum.SUCCESS.getCode());
        r.setMessage(ResponseEnum.SUCCESS.getMessage());
        return r;
    }

    /**
     * 返回失败结果
     * @return
     */
    public static R error(){
        R r = new R();
        r.setCode(ResponseEnum.ERROR.getCode());
        r.setMessage(ResponseEnum.ERROR.getMessage());
        return r;
    }

    /**
     * 设置特定的结果
     * @param responseEnum
     * @return
     */
    public static R setResult(ResponseEnum responseEnum){
        R r = new R();
        r.setCode(responseEnum.getCode());
        r.setMessage(responseEnum.getMessage());
        return r;
    }

    public R data(T entity) {
        this.setData(entity);
        return this;
    }

    /**
     * 设置特定的响应消息
     * @param message
     * @return
     */
    public R message(String message){
        this.setMessage(message);
        return this;
    }


    /**
     * 设置特定的响应码
     * @param code
     * @return
     */
    public R code(Integer code){
        this.setCode(code);
        return this;
    }
}

3.7、org.star.exception

3.7.1、BusinessException

package org.star.exception;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.star.result.ResponseEnum;

@Data
@NoArgsConstructor
public class BusinessException extends RuntimeException {
    //错误码
    private Integer code;
    //错误消息
    private String message;

    /**
     *
     * @param message 错误消息
     */
    public BusinessException(String message) {
        this.message = message;
    }

    /**
     *
     * @param message 错误消息
     * @param code 错误码
     */
    public BusinessException(String message, Integer code) {
        this.message = message;
        this.code = code;
    }

    /**
     *
     * @param message 错误消息
     * @param code 错误码
     * @param cause 原始异常对象
     */
    public BusinessException(String message, Integer code, Throwable cause) {
        super(cause);
        this.message = message;
        this.code = code;
    }

    /**
     *
     * @param resultCodeEnum 接收枚举类型
     */
    public BusinessException(ResponseEnum resultCodeEnum) {
        this.message = resultCodeEnum.getMessage();
        this.code = resultCodeEnum.getCode();
    }

    /**
     *
     * @param resultCodeEnum 接收枚举类型
     * @param cause 原始异常对象
     */
    public BusinessException(ResponseEnum resultCodeEnum, Throwable cause) {
        super(cause);
        this.message = resultCodeEnum.getMessage();
        this.code = resultCodeEnum.getCode();
    }

}

3.7.2、UnifiedExceptionHandler

package org.star.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.star.result.R;
import org.star.result.ResponseEnum;

@Slf4j
@Component
@RestControllerAdvice // 在controller层添加通知。如果使用@ControllerAdvice,则方法上需要添加@ResponseBody
public class UnifiedExceptionHandler {


    /**
     * 未定义异常,当controller中抛出异常时则捕获
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public R handleException(Exception e) {
        log.error(e.getMessage(),e);
        return R.error();
    }

    /**
     * 自定义异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    public R handleException(BusinessException e) {
        log.error(e.getMessage(),e);
        return R.error().message(e.getMessage()).code(e.getCode());
    }

    @ExceptionHandler({
            NoHandlerFoundException.class,
            HttpRequestMethodNotSupportedException.class,
            HttpMediaTypeNotSupportedException.class,
            MissingPathVariableException.class,
            MissingServletRequestParameterException.class,
            TypeMismatchException.class,
            HttpMessageNotReadableException.class,
            HttpMessageNotWritableException.class,
            MethodArgumentNotValidException.class,
            HttpMediaTypeNotAcceptableException.class,
            ServletRequestBindingException.class,
            ConversionNotSupportedException.class,
            MissingServletRequestPartException.class,
            AsyncRequestTimeoutException.class
    })

    /**
     * 处理Controller上层异常
     * 如何测试:在save测试用例中输入非法的json参数,则得到下面的结果。我们可以在控制台日志中查看具体的错误原因。前端只需要返回相对简单友好的提示即可。
     */
    public R handleServletException(Exception e) {
        log.error(e.getMessage(),e);
        return R.error().message(ResponseEnum.SERVLET_ERROR.getMessage()).code(ResponseEnum.SERVLET_ERROR.getCode());
    }

}

3.7.3、Assert

package org.star.exception;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.star.result.ResponseEnum;

/**
 * 自定义断言:用断言的方式封装抛出的异常
 */
@Slf4j
public abstract class Assert {

    /**
     * 断言对象不为空
     * obj 为空则抛异常
     * @param obj
     * @param responseEnum
     */
    public static void notNull(Object obj, ResponseEnum responseEnum){
        if(obj == null){
            log.info("obj is null.....................");
            throw new BusinessException(responseEnum);
        }
    }


    /**
     * 断言对象为空
     * 如果对象obj不为空,则抛出异常
     * @param object
     * @param responseEnum
     */
    public static void isNull(Object object, ResponseEnum responseEnum) {
        if (object != null) {
            log.info("obj is not null......");
            throw new BusinessException(responseEnum);
        }
    }

    /**
     * 断言对象不为空
     * 如果对象obj为空,则抛出异常
     * @param object
     * @param responseEnum
     */
    public static void isNotNull(Object object, ResponseEnum responseEnum) {
        if (object == null) {
            log.info("obj is null......");
            throw new BusinessException(responseEnum);
        }
    }

    /**
     * 断言表达式为真
     * 如果不为真,则抛出异常
     *
     * @param expression 是否成功
     */
    public static void isTrue(boolean expression, ResponseEnum responseEnum) {
        if (!expression) {
            log.info("fail...............");
            throw new BusinessException(responseEnum);
        }
    }

    /**
     * 断言两个对象不相等
     * 如果相等,则抛出异常
     * @param m1
     * @param m2
     * @param responseEnum
     */
    public static void notEquals(Object m1, Object m2,  ResponseEnum responseEnum) {
        if (m1.equals(m2)) {
            log.info("equals...............");
            throw new BusinessException(responseEnum);
        }
    }

    /**
     * 断言两个对象相等
     * 如果不相等,则抛出异常
     * @param m1
     * @param m2
     * @param responseEnum
     */
    public static void equals(Object m1, Object m2,  ResponseEnum responseEnum) {
        if (!m1.equals(m2)) {
            log.info("not equals...............");
            throw new BusinessException(responseEnum);
        }
    }

    /**
     * 断言参数不为空
     * 如果为空,则抛出异常
     * @param s
     * @param responseEnum
     */
    public static void notEmpty(String s, ResponseEnum responseEnum) {
        if (StringUtils.isEmpty(s)) {
            log.info("is empty...............");
            throw new BusinessException(responseEnum);
        }
    }

}

3.8、org.star.service

3.8.1、FileService

package org.star.service;

import java.io.InputStream;

public interface FileService {

    /**
     * 文件上传至阿里云
     * @param inputStream
     * @param module
     * @param fileName
     * @return
     */
    String upload(InputStream inputStream,String module,String fileName);

}

3.8.2、FileServiceImpl

package org.star.service;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.star.utils.OssProperties;

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实例是否存在:如果不存在则创建,如果存在则获取
        if (!ossClient.doesBucketExist(OssProperties.BUCKET_NAME)) {
            // 创建Bucket
            ossClient.createBucket(OssProperties.BUCKET_NAME);

            // 设置oss实例的访问权限:公共读
            ossClient.setBucketAcl(OssProperties.BUCKET_NAME, CannedAccessControlList.PublicRead);
        }

        // 构建日期路径:avater/2023/03/09/文件名
        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;

    }
}

3.9、org.star.controller/FileController

package org.star.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.star.exception.BusinessException;
import org.star.result.R;
import org.star.result.ResponseEnum;
import org.star.service.FileService;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "阿里云文件管理")
@CrossOrigin
@RestController
@RequestMapping("/api/oss/file")
public class FileController {

    @Autowired
    private FileService fileService;

    @ApiOperation("文件上传")
    @PostMapping("/upload")
    public R upload(
            @ApiParam(value = "文件",required = true)
            @RequestParam(value = "file") MultipartFile file,

            @ApiParam(value = "模块",required = true)
            @RequestParam(value = "module") String module) {

        try {
            InputStream inputStream = file.getInputStream();
            String originalFilename = file.getOriginalFilename();
            String uploadUrl = fileService.upload(inputStream,module,originalFilename);
            Map<String,Object> resultMap = new HashMap<>();
            resultMap.put("url",uploadUrl);

            // 返回R对象
            return R.ok().message("文件上传成功").data(resultMap);
        } catch (Exception e) {
            throw new BusinessException(ResponseEnum.UPLOAD_ERROR,e);
        }
    }

}

3.10、org.star.config/Swagger2Config

package org.star.config;

import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableSwagger2
@EnableSwaggerBootstrapUI
@Configuration
public class Swagger2Config extends WebMvcConfigurerAdapter {

    @Bean
    public Docket aliyunOssDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("阿里云文件管理")
                .select()
                .apis(RequestHandlerSelectors.basePackage("org.star.controller"))
                .paths(PathSelectors.any())
                .build();

    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("权限管理系统")
                .description("权限管理系统API")
                .termsOfServiceUrl("http://localhost:9000/doc.html")
                .contact(new Contact("阿里巴巴权限管理系统项目", "http://localhost:9000/doc.html", "1293840962@qq.com"))
                .version("1.0")
                .build();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

}

3.11、Swagger2测试

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/400952.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式3——结构型模式

结构型模式描述如何将类或对象按某种布局组成更大的结构&#xff0c;它分为类结构型和对象结构型模式&#xff0c;前者采用继承机制来组织接口和类&#xff0c;后者采用组合或聚合来组合对象。 由于组合关系或聚合关系比继承关系耦合度低&#xff0c;满足“合成复用原则”&…

哈希表的实现

哈希表概念 二叉搜索树具有对数时间的表现&#xff0c;但这样的表现建立在一个假设上&#xff1a;输入的数据有足够的随机性。哈希表又名散列表&#xff0c;在插入、删除、搜索等操作上具有「常数平均时间」的表现&#xff0c;而且这种表现是以统计为基础&#xff0c;不需依赖…

CMU15-445 Project.4总结

在线测试 Project #4 - Concurrency Control 以下是Project #4的网址&#xff0c;2022FALL的Project #4是实现并发控制&#xff0c;可以分为以下三个任务&#xff1a; 我们首先需要实现一个锁管理器&#xff0c;能够支持 READ_UNCOMMITED、READ_COMMITTED、REPEATABLE_READ…

layui表格合并

先看一下最终合并之后的效果&#xff0c;能对单选、复选框进行按照某一列的合并 最开始的解决方案来自于这篇博客介绍的方法&#xff1a;https://blog.csdn.net/guishifoxin/article/details/81480136 但是还是存在没能解决的问题。 在完善之后达到的效果&#xff1a; 一&…

移动硬盘格式化?想要恢复硬盘那就看这里!

案例&#xff1a;移动硬盘无法打开&#xff0c;提示格式化&#xff1f; “怎么办啊&#xff01;&#xff01;&#xff01;今天下午给同学重装系统&#xff0c;插上自己的移动硬盘&#xff0c;却发现读不出来&#xff0c;提示需要格式化&#xff01;里面有很多东西&#xff0c;…

第十四章 opengl之高级OpenGL(深度测试)

OpenGL深度测试深度测试函数深度值精度深度缓冲的可视化深度冲突防止深度冲突深度测试 前面我们渲染一个3D图片中运用了深度缓冲&#xff1a;防止被阻挡的面渲染到其他面的前面。 深度缓冲就像颜色缓冲(Color Buffer)&#xff08;储存所有的片段颜色&#xff1a;视觉输出&…

JAVA开发(JAVA中的异常)

在java开发与代码运行过程中&#xff0c;我们经常会遇到需要处理异常的时候。有时候是在用编辑器写代码&#xff0c;点击保存的时候&#xff0c;编辑器就提示我们某块代码有异常&#xff0c;强制需要处理。有时候是我们启动&#xff0c;运行JAVA代码的时候的&#xff0c;日志里…

案例06-没有复用思想的接口和sql--mybatis,spring

目录一、背景二、思路&方案问题1优化问题2优化三、总结四、升华一、背景 写这篇文章的目的是通过对没有复用思想接口的代码例子优化告诉大家&#xff0c;没有复用思想的代码不要写&#xff0c;用这种思维方式和习惯来指导我们写代码。 项目中有两处没有复用思想代码&#…

R语言基础(三):运算

接前文 R语言基础(一)&#xff1a;注释、变量 R语言基础(二)&#xff1a;常用函数 4.运算 4.1 数学运算 R语言中支持加减乘除四则运算、乘方运算、求余数(取模)运算&#xff1a; 符号含义示例加法11 结果是2-减法2-1 结果是1*乘法4*5 结果是20/除法4/5 结果是0.8%/%整除(只要…

MySQL 事务隔离

MySQL 事务隔离事务隔离实现事务的启动ACID : 原子(Atomicity)、一致(Consistency)、隔离(Isolation)、永久(Durability) 多个事务可能出现问题 : 脏读 (dirty read) , 不可重复读 (non-repeatable read) , 幻读 (phantom read) 事务隔离级别 : 读未提交 (read uncommitted)…

一篇学习ES

文章目录ES简介1.什么是ElasticSearch2.ElasticSearch的使用案例3.ElasticSearch对比SolrElasticSearch环境搭建1. 下载ES压缩包2. 安装ES服务3. 启动ES服务3. 安装ES的图形化界面插件ES术语1.概述2.索引 index3.类型 type4.字段Field5.映射 mapping6.文档 document7. 接近实时…

制造业数字化转型要注重哪些方面?

近年来&#xff0c;制造业企业数字化转型的话题一直处于行业高热位置。中央经济工作会议作出“大力发展数字经济”的部署&#xff0c;工信部提出要深化产业数字化转型&#xff0c;建设一批全球领先的智能工厂、智慧供应链&#xff0c;并向中小企业场景化、标准化复制推广。 随…

监控体系划分

按采集类型划分 1.基于 Metrics 的监控 基于 Metrics 的监控&#xff0c;背后对应的是度量&#xff08;指标监控&#xff09;系统&#xff0c;监控机器在某段时间内的 CPU 使用率、系统负载&#xff1b; HTTP 请求访问量等。 1.Skywalking 开源地址 &#xff08;既能做调用链监…

Spring-AOP简介案例

Spring-AOP简介&案例 1&#xff0c;AOP简介 Spring有两个核心的概念&#xff0c;一个是IOC/DI&#xff0c;一个是AOP。 对于AOP,我们前面提过一句话是:AOP是在不改原有代码的前提下对其进行增强。 1.1 什么是AOP? AOP(Aspect Oriented Programming)面向切面编程&…

java Spring5 xml配置文件方式实现声明式事务

在java Spring5通过声明式事务(注解方式)完成一个简单的事务操作中 我们通过注解方式完成了一个事务操作 那么 下面 我还是讲一下 基于xml实现声明式事务的操作 其实在开发过程中 大家肯定都喜欢用注解 因为他方便 这篇文章中的xml方式 大家做个了解就好 还是 我们的这张表 记…

ECharts数据可视化--常用图表类型

目录 一.柱状图 1.基本柱状图 1.1最简单的柱状图 ​编辑 1.2多系列柱状图 1.3柱状图的样式 &#xff08;1&#xff09;柱条样式 &#xff08;2&#xff09;柱条的宽度和高度 &#xff08;3&#xff09;柱条间距 &#xff08;4&#xff09;为柱条添加背景颜色 ​编辑 2.堆…

SpringBoot创建和使用

目录 什么是SpringBoot SpringBoot的优点 SpringBoot项目的创建 1、使用idea创建 2、项目目录介绍和运行 Spring Boot配置文件 1、配置文件 2、配置文件的格式 3、properties 3.1、properties基本语法 3.2、读取配置文件 3.3、缺点 4、yml 4.1、优点 4.2、yml基本…

虚拟机下Linux系统磁盘扩容

在VM虚拟机中&#xff0c;我们经常会选择默认磁盘大小20G&#xff0c;用着用着才发现20G不够用&#xff0c;服务启动不了&#xff0c;就很尴尬&#xff0c;让我们今天一起来学习下&#xff0c;如何在虚拟机给磁盘扩容。一&#xff1a;关闭虚拟机&#xff0c;添加硬盘背景&#…

mysql Docker容器的安装(centos版)以及修改docker默认端口、解决1251问题

文章目录一、Docker的安装以及在Docker下进行mysql的安装1、安装Docker2、上传安装包并进行安装并启动docker3、 配置Docker的镜像加速器&#xff0c;这里使用阿里云的镜像4、刷新守护进程&#xff0c;并重启docker&#xff0c;检验镜像是否配置成功5、搜索并下载mysql镜像6、导…

超分扩散模型 SR3 可以做图像去雨、去雾等恢复任务吗?

文章目录前言代码及原文链接主要的点如何进行图像恢复前言 关于扩散模型以及条件扩散模型的介绍&#xff0c;大家可以前往我的上一篇博客&#xff1a;扩散模型diffusion model用于图像恢复任务详细原理 (去雨&#xff0c;去雾等皆可)&#xff0c;附实现代码。 SR3是利用扩散模…