1、准備知識:
1)需要掌握的知識:
Java基礎,JavaWeb開發基礎,Spring基礎(沒有Spring的基礎也可以,接觸過Spring最好),ajax,Jquery,Mybatis。
2)項目結構介紹:
-
crud-core:這里面存放的是項目的一些公共的東西,如工具類util包、自定義異常類、枚舉類型等。
-
crud-sys:這里面主要是和數據庫操作有關系的文件。實體類entity、在沒有使用Mybatis情況下有repository或dao實體操作類、使用Mybatis情況下有Mapper類、Service類和Service的實現類都在sys子模塊下。
-
實體類entity:是對應於數據庫的一些實體類,是所有數據操作的基礎。
-
repository或dao:是對實體類進行增刪改查操作的類,是直接和數據庫進行交互的類,這兩個使用哪個都可以,完全看個人愛好。
-
Mapper:是Mybatis下與數據庫進行交互實現實體類的操作,和repository和dao相似。
-
Service:是在前端Controller和后端Dao層之間進行協調的類,用於接收Controller傳遞過來的信息,並調用Dao層對數據庫進行操作后返回信息給Controller。
-
crud-web:是整個項目中唯一一個和外部網頁交互的模塊。包含Controller,啟動類等。
-
Controller:接收用戶從前端發送的request請求,指定請求的路徑以及返回信息給前台頁面。
-
pom.xml文件:每個項目都有自己的pom.xml文件,里面包含項目和父項目的信息,以及項目所依賴的所有依賴文件,在pom.xml文件中寫入依賴后,項目會自動從本地倉庫中查找需要的jar包,如果沒有則從遠程倉庫中下載后存入本地倉庫,這樣就省去了下載jar包的步驟。
-
application.properties文件:這里面寫着項目中的所有配置,包括數據庫的連接、mybatis的配置,自定義配置項、項目端口等等各種配置。
下面開始實現一個簡單的學生的添加
2、創建實體類
在crud-sys子項目中創建entity文件夾並創建和數據庫相對應的Student類及其get,set函數。
public class Student { /** 學生id */ private String Name; /** 學生英語成績 */ private Integer English; /** 學生數學成績 */ private Integer Math; /** 學生計算機成績 */ private Integer Computer; public String getName () { return Name; } public void setId(String Name) { this.Name = Name; } public Integer getEnglish() { return English; } public void setEnglish(Integer english) { English = english; } public Integer getMath() { return Math; } public void setMath(Integer math) { Math = math; } public Integer getComputer() { return Computer; } public void setComputer(Integer computer) { Computer = computer; } }
3、集成Mybatis
這個項目中繼承了Mybatis,所以在進行數據庫操作之前我們需要進行Mybatis的相關配置以及數據庫的連接操作。
1)查找依賴包
進入https://mvnrepository.com/網站,輸入mybatis查詢mybatis依賴包:
這里選擇org.mybatis.spring.boot里的mybatis-spring-boot-starter:
點擊之后選擇版本,這里我不習慣選擇太新的也不喜歡太舊的版本,所以一般會在稍微新的版本中選擇用戶數最多的那一個,比如mybatis我選擇2.0.1
點擊進去之后復制依賴:
2)注入依賴並下載jar包
第一步之后,將文本復制到crud-web子項目的pom.xml文件中,在<dependencies>標簽中加入剛才復制的文本。
此時右下角出現Import changes和Enable auto import,這里可以選擇后者,以后修改pom.xml文件后,項目會自動導入jar包。
3)連接數據庫
首先還是要通過上面的方法添加mysql的依賴到pom.xml文件中
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency>
在crud-web的resource文件夾下的application.properties文件中配置連接信息:
這些和普通的web開發中的DBUtil的寫法大同小異。
4)配置mybatis
同樣在application.properties文件配置mybatis的映射文件路徑
mybatis.mapper-locations=classpath:/mapping/*.xml
這句話的意思是mybatis的映射文件存在於classpath(classpath就是生成target目錄后classes文件所在目錄)的mapping目錄下以.xml結尾的文件。
4、編寫Mapper類
1)創建文件
在crud-sys子項目下新建mapper文件夾,其下新建StudentMapper接口:
-
這里要注意,在Mapper接口上需要加入@Compent注解,表示這是一個和Bean類似的實體。
-
@Component:泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。
2)編寫函數
Mapper類中主要寫對實體的操作函數的定義,這里我們先定義一個添加函數。
添加代碼:public void add(Student student);
5、編寫映射文件Mapping文件
1)創建文件
在resource文件夾下創建mapping文件夾,在其下創建StudentMapping.xml文件。
2)添加xml頭
在xml文件中寫入mybatis映射文件需要的頭,可以在網上搜索mybatis映射文件頭文件,也可進入官網去找
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3)設置所映射的接口
設置這個xml文件對應的是哪個接口類中的函數。
添加<mapper>標簽,在標簽中配置namespace為接口類所在的路徑
4)編寫相應的函數所對應的SQL
Mybatis提供了insert、update、delete和select分別對應添加、更改、刪除和查詢操作,這里我們用到的是insert標簽。
<insert id="add" parameterType="com.dingcheng365.crudsys.entity.Student ">
</insert>
-
id:id的值為所對應的Mapper接口中的函數的名稱,必須完全一致。
-
parameterType:參數類型,如果沒有參數或兩個以上參數,可不寫改屬性,如果是一個參數,需要寫上參數的類型,最好將包名加上,如String類型寫java.lang.String,Map類型寫java.util.Map
-
resultType:這個在這個例子中沒有體現。表示的是函數的返回值類型,如果為void可不寫該屬性。這里需要注意的是:resultType表示每一個元素的值,例如我們要進行查詢,返回值是List<Student>,因為查詢結果不一定是一個學生滿足條件,但是這時候resultType需要填寫的是Student類而非List。
如果字段多的話添加語句會很長很難寫,這里介紹一個快速且簡單的辦法:
在Navicat中隨便選中一行,右鍵復制為insert語句:
粘貼后效果:
INSERT INTO `test`.`student` (`Name`, `English`, `Math`, `Computer`) VALUES ('zhangsan', '69', '86', '77');
這時候只需要修改后面的參數即可。
將語句粘貼到insert標簽中,同時修改參數,使用#{}中間加上參數的名稱:
6、編寫Service層
1)編寫service接口類
在crud-sys下創建service文件夾,在其下創建StudentService接口類,里面寫入函數,一般會和Mapper類中的函數相似,可能會返回值不同。
2)編寫service實現類
在service文件夾下創建impl文件夾,在其下創建StudentServiceImpl類實現StudentSerivce接口。
這里需要注意的是:Service實現類上面需要加入@Service注解。在這個類中需要使用@Autowired注解注入studentMapper對象。
-
@Autowired:自動導入依賴的bean
-
@Service:一般用於修飾service層的組件
然后編寫代碼,調用studentMapper的添加函數,添加成功后返回1,如果失敗則返回0;
@Autowired private StudentMapper studentMapper; @Override public int add(Student student) { try { studentMapper.add(student); return 1; } catch (Exception e) { return 0; } }
至此,crud-sys子項目中所需要實現的功能已經編寫完畢,接下來就是和網頁的交互了。
7、編寫頁面
SpringBoot可以識別出resources文件夾下的static及其子文件夾下的文件,如果需要自定義文件夾,則需要在配置文件中配置。
1)創建文件並寫入元素
在curd-web子目錄的templates文件夾下創建addstudent.html並寫入表單元素。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>學生添加</title> </head> <body> <form id="studentinfo"> <table> <tr> <td>姓名:</td> <td><input type="text" name="name" id="name"></td> </tr> <tr> <td>英語成績:</td> <td><input type="text" name="English" id="English"></td> </tr> <tr> <td>數學成績:</td> <td><input type="text" name="Math" id="Math"></td> </tr> <tr> <td>計算機成績:</td> <td><input type="text" name="Computer" id="Computer"></td> </tr> <tr> <td colspan="2"> <button id="add-student-btn" type="button">提交</button> </td> </tr> </table> </form> </body> </html>
2)表單驗證
使用jquery-validate對表單輸入的值進行驗證,導入jquery.min.js和jquery-validate.min.js后進行編寫。
// 表單驗證 userInfoValidate = $('#userInfo').validate({ rules: { name: { required: true }, English: { required: true }, Math: { required: true }, Computer: { required: true } }, messages: { name: { required: '姓名不能為空' }, English: { required: '英語成績不能為空' }, Math: { required: '數學成績不能為空' }, Computer: { required: '計算機成績不能為空' } }, errorElement: 'small', errorPlacement: function(error, element) { // 在error 上添加 `invalid-feedback` class error.addClass('invalid-feedback'); element.parent().append(error); }, highlight: function(element) { $(element) .addClass('is-invalid') .removeClass('is-valid'); }, unhighlight: function(element, errorClass, validClass) { var $valid = $(element); if (!validClass) { $valid.removeClass('is-invalid is-valid'); } else { $valid.addClass('is-valid').removeClass('is-invalid'); } }, submitHandler: function (form) { // 確認登錄時刪除存儲標簽頁對象 // TODO: KEY值請參考`site-configs.js`文件中配置的`tabSittings`的值 window.sessionStorage.removeItem('admui.contentTabs'); } });
-
通過id調用validate函數,示例中的$('#userinfo').validate({..})
-
rules:表示表單驗證的規則,rules中的第一層的子元素對應的是input標簽的name而非id值。
-
子元素驗證,在子元素中寫入需要進行的驗證,常用的有required:true表示不可為空,false表示可為空;minlength:設置輸入的最短長度;maxlength:輸入的最長長度;email:true表示必須輸入正確的電子郵件;digtis:true表示必須輸入整數等。
-
message:自定義提示信息,與rules中一一對應,表示不滿足規則時提示的信息。
-
errorElement:用什么標簽標記錯誤,默認是label
-
errorPlacement:自定義錯誤放置的位置
-
highlight:可以給未通過驗證的元素加效果、閃爍等。
-
submitHandler:所有驗證通過后執行的函數
效果圖:
3)Ajax實現和Controller的交互
$("#add-student-btn").on('click', function () { $.ajax({ url: '/student/addstudent',//請求的地址 type: 'post',//請求類型:GET、POST、DELETE、PUT data: { //向請求傳遞的數據 "name": $("#name").val(), "English": $("#English").val(), "Math": $("#Math").val(), "Computer": $("#Computer").val() }, async: true, //是否異步,默認為true success: function (e) { //請求成功的回調函數,e為后台傳遞過來的信息 console.log(e) }, error: function (e) { //請求失敗的回調函數 console.log("ajax請求失敗"); } }); });
通過提交按鈕的點擊事件,向student/addstudent發送POST請求,傳遞的數據為用戶輸入的信息,請求后將后台返回的信息打印到控制台。
8、編寫Controller層
Controller是與前台進行直接交互的模塊,所以在crud-web子項目中創建包controller,在其下創建StudentController類。
-
Controller類都需要加入注解@Controller,表示這是一個控制類
-
Controller類上面的@RequestMapping中的參數表示這個Controller中的所有映射路徑都是以這個參數開頭
-
如果Controller中一個函數需要返回json數據類型,則需要加入@ResponseBody注解,通常用來返回JSON數據或者是XML,一般我們返回字符串類型時也需要使用這個注解
-
慎用@RestController,@RestController是@ResponseBody和@Controller的結合,當你返回的類型不是json等的時候,使用這個會將你返回的數據自動轉換成json類型返回。比如你需要返回一個頁面的時候就不能使用這個。
-
Controller返回頁面也是一個很重要的點,可以參考我的博客:https://www.cnblogs.com/guo-xu/p/11203740.html
-
這里會發現一個錯誤:service無法進行注入。原因是service所在的路徑必須是啟動類所在的路徑的子目錄。修改目錄結構后問題得到解決。
@Controller @RequestMapping("/student") public class StudentController { @Autowired private StudentService studentService; @RequestMapping("/addstudent") public String addstudent(Student student) { return String.valueOf(studentService.add(student)); } }
由於前台傳遞數據的時候所傳遞的json對象與Student對象的屬性一一對應,所以在Controller接收的時候可以直接在參數中書寫Student對象,系統會進行自動轉換。
9、控制顯示頁面
我們需要編寫IndexController來實現默認頁面的顯示,在controller文件夾下創建IndexController文件,寫入根路徑的映射:
@RequestMapping("/") public ModelAndView index() { return new ModelAndView("addstudent.html"); }
如果發現設置完畢后啟動項目顯示404的問題,可以參考博客:https://www.cnblogs.com/guo-xu/p/11203740.html里面詳細闡述了SpringBoot如何返回頁面的問題
10、啟動項目
在CrudWebApplication.java下右鍵Run CrudWebApplication,發現啟動錯誤:
這個問題產生的原因是雖然我們在Mapper類上面都加入了@Compent注解,但是項目並不知道有Mapper,不知道需要去加載Mapper,所以我們需要在啟動類上方加入@MapperScan注解,參數為basePackages = {"com.dingcheng365.crud.sys.mapper"},加入之后在項目啟動的時候就會自動掃描這個包中的所有Mapper類。
@MapperScan(basePackages = {"com.dingcheng365.crud.sys.mapper"})
重新啟動項目:
出現這個提示表示項目啟動成功,端口號為8080,如果想修改項目的端口號,可以修改application.properties文件加入 server.port=端口號 配置項。
11、測試
啟動后輸入localhost:8080,由於我們之前配置了根路徑映射的函數,是返回addstudent.html頁面,所以會出現這個頁面。
輸入信息后點擊提交,發現添加失敗,查看控制台報錯:
這個問題的解決辦法可參考博客:https://www.cnblogs.com/guo-xu/p/11177028.html
最簡單的解決辦法就是在連接語句中加入serverTimezone=GMT
加入之后重新啟動並輸入信息后點擊提交,發現數據庫中存在新添加的信息,至此學生信息添加的功能實現完畢。
實現了這個功能之后,刪除、修改、查詢之類的功能基本大同小異,這里我只說幾點需要注意的地方。
12、其他問題
1)刪除時刪除單個信息
如果刪除單個信息我們一般會使用/delete/id這樣的路徑,也就是直接將id值傳遞到路徑中,並且不使用?id=1這種格式,這樣在Controller類中接收的時候有所不同,下面是實例:
@RequestMapping("/deletestudent/{id}") @ResponseBody public String deleteUser(@PathVariable("id") String id) { return studentService.delete(id); }
可以看到,需要加入@PathVariable注解,參數為需要讀取的值的名稱,而且在RequestMapping中寫的路徑id值不確定需要加上大括號。
2)刪除時刪除多個信息(批量刪除)
批量刪除的時候,我們在前台傳遞的肯定是一個數組,里面包含要刪除的多個id值,這個在Controller接受的時候也有所不同,由於是數組的問題。下面是實例:
前台:
$.ajax({ url: "/user/deleteUsers", type: "post", data: { ids": ids }, success: function (e) { if (e == "success") { toastr.success("刪除成功"); } else { toastr.error("刪除失敗,請稍后重試"); } }, error: function (e) { console.log(e); } });
后台接收:
@RequestMapping(value = "/deleteUsers") @ResponseBody public String deleteUsers(@RequestParam("ids[]") List<String> ids,) { …… }
在進行數組接受的時候,需要在@RequestParam注解中加入名稱加上[]的參數才能正確接收。
3)前台傳遞過來的對象並沒有和后台相對應
這個實例中,我們從前台接收的對象的參數正好和后台存在的Student類相對應,所以我們在后台直接用Student對象接受,那如果不一致的時候該怎么辦?有兩種情況:
- 參數少的時候
當參數個數比較少,2-4個左右時,我們可以直接在接收的函數中一個一個羅列出來,對應關系使用@RequestParam來進行區分。
- 參數多的時候
當參數個數比較多時,我個人推薦一個類型——Map類,這個類真的是百用不爽,由於他和json結構上的相似性,導致這個類的用途非常之大。在進行數據查詢的時候如果我們要查詢的結果並不是某一個類的集合,這個時候用Map對象也可以很完美的解決問題。