第106天学习打卡(SpringBoot 配置API文档的分组 任务 Springboot整合前半部分 Nosql概述)

配置API文档的分组

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("狂神")
                .enable(flag) //enable是否启动swagger,如果为false,则swagger不能在浏览器中访问
                //select  apis  build 是一套的
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
                //paths()过滤什么路径
                //.paths(PathSelectors.ant("/kuang/**"))
                .build();

如何配置多个分组

package com.kuang.swagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
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;

import java.util.ArrayList;



@Configuration //相当于@Component
@EnableSwagger2  //开启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");
    }
    //配置了swagger的Docket的bean实例

    @Bean
    public Docket docket(Environment environment){
        //设置要显示的Swagger环境
        Profiles profiles = Profiles.of("dev","test");
        //获取项目环境
        //通过environment.acceptsProfiles() 判断是否处在自己设定的环境当中
        boolean flag = environment.acceptsProfiles(profiles);
        System.out.println(flag);


        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("狂神")
                .enable(flag) //enable是否启动swagger,如果为false,则swagger不能在浏览器中访问
                //select  apis  build 是一套的
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
                //paths()过滤什么路径
                //.paths(PathSelectors.ant("/kuang/**"))
                .build();
    }

    //配置Swagger信息 = apiInfo
    private ApiInfo apiInfo(){
        //作者信息
        Contact contact = new Contact("秦疆", "https://blog.kuangstudy.com/", "24736743@qq.com");


        return new ApiInfo("狂神的SwaggerAPI文档",
                "即使再小的帆也能远航",
                "v1.0", "https://blog.kuangstudy.com",
              contact, "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());

    }
}

image-20210424102749283

实体类配置:

HelloController.java

package com.kuang.swagger.controller;

import com.kuang.swagger.pojo.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RestController;



@RestController //由于我们没有页面所有要给他返回一个字符串
public class HelloController {

    @GetMapping(value = "/hello")
    public String hello(){
        return "hello";
    }

    //只要我们的接口中,返回值中存在实体类,他就会被扫描到Swagger中

    @PostMapping(value = "/user")
    public User user(){
        return new User();
    }
}

User.java

package com.kuang.swagger.pojo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 注意:这里的实体类的属性是不能private的   私有属性不会被暴露和注释
@ApiModel("用户实体类")//给实体类添加文档注释
public class User {
    @ApiModelProperty("用户名") //给字段生成文档注释
    public String username;
    @ApiModelProperty("密码")
    public String password;
}

结果显示

image-20210424104210868

package com.kuang.swagger.controller;

import com.kuang.swagger.pojo.User;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RestController;


@RestController //由于我们没有页面所有要给他返回一个字符串
public class HelloController {

    @GetMapping(value = "/hello")
    public String hello(){
        return "hello";
    }

    //只要我们的接口中,返回值中存在实体类,他就会被扫描到Swagger中

    @PostMapping(value = "/user")
    public User user(){
        return new User();
    }
    //Operation接口   不是放在类上的  是放在方法上的
    @ApiOperation("Hello控制类")
    @GetMapping(value = "/hello2")
    public String hello2(@ApiParam("用户名") String username){
        return "hello" + username;
    }


}


结果显示

image-20210424105240494

Post测试

    @ApiOperation("Post测试类")
    @PostMapping(value = "/postt")
    public User post(@ApiParam("用户名") User user){
        int i =  5 / 0 ;
        return user;
    }

image-20210424110524381

总结:

1.我们可以通过Swagger给一些比较难理解的属性或者接口,增加注释信息

2.接口文档实时更新

3.可以在线测试

注意点:

在正式发布的时候,关闭Swagger。出于安全考虑,而且节省运行内存

任务

异步任务~

controller

AsyncController.java

package com.kuang.springboot11test.controller;

import com.kuang.springboot11test.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AsyncController {

    @Autowired
    AsyncService asyncService;
    @RequestMapping("/hello")
    public String hello(){
        asyncService.hello();//停止3秒
        return "OK";
    }
}

service

service.java

package com.kuang.springboot11test.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service  //spring托管
public class AsyncService {

    //告诉Spring这是一个异步的方法
    @Async
    public void hello(){
        try {
            //休息3秒
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("数据正在处理");
    }
}

package com.kuang.springboot11test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

//开启异步注解功能
@EnableAsync
@SpringBootApplication
public class Springboot11TestApplication {

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

}

定时任务~
TaskScheduler 任务调度者
TaskExecutor 任务执行者
   
    
@EnableScheduling//开启定时功能的注解
@Scheuled//什么时候执行

    cron表达式
package com.kuang.springboot11test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

//开启异步注解功能
@EnableAsync
@EnableScheduling//开启定时功能的注解
@SpringBootApplication
public class Springboot11TestApplication {

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

}

**service **

ScheduledService.java

package com.kuang.springboot11test.service;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class ScheduledService {
    //在特定的时间执行这行方法 Timer

    //cron表达式
    //秒  分 时  日 月 周几
    //* 代表匹配该域的任意值
    // ? 代表只能用在DayofMonth和DayofWeek两个域,它也匹配域的任意值,但实际不会,因为DayofMonth和DayofWeek会相互影响
    //0 0/53 16,18 * * ? 每天16点和18点,每隔53分钟执行一次
    // 0 15 10 ? * 1-6  每个月的周一到周六 10点15分执行一次
    //@Scheduled(cron = "0 * * * * 0-7") //周一到周七的任何时候的第0秒 就会去执行下面的代码
   // @Scheduled(cron = "0 53 16 * * ?")// 0 53 16 * * ? 每天的16时 53分执行一次
   @Scheduled(cron = "0/2 * * * * ?") //每两秒执行一次
    public void hello(){
        System.out.println("hello,你被执行了~");
    }
}

邮件发送~

导入依赖pom.xml

<!--        javax.mail-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

application.properties

spring.mail.username=xxxxx@qq.com
spring.mail.password=授权码
spring.mail.host=smtp.qq.com
# 开启加密验证
spring.mail.properties.mail.smtp.ssl.enable=true

测试里面写的: test

image-20210424163231855

package com.kuang.springboot11test;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;

@SpringBootTest
class Springboot11TestApplicationTests {
    @Autowired
    JavaMailSenderImpl mailSender;


    @Test
    void contextLoads() {
        //一个简单的邮件
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setSubject("小狂神你好呀");//邮件主题
        mailMessage.setText("谢谢你的狂神说java系列课程");//邮件内容
        mailMessage.setTo("xxxx@qq.com");
        mailMessage.setFrom("xxxx@qq.com");
        mailSender.send(mailMessage);

    }

    @Test
    void contextLoads2() throws MessagingException {
        //一个复杂的邮件
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        //组装  正文
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
        helper.setSubject("小狂神你好呀,好好学习");//设置主题
        helper.setText("<p style='color:red'>谢谢你的狂神说Java系列课程</p>",true);

        //组件
        helper.addAttachment("1.jpg",new File("C:\\Users\\HP\\Desktop\\1.jpg"));
        helper.addAttachment("2.jpg",new File("C:\\Users\\HP\\Desktop\\1.jpg"));

        helper.setTo("xxxx@qq.com");
        helper.setFrom("xxxx@qq.com");


        mailSender.send(mimeMessage);

    }
//  这里的操作是/** 加回车

    /**
     *
     * @param html
     * @param subject
     * @param text
     * @throws MessagingException
     * @Author kuangshenya
     */

    //封装
    public void sendMail(Boolean html, String subject, String text) throws MessagingException {
        //一个复杂的邮件
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        //组装  正文
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,html);
        helper.setSubject(subject);//设置主题
        helper.setText(text,true);

        //组件
        helper.addAttachment("1.jpg",new File("C:\\Users\\HP\\Desktop\\1.jpg"));
        helper.addAttachment("2.jpg",new File("C:\\Users\\HP\\Desktop\\1.jpg"));

        helper.setTo("xxxx@qq.com");
        helper.setFrom("xxxx@qq.com");


        mailSender.send(mimeMessage);

    }

}

SpringBoot整合

SpringBoot操作数据:spring-data jpa jdbc mongodb redis!

SpringData也是和SpringBoot齐名的项目

说明:在springboot2.x之后,原来使用的jedis被替换为了lettuce

jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis pool 连接池 更像BIO阻塞模式

lettuce:采用nety,实例可以在多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据了,更像NIO模式。

源码分析:

 @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    ) //我们可以自己定义一个redisTemplate来替换这个默认的
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        //默认的RedisTemplate 没有过多的设置, redis对象都需要序列化
        //两个泛型都是Object , Object的类型,我们后面使用需要强制转换<String, Object>
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean// 由于String 是redis中最常用的类型,所以说单独提出来了一个bean!
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

整合测试

  1. 导入依赖
<!--        操作redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

2.配置连接

# 配置reddis
spring.redis.host=127.0.0.1
spring.redis.port=6379

3.测试

package com.kuang;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Redis02SpringbootApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        //redisTemplate   操作不同的数据类型  api和我们的指令是一样的
        // opsForValue  操作字符串的 类似String
        //opsForList  操作List  类似List
        //opsForGeo
        //opsForHash
        //opsForZSet
        //opsForSet
        //opsForHyperLogLog

        //除了基本的操作,我们常用的方法都可以直接通过 redisTemplate 操作  比如事务和CRUD
        // 获取redis的连接对象
//        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
//        connection.flushDb();
//        connection.flushAll();


        redisTemplate.opsForValue().set("mykey","kuangshen");
        System.out.println(redisTemplate.opsForValue().get("mykey"));


    }

}

image-20210424191541976

image-20210424191833383

因为这部分的知识需要用到Redis 所以 现在开始学习Redis部分

Nosql概述

为什么要用Nosql

1.单机MySQL的年代

image-20210424193958835

90年代,一个基本的网站访问量一般不会太大,单个数据库完全足够

那个时候,更多的去使用静态网页Html,服务器根本没有太大的压力!
思考一下,这种情况下:整个网站的 瓶颈是什么??

1.数据量如果太大,一个机器放不下

2.数据的索引(B + Tree),一个机器内存也放不下

3.访问量(读写混合),一个服务器承受不了

只要出现以上的三种情况之一,那么就必须晋级。

2.Memcached(缓存)+ MySQL+垂直拆分(读写分离)

网站80%都是在读,每次去查询数据库就很麻烦!所以说我们希望减轻数据库的压力,我们可以使用缓存保证。

发展过程:优化数据库和索引 --> 文件缓存(IO)—>Memcached(当时最热门的技术!)

image-20210424195434823

3分库分表 + 水平拆分 + MySQL集群

本质:数据库(读,写)

早些年MyISAM:表锁,十分影响效率,会锁住一个表!高并发下就会出现严重的锁问题

转战Innodb:行锁,只锁定一行

慢慢的就开始使用分库分表来解决写的压力!

为什么要用NoSQL

用户的个人信息,社交网络,地理位置,用户自己产生的数据,用户日志等爆发式增长!

这时候我们就需要使用Nosql数据库, NoSQL可以很好的处理以上问题。

NoSQL

Nosql

Nosql = Not Only SQL(不仅仅是SQL)

泛指非关系性数据库,随着web2.0互联网的诞生!传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区!暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的,而且是我们当下必须要掌握的技术。

很多的数据类型用户的个人信息,社交网络,地理位置,这些数据类型的存储不需要一个固定的格式!不需要多余的操作就可以横向扩展的。Map<String, Object>

NoSQL特点

解耦!

1.方便扩展(数据库之间没有关系,很好扩展)

2.大数据量高性能(Redis一秒写8万次,读取11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高)

3.数据类型是多样类型的(不需要事先设计数据库!随取随用,如果数据量十分大的表,很多人就无法去设计了)

  • 五大基本数据类型
    • String
    • Lust
    • Set
    • Hash
    • Zset
  • 三种特殊数据类型
    • geo
    • hyperloglog
    • bitmap

4.传统RDBMS(关系型数据库) 和NoSQL的区别

传统的 ROBMS
- 结构化组织
- SQL
- 数据和关系都存在单独的表中 row  col
- 数据操作,数据定义语言
- 严格的一致性
- 基础的事务
- ...
Nosql
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,图形数据库(社交关系)
- 最终一致性
- CAP定理和BASE(异地多活) 初级架构师
- 高性能,高可用,高可扩
-......

了解:3 V + 3高

大数据时代的3V :主要是描述问题

  1. 海量Volume
  2. 多样Variety
  3. 实时Velocity

大数据时代的3高:主要是对程序的要求

1.高并发

2.高可扩

3.高性能(保证用户体验和性能)

真正在公司中的实践:Nosql + ROBMS

B站学习网址:【狂神说Java】SpringBoot最新教程IDEA版通俗易懂_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

【狂神说Java】Redis最新超详细版教程通俗易懂_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值