SpringBoot 進階

SpringBoot配置文件

YML

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虛擬機參數:
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

相關文章
相關標籤/搜索