接上一篇https://blog.csdn.net/m0_46128962/article/details/109174205


五.Docker

1.简介
Docker是一个开源的应用容器引擎;是一个轻量级容器技术;
Docker支持将软件编译成一个镜像;然后在镜像中各种软件做好配置,将镜像发布出去,其他使用者可以直接使 用这个镜像;
运行中的这个镜像称为容器,容器启动是非常快速的。
在这里插入图片描述
在这里插入图片描述
2.核心概念


docker主机(Host):安装了Docker程序的机器(Docker直接安装在操作系统之上);
docker客户端(Client):连接docker主机进行操作;
docker仓库(Registry):用来保存各种打包好的软件镜像;
docker镜像(Images):软件打包好的镜像;放在docker仓库中;
docker容器(Container):镜像启动后的实例称为一个容器;容器是独立运行的一个或一组应用
在这里插入图片描述
使用Docker的步骤:
1)、安装Docker
2)、去Docker仓库找到这个软件对应的镜像;
3)、使用Docker运行这个镜像,这个镜像就会生成一个Docker容器; 4)、对容器的启动停止就是对软件的启动停止;


3.安装Docker


1)、安装linux虚拟机
1、VMWare、VirtualBox(安装);
2、导入虚拟机文件centos7-atguigu.ova;
3、双击启动linux虚拟机;使用 root/ 123456登陆
4、使用客户端连接linux服务器进行命令操作;
5、设置虚拟机网络;

桥接网络=选好网卡==接入网线;
6、设置好网络以后使用命令重启虚拟机的网络

service network restart 

7、查看linux的ip地址

ip addr

8、查看IP后将IP地址填入连接的输入栏,使用客户端连接linux; (当你的WiFi连接的校园网可能造成无法分配IP的问题,造成后面的docker安装有问题,最好使用稳定的网络重新建立一个连接)


2)、在linux虚拟机上安装docker
1、检查内核版本必须是3.10及以上

uname -r

2、安装docker(这里出问题的可以去看看https://blog.csdn.net/qq_39720249/article/details/84104646)

yum install docker

3、输入y确认安装
4、启动docker

[root@localhost ~]# systemctl start docker
[root@localhost ~]# docker -v

5、设置打开虚拟机开机启动docker

[root@localhost ~]# systemctl enable docker

6、停止docker

[root@localhost ~]# systemctl stop docker

4.Docker常用命令&操作
1)、镜像操作

操作命令说明
检索docker search 关键字 eg:docker search redis我们经常去docker hub上检索镜像的详细信息,如镜 像的TAG。
拉取docker pull 镜像名:tag:tag是可选的,tag表示标签,多为软件的版本,后面可以接版本号docker pull:(版本号),默认 是latest
列表docker images查看所有本地镜像
删除docker rmi image-id删除指定的本地镜像

在下载MySQL的时候最好配置阿里云的镜像服务,不然会下载的很慢。地址:https://www.cnblogs.com/360minitao/p/11960655.html
2)、容器操作
软件镜像(QQ安装程序)—运行镜像—产生一个容器(正在运行的软件,运行的QQ);
步骤:

  • 搜索镜像
docker search tomcat
  • 拉取镜像
 docker pull tomcat
  • 根据镜像启动容器(后面的版本号可加可不加)
docker run --name mytomcat -d tomcat:latest
  • 查看运行中的容器
docker ps
  • 停止运行中的容器(这里后面的mytomcat这个位置可以用docker ps中的names也可以用CONTAINER ID)
docker stop mytomcat
  • 查看所有的容器(包括运行过的)
docker ps -a
  • 启动容器(跟run的区别是run是创建一个没有启动过的,而start是启动一个停止了的)
docker start 容器ID或者name
  • 删除容器(一定要停止状态)
docker rm a2b1cb16d8c9(或者name)
  • 启动一个做了端口映射的Tomcat
 docker run -d -p 8888:8080 tomcat 

-d:后台运行
-p将主机的一个端口映射到容器的一个端口 主机端口:容器内部端口

  • 防火墙
service firewalld status(查看防火墙状态)
service firewalld stop (关闭防火墙)
  • 查看容器的日志
 docker logs 2cf186bfb462(容器ID或者容器名)

更多命令参考docker官方文档中每一个镜像的文档
https://docs.docker.com/engine/reference/commandline/docker/
3)、安装mysql示例
https://hub.docker.com/到docker hub中寻找镜像及镜像操作

  • docker pull mysql

  • docker run ‐‐name mysql01 ‐d mysql
    但是这是错误的:通过docker ps我们看不到MySQL正在运行而docker ps -a
    可以看到MySQL运行过了
    通过:
docker logs MySQLId//查看MySQL的日志可以看到我们没有配置密码。

在docker hub 中查找正确的命令。

[root@localhost ~]# docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
2d4a7c0bed264f4a5c3dead38287ba5e67b7d706bf6a47211440222172137c28
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
2d4a7c0bed26        mysql               "docker-entrypoint..."   11 seconds ago      Up 11 seconds       3306/tcp, 33060/tcp   mysql01

然后我们还应该做端口映射。

[root@localhost ~]# docker run -p 3306:3306 --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
6759e7219f3e2f5b282e090d38a69b38971ef9d17b10d30fdccdfaeaad188910

在这里插入图片描述
几个其他的高级操作:
1、用客户端的配置文件

$ docker run --name some-mysql -v /conf/mysql:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

把主机的/conf/mysql文件夹挂载到 mysqldocker容器的/etc/mysql/conf.d文件夹里面
改mysql的配置文件就只需要把mysql配置文件放在自定义的文件夹下(/conf/mysql)
2、不用配置文件直接配置来制定MySQL的一些配置参数。

$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

六.Spring Boot 与数据访问

1.jdbc
先导入依赖

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://192.168.43.243:3306/jdbc
    driver-class-name: com.mysql.cj.jdbc.Driver

效果:
在这里插入图片描述

默认是用class com.zaxxer.hikari.HikariDataSource作为数据源;
数据源的相关配置都在DataSourceProperties里面;(点击yml中的DataSource下的任意一个)
自动配置原理:
org\springframework\boot\autoconfigure\jdbc
1)、参考DataSourceConfiguration,根据配置创建数据源,默认使用HikariDataSource数据源;可以使用spring.datasource.type指定自定义的数据源类型
2)、spring boot默认可以支持:

BasicDataSource、HikariDataSource、org.apache.tomcat.jdbc.pool.DataSource

3)、自定义数据源类型

    @ConditionalOnMissingBean({DataSource.class})
    @ConditionalOnProperty(
        name = {"spring.datasource.type"}
    )
    static class Generic {
        Generic() {
        }

        @Bean
        DataSource dataSource(DataSourceProperties properties) {
        //使用DataSourceBuilder创建数据源,查看build()可以发现利用反射创建响应type的数据源,并且绑定相关属性
            return properties.initializeDataSourceBuilder().build();
        }
    }

4)、同包下的DataSourceInitializerInvoker继承ApplicationListener;可以看到它调用同包下的DataSourceInitializer中的各种schema操作,我们查看DataSourceInitializer
作用:
1、runScripts(scripts, username, password);运行建表语句;
2、runDataScripts();运行插入数据的sql语句;
默认只需要将文件命名为:

schema‐*.sql、data‐*.sql
默认规则:schema.sql,schema‐all.sql;//这两种可以直接使用
在yml中可以使用
schema:
‐ classpath:department.sql
指定位置

在2.0以后必须加上一句

spring.datasource.initialization-mode=always

这里是原理

    private List<Resource> getScripts(String propertyName, List<String> resources, String fallback) {
        if (resources != null) {
            return this.getResources(propertyName, resources, true);
        } else {
            String platform = this.properties.getPlatform();
            List<String> fallbackResources = new ArrayList();
            fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
            fallbackResources.add("classpath*:" + fallback + ".sql");
            return this.getResources(propertyName, fallbackResources, false);
        }
    }

这是我的几种尝试,亲测可行
在这里插入图片描述
5)、操作数据库:自动配置了JdbcTemplate操作数据库

@Controller
public class QueryController {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @ResponseBody
    @GetMapping("/find")
    public Map<String,Object> a(){
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * FROM department");
       return maps.get(0);

    }
}

2.整合Druid数据源

Arrays.asList()

该方法是将数组转化成List集合的方法

//导入Druid数据源
@Configuration
public class DruidConfig {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druid(){
        return  new DruidDataSource();
    }

    //配置Druid的监控
    //1、配置一个管理后台的Servlet
    @Bean
    public ServletRegistrationBean statViewServlet(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String,String> initParams = new HashMap<>();

        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","123456");
        initParams.put("allow","");//默认就是允许所有访问
        initParams.put("deny"," 192.168.43.213");

        bean.setInitParameters(initParams);
        return bean;
    }


    //2、配置一个web监控的filter
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        Map<String,String> initParams = new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");

        bean.setInitParameters(initParams);

        bean.setUrlPatterns(Arrays.asList("/*"));

        return  bean;
    }
}

3.整合mybatis

<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>

步骤:
1)、配置数据源相关属性(见上一节Druid)
2)、给数据库建表

#spring.datasource.schema=classpath:sql/department.sql,classpath:sql/employee.sql
#spring.datasource.initialization-mode=always

3)、创建JavaBean(表中的bean)
4)、注解版

//指定这是一个操作数据库的mapper
@Mapper
public interface DepartmentMapper {

    @Select("select * from department where id=#{id}")
    public Department getDeptById(Integer id);

    @Delete("delete from department where id=#{id}")
    public int deleteDeptById(Integer id);

    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into department(department-name) values(#{departmentName})")
    public int insertDept(Department department);

    @Update("update department set departmentName=#{departmentName} where id=#{id}")
    public int updateDept(Department department);
}

问题:在上面的查找中会出现sql语句的错误,我们应该开启驼峰匹配:
可以在配置文件中加入

mybatis.configuration.map-underscore-to-camel-case=true
#开启驼峰匹配

也可以自定义MyBatis的配置规则;给容器中添加一个ConfigurationCustomizer;

@org.springframework.context.annotation.Configuration
public class MybatisConfig {
    @Bean
    public ConfigurationCustomizer configurationCustomizer(){
        return new ConfigurationCustomizer(){

            @Override
            public void customize(Configuration configuration) {
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}

除了在mapper类上注解@Mapper之外我们还可以在启动类的上面加上下面代码来批量扫描所有接口。

@MapperScan(value = "com.nyb.springboot04web.mapper")
@SpringBootApplication
public class SpringBoot04WebRestfulcrudApplication {

5)、配置文件版

mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

但是这里出现了问题,原来是在主程序类上还是要加上@MapperScan这个注解,否则不会把mapper注入容器中。
总结:这两个XML只是起一个将mapper和xml文件绑定的作用,加入容器中还是要我们自己来。
4.整合SpringData JPA


1)、SpringData JPA简介
在这里插入图片描述
2)、整合SpringData JPA
JPA:ORM(Object Relational Mapping);它也是基于ORM思想


1、编写一个实体类Bean和数据表进行映射,并且配置好映射关系;


//使用jpa注解配置映射关系
@Entity//告诉jpa这是一个实体类
@Table(name = "tb_user")//@Table来指定和那个数据表对应;如果省略就是默认和user对应
public class User {
    @Id//这是一个主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)//主键自增
    private Integer id;
    @Column(name = "last_name" ,length = 50)//这是和数据表对应的一个列
    private String lastName;
    @Column//省略默认列名就是属性名
    private String email;

2、编写一个Dao接口来操作实体类对应的数据表(Repository)

//继承JpaRepository来完成对数据库的操作
public interface UserRepository extends JpaRepository<User,Integer> {
}

3、基本的配置jpaProperties

#更新或者创建数据表结构,当你没有这个表示它自己会帮你创建
spring.jpa.hibernate.ddl-auto=update
#控制台显示sql
spring.jpa.show-sql=true

4、直接写controller就可以了,它那个UserRepository里面有很多的数据访问操作方法。

@RestController
public class JpaUserController {
    @Autowired
    UserRepository userRepository;
    @GetMapping("/user/{id}")
    public User getUser(@PathVariable("id") Integer id){
        return userRepository.findById(id).orElse(null);
    }
}

七.自动配置原理

几个重要的事件回调机制
配置在META-INF/spring.factories
ApplicationContextInitializer
SpringApplicationRunListener
只需要放在ioc容器中
ApplicationRunner
CommandLineRunner
启动流程:
1.创建SpringApplication对象
对主应用的函数debug发现调用类中这个方法

public SpringApplication(Class<?>... primarySources) {
        this((ResourceLoader)null, primarySources);
    }

我们看这个方法

    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        //保存主配置类
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        //判断当前是否为一个web应用,点进去发现如果是它的值为SERVLET
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        //从类路径下找到META‐INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来通过debug中两次stepinto然后stepover可以看到如下图七个initializer       
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //从类路径下找到META‐INF/spring.factories配置的所有ApplicationListener
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        //从多个配置类中找到有main方法的主配置类,可以有多个,因为可以给run方法传入数组
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

在这里插入图片描述
在这里插入图片描述

2.运行run方法

  public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        //获取SpringApplicationRunListeners;从类路径下META‐INF/spring.factories
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //回调所有的获取SpringApplicationRunListener.starting()方法
        listeners.starting();
        Collection exceptionReporters;
        try {
                //封装命令行参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //准备环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            //创建环境完成后回调SpringApplicationRunListener.environmentPrepared();(在prepareEnvironment函数中)表示环境准备完成
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            //创建ApplicationContext;决定创建web(如果type参数是servlet就是web)的ioc还是普通的ioc
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            //准备上下文环境;将environment保存到ioc中;而且applyInitializers();
            //applyInitializers():回调之前保存的所有的ApplicationContextInitializer的initialize方法
            //回调所有的SpringApplicationRunListener的contextPrepared();
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded();

			//刷新容器;ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat);Spring注解版
			//扫描,创建,加载所有组件的地方;(配置类,组件,自动配置)
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }
             //所有的SpringApplicationRunListener回调started方法
            listeners.started(context);
            //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
            //ApplicationRunner先回调,CommandLineRunner再回调
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            //所有的SpringApplicationRunListener回调running方法
            listeners.running(context);
            //整个SpringBoot应用启动完成以后返回启动的ioc容器;
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐