5. 修改部門
對于任何業務的修改功能來說,一般都會分為兩步進行:查詢回顯、修改數據。
5.1 查詢回顯
5.1.1 需求
當我們點擊 "編輯" 的時候,需要根據ID查詢部門數據,然后用于頁面回顯展示。
5.1.2 接口描述
參照參照課程資料中提供的接口文檔。 部門管理
-> 根據ID查詢
5.1.3 思路分析
明確了根據ID查詢部門的需求之后,再來梳理一下實現該功能時,三層架構每一層的職責:
了解了需求之后,我們再看看接口文檔中,關于根據ID查詢部門的接口的描述,然后根據接口文檔進行服務端接口的開發 。
5.1.4 路徑參數接收
/depts/1
,/depts/2
這種在url中傳遞的參數,我們稱之為路徑參數。 那么如何接收這樣的路徑參數呢 ?
路徑參數:通過請求URL直接傳遞參數,使用{…}來標識該路徑參數,需要使用 @PathVariable
獲取路徑參數。如下所示:
如果路徑參數名與controller方法形參名稱一致,@PathVariable
注解的value屬性是可以省略的。
5.1.5 代碼實現
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);
代碼編寫完畢之后,我們就可以啟動服務,進行測試了。
5.2 修改數據
5.2.1 需求
查詢回顯回來之后,就可以對部門的信息進行修改了,修改完畢之后,點擊確定,此時,就需要根據ID修改部門的數據。
了解了需求之后,我們再看看接口文檔中,關于修改部門的接口的描述,然后根據接口文檔進行服務端接口的開發 。
5.2.2 接口描述
參照參照課程資料中提供的接口文檔。 部門管理
-> 修改部門
5.2.3 思路分析
參照接口文檔,梳理三層架構每一層的職責:
通過接口文檔,我們可以看到前端傳遞的請求參數是json格式的請求參數,在Controller的方法中,我們可以通過 @RequestBody
注解來接收,并將其封裝到一個對象中。
5.2.4 代碼實現
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);
代碼編寫完畢之后,我們就可以啟動服務,進行測試了。
修改完成之后,我們可以看到最新的數據,如下:
5.2.5 @RequestMapping
到此呢,關于基本的部門的增刪改查功能,我們已經實現了。 我們會發現,我們在 DeptController
中所定義的方法,所有的請求路徑,都是 /depts
開頭的,只要操作的是部門數據,請求路徑都是 /depts
開頭。
那么這個時候,我們其實是可以把這個公共的路徑 /depts
抽取到類上的,那在各個方法上,就可以省略了這個 /depts
路徑。 代碼如下:
一個完整的請求路徑,應該是類上的 @RequestMapping 的value屬性 + 方法上的 @RequestMapping的value屬性。
6. 日志技術
6.1 概述
- 什么是日志?
-
- 日志就好比生活中的日記,可以隨時隨地記錄你生活中的點點滴滴。
- 程序中的日志,是用來記錄應用程序的運行信息、狀態信息、錯誤信息的。
- 為什么要在程序中記錄日志呢?
-
- 便于追蹤應用程序中的數據信息、程序的執行過程。
- 便于對應用程序的性能進行優化。
- 便于應用程序出現問題之后,排查問題,解決問題。
- 便于監控系統的運行狀態。
- ... ...
- 之前我們編寫程序時,也可以通過
System.out.println(...)
來輸出日志,為什么我們還要學習單獨的日志技術呢?
這是因為,如果通過 System.out.println(...)
來記錄日志,會存在以下幾點問題:
- 硬編碼。所有的記錄日志的代碼,都是硬編碼,沒有辦法做到靈活控制,要想不輸出這個日志了,只能刪除掉記錄日志的代碼。
- 只能輸出日志到控制臺。
- 不便于程序的擴展、維護。
所以,在現在的項目開發中,我們一般都會使用專業的日志框架,來解決這些問題。
6.2 日志框架
- JUL:這是JavaSE平臺提供的官方日志框架,也被稱為JUL。配置相對簡單,但不夠靈活,性能較差。
- Log4j:一個流行的日志框架,提供了靈活的配置選項,支持多種輸出目標。
- Logback:基于Log4j升級而來,提供了更多的功能和配置選項,性能由于Log4j。
- Slf4j:(Simple Logging Facade for Java)簡單日志門面,提供了一套日志操作的標準接口及抽象類,允許應用程序使用不同的底層日志框架。
6.3 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("結束計算...");}}
運行單元測試,可以在控制臺中看到輸出的日志,如下所示:
我們可以看到在輸出的日志信息中,不僅輸出了日志的信息,還包括:日志的輸出時間、線程名、具體在那個類中輸出的。
6.4 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"><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>
6.5 Logback日志級別
日志級別指的是日志信息的類型,日志都會分級別,常見的日志級別如下(優先級由低到高):
表格 還在加載中,請等待加載完成后再嘗試復制
可以在配置文件logback.xml
中,靈活的控制輸出那些類型的日志。(大于等于配置的日志級別的日志才會輸出)
<!-- 日志輸出級別 -->
<root level="info"><!--輸出到控制臺--><appender-ref ref="STDOUT" /><!--輸出到文件--><appender-ref ref="FILE" />
</root>
6.6 案例日志記錄
/*** 部門管理控制器*/
@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);