前兩天忙着寫開題報告,沒有來得及作項目,今天繼續研究一下這個項目。前端
上次研究到後端的DAO層,研究了一下後端和數據庫交互的過程,service層封裝了一些DAO層的函數,沒有什麼太多的東西,今天研究一下controller層和前端的代碼。vue
首先,一個典型的controller層代碼是這樣的:java
package... import ... import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController public class LibraryController { @Autowired BookService bookService; @CrossOrigin @GetMapping("/api/books") public List<Book> list() throws Exception { return bookService.list(); } ... }
按照慣例,首先看一下各個註解:web
@RestController:至關於@ResponseBody+@Controller註解面試
@ResponseBody:@ResponseBody的做用實際上是將java對象轉爲json格式的數據。將controller的方法返回的對象經過適當的轉換器轉換爲指定的格式以後,寫入到response對象的body區。spring
@Controller:用於標記在一個類上,使用它標記的類就是一個SpringMVC Controller對象。分發處理器將會掃描使用了該註解的類的方法,並檢測該方法是否使用了@RequestMapping註解。@Controller只是定義了一個控制器類,而使用@RequestMapping註解的方法纔是真正處理請求的處理器。chrome
@Autowired:自動裝配,和控制反轉什麼的有關係,這個這裏不展開了。數據庫
@CrossOrigin:跨域,這個問題大概就是說先後端不用一個服務器,瀏覽器對這種行爲會出於安全考慮不容許跨域訪問,因此須要設置一下,具體細節比較瑣碎,這裏不展開了。json
@GetMapping:SpringMVC之前版本的@RequestMapping,到了新版本被下面新註釋替代,至關於增長的選項:@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping,從命名約定咱們能夠看到每一個註釋都是爲了處理各自的傳入請求方法類型,即@GetMapping用於處理請求方法的GET類型,@PostMapping用於處理請求方法的POST類型等。若是咱們想使用傳統的@RequestMapping註釋實現URL處理程序,那麼它應該是這樣的:@RequestMapping(value = "/get/{id}", method = RequestMethod.GET),新方法能夠簡化爲:@GetMapping("/get/{id}")。後端
後面的函數中還有一些其餘的註解,一塊兒看一下:
@CrossOrigin @PostMapping("/api/books") public Book addOrUpdate(@RequestBody Book book) throws Exception { bookService.addOrUpdate(book); return book; } @CrossOrigin @PostMapping("/api/delete") public void delete(@RequestBody Book book) throws Exception { bookService.deleteById(book.getId()); } @CrossOrigin @GetMapping("/api/categories/{cid}/books") public List<Book> listByCategory(@PathVariable("cid") int cid) throws Exception { if (0 != cid) { return bookService.listByCategory(cid); } else { return list(); } } @CrossOrigin @GetMapping("/api/search") public List<Book> searchResult(@RequestParam("keywords") String keywords) { // 關鍵詞爲空時查詢出全部書籍
if ("".equals(keywords)) { return bookService.list(); } else { return bookService.Search(keywords); } }
@RequestBody:@RequestBody主要用來接收前端傳遞給後端的json字符串中的數據的(請求體中的數據的);GET方式無請求體,因此使用@RequestBody接收數據時,前端不能使用GET方式提交數據,而是用POST方式進行提交。
@PathVariable是spring3.0的一個新功能:接收請求路徑中佔位符的值
@RequestParam:@RequestParam有三個配置參數:required
表示是否必須,默認爲true,
必須。defaultValue
可設置請求參數的默認值。value
爲接收url的參數名(至關於key值。這個好像用法比較複雜,以後再仔細看一下。
首先咱們登陸進入系統,我這裏先後端交互使用的8443端口,後續測試也在8443端口上進行。
能夠看到發送了一個請求報文,收到了一個回覆報文,回覆報文的內容是一些json鍵值對,下面放了一個樣例:
{ "id": 69, "category": { "id": 1, "name": "文學" }, "cover": "https://i.loli.net/2019/04/10/5cad63931ce27.jpg", "title": "謀殺狄更斯", "author": "[美] 丹·西蒙斯 ", "date": "2019-4", "press": "上海文藝出版社", "abs": "「狄更斯的那場意外災難發生在1865年6月9日,那列搭載他的成功、平靜、理智、手稿與情婦的火車一路飛馳,迎向鐵道上的裂隙,忽然觸目驚心地墜落了。」" }
與Pojo中的book和category徹底對應,這裏放一下代碼。
public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") int id; //把 category 對象的 id 屬性做爲 cid 進行了查詢
@ManyToOne @JoinColumn(name="cid") private Category category; String cover; String title; String author; String date; String press; String abs; ... } public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") int id; String name; ... }
前端的EditForm.vue中有這麼一段代碼顯然是和這個相對應的,這裏咱們先不去管這個:
咱們接着測試一下其餘方法:
構造了一個post報文,返回200表示成功了,有趣的是雖然傳入了id,可是因爲id是自增的,並無起做用,再使用get方法查詢一下。
下一個方法表示要刪除一本書,咱們從代碼這個大概知道是拿到一個json對象,轉換成javabean的book,而後根據id把書刪除了,咱們應該傳入一個json對象的書,試一下:
成功了,可是有趣的是在chrome瀏覽器中,對於前端的行爲不徹底是這樣:
根據網上的教程,F12打開後,在Network下勾選Preserve log就能夠監控報文。
咱們打開後刪除一本書。
雙擊點開後發現Request只傳遞了id,由於原來函數裏只須要id,因此只傳id是徹底沒毛病的,這個我在postman裏面測過了,就不發上來了:
這個就是拿一個從url路徑裏面拿一個參數,測試了一下不存在的分類號,不會報錯,而是給一個空集合。
這個沒太看懂參數是怎麼傳遞的,咱們用Chrome看一下。
是經過在路徑後面加上「?keyword=關鍵詞」實現的。
去postman裏面試一下,成功!
今天的探索到這裏就結束了,後面再看一下前端代碼的邏輯,這個交互過程就比較清楚了。