1. 程式人生 > 實用技巧 >SpringBoot入門(四)——Docker、資料訪問、原理

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/