你們好,我是小菜,一個渴望在互聯網行業作到蔡不菜的小菜。可柔可剛,點贊則柔,白嫖則剛!
死鬼~看完記得給我來個三連哦!html
「本文主要介紹
SprinBoot
若有須要,能夠參考
若有幫助,不忘 點贊 ❥java
「
官方
:Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".
We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.官翻
:經過Spring Boot,能夠輕鬆地建立獨立的,基於生產級別的基於Spring的應用程序,您能夠「運行」它們。
咱們對Spring平臺和第三方庫持執拗己見的觀點,所以您能夠以最小的麻煩開始使用。大多數Spring Boot應用程序須要最少的Spring配置。jquery
獨立運行
的Spring項目以及與主流框架集成嵌入式
的Servlet容器,應用無需打成WAR
包starters
自動依賴與版本控制自動配置
,簡化開發,也可修改默認值無需配置XML
,無代碼生成,開箱即用應用監控
SpringBoot使用一個全局的配置文件,配置文件名是固定的
web
application.propertiesspring
application.ymljson
YAML(YAML Ain't Markup Language) 標記語言,以數據爲中心,比 json 、xml 等更適合作配置文件數組
//YAML 配置文件
server:
port: 8081
//XML 配置文件
<server>
<port>8081</port>
</server>
複製代碼
k:(空格)v
: 表示一對鍵值對(空格必須有)
以空格的縮進來控制層級關係;只要是左對齊的一列數據,都是同一個層級的瀏覽器
server:
port: 8081
path: /hello
複製代碼
注:屬性和值是大小寫敏感,字面量:普通的值(數字,字符串,布爾),字符串默認不用加上單引號或者雙引號緩存
" "
:雙引號;不會轉義字符串裏面的特殊字符;特殊字符會做爲自己想表示的意思
輸入:name: "zhangsan \n lisi"
springboot
輸出:zhangsan 換行 lisi
' '
:單引號;會轉義特殊字符,特殊字符最終只是一個普通的字符串數據
輸入:name: ‘zhangsan \n lisi’
輸出:zhangsan \n lisi
1)對象、Map(屬性和值)(鍵值對)
k: v 寫法
friends:
lastName: zhangsan
age: 20
複製代碼
行內寫法
:
friends: {lastName: zhangsan,age: 18}
複製代碼
2)數組(List、Set)
用
- 值表示數組中的一個元素
:pets:
- cat
- dog
- pig
複製代碼
行內寫法
:pets: [cat,dog,pig]
複製代碼
配置文件:
person:
lastName: Cbuc
age: 22
birth: 11/13
maps: {k1: v1,k2: v2}
lists:
- apple
- pear
dog:
name: 旺財
age: 12
複製代碼
javaBean:
/**
* 將配置文件中配置的每個屬性的值,映射到這個組件中
* @ConfigurationProperties:告訴SpringBoot將本類中的全部屬性和配置文件中相關的配置進行綁定;
* prefix = "person":配置文件中哪一個下面的全部屬性進行一一映射
*
* 只有這個組件是容器中的組件,才能容器提供的@ConfigurationProperties功能;
*
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Date birth;
private Map<String,Object> maps;
private List<Fruit> lists;
private Dog dog;
}
複製代碼
咱們能夠導入配置文件處理器,之後編寫配置就有提示了:
<!--導入配置文件處理器,配置文件進行綁定就會有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
複製代碼
@Value
和 @ConfigurationProperties
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的屬性 | 一個個指定 |
鬆散綁定(鬆散語法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303數據校驗 | 支持 | 不支持 |
複雜類型封裝 | 支持 | 不支持 |
不管是yml
仍是properties
它們都能獲取到值
@Value
javaBean
來和配置文件進行映射,咱們就直接使用@ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
//lastName必須是郵箱格式
@Email
private String lastName;
private Integer age;
private Date birth;
private Map<String,Object> maps;
private List<Fruit> lists;
private Dog dog;
}
複製代碼
@PropertySource:
加載指定的配置文件@PropertySource(value = {"classpath:person.properties"})
@Component
public class Person {
private String lastName;
private Integer age;
複製代碼
@ImportResource:
導入Spring的配置文件,讓配置文件裏面的內容生效SpringBoot裏面沒有Spring的配置文件,咱們本身編寫的配置文件,不能自動識別
想讓Spring的配置文件生效,加載進來須要使用@ImportResource
標註在一個配置類(主配置類)上
//導入Spring的配置文件讓其生效
@ImportResource(locations = {"classpath:beans.xml"})
複製代碼
@Bean:
加載指定的配置文件<bean id="helloService" class="cbuc.life.service.HelloService"></bean>
複製代碼
SpringBoot一般不用xml的方式導入組件,推薦註解的方式
@Configuration
指明爲配置類@Bean
給容器中添加組件/**
* @Configuration:指明當前類是一個配置類;就是來替代以前的Spring配置文件
*
* 在配置文件中用<bean><bean/>標籤添加組件
*
*/
@Configuration
public class MyAppConfig {
//將方法的返回值添加到容器中;容器中這個組件默認的id就是方法名
@Bean
public HelloService helloService02(){
System.out.println("配置類@Bean給容器中添加組件了...");
return new HelloService();
}
}
複製代碼
市面上的框架
JUL(java.util.logging)
JCL(Apache Commons Logging)
Log4j
Log4j2
Logback
SLF4j
jboss-logging
SpringBoot:底層是Spring框架,Spring框架默認是用JCL
在框架內部使用JCL,spring-boot-starter-logging
採用了slf4j+logback
的形式
Spring Boot也能自動適配(jul、log4j二、logback) 並簡化配置
SpringBoot選用SLF4j
和logback
實現:
左邊選一個門面(抽象層)、右邊來選一個實現
日誌門面 (日誌的抽象層) | 日誌實現 |
---|---|
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging |
Log4j JUL(java.util.logging) Log4j2 Logback |
給系統裏面導入slf4j
的 jar 包和 logback
的 jar 包
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
複製代碼
每個日誌的實現框架都有本身的配置文件。使用slf4j之後,配置文件仍是作成日誌實現框架本身自己的配置文件
存在問題:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
複製代碼
SpringBoot的日誌功能
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
複製代碼
底層依賴關係:
SpringBoot能自動適配全部的日誌,並且底層使用slf4j+logback
的方式記錄日誌,引入其餘框架的時候,只須要把這個框架依賴的日誌框架排除掉便可
slf4j + logback
的方式進行日誌記錄slf4j
@SuppressWarnings("rawtypes")
public abstract class LogFactory {
static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";
static LogFactory logFactory = new SLF4JLogFactory();
}
複製代碼
commons-logging
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
複製代碼
默認配置:
SpringBoot默認配置好了的日誌
//日誌記錄器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
//System.out.println();
//日誌的級別;
//由低到高 trace<debug<info<warn<error
//能夠調整輸出的日誌級別;日誌就只會在這個級別以之後的高級別生效
logger.trace("這是trace日誌...");
logger.debug("這是debug日誌...");
//SpringBoot默認給咱們使用的是info級別的,沒有指定級別的就用SpringBoot默認規定的級別;root級別
logger.info("這是info日誌...");
logger.warn("這是warn日誌...");
logger.error("這是error日誌...");
}
複製代碼
SpringBoot修改日誌的默認配置
日誌輸出格式
%d
:表示日期時間
%thread
: 表示線程名
%-5level
:級別從左顯示5個字符寬度
%logger{50}
: 表示logger名字最長50個字符,不然按照句點分割
%msg
:日誌消息
%n
:是換行符
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
#給所在的包下設計日誌級別
logging.level.cbuc.life=trace
# 不指定路徑在當前項目下生成springboot.log日誌
#logging.path=
# 能夠指定完整的路徑;
#logging.file=D:/springboot.log
# 在當前磁盤的根路徑下建立spring文件夾和裏面的log文件夾;使用 spring.log 做爲默認文件
logging.path=/spring/log
# 在控制檯輸出的日誌的格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定文件中日誌輸出的格式
logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n
複製代碼
logging.file | logging.path | Example | Description |
---|---|---|---|
(none) | (none) | 只在控制檯輸出 | |
指定文件名 | (none) | my.log | 輸出日誌到my.log文件 |
(none) | 指定目錄 | /var/log | 輸出到指定目錄的 spring.log 文件中 |
指定配置:
給類路徑下放上每一個日誌框架本身的配置文件便可,SpringBoot就不會使用它默認配置的了
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
logback.xml
: 直接會被日誌框架識別logback-spring.xml
: 日誌框架就不直接加載日誌的配置項,由SpringBoot解析日誌配置,可使用SpringBoot的高級Profile功能
<springProfile name="staging">
<!--能夠指定某段配置只在某個環境下生效-->
<!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>
複製代碼
例子:
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!--
日誌輸出格式:
%d 表示日期時間,
%thread 表示線程名,
%-5level: 級別從左顯示5個字符寬度
%logger{50} 表示logger名字最長50個字符,不然按照句點分割。
%msg: 日誌消息,
%n 是換行符
-->
<layout class="ch.qos.logback.classic.PatternLayout">
<springProfile name="dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
</springProfile>
<springProfile name="!dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
</springProfile>
</layout>
</appender>
複製代碼
若是使用logback.xml做爲日誌配置文件,還要使用profile功能,會有如下錯誤:
no applicable action for [springProfile]
能夠按照slf4j的日誌適配圖,進行相關的切換;
slf4j+log4j
的方式:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<artifactId>log4j-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
複製代碼
切換爲log4j2
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
複製代碼
簡易步驟:
自動配置原理:
xxxAutoConfiguration
: 幫咱們給容器中自動配置組件xxxProperties
:配置類來封裝配置文件的內容@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {
//能夠設置和靜態資源有關的參數,緩存時間等
}
複製代碼
全部/webjars/**
,都去 classpath:/META-INF/resources/webjars/
中尋找資源webjars
:以jar包的方式引入靜態資源
引入jquery-webjar
<!--在訪問的時候只須要寫webjars下面資源的名稱便可-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
複製代碼
引入後咱們能夠經過 :localhost:8080/webjars/jquery/3.3.1/jquery.js
訪問到靜態資源
"/**"
訪問當前項目的任何資源,都去(靜態資源的文件夾)找映射
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":當前項目的根路徑
複製代碼
歡迎頁: 靜態資源文件夾下的全部index.html頁面
被"/**"
映射訪問:localhost:8080/
便會去靜態資源文件夾下找index頁面
*全部的 */favicon.ico 都是在靜態資源文件下找
市面上常見的模板引擎:
SpringBoot自動配置好了SpringMVC,如下是SpringBoot對SpringMVC的默認配置:WebMvcAutoConfiguration
自動配置了ViewResolver
(視圖解析器:根據方法的返回值獲得視圖對象(View),視圖對象決定如何渲染 (轉發/重定向)
ContentNegotiatingViewResolver
組合全部的視圖解析器
自定義配置:咱們能夠本身給容器中添加一個視圖解析器,自動的將如下組合進來
webjars
:靜態資源文件夾路徑Static index.html suppor
:靜態首頁訪問favicon.ico
:個性化圖標Converter
:類型轉換器Formatter
:格式化器@Bean
@ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")//在文件中配置日期格式化的規則
public Formatter<Date> dateFormatter() {
return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化組件
}
複製代碼
在配置文件中自定義規則:
spring.mvc.date-format=yyyy-MM-dd
複製代碼
HttpMessageConverter
:SpringMVC用來轉換Http請求和響應的Automatic registration of MessageCodesResolver (see below)
:定義錯誤代碼生成規則傳統寫法:
<mvc:view-controller path="/hello" view-name="success"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/hello"/>
</mvc:interceptor>
</mvc:interceptors>
複製代碼
SpringBoot寫法:
@Configuration
):既保留了全部的自動配置,也能用咱們擴展的配置WebMvcConfigurerAdapter
類型//使用WebMvcConfigurerAdapter能夠來擴展SpringMVC的功能
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//瀏覽器發送 /hello 請求直接來到 success
registry.addViewController("/hello").setViewName("success");
}
}
複製代碼
原理:
WebMvcAutoConfiguration
是SpringMVC的自動配置類@Import(EnableWebMvcConfiguration.class)
@Configuration
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
//從容器中獲取全部的WebMvcConfigurer
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
//一個參考實現;將全部的WebMvcConfigurer相關配置都來一塊兒調用;
this.configurers.addWebMvcConfigurers(configurers);
}
}
}
複製代碼
@Override
public void addViewControllers(ViewControllerRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addViewControllers(registry);
}
}
複製代碼
WebMvcConfigurer
都會一塊兒起做用,咱們的配置類也會被調用;效果:SpringMVC的自動配置和咱們的擴展配置都會起做用
咱們須要在配置類中添加@EnableWebMvc
//使用WebMvcConfigurerAdapter能夠來擴展SpringMVC的功能
@EnableWebMvc
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//瀏覽器發送 /hello 請求直接來到 success
registry.addViewController("/hello").setViewName("success");
}
}
複製代碼
問題:
爲何添加@EnableWebMvc
自動配置就失效了
原理:
@EnableWebMvc
的核心@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {}
複製代碼
DelegatingWebMvcConfiguration
類@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {}
複製代碼
WebMvcAutoConfiguration
類@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class })
//容器中沒有這個組件的時候,這個自動配置類才生效
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
複製代碼
WebMvcConfigurationSupport
只是SpringMVC最基本的功能(因此有時候避免添加@EnableWebMvc
)xxxConfigurer
幫助咱們進行擴展配置xxxCustomizer
幫助咱們進行定製配置使用過SpringBoot的人對下圖都不陌生
ErrorMvcAutoConfiguration
:錯誤處理的自動配置
DefaultErrorAttributes
BasicErrorController
:處理默認/error請求
ErrorPageCustomizer
DefaultErrorViewResolver
步驟:
「系統出現4xx或者5xx之類的錯誤:
ErrorPageCustomizer
就會生效(定製錯誤的響應規則),就會來到/error
請求;就會被BasicErrorController
處理
定製錯誤的頁面
有模板引擎的狀況下:error/狀態碼
將錯誤頁面命名爲 錯誤狀態碼.html
放在模板引擎文件夾裏面的 error文件夾
下,發生此狀態碼的錯誤就會來到對應的頁面
咱們可使用4xx
和5xx
做爲錯誤頁面的文件名來匹配這種類型的全部錯誤,精確優先(優先尋找精確的狀態碼.html)
頁面能獲取的信息
timestamp:時間戳
status:狀態碼
error:錯誤提示
exception:異常對象
message:異常消息
errors:JSR303數據校驗的錯誤都在這裏
複製代碼
定製錯誤的json數據:
json
數據@ControllerAdvice
public class MyExceptionHandler {
@ResponseBody
@ExceptionHandler(UserNotExistException.class)
public Map<String,Object> handleException(Exception e){
Map<String,Object> map = new HashMap<>();
map.put("code","user.notexist");
map.put("message",e.getMessage());
return map;
}
}
複製代碼
/error
進行自適應響應效果處理 @ExceptionHandler(UserNotExistException.class)
public String handleException(Exception e, HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
//傳入咱們本身的錯誤狀態碼 4xx 5xx,不然就不會進入定製錯誤頁面的解析流程
/**
* Integer statusCode = (Integer) request
.getAttribute("javax.servlet.error.status_code");
*/
request.setAttribute("javax.servlet.error.status_code",500);
map.put("code","user.notexist");
map.put("message",e.getMessage());
//轉發到/error
return "forward:/error";
}
複製代碼
「出現錯誤之後,會來到
/error
請求,會被BasicErrorController
處理,響應出去能夠獲取的數據是由getErrorAttributes()
獲得的。(是AbstractErrorController(ErrorController)規定的方法)
ErrorController
的實現類【或者是編寫AbstractErrorController
的子類】,放在容器中errorAttributes.getErrorAttributes()
獲得, 容器中DefaultErrorAttributes.getErrorAttributes()
默認進行數據處理的自定義ErrorAttributes
//給容器中加入咱們本身定義的ErrorAttributes
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);
map.put("name","cbuc");
return map;
}
}
複製代碼
ErrorAttributes
改變須要返回的內容「今天的你多努力一點,明天的你就能少說一句求人的話!
我是小菜,一個和你一塊兒學習的男人。
💋