Data JPA 和 Thymeleaf 綜合實踐

1    第3-8課:Spring Data JPA 和 Thymeleaf 綜合實踐

在前面課程中,咱們學習了 Spring Boot Web 開發、JPA 數據庫操做、Thymeleaf 和頁面交互技術,這節課綜合這些內容作一個用戶管理功能,包括展現用戶列表(分頁)、添加用戶、修改用戶和刪除用戶。有人說程序員的一輩子都是在增、刪、改、查,這句話不必定全對,但也有必定的道理,相比於這句話,我更認同的是這句:程序員的技術學習都是從增、刪、改、查開始的。css

這節課將介紹如何使用 JPA 和 Thymeleaf 作一個用戶管理功能。html

1.1    配置信息

1.1.1  添加依賴

pom 包裏面添加 JPA 和 Thymeleaf 的相關包引用。前端

<dependency>
<groupId></groupId>   org.springframework.boot
<artifactId></artifactId>   spring-boot-starter-web
</dependency>
<dependency>
<groupId></groupId>   org.springframework.boot
<artifactId></artifactId>   spring-boot-starter-Thymeleaf
</dependency>
<dependency>
<groupId></groupId>   org.springframework.boot
<artifactId></artifactId>   spring-boot-starter-data-Jpa
</dependency>
<dependency>
<groupId></groupId>   mysql
<artifactId></artifactId>   mysql-connector-java
</dependency>

1.1.2  配置文件

在 application.properties 中添加配置:java

testtruetruespring.datasource.url=jdbc:mysql://localhost:3306/?serverTimezone=UTC&useUnicode=&characterEncoding=utf-8&useSSL=
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
truespring.jpa.show-sql=
 
falsespring.thymeleaf.cache=

其中,spring.Thymeleaf.cache=false 是關閉 Thymeleaf 的緩存,否則在開發過程當中修改頁面不會馬上生效須要重啓,生產可配置爲 true。mysql

在項目 resources 目錄下會有兩個文件夾:static 目錄用於放置網站的靜態內容如 css、js、圖片;templates 目錄用於放置項目使用的頁面模板。git

1.1.3  啓動類

啓動類須要添加 Servlet 的支持:程序員

@SpringBootApplication
publicclass JpaThymeleafApplication extends SpringBootServletInitializer {
@Override   
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)    {
return       application.sources(JpaThymeleafApplication.class);
    }
 
public static void main(String[] args) throws Exception    {
        SpringApplication.run(JpaThymeleafApplication.class, args);
    }
}

添加 SpringBootServletInitializer 是爲了支持將項目打包成獨立的 war 在 Tomcat 中運行的狀況。github

1.2    數據庫層

實體類映射數據庫表:web

@Entity
publicclass User {
@Id   
@GeneratedValue   
privatelong   id;
@Columnfalsetrue   (nullable =, unique =)
private   String userName;
@Columnfalse   (nullable =)
private   String passWord;
@Columnfalse   (nullable =)
privateint   age;
@Columnfalse   (nullable =)
private   Date regTime;
//省略getter settet方法   
}

繼承 JpaRepository 類會自動實現不少內置的方法,包括增、刪、改、查,也能夠根據方法名來自動生成相關 SQL。spring

publicinterface UserRepository extends JpaRepository<User, Long> {
@Query"select u from User u"   ()
Page<User> findList(Pageable pageable)   ;
User findById(long id)   ;
User findByUserName(String userName)   ;
void deleteById(Long id)   ;
}

Repository 內編寫咱們須要的 SQL 和分頁查詢。

1.3    實現一個添加功能

在處理前端業務的時候通常是使用 param 結尾的參數來處理,在項目下新建 param 包,在 param 包下建立 UserParam 類接收添加用戶的請求參數。另外,須要對接收的參數作校驗,按照前面課程的內容,引入 hibernate-validator 作校驗。

publicclass UserParam {
privatelong   id;
@NotEmpty"姓名不能爲空"   (message=)
private   String userName;
@NotEmpty"密碼不能爲空"   (message=)
@Length6"密碼長度不能小於6位"   (min=,message=)
private   String passWord;
@Max100"年齡不能大於100歲"   (value =, message =)
@Min18"必須年滿18歲!"   (value=,message=)
privateint   age;
//省略getter settet方法   
}

Controller 負責接收請求,首先判斷參數是否正確,若是有錯誤直接返回頁面,將錯誤信息展現給用戶,再判斷用戶是否存在,若是用戶已經存在一樣返回頁面給出提示。驗證經過後,將 UserParam 屬性複製到 User 並添加用戶註冊時間,最後將用戶信息保存到數據庫中。

"/add"@RequestMapping()
publicString add(@Valid UserParam userParam,BindingResult result, Model model) {
""    String errorMsg=;
// 參數校驗   
if   (result.hasErrors()) {
Listlist       <ObjectError>= result.getAllErrors();
forlist       (ObjectError error :) {
"-"";"            errorMsg=errorMsg + error.getCode() ++ error.getDefaultMessage() +;
        }
"errorMsg"        model.addAttribute(,errorMsg);
return"user/userAdd"       ;
    }
//判斷是否重複添加   
    User u= userRepository.findByUserName(userParam.getUserName());
ifnull   (u!=){
"errorMsg""用戶已存在!"        model.addAttribute(,);
return"user/userAdd"       ;
    }
new    User user=User();
    BeanUtils.copyProperties(userParam,user);
new    user.setRegTime(Date());
//保存   
    userRepository.save(user);
return"redirect:/list"   ;
}
  • model 對象主要用於傳遞控制方法處理數據到結果頁面;
  • return "redirect:/list"; 表明添加成功後直接跳轉到用戶列表頁面。

添加用戶部分頁面(userAdd.html)

前端頁面引入了 Bootstrap 前端框架,如下表單按照 Bootstrap 的格式進行設計。

<form class="form-horizontal"   th:action="@{/add}"  method="post">
<!-- 表單內容-->   
<div class="form-group">   
<label for="userName" class="col-sm-2 control-label"></label>       userName
<div class="col-sm-10">       
<input type="text" class="form-control" name="userName"  id="userName" placeholder="userName"/>           
</div>       
</div>   
<div class="form-group">   
<label for="password" class="col-sm-2 control-label" ></label>       passWord
<div class="col-sm-10">       
<input type="password" class="form-control" name="passWord" id="passWord" placeholder="passWord"/>           
</div>       
</div>   
    ....
<!-- 錯誤信息展現區-->   
<div class="form-group">   
<label  class="col-sm-2 control-label"></label>       
<div class="col-sm-10">       
<div th:if="${errorMsg != null}"  class="alert alert-danger" role="alert" th:text="${errorMsg}">           
</div>           
</div>       
</div>   
<!-- 按鈕區-->   
<div class="form-group">   
<div class="col-sm-offset-2 col-sm-10">       
<input type="submit" value="Submit" class="btn btn-info" />           
            &nbsp; &nbsp; &nbsp;
<input type="reset" value="Reset" class="btn btn-info" />           
            &nbsp; &nbsp; &nbsp;
<a href="/toAdd" th:href="@{/list}" class="btn btn-info"></a>           Back
</div>       
</div>   
</form>

效果圖:

 

1.4    用戶列表

參考前面課程,JPA 依賴 Pageable 爲用戶列表頁作分頁,默認每頁展現 6 個用戶,而且按照用戶註冊的倒序來排列,具體信息以下:

"/list"@RequestMapping()
"page""0"public String list(Model model,@RequestParam(value =, defaultValue =) Integer page,
"size""6"                   @RequestParam(value =, defaultValue =) Integer size) {
new"id"    Sort sort =Sort(Sort.Direction.DESC,);
of    Pageable pageable = PageRequest.(page, size, sort);
    Page<User> users=userRepository.findList(pageable);
"users"    model.addAttribute(, users);
return"user/list"   ;
}
  • @RequestParam 經常使用來處理簡單類型的綁定,註解有三個屬性:value、required 和 defaultValue;value 用來指定要傳入值的 ID 名稱,required 用來指示參數是否必須綁定,defaultValue 能夠設置參數的默認值。

前端頁抽取一個公共的分頁信息——page.html,頁面部分信息以下:

<div th:if="${(users.totalPages le 10) and (users.totalPages gt 0)}" th:remove="tag">
<div th:each="pg : ${#numbers.sequence(0, users.totalPages - 1)}" th:remove="tag">   
<span th:if="${pg eq users.getNumber()}" th:remove="tag">           
<li class="active"><span class="current_page line_height" th:text="${pg+1}"></span></li>               ${pageNumber}
</span>           
<span th:unless="${pg eq users.getNumber()}" th:remove="tag">       
<li><a href="#" th:href="@{${pageUrl}(page=${pg})}" th:text="${pg+1}"></a></li>               
</span>           
</div>   
</div>
 
<li th:if="${users.hasNext()}"><a href="#" th:href="@{${pageUrl}(page=${users.number+1})}"></a></li>下一頁
<li><a href="#" th:href="${users.totalPages le 0 ? pageUrl+'page=0':pageUrl+'&amp;page='+(users.totalPages-1)}"></a></li>尾頁
<li><span th:utext="'共'+${users.totalPages}+'頁 / '+${users.totalElements}+' 條'"></span></li>

page.html 頁面的做用是顯示主頁的頁碼,包括首頁、末頁、第幾頁,共幾頁這類信息,須要根據頁碼的數據進行動態調整。頁面中使用了 Thymeleaf 大量語法:th:if 判斷、th:each 循環、th:href 連接等,分頁信息主要從後端傳遞的 Page 對象獲取。

而後在 list.html 頁面中引入 page.html 頁面分頁信息。

<h1></h1>用戶列表
<br/><br/>
<div class="with:80%">
<table class="table table-hover">   
<thead>       
<!-- 表頭信息-->        
<tr>       
<th></th>           #
<th></th>           User Name
<th></th>           Password
<th></th>           Age
<th></th>           Reg Time
<th></th>           Edit
<th></th>           Delete
</tr>       
</thead>       
<tbody>       
<!-- 表循環展現用戶信息-->       
<tr  th:each="user : ${users}">       
<th scope="row" th:text="${user.id}"></th>           1
<td th:text="${user.userName}"></td>           neo
<td th:text="${user.passWord}"></td>           Otto
<td th:text="${user.age}"></td>           6
<td th:text="${#dates.format(user.regTime, 'yyyy/MMM/dd HH:mm:ss')}"></td>           
<td><a th:href="@{/toEdit(id=${user.id})}"></a></td>           edit
<td><a th:href="@{/delete(id=${user.id})}"  onclick="return confirm('確認是否刪除此用戶?')"  ></a></td>           delete
</tr>       
</tbody>       
</table>   
<!-- 引入分頁內容-->   
<div th:include="page :: pager" th:remove="tag"></div>   
</div>
<div class="form-group">
<div class="col-sm-2 control-label">   
<a href="/toAdd" th:href="@{/toAdd}" class="btn btn-info"></a>       add
</div>   
</div>

<tr th:each="user : ${users}"> 這裏會從 Controler 層 model set 的對象去獲取相關的內容,th:each 表示會循環遍歷對象內容。

效果圖以下:

 

1.5    修改功能

點擊修改功能的時候,須要帶上用戶的 ID 信息:

<a th:href="@{/toEdit(id=${user.id})}">edit</a></td><td>

後端根據用戶 ID 獲取用戶信息,並放入 Model 中。

@RequestMapping"/toEdit"()
public String toEdit(Model model,Long id) {
    User user=userRepository.findById(id);
"user"    model.addAttribute(, user);
return"user/userEdit"   ;
}

修改頁面展現用戶信息,如下爲 userEdit.html 頁面部份內容:

<form class="form-horizontal"   th:action="@{/edit}" th:object="${user}"  method="post">
<!--隱藏用戶 ID-->   
<input type="hidden" name="id" th:value="*{id}" />   
<div class="form-group">   
<label for="userName" class="col-sm-2 control-label"></label>       userName
<div class="col-sm-10">       
<input type="text" class="form-control" name="userName"  id="userName" th:value="*{userName}" placeholder="userName"/>           
</div>       
</div>   
<div class="form-group">   
<label for="password" class="col-sm-2 control-label" ></label>       passWord
<div class="col-sm-10">       
<input type="password" class="form-control" name="passWord" id="passWord"  th:value="*{passWord}" placeholder="passWord"/>           
</div>       
</div>   
 
<!--錯誤信息-->   
<div class="form-group">   
<label  class="col-sm-2 control-label"></label>       
<div class="col-sm-10">       
<div th:if="${errorMsg != null}"  class="alert alert-danger" role="alert" th:text="${errorMsg}">           
 
</div>           
</div>       
</div>   
 
<!--按鈕區-->   
<div class="form-group">   
<div class="col-sm-offset-2 col-sm-10">       
<input type="submit" value="Submit" class="btn btn-info" />           
            &nbsp; &nbsp; &nbsp;
<a  th:href="@{/list}" class="btn btn-info"></a>           Back
</div>       
 
</div>   
</form>

修改完成後提交到後臺:

"/edit"@RequestMapping()
public String edit(@Valid UserParam userParam, BindingResult result,Model model) {
""    String errorMsg=;
//參數校驗   
if   (result.hasErrors()) {
list        List<ObjectError>= result.getAllErrors();
forlist       (ObjectError error :) {
"-"";"            errorMsg=errorMsg + error.getCode() ++ error.getDefaultMessage() +;
        }
"errorMsg"        model.addAttribute(,errorMsg);
"user"        model.addAttribute(, userParam);
return"user/userEdit"       ;
    }
 
//複製屬性保持修改後數據   
new    User user=User();
    BeanUtils.copyProperties(userParam,user);
new    user.setRegTime(Date());
    userRepository.save(user);
return"redirect:/list"   ;
}

後臺一樣須要進行參數驗證,無誤後修改對應的用戶信息。

效果圖:

 

1.6    刪除功能

單擊刪除按鈕的時候須要用戶再次確認,確認後才能刪除。

<a th:href="@{/delete(id=${user.id})}"  onclick="return confirm('確認是否刪除此用戶?')"  >delete</a></td><td>

效果以下:

 

後端根據用戶 ID 進行刪除便可。

"/delete"@RequestMapping()
deletepublic String(Long id) {
delete    userRepository.(id);
return"redirect:/list"   ;
}

刪除完成以後,再跳轉到用戶列表頁。

1.7    總結

用戶管理功能包含了用戶的增長、修改、刪除、展現等功能,也是咱們平常開發中最經常使用的四個功能。在實現用戶管理功能的過程當中使用了 JPA 的增長、修改、刪除、查詢、分頁查詢功能;使用了 Thymeleaf 展現用戶信息,在 list 頁面引入分頁模板,使用了 Thymeleaf 內嵌的 dates 對日期進行了格式化;通過今天的學習較全面演練了前期的學習內容。

點擊這裏下載源碼

相關文章
相關標籤/搜索