准备环境 application.yml spring: application: name: knife4j-demo knife4j: enable: true openapi: title: Knife4j官方文档 description: "`我是测试`,**你知道吗** # aaa" email: xiaoymin@foxmail.com concat: 八一菜刀 url: https://docs.xiaominfo.com version: v4.0 license: Apache 2.0 license-url: https://stackoverflow.com/ terms-of-service-url: https://stackoverflow.com/ group: test1: group-name: 分组名称 api-rule: package api-rule-resources: - com.example.swaggertest pom.xml <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.5</version> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>Swagger-Test</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Swagger-Test</name> <description>Swagger-Test</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi2-spring-boot-starter</artifactId> <version>4.4.0</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>30.1-jre</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 目录配置 仅需三个文件即可实现无需其他配置类 @ApiOperationExtended package com.example.swaggertest.annotaion; import io.swagger.annotations.Extension; import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.ApiOperation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @ApiOperation(value = "", extensions = { @Extension(name = "price", properties = { @ExtensionProperty(name = "price", value = "") }) }) public @interface ApiOperationExtended { String value() default ""; String price() default ""; } ApiOperationExtendedPlugin package com.example.swaggertest.plugin; import com.example.swaggertest.annotaion.ApiOperationExtended; import io.swagger.annotations.ApiOperation; import org.springframework.stereotype.Component; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.OperationBuilderPlugin; import springfox.documentation.spi.service.contexts.OperationContext; import springfox.documentation.swagger.common.SwaggerPluginSupport; import java.util.Collections; import java.util.Optional; @Component public class ApiOperationExtendedPlugin implements OperationBuilderPlugin { @Override public boolean supports(DocumentationType d) { return SwaggerPluginSupport.pluginDoesApply(d); } @Override public void apply(OperationContext context) { Optional<ApiOperation> methodAnnotation = context.findAnnotation(ApiOperation.class); if (methodAnnotation.isPresent()) { Optional<ApiOperationExtended> apiOperationExtended = context.findAnnotation(ApiOperationExtended.class); if (apiOperationExtended.isPresent()) { String price = apiOperationExtended.get().price(); String value = apiOperationExtended.get().value(); context.operationBuilder().extensions(Collections.singletonList(new springfox.documentation.service.StringVendorExtension("price", price))); context.operationBuilder().extensions(Collections.singletonList(new springfox.documentation.service.StringVendorExtension("summary", value))); } } } } Controller package com.example.swaggertest.controller; import com.example.swaggertest.annotaion.ApiOperationExtended; import io.swagger.annotations.Api; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author 王成宇 2024/6/3 10:38 */ @RestController @Api(tags = "test") public class TestController { @ApiOperationExtended(value = "测试新增注解",price = "99.99元/个") @GetMapping("/test") public String test() { return "test"; } } 实现效果
版本列表 有找不到版本号的可以从此处找寻 SpringCloud Alibaba 项目参考 ------------------------------------------------------------------------------- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-boot.version>2.7.3</spring-boot.version> <spring-cloud.version>2021.0.4</spring-cloud.version> <spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version> <spring-boot-admin.version>2.7.5</spring-boot-admin.version> <spring-boot.mybatis>2.2.2</spring-boot.mybatis> <swagger.fox.version>3.0.0</swagger.fox.version> <swagger.core.version>1.6.2</swagger.core.version> <tobato.version>1.27.2</tobato.version> <kaptcha.version>2.3.2</kaptcha.version> <pagehelper.boot.version>1.4.5</pagehelper.boot.version> <druid.version>1.2.12</druid.version> <dynamic-ds.version>3.5.2</dynamic-ds.version> <commons.io.version>2.11.0</commons.io.version> <commons.fileupload.version>1.4</commons.fileupload.version> <velocity.version>2.3</velocity.version> <fastjson.version>2.0.14</fastjson.version> <jjwt.version>0.9.1</jjwt.version> <minio.version>8.2.2</minio.version> <poi.version>4.1.2</poi.version> <commons-collections.version>3.2.2</commons-collections.version> <transmittable-thread-local.version>2.13.2</transmittable-thread-local.version> ------------------------------------------------------------------------------- SpringCloud 项目参考 ------------------------------------------------------------------------------- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-boot.version>2.3.2.RELEASE</spring-boot.version> <spring-cloud.version>Hoxton.SR7</spring-cloud.version> <spring-boot-admin.version>2.2.2</spring-boot-admin.version> <druid.version>1.1.14</druid.version> <bitwalker.version>1.19</bitwalker.version> <kaptcha.version>2.3.2</kaptcha.version> <swagger.version>2.7.0</swagger.version> <pagehelper.boot.version>1.2.12</pagehelper.boot.version> <mapper.starter.version>2.1.5</mapper.starter.version> <oshi.version>3.9.1</oshi.version> <commons.io.version>2.5</commons.io.version> <commons.fileupload.version>1.3.3</commons.fileupload.version> <jsoup.version>1.11.3</jsoup.version> <poi.version>3.17</poi.version> <velocity.version>1.7</velocity.version> <qiniu.version>[7.2.0, 7.2.99]</qiniu.version> <aliyun.oss.version>3.5.0</aliyun.oss.version> <qcloud.cos.version>5.6.3</qcloud.cos.version> <fastjson.version>1.2.70</fastjson.version> <lombok.version>1.18.4</lombok.version> <hutool.version>4.1.19</hutool.version> <common-pool.version>2.6.2</common-pool.version> <swagger.version>2.9.2</swagger.version> <swagger-ui.version>1.9.5</swagger-ui.version> <guava.version>26.0-jre</guava.version> <anji-plus.version>1.2.4</anji-plus.version> ------------------------------------------------------------------------------- SpringBoot 项目参考 ------------------------------------------------------------------------------- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <druid.version>1.2.11</druid.version> <bitwalker.version>1.21</bitwalker.version> <swagger.version>3.0.0</swagger.version> <kaptcha.version>2.3.2</kaptcha.version> <mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version> <pagehelper.boot.version>1.4.3</pagehelper.boot.version> <fastjson.version>2.0.14</fastjson.version> <oshi.version>6.2.2</oshi.version> <commons.io.version>2.11.0</commons.io.version> <commons.fileupload.version>1.4</commons.fileupload.version> <commons.collections.version>3.2.2</commons.collections.version> <poi.version>4.1.2</poi.version> <velocity.version>2.3</velocity.version> <jwt.version>0.9.1</jwt.version> Spring Spring框架基本的核心工具 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> Spring-Web <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> Spring-webmvc <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> Spring-context-support <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> SpringBoot SpringBoot Parent 模块 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> </parent> SpringBoot 依赖配置 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.5.14</version> <type>pom</type> <scope>import</scope> </dependency> spring security 安全认证 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> 自定义验证注解 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> redis缓存操作 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> SpringBoot web容器 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> SpringBoot Aop 拦截器 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> spring-boot-devtools <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> SpringBoot Admin <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-dependencies</artifactId> <version>2.2.2</version> <type>pom</type> <scope>import</scope> </dependency> 监控服务端 <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-server</artifactId> </dependency> undertow容器 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> Actuator 健康监控 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> JPA <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> SpringCloud 父依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR6</version> <type>pom</type> <scope>import</scope> </dependency> Config <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> Config-Server <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> Eureka- Client <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> Eureka-Server <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> Hytrix <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> Gateway <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> SpringCloud Alibaba 父依赖 <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2021.0.4.0</version> <type>pom</type> <scope>import</scope> </dependency> Nacos discovery <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> Nacos Config <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> Sentinel <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> Sentinel Gateway <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> </dependency> Sentinel Datasource Nacos <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> Loadbalancer <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency> openfeign <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> Seata <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency> 数据库相关 Mysql驱动包 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> Druid连接池 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.11</version> </dependency> Mybatis <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId <version>2.2.2</version> </dependency> tk-mapper <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <exclusions> <exclusion> <artifactId>persistence-api</artifactId> <groupId>javax.persistence</groupId> </exclusion> </exclusions> </dependency> pagehelper 分页插件 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.4.3</version> </dependency> Swagger Swagger 3 依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> <exclusions> <exclusion> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> </exclusion> </exclusions> </dependency> Swagger models <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> <version>1.6.2</version> </dependency> swagger-bootstrap-ui <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.5</version> </dependency> swagger-annotations <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>${swagger.core.version}</version> </dependency> knife4j <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.9</version> </dependency> 工具类 LomBok <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> io常用工具类 <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> 文件上传工具类 <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> Excel工具 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> velocity代码生成使用模板 <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.3</version> </dependency> Collections工具类 <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.2</version> </dependency> Json工具类 <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> FastJson <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.14</version> </dependency> JWT - Token生成与解析 <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> 验证码 <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency> 定时任务 <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <exclusions> <exclusion> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> </exclusion> </exclusions> </dependency> Yml解析器 <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> </dependency> Jaxb <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency> pool 对象池 <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> HTML解析器 <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.3</version> </dependency> Hutool 工具类 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.1.19</version> </dependency> 其他依赖 解析客户端操作系统、浏览器等 <dependency> <groupId>eu.bitwalker</groupId> <artifactId>UserAgentUtils</artifactId> <version>1.21</version> </dependency> 获取系统信息 <dependency> <groupId>com.github.oshi</groupId> <artifactId>oshi-core</artifactId> <version>6.2.2</version> </dependency> Servlet 包 <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> 阿里云OSS <dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>[7.2.0, 7.2.99]</version> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>5.6.3</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> guava <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>26.0-jre</version> </dependency> Activiti <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactI <version>5.22.0</version> <exclusions> <exclusion> <artifactId>activation</artifactId> <groupId>javax.activation</groupId> </exclusion> <exclusion> <artifactId>mybatis</artifactId> <groupId>org.mybatis</groupId> </exclusion> </exclusions> </dependency> Activiti 流程图 <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-diagram-rest</artifactId> <version>5.22.0</version> <exclusions> <exclusion> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </exclusion> <exclusion> <groupId>org.springframework.security</groupId> <artifactId>spring-security-crypto</artifactId> </exclusion> <exclusion> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> </exclusion> </exclusions> </dependency> Activiti 在线设计 <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-modeler</artifactId> <version>${activiti.version}</version> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> <exclusion> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </exclusion> <exclusion> <groupId>org.springframework.security</groupId> <artifactId>spring-security-crypto</artifactId> </exclusion> <exclusion> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> </exclusion> </exclusions> </dependency> FastDFS 分布式文件系统 <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.27.2</version> </dependency> 线程传递值 <dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-thread-local</artifactId> <version>${transmittable-thread-local.version}</version> </dependency> 中央仓库 默认仓库 <repositories> <repository> <id>central</id> <name>Central Repository</name> <url>https://repo.maven.apache.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> 阿里云 <repositories> <repository> <id>public</id> <name>aliyun nexus</name> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>public</id> <name>aliyun nexus</name> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories>
import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.cynthia.common.utils.StringUtils; //可参见 StringUtils 工具类 /** * 防止XSS攻击的过滤器 * * @author Wcy */ public class XssFilter implements Filter { /** * 排除链接 */ public List<String> excludes = new ArrayList<>(); @Override public void init(FilterConfig filterConfig) throws ServletException { String tempExcludes = filterConfig.getInitParameter("excludes"); if (StringUtils.isNotEmpty(tempExcludes)) { String[] url = tempExcludes.split(","); for (int i = 0; url != null && i < url.length; i++) { excludes.add(url[i]); } } } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; if (handleExcludeURL(req, resp)) { chain.doFilter(request, response); return; } XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); chain.doFilter(xssRequest, response); } private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) { String url = request.getServletPath(); String method = request.getMethod(); // GET DELETE 不过滤 if (method == null || method.matches("GET") || method.matches("DELETE")) { return true; } return StringUtils.matches(url, excludes); } @Override public void destroy() { } } XssHttpServletRequestWrapper: import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import com.cynthia.common.utils.html.EscapeUtil;//参见 EscapeUtil 转义和反转义工具类 /** * XSS过滤处理 * * @author Wcy */ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { /** * @param request */ public XssHttpServletRequestWrapper(HttpServletRequest request) { super(request); } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); if (values != null) { int length = values.length; String[] escapseValues = new String[length]; for (int i = 0; i < length; i++) { // 防xss攻击和过滤前后空格 escapseValues[i] = EscapeUtil.clean(values[i]).trim(); } return escapseValues; } return super.getParameterValues(name); } }
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * 网关全局设置，允许跨域 * * @author Wcy * @date 2021-08-13 17:28 */ @Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); return new CorsFilter(source); } }
官网下载 https://git-scm.com/downloads 但是官网下载太慢了，我估计我这网络肯定得下载好几天呢，可能大家也是，于是我找到阿里镜像 下载最新版的Git，利用阿里镜像会下载的很快 https://npm.taobao.org/mirrors/git-for-windows/ 去选择你想下载的版本就好啦！希望可以帮到你！ 一、 Git 常用命令速查 git branch 查看本地所有分支 git status 查看当前状态 git commit 提交 git branch -a 查看所有的分支 git branch -r 查看远程所有分支 git commit -am "init" 提交并且加注释 git remote add origin git@666.666.666.66:666 git push origin master 将文件给推到服务器上 git remote show origin 显示远程库origin里的资源 git push origin master:develop git push origin master:hb-dev 将本地库与服务器上的库进行关联 git checkout --track origin/dev 切换到远程dev分支 git branch -D master develop 删除本地库develop git checkout -b dev 建立一个新的本地分支dev git merge origin/dev 将分支dev与当前分支进行合并 git checkout dev 切换到本地dev分支 git remote show 查看远程库 git add . git rm 文件名(包括路径) 从git中删除指定文件 git clone git://github.com/schacon/grit.git 从服务器上将代码给拉下来 git config --list 看所有用户 git ls-files 看已经被提交的 git rm [file name] 删除一个文件 git commit -a 提交当前repos的所有的改变 git add [file name] 添加一个文件到git index git commit -v 当你用－v参数的时候可以看commit的差异 git commit -m "This is the message describing the commit" 添加commit信息 git commit -a -a是代表add，把所有的change加到git index里然后再commit git commit -a -v 一般提交命令 git log 看你commit的日志 git diff 查看尚未暂存的更新 git rm a.a 移除文件(从暂存区和工作区中删除) git rm --cached a.a 移除文件(只从暂存区中删除) git commit -m "remove" 移除文件(从Git中删除) git rm -f a.a 强行移除修改后文件(从暂存区和工作区中删除) git diff --cached 或 $ git diff --staged 查看尚未提交的更新 git stash push 将文件给push到一个临时空间中 git stash pop 将文件从临时空间pop下来 --------------------------------------------------------- git remote add origin git@github.com:username/Hello-World.git git push origin master 将本地项目给提交到服务器中 ----------------------------------------------------------- git pull 本地与服务器端同步 ----------------------------------------------------------------- git push (远程仓库名) (分支名) 将本地分支推送到服务器上去。 git push origin serverfix:awesomebranch ------------------------------------------------------------------ git fetch 相当于是从远程获取最新版本到本地，不会自动merge git commit -a -m "log_message" (-a是提交所有改动，-m是加入log信息) 本地修改同步至服务器端 ： git branch branch_0.1 master 从主分支master创建branch_0.1分支 git branch -m branch_0.1 branch_1.0 将branch_0.1重命名为branch_1.0 git checkout branch_1.0/master 切换到branch_1.0/master分支 du -hs git branch 删除远程branch git push origin :branch_remote_name git branch -r -d branch_remote_name ----------------------------------------------------------- 初始化版本库，并提交到远程服务器端 mkdir WebApp cd WebApp git init 本地初始化 touch README git add README 添加文件 git commit -m 'first commit' git remote add origin git@github.com:666/WebApp.git 增加一个远程服务器端 上面的命令会增加URL地址为'git@github.com:666/WebApp.git'，名称为origin的远程服务器库，以后提交代码的时候只需要使用 origin别名即可 二、配置 Git的设置文件为.gitconfig，它可以在用户主目录下（全局配置），也可以在项目目录下（项目配置）。 # 显示当前的Git配置 $ git config --list # 编辑Git配置文件 $ git config -e [--global] # 设置提交代码时的用户信息 $ git config [--global] user.name "[name]" $ git config [--global] user.email "[email address]" 三、增加/删除文件 # 添加指定文件到暂存区 $ git add [file1] [file2] ... # 添加指定目录到暂存区，包括子目录 $ git add [dir] # 添加当前目录的所有文件到暂存区 $ git add . # 添加每个变化前，都会要求确认 # 对于同一个文件的多处变化，可以实现分次提交 $ git add -p # 删除工作区文件，并且将这次删除放入暂存区 $ git rm [file1] [file2] ... # 停止追踪指定文件，但该文件会保留在工作区 $ git rm --cached [file] # 改名文件，并且将这个改名放入暂存区 $ git mv [file-original] [file-renamed] 四、代码提交 # 提交暂存区到仓库区 $ git commit -m [message] # 提交暂存区的指定文件到仓库区 $ git commit [file1] [file2] ... -m [message] # 提交工作区自上次commit之后的变化，直接到仓库区 $ git commit -a # 提交时显示所有diff信息 $ git commit -v # 使用一次新的commit，替代上一次提交 # 如果代码没有任何新变化，则用来改写上一次commit的提交信息 $ git commit --amend -m [message] # 重做上一次commit，并包括指定文件的新变化 $ git commit --amend [file1] [file2] ... 五、分支 # 列出所有本地分支 $ git branch # 列出所有远程分支 $ git branch -r # 列出所有本地分支和远程分支 $ git branch -a # 新建一个分支，但依然停留在当前分支 $ git branch [branch-name] # 新建一个分支，并切换到该分支 $ git checkout -b [branch] # 新建一个分支，指向指定commit $ git branch [branch] [commit] # 新建一个分支，与指定的远程分支建立追踪关系 $ git branch --track [branch] [remote-branch] # 切换到指定分支，并更新工作区 $ git checkout [branch-name] # 切换到上一个分支 $ git checkout - # 建立追踪关系，在现有分支与指定的远程分支之间 $ git branch --set-upstream [branch] [remote-branch] # 合并指定分支到当前分支 $ git merge [branch] # 选择一个commit，合并进当前分支 $ git cherry-pick [commit] # 删除分支 $ git branch -d [branch-name] # 删除远程分支 $ git push origin --delete [branch-name] $ git branch -dr [remote/branch] 六、标签 # 列出所有tag $ git tag # 新建一个tag在当前commit $ git tag [tag] # 新建一个tag在指定commit $ git tag [tag] [commit] # 删除本地tag $ git tag -d [tag] # 删除远程tag $ git push origin :refs/tags/[tagName] # 查看tag信息 $ git show [tag] # 提交指定tag $ git push [remote] [tag] # 提交所有tag $ git push [remote] --tags # 新建一个分支，指向某个tag $ git checkout -b [branch] [tag] 七、查看信息 # 显示有变更的文件 $ git status # 显示当前分支的版本历史 $ git log # 显示commit历史，以及每次commit发生变更的文件 $ git log --stat # 搜索提交历史，根据关键词 $ git log -S [keyword] # 显示某个commit之后的所有变动，每个commit占据一行 $ git log [tag] HEAD --pretty=format:%s # 显示某个commit之后的所有变动，其"提交说明"必须符合搜索条件 $ git log [tag] HEAD --grep feature # 显示某个文件的版本历史，包括文件改名 $ git log --follow [file] $ git whatchanged [file] # 显示指定文件相关的每一次diff $ git log -p [file] # 显示过去5次提交 $ git log -5 --pretty --oneline # 显示所有提交过的用户，按提交次数排序 $ git shortlog -sn # 显示指定文件是什么人在什么时间修改过 $ git blame [file] # 显示暂存区和工作区的差异 $ git diff # 显示暂存区和上一个commit的差异 $ git diff --cached [file] # 显示工作区与当前分支最新commit之间的差异 $ git diff HEAD # 显示两次提交之间的差异 $ git diff [first-branch]...[second-branch] # 显示今天你写了多少行代码 $ git diff --shortstat "@{0 day ago}" # 显示某次提交的元数据和内容变化 $ git show [commit] # 显示某次提交发生变化的文件 $ git show --name-only [commit] # 显示某次提交时，某个文件的内容 $ git show [commit]:[filename] # 显示当前分支的最近几次提交 $ git reflog 八、远程同步 # 下载远程仓库的所有变动 $ git fetch [remote] # 显示所有远程仓库 $ git remote -v # 显示某个远程仓库的信息 $ git remote show [remote] # 增加一个新的远程仓库，并命名 $ git remote add [shortname] [url] # 取回远程仓库的变化，并与本地分支合并 $ git pull [remote] [branch] # 上传本地指定分支到远程仓库 $ git push [remote] [branch] # 强行推送当前分支到远程仓库，即使有冲突 $ git push [remote] --force # 推送所有分支到远程仓库 $ git push [remote] --all 九、撤销 # 恢复暂存区的指定文件到工作区 $ git checkout [file] # 恢复某个commit的指定文件到暂存区和工作区 $ git checkout [commit] [file] # 恢复暂存区的所有文件到工作区 $ git checkout . # 重置暂存区的指定文件，与上一次commit保持一致，但工作区不变 $ git reset [file] # 重置暂存区与工作区，与上一次commit保持一致 $ git reset --hard # 重置当前分支的指针为指定commit，同时重置暂存区，但工作区不变 $ git reset [commit] # 重置当前分支的HEAD为指定commit，同时重置暂存区和工作区，与指定commit一致 $ git reset --hard [commit] # 重置当前HEAD为指定commit，但保持暂存区和工作区不变 $ git reset --keep [commit] # 新建一个commit，用来撤销指定commit # 后者的所有变化都将被前者抵消，并且应用到当前分支 $ git revert [commit] # 暂时将未提交的变化移除，稍后再移入 $ git stash $ git stash pop 十、其他 # 生成一个可供发布的压缩包 $ git archive
首先，我们在Gitee创建一个仓库：如图： 接下来进入这个页面： 咱们复制上面的https地址： 之后咱们进入要项目的文件目录： 右键点击git Bash here git init //初始化仓库 git add .(文件name) //添加文件到本地仓库 git commit -m “first commit” //添加文件描述信息 git remote add origin + 远程仓库地址 //链接远程仓库，创建主分支 接着： git push -u origin master //把本地仓库的文件推送到远程仓库 如出现警告，可使用 git push -u origin master -f //强制向远程仓库推送本地仓库的改动(仅仅建议在初始状态下使用) 1）使用强制push的方法：使用该代码。但这样会使远程修改丢失，一般是不可取的，尤其是多人协作开发的时候。 2）push前先将远程仓库修改pull下来 //仓库已有代码时 到这里没问题的话远程就应该代码上传完毕了 我们来到Gitee里看看我们的仓库代码： 咱们的仓库搭建就完成了，可在IDEA中安装git进行快速管理项目了。 在idea中即可通过控制台快速管理项目版本
首先Swagger它是一个API文档工具，可以通过各种注解生成接口文档，Model文档，但是我在使用Swagger的时候，觉得实用性并不高，一个机会接触到了基于Swagger开发的Swagger-Bootstrap-UI，觉得很好用. 1.引入依赖 <properties> <swagger.version>2.9.2</swagger.version> <xiaoymin.version>1.9.2</xiaoymin.version> </properties> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>${xiaoymin.version}</version> </dependency> 2.配置类 import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI; import io.swagger.annotations.ApiOperation; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ApiKey; import springfox.documentation.service.Contact; import springfox.documentation.service.SecurityScheme; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.Collections; /** * Swagger配置 * * @author Wcy * @date 2020/8/19 20:53 */ @Configuration @EnableSwagger2 @EnableSwaggerBootstrapUI @ConfigurationProperties(prefix = "swagger") public class SwaggerConfig { //bootstrap-ui @Bean public Docket examApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .groupName("考试模块接口") .host("http://666.66.66.666:8081") .select() .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .paths(PathSelectors.ant("/exam/api/**")) .build() .securitySchemes(Collections.singletonList(securityScheme())); } //swagger-ui private ApiInfo apiInfo() { return new ApiInfoBuilder().title("考试系统接口") .description("考试系统接口") .contact(new Contact("Wcy", "url", "email")) .version("1.0.0") .build() ; } /** * 授权头部 * * @return */ @Bean SecurityScheme securityScheme() { return new ApiKey("token", "token", "header"); } } ShiroConfig配置类 import com.yf.exam.modules.shiro.ShiroRealm; import com.yf.exam.modules.shiro.aop.JwtFilter; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; import org.apache.shiro.mgt.DefaultSubjectDAO; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import javax.servlet.Filter; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; /** * Shiro配置类 * * @author Wcy */ @Slf4j @Configuration public class ShiroConfig { /** * Filter Chain定义说明 * * 1、一个URL可以配置多个Filter，使用逗号分隔 * 2、当设置多个过滤器时，全部验证通过，才视为通过 * 3、部分过滤器可指定参数，如perms，roles */ @Bean("shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); // 拦截器 Map<String, String> map = new LinkedHashMap<>(); // 需要排除的一些接口 map.put("/exam/api/sys/user/login", "anon"); map.put("/exam/api/sys/user/reg", "anon"); map.put("/exam/api/sys/user/quick-reg", "anon"); // 获取网站基本信息 map.put("/exam/api/sys/config/detail", "anon"); // 文件读取 map.put("/upload/file/**", "anon"); map.put("/", "anon"); map.put("/v2/**", "anon"); map.put("/doc.html", "anon"); map.put("/**/*.js", "anon"); map.put("/**/*.css", "anon"); map.put("/**/*.html", "anon"); map.put("/**/*.svg", "anon"); map.put("/**/*.pdf", "anon"); map.put("/**/*.jpg", "anon"); map.put("/**/*.png", "anon"); map.put("/**/*.ico", "anon"); // 字体 map.put("/**/*.ttf", "anon"); map.put("/**/*.woff", "anon"); map.put("/**/*.woff2", "anon"); map.put("/druid/**", "anon"); map.put("/swagger-ui.html", "anon"); map.put("/swagger**/**", "anon"); map.put("/webjars/**", "anon"); // 添加自己的过滤器并且取名为jwt Map<String, Filter> filterMap = new HashMap<String, Filter>(1); filterMap.put("jwt", new JwtFilter()); shiroFilterFactoryBean.setFilters(filterMap); map.put("/**", "jwt"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } @Bean("securityManager") public DefaultWebSecurityManager securityManager(ShiroRealm myRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myRealm); DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO(); DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator(); defaultSessionStorageEvaluator.setSessionStorageEnabled(false); subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator); securityManager.setSubjectDAO(subjectDAO); return securityManager; } /** * 下面的代码是添加注解支持 * * @return */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); defaultAdvisorAutoProxyCreator.setUsePrefix(true); defaultAdvisorAutoProxyCreator.setAdvisorBeanNamePrefix("_no_advisor"); return defaultAdvisorAutoProxyCreator; } @Bean public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } } 配置好后，将项目启动，访问 http://localhost:8081/doc.html 如下图，即成功: 在进到这个页面以后，可以去往网络doc.html的标头里获取token填到Authorize里面便可以进行接口调试 3.常用注解 swagger得注解其实有很多，但是没必要每一个都去掌握，掌握几个最实用得注解就好了，其他得注解可以在学习或者工作得过程中去了解，我们可以打开它得引入得jar大概得了解一下，让自己心里有个数: 3.1.Api类注解 3.1.1.@Api @Api顾名思义，它就是打在接口(controller类)上的注解。 @Api(tags = "用户管理") 3.1.2.@ApiOperation @ApiOperation这个注解，打在接口里得方法上，与@Api注解结合使用 @ApiOperation(value = "新增用户") 如果你不希望某个接口通过这个文档暴露出去，可以这样 @ApiOperation(value = "批量新增用户", hidden = true) 3.2.Model类注解 Model类得注解主要是使用在一些entity，dto，vo，model上，可以在swagger-bootstrap-UI里得swagger-models里查看，可以在接口里的请求实例或者响应示例里查看 3.2.1.@ApiModel @ApiModel(value="SysUser对象") 下面给出两个实例: 3.2.2.@ApiModelProperty 这个注解用来打在entity，vo …这些类得字段上，与@ApiModel注解配合使用 @ApiModelProperty(value = “主键:用户ID”) 如果你不希望某个字段通过这个文档暴露出去，你可以这样 @ApiModelProperty(value = "用户登录密码", hidden = true) 3.3.参数类注解 其实参数类注解之前我也有用过，这个时候我们可以看一下是哪个注解，首先打开jar，找一下: 3.3.1.@ApiParam @ApiParam就是参数的注解，接下来我们再来看一下这个注解的内容。 value是参数的名称含义了，这个defaultValue和required在@RequestParam注解里都有，它们意思分别是默认值和是否必填，再看hidden和readOnly，一个是隐藏，另一个就是只读，最后我们看一下example，这个是参数的填写示例 然后我们再来看一下hidden属性，加上这个后文档中的这个参数就消失了. 4.接口调试 接口调试的话，打开接口文档，找到调试，填写参数，点击发送即可 5.版本控制 knife4j 使用浏览器的localStorage对象,提供了一个细微的版本控制功能,主要体现在如下两个方面： 后端新增接口是识别出变化 后端接口信息变更是会识别出接口变更 knife4j 判断新接口的依据:接口地址+接口请求类型(POST|GET|PUT…) 而任何元素的变更,包括参数类型、接口说明、响应参数等等元素的变更,knife4j 都能识别出接口的变化,并通过icon图表(new)的方式在接口文档中展示出来 对接接口的开发者只需要刷新当前文档页就能看到后端接口是否新增或修改. 效果图: 相关官方文档可参考：官方文档
HashMap类型返回值，可自定义返回消息结构。 import java.util.HashMap; import com.cynthia.common.constant.HttpStatus; import com.cynthia.common.utils.StringUtils; /** * 操作消息提醒 * * @author wcy */ public class AjaxResult extends HashMap<String, Object> { private static final long serialVersionUID = 1L; /** * 状态码 */ public static final String CODE_TAG = "code"; /** * 返回内容 */ public static final String MSG_TAG = "msg"; /** * 数据对象 */ public static final String DATA_TAG = "data"; /** * 初始化一个新创建的 AjaxResult 对象，使其表示一个空消息。 */ public AjaxResult() { } /** * 初始化一个新创建的 AjaxResult 对象 * * @param code 状态码 * @param msg 返回内容 */ public AjaxResult(int code, String msg) { super.put(CODE_TAG, code); super.put(MSG_TAG, msg); } /** * 初始化一个新创建的 AjaxResult 对象 * * @param code 状态码 * @param msg 返回内容 * @param data 数据对象 */ public AjaxResult(int code, String msg, Object data) { super.put(CODE_TAG, code); super.put(MSG_TAG, msg); if (StringUtils.isNotNull(data)) { super.put(DATA_TAG, data); } } /** * 返回成功消息 * * @return 成功消息 */ public static AjaxResult success() { return AjaxResult.success("操作成功"); } /** * 返回成功数据 * * @return 成功消息 */ public static AjaxResult success(Object data) { return AjaxResult.success("操作成功", data); } /** * 返回成功消息 * * @param msg 返回内容 * @return 成功消息 */ public static AjaxResult success(String msg) { return AjaxResult.success(msg, null); } /** * 返回成功消息 * * @param msg 返回内容 * @param data 数据对象 * @return 成功消息 */ public static AjaxResult success(String msg, Object data) { return new AjaxResult(HttpStatus.SUCCESS, msg, data); } /** * 返回错误消息 * * @return */ public static AjaxResult error() { return AjaxResult.error("操作失败"); } /** * 返回错误消息 * * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult error(String msg) { return AjaxResult.error(msg, null); } /** * 返回错误消息 * * @param msg 返回内容 * @param data 数据对象 * @return 警告消息 */ public static AjaxResult error(String msg, Object data) { return new AjaxResult(HttpStatus.ERROR, msg, data); } /** * 返回错误消息 * * @param code 状态码 * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult error(int code, String msg) { return new AjaxResult(code, msg, null); } }
/** * 返回状态码 * * @author wcy */ public class HttpStatus { /** * 操作成功 */ public static final int SUCCESS = 200; /** * 对象创建成功 */ public static final int CREATED = 201; /** * 请求已经被接受 */ public static final int ACCEPTED = 202; /** * 操作已经执行成功，但是没有返回数据 */ public static final int NO_CONTENT = 204; /** * 资源已被移除 */ public static final int MOVED_PERM = 301; /** * 重定向 */ public static final int SEE_OTHER = 303; /** * 资源没有被修改 */ public static final int NOT_MODIFIED = 304; /** * 参数列表错误（缺少，格式不匹配） */ public static final int BAD_REQUEST = 400; /** * 未授权 */ public static final int UNAUTHORIZED = 401; /** * 访问受限，授权过期 */ public static final int FORBIDDEN = 403; /** * 资源，服务未找到 */ public static final int NOT_FOUND = 404; /** * 不允许的http方法 */ public static final int BAD_METHOD = 405; /** * 资源冲突，或者资源被锁 */ public static final int CONFLICT = 409; /** * 不支持的数据，媒体类型 */ public static final int UNSUPPORTED_TYPE = 415; /** * 系统内部错误 */ public static final int ERROR = 500; /** * 接口未实现 */ public static final int NOT_IMPLEMENTED = 501; }
AliOssCloudUtil 工具类 import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; import com.aliyun.oss.OSSClient; import com.aliyun.oss.model.*; import java.io.IOException; import java.io.InputStream; public class AliOssCloudUtil { Log log = LogFactory.getLog(AliOssCloudUtil.class); String endpoint="oss-cn-beijing.aliyuncs.com"; String accessKeyId ="xxxxxxxx"; //你的acessKeyId String accessKeySecret ="xxxxxxxx"; //你的accessKeySecret //空间 private String bucketName = "xxx"; //你的bucketName //文件存储目录 private String filedir = "file/"; private OSSClient ossClient; public AliOssCloudUtil() { ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); } public String getFiledir() { return this.filedir; } //自定义上传文件夹 public AliOssCloudUtil(String filedir) { this.filedir = filedir; ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); } /** * 初始化 */ public void init() { ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); } /** * 销毁 */ public void destory() { ossClient.shutdown(); } /** * 上传到OSS服务器 * * @param instream 文件流 * @param fileName 文件名称 包括后缀名 * @return 出错返回"" ,唯一MD5数字签名 */ public String uploadFile2OSS(InputStream instream, String fileName) { String ret = ""; // 判断bucket是否已经存在,不存在进行创建 if (!doesBucketExist()) { createBucket(); } try { //创建上传Object的Metadata ObjectMetadata objectMetadata = new ObjectMetadata(); objectMetadata.setContentLength(instream.available()); objectMetadata.setCacheControl("no-cache"); objectMetadata.setHeader("Pragma", "no-cache"); objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf(".")))); objectMetadata.setContentDisposition("inline;filename=" + fileName); // 指定上传文件操作时是否覆盖同名Object。 // 不指定x-oss-forbid-overwrite时，默认覆盖同名Object。 // 指定x-oss-forbid-overwrite为false时，表示允许覆盖同名Object。 // 指定x-oss-forbid-overwrite为true时，表示禁止覆盖同名Object，如果同名Object已存在，程序将报错。 objectMetadata.setHeader("x-oss-forbid-overwrite", "false"); String objectName = filedir + fileName; //上传文件 ossClient.putObject(bucketName, objectName, instream, objectMetadata); // 封装 url 路径 String url = "http://" + bucketName + "." + endpoint + "/" + objectName; System.out.println(objectName); ret = url; } catch (IOException e) { log.error(e.getMessage(), e); } finally { ossClient.shutdown(); try { if (instream != null) { instream.close(); } } catch (IOException e) { e.printStackTrace(); } } return ret; } /** * 判断文件是否存在。doesObjectExist还有一个参数isOnlyInOSS， * 如果为true则忽略302重定向或镜像；如果为false，则考虑302重定向或镜像。 * yourObjectName 表示上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。 * * @return 存在返回true */ public boolean doesObjectExist(String objectName) { boolean exists = ossClient.doesObjectExist(bucketName, filedir + objectName); return exists; } /** * 判断Bucket是否存在 * * @return 存在返回true */ public boolean doesBucketExist() { boolean exists = ossClient.doesBucketExist(bucketName); return exists; } /** * 创建Bucket */ public void createBucket() { CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); // 设置bucket权限为公共读，默认是私有读写 createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); // 设置bucket存储类型为低频访问类型，默认是标准类型 createBucketRequest.setStorageClass(StorageClass.IA); boolean exists = ossClient.doesBucketExist(bucketName); if (!exists) { try { ossClient.createBucket(createBucketRequest); // 关闭client ossClient.shutdown(); } catch (Exception e) { log.error(e.getMessage()); } } } /** * Description: 判断OSS服务文件上传时文件的contentType * * @param FilenameExtension 文件后缀 * @return String */ public static String getcontentType(String FilenameExtension) { if (FilenameExtension.equalsIgnoreCase(".bmp")) { return "application/x-bmp"; } if (FilenameExtension.equalsIgnoreCase(".gif")) { return "image/gif"; } if (FilenameExtension.equalsIgnoreCase(".jpeg") || FilenameExtension.equalsIgnoreCase(".jpg") || FilenameExtension.equalsIgnoreCase(".png")) { return "image/jpeg"; } if (FilenameExtension.equalsIgnoreCase(".html")) { return "text/html"; } if (FilenameExtension.equalsIgnoreCase(".txt")) { return "text/plain"; } if (FilenameExtension.equalsIgnoreCase(".vsd")) { return "application/vnd.visio"; } if (FilenameExtension.equalsIgnoreCase(".pptx") || FilenameExtension.equalsIgnoreCase(".ppt")) { return "application/vnd.ms-powerpoint"; } if (FilenameExtension.equalsIgnoreCase(".docx") || FilenameExtension.equalsIgnoreCase(".doc")) { return "application/msword"; } if (FilenameExtension.equalsIgnoreCase(".xla") || FilenameExtension.equalsIgnoreCase(".xlc") || FilenameExtension.equalsIgnoreCase(".xlm") || FilenameExtension.equalsIgnoreCase(".xls") || FilenameExtension.equalsIgnoreCase(".xlt") || FilenameExtension.equalsIgnoreCase(".xlw")) { return "application/vnd.ms-excel"; } if (FilenameExtension.equalsIgnoreCase(".xml")) { return "text/xml"; } if (FilenameExtension.equalsIgnoreCase(".pdf")) { return "application/pdf"; } if (FilenameExtension.equalsIgnoreCase(".zip")) { return "application/zip"; } if (FilenameExtension.equalsIgnoreCase(".tar")) { return "application/x-tar"; } if (FilenameExtension.equalsIgnoreCase(".avi")) { return "video/avi"; } if (FilenameExtension.equalsIgnoreCase(".mp4")) { return "video/mpeg4"; } if (FilenameExtension.equalsIgnoreCase(".mp3")) { return "audio/mp3"; } if (FilenameExtension.equalsIgnoreCase(".mp2")) { return "audio/mp2"; } return "application/octet-stream"; } /** * @param fileName * @return * @Title: getInputStreamByFileUrl * @Description: 根据文件路径获取InputStream流 * @return: InputStream */ public InputStream getInputStreamByFileUrl(String fileName) { // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。 OSSObject ossObject = ossClient.getObject(bucketName, fileName); return ossObject.getObjectContent(); } } 文件上传类例 import com.alibaba.fastjson.JSONObject; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; /** * @author Wcy * @Date 2021/4/23 17:06 */ @RestController public class unloadFile { /** * 文件上传 * @param file * @return */ @PostMapping("/file/upload") public JSONObject upload(@RequestParam("file") MultipartFile file, HttpServletRequest servletRequest) { JSONObject res = new JSONObject(); JSONObject resUrl = new JSONObject(); String filename = file.getResource().getFilename();//文件名称 System.out.println(filename); //这里文件名用了uuid 防止重复，可以根据自己的需要来写 // String name = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."), filename.length()); String name=filename; // name = name.replace("-", ""); InputStream inputStream = null; try { inputStream = file.getInputStream(); } catch (IOException e) { e.printStackTrace(); System.out.println("上传失败"); } AliOssCloudUtil util = new AliOssCloudUtil(); //上传成功返回完整路径的url String url = util.uploadFile2OSS(inputStream, name); System.out.println("上传成功："+url); /** * 以下为可能用到的保存上传信息 double filesize=file.getSize(); String size=String.format("%.2f",filesize/(1024*1024)).toString(); */ return res; } /** * 判断文件是否存在 * @param fileName 储存的文件名 * @return */ @GetMapping("/file/exists") public Boolean exists(String fileName) { AliOssCloudUtil util = new AliOssCloudUtil(); Boolean bool = util.doesObjectExist(fileName); return bool; } /** * 下载oss对应文件 * @param fileName 储存的文件名 * @return */ @PostMapping("/file/downLoad") public void downloadFile(String fileName, HttpServletResponse response) { try { AliOssCloudUtil ossClientUtil = new AliOssCloudUtil(); InputStream is = ossClientUtil.getInputStreamByFileUrl(ossClientUtil.getFiledir() + fileName); // 配置文件下载 response.setHeader("content-type", "application/octet-stream"); response.setContentType("application/octet-stream"); // 下载文件能正常显示中文 response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); OutputStream os = response.getOutputStream(); byte[] b = new byte[1024]; int len = -1; while ((len = is.read(b)) != -1) { os.write(b, 0, len); } is.close(); os.close(); } catch (Exception e) { e.printStackTrace(); } } } 相关配置 //控制文件上传大小 spring.servlet.multipart.max-file-size=1000MB spring.servlet.multipart.max-request-size=1000MB