后端Web實戰(項目管理)

?Restful風格

我們的案例是基于當前最為主流的前后端分離模式進行開發

在前后端分離的開發模式中,前后端開發人員都需要根據提前定義好的接口文檔,來進行前后端功能的開發。

后端開發人員:必須嚴格遵守提供的接口文檔進行后端功能開發(保障開發的功能可以和前端對接)

基于REST風格URL如下:

  • http://localhost:8080/users/1 GET:查詢id為1的用戶

  • http://localhost:8080/users POST:新增用戶

  • http://localhost:8080/users PUT:修改用戶

  • http://localhost:8080/users/1 DELETE:刪除id為1的用戶

其中總結起來,就一句話:通過URL定位要操作的資源,通過HTTP動詞(請求方式)來描述具體的操作。

在REST風格的URL中,通過四種請求方式,來操作數據的增刪改查。

  • GET : 查詢

  • POST :新增

  • PUT : 修改

  • DELETE :刪除

我們看到如果是基于REST風格,定義URL,URL將會更加簡潔、更加規范、更加優雅

注意事項:

  • REST是風格,是約定方式,約定不是規定,可以打破

  • 描述模塊的功能通常使用復數,也就是加s的格式來描述,表示此類資源,而非單個資源。如:users、emps、books…

  1. 工程搭建

1). 創建SpringBoot工程,并引入web開發起步依賴、mybatis、mysql驅動、lombok

  • 創建項目

配置編碼格式?

jdk版本

2). 創建數據庫及對應的表結構,并在application.yml中配置數據庫的基本信息。

  • 創建tlias數據庫,并準備dept部門表。

    CREATE TABLE dept (id int unsigned PRIMARY KEY AUTO_INCREMENT COMMENT 'ID, 主鍵',name varchar(10) NOT NULL UNIQUE COMMENT '部門名稱',create_time datetime DEFAULT NULL COMMENT '創建時間',update_time datetime DEFAULT NULL COMMENT '修改時間'
    ) COMMENT '部門表';INSERT INTO dept VALUES (1,'學工部','2023-09-25 09:47:40','2024-07-25 09:47:40'),(2,'教研部','2023-09-25 09:47:40','2024-08-09 15:17:04'),(3,'咨詢部','2023-09-25 09:47:40','2024-07-30 21:26:24'),(4,'就業部','2023-09-25 09:47:40','2024-07-25 09:47:40'),(5,'人事部','2023-09-25 09:47:40','2024-07-25 09:47:40'),(6,'行政部','2023-11-30 20:56:37','2024-07-30 20:56:37');

    application.yml 配置文件中配置數據庫的連接信息

spring:application:name: tlias-web-management#mysql連接配置datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/tliasusername: rootpassword: 123456
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3). 準備基礎包結構,并引入實體類Dept及統一的響應結果封裝類Result

  • 準備基礎包結構

  • 實體類Dept

package com.itheima.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDateTime;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {private Integer id;private String name;private LocalDateTime createTime;private LocalDateTime updateTime;
}
  • 統一響應結果Result

    package com.itheima.pojo;import lombok.Data;
    import java.io.Serializable;/*** 后端統一返回結果*/
    @Data
    public class Result {private Integer code; //編碼:1成功,0為失敗private String msg; //錯誤信息private Object data; //數據public static Result success() {Result result = new Result();result.code = 1;result.msg = "success";return result;}public static Result success(Object object) {Result result = new Result();result.data = object;result.code = 1;result.msg = "success";return result;}public static Result error(String msg) {Result result = new Result();result.msg = msg;result.code = 0;return result;}}
  • 基礎代碼結構

    • DeptMapper

      package com.itheima.mapper;import org.apache.ibatis.annotations.Mapper;@Mapper
      public interface DeptMapper {
      }
    • DeptService

      package com.itheima.service;public interface DeptService {
      }

    • DeptServiceImpl

    • package com.itheima.service.impl;import com.itheima.service.DeptService;
      import org.springframework.stereotype.Service;@Service
      public class DeptServiceImpl implements DeptService {
      }

    • DeptController

      package com.itheima.controller;import org.springframework.web.bind.annotation.RestController;/*** 部門管理控制器*/
      @RestController
      public class DeptController {
      }

    • 代碼實現
    • 1). Controller層

      DeptController 中,增加 list 方法,代碼如下:

      /*** 部門管理控制器*/
      @RestController
      public class DeptController {@Autowiredprivate DeptService deptService;/*** 查詢部門列表*/@RequestMapping("/depts")public Result list(){List<Dept> deptList = deptService.findAll();return Result.success(deptList);}
      }

    2). Service層

    DeptService 中,增加 findAll方法,代碼如下:

    public interface DeptService {/*** 查詢所有部門*/public List<Dept> findAll();
    }

    DeptServiceImpl 中,增加 findAll方法,代碼如下:

    @Service
    public class DeptServiceImpl implements DeptService {@Autowiredprivate DeptMapper deptMapper;public List<Dept> findAll() {return deptMapper.findAll();}
    }

    3). Mapper層

    DeptMapper 中,增加 findAll方法,代碼如下:

    @Mapper
    public interface DeptMapper {/*** 查詢所有部門*/@Select("select * from dept")public List<Dept> findAll();}
    1. 接口測試

    啟動項目,然后我們就可以打開Apifox進行測試了。

    :在controller方法上使用,@RequestMapping的衍生注解 @GetMapping。 該注解就是標識當前方法,必須以GET方式請求。

    @RestController
    public class DeptController {@Autowiredprivate DeptService deptService;/*** 查詢部門列表*/@GetMapping("/depts")public Result list(){List<Dept> deptList = deptService.findAll();return Result.success(deptList);}
    }

    上述兩種方式,在項目開發中,推薦使用第二種方式,簡潔、優雅。

    • GET方式:@GetMapping

    • POST方式:@PostMapping

    • PUT方式:@PutMapping

    • DELETE方式:@DeleteMapping

    1. 數據封裝
    2. 在上述測試中,我們發現部門的數據中,id、name兩個屬性是有值的,但是createTime、updateTime兩個字段值并未成功封裝,而數據庫中是有對應的字段值的,這是為什么呢?

    原因如下:

    • 實體類屬性名和數據庫表查詢返回的字段名一致,mybatis會自動封裝。

    • 如果實體類屬性名和數據庫表查詢返回的字段名不一致,不能自動封裝。

    解決方案:

    • 手動結果映射

    • 起別名

    • 開啟駝峰命名

      @Results({@Result(column = "create_time", property = "createTime"),@Result(column = "update_time", property = "updateTime")})
      @Select("select id, name, create_time, update_time from dept")
      public List<Dept> findAll();

      1). 手動結果映射

      在DeptMapper接口方法上,通過 @Results及@Result 進行手動結果映射。

    說明:

    • @Results 注解源碼:

    • @Result源代碼:

    2). 起別名

    在SQL語句中,對不一樣的列名起別名,別名和實體類屬性名一樣。

    @Select("select id, name, create_time createTime, update_time updateTime from dept")
    public List<Dept> findAll();

    3). 開啟駝峰命名(推薦)

    如果字段名與屬性名符合駝峰命名規則,mybatis會自動通過駝峰命名規則映射。駝峰命名規則: abc_xyz => abcXyz

    • 表中字段名:abc_xyz

    • 類中屬性名:abcXyz

    在application.yml中做如下配置,開啟開關。

    mybatis:configuration:map-underscore-to-camel-case: true

    1. 前后端聯調

    1. 聯調測試

    完成了查詢部門的功能,我們也通過 Apifox 工具測試通過了,下面我們再基于前后端分離的方式進行接口聯調。具體操作如下:

    1). 將資料中提供的 "前端環境" 文件夾中的壓縮包,拷貝到一個沒有中文不帶空格的目錄下。

    3). 雙擊 nginx.exe 啟動Nginx,一閃而過,就說明nginx已啟動完成。

    如果在任務管理器中,能看到上述兩個進程,就說明nginx已經啟動成功。

    ?4). 打開瀏覽器,訪問:http://localhost:90

    1. 請求訪問流程

    前端工程請求服務器的地址為 http://localhost:90/api/depts,是如何訪問到后端的tomcat服務器的?

    ?其實這里,是通過前端服務Nginx中提供的反向代理功能實現的。

    1). 瀏覽器發起請求,請求的是localhost:90 ,那其實請求的是nginx服務器。

    2). 在nginx服務器中呢,并沒有對請求直接進行處理,而是將請求轉發給了后端的tomcat服務器,最終由tomcat服務器來處理該請求。

    這個過程就是通過nginx的反向代理實現的。 那為什么瀏覽器不直接請求后端的tomcat服務器,而是直接請求nginx服務器呢,主要有以下幾點原因:

    1). 安全:由于后端的tomcat服務器一般都會搭建集群,會有很多的服務器,把所有的tomcat暴露給前端,讓前端直接請求tomcat,對于后端服務器是比較危險的。

    2). 靈活:基于nginx的反向代理實現,更加靈活,后端想增加、減少服務器,對于前端來說是無感知的,只需要在nginx中配置即可。

    3). 負載均衡:基于nginx的反向代理,可以很方便的實現后端tomcat的負載均衡操作。

    具體的請求訪問流程如下:

    1. location:用于定義匹配特定uri請求的規則。

    2. ^~ /api/:表示精確匹配,即只匹配以/api/開頭的路徑。

    3. rewrite:該指令用于重寫匹配到的uri路徑。

    4. proxy_pass:該指令用于代理轉發,它將匹配到的請求轉發給位于后端的指令服務器。

    1. 刪除部門

    1. 需求

    刪除部門數據。在點擊 "刪除" 按鈕,會根據ID刪除部門數據。

    1. 思路分析

    明確了刪除部門的需求之后,再來梳理一下實現該功能時,三層架構每一層的職責:

    1. 簡單參數接收

    我們看到,在controller中,需要接收前端傳遞的請求參數。 那接下來,我們就先來看看在服務器端的Controller程序中,如何獲取這類簡單參數。 具體的方案有如下三種:

    • 方案一:通過原始的 HttpServletRequest 對象獲取請求參數

      /**
      * 根據ID刪除部門 - 簡單參數接收: 方式一 (HttpServletRequest)
      */
      @DeleteMapping("/depts")
      public Result delete(HttpServletRequest request){String idStr = request.getParameter("id");int id = Integer.parseInt(idStr);System.out.println("根據ID刪除部門: " + id);return Result.success();
      }

      這種方案實現較為繁瑣,而且還需要進行手動類型轉換。【項目開發很少用】

    • 方案二:通過Spring提供的 @RequestParam 注解,將請求參數綁定給方法形參

      @DeleteMapping("/depts")
      public Result delete(@RequestParam("id") Integer deptId){System.out.println("根據ID刪除部門: " + deptId);return Result.success();
      }

      @RequestParam 注解的value屬性,需要與前端傳遞的參數名保持一致 。

      @RequestParam注解required屬性默認為true,代表該參數必須傳遞,如果不傳遞將報錯。 如果參數可選,可以將屬性設置為false。

    • 方案三:如果請求參數名與形參變量名相同,直接定義方法形參即可接收。(省略@RequestParam)

      @DeleteMapping("/depts")
      public Result delete(Integer id){System.out.println("根據ID刪除部門: " + deptId);return Result.success();
      }

      對于以上的這三種方案呢,我們推薦第三種方案

    1. 代碼實現

    1). Controller層

    DeptMapper 中,增加 delete 方法,代碼實現如下:

    /*** 根據id刪除部門 - delete http://localhost:8080/depts?id=1*/
    @DeleteMapping("/depts")
    public Result delete(Integer id){System.out.println("根據id刪除部門, id=" + id);deptService.deleteById(id);return Result.success();
    }

    2). Service層

    DeptService 中,增加 deleteById 方法,代碼實現如下:

    /*** 根據id刪除部門*/
    void deleteById(Integer id);

    DeptServiceImpl 中,增加 deleteById 方法,代碼實現如下:

    public void deleteById(Integer id) {deptMapper.deleteById(id);
    }

    3). Mapper層

    DeptMapper 中,增加 deleteById 方法,代碼實現如下:

    /*** 根據id刪除部門*/
    @Delete("delete from dept where id = #{id}")
    void deleteById(Integer id);

    如果mapper接口方法形參只有一個普通類型的參數,#{…} 里面的屬性名可以隨便寫,如:#{id}#{value}

    對于 DML 語句來說,執行完畢,也是有返回值的,返回值代表的是增刪改操作,影響的記錄數,所以可以將執行 DML 語句的方法返回值設置為 Integer。 但是一般開發時,是不需要這個返回值的,所以也可以設置為void。

    代碼編寫完畢之后,我們就可以啟動服務,進行測試了

    1. 新增部門

    1. 需求

    點擊 "新增部門" 的按鈕之后,彈出新增部門表單,填寫部門名稱之后,點擊確定之后,保存部門數據。

    1. 思路分析

    明確了新增部門的需求之后,再來梳理一下實現該功能時,三層架構每一層的職責:

    1. json參數接收

    我們看到,在controller中,需要接收前端傳遞的請求參數。 那接下來,我們就先來看看在服務器端的Controller程序中,如何獲取json格式的參數。

    • JSON格式的參數,通常會使用一個實體對象進行接收 。

    • 規則:JSON數據的鍵名與方法形參對象的屬性名相同,并需要使用@RequestBody注解標識

    前端傳遞的請求參數格式為json,內容如下:{"name":"研發部"}。這里,我們可以通過一個對象來接收,只需要保證對象中有name屬性即可。

    1. 代碼實現

    1). Controller層

    DeptController中增加方法save,具體代碼如下:

    /*** 新增部門 - POST http://localhost:8080/depts   請求參數:{"name":"研發部"}*/
    @PostMapping("/depts")
    public Result save(@RequestBody Dept dept){System.out.println("新增部門, dept=" + dept);deptService.save(dept);return Result.success();
    }

    2). Service層

    DeptService中增加接口方法save,具體代碼如下:

    /*** 新增部門*/
    void save(Dept dept);

    DeptServiceImpl中增加save方法,完成添加部門的操作,具體代碼如下:

    public void save(Dept dept) {//補全基礎屬性dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());//保存部門deptMapper.insert(dept);
    }

    3). Mapper層

    /*** 保存部門*/
    @Insert("insert into dept(name,create_time,update_time) values(#{name},#{createTime},#{updateTime})")
    void insert(Dept dept);

    ?如果在mapper接口中,需要傳遞多個參數,可以把多個參數封裝到一個對象中。 在SQL語句中獲取參數的時候,#{...} 里面寫的是對象的屬性名【注意是屬性名,不是表的字段名】。

    代碼編寫完畢之后,我們就可以啟動服務,進行測試了。

    1. 修改部門

    對于任何業務的修改功能來說,一般都會分為兩步進行:查詢回顯、修改數據。

    1. 查詢回顯

    1. 需求

    當我們點擊 "編輯" 的時候,需要根據ID查詢部門數據,然后用于頁面回顯展示。

    1. 思路分析

    明確了根據ID查詢部門的需求之后,再來梳理一下實現該功能時,三層架構每一層的職責

    ?

    1. 路徑參數接收

    /depts/1/depts/2 這種在url中傳遞的參數,我們稱之為路徑參數。 那么如何接收這樣的路徑參數呢 ?

    路徑參數:通過請求URL直接傳遞參數,使用{…}來標識該路徑參數,需要使用 @PathVariable獲取路徑參數。如下所示:

    如果路徑參數名與controller方法形參名稱一致,@PathVariable注解的value屬性是可以省略的。

    1. 代碼實現

    1). Controller層

    DeptController 中增加 getById方法,具體代碼如下:

    /*** 根據ID查詢 - GET http://localhost:8080/depts/1*/
    @GetMapping("/depts/{id}")
    public Result getById(@PathVariable Integer id){System.out.println("根據ID查詢, id=" + id);Dept dept = deptService.getById(id);return Result.success(dept);
    }

    2). Service層

    DeptService 中增加 getById方法,具體代碼如下:

    /*** 根據id查詢部門*/
    Dept getById(Integer id);

    DeptServiceImpl 中增加 getById方法,具體代碼如下:

    public Dept getById(Integer id) {return deptMapper.getById(id);
    }

    3). Mapper層

    DeptMapper 中增加 getById 方法,具體代碼如下:

    /**
    * 根據ID查詢部門數據
    */
    @Select("select id, name, create_time, update_time from dept where id = #{id}")
    Dept getById(Integer id);

    代碼編寫完畢之后,我們就可以啟動服務,進行測試了。

    1. 修改數據

    1. 需求

    查詢回顯回來之后,就可以對部門的信息進行修改了,修改完畢之后,點擊確定,此時,就需要根據ID修改部門的數據。

    1. 接口描述

    參照參照課程資料中提供的接口文檔。 部門管理 -> 修改部門

    1. 思路分析

    參照接口文檔,梳理三層架構每一層的職責:

    通過接口文檔,我們可以看到前端傳遞的請求參數是json格式的請求參數,在Controller的方法中,我們可以通過 @RequestBody 注解來接收,并將其封裝到一個對象中。?

    1. 代碼實現

    1). Controller層

    DeptController 中增加 update 方法,具體代碼如下:

    /*** 修改部門 - PUT http://localhost:8080/depts  請求參數:{"id":1,"name":"研發部"}*/
    @PutMapping("/depts")
    public Result update(@RequestBody Dept dept){System.out.println("修改部門, dept=" + dept);deptService.update(dept);return Result.success();
    }

    2). Service層

    DeptService 中增加 update 方法。

    /*** 修改部門*/
    void update(Dept dept);

    DeptServiceImpl 中增加 update 方法。 由于是修改操作,每一次修改數據,都需要更新updateTime。所以,具體代碼如下:

    public void update(Dept dept) {//補全基礎屬性dept.setUpdateTime(LocalDateTime.now());//保存部門deptMapper.update(dept);
    }

    3). Mapper層

    DeptMapper 中增加 update 方法,具體代碼如下:

    /*** 更新部門*/
    @Update("update dept set name = #{name},update_time = #{updateTime} where id = #{id}")
    void update(Dept dept);

    代碼編寫完畢之后,我們就可以啟動服務,進行測試了。修改完成之后,我們可以看到最新的數據,如下:

    1. @RequestMapping

    到此呢,關于基本的部門的增刪改查功能,我們已經實現了。 我們會發現,我們在 DeptController 中所定義的方法,所有的請求路徑,都是 /depts 開頭的,只要操作的是部門數據,請求路徑都是 /depts 開頭。

    那么這個時候,我們其實是可以把這個公共的路徑 /depts 抽取到類上的,那在各個方法上,就可以省略了這個 /depts 路徑。 代碼如下:

    ?一個完整的請求路徑,應該是類上的 @RequestMapping 的value屬性 + 方法上的 @RequestMapping的value屬性。

    1. 日志技術

    1. 概述

    • 什么是日志?

      • 日志就好比生活中的日記,可以隨時隨地記錄你生活中的點點滴滴。

      • 程序中的日志,是用來記錄應用程序的運行信息、狀態信息、錯誤信息的。

    • 為什么要在程序中記錄日志呢?

      • 便于追蹤應用程序中的數據信息、程序的執行過程。

      • 便于對應用程序的性能進行優化。

      • 便于應用程序出現問題之后,排查問題,解決問題。

      • 便于監控系統的運行狀態。

      • ... ...

    • 之前我們編寫程序時,也可以通過 System.out.println(...) 來輸出日志,為什么我們還要學習單獨的日志技術呢?

    這是因為,如果通過 System.out.println(...) 來記錄日志,會存在以下幾點問題:

    • 硬編碼。所有的記錄日志的代碼,都是硬編碼,沒有辦法做到靈活控制,要想不輸出這個日志了,只能刪除掉記錄日志的代碼。

    • 只能輸出日志到控制臺。

    • 不便于程序的擴展、維護。

    1. 日志框架

    2. JUL這是JavaSE平臺提供的官方日志框架,也被稱為JUL。配置相對簡單,但不夠靈活,性能較差。

    3. Log4j一個流行的日志框架,提供了靈活的配置選項,支持多種輸出目標。

    4. Logback:基于Log4j升級而來,提供了更多的功能和配置選項,性能由于Log4j。

    5. Slf4j(Simple Logging Facade for Java)簡單日志門面,提供了一套日志操作的標準接口及抽象類,允許應用程序使用不同的底層日志框架。

    1. Logback入門

    1). 準備工作:引入logback的依賴(springboot中無需引入,在springboot中已經傳遞了此依賴)

    <dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.4.11</version>
    </dependency>

    ?2). 引入配置文件 logback.xml (資料中已經提供,拷貝進來,放在 src/main/resources 目錄下; 或者直接AI生成)

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration><!-- 控制臺輸出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度  %msg:日志消息,%n是換行符 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern></encoder></appender><!-- 日志輸出級別 --><root level="ALL"><appender-ref ref="STDOUT" /></root>
    </configuration>

    3). 記錄日志:定義日志記錄對象Logger,記錄日志

    public class LogTest {//定義日志記錄對象private static final Logger log = LoggerFactory.getLogger(LogTest.class);@Testpublic void testLog(){log.debug("開始計算...");int sum = 0;int[] nums = {1, 5, 3, 2, 1, 4, 5, 4, 6, 7, 4, 34, 2, 23};for (int i = 0; i < nums.length; i++) {sum += nums[i];}log.info("計算結果為: "+sum);log.debug("結束計算...");}}

    運行單元測試,可以在控制臺中看到輸出的日志,如下所示:

    1. Logback配置文件

    Logback日志框架的配置文件叫 logback.xml

    該配置文件是對Logback日志框架輸出的日志進行控制的,可以來配置輸出的格式、位置及日志開關等。

    常用的兩種輸出日志的位置:控制臺、系統文件。

    1). 如果需要輸出日志到控制臺。添加如下配置:

    <!-- 控制臺輸出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d 表示日期,%thread 表示線程名,%-5level表示級別從左顯示5個字符寬度,%msg表示日志消息,%n表示換行符 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern></encoder>
    </appender>

    2). 如果需要輸出日志到文件。添加如下配置:

    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">日志輸出文件的位置<file>./logs/talis.log</file><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 日志文件輸出的文件名, %i表示序號 --><FileNamePattern>D:/tlias-%d{yyyy-MM-dd}-%i.log</FileNamePattern><!-- 最多保留的歷史日志文件數量 --><MaxHistory>30</MaxHistory><!-- 最大文件大小,超過這個大小會觸發滾動到新文件,默認為 10MB --><maxFileSize>10MB</maxFileSize></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d 表示日期,%thread 表示線程名,%-5level表示級別從左顯示5個字符寬度,%msg表示日志消息,%n表示換行符 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern></encoder>
    </appender>

    3). 日志開關配置 (開啟日志(ALL),取消日志(OFF))

    <!-- 日志輸出級別 -->
    <root level="ALL"><!--輸出到控制臺--><appender-ref ref="STDOUT" /><!--輸出到文件--><appender-ref ref="FILE" />
    </root>
    1. <!-- 日志輸出級別 -->
      <root level="info"><!--輸出到控制臺--><appender-ref ref="STDOUT" /><!--輸出到文件--><appender-ref ref="FILE" />
      </root>

      Logback日志級別

    日志級別指的是日志信息的類型,日志都會分級別,常見的日志級別如下(優先級由低到高):

    日志級別說明記錄方式
    trace追蹤,記錄程序運行軌跡 【使用很少】log.trace("...")
    debug調試,記錄程序調試過程中的信息,實際應用中一般將其視為最低級別 【使用較多】log.debug("...")
    info記錄一般信息,描述程序運行的關鍵事件,如:網絡連接、io操作 【使用較多】log.info("...")
    warn警告信息,記錄潛在有害的情況 【使用較多】log.warn("...")
    error錯誤信息 【使用較多】log.error("...")

    可以在配置文件logback.xml中,靈活的控制輸出那些類型的日志。(大于等于配置的日志級別的日志才會輸出)?

    1. 案例日志記錄

      /*** 部門管理控制器*/
      @Slf4j
      @RequestMapping("/depts")
      @RestController
      public class DeptController {@Autowiredprivate DeptService deptService;/*** 查詢部門列表*///@RequestMapping(value = "/depts", method = RequestMethod.GET)@GetMappingpublic Result list(){//System.out.println("查詢部門列表");log.info("查詢部門列表");List<Dept> deptList = deptService.findAll();return Result.success(deptList);}/*** 根據id刪除部門 - delete http://localhost:8080/depts?id=1*/@DeleteMappingpublic Result delete(Integer id){//System.out.println("根據id刪除部門, id=" + id);log.info("根據id刪除部門, id: {}" , id);deptService.deleteById(id);return Result.success();}/*** 新增部門 - POST http://localhost:8080/depts   請求參數:{"name":"研發部"}*/@PostMappingpublic Result save(@RequestBody Dept dept){//System.out.println("新增部門, dept=" + dept);log.info("新增部門, dept: {}" , dept);deptService.save(dept);return Result.success();}/*** 根據ID查詢 - GET http://localhost:8080/depts/1*/@GetMapping("/{id}")public Result getById(@PathVariable Integer id){//System.out.println("根據ID查詢, id=" + id);log.info("根據ID查詢, id: {}" , id);Dept dept = deptService.getById(id);return Result.success(dept);}/*** 修改部門 - PUT http://localhost:8080/depts  請求參數:{"id":1,"name":"研發部"}*/@PutMappingpublic Result update(@RequestBody Dept dept){//System.out.println("修改部門, dept=" + dept);log.info("修改部門, dept: {}" , dept);deptService.update(dept);return Result.success();}
      }

      lombok中提供的@Slf4j注解,可以簡化定義日志記錄器這步操作。添加了該注解,就相當于在類中定義了日志記錄器,就下面這句代碼:

      private static Logger log = LoggerFactory. getLogger(Xxx. class);

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/web/88232.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/web/88232.shtml
    英文地址,請注明出處:http://en.pswp.cn/web/88232.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    Leetcode 3604. Minimum Time to Reach Destination in Directed Graph

    Leetcode 3604. Minimum Time to Reach Destination in Directed Graph 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3604. Minimum Time to Reach Destination in Directed Graph 1. 解題思路 這一題思路上就是一個廣度優先遍歷&#xff0c;我們不斷考察當前時間點以及位置…

    OpenXR Runtime切換工具-OpenXR-Runtime-Switcher

    在開發VR時&#xff0c;有時有多個設備&#xff0c;大家可能也會選擇不同的串流工具&#xff0c;OpenXR類似于默認瀏覽器&#xff0c;如果設置錯誤可能導致游戲無法串流。 推薦一個工具&#xff0c;可以設置默認的OpenXR工具。 OpenXR-Runtime-Switcher 對于沒有的設備&#…

    Opencv探索之旅:從像素變化到世界輪廓的奧秘

    在你已經能熟練地為圖像施展“降噪”、“縮放”等魔法之后&#xff0c;你的探索之旅來到了一個全新的領域。你可能會好奇&#xff1a;我們人類能輕易地識別出照片中杯子的邊緣、建筑的輪廓&#xff0c;那計算機是如何“看見”這些邊界的呢&#xff1f;僅僅依靠濾波和顏色變換&a…

    Ubuntu 22.04 + MySQL 8 無密碼登錄問題與 root 密碼重置指南

    背景場景 在 Ubuntu 系統中使用 apt 或 deb 包方式安裝 MySQL 8 時&#xff1a; 初次安裝后會自動初始化數據庫&#xff1b;但 沒有提示 root 初始密碼&#xff1b;導致 mysql -u root -p 無法登錄。 為了解決該問題&#xff0c;通常我們使用 --skip-grant-tables 方式跳過權限…

    題解:P13017 [GESP202506 七級] 線圖

    首先明白定義&#xff1a; 線圖 L(G)L(G)L(G) 的頂點對應原圖 GGG 的邊&#xff0c;當且僅當原圖中的兩條邊有公共頂點時&#xff0c;對應的線圖頂點之間有一條邊。 不難想到&#xff0c;對于原圖中的每個頂點 vvv&#xff0c;其度數 d(v)d(v)d(v) 對應的邊集可以形成 (d(v)2)\…

    c++ duiLib環境集成2

    繼續上一篇&#xff0c;現在需要把控制臺隱藏&#xff0c;只顯示調用duiLib框架顯示的窗口。右鍵項目 → 屬性 → 鏈接器 → 系統 → ?子系統?改為 窗口(/SUBSYSTEM:WINDOWS)。原來是這樣&#xff1a;修改為&#xff1a;運行報錯&#xff1a;需要修改入口函數為WinMain。如下…

    常見的網絡攻擊方式及防御措施

    常見的網絡攻擊方式及防御措施&#xff1a;全面解析網絡安全威脅 前言肝文不易&#xff0c;點個免費的贊和關注&#xff0c;有錯誤的地方請指出&#xff0c;看個人主頁有驚喜。 作者&#xff1a;神的孩子都在歌唱在信息化高速發展的今天&#xff0c;網絡安全威脅無處不在&#…

    JavaScript 中導入模塊時,確實不需要顯式地寫 node_modules 路徑。

    1. 正確的導入語法在 Webpack、Vite 等打包工具中&#xff0c;node_modules 目錄是默認的模塊搜索路徑&#xff0c;因此直接寫包名即可&#xff1a;// ? 正確&#xff1a;直接使用包名import nprogress/nprogress.css;// ? 錯誤&#xff1a;不需要顯式寫 node_modules 路徑im…

    ELK Stack技術棧

    文章目錄一、日志收集所解決的問題二、Elastic Stack 組件介紹2.1 Elasticsearch2.2 Logstash2.3 Kibana2.4 Filebeat beats三、ELK Stack集群安裝3.1 安裝JAVA環境&#xff08;所有ES節點&#xff09;3.2 安裝ES集群3.2.1 ES單節點部署3.2.2 ES JAVA調優&#xff1a;堆(heap)內…

    大騰智能國產 3D CAD:設計自由度拉滿,數據安全鎖死

    在智能制造與數字化轉型的浪潮中&#xff0c;大騰智能CAD作為一款自主研發的三維計算機輔助設計軟件&#xff0c;憑借其從概念設計到制造落地的全流程覆蓋能力&#xff0c;正成為國產工業設計軟件領域的新銳力量。軟件深度融合先進建模技術與工程實踐需求&#xff0c;為機械制造…

    ubuntu 操作記錄

    1&#xff1a;安裝minicom 1: sudo apt-get install minicom minicom -s 2&#xff1a;Ctrl Z C 的區別 ctrlz的是將任務中斷,但是此任務并沒有結束,他仍然在進程中他只是維持掛起的狀態,用戶可以使用fg/bg操作繼續前臺或后臺的任務,fg命令重新啟動前臺被中斷的任務,bg命令…

    深度剖析:向70歲老系統植入通信芯片——MCP注入構建未來級分布式通信

    > 如何讓老舊系統重獲新生?協議注入技術是關鍵。 ## 一、當遺留系統遇上分布式未來:一場艱難的對話 想象一下:你負責維護一套誕生于20年前的單體式銀行核心系統,它像一位固執的70歲老人,使用著陳舊的TCP自定義協議。這時業務部門要求實現與云原生風險分析引擎的實時…

    針對 SSD 固態硬盤的安全擦除 Secure Erase

    SSD 的安全擦除&#xff08;Secure Erase&#xff09;用于永久刪除存儲介質上的數據&#xff0c;以及在驅動器性能開始明顯下降至低于標稱值時恢復其速度。Secure Erase 可以解決的問題核心當 SSD 開始運行緩慢&#xff08;讀寫數據變差&#xff09;時&#xff0c;這里有許多可…

    Three.js搭建小米SU7三維汽車實戰(3)軌道控制器

    往期內容&#xff1a; Three.js搭建小米SU7三維汽車實戰&#xff08;1&#xff09;搭建開發環境 Three.js搭建小米SU7三維汽車實戰&#xff08;2&#xff09;場景搭建 軌道控制器 軌道控制器可以改變相機在空間坐標系中的位置 進而方便從不同的角度觀察物體 1. 軌道控制器響…

    C++樹狀數組詳解

    C樹狀數組深度解析 第1章 引言&#xff1a;為什么需要樹狀數組 1.1 動態序列處理的挑戰 在現代計算機科學中&#xff0c;我們經常需要處理動態變化的序列數據&#xff0c;這類數據具有以下特點&#xff1a; 實時更新&#xff1a;數據點會隨時間不斷變化頻繁查詢&#xff1a;需要…

    TeamT5-ThreatSonar 解決方案:構建智能動態的 APT 與勒索軟件防御體系

    一、核心功能深度解析&#xff1a;從威脅狩獵到自動化響應的閉環能力 &#xff08;一&#xff09;威脅狩獵&#xff1a;主動挖掘潛伏性攻擊的 “數字偵探” 多層級威脅識別引擎&#xff1a; 靜態特征匹配&#xff1a;內置超 1000 種 APT 后門簽名&#xff08;如 Regin、Duqu 等…

    C#基礎篇(10)集合類之列表

    C# 中的列表(List)詳解列表(List)概述在C#中&#xff0c;List<T>是System.Collections.Generic命名空間中的一個泛型集合類&#xff0c;它提供了動態大小的數組功能&#xff0c;可以存儲指定類型的元素。列表的創建與初始化// 創建一個空列表 List<int> numbers n…

    SpringBoot訂單模塊核心接口設計與實現

    目錄 一、 管理端接口實現 (后臺管理系統) 一、訂單搜索 (高權重 - 核心管理功能) 1.Controller (OrderController): 2.Service (OrderService): 3.ServiceImpl (OrderServiceImpl): 1.使用MyBatis分頁插件PageHelper 2.基礎數據查詢 4.Mapper (OrderMapper): 5.Mapper …

    EXCEL鏈接模板無法自動鏈接到PowerBI?試試這個方法

    在使用EXCEL鏈接模板連接PowerBI時&#xff0c;你有沒有遇到如圖所示的提示呢&#xff1a;下面我來分享一下&#xff0c;出現彈框的原因及解決方法&#xff1a;首先我們先看一下這個英文翻譯&#xff0c;意思就是說&#xff0c;我們只能使一個PowerBI文件處于打開的狀態&#x…

    最新全開源禮品代發系統源碼/電商快遞代發/一件代發系統

    簡介&#xff1a;最新全開源禮品代發系統源碼/電商快遞代發/一件代發系統測試環境&#xff1a;Nginx PHP7.2 MySQL5.6圖片&#xff1a;