SpringBoot配置文件 YML YAML (YAML Ain't a Markup Language)YAML不是一種標記語言,通常以.yml為尾碼的文件,是一種直觀的能夠被電腦識別的數據序列化格式,並且容易被人類閱讀,容易和腳本語言交互的,可以被支持YAML庫的不同的編程語言程式導入,一種專 ...
SpringBoot配置文件
YML
YAML (YAML Ain't a Markup Language)YAML不是一種標記語言,通常以.yml為尾碼的文件,是一種直觀的能夠被電腦識別的數據序列化格式,並且容易被人類閱讀,容易和腳本語言交互的,可以被支持YAML庫的不同的編程語言程式導入,一種專門用來寫配置文件的語言。
YML是代替XML的最優解決方案,語法簡潔,清晰易讀,跨平臺性和擴展性良好好,可以表達複雜的數據結構;
基本語法:
1.數據以key: value
鍵值對的形式存儲
需要強調的是冒號後面必須有一個空格
name: jerry
2.不區分數據類型
name: jerry
age: 18
3.使用縮進來表示作用域,相同縮進的鍵值對處於同一個級別
student:
name: jerry
age: 18
4.[]表示數組或集合
numbser: [1,2,3,4]
5.{}可以在同一行書寫map/對象
maps: {key1: value1,key2: value2}
6.數組和字典中的元素也可以使用 -
來分隔到多行
#字元數組/list:
hobby:
- game
- music
#存儲map/對象的 數組/list:
dogs:
- name: 阿花
age: 1
- name: 啊醜
age: 2
- {name: 啊啊,age: 3}
7.日期
birthday: 2020/12/12 10:10:10
8.文檔塊,可在同一個文件中編寫兩份不同的配置
server:
port: 8081
spring:
profiles:
active: prod #激活對應的文檔塊
---
server:
port: 8083
spring:
profiles: dev #指定屬於哪個環境
---
server:
port: 8084
spring:
profiles: prod #指定屬於哪個環境
案例:
java類:
public class Person {
private String name;
private int age;
private String[] hobby;
private HashSet<String> gfs;
private Map<String,String> maps;
private Dog dog;
private List<Dog> dogs;
private Date birth;
public Date getBirth() {
return birth;
}
}
class Dog {
private String name;
}
yml:
person:
name: jerry
age: 18
hobby: #[game,music]
- game
- music
gfs: [a,b,c]
maps: {key1: value1,key2: value2}
#maps:
# key1: value1
#key2: value2
dog:
name: 大黃
dogs:
- name: 阿花
age: 18
- name: 啊醜
age: 20
birth: 2020/12/12 23:56:10
獲取配置信息
1.當容器中的bean需要使用配置文件中的內容時,可以使用@Value註解:當然要保證該類的Bean以及加入容器
@Value("${myname}")
private String myname;
2.當有很多屬性都要註入到Bean中時可以採用@ConfigurationProperties
註解,SpringBoot會按照屬性名稱進行註入,註意:必須提供set方法
@Component
//perfix指定要映射的key名稱 與配置文件中對應
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private int age;
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;}
}
切換配置文件
在項目開發過程中我們為了不影響線上數據,通常會使用一套專門用於開發階段的配置,在編寫完成後再切換到線上配置比如redis,zookeeper,資料庫等等,SpringBoot可以幫助我們輕鬆實現配置文件的切換;
配置文件的命名:
根據不同使用場景,創建格式為application-環境標識.yml(/properties)
的配置文件,例如:
application-dev.yml
application-prod.yml
指定要使用的配置文件
方式一:
創建名為application-dev.yml的配置文件,SpringBoot預設會讀取該文件,在文件中指定要使用的配置文件信息:
spring:
profiles:
active: dev #dev即為環境標識
方式二
不需要創建預設的application.yml,而是在運行程式時通過參數來指定要使用的配置文件
- 通過java虛擬機參數:
java -jar -Dspring.profiles.active=prod /Users/jerry/IdeaProjects/SpringBootDemo/target/SpringBootDemo-1.0-SNAPSHOT.jar
- 也可以通過Springboot參數指定:
java -jar /Users/jerry/IdeaProjects/SpringBootDemo/target/SpringBootDemo-1.0-SNAPSHOT.jar --spring.profiles.active=prod
註意:使用該方式則必須在引導類中將獲取的命令行參數傳遞給SpringBoot
@SpringBootApplication
public class Application {
public static void main(String[] args) {
//args 即為命令行參數
SpringApplication.run(Application.class,args);
}
}
常見配置項:
# ----------------------------------------
# WEB PROPERTIES
# ----------------------------------------
# EMBEDDED SERVER CONFIGURATION (ServerProperties)
server.port=8080 # Server HTTP port.
server.servlet.context-path= # Context path of the application.
server.servlet.path=/ # Path of the main dispatcher servlet.
# HTTP encoding (HttpEncodingProperties)
spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses.
Added to the "Content-Type" header if not set explicitly.
# JACKSON (JacksonProperties)
spring.jackson.date-format= # Date format string or a fully-qualified date
format class name. For instance, `yyyy-MM-dd HH:mm:ss`.
# SPRING MVC (WebMvcProperties)
spring.mvc.servlet.load-on-startup=-1 # Load on startup priority of the
dispatcher servlet.
spring.mvc.static-path-pattern=/** # Path pattern used for static resources.
spring.mvc.view.prefix= # Spring MVC view prefix.
spring.mvc.view.suffix= # Spring MVC view suffix.
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver.
Auto-detected based on the URL by default.
spring.datasource.password= # Login password of the database.
spring.datasource.url= # JDBC URL of the database.
spring.datasource.username= # Login username of the database.
# JEST (Elasticsearch HTTP client) (JestProperties)
spring.elasticsearch.jest.password= # Login password.
spring.elasticsearch.jest.proxy.host= # Proxy host the HTTP client should use.
spring.elasticsearch.jest.proxy.port= # Proxy port the HTTP client should use.
spring.elasticsearch.jest.read-timeout=3s # Read timeout.
spring.elasticsearch.jest.username= # Login username.
參考官網:去看看
SpringBoot中Redis的使用
添加起步依賴
<!-- 配置使用redis啟動器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置redis信息
單機
spring: redis: host: 10.211.55.6 port: 6379 #Sprin boot 預設使用的是lettuce作為redis客戶端,使用非同步IO,且線程安全 lettuce: pool: max-active: 10 max-idle: 5 #連接池不是必須的配置項,基礎配置只需要host和port即可
集群
spring: redis: cluster: nodes: 10.211.55.6:6379,10.211.55.6:6380,10.211.55.6:6381,10.211.55.6:6382,10.211.55.6:6383,10.211.55.6:6384 #節點之間使用逗號隔開
數據讀寫案列
@Service
public class UserServiceImpl implements UserService {
@Autowired
StringRedisTemplate redisTemplate;
@Autowired
UserMapper mapper;
@Autowired
ObjectMapper objectMapper;//用於json序列化
@Override
public List<User> getAll() {
try {
//從redis獲取數據
String users_json = redisTemplate.opsForValue().get("users");
//如果存在則直接返回
if (users_json != null && users_json.length() > 0){
System.out.println("緩存數據.......");
return objectMapper.readValue(users_json,List.class);
}else{
//不存在則查詢資料庫
List<User> users = mapper.selectUserList();
//並放入redis
redisTemplate.opsForValue().set("users",objectMapper.writeValueAsString(users));
//返回
return users;
}
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return mapper.selectUserList();
}
}
請求測試:http://localhost:8080/user/list,可以看到輸出緩存數據
表示redis已正常工作
事務管理
涉及資料庫的操作就免不了事務,在ssm項目中我們需要配置事務管理器等相關信息,這寫配置但多數情況下也都是差不多的,所以在SpringBoot中,我們不需要編寫任何的配置信息,只要在需要進行事務管理的方法上添加事務註解即可
事務測試案例:
@Service
public class UserServiceImpl implements UserService {
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void updateUser(){
User user = mapper.selectUserById(1);
user.setUsername("JERRY1");
mapper.updateByPrimaryKey(user);
int i = 1/0;
}
}
若不生效可在引導類上添加@EnableTransactionManagement
註解
@EnableTransactionManagement
public class Application {
public static void main(String[] args) {
//啟動Spring boot 需要指定引導類
SpringApplication.run(Application.class,args);
}
}
日誌配置
當我們加入了web的起步依賴後,SpringBoot就已經自動的配置了日誌了,其預設使用的是slf4j+logback,並將日誌直接輸出到控制台,一些情況下我們需要自己來修改日誌的一些參數,如級別,輸出位置等;
日誌的起步依賴:當然這不需要我們自己添加,SpringBoot已經有了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
輸出日誌
@Controller
public class UserController {
//獲取一個logger
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
UserService service;
@RequestMapping("/show")
public String showList(Model model){
logger.info("request path:/show");
logger.info("request path:/show");
logger.debug("request path:/show");
logger.warn("request path:/show");
List<User> all = service.getAll();
model.addAttribute("userList",all);
return "userlist";
}
}
簡單配置
logging:
level:
root: info # rootLogger的級別
com.kkb.controller: debug #某個包的日誌級別
file:
path: ./logs/ #日誌輸出目錄
max-size: 1GB #文件大小
max-history: 5 #文件個數
pattern:
console: "%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger-%msg哈哈哈哈%n"
切換至log4j
logback的配置文件基本上和log4j差不多,但仍然有一些差別,當我們需要對日誌進行詳細的定製時無疑會增加我們的學習成本,推薦直接使用log4j,單從對比數據上來看log4j更有優勢;
使用前需要先將原本的logback依賴排除掉,然後添加log4f的依賴
添加依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!--找到spring-web的起步依賴 排除logback-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
在resources下提供log4j2.xml
日誌配置:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<!--自定義屬性信息-->
<properties>
<property name="LOG_HOME">logs</property>
<property name="FILE_NAME">applog</property>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<!--滾動日誌配置
filePattern用於設置滾動文件的命名規則
若以.zip為結尾則會自動歸檔日誌文件 也支持其他的格式.gz, .zip, .bz2, 等-->
<RollingRandomAccessFile name="RollingAppender"
fileName="${LOG_HOME}/${FILE_NAME}.log"
filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i.log">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<!--滾動時間間隔 該參數需結合filePattern中的時間格式 此時表示為1分鐘更換一個新文件
若時間格式為%d{yyyy-MM-dd HH}則表示每小時更換一個新文件-->
<TimeBasedTriggeringPolicy interval="1"/>
<!--單個日誌文件最大容量 -->
<SizeBasedTriggeringPolicy size="1 MB"/>
</Policies>
<!--最大保留的日誌文件個數 預設為7個 -->
<DefaultRolloverStrategy max="20"/>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
<Logger name="com.kkb.controller" level="debug">
<AppenderRef ref="RollingAppender"/>
<AppenderRef ref="Console"/>
</Logger>
</Loggers>
</Configuration>
若名稱不是預設的log42.xml
則可以在springboot中添加配置來指定:
logging:
config: classpath:log4j3.xml
Handler攔截器
還記得攔截器是用來乾什麼的嗎,它在什麼時候執行?
在web-mvc中我們已經認識了攔截器,它可以在一個請求到達Handler處理之前對請求進行攔截,從而可以輕鬆的實現許可權控制,登錄認證等功能;
定義攔截器:
public class LogginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("攔截器執行..................");
if (request.getRequestURI().contains("login")){
return true;
}
if (request.getSession().getAttribute("user") == null){
response.sendRedirect("/login.html");
return false;
}
return true;
}
}
控制器添加代登錄介面和登錄頁面
@RequestMapping("/login")
public String userLogin(User user, HttpSession session){
User u = service.userLogin(user);
if (user.getUsername().equals("jerry") && user.getPassword().equals("123")){
session.setAttribute("user",user);
return "redirect:/show";
}
return "redirect:/login.html";
}
@RequestMapping("/login.html")
public String getage(){
return "login";
}
創建mvc配置類添加自定義的攔截器
@Configuration
public class MyConfigruation implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogginInterceptor()).addPathPatterns("/**");
}
}
異常處理
webmvc中異常處理採用的是AOP,我開門只需要提供用於處理異常的通知即可
定義異常處理通知:
@ControllerAdvice //異常處理使用的是AOP 所以處理邏輯 將做為通知被織入
public class GlobalExceptionHandler {
//日誌記錄器
private Logger logger = LoggerFactory.getLogger(getClass());
//指定該方法可以處理的異常類型
@ExceptionHandler(Exception.class)
//model 用於向錯誤頁面傳遞數據
public String defaultHandler(Model model,Exception e){
model.addAttribute("error",e.getMessage());//添加錯誤信息
logger.error(e.getMessage(),e);//輸出到日誌
return "error";//跳轉error.html
}
}
提供一個錯誤頁面:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>系統錯誤</h1>
原因:<span th:text="${error}" style="color:red"/>
</body>
</html>
SpringBoo工程的打包
在pom中添加SpringBoot的maven插件,這將使得maven打包時會將所有依賴的jar包全部打包,形成一個fat jar,這樣一來只要有java環境就能運行工程了,不需要在配置相關的依賴;
添加插件:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
執行命令:
#cd到工程根目錄下:
mavem package
#打包前會先執行項目中的所有單元測試,若不需要運行測試可以使用以下參數跳過測試直接打包
maven -DskipTests package
運行打包好的項目:
#打包完成後會在項目根目錄下生產target目錄,裡面就包含了打包完的jar,進入target後執行以下命令即可
java -jar ./target/SpringBootDemo-1.0-SNAPSHOT.jar
整合Dubbo
服務提供方和消費方依然是獨立的項目,各自管理自己的依賴關係,然後抽取公共部分
創建工程:
| common (空的maven)
| HelloService
| provider (dubbo + SpringBot)
| HelloServiceImpl
| consumer (dubbo + SpringBot + webMVC)
| HelloController
服務提供方:
pom文件:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
實現類:
@Service //註意 要使用dubbo提供的Service註解
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "hello "+name;
}
}
配置文件:
dubbo:
application:
name: my-provider
qos-enable: false
registry:
protocol: zookeeper
address: 10.211.55.5:2182
protocol:
name: dubbo
port: 21888
引導類:
@SpringBootApplication
@EnableDubbo
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
消費方:
pom文件:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
控制器:
@RestController
public class HeolloController {
@Reference
HelloService helloService;
@RequestMapping("/test/{name}")
public String serviceTest(@PathVariable String name){
return helloService.sayHello(name);
}
}
配置文件:
dubbo:
application:
name: my-consumer
qos-enable: false
registry:
protocol: zookeeper
address: 10.211.55.5:2182
#集群寫法 address: zookeeper://192.168.50.132:2181?backup=192.168.50.133:2181,192.168.50.134:2181
引導類:
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
訪問測試:http://localhost:8080/test/jerry
頁面輸出名字即訪問成功
Dubbo的pom文件和普通的SpringBoot略微不同,不用指定parent