Java必知必會-SpringBoot02
五、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)、使用客戶端連線linux;
2)、在linux虛擬機器上安裝docker
步驟:(Centos7版)
1、檢查核心版本,必須是3.10及以上
uname -r
2、安裝docker
yum install docker
3、輸入y確認安裝
4、啟動docker
[root@localhost ~]# systemctl start docker
[root@localhost ~]# docker -v
Docker version 1.12.6, build 3e8e77d/1.12.6
5、開機啟動docker
[root@localhost ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
6、停止docker
systemctl stop docker
4、Docker常用命令&操作
1)、映象操作
操作 | 命令 | 說明 |
---|---|---|
檢索 | docker search 關鍵字 eg:docker search redis | 我們經常去docker hub上檢索映象的詳細資訊,如映象的TAG。 |
拉取 | docker pull 映象名:tag | :tag是可選的,tag表示標籤,多為軟體的版本,預設是latest |
列表 | docker images | 檢視所有本地映象 |
刪除 | docker rmi image-id | 刪除指定的本地映象 |
2)、容器操作
軟體映象(QQ安裝程式)----執行映象----產生一個容器(正在執行的軟體,執行的QQ);
步驟:
1、搜尋映象
[root@localhost ~]# docker search tomcat
2、拉取映象
[root@localhost ~]# docker pull tomcat
3、根據映象啟動容器
docker run --name mytomcat -d tomcat:latest
4、docker ps 檢視執行中的容器
5、 停止執行中的容器
docker stop 容器的id
6、檢視所有的容器
docker ps -a
7、啟動容器
docker start 容器id
8、刪除一個容器
docker rm 容器id
9、啟動一個做了埠對映的tomcat
[root@localhost ~]# docker run -d -p 8888:8080 tomcat
-d:後臺執行
-p: 將主機的埠對映到容器的一個埠 主機埠:容器內部的埠
10、為了演示簡單關閉了linux的防火牆
service firewalld status ;檢視防火牆狀態
service firewalld stop:關閉防火牆
11、檢視容器的日誌
docker logs container-name/container-id
更多命令參看
https://docs.docker.com/engine/reference/commandline/docker/
可以參考每一個映象的文件
3)、安裝MySQL示例
docker pull mysql
錯誤的啟動
[root@localhost ~]# docker run --name mysql01 -d mysql
42f09819908bb72dd99ae19e792e0a5d03c48638421fa64cce5f8ba0f40f5846
mysql退出了
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
42f09819908b mysql "docker-entrypoint.sh" 34 seconds ago Exited (1) 33 seconds ago mysql01
538bde63e500 tomcat "catalina.sh run" About an hour ago Exited (143) About an hour ago compassionate_
goldstine
c4f1ac60b3fc tomcat "catalina.sh run" About an hour ago Exited (143) About an hour ago lonely_fermi
81ec743a5271 tomcat "catalina.sh run" About an hour ago Exited (143) About an hour ago sick_ramanujan
//錯誤日誌
[root@localhost ~]# docker logs 42f09819908b
error: database is uninitialized and password option is not specified
You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD;這個三個引數必須指定一個
正確的啟動
[root@localhost ~]# docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
b874c56bec49fb43024b3805ab51e9097da779f2f572c22c695305dedd684c5f
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b874c56bec49 mysql "docker-entrypoint.sh" 4 seconds ago Up 3 seconds 3306/tcp mysql01
做了埠對映
[root@localhost ~]# docker run -p 3306:3306 --name mysql02 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
ad10e4bc5c6a0f61cbad43898de71d366117d120e39db651844c0e73863b9434
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad10e4bc5c6a mysql "docker-entrypoint.sh" 4 seconds ago Up 2 seconds 0.0.0.0:3306->3306/tcp mysql02
幾個其他的高階操作
docker run --name mysql03 -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)
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
指定mysql的一些配置引數
六、SpringBoot與資料訪問
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.15.22:3306/jdbc
driver-class-name: com.mysql.jdbc.Driver
效果:
預設是用org.apache.tomcat.jdbc.pool.DataSource作為資料來源;
資料來源的相關配置都在DataSourceProperties裡面;
自動配置原理:
org.springframework.boot.autoconfigure.jdbc:
1、參考DataSourceConfiguration,根據配置建立資料來源,預設使用Tomcat連線池;可以使用spring.datasource.type指定自定義的資料來源型別;
2、SpringBoot預設可以支援;
org.apache.tomcat.jdbc.pool.DataSource、HikariDataSource(SpringBoot推薦)、BasicDataSource、Druid
3、自定義資料來源型別
/**
* Generic DataSource configuration.
*/
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {
@Bean
public DataSource dataSource(DataSourceProperties properties) {
//使用DataSourceBuilder建立資料來源,利用反射建立響應type的資料來源,並且繫結相關屬性
return properties.initializeDataSourceBuilder().build();
}
}
4、DataSourceInitializer:ApplicationListener;
作用:
1)、runSchemaScripts();執行建表語句;
2)、runDataScripts();執行插入資料的sql語句;
預設只需要將檔案命名為:
# schema-*.sql、data-*.sql
# 預設規則:schema.sql,schema-all.sql;
# 可以使用一下配置指定sql指令碼檔案位置
spring:
datasource:
schema:
- classpath:sql/xxx.sql
5、操作資料庫:自動配置了JdbcTemplate操作資料庫
2、整合Druid資料來源
//匯入druid資料來源
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的監控
//1、配置一個管理後臺的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
// url為: localhost:8080/druid 即可登入到druid後臺介面
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.15.21");
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("/*")); // 監控除了exclusions 的所有頁面
return bean;
}
}
3、整合MyBatis
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
步驟:
1)、配置資料來源相關屬性(見上一節Druid)
2)、給資料庫建表
3)、建立JavaBean
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") // useGeneratedKeys自動生成id,keyProperty指定主鍵
@Insert("insert into department(departmentName) values(#{departmentName})")
public int insertDept(Department department);
@Update("update department set departmentName=#{departmentName} where id=#{id}")
public int updateDept(Department department);
}
問題:
自定義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); // 自定義定製其,開啟駝峰命名規則
}
};
}
}
- @MapperScan()
// 使用MapperScan批量掃描所有的Mapper介面;
@MapperScan(value = "com.atguigu.springboot.mapper") // 掃描所有Mapper層檔案,相當於該包下的所有Mapper檔案加上@Mapper註解
@SpringBootApplication
public class SpringBoot06DataMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot06DataMybatisApplication.class, args);
}
}
5)、配置檔案版
mybatis:
config-location: classpath:mybatis/mybatis-config.xml # 指定mybatis全域性配置檔案的位置
mapper-locations: classpath:mybatis/mapper/*.xml # 指定sql對映檔案的位置
- mybatis全域性配置檔案mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
- sql對映檔案(常用)(如EmployeeMapper.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.springboot.mapper.EmployeeMapper">
<!-- public Employee getEmpById(Integer id);
public void insertEmp(Employee employee);
-->
<select id="getEmpById" resultType="com.atguigu.springboot.bean.Employee">
SELECT * FROM employee WHERE id=#{id}
</select>
<insert id="insertEmp">
INSERT INTO employee(lastName,email,gender,d_id) VALUES (#{lastName},#{email},#{gender},#{dId})
</insert>
</mapper>
4、整合SpringData JPA
1)、SpringData簡介
2)、整合SpringData JPA
JPA:ORM(Object Relational Mapping);即 JPA是基於ORM物件關係對映的
1)、編寫一個實體類(bean)和資料表進行對映,並且配置好對映關係;
//使用JPA註解配置對映關係
@Entity //告訴JPA這是一個實體類(和資料庫中的表對映的類)
@Table(name = "tbl_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來完成對資料庫的操作,引數分別為對映的Entity實體類名和主鍵型別
public interface UserRepository extends JpaRepository<User,Integer> {
}
3)、基本的配置 (參照:JpaProperties)
spring:
jpa:
hibernate:
# 更新或者建立資料表結構(不存在所需要的表則會自動在資料庫中建立)
ddl-auto: update
# 控制檯顯示SQL
show-sql: true
七、啟動配置原理
幾個重要的事件回撥機制
配置在META-INF/spring.factories
ApplicationContextInitializer
SpringApplicationRunListener
只需要放在ioc容器中
ApplicationRunner
CommandLineRunner
啟動流程:
1、建立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(在autoconfigure原始碼裡);然後儲存起來
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//從類路徑下找到META-INF/spring.factories配置的所有ApplicationListener(在autoconfigure/原始碼裡)
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//從多個配置類中找到有main方法的主配置類
this.mainApplicationClass = deduceMainApplicationClass();
}
2、執行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);
//準備環境
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//建立環境完成後回撥SpringApplicationRunListener.environmentPrepared();表示環境準備完成
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();
//s重新整理容器;ioc容器初始化(如果是web應用還會建立嵌入式的Tomcat);Spring註解版
//掃描,建立,載入所有元件的地方;(配置類,元件,自動配置)
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);
}
}
3、事件監聽機制
配置在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));
}
}
八、自定義starter
starter:
1、這個場景需要使用到的依賴是什麼?
2、如何編寫自動配置
@Configuration //指定這個類是一個配置類
@ConditionalOnXXX //在指定條件成立的情況下自動配置類生效
@AutoConfigureAfter //指定自動配置類的順序
@Bean //給容器中新增元件
@ConfigurationPropertie結合相關xxxProperties類來繫結相關的配置
@EnableConfigurationProperties //讓xxxProperties生效加入到容器中
自動配置類要能載入
將需要啟動就載入的自動配置類,配置在META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
3、模式:
啟動器只用來做依賴匯入;
專門來寫一個自動配置模組;
啟動器依賴自動配置;別人只需要引入啟動器(starter)
mybatis-spring-boot-starter;自定義啟動器名-spring-boot-starter
步驟:
1)、啟動器模組
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu.starter</groupId>
<artifactId>atguigu-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<!--啟動器-->
<dependencies>
<!--引入自動配置模組-->
<dependency>
<groupId>com.atguigu.starter</groupId>
<artifactId>atguigu-spring-boot-starter-autoconfigurer</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
2)、自動配置模組
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu.starter</groupId>
<artifactId>atguigu-spring-boot-starter-autoconfigurer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>atguigu-spring-boot-starter-autoconfigurer</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--引入spring-boot-starter;所有starter的基本配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
package com.atguigu.starter;
import org.springframework.boot.context.properties.ConfigurationProperties;
@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;
}
}
package com.atguigu.starter;
// 自定義元件,用到的屬性與配置類繫結
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();
}
}
package com.atguigu.starter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@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;
}
}