在Struts應用中,到JSP頁面上顯示下拉列表框應該是常有的事。
在基于是Struts的MVC框架中顯示下拉框,有好些方法,用自定義標簽庫就是其中之一。
若我們的此下拉框是放在基于HtmlForm中的。Struts可以通過ActionForm來保存其歷史記錄(不排除我們人為地給此ActionForm清理一下)。然而此自定義標簽庫卻沒有此功能!因為它沒有通過過ActionForm中的字段來保存其記錄。所以選擇的時候可以根據自己的需要來定(我覺得在ActionForm中處理List列表框真的是一件非常龐大的工程:) )。
JSP中對標簽的應用:
<%
@?taglib?uri
=
"
/WEB-INF/self-html.tld
"
?prefix
=
"
test
"
?
%>
<
div?
class
="formitem"
>
??????
<
span?
class
="parameter_name"
>
所屬欄目:
</
span
>
??????
<
span?
class
="parameter_value"
>
??????
<
test:category?
name
="dto.id"
?type
="17"
/>
??????
</
span
>
?????
</
div
>
web.xml配置文件中:
<!--
?self?Tag?Library?Descriptors?
-->
??
<
taglib
>
????
<
taglib-uri
>
/WEB-INF/self-html.tld
</
taglib-uri
>
????
<
taglib-location
>
/WEB-INF/self-html.tld
</
taglib-location
>
??
</
taglib
>
self-html.tld定義:
<
taglib
>
?
<
tlibversion
>
1.0
</
tlibversion
>
?
<
jspversion
>
1.1
</
jspversion
>
?
<
shortname
>
netedu
</
shortname
>
?
?
?
<
tag
>
??
<
name
>
category
</
name
>
??
<
tagclass
>
com.CategoryTag
</
tagclass
>
?
??
<
bodycontent
>
empty
</
bodycontent
>
??
<
info
>
tag?here
</
info
>
??
??
<
attribute
>
??
<
name
>
name
</
name
>
??
<
required
>
false
</
required
>
??
<
rtexprvalue
>
false
</
rtexprvalue
>
??
</
attribute
>
??
<
attribute
>
??
<
name
>
id
</
name
>
??
??
?
</
tag
>
</
taglib
>
以后自己就有什么擴展的需要就是在這兒加參數了!
總算是到了標簽庫的定義的地方了:
/**?*/
/**
?*?
@author
?test?
?
*/
public
?
class
?CategoryTag?
extends
?TagSupport?
{

?
/**/
/*
?(non-Javadoc)
?????*?@see?javax.servlet.jsp.tagext.Tag#doStartTag()
?????
*/
????
public
?
int
?doStartTag()?
throws
?JspException?
{
????????
//
?TODO?Auto-generated?method?stub
????????
try
?
{
????????????JspWriter?out?
=
?pageContext.getOut();
????????????
//
jspwriter是一個隱含對象,用于向jsp網頁輸出內容。輸出的目標由
????????????CategoryManager?manager?
=
?getManager();
????????????List?options
=
null
;
????????????
????????????
if
(type
==
Constants.SORT_VALUE_ARCHIVE_YEAR)
????????????????options
=
getArchiveYear();
????????????
if
(options
==
null
||
options.size()
==
0
)
????????????????options
=
UMParameterUtil.getParameters(type);
????????????
????????????
if
(options
==
null
||
options.size()
==
0
)
???????????????options
=
?manager.getCategorys(type);
????????????
????????????BaseCategoryDTO?dto;
????????????ParametersDTO?param;
????????????Object?o?
=
?
null
;

????????????
if
?(bean?
!=
?
null
)
????????????????????o?
=
?RequestUtils.lookup(pageContext,?bean,?property,?scope);
???????????
????????????
if
?(o?
!=
?
null
?
&&
?((?
!
(o?
instanceof
?Integer))
&&
(?
!
(o?
instanceof
?Long))
&&
?(
!
(o?
instanceof
?List))
&&
?(
!
(o?

instanceof
?Long[]))?))
????????????????????
throw
?
new
?JspException(
????????????????????????????
"
bean?or?property?must?be?instanceof?Long?or?List
"
);
????????????
????????????out.print(
"
<select?
"
?
+
?TaglibUtil.attrFormat(
"
name
"
,?name));
????????????out.print(TaglibUtil.attrFormat(
"
id
"
,?id));
????????????out.print(TaglibUtil.attrFormat(
"
multiple
"
,?multiple));
????????????out.print(TaglibUtil.attrFormat(
"
class
"
,?styleClass));
????????????out.print(TaglibUtil.attrFormat(
"
size
"
,?String.valueOf(size)));
????????????out.print(TaglibUtil.attrFormat(
"
onchange
"
,?onchange));
????????????out.print(TaglibUtil.attrFormat(
"
style
"
,?style));
????????????out.print(TaglibUtil.attrFormat(
"
disable
"
,?disable));
????????????out.print(
"
>
"
);
????????????
if
?(showAll)?out.print(
"
<option?value=-1>不限</option>
"
);
????????????
if
?(showNull)?out.print(
"
<option?value=''></option>
"
);
????????????????printOption(out,?options,?o);
??out.print(
"
</select>
"
);

?}
?
catch
?(IOException?ioException)?
{
????????????
throw
?
new
?JspException(ioException.getMessage());
????????}
//
catch
????????
return
?(SKIP_BODY);
????????
//
return?super.doStartTag();
????}
注:
有options= manager.getCategorys(type);其中manager是CategoryManager類。此方法返回的一個List就是下拉框的值。具體實現可由我們自己來定義好了!記得在JSP中也有<test:category name="dto..id" type="17"/>,其中的type="17"(比如說可以是傳一個DB中的一個表的一個外鍵)就是此方法中的初始化參數值了(關于此標簽庫的定義的一些setter and getter方法中也舍了).既然是庫當然要通用。這個type就是通用的一個關鍵入口,不過顯然這樣一樣可讀性打了幾分折扣。
TaglibUtil.attrFormat("name", name)的方法如下:
public
?
class
?TaglibUtil?
{


?
public
?
static
?String?attrFormat(String?attrName,?Object?attrValue)?
{
?????
if
?(attrValue
!=
null
)
?????????
return
?
"
?
"
?
+
?attrName?
+
?
"
=
"
?
+
?
"
\
""
?+?attrValue?+?
"
\
""
;
?????
else
?????????
return
?
"
?
"
;
?}
}
還有一個就是printOption,這個方法應該比較重要了。它負責生成了列表框的選擇的值與名稱。如:
?
if
?(
!
excludeFlag)?
{
????????????out.print(
"
<option?
"
????????????????????
+
?TaglibUtil.attrFormat(
"
value
"
,?id
????????????????????????????.toString()));
????????????out.println(TaglibUtil.attrFormat(
"
sysValue
"
,?sysValue));

????????????
if
(o
!=
null
)
{

????????????????
if
(o?
instanceof
?Long)
{
????????????????????
if
?(id.equals(o))?out.print(
"
selected?
"
);
????????????????}
????????????????
else
????????????????????
if
(o?
instanceof
?List)
{
????????????????????????
if
?(((List)o).contains(id))?
????????????????????????????out.print(
"
selected?
"
);??
????????????????????}
else
?

????????????????????????
if
(o?
instanceof
?Long[])
{
????????????????????????????
if
(isSelected(id,(Long[])o))
????????????????????????????????out.print(
"
selected?
"
);?
????????????????????????}
????????????}
???????????
//
?if?(dto.getId().equals(o))?out.print("selected?");
????????????out.print(
"
>
"
);
????????????out.print(name);
????????????out.print(
"
</option>
"
);
????????}
不要郁悶id是如何來的。當然是從options= manager.getCategorys(type)中來的了。
也許說得不是太詳細,代碼也有些殘缺。不過實現過程基本全在這里了。我覺得它非常棒,直到我用到它的onchange,style時!簡直在直接跟使用html中的list一樣!
out.print(TaglibUtil.attrFormat("size",?String.valueOf(size)));
????????????out.print(TaglibUtil.attrFormat("onchange",?onchange));
????????????out.print(TaglibUtil.attrFormat("style",?style));
????????????out.print(TaglibUtil.attrFormat("disable",?disable));

至少給我們指明了一些自定義標簽庫的經驗!