应用中用到的select经常需要向后台获取系统字典定义的选项然后再<#list>出来。为了重用可以使用服务端标签封装,或者用前端模板组件封装。这里记录一下使用FreeMarker自定义标签封装的方法。主要参考《FreeMarker_Manual_zh_CN》。
###用户自定义指令
<@user_def_dir_exp param1=val1 param2=val2 ... paramN=valN/>
<@user_def_dir_exp param1=val1 param2=val2 ... paramN=valN ; lv1, lv2, ..., lvN/>
<@user_def_dir_exp ...>...</@user_def_dir_exp>
或
<@user_def_dir_exp ...>...</@>
<@user val1, val2, ..., valN/>
这里:
1)user_def_dir_exp:表达式算作是自定义指令(比如宏),将会被调用;
2)param1,param2等:参数的名称,它们不是表达式;
3)val1,val2等:参数的值,它们是表达式;
4)lv1,lv2等:循环变量的名称,它们不是表达式;
参数的数量可以是0(也就是没有参数)。参数的顺序并不重要(除非你使用了位置参数传递)。参数名称必须唯一。在参数名中小写和大写的字母被认为是不同的字母(也就是Color和color是不同的)。
###select标签规则
<@select style="height:200px;padding:3px" name="cd" id="" default="x" desc="请选择">9100</@select>
1)标签体内是系统字典的id或code;
2)标签的参数不限,用来接收常规select html标签的属性,增加default参数用于指定selected,增加desc参数指定空option显示的提示信息;
###TemplateDirectiveModel实现类 public class DictSelectDirective implements TemplateDirectiveModel {
@Autowired
private DataDictService dataDictService;
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
throws TemplateException, IOException {
Map<String,String> attrs=new HashMap<String, String>();
Iterator paramIter = params.entrySet().iterator();
while (paramIter.hasNext())
{
Map.Entry ent = (Map.Entry) paramIter.next();
String paramName = (String) ent.getKey();
TemplateModel paramValue = (TemplateModel) ent.getValue();
attrs.put(paramName,paramValue.toString());
}
if(body==null)
return;
body.render(new DictSelectDirectiveWriter(env.getOut(),attrs));
}
private class DictSelectDirectiveWriter extends Writer {
private final Writer out;
private Map<String,String> attrs;
DictSelectDirectiveWriter(Writer out,Map<String,String> attrs)
{
this.out = out;
this.attrs = attrs;
}
public void write(char[] cbuf, int off, int len) throws IOException
{
//获取字典选项
Map<String,String> options=new HashMap<String, String>();
Integer dictId=Integer.valueOf(new String(cbuf));
List<DataDict> dataDicts=dataDictService.findChildrenById(dictId);
if(dataDicts!=null&&dataDicts.size()>0)
{
for(DataDict dataDict:dataDicts)
options.put(dataDict.getCode(), dataDict.getName());
}
StringBuffer buf = new StringBuffer(300);
buf.append("<select");
//拼属性
for(Map.Entry<String, String> entry:attrs.entrySet())
buf.append(" ").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
buf.append(">");
//拼提示
String desc=attrs.get("desc");
buf.append("<option>").append(desc==null?"请选择":desc).append("</option>");
//默认值
String defaultVal=attrs.get("default");
//拼选项
for(Map.Entry<String, String> entry:options.entrySet())
{
String key=entry.getKey();
buf.append("<option ");
if(key.equals(defaultVal))
buf.append("selected");
buf.append(" value=\"").append(key).append("\">").append(entry.getValue()).append("</option>");
}
buf.append("</select>");
out.write(buf.toString());
}
public void flush() throws IOException {
out.flush();
}
public void close() throws IOException {
out.close();
}
}
}
###FreeMarkerConfigurer配置
<bean id="dictSelect" class="cn.alpha.common.springmvc.DictSelectDirective" />
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="freemarkerVariables">
<map>
<entry key="select" value-ref="dictSelect"/>
</map>
</property>
</bean>