YAML (YAML Ain't a Markup Language)YAML不是一種標記語言,一般以.yml爲後綴的文件,是一種直觀的可以被電腦識別的數據序列化格式,而且容易被人類閱讀,容易和腳本語言交互的,能夠被支持YAML庫的不一樣的編程語言程序導入,一種專門用來寫配置文件的語言。html
YML是代替XML的最優解決方案,語法簡潔,清晰易讀,跨平臺性和擴展性良好好,能夠表達複雜的數據結構;java
基本語法:node
1.數據以key: value
鍵值對的形式存儲web
須要強調的是冒號後面必須有一個空格redis
name: jerry
2.不區分數據類型spring
name: jerry age: 18
3.使用縮進來表示做用域,相同縮進的鍵值對處於同一個級別shell
student: name: jerry age: 18
4.[]表示數組或集合數據庫
numbser: [1,2,3,4]
5.{}能夠在同一行書寫map/對象apache
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 -jar -Dspring.profiles.active=prod /Users/jerry/IdeaProjects/SpringBootDemo/target/SpringBootDemo-1.0-SNAPSHOT.jar
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.
參考官網:去看看
<!-- 配置使用redis啓動器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
單機
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"
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
還記得攔截器是用來幹什麼的嗎,它在何時執行?
在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"; }
@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>
在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
服務提供方和消費方依然是獨立的項目,各自管理本身的依賴關係,而後抽取公共部分
建立工程:
| 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