在这里会简述及展示,部分表单控件如何应用以及后端数据如何处理和应用。
框架使用Spring封装的一系列表单标签。
Spring MVC form声明
JSTL 1.1声明
文件位置:WEB-INF/tlds/fns.tld
涉及方法:
获取字典标签
getDictLabel
com.thinkgem.jeesite.modules.sys.utils.DictUtils
java.lang.String getDictLabel(java.lang.String, java.lang.String, java.lang.String)
${fns:getDictLabel(value, type, defaultValue)}
获取字典标签(多个)
getDictLabels
com.thinkgem.jeesite.modules.sys.utils.DictUtils
java.lang.String getDictLabels(java.lang.String, java.lang.String, java.lang.String)
${fns:getDictLabels(values, type, defaultValue)}
获取字典值
getDictValue
com.thinkgem.jeesite.modules.sys.utils.DictUtils
java.lang.String getDictValue(java.lang.String, java.lang.String, java.lang.String)
${fns:getDictValue(label, type, defaultValue)}
获取字典对象列表
getDictList
com.thinkgem.jeesite.modules.sys.utils.DictUtils
java.util.List getDictList(java.lang.String)
${fns:getDictList(type)}
获取字典对象列表
getDictListJson
com.thinkgem.jeesite.modules.sys.utils.DictUtils
java.lang.String getDictListJson(java.lang.String)
${fns:getDictListJson(type)}
DictUtils字典工具类
文件位置:com.thinkgem.jeesite.modules.sys.utils.DictUtils.java
/**
* Copyright © 2012-2016 JeeSite 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 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 getDictList(String type){
@SuppressWarnings("unchecked")
Map> dictMap = (Map>)CacheUtils.get(CACHE_DICT_MAP);
if (dictMap==null){
dictMap = Maps.newHashMap();
for (Dict dict : dictDao.findAllList(new Dict())){
List 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 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
前端回显目标数据:Radio-String;Select-String;CheckBox-List或List;
前端提交:String
页面数据编辑和回显:
单选按钮(单选):
下拉框(单选):
复选框(多选):
页面数据显示:
单选按钮和单选下拉框:
${fns:getDictLabel(对象.属性, 'yes_no', '')}
复选框:
${fns:getDictLabels(对象.属性, 'map_goods_format', '')}
控件属性说明
path,属性名称或目标数据名称;
items,源数据集合,封装源数据类型为List或自定义数据类型;
itemLabel,指定属性值为Dict对象的label属性或自定义;
itemValue,指定数值为Dict对象的value属性或自定义;
CheckBox-多选说明及案例
Radio和Select比较简单,因为存储的都是单一值,在数据编辑方面并没有需要注意的地方,只需要稍微注意一下所封装的数据类型对应调整就可以了。
CheckBox在数据回显和提交时需要特别注意一下,因为封装的形式和提交的方式稍微会有所调整,在此我重新以自定义对象举例说明:
一共有3张表,TravelRout,旅游路线表;ScenicArea,景区信息表;TravelRouteScenicArea,旅游路线和景区信息关联表,多对多的关系;
需求解释:添加旅游路线时,可以关联多个景区,因此每一条旅游路线信息都会有景区信息的集合。
实体模型TravelRoute类中,需要ScenicArea属性标识,用于封装传递的多选数值:
private List scenicAreaIdList = Lists.newArrayList(); //拥有的景区ID集合,用于数据回显
private List scenicAreaList = Lists.newArrayList(); //拥有的景区源数据集合
public List getScenicAreaList() {
return scenicAreaList;
}
public void setScenicAreaList(List scenicAreaList) {
this.scenicAreaList = scenicAreaList;
}
@JsonIgnore
public List getScenicAreaIdList(){
List scenicAreaIdList = Lists.newArrayList();
for(ScenicArea scenicArea : scenicAreaList){
scenicAreaIdList.add(scenicArea.getId());
}
return scenicAreaIdList;
}
public void setScenicAreaIdList(List 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 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:
途径景区:
执行新增或更新操作时,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,在联合表中插入数据需要注意:
DELETE FROM hnly_travel_route_scenic_area
WHERE hnly_travel_route_id = #{id}
INSERT INTO hnly_travel_route_scenic_area(hnly_travel_route_id, hnly_scenic_area_id)
SELECT #{id}, #{scenicArea.id}
FROM dual
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}
图样图森破
Ckfinder-图片及文件上传控件
图片及文件上传均使用的CF控件,在页面编辑的同时就已经将图片和文件数据上传完了,最后表单提交的时候是一串上传地址,所以后台数据格式为String字符串类型即可。
图片:
文件:
由两部分组成,form:hidden隐藏文本和sys:ckfinder控件,type分为两种images和files;uploadPath为上传路径;selectMultiple为是否为文件模式的是否允许多文件上传;maxHeight和maxWeight为图片模式使用的回显图片长宽;
WdatePicker-时间选择控件
如果系统中使用到时间数据格式是多样化的,如年月日/日分等等,建议后台和数据库的时间数据格式设置为文本,在页面中取消时间格式化就好了,原系统中如何设置请自行参考,这里我只贴修改后的。
时间:
value="${activity.publishTime}"
οnclick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss',isShowClear:false});"/>
value,为提交和回显属性,这里我已经将格式化方法去除,不再做格式化,且数据库和后台类型为字符串类型,如果使用原格式化方法处理则必须统一数据格式,不能使用字符串类型,去除后可使用。WdatePicker为控件调用方式;dataFmt,可设置多种时间显示方法;
Input-普通文本
标题:
Textarea-多行文本
内容: