Jeesite 表單控件使用方法 Spring-MVC form、JSTL1.1

在這裏會簡述及展現,部分表單控件如何應用以及後端數據如何處理和應用。html

框架使用Spring封裝的一系列表單標籤。前端

Spring MVC form聲明

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>

JSTL 1.1聲明

  • 文件位置:WEB-INF/tlds/fns.tld

    涉及方法:java

<!-- DictUtils -->
  <function>
    <description>獲取字典標籤</description>
    <name>getDictLabel</name>
    <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class>
    <function-signature>java.lang.String getDictLabel(java.lang.String, java.lang.String, java.lang.String)</function-signature>
    <example>${fns:getDictLabel(value, type, defaultValue)}</example>  
  </function>
  
  <function>
    <description>獲取字典標籤(多個)</description>
    <name>getDictLabels</name>
    <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class>
    <function-signature>java.lang.String getDictLabels(java.lang.String, java.lang.String, java.lang.String)</function-signature>
    <example>${fns:getDictLabels(values, type, defaultValue)}</example>  
  </function>

  <function>
    <description>獲取字典值</description>
    <name>getDictValue</name>
    <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class>
    <function-signature>java.lang.String getDictValue(java.lang.String, java.lang.String, java.lang.String)</function-signature>
    <example>${fns:getDictValue(label, type, defaultValue)}</example>  
  </function>
  
  <function>
    <description>獲取字典對象列表</description>
    <name>getDictList</name>
    <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class>
    <function-signature>java.util.List getDictList(java.lang.String)</function-signature>
    <example>${fns:getDictList(type)}</example>  
  </function>
  
  <function>
    <description>獲取字典對象列表</description>
    <name>getDictListJson</name>
    <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class>
    <function-signature>java.lang.String getDictListJson(java.lang.String)</function-signature>
    <example>${fns:getDictListJson(type)}</example>  
  </function>

DictUtils字典工具類

    文件位置:com.thinkgem.jeesite.modules.sys.utils.DictUtils.javagit

/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.thinkgem.jeesite.modules.sys.utils;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.thinkgem.jeesite.common.mapper.JsonMapper;
import com.thinkgem.jeesite.common.utils.CacheUtils;
import com.thinkgem.jeesite.common.utils.SpringContextHolder;
import com.thinkgem.jeesite.modules.sys.dao.DictDao;
import com.thinkgem.jeesite.modules.sys.entity.Dict;

/**
 * 字典工具類
 * @author ThinkGem
 * @version 2013-5-29
 */
public class DictUtils {
	
	private static DictDao dictDao = SpringContextHolder.getBean(DictDao.class);

	public static final String CACHE_DICT_MAP = "dictMap";
	
	public static String getDictLabel(String value, String type, String defaultValue){
		if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(value)){
			for (Dict dict : getDictList(type)){
				if (type.equals(dict.getType()) && value.equals(dict.getValue())){
					return dict.getLabel();
				}
			}
		}
		return defaultValue;
	}
	
	public static String getDictLabels(String values, String type, String defaultValue){
		if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(values)){
			List<String> valueList = Lists.newArrayList();
			for (String value : StringUtils.split(values, ",")){
				valueList.add(getDictLabel(value, type, defaultValue));
			}
			return StringUtils.join(valueList, ",");
		}
		return defaultValue;
	}

	public static String getDictValue(String label, String type, String defaultLabel){
		if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(label)){
			for (Dict dict : getDictList(type)){
				if (type.equals(dict.getType()) && label.equals(dict.getLabel())){
					return dict.getValue();
				}
			}
		}
		return defaultLabel;
	}
	
	public static List<Dict> getDictList(String type){
		@SuppressWarnings("unchecked")
		Map<String, List<Dict>> dictMap = (Map<String, List<Dict>>)CacheUtils.get(CACHE_DICT_MAP);
		if (dictMap==null){
			dictMap = Maps.newHashMap();
			for (Dict dict : dictDao.findAllList(new Dict())){
				List<Dict> dictList = dictMap.get(dict.getType());
				if (dictList != null){
					dictList.add(dict);
				}else{
					dictMap.put(dict.getType(), Lists.newArrayList(dict));
				}
			}
			CacheUtils.put(CACHE_DICT_MAP, dictMap);
		}
		List<Dict> dictList = dictMap.get(type);
		if (dictList == null){
			dictList = Lists.newArrayList();
		}
		return dictList;
	}
	
	/**
	 * 返回字典列表(JSON)
	 * @param type
	 * @return
	 */
	public static String getDictListJson(String type){
		return JsonMapper.toJsonString(getDictList(type));
	}
	
}

Radio單選框、Select下拉框、CheckBox複選框

  • 數據庫存儲:Varchar
  • 後臺數據:String
  • 前端回顯列表數據集合:List<Dict>
  • 前端回顯目標數據:Radio-String;Select-String;CheckBox-List<String>或List<Dict>
  • 前端提交:String

    頁面數據編輯和回顯:github

單選按鈕(單選):
<form:radiobuttons path="check" items="${fns:getDictList('yes_no')}" itemLabel="label" itemValue="value" htmlEscape="false"/>
下拉框(單選):
<form:select path="check" class="input-xlarge ">
     <form:option value="" label=""/>
     <form:options items="${fns:getDictList('yes_no')}" itemLabel="label" itemValue="value" htmlEscape="false"/>
</form:select>
複選框(多選):
<form:checkboxes path="goodsTypeFormatDictList" items="${fns:getDictList('map_goods_format')}" itemLabel="label" itemValue="value" htmlEscape="false"/>

    頁面數據顯示:spring

單選按鈕和單選下拉框:
${fns:getDictLabel(對象.屬性, 'yes_no', '')}
複選框:
${fns:getDictLabels(對象.屬性, 'map_goods_format', '')}

    控件屬性說明sql

  • path,屬性名稱或目標數據名稱;
  • items,源數據集合,封裝源數據類型爲List<Dict>或自定義數據類型;
  • itemLabel,指定屬性值爲Dict對象的label屬性或自定義;
  • itemValue,指定數值爲Dict對象的value屬性或自定義;

CheckBox-多選說明及案例

    Radio和Select比較簡單,由於存儲的都是單一值,在數據編輯方面並無須要注意的地方,只須要稍微注意一下所封裝的數據類型對應調整就能夠了。數據庫

    CheckBox在數據回顯和提交時須要特別注意一下,由於封裝的形式和提交的方式稍微會有所調整,在此我從新以自定義對象舉例說明:apache

    一共有3張表,TravelRout,旅遊路線表;ScenicArea,景區信息表;TravelRouteScenicArea,旅遊路線和景區信息關聯表,多對多的關係;後端

  • 需求解釋:添加旅遊路線時,能夠關聯多個景區,所以每一條旅遊路線信息都會有景區信息的集合。

    實體模型TravelRoute類中,須要ScenicArea屬性標識,用於封裝傳遞的多選數值:

private List<String> scenicAreaIdList = Lists.newArrayList(); //擁有的景區ID集合,用於數據回顯
private List<ScenicArea> scenicAreaList = Lists.newArrayList(); //擁有的景區源數據集合
public List<ScenicArea> getScenicAreaList() {
		return scenicAreaList;
	}

	public void setScenicAreaList(List<ScenicArea> scenicAreaList) {
		this.scenicAreaList = scenicAreaList;
	}
@JsonIgnore
	public List<String> getScenicAreaIdList(){
		List<String> scenicAreaIdList = Lists.newArrayList();
		for(ScenicArea scenicArea : scenicAreaList){
			scenicAreaIdList.add(scenicArea.getId());
		}
		return scenicAreaIdList;
	}
	
	public void setScenicAreaIdList(List<String> scenicAreaIdList){
		scenicAreaList = Lists.newArrayList();
		for(String scenicAreaId : scenicAreaIdList){
			ScenicArea scenicArea = new ScenicArea();
			scenicArea.setId(scenicAreaId);
			scenicAreaList.add(scenicArea);
		}
	}

    TravelRouteService類中,get方法須要獲取scenicAreaList集合進行數據填充,該數據源是利用scenicAreaId查詢TravelRouteScenicArea獲得的集合,注意:

public TravelRoute get(String id) {
		TravelRoute travelRoute = travelRouteDao.get(id);
		List<ScenicArea> list = travelRouteDao.findTravelRouteScenicAreaByTR(id);
		travelRoute.setScenicAreaList(list);
		return travelRoute;
	}

    TravelRouteController類中,還須要針對前端所有景區數據列表作一個屬性回顯,allScenicAreas,即查詢所有景區信息列表:

@RequiresPermissions("hnly:travelRoute:view")
	@RequestMapping(value = "form")
	public String form(TravelRoute travelRoute, Model model) {
		model.addAttribute("travelRoute", travelRoute);
		model.addAttribute("allScenicAreas", scenicAreaService.findList(null));
		return "modules/hnly/travelRouteForm";
	}

    前端JSP:

<div class="control-group">
			<label class="control-label">途徑景區:</label>
			<div class="controls">
				<form:checkboxes path="scenicAreaIdList" items="${allScenicAreas}" itemLabel="name" itemValue="id" htmlEscape="false" class="required"/>
			</div>
		</div>

    執行新增或更新操做時,TravelRouteService類中,須要作響應的修改,先刪除聯合表中的數據,再添加:

@Transactional(readOnly = false)
	public void save(TravelRoute travelRoute) {
		if (StringUtils.isBlank(travelRoute.getId())){
			travelRouteDao.insert(travelRoute);
		} else {
			travelRouteDao.update(travelRoute);
		}
		travelRouteDao.deleteTravelRouteScenicArea(travelRoute);
		travelRouteDao.insertTravelRouteScenicArea(travelRoute);
	}

    TravelRouteDao,在聯合表中插入數據須要注意:

<!-- 刪除推薦旅遊路線和景區關聯表數據 -->
	<update id="deleteTravelRouteScenicArea">
		DELETE FROM hnly_travel_route_scenic_area
		WHERE hnly_travel_route_id = #{id}
	</update>
	
	<!-- 插入推薦旅遊路線和景區關聯表數據 -->
	<insert id="insertTravelRouteScenicArea" useGeneratedKeys="true" keyProperty="id">
		INSERT INTO hnly_travel_route_scenic_area(hnly_travel_route_id, hnly_scenic_area_id)
		<foreach collection="scenicAreaList" item="scenicArea" separator=" union all ">
			SELECT #{id}, #{scenicArea.id}
			<if test="dbName != 'mssql'">
			FROM dual
			</if>
		</foreach>
	</insert>
	
	<!-- 根據路線ID獲取推薦旅遊路線關聯的景區數據 -->
	<select id="findTravelRouteScenicAreaByTR" resultType="ScenicArea">
		SELECT 
			a.hnly_scenic_area_id AS "id",
			sa.name AS "name",
			sa.addr AS "addr",
			sa.lat AS "lat",
			sa.lon AS "lon",
			sa.hnly_panoramic_id AS "panoramic.id"
		FROM hnly_travel_route_scenic_area a 
		LEFT JOIN hnly_scenic_area sa ON sa.id = a.hnly_scenic_area_id 
		WHERE a.hnly_travel_route_id = #{id} 
	</select>

    圖樣圖森破

Ckfinder-圖片及文件上傳控件

    圖片及文件上傳均使用的CF控件,在頁面編輯的同時就已經將圖片和文件數據上傳完了,最後表單提交的時候是一串上傳地址,因此後臺數據格式爲String字符串類型便可。

<div class="control-group">
			<label class="control-label">圖片:</label>
			<div class="controls">
				<form:hidden id="pic" path="pic" htmlEscape="false" maxlength="255" class="input-xlarge"/>
				<sys:ckfinder input="pic" type="images" uploadPath="/hnly/activity" maxHeight="100" maxWidth="100"/>
			</div>
		</div>
<div class="control-group">
			<label class="control-label">文件:</label>
			<div class="controls">
				<form:hidden id="fil" path="fil" htmlEscape="false" maxlength="255" class="input-xlarge"/>
				<sys:ckfinder input="fil" type="files" uploadPath="/hnly/activity" selectMultiple="true"/>
			</div>
		</div>

    由兩部分組成,form:hidden隱藏文本和sys:ckfinder控件,type分爲兩種images和files;uploadPath爲上傳路徑;selectMultiple爲是否爲文件模式的是否容許多文件上傳;maxHeight和maxWeight爲圖片模式使用的回顯圖片長寬;

WdatePicker-時間選擇控件

    若是系統中使用到時間數據格式是多樣化的,如年月日/日分等等,建議後臺和數據庫的時間數據格式設置爲文本,在頁面中取消時間格式化就行了,原系統中如何設置請自行參考,這裏我只貼修改後的。

<div class="control-group">
			<label class="control-label">時間:</label>
			<div class="controls">
				<input name="publishTime" type="text" readonly="readonly" maxlength="20" class="input-medium Wdate "
					value="${activity.publishTime}"
					onclick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss',isShowClear:false});"/>
			</div>
		</div>

    value,爲提交和回顯屬性,這裏我已經將格式化方法去除,再也不作格式化,且數據庫和後臺類型爲字符串類型,若是使用原格式化方法處理則必須統一數據格式,不能使用字符串類型,去除後可以使用。WdatePicker爲控件調用方式;dataFmt,可設置多種時間顯示方法;

Input-普通文本

<div class="control-group">
			<label class="control-label">標題:</label>
			<div class="controls">
				<form:input path="title" htmlEscape="false" maxlength="255" class="input-xlarge "/>
			</div>
		</div>

Textarea-多行文本

<div class="control-group">
			<label class="control-label">內容:</label>
			<div class="controls">
				<form:textarea path="content" htmlEscape="false" rows="4" class="input-xxlarge "/>
			</div>
		</div>
相關文章
相關標籤/搜索