Swagger

  1. 了解Swagger
  2. 导入环境
  3. 配置Swagger
    1. 配置Swagger信息
    2. 配置Swagger的扫描接口
    3. 配置是否启动Swagger
    4. 分组
    5. 注解和测试
  • 任务
    1. 异步任务
    2. 邮件任务
    3. 定时任务和CRON表达式
  • 了解Swagger

    • 号称是世界上最流行的API框架
    • Restful API文档在线自动生成工具==>API文档与API同步更新
    • 直接运行,可以在线直接测试API接口
    • 支持多种语言:JAVA,PHP等

    官网:https://swagger.io/


    导入环境

    • swagger2
    • ui
    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>
    
    • SpringBoot继承Swagger
    1. 新建一个Spring Boot - web项目
    2. 引入环境
    3. 配置Swagger

    我们都知道,配置在Spring Boot中就是Config

    有一件事:Swagger2是新版的,而Swagger是老版的

    @Configuration
    @EnableSwagger2 //允许Swagger使用,Swagger2是新版
    public class SwaggerConfig {
    }
    

    Swagger默认的页面是swagger-ui.html,不用配置就有


    配置Swagger

    配置Swagger信息

    • Contact:作者信息
      • name:作者
      • url:作者地址
      • email:作者邮箱
    • API Info
      • title:标题
      • description:描述
      • version:版本
      • termsOfServiceURL:组织的地址
      • concat:作者描述
    @Configuration
    @EnableSwagger2 //允许Swagger使用,Swagger2是新版
    public class SwaggerConfig {
    
        /**
         * 配置Swagger的Docket实例
         * apiInfo:Swagger信息
         * @return
         */
        @Bean
        public Docket docket(){
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo());
        }
    
    
        /**
         * Contact
         *      name:作者名
         *      url:作者地址
         *      email:作者邮箱
         *  ApiInfo
         *      title:标题
         *      description:描述
         *      version:版本
         *      termsOfServiceUrl:组织的地址
         *      concat:作者描述
         * @return
         */
        private ApiInfo apiInfo(){
            Contact contact = new Contact("嚎羸","localhost:8080","xxxx@qq.com");
            return new ApiInfo(
                    "嚎羸的Swagger",
                    "Swagger文档",
                    "v1.0",
                    "localhost:8080",
                    contact,
                    "Apache 2.0",
                    "http://www.apache.org/licenses/LICENSE-2.0",
                    new ArrayList<>()
            );
        }
    
    }
    


    配置Swagger的扫描接口

    • apis:设置要扫描的api
      • RequesthandlerSelectors:配置api的扫描方式
        • basePackage:指定要扫描的包
        • any:全部扫描
        • none:全不扫描
        • withClassAnnotation:扫描类上的注解,参数是一个注解的反射对象
        • withMethodAnnotation:扫描方法上的注解,参数同上
    • paths:指定请求的路径
      • PathSelectors:路径设置
        • any:全都要
        • ant:配置路径
        • none:全不要
        • regex:正则方式
    @Configuration
    @EnableSwagger2 //允许Swagger使用,Swagger2是新版
    public class SwaggerConfig {
    
        /**
         * .apis(RequestHandlerSelectors.basePackage("com.bean")):只扫描com.bean.controller下的
         * .paths(PathSelectors.ant("/hello/**")):只扫描请求为xxx/hello/xxx的
         * @return
         */
        @Bean
        public Docket docket(){
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.bean.controller"))
                    .paths(PathSelectors.ant("/hello/**"))
                    .build();
        }
    
        private ApiInfo apiInfo(){
            Contact contact = new Contact("嚎羸","localhost:8080","xxxx@qq.com");
            return new ApiInfo(
                    "嚎羸的Swagger",
                    "Swagger文档",
                    "v1.0",
                    "localhost:8080",
                    contact,
                    "Apache 2.0",
                    "http://www.apache.org/licenses/LICENSE-2.0",
                    new ArrayList<>()
            );
        }
    
    }
    

    这场使用了构造器

    • select
    • builder

    那么注意了,从select–>build中是一套,只有apispaths两个方法,要使用其他方法,到外边去


    配置是否启动Swagger

    • enable
      • true:可以在浏览器中访问
      • false:不可以在浏览器中访问
    @Configuration
    @EnableSwagger2 //允许Swagger使用,Swagger2是新版
    public class SwaggerConfig {
    
        @Bean
        public Docket docket(){
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .enable(false);
        }
    
        private ApiInfo apiInfo(){
            Contact contact = new Contact("嚎羸","localhost:8080","xxxx@qq.com");
            return new ApiInfo(
                    "嚎羸的Swagger",
                    "Swagger文档",
                    "v1.0",
                    "localhost:8080",
                    contact,
                    "Apache 2.0",
                    "http://www.apache.org/licenses/LICENSE-2.0",
                    new ArrayList<>()
            );
        }
    
    }
    

    问题来了:

    我只想让我的Swagger的生产环境中使用,而不想在发布的时候用


    解决方法:

    1. 要有多个配置文件
    2. 设定配置文件中哪个配置文件可以访问,哪些不可以访问Swagger
    3. 获取运行时使用的配置
    4. 判断是否为可以访问的配置文件
    5. 设置Swagger
    6. 配置多个配置文件
    application.properties			#总控台
    application-dev.properties		#生产环境 
    application-pro.properties		#发布环境
    application-test.properties		#测试环境
    

    这些配置文件什么也没有,就是个空壳,只不过创建出来了

    1. 我们假定使用生产环境和测试环境的时候可以访问
    2. 获取运行时的配置+判断是否可以访问+设置Swagger
    • SwaggerConfig.java
    import org.springframework.core.env.Environment;
    import org.springframework.core.env.Profiles;
    
    @Configuration
    @EnableSwagger2 //允许Swagger使用,Swagger2是新版
    public class SwaggerConfig {
    
        @Bean
        public Docket docket(Environment environment){
    
            //通过profiles得到具体的环境配置
            Profiles profiles = Profiles.of("dev","test");
    
            //通过环境检测现在运行的环境是否是profiles中配置的环境
            boolean flag = environment.acceptsProfiles(profiles);
    
            //通过flag来设置swagger是否可见
            return new Docket(DocumentationType.SWAGGER_2)
                    .enable(flag)
                    .apiInfo(apiInfo());
        }
    
        private ApiInfo apiInfo(){
            Contact contact = new Contact("嚎羸","localhost:8080","xxxx@qq.com");
            return new ApiInfo(
                    "嚎羸的Swagger",
                    "Swagger文档",
                    "v1.0",
                    "localhost:8080",
                    contact,
                    "Apache 2.0",
                    "http://www.apache.org/licenses/LICENSE-2.0",
                    new ArrayList<>()
            );
        }
    
    }
    

    注意导入包别导错了


    这只是一个方法,当然也可以使用Properties来进行检测



    分组

    @Configuration
    @EnableSwagger2 //允许Swagger使用,Swagger2是新版
    public class SwaggerConfig {
    
        @Bean
        public Docket docket(Environment environment){
    
            //groupName:分组名字
            return new Docket(DocumentationType.SWAGGER_2)
                    .groupName("Bean")
                    .apiInfo(apiInfo());
        }
    
        private ApiInfo apiInfo(){
            Contact contact = new Contact("嚎羸","localhost:8080","xxxx@qq.com");
            return new ApiInfo(
                    "嚎羸的Swagger",
                    "Swagger文档",
                    "v1.0",
                    "localhost:8080",
                    contact,
                    "Apache 2.0",
                    "http://www.apache.org/licenses/LICENSE-2.0",
                    new ArrayList<>()
            );
        }
    
    }
    

    使用.groupName进行分组

    那么问题来了:

    如何进行多组分组?

    配置多个分组就需要多个.groupName(),而多个groupName就需要多个Docket

    @Configuration
    @EnableSwagger2 //允许Swagger使用,Swagger2是新版
    public class SwaggerConfig {
    
    
        @Bean
        public Docket docket1(){
            return new Docket(DocumentationType.SWAGGER_2).groupName("A");
        }
    
        @Bean
        public Docket docket2(){
            return new Docket(DocumentationType.SWAGGER_2).groupName("B");
        }
    
        @Bean
        public Docket docket3(){
            return new Docket(DocumentationType.SWAGGER_2).groupName("C");
        }
    
        @Bean
        public Docket docket(Environment environment){
    
            //groupName:分组名字
            return new Docket(DocumentationType.SWAGGER_2)
                    .groupName("Bean")
                    .apiInfo(apiInfo());
        }
    
        private ApiInfo apiInfo(){
            Contact contact = new Contact("嚎羸","localhost:8080","xxxx@qq.com");
            return new ApiInfo(
                    "嚎羸的Swagger",
                    "Swagger文档",
                    "v1.0",
                    "localhost:8080",
                    contact,
                    "Apache 2.0",
                    "http://www.apache.org/licenses/LICENSE-2.0",
                    new ArrayList<>()
            );
        }
    
    }
    
    • 不要忘记交给Spring托管
    • 分组的名字不能重复,否则会报错


    注解和测试

    • @ApiModle("xxx"):实体类
    • @ApiModelProperty("xxx"):实体类参数
    • @ApiOperation("xxx"):控制层方法
    • @ApiParam("xxx"):控制层方法参数
    • 实体类
    @ApiModel("学生实体类")
    public class Student {
    
        @ApiModelProperty("id")
        private int id;
    
        @ApiModelProperty("用户名")
        public String username;
    
        @ApiModelProperty("密码")
        public String password;
    
    }
    
    • 注意,这里使用private的时候swagger是扫描不到的
    • 只有控制层返回了这个实体类之后,swagger才会显示这个实体类
    • controller
    @Controller
    public class HelloController {
    
    
        @PostMapping("/hello")
        @ResponseBody
        @ApiOperation("Hello控制")
        public String hello(){
            return "hello";
        }
    
    
        @PostMapping("/hello2")
        @ResponseBody
        @ApiOperation("Hello2控制")
        public Student hello2(@ApiParam("用户名") String username){
            return new Student();
        }
    }
    




    任务

    • 异步任务
    • 定时任务
    • 邮件发送

    异步任务

    在后端使用异步任务的时候前台不得不停止,这是一个很恐怖的事情

    但是现在我们只需要两个注解就可以告诉spring这是一个异步任务,那么我们就可以实现前端秒刷新,后端慢慢加载

    • @EnableAsync:用于主方法上的类,开启异步任务
    • @Async:作用于具体的异步方法,用于告诉Spring这是一个异步方法
    • MainActivity
    //开启异步注解功能:@EnableAsync
    @EnableAsync
    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    
    • service
    @Service
    public class AsyncService {
    
        //告诉spring这是一个异步的方法:@Async
        @Async
        public void hello(){
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("数据正在加载...");
        }
    
    }
    
    • controller
    @Controller
    public class AsyncController {
    
        @Autowired
        AsyncService asyncService;
    
        @RequestMapping("/hello")
        @ResponseBody
        public String hello(){
            asyncService.hello();
            return "hello";
        }
    
    }
    

    邮件任务

    1. 环境
    <!--邮件发送-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    
    1. properties
    # 账户
    spring.mail.username=2592716753@qq.com
    # 从邮箱中来的授权码
    spring.mail.password=ivlqayhvydkaecec
    # 主机,以smtp开头,如果是163就是smtp.163.com
    spring.mail.host=smtp.qq.com
    
    # qq特有的加密规则,是否开启安全验证
    spring.mail.properties.mail.smtp.ssl.enable=true
    
    1. 测试代码
    @SpringBootTest
    class DemoApplicationTests {
    
        @Autowired
        JavaMailSenderImpl mailSender;
    
        @Test
        void contextLoads() {
    
            SimpleMailMessage message = new SimpleMailMessage();
    
            //收件人标题
            message.setSubject("收件人");
            //文本
            message.setText("文本");
            //收件人
            message.setTo("2592716753@qq.com");
            //发件人
            message.setFrom("2592716753@qq.com");
    
    
            mailSender.send(message);
        }
    
    }
    

    复杂些的邮件

    @SpringBootTest
    class DemoApplicationTests {
    
        @Autowired
        JavaMailSenderImpl mailSender;
    
    	@Test
        void contextLoads2() throws MessagingException {
    
    
            MimeMessage message = mailSender.createMimeMessage();
    
            //这个有四个重载:MimeMessage(复杂邮件),multipart(支持多文件),encoding(支持编码)
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
    
            //标题
            helper.setSubject("复杂类型邮件");
    
            //正文,这个也有重载:text(文本),html(html支持)
            helper.setText("<p style='color:red'>正文</p>",true);
    
            //添加附件
            helper.addAttachment("1.txt",new File("C:\\Users\\Bean\\Desktop\\1.txt"));
    
            //发件人
            message.setFrom("2592716753@qq.com");
    
            //收件人
            helper.setTo("2592716753@qq.com");
    
    
            mailSender.send(message);
        }
    }
    

    定时任务和CRON表达式

    两个核心接口

    • TaskExecutor:任务执行者
    • TaskScheduler:任务调度者

    两个注解

    • @EnableScheduling:开启定时功能的注解
    • @Scheduled:表示什么时候执行

    CRON表达式

    cron,在特定的时间执行特定的事情

    CRON有六个参数,从左往右分别为:秒、分、时、日、月、周几(0~7)、年

    域名 可取值 可取符号(仅列部分常用)
    秒域 0~59的整数 *    -    ,    /
    分域 0~59的整数 *    -    ,    /
    时域 0~23的整数 *    -    ,    /
    日域 1~31的整数 *    -    ,    /    ?    L
    月域 112的整数或JANDEC *    -    ,    /
    周域 17的整数或SUNSAT *    -    ,    /    ?    L    #
    年域 1970~2099的整数 *    -    ,    /
    • *匹配全部
    • -匹配范围:1-2表示1到2
    • ,表示枚举:1,2表示1和2
    • /表示起始时间和间隔时间:*/5 * * * * ?:表示每隔5秒执行一次
    • ?只可以用在周或者日上,必须出现且只出现一次,表示不确定值
    • L表示最后,只能用于日或者周:0 0 0 ? * 6L:每个星期六的0秒0分0时执行一次
    • #只可以用于周,表示周几:#3:周3
    • 年可以省略,省略时表示每年
    • 注意,在CRON中,0和7都代表着周日,这个对中国人很友好
    • 只有日和周有扩展符号
    • ?在表达式中必须且仅出现一次,并且只能用于周或者日上,因为这两个相互冲突
    • 只有周有#

    例子:

    秒		分 		时 		日 		月 		周		年
    
    每隔5秒执行一次:*/5 * * * * ?
     
    每隔1分钟执行一次:0 */1 * * * ?
     
    每天23点执行一次:0 0 23 * * ?
     
    每天凌晨1点执行一次:0 0 1 * * ?
     
    每月1号凌晨1点执行一次:0 0 1 1 * ?
     
    每月最后一天23点执行一次:0 0 23 L * ?
     
    每周星期天凌晨1点实行一次:0 0 1 ? * L
     
    在26分、29分、33分执行一次:0 26,29,33 * * * ?
    每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?
    

    @EnableScheduling//开启任务调度
    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
    
        }
    }
    
    @Service
    public class ScheduledService {
    
        @Scheduled(cron = "*/5 * * ? * 6")
        public void hello(){
            System.out.println("在特定的时间执行这个方法");
        }
    }
    


    转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。