來處:是spring項目中的一個子項目css
優勢 (被稱爲搭建項目的腳手架)html
減小一切xml配置,作到開箱即用,快速上手,專一於業務而非配置前端
從建立項目上: -- 快速建立獨立運行的spring項目以及與主流框架集成(雲計算)java
從運行項目上:--使用嵌入式的Servlet 容器,應用無需打成war包 直接打成jar包使用java -jar就能夠啓動mysql
從項目jar包上 :-- starters 自動依賴與版本控制,大量的自動配置。jquery
微服務:linux
一個應用就是一組小型的服務,能夠經過http的方式進行互通git
每個功能元素最終都是一個可獨立替換和獨立升級的軟件單元web
查看maven版本 mvn -vredis
搭建一個springboot應用(由淺到深的瞭解便於記憶)
1. 1.1同以往搭建項目同樣首先重視的就是環境配置
jar包會被場景啓動器所替換首先會引入場景啓動器
<!--全部的springboot應用都須要以該工程爲父工程包含了啓動springboot所需的所有jar包--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> </parent>
從官網上拷貝下來的依賴須要什麼場景啓動器就引入什麼場景啓動器就行
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <scope>test</scope> </dependency>
也能夠加入日誌文件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency>
</dependencies> <properties> <java.version>1.8</java.version> </properties>
spring的幾個項目結構介紹
libraries 庫(maven自定下載的jar包)
compiler.xml 編譯器(主要用於maven初始化的編譯)
modules.xml(模塊的xml)
.mvn :主要用於版本切換 由於maven的版本和插件配合並非那麼完美,.mvn爲解決這個問題有一個第三方的插件wrapper可使用
properties文件中記錄你要使用的maven版本當用戶執行mvn的clear命令時發現當前用戶使用的maven版本和用戶指望的版本不同那麼就下載指望的maven版本。
.gitignore 的做用 忽略不須要上傳的文件
demo.iml idea工程的配置文件是當前project的一些配置信息
開啓第一個springboot項目
MVC 中 建立的第一個Controller類
註解
@RestController /*ResponseBody+Controller 返回json類型的數據*/ http://www.javashuo.com/article/p-finclvbr-bh.html RESTFUL風格基礎概念
@RequestMapping("hello") 請求映射 能夠配置全局的也能夠配置局部的
@EnableAutoConfiguration /*啓用自動配置若是不聲明那麼他就認爲你不須要自動配置*/
實際上springboot的自動配置是根據你引入了什麼依賴,若是你引入了他就會給你自動配置這些須要的config 或則javabean 或者class
後來我將springboot啓動類換到了另一個方法中
出現了一個異常 http://www.javashuo.com/article/p-fwzwursd-t.html 解決辦法
由於我換了類可是忘記了換類名因此才報錯
** WARNING ** : Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package.
這個是由於 ComponentScan註解的默認掃描範圍是啓動程序XxxApplication. java所在目錄及其下的全部子包。
因此你不能夠直接放在java目錄下須要建一個父包 而後進行掃描,這時就能夠了
對比之前的寫法
Properties properties = new Properties(); properties.load(JDBCUtil.class.getResourceAsStream("/jdbc.properties"));
底層使用流來進行讀取
springboot 如今的寫法
1.在resources下建立jdbc.properties
@Configuration //聲明一個類是java配置類至關於一個xml配置文件
@PropertySource("classpath:jdbc.properties") //指定外部屬性文件 讀取咱們的資源文件
public class jdbcConfiguration {
//聲明jdbc的配置文件
//使用屬性注入的方式
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean //相似一個bean標籤將方法的返回值加入bean容器
public DataSource dateSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(this.driverClassName);
dataSource.setUrl(this.url);
dataSource.setUsername(this.username);
dataSource.setPassword(this.password); 這裏用上this主要是爲了區分紅員變量和局部變量
return null;
}
}
升級寫法
設置set/get方法
springboot 給咱們提供了四種注入方式 第一種是set/get方式也就是上面那種方式
第二種是經過 構造方法
第三種:經過bean方法的形參也能夠自動注入
第四種:是一種更加簡單的方法
@ConfigurationProperties(prefix = "jdbc") 不只能夠用在類上也能夠用在方法上。
底層使用Datasource 的構造方法 get/set方法
4.yml文件中的值不能以*開頭,能夠用 "*" 加個引號開頭。
/*來標註主程序類,來講明這是一個spring boot應用 * */ @SpringBootApplication public class SpringBoot01ConfigApplication { public static void main(String[] args) { /*springboot應用啓動起來*/ SpringApplication.run(SpringBoot01ConfigApplication.class, args); }
package cn.edu.aynu.springboot01config; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { @RequestMapping("/some") public String doFirst(){ return "Helloworld"; } }
將一下工程的監控器,監控工程的運行狀態
Actuator是Spring Boot提供的一個可插拔模塊,用於對工程進行監控。其經過不一樣的監控終端實現不一樣的監控功能。其功能與Dubbo的監控中心相似,不一樣的是,Dubbo的監控中心是須要專門部署的,而Spring Boot的Actuator是存在於每個工程中的。官網https://docs.spring.io/spring-boot/docs/2.0.5.RELEASE/reference/htmlsingle/#production-ready
導入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
有一點要注意:Actuator 與 elasticsearch 是相互衝突的。若是導入了 Acturtor 就不要再使用 elasticserach 不然報錯
server: port: 8081 tomcat: uri-encoding: UTF-8 management: server: port: 9999 servlet: context-path: /xxx endpoints: web: base-path: /base endpoint: health: show-details: always
{ "status": "DOWN", "details": { "diskSpace": { "status": "UP", "details": { "total": 15453913088, "free": 7720787968, "threshold": 10485760 } }, "redis": { "status": "DOWN", "details": { "error": "org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379" } } } }
management.server.port=9999 management.server.servlet.context-path=/xxx management.endpoints.web.base-path=/actuator #自定義info 信息 info.company.name=abc info.auth.name=lisi
{ "company": { "name": "abc" }, "auth": { "name": "lisi" } }
開放全部的監控終端
management.endpoints.web.exposure.include=*
排除某些不想開放的終端
management.endpoints.web.exposure.exclude=env,beans
經常使用的監控終端
在配置文件中取出屬性值
方法一:
使用主配置文件或者自定義的配置文件均可以 @RestController @PropertySource(value = "classpath:student.properties",encoding = "utf-8") /*@PropertySource(value = "application.properties")*/ public class controller { @Value("${student.id}") int id; @Value("${student.name}") String name; @Value("${student.age}") int age; @RequestMapping("/hello") public String handler(){ return id+","+name+","+age; }
student.id = 111111111 student.name = zhu student.age = 12
可是建議通常不要寫在主主配置文件中
方法二
將實體類聲明爲一個組件,並使用ConfigurationProperties註解將配置文件中的屬性賦值上去
package cn.edu.aynu.bean; import com.sun.tracing.dtrace.ArgsAttributes; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "student") public class Student { private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
student: id: 12 name: lisi age: 34
package cn.edu.aynu.controller; import cn.edu.aynu.bean.Student; import cn.edu.aynu.service.ServiceHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.web.bind.annotation.*; @RestController public class controller { @Autowired Student student; @RequestMapping("/hello") public String handler(){ System.out.println(student); return "/hello"; } }
controller 中須要注意一點,當咱們使用自動注入bean的時候,是能夠獲得值的,可是若是咱們在從新定義一個劇不能獲得值了,應爲那就至關因而重寫了這個方法。
須要注意一點,有時候咱們不只僅須要的屬性只是int 或者是String 咱們可能須要的是map 或者list
若是配置文件沒有了提示就導入這個jar包
<!‐‐導入配置文件處理器,配置文件進行綁定就會有提示‐‐>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐configuration‐processor</artifactId>
<optional>true</optional>
</dependency>
能夠將程序打包成jar包
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
怎麼打成jar包
能夠直接在命令行上進行啓動執行
執行成功 這個路徑是Controller裏面的requestMapping
探究原理
自動導入的jar包
父項目
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
因此又叫他Springboot的仲裁中心
導入的依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
主程序類
package cn.edu.aynu.springboot01config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /*來標註主程序類,來講明這是一個spring boot應用 * */ @SpringBootApplication public class SpringBoot01ConfigApplication { public static void main(String[] args) { /*springboot應用啓動起來*/ SpringApplication.run(SpringBoot01ConfigApplication.class, args); } }
/*這個類的全部方法返回的數據寫給瀏覽器,若是是對象轉爲json格式*/ /*@ResponseBody @Controller*/ @RestController /*@RestController 直接表明了@RequestBody 和@Controller*/ public class MyController { @RequestMapping("/some") public String doFirst(){ return "Helloworld"; } }
application.properties的配置文件
server.port=9090 # 服務端口號 server.tomcat.uri-encoding=UTF-8 #以Tomcat爲web容器時的字符編碼 spring.application.name=customer # 應用名稱,通常就是項目名稱,這個名稱在SpringCloud中比較關鍵 spring.profiles.active=dev #指定當前的活動配置文件,主要用於多環境多配置文件的應用中 spring.http.encoding.charset=UTF-8 #http請求的字符編碼 spring.http.multipart.max-file-size=10MB #設置文件上傳時單個文件的大小限制 spring.http.multipart.max-request-size=100MB #設置文件上傳時總文件大小限制 spring.thymeleaf.prefix=classpath:/templates/ #配置在使用Thymeleaf作頁面模板時的前綴,即頁面所在路徑 spring.thymeleaf.suffix=.html #設置在使用Thymeleaf作頁面模板時的後綴 spring.thymeleaf.cache=false #設置在使用Thymeleaf作頁面模板時是否啓用緩存 spring.mvc.static-path-pattern=/** #設置靜態資源的請求路徑 spring.resources.static-locations=classpath:/static/,classpath:/public/ #指定靜態資源的路徑 ##如下是使用MySQL數據庫的配置 hibernate.dialect=org.hibernate.dialect.MySQL5Dialect #指定數據庫方言 hibernate.show_sql=true #是否顯示sql語句 hibernate.hbm2dll.auto=update #設置使用Hibernate的自動建表方式 entitymanager.packagesToScan=com.zslin #設置自動掃描的包前綴 spring.datasource.url=jdbc:mysql://localhost:3306/customer?\ useUnicode=true&characterEncoding=utf-8&useSSL=true&autoReconnect=true #數據庫連接 spring.datasource.username=root #數據庫用戶名 spring.datasource.password=123 #數據庫用戶對應的密碼 spring.datasource.driver-class-name=com.mysql.jdbc.Driver #數據庫驅動名稱
@ConfigurationProperties主要做用:就是綁定application.properties中的屬性
使用方法
@ConfigurationProperties(prefix = "spring.datasource")
application.properties 文件 spring.datasource.password=root spring.datasource.username=root spring.datasource.url=jdbc:mysql:///jdbc spring.datasource.driver-class-name=com.alibaba.druid.proxy.DruidDriver
springboot的包掃描問題
根據英文的提示是在配置中找不到一個指定自動注入類型的bean,SpringBoot項目的Bean裝配默認規則是根據Application類所在的包位置從上往下掃描!Application類是指SpringBoot項目入口類。
這個類的位置很關鍵:若是mapper、service所在包不在其子包下,則不會被掃描。
即, 把Application類放到mapper、service所在包的上級,
兩種解決辦法:
1 .將接口與對應的實現類放在與application啓動類的同一個目錄或者他的子目錄下,這樣註解能夠被掃描到,這是最省事的辦法
2 .在指定的application類上加上這麼一行註解,手動指定application類要掃描哪些包下的註解(圖3)
圖3
@ComponentScan(basePackages = "cn.edu.aynu.*")
server: port: 8087
xml
<server> port:8087 </server>
<!--導入配置文件處理器,配置文件進行綁定就會有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
作一個小練習
定義兩個類 在yaml文件中給屬性賦值
people: lastName: zs age: 12 boss: ls birth: 2017/12/14 maps: {k1: v1,k2: v2} lists: - lisi - zhou dog: name: 小狗 age: 23
如今如何將兩個屬性與java bean類進行綁定
/*將配置文件中的每個值映射到這個組件中 * @ConfigurationProperties 告訴springboot這個類中的屬性和配置文件的屬性進行綁定 * 加上前綴是由於配置文件中能夠寫入不少的屬性值要找到相對應的那一個。進行一一映射 * 只有這個組件是容器中的組件才能使用容器中提供的功能,因此要將這個類聲明爲組件 * */ @Component @ConfigurationProperties(prefix = "people") public class People { private String lastName; private Integer age; private Boolean boss; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog;
public class Dog { private String name; private Integer age;
@RunWith(SpringRunner.class) @SpringBootTest public class SpringBoot01ConfigApplicationTests { @Autowired People people; @Test public void contextLoads() { System.out.println(people); }
執行成功
在properties配置文件中進行配置
people.last-name=zs people.age=23 people.birth=2013/12/12 people.boss=false people.maps.k1=v1 people.maps.k2=v2 people.lists=a,b,c people.dog.name=li people.dog.age=34
若是在peoperties文件中產生了亂碼就在idea中改變一下,file-setting-輸入file Enconding 調一下
@Component //@ConfigurationProperties(prefix = "people") public class People { /*在spring中進行給變量賦值 * <bean> * <property name="" values="字面量/#{}從EL表達式中獲取/${}從配置文件,環境變量中獲取"></property> * </bean>那麼註解也支持這幾種方式 * 採用註解的方式 */ @Value("${people.last-name}") private String lastName; @Value("#{11*2}") private Integer age; private Boolean boss; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog;
@ConfigurationProperties(prefix = "people")表明從全局配置文件中獲取值,本身也能夠定義配置文件
@PropertySource(value = {"classpath:people.properties"}) @Component @ConfigurationProperties(prefix = "people") public class People { /*在spring中進行給變量賦值 * <bean> * <property name="" values="字面量/#{}從EL表達式中獲取/${}從配置文件,環境變量中獲取"></property> * </bean>那麼註解也支持這幾種方式 * 採用註解的方式 */ @Value("${people.last-name}") private String lastName; @Value("#{11*2}") private Integer age; private Boolean boss; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog;
這裏面須要補充一點,也是須要注意的地方
@PropertySources 和 ConfigurationProprtties 這兩個註解式相輔相成的
若是隻是加上 @COnfigurationSources這個註解那麼,與bean綁定的屬性值默認是從主配置文件中加載,
可是若是加上 PropertySources這個註解,則能夠從本身自定義的 XXX.properties 中加載。
@PropertySource(value = {"classpath:person.properties"}) //加載指定的配置文件;
@ImportResource //導入Spring的配置文件,讓配置文件裏面的內容生效;Spring Boot裏面沒有Spring的配置文件,咱們本身編寫的配置文件,也不能自動識別;想讓Spring的配置文件生效,加載進來;@ImportResource標註在一個配置類上
用法:
@ImportResource(locations = {"classpath:beans.xml"})
導入Spring的配置文件讓其生效這個配置文件主要是讓配置文件進行生效。
<?xml version="1.0" encoding="UTF‐8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema‐instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring‐beans.xsd"> <bean id="helloService" class="com.atguigu.springboot.service.HelloService"></bean> </beans>
@Bean
SpringBoot推薦給容器中添加組件的方式;推薦使用全註解的方式一、配置類@Configuration------>Spring配置文件二、使用@Bean給容器中添加
舉個例子
* 在配置文件中用<bean><bean/>標籤添加組件 * */ @Configuration public class MyAppConfig { //將方法的返回值添加到容器中;容器中這個組件默認的id就是方法名 @Bean public HelloService helloService02(){ System.out.println("配置類@Bean給容器中添加組件了..."); return new HelloService(); } }
@ConfigurationProperties:告訴SpringBoot將本類中的全部屬性和配置文件中相關的配置進行綁定;prefix = "person":配置文件中哪一個下面的全部屬性進行一一映射只有這個組件是容器中的組件,才能容器提供的@ConfigurationProperties功能;@ConfigurationProperties(prefix = "person")默認從全局配置文件中獲取值;
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="hello" class="cn.edu.aynu.springboot01config.helloService"></bean> </beans>
@Test public void testService(){ boolean helloService = ioc.containsBean("hello"); System.out.println(helloService); }
@ImportResource(locations = {"classpath:beans.xml"}) @SpringBootApplication public class SpringBoot01ConfigApplication { public static void main(String[] args) { /*springboot應用啓動起來*/ SpringApplication.run(SpringBoot01ConfigApplication.class, args); } }
/*@Configuration 指明當前類就是一個配置類,用來代替以前的spring配置文件 * 在標籤中使用<bean></bean>添加組件 * * */ @Configuration public class RegisterConfig { /*將方法的返回值添加到容器中;容器中這個組件默認的id就是方法名*/ @Bean public helloService helloService02(){ return new helloService(); } }
package cn.edu.aynu.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Description: review-project * Created by lenovo on 2019/4/26 16:33 */ @Configuration //告訴springboot 這是一個配置類 public class MyConfig { @Bean //將方法的返回值添加到容器中,容器中這個組件默認的id就是方法名 public HelloService configApp(){ System.out.println("@bean給容器中添加了組件,根據方法名這到這個類"); return new HelloService(); } }
2019-04-26 16:38:36.327 INFO 11556 --- [ main] cn.edu.aynu.ReviewApplication : Starting ReviewApplication on LAPTOP-4U4DHM78 with PID 11556 (E:\sturts2\review-project\target\classes started by lenovo in E:\sturts2\review-project) 2019-04-26 16:38:36.336 INFO 11556 --- [ main] cn.edu.aynu.ReviewApplication : No active profile set, falling back to default profiles: default 2019-04-26 16:38:38.298 INFO 11556 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode! 2019-04-26 16:38:38.302 INFO 11556 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode. 2019-04-26 16:38:38.414 INFO 11556 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 88ms. Found 0 repository interfaces. 2019-04-26 16:38:39.418 INFO 11556 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http) 2019-04-26 16:38:39.449 INFO 11556 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2019-04-26 16:38:39.449 INFO 11556 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.17] 2019-04-26 16:38:39.653 INFO 11556 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2019-04-26 16:38:39.653 INFO 11556 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3207 ms @bean給容器中添加了組件,根據方法名這到這個類
經過這個控制檯打印的信息能夠看出 Root WebApplicationContext: initialization completed in 3207 ms
當WebApplicationContext 初始化完成後,就打印了自定義信息
看一下控制檯的輸出就能夠知道程序執行的前後順序,挑幾個我認識的
1.先檢查一個有沒有多環境選擇的profile
No active profile set, falling back to default profiles: default
2.是對 Spring Data repository 的掃描
Finished Spring Data repository scanning in 88ms. Found 0 repository interfaces.
Tomcat initialized with port(s): 8081 (http)
Starting service [Tomcat]
Starting Servlet engine: [Apache Tomcat/9.0.17]
Initializing Spring embedded WebApplicationContext
Root WebApplicationContext: initialization completed in 3207 ms
.................
在配置文件中的代碼,通常都是按照配置文件的前後循序執行。
解釋一下spring Data (https://www.cnblogs.com/airycode/p/6535323.html能夠參考這個博主)
Repository 接口是 Spring Data 的一個核心接口,它不提供任何方法,開發者須要在本身定義的接口中聲明須要的方法 public interface Repository<T, ID extends Serializable> { } Spring Data可讓咱們只定義接口,只要遵循 Spring Data的規範,就無需寫實現類。 與繼承 Repository 等價的一種方式,就是在持久層接口上使用 @RepositoryDefinition 註解,併爲其指定 domainClass 和 idClass 屬性。以下兩種方式是徹底等價的 Repository 的子接口 基礎的 Repository 提供了最基本的數據訪問功能,其幾個子接口則擴展了一些功能。它們的繼承關係以下: 1.Repository: 僅僅是一個標識,代表任何繼承它的均爲倉庫接口類 2.CrudRepository: 繼承 Repository,實現了一組 CRUD 相關的方法 3.PagingAndSortingRepository: 繼承 CrudRepository,實現了一組分頁排序相關的方法 4.JpaRepository: 繼承 PagingAndSortingRepository,實現一組 JPA 規範相關的方法 5.自定義的 XxxxRepository 須要繼承 JpaRepository,這樣的 XxxxRepository 接口就具有了通用的數據訪問控制層的能力。 6.JpaSpecificationExecutor: 不屬於Repository體系,實現一組 JPA Criteria 查詢相關的方法 https://www.cnblogs.com/airycode/p/6535323.html
---表明一個文檔
配置文件的加載順序:
springboot啓動會掃描如下位置的application.properties或者application.yml做爲springboot的默認配置文件
-file:./config
-file:./
-classpath:/config/
-classpath:/
優先級從高到低,高優先級的配置會覆蓋低優先級的配置。
最重要的是,springboot會從這四個位置所有加載配置文件,想成互補配置
咱們還能夠經過改變
spring.config.location 來改變默認配置文件的位置,可是這個方式有一個前提就是須要在項目打包好之後,啓動項目的時候指定配置文件的新位置,
全部的配置文件都會造成互補配置
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
剛纔講的都是內部文件的加載順序,如今講一下外部文件的加載順序
1.命令行參數,全部你命令均可以在命令行中進行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
特色:能夠同時加載多個配置項,可是多個配置項之間須要使用空格隔開
2由jar包外向jar包內進行尋找
優先加載帶profile的
jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
jar包內部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
再來加載不帶profile的
jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
jar包內部的application.properties或application.yml(不帶spring.profile)配置文件
配置文件上進行指定
@Configuration註解類上的@PropertySource
經過SpringApplication.setDefaultProperties指定的默認屬性
8.自動配置原理
springboot啓動的時候加載了主啓動類開啓了自動配置功能
@EnableAutoConfiguration的做用是:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {
@EnableAutoConfiguration 裏面封裝了
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {
利用EnableAutoConfigurationImportSelector,先判斷是屬於什麼註解,而後再進行下一步操做
類的全名就做爲組件的id.
List configurations = getCandidateConfigurations(annotationMetadata, attributes);獲取候選的配置,也就是將候選的組件組件獲取內容保存起來。
接着,有一個類SpringFactoriesLoader.loadFactoryNames()
掃描全部jar包類路徑下 META‐INF/spring.factories把掃描到的這些文件的內容包裝成properties對象從properties中獲取到EnableAutoConfiguration.class類(類名)對應的值,而後把他們添加在容器中
將 類路徑下 META-INF/spring.factories 裏面配置的全部EnableAutoConfiguration的值加入到了容器中;
這時,自定義配置纔算真正的加載到容器中
一但這個配置類生效;這個配置類就會給容器中添加各類組件;這些組件的屬性是從對應的properties類中獲取
的,這些類裏面的每個屬性又是和配置文件綁定的;
全部在配置文件中能配置的屬性都是在xxxxProperties類中封裝者‘;配置文件能配置什麼就能夠參照某個功
能對應的這個屬性類精髓:
1)、SpringBoot啓動會加載大量的自動配置類
2)、咱們看咱們須要的功能有沒有SpringBoot默認寫好的自動配置類;
3)、咱們再來看這個自動配置類中到底配置了哪些組件;(只要咱們要用的組件有,咱們就不須要再來配置了)
4)、給容器中自動配置類添加組件的時候,會從properties類中獲取某些屬性。咱們就能夠在配置文件中指定這
些屬性的值;
xxxxAutoConfigurartion:自動配置類;
給容器中添加組件
xxxxProperties:封裝配置文件中相關屬性
細節
一、@Conditional派生註解(Spring註解版原生的@Conditional做用)
做用:必須是@Conditional指定的條件成立,纔給容器中添加組件,配置配裏面的全部內容才生效;
自動配置類在必定條件下才能生效 咱們怎麼知道哪些配置類生效
咱們能夠經過啓用 debug=true屬性;來讓控制檯打印自動配置報告,這樣咱們就能夠很方便的知道哪些自動配置
類生效;
docker pull mysql
SpringBoot與數據訪問
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裏面;
public interface DataSource extends CommonDataSource, Wrapper { Connection getConnection() throws SQLException; Connection getConnection(String username, String password) throws SQLException;
abstract class DataSourceConfiguration { @SuppressWarnings("unchecked") protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) { return (T) properties.initializeDataSourceBuilder().type(type).build(); } /** * Tomcat Pool DataSource configuration. */ @Configuration @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true) static class Tomcat { @Bean @ConfigurationProperties(prefix = "spring.datasource.tomcat") public org.apache.tomcat.jdbc.pool.DataSource dataSource( DataSourceProperties properties) { org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource( properties, org.apache.tomcat.jdbc.pool.DataSource.class); DatabaseDriver databaseDriver = DatabaseDriver .fromJdbcUrl(properties.determineUrl()); String validationQuery = databaseDriver.getValidationQuery(); if (validationQuery != null) { dataSource.setTestOnBorrow(true); dataSource.setValidationQuery(validationQuery); } return dataSource; } } /** * Hikari DataSource configuration. */ @Configuration @ConditionalOnClass(HikariDataSource.class) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true) static class Hikari { @Bean @ConfigurationProperties(prefix = "spring.datasource.hikari") public HikariDataSource dataSource(DataSourceProperties properties) { HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class); if (StringUtils.hasText(properties.getName())) { dataSource.setPoolName(properties.getName()); } return dataSource; } } /** * DBCP DataSource configuration. */ @Configuration @ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp2.BasicDataSource", matchIfMissing = true) static class Dbcp2 { @Bean @ConfigurationProperties(prefix = "spring.datasource.dbcp2") public org.apache.commons.dbcp2.BasicDataSource dataSource( DataSourceProperties properties) { return createDataSource(properties, org.apache.commons.dbcp2.BasicDataSource.class); } } /** * Generic DataSource configuration. */ @Configuration @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type") static class Generic { @Bean public DataSource dataSource(DataSourceProperties properties) { return properties.initializeDataSourceBuilder().build(); } }
自動配置原理:
org.springframework.boot.autoconfigure.jdbc:
一、參考DataSourceConfiguration,根據配置建立數據源,默認使用Tomcat鏈接池;可使用
spring.datasource.type指定自定義的數據源類型;
二、SpringBoot默承認以支持;
org.apache.tomcat.jdbc.pool.DataSource、HikariDataSource、BasicDataSource、
自定義數據源類型
/** * 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(); } }
DataSourceInitializer:ApplicationListener;
做用:
1)、runSchemaScripts();運行建表語句;
2)、runDataScripts();運行插入數據的sql語句;
默認只須要將文件命名爲:
schema‐*.sql、data‐*.sql
默認規則:schema.sql,schema‐all.sql;
可使用
schema:
‐ classpath:department.sql
指定位置
五、操做數據庫:自動配置了JdbcTemplate操做數據庫
spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource schema: - classpath:sql/department.sql - classpath:sql/employee.sql
根據上面的配置,能夠知道掃描 resources下面的.sql文件,而後加載這個sql文件,在數據庫中進行建立
如何整合Druid數據源
首先確定是一個配置文件,當配置好了druid數據源以後,根據.sql文件也會在數據中建立表,
導入druid數據源 @Configuration public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource druid(){
return new DruidDataSource(); } //配置Druid的監控 //一、配置一個管理後臺的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.15.21"); bean.setInitParameters(initParams); return bean; } //二、配置一個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; } }
整合Mybaties
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis‐spring‐boot‐starter</artifactId> <version>1.3.1</version> </dependency>
註解版
//指定這是一個操做數據庫的mapper @Mapperpublic 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) 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批量掃描全部的Mapper接口; @MapperScan(value = "com.atguigu.springboot.mapper") @SpringBootApplication public class SpringBoot06DataMybatisApplication { public static void main(String[] args) { SpringApplication.run(SpringBoot06DataMybatisApplication.class, args); } }
下面一個就是配置文件版
像spring 寫sql文件同樣聲明配置文件,還有映射文件、
<?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="cn.edu.aynu.springboot.zhaoyujing.mapper.EmployeeMapper"> <!-- public Employee getEmpById(Integer id); public void insertEmp(Employee employee);--> <select id="getEmpById" resultType="cn.edu.aynu.springboot.zhaoyujing.entities.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> <select id="getAll" resultType="cn.edu.aynu.springboot.zhaoyujing.entities.Employee"> SELECT * FROM employee </select> <delete id="delete"> delete from employee WHERE id=#{id} </delete> </mapper>
<?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>
整合srpingData JPA
1.寫一個實體類
//使用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)
也就是你能夠自定義sql語句而後直接就能夠被使用了,可是定義的方法名要符合一些規則
具體信息在下面這個網址中(https://www.cnblogs.com/zhulina-917/p/10504377.html)
//繼承JpaRepository來完成對數據庫的操做 public interface UserRepository extends JpaRepository<User,Integer> { }
基本的配置JpaProperties
spring: jpa: hibernate: # 更新或者建立數據表結構 ddl‐auto: update # 控制檯顯示SQL show‐sql: true
講解springboot的啓動配置原理
幾個重要的事件回調機制
配置在META-INF/spring.factories
ApplicationContextInitializer
SpringApplicationRunListener
只須要放在ioc容器中
ApplicationRunner
CommandLineRunner
啓動流程
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)); //從類路徑下找到ETA‐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);
//準備環境
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);
}
}
事件的監聽機制
配置在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