SpringMVC4+thymeleaf3的一個簡單實例(篇五:頁面和MySql的數據交互-展示以及存儲)


這一篇將介紹怎樣把頁面數據保存的MySQL數據庫,並將數據庫內容展示到頁面上。

首先做一個基礎工作,添加以下jar到lib:
1: mysql-connector-Java-5.1.40-bin.jar 下載 http://dev.mysql.com/downloads/connector/j/
2: spring-jdbc-4.3.3.RELEASE.jar
3: spring-tx-4.3.3.RELEASE.jar


2和3從spring framework發布包里面找。

繼續沿用前面篇節的程序代碼。我們開始吧!

一、創建數據庫

打開ubuntu終端,輸入命令: mysql -u root -p,提示輸入用戶root的密碼后即可進入數據庫,你也可用其它有創建數據庫權限的用戶進入:

 

創建名為test的schema(數據庫):CREATE SCHEMA `test` DEFAULT CHARACTER SET utf8 ;
完成后進入test數據庫:mysql> use test;
創建數據表:

1 CREATE TABLE `animals` (  
2   `id` int(11) NOT NULL AUTO_INCREMENT,  
3   `name` varchar(45) DEFAULT NULL,  
4   `count` int(11) DEFAULT NULL,  
5   `memo` varchar(45) DEFAULT NULL,  
6   PRIMARY KEY (`id`),  
7   UNIQUE KEY `id_UNIQUE` (`id`)  
8 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; 

 

插入幾條數據:
INSERT INTO animals(name, count, memo) VALUES('大馬猴', 10, '散養');
INSERT INTO animals(name, count, memo) VALUES('小綿陽', 8, '圈養');
INSERT INTO animals(name, count, memo) VALUES('火星猿', 1, '圈養');
用select * from animals;看看結果:

 

大功告成!

以上所有操作也可通過MysqlWorkbench圖形界面來操作完成,界面是這個樣子:

 

二、在Spring中配置MySql數據庫

添加以下代碼到spring-mvc.xml文件

    <context:component-scan base-package="com.zoo.dao"/>  
    <context:component-scan base-package="com.zoo.service"/>  
    <!-- 數據源配置 -->  
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
      <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
      <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>  
      <property name="username" value="root"/>  
      <property name="password" value="password"/>  
    </bean>  
      
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
      <property name="dataSource" ref="dataSource"></property>  
    </bean>  

解釋:

component-scan用於掃描dao包和service包以便讓spring對有注解的組件進行配置,比如組件注冊,綁定組件(用@Autowired標注的代碼)等。

數據源讓spring來管理,記得把password改成你自己的哦。重點說一下url屬性,格式為 jdbc:mysql://host:port/database?prams,其中host是數據庫所在服務器的ip或者名稱;port為端口號,默認是3306;使用test數據庫(我在我的數據庫中創建了一個名叫test的庫);問號后面是各種參數,本例設置了3個。

注意useUnicode和characterEncoding這兩個參數,為了確保保存到數據庫的字符不出現亂碼,記得把它們設置成useUnicode=true&characterEncoding=UTF-8,否則很有可能在開發的時候碰到:頁面傳到后台程序的字符是正常的,但是保存到數據庫就是亂碼了。

另外細心的同學已經發現url的字符串里怎么會有”&amp;“,這是因為”&“符號對xml來說是個特殊字符,如果不將其轉義為"&amp;",你會收到一個解析exception,類似這個:org.xml.sax.SAXParseException; lineNumber: 24; columnNumber: 95; 對實體 "characterEncoding" 的引用必須以 ';' 分隔符結尾?

三、添加幾個java類

(1)新建三個包:com.zoo.service,com.zoo.service.impl,com.zoo.dao,com.zoo.entity
(2)在com.zoo.entity中添加類AnimalEntity.java,對應數據表內的一條數據,從數據庫取出的數據會放在這個類的實例中

    package com.zoo.entity;  
      
    public class AnimalEntity {  
      
        //數據庫自動生成的id  
        private Long id;  
          
        //動物名稱  
        private String name;  
          
        //動物數量  
        private Integer count;  
          
        //備注  
        private String memo;  
      
            //getters and setters  
    }  

 

(3)在com.zoo.dao內添加AnimalDAO.java,dao用於操作數據表(增刪改查等)

 1     package com.zoo.dao;  
 2       
 3     import java.util.List;  
 4       
 5     import org.springframework.beans.factory.annotation.Autowired;  
 6     import org.springframework.jdbc.core.BeanPropertyRowMapper;  
 7     import org.springframework.jdbc.core.JdbcTemplate;  
 8     import org.springframework.stereotype.Service;  
 9       
10     import com.zoo.entity.AnimalEntity;  
11       
12     @Repository  
13     public class AnimalDAO {  
14       
15         @Autowired  
16         private JdbcTemplate jdbcTmplt;  
17           
18         //從animals表檢索出所有數據  
19         public List<AnimalEntity> getAll() {  
20             String sql = "SELECT id, name, count, memo FROM animals";  
21             List<AnimalEntity> list = this.jdbcTmplt.query(sql, new BeanPropertyRowMapper<AnimalEntity>(AnimalEntity.class));  
22             return list;  
23         }  
24           
25         //插入一條數據到animals表  
26         public int insertOne(AnimalEntity entity){  
27             int cnt = this.jdbcTmplt.update("INSERT INTO animals(name, count, memo) VALUES(?, ?, ?)",   
28                     entity.getName(), entity.getCount(), entity.getMemo());  
29             return cnt;  
30         }  
31     }  

解釋:
@Service標注,還記得上面spring-mvc.xml中的context:component-scan么標簽?它用於掃描指定包下(含子包)所有帶@Component, @Service, @Controller以及@Repository的類,並將其注冊到spring容器,以供其它代碼使用。spring推薦將@Service用於業務邏輯層,@Controller用於控制層,@Repository用於持久化層。

@Autowired標注的字段,spring容器會自動從已經注冊的組件中找到對應的component,並將其綁定。


注意:在getAll方法中我們用到了spring提供的一個非常實用的工具類:BeanPropertyRowMapper,它的作用就是將數據表里每條數據填充到指定類中,用了它好省心呀。注意指定類里的字段和數據表的字段名稱要保持一致哦。

(4)在com.zoo.service里添加接口類AnimalService.java,controller會調用service層的方法

 1     package com.zoo.service;  
 2       
 3     import java.util.List;  
 4       
 5     import com.zoo.entity.AnimalEntity;  
 6       
 7     public interface AnimalService {  
 8       
 9         public List<AnimalEntity> getAllAnimals();  
10           
11         public int insertOne(AnimalEntity entity);  
12     }  

 

(5)在com.zoo.service.impl中添加AnimalService的實現類AnimalServiceImpl.java:

 1     package com.zoo.service.impl;  
 2       
 3     import java.util.List;  
 4       
 5     import org.springframework.beans.factory.annotation.Autowired;  
 6     import org.springframework.stereotype.Service;  
 7       
 8     import com.zoo.dao.AnimalDAO;  
 9     import com.zoo.entity.AnimalEntity;  
10     import com.zoo.service.AnimalService;  
11       
12     @Service  
13     public class AnimalServiceImpl implements AnimalService {  
14           
15         @Autowired  
16         private AnimalDAO dao;  
17       
18         @Override  
19         public List<AnimalEntity> getAllAnimals() {  
20             return dao.getAll();  
21         }  
22       
23         @Override  
24         public int insertOne(AnimalEntity entity) {  
25             return dao.insertOne(entity);  
26         }  
27       
28     }  

 

(6)修改ZooController,定義AnimalService字段並將其標注為自動綁定@Autowired;修改showZooList方法,調用service取出數據庫數據

 1     @Autowired  
 2     private AnimalService service;  
 3       
 4     @RequestMapping(path = "/list", method = RequestMethod.GET)  
 5     public ModelAndView showZooList(){  
 6         //從數據庫取出數據  
 7         List<AnimalEntity> animals = service.getAllAnimals();  
 8         ModelAndView mav = new ModelAndView();  
 9         mav.setViewName("zoolist");  
10         mav.addObject("animalForm", new AnimalForm());  
11         mav.addObject("animalsList", animals);  
12         return mav;  
13     }  

我們調用service的getAllAnimals方法,取得動物列表,並將這個list傳遞給頁面用於展示。

(7)修改zoolist.html,由於我們在頁面上一直用的是靜態數據,現在有了數據庫就可以用動態的了,但是需要修改代碼以便顯示list中的內容,只修改table那段

    <table border="1">  
          <thead>  
              <tr>  
                <th>序號</th>  
                <th>動物名稱</th>    
                <th>數量</th>   
                <th>備注</th>  
              </tr>  
          </thead>  
          <tbody th:remove="all-but-first">  
              <tr th:each="obj, objStat: ${animalsList}">  
                <td th:text="${objStat.count}">1</td>  
                <td th:text="${obj.name}">大馬猴</td>  
                <td th:text="${obj.count}">10</td>  
                <td th:text="${obj.memo}">機靈古怪,俏皮活潑</td>  
              </tr>  
              <tr>  
                <td>2</td>  
                <td>大熊貓</td>  
                <td>80</td>  
                <td>體型笨重,喜歡吃竹子</td>  
              </tr>  
              <tr>  
                <td>3</td>  
                <td>澳洲羊駝</td>  
                <td>13</td>  
                <td>長相奇特,大國人俗稱其草泥馬</td>  
              </tr>  
              <tr>  
                <td>4</td>  
                <td>峨眉山猴</td>  
                <td>90</td>  
                <td>不怕人,有時候發賤搶游客面包吃</td>  
              </tr>  
          </tbody>  
        </table>  

注意:我們在table里增加了theadtbody標簽,用於將table分成兩部分;

在tbody標簽中的th:remove="all-but-first",意思是只保留tbody中第一個子標簽,其它子標簽全都刪掉,什么意思呢,讓我們先看看tbody里的內容:它有4組tr標簽,也就是有4條靜態數據,當thymeleaf解析到這里的時候一看有個th:remove="all-but-first",好吧,它就會把第一組tr保留,剩下的三個給刪掉,等下運行畫面讓你有個直觀感受。

th:remove的5個備選值及其含義:

1. all:刪除所在的標簽以及所在標簽的所有子節點

2. body:除所在標簽外,刪除所有所在標簽的子節點
3. tag:刪除所在標簽,但保留所在標簽的子節點
4. all-but-first:刪除除所在標簽第一個子節點外的所有其他子節點
5. none:不做任何事情,等同於不聲明th:remove表達式

<tr th:each="obj, objStat: ${animalsList}">,里面的th:each表達式意思是把${animalList}變量進行迭代,以將list里的所有數據條目顯示出來。注意前面的兩個變量obj和objStat,obj表示list里面的具體實例,我們這里是AnimalEntity的實例;objStat是一個狀態變量,表示迭代的當前狀態,這個狀態變量包含以下屬性,代碼中可直接使用:
index:當前迭代的index,從0開始
count:當前迭代的index,從1開始
size:迭代變量所含元素總數
current:表示當前迭代的元素,也就是某個AnimalEntity的實例
even/odd:布爾值,表示當前迭代是奇數還是偶數
first:布爾值,表示當前迭代是不是第一條記錄
last:布爾值,表示當前迭代是不是最后一條記錄

我們運行tomcat看看:

 

ok,一切正常,是我們想要的結果。

這個過程中你是否感受到了thymeleaf不同於其它template(比如jsp,freeMarker,volecity等)的地方?

thymeleaf同一個頁面既可用於展示靜態數據也可以用於運行動態數據

如果把th:remove去掉會是怎樣的效果呢:

嗯,聰明的你看懂了吧!有興趣你還可以試一試th:remove其它的值。

ok,接下來我們制作最后一個步驟:插數據庫。

四、保存數據到數據庫

修改ZooCotroller,增加copyDataFromForm2Entity方法將form里的數據copy到entity中;
在doAdd方法中調用service的insertOne方法保存數據;
完整代碼:

 1 package com.zoo.web.controller;
 2 
 3 import java.util.List;
 4 
 5 import javax.validation.Valid;
 6 
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.stereotype.Controller;
 9 import org.springframework.ui.Model;
10 import org.springframework.validation.BindingResult;
11 import org.springframework.web.bind.annotation.RequestMapping;
12 import org.springframework.web.bind.annotation.RequestMethod;
13 import org.springframework.web.servlet.ModelAndView;
14 
15 import com.zoo.entity.AnimalEntity;
16 import com.zoo.service.AnimalService;
17 import com.zoo.web.form.AnimalForm;
18 
19 @Controller
20 public class ZooController {
21 
22     @Autowired
23     private AnimalService service;
24     
25     @RequestMapping(path = "/list", method = RequestMethod.GET)
26     public ModelAndView showZooList(){
27         //從數據庫取出數據
28         List<AnimalEntity> animals = service.getAllAnimals();
29         ModelAndView mav = new ModelAndView();
30         mav.setViewName("zoolist");
31         mav.addObject("animalForm", new AnimalForm());
32         mav.addObject("animalsList", animals);
33         return mav;
34     }
35     
36     @RequestMapping(path = "/list", params = {"save"}, method = RequestMethod.POST)
37     public String doAdd(Model model, @Valid AnimalForm form, BindingResult result){
38         if(result.hasErrors()){
39             model.addAttribute("MSG", "出錯啦!");
40         }else{
41             //保存數據到數據庫
42             service.insertOne(this.copyDataFromForm2Entity(form));
43             model.addAttribute("MSG", "提交成功!");
44         }
45         //從數據庫取出數據
46         List<AnimalEntity> animals = service.getAllAnimals();
47         model.addAttribute("animalsList", animals);
48         return "zoolist";
49     }
50     
51     //把form里的數據copy到entity中
52     private AnimalEntity copyDataFromForm2Entity(AnimalForm form){
53         AnimalEntity entity = new AnimalEntity();
54         entity.setName(form.getOname());
55         entity.setCount(Integer.valueOf(form.getOcount()));
56         entity.setMemo(form.getMemo());
57         return entity;
58     }
59 }

刪除之前的system.out.print語句,在數據保存后,需要重新從數據庫選出數據以刷新畫面。

試一試吧!

嗯,這說明頁面的數據已經保存到了數據庫。聰明的你一定做出來了吧!

我們這個主題的實例小制作也就結束了,希望這些代碼能讓你對springMVC+thymeleaf+mysql有所了解,那我也就開心了!

末語:
在這個實例中,我僅簡單的介紹了最基本的一些用法,希望能幫助到你們。本人水平有限,也只能寫成這樣了,如果哪里寫錯了請毫無保留的披頭蓋臉的向我指出來,在下必虛心改之!

springMVC和thymeleaf都是非常優秀的開源項目,而且相應的文檔也很詳細,如果大家遇到了問題,請先查閱文檔以及API,應該會讓你找到答案的。

 

 

END.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM