1. 程式人生 > >SpringMVC4+thymeleaf3的一個簡單例項(篇五:頁面和MySql的資料互動-展示以及儲存)

SpringMVC4+thymeleaf3的一個簡單例項(篇五:頁面和MySql的資料互動-展示以及儲存)

這一篇將介紹怎樣把頁面資料儲存的MySql資料庫,並將資料庫內容展示到頁面上。

首先做一個基礎工作,新增以下jar到lib:

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;

建立資料表:

CREATE TABLE `animals` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  `count` int(11) DEFAULT NULL,
  `memo` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) 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>

掃描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用於操作資料表(增刪改查等)

package com.zoo.dao;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.zoo.entity.AnimalEntity;

@Repository
public class AnimalDAO {

	@Autowired
	private JdbcTemplate jdbcTmplt;
	
	//從animals表檢索出所有資料
	public List<AnimalEntity> getAll() {
		String sql = "SELECT id, name, count, memo FROM animals";
		List<AnimalEntity> list = this.jdbcTmplt.query(sql, new BeanPropertyRowMapper<AnimalEntity>(AnimalEntity.class));
		return list;
	}
	
	//插入一條資料到animals表
	public int insertOne(AnimalEntity entity){
		int cnt = this.jdbcTmplt.update("INSERT INTO animals(name, count, memo) VALUES(?, ?, ?)", 
				entity.getName(), entity.getCount(), entity.getMemo());
		return cnt;
	}
}

解釋:

@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層的方法

package com.zoo.service;

import java.util.List;

import com.zoo.entity.AnimalEntity;

public interface AnimalService {

	public List<AnimalEntity> getAllAnimals();
	
	public int insertOne(AnimalEntity entity);
}

(5)在com.zoo.service.impl中新增AnimalService的實現類AnimalServiceImpl.java:
package com.zoo.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zoo.dao.AnimalDAO;
import com.zoo.entity.AnimalEntity;
import com.zoo.service.AnimalService;

@Service
public class AnimalServiceImpl implements AnimalService {
	
	@Autowired
	private AnimalDAO dao;

	@Override
	public List<AnimalEntity> getAllAnimals() {
		return dao.getAll();
	}

	@Override
	public int insertOne(AnimalEntity entity) {
		return dao.insertOne(entity);
	}

}

(6)修改ZooController,定義AnimalService欄位並將其標註為自動繫結@Autowired;修改showZooList方法,呼叫service取出資料庫資料
	@Autowired
	private AnimalService service;
	
	@RequestMapping(path = "/list", method = RequestMethod.GET)
	public ModelAndView showZooList(){
		//從資料庫取出資料
		List<AnimalEntity> animals = service.getAllAnimals();
		ModelAndView mav = new ModelAndView();
		mav.setViewName("zoolist");
		mav.addObject("animalForm", new AnimalForm());
		mav.addObject("animalsList", animals);
		return mav;
	}

我們呼叫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裡增加了thead和tbody標籤,用於將table分成兩部分;

在tbody標籤中的th:remove="all-but-first",意思是隻保留tbody中第一個子標籤,其它子標籤全都刪掉,什麼意思呢,讓我們先看看tbody裡的內容:它有4組tr標籤,也就是有4條靜態資料,當thymeleaf解析到這裡的時候一看有個th:remove="all-but-first",好吧,它就會把第一組tr保留,剩下的三個給刪掉,等下執行畫面讓你有個直觀感受。th:remove的5個備選值及其含義:

all:刪除所在的標籤以及所在標籤的所有子節點

body:除所在標籤外,刪除所有所在標籤的子節點

tag:刪除所在標籤,但保留所在標籤的子節點

all-but-first:刪除除所在標籤第一個子節點外的所有其他子節點

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看看:


哇,資料庫的資料出來了,是我們想要的結果。這就是thymeleaf不同於其它template(比如jsp,freeMarker,volecity等)的地方,同一個頁面既可用於展示靜態資料也可以用於執行動態資料。

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


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

ok,接下來我們製作最後一個步驟:插資料庫。

四、儲存資料到資料庫

修改ZooCotroller,增加copyDataFromForm2Entity方法將form裡的資料copy到entity中;

在doAdd方法中呼叫service的insertOne方法儲存資料;

完整程式碼:

package com.zoo.web.controller;

import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.zoo.entity.AnimalEntity;
import com.zoo.service.AnimalService;
import com.zoo.web.form.AnimalForm;

@Controller
public class ZooController {

	@Autowired
	private AnimalService service;
	
	@RequestMapping(path = "/list", method = RequestMethod.GET)
	public ModelAndView showZooList(){
		//從資料庫取出資料
		List<AnimalEntity> animals = service.getAllAnimals();
		ModelAndView mav = new ModelAndView();
		mav.setViewName("zoolist");
		mav.addObject("animalForm", new AnimalForm());
		mav.addObject("animalsList", animals);
		return mav;
	}
	
    @RequestMapping(path = "/list", params = {"save"}, method = RequestMethod.POST)
	public String doAdd(Model model, @Valid AnimalForm form, BindingResult result){
	    if(result.hasErrors()){
	        model.addAttribute("MSG", "出錯啦!");
	    }else{
	    	//儲存資料到資料庫
	    	service.insertOne(this.copyDataFromForm2Entity(form));
	        model.addAttribute("MSG", "提交成功!");
	    }
		//從資料庫取出資料
		List<AnimalEntity> animals = service.getAllAnimals();
		model.addAttribute("animalsList", animals);
	    return "zoolist";
	}
    
    //把form裡的資料copy到entity中
    private AnimalEntity copyDataFromForm2Entity(AnimalForm form){
    	AnimalEntity entity = new AnimalEntity();
    	entity.setName(form.getOname());
    	entity.setCount(Integer.valueOf(form.getOcount()));
    	entity.setMemo(form.getMemo());
    	return entity;
    }
}

刪除之前的system.out.print語句,在資料儲存後,需要重新從資料庫選出資料以重新整理畫面。

試一試吧!


聰明的你一定做出來了吧!

我們的例項小製作也就到這裡結束了,希望這些程式碼能讓你對springMVC+thymeleaf+mysql有所瞭解,那我也就開心了!

末語:

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

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