zoukankan      html  css  js  c++  java
  • SpringBoot入门(四)——Docker、数据访问、原理

    iwehdio的博客园:https://www.cnblogs.com/iwehdio/

    1、Docker

    一个开源的应用容器引擎。

    • 支持将软件编译成一个镜像,然后再镜像中各种软件做好配置,将镜像发布出去。其他使用者可以直接使用这个镜像。
    • 运行中的这个镜像被称为容器。
    • Docker核心概念:
      • docker主机:安装了Docker程序的机器。
      • docker客户端:连接docker主机进行操作。
      • docker仓库:用来保存各种打包好的软件镜像。分为公共仓库和私人仓库等。
      • docker镜像:配置好的软件打包好的镜像,放在docker仓库中。
      • docker容器:镜像启动后的实例被成为一个容器。
    • 使用docker的步骤:
      • 安装docker。
      • 去docker仓库找到这个软件对应的镜像,
      • 使用docker运行这个镜像,生成一个docker容器。
      • 容器的运行与停止就是软件的启动停止。
    • 使用Docker:
      • 安装Docker:yum install docker
      • 启动Docker:systemctl start docker
      • docker开机启动:systemctl enable docker
      • 停止docker:systemctl stop docker
    • Docker常用操作:
      • 镜像操作:
        • 检索:docker search 镜像名
        • 拉取:docker pull 镜像名:标签名。不加标签名默认最新。
        • 查看所有镜像:docker images
        • 删除:docker rmi 镜像id
      • 容器操作:
        • 软件镜像 > 运行镜像 > 产生容器(正在运行的软件)。
        • 根据镜像启动容器:docker run --name 容器名 -d 镜像名:标签名。--name后写自定义容器名,-d表示后台运行。
          • 端口映射:-p 主机端口:容器端口
          • 外部连接容器需要进行端口映射。
        • 查看运行的容器:docker ps。-a表示查看所有容器。
        • 停止运行中的容器:docker stop 容器名或id
        • 删除容器:docker rm 容器名或id
        • 启动容器:docker start 容器名或id
        • 容器日志:docker logs 容器名或id
    • Docker启动MYSQL:
      • 启动时指定密码:-e MYSQL_ROOT_PASSWORD=
    • 使用阿里云服务器,需要在安全组中开放端口8080(tomcat)、3306(mysql)
    • 访问阿里云上Docker部署的Tomcat:https://blog.csdn.net/abcde123_123/article/details/103879385。

    2、数据访问

    • 底层使用SpringData访问关系型数据库和非关系型数据库。

    • 配置连接的数据库:

    • SpringBoot2.0配置Druid:

      • 配置文件:

        spring:
          datasource:
            type: com.alibaba.druid.pool.DruidDataSource
            driverClassName: com.mysql.cj.jdbc.Driver
            platform: mysql
            url: jdbc:mysql://IP地址:3306/springboot_jdbc
            username: root
            password: 123456
            initialSize: 5
            minIdle: 5
            maxActive: 20
            maxWait: 60000
            timeBetweenEvictionRunsMillis: 60000
            minEvictableIdleTimeMillis: 300000
            validationQuery: SELECT1FROMDUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
        
      • 实现监控:

        @Configuration
        public class DruidConfig {
        
            @Bean
            public ServletRegistrationBean druidServlet() {// 主要实现web监控的配置处理
                ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
                        new StatViewServlet(), "/druid/*");//表示进行druid监控的配置处理操作
                servletRegistrationBean.addInitParameter("loginUsername", "root");//用户名
                servletRegistrationBean.addInitParameter("loginPassword", "root");//密码
                servletRegistrationBean.addInitParameter("resetEnable", "false");//是否可以重置数据源
                return servletRegistrationBean;
            }
        
            @Bean    //监控
            public FilterRegistrationBean filterRegistrationBean() {
                FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
                filterRegistrationBean.setFilter(new WebStatFilter());
                filterRegistrationBean.addUrlPatterns("/*");//所有请求进行监控处理
                filterRegistrationBean.addInitParameter("exclusions", "/static/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");//排除
                return filterRegistrationBean;
            }
        
            @Bean
            @ConfigurationProperties(prefix = "spring.datasource")
            public DataSource druidDataSource() {
                return new DruidDataSource();
            }
        
        }
        
    • 整合Mybatis(注解):

      • 编写操作数据库的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(departmentName) value(#{departmentName})")
            public int insertDept(Department department);
            @Update("update department set departmentName=#{departmentName} where id=#{id}")
            public int updateDept(Department department);
        }
        
      • 编写控制器:

        @RestController
        public class DeptController {
            @Autowired
            DepartmentMapper departmentMapper;
            @GetMapping("/dept/{id}")
            public Department getDept(@PathVariable("id") Integer id) {
                return departmentMapper.getDeptById(id);
            }
            @GetMapping("/dept")
            public Department insertDept(Department department) {
                departmentMapper.insertDept(department);
                return department;
            }
        }
        
      • 或者在主程序中使用@MapperScan指定批量扫描。

    • 整合Mybatis(配置文件):

      • 在Springboot配置文件中指定配置文件的位置。
      • mybatis.config-locations指定全局配置文件的位置。
      • mybatis.mapper-locations指定映射配置文件的位置。
    • 整合JPA:

      • application.yaml配置文件:

        spring:
          datasource:
            url: jdbc:mysql:///jpa
            username: root
            password: root
            driver-class-name: com.mysql.jdbc.Driver
          jpa:
            hibernate:
              ddl-auto: update
            show-sql: true
        
      • 实体类:

        @Entity
        @Table(name = "tbl_user")
        public class User {
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            @Column
            private Integer id;
            @Column
            private String lastName;
            @Column
            private String email;
        }
        
      • UserDao接口:

        public interface UserDao extends JpaRepository<User, Integer> {
        }
        
      • 控制器:

        @RestController
        public class UserController {
        
            @Autowired
            UserDao userDao;
            
            @GetMapping("/user/{id}")
            public User getUser(@PathVariable("id") Integer id) {
                User one = userDao.findOne(id);
                return one;
            }
        
            @GetMapping("/user")
            public User insertUser(User user) {
                User save = userDao.save(user);
                return save;
            }
        }
        

    3、Springboot原理

    • 启动运行流程:

      • 创建SpringApplication对象。

        initialize(sources);
        private void initialize(Object[] sources) {
            //保存主配置类
            if (sources != null && sources.length > 0) {
                this.sources.addAll(Arrays.asList(sources));
            }
            //判断当前是否一个web应用
            this.webEnvironment = deduceWebEnvironment();
            //从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
            setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
            //从类路径下找到META-INF/spring.factories配置的所有ApplicationListener
            setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
            //从多个配置类中找到有main方法的主配置类
            this.mainApplicationClass = deduceMainApplicationClass();
        }
        
      • 运行run()方法。

        public ConfigurableApplicationContext run(String... args) {
           StopWatch stopWatch = new StopWatch();
           stopWatch.start();
           ConfigurableApplicationContext context = null;
           FailureAnalyzers analyzers = null;
           configureHeadlessProperty();
            
           //获取SpringApplicationRunListeners;从类路径下META-INF/spring.factories
           SpringApplicationRunListeners listeners = getRunListeners(args);
            //回调所有的获取SpringApplicationRunListener.starting()方法
           listeners.starting();
           try {
               //封装命令行参数
              ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
              //准备环境
              //创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成
              ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
               		
              Banner printedBanner = printBanner(environment);
               //创建ApplicationContext;决定创建web的ioc还是普通的ioc
              context = createApplicationContext();
               
              analyzers = new FailureAnalyzers(context);
               //准备上下文环境;将environment保存到ioc中;而且applyInitializers();
               //applyInitializers():回调之前保存的所有的ApplicationContextInitializer的initialize方法
               //回调所有的SpringApplicationRunListener的contextPrepared();
              prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
               //prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded();
               
               //刷新容器;ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat)
               //扫描,创建,加载所有组件的地方;(配置类,组件,自动配置)
              refreshContext(context);
               //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
               //ApplicationRunner先回调,CommandLineRunner再回调
              afterRefresh(context, applicationArguments);
               //所有的SpringApplicationRunListener回调finished方法
              listeners.finished(context, null);
              stopWatch.stop();
              if (this.logStartupInfo) {
                 new StartupInfoLogger(this.mainApplicationClass)
                       .logStarted(getApplicationLog(), stopWatch);
              }
               //整个SpringBoot应用启动完成以后返回启动的ioc容器;
              return context;
           }
           catch (Throwable ex) {
              handleRunFailure(context, listeners, analyzers, ex);
              throw new IllegalStateException(ex);
           }
        }
        
    • 几个重要的事件回调机制:

      • 配置在META-INF/spring.factories:

        • ApplicationContextInitializer

          public class HelloApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
              @Override
              public void initialize(ConfigurableApplicationContext applicationContext) {
                  System.out.println("ApplicationContextInitializer...initialize..."+applicationContext);
              }
          }
          
        • SpringApplicationRunListener

          public class HelloSpringApplicationRunListener implements SpringApplicationRunListener {
              //必须有的构造器
              public HelloSpringApplicationRunListener(SpringApplication application, String[] args){
              }
              @Override
              public void starting() {
                  System.out.println("SpringApplicationRunListener...starting...");
              }
              @Override
              public void environmentPrepared(ConfigurableEnvironment environment) {
                  Object o = environment.getSystemProperties().get("os.name");
                  System.out.println("SpringApplicationRunListener...environmentPrepared.."+o);
              }
              @Override
              public void contextPrepared(ConfigurableApplicationContext context) {
                  System.out.println("SpringApplicationRunListener...contextPrepared...");
              }
              @Override
              public void contextLoaded(ConfigurableApplicationContext context) {
                  System.out.println("SpringApplicationRunListener...contextLoaded...");
              }
              @Override
              public void finished(ConfigurableApplicationContext context, Throwable exception) {
                  System.out.println("SpringApplicationRunListener...finished...");
              }
          }
          
        • 配置文件META-INF/spring.factories:

          org.springframework.context.ApplicationContextInitializer=
          com.atguigu.springboot.listener.HelloApplicationContextInitializer
          
          org.springframework.boot.SpringApplicationRunListener=
          com.atguigu.springboot.listener.HelloSpringApplicationRunListener
          
      • 只需要放在ioc容器中:

        • ApplicationRunner

          @Component
          public class HelloApplicationRunner implements ApplicationRunner {
              @Override
              public void run(ApplicationArguments args) throws Exception {
                  System.out.println("ApplicationRunner...run....");
              }
          }
          
        • CommandLineRunner

          @Component
          public class HelloCommandLineRunner implements CommandLineRunner {
              @Override
              public void run(String... args) throws Exception {
                  System.out.println("CommandLineRunner...run..."+ Arrays.asList(args));
              }
          }
          
    • 自定义starters:

      • 如何编写自动配置:

        @Configuration  //指定这个类是一个配置类
        @ConditionalOnXXX  //在指定XXX条件成立的情况下自动配置类生效
        @AutoConfigureAfter  //指定自动配置类的顺序
        @Bean  //给容器中添加组件
        
        @ConfigurationPropertie结合相关xxxProperties类来绑定相关的配置
        @EnableConfigurationProperties //让xxxProperties生效加入到容器中
        
        自动配置类要能加载
        将需要启动就加载的自动配置类,配置在META-INF/spring.factories
        
      • 模式:

        • 启动器starter只用来做依赖导入,专门写一个自动配置模块。
        • 启动器模块需要引入自动配置模块。自动配置模块都需要引入spring-boot-starter-parent。
        • 命名:启动器名-spring-boot-starter。
      • 自定义步骤:

        • 创建HelloProperties,绑定主配置文件中的atguigu.hello属性:

          @ConfigurationProperties(prefix = "atguigu.hello")
          public class HelloProperties {
              private String prefix;
              private String suffix;
          
              public String getPrefix() {
                  return prefix;
              }
              public void setPrefix(String prefix) {
                  this.prefix = prefix;
              }
              public String getSuffix() {
                  return suffix;
              }
              public void setSuffix(String suffix) {
                  this.suffix = suffix;
              }
          }
          
        • 创建HelloService组件,创建sayHellAtguigu打招呼方法:

          public class HelloService {
          
              HelloProperties helloProperties;
          
              public HelloProperties getHelloProperties() {
                  return helloProperties;
              }
              public void setHelloProperties(HelloProperties helloProperties) {
                  this.helloProperties = helloProperties;
              }
          
              public String sayHellAtguigu(String name){
                  return helloProperties.getPrefix()+"-" +name + helloProperties.getSuffix();
              }
          }
          
        • 创建HelloServiceAutoConfiguration自动配置类,向容器中添加HelloService:

          @Configuration
          @ConditionalOnWebApplication //web应用才生效
          @EnableConfigurationProperties(HelloProperties.class) //属性配置文件生效
          public class HelloServiceAutoConfiguration {
          
              @Autowired
              HelloProperties helloProperties;
              @Bean
              public HelloService helloService(){
                  HelloService service = new HelloService();
                  service.setHelloProperties(helloProperties);
                  return service;
              }
          }
          
        • 在META-INF下创建spring.factories:

          org.springframework.boot.autoconfigure.EnableAutoConfiguration=
          com.atguigu.starter.HelloServiceAutoConfiguration
          
        • 在其他项目中引入该starter并使用:

          @RestController
          public class HelloController {
          
              @Autowired
              HelloService helloService;
          
              @GetMapping("/hello")
              public String hello(){
                  return helloService.sayHellAtguigu("haha");
              }
          }
          

    iwehdio的博客园:https://www.cnblogs.com/iwehdio/
  • 相关阅读:
    P1144 最短路计数
    P2966 [USACO09DEC]牛收费路径Cow Toll Paths
    P2419 [USACO08JAN]牛大赛Cow Contest
    P1462 通往奥格瑞玛的道路
    P1346 电车
    P1339 [USACO09OCT]热浪Heat Wave
    P1418 选点问题
    P1330 封锁阳光大学
    P1182 数列分段Section II
    P2661 信息传递
  • 原文地址:https://www.cnblogs.com/iwehdio/p/13520346.html
Copyright © 2011-2022 走看看