關于<html:link>标簽在URI後面傳參數的問題
在struts标簽<html:link>的page屬性指定的URI後面傳遞參數可以有幾種方式:
1.若明确參數名和參數值則直接在URI後輸出,
如:<html:link page="/test.do?action=add">add</html:link>
2.對于參數值不确定的,paramName和paramProperty來輸出,用paramId屬性指定參數名。
對于paramName指定的對象應該存在于page、request、session、application其中之一。一般來說,是從Action類傳過來的,作為request的屬性之一(requst.setAttribute("name",object))。
如果paramName指定的對象是action的ActionForm,則無需使用request.setAttribute方法。
例:<html:link page="/test.do" paramId="userid" paramName="uid">uname</html:link>
若參數值是一個bean對象的屬性值(比如ActionForm,或者集合中存放的對象)則:
<html:link page="/test.do" paramId="userid" paramName="user" paramProperty="uid">uname</html:link>
3.若兩個參數,一個确定一個不确定,則是以上兩種方法的結合,即:
<html:link page="/test.do?action=modify" paramId="userid" paramName="uid">modify</html:link>
4.對于多個參數的問題,可以使用一個HashMap集合對象來存放所有的參數名及對應的參數值的方式,paramName屬性值指定為該HashMap集合對象即可。
舉例:
<%
//代碼理想的位置應該是在action中
//可以在jsp頁面測試
java.util.HashMap pms = new java.util.HashMap();
pms.put("code", "001002");
pms.put("name", "tester");
pms.put("alias", new String[]{"matin","jack"});
request.setAttribute("params", pms);
%>
<html:link action="/test.do" name="params" >test</html:link>
編譯後的結果:<a href="/test.do?code=001002&name=tester&alias=matin&alias=jack" target="_blank" rel="external nofollow" >test</a>
這種方式雖然可以解決傳多參數的問題,但是實作起來也比較麻煩,特别是對記錄集中的資料逐條列出的時候
5.針對有的網友在<html:link>标簽中嵌入使用jsp腳本(scriptlet)的問題,
例如:
<html:link page="/test.do?code=<%=varible%>">add</html:link>,這種寫法是錯誤的,是無法編譯的。
有的網友認為在struts标簽内是不允許使用jsp腳本的,這種說法也不準确。如果前面的寫法改成:
<html:link page="<%="/test.do?code="+varible%>">add</html:link>,就可以被執行,但是要注意URL相對路徑的問題。
雖然在struts标簽中嵌入jsp腳本不是真正意義上的struts應用,但是有時在委曲求全的情況下也隻能如此了,除非使用自定義标簽。比如在form表單中可能需要根據具體資料讓某個字段是隻讀的,就可以用嵌入jsp腳本來實作:
<%
boolean rdonly=false;
if(2==2) rdonly=true;
%>
<html:text property="userid" readonly="<%=rdonly%>" />
6.另外一種比較變态的方法,既不是真正意義上的struts,也不符合xml規範。那就是在<a>标簽中用<bean:write>标簽輸出參數值。
如:<a href="test.do?uid=<bean:write name=" target="_blank" rel="external nofollow" user" property="userid"/>&name=<bean:write name="user" property="username"/>">test</a>
了解到這裡之後,感覺到一絲遺憾,因為如果隻有paramId,paramName,paramProperty這三個屬性的話,那麼對于html:link标簽來說,就永遠隻能自定義一個參數,如果需要定義多個參數,如http://serverip:portno/projectcontextname/html-link.do?a=3&b=5&y=9這樣的連結URL來說,就無能為力了
如果要定義多個參數,就需要手動拼URL,定義在page屬性裡面,這就失去了使用标簽的意義了。
在此情況下,懷着失望的心情,打開了Struts的源碼,開始檢視這個标簽的源碼,忽然發現,這個标簽完全是可以自定義多個參數的,關鍵就在name屬性上
首先來看一段如何自定義多個參數的代碼,如下:
=========================================================
<%
java.util.HashMap newValues = new java.util.HashMap();
newValues.put("floatProperty", new Float(444.0));
newValues.put("intProperty", new Integer(555));
newValues.put("stringArray", new String[]
{ "Value1", "Value2", "Value3" });
pageContext.setAttribute("newValues", newValues);
%>
<html:link page="/html-link.do" name="newValues">
Float, int, and stringArray via name (Map)
</html:link>
=========================================================
原來使用name屬性就可以将一個Map類型的變量放入request、session、application、page四種範圍的容器内,然後取個key值,填在name屬性裡就可以了
Struts将自動讀取這個Map類型對象的所有key和key所定義的對象,然後自動生成HTML代碼
好比上述的例子,将生成如下的HTML代碼:
<a href="http://serverip:portno/projectcontextname/html-link.do?stringArray=Value1&stringArray=Value2&stringArray=Value3&floatProperty=444.0&intProperty=555">
Float, int, and stringArray via name (Map)</a>
願望終于達到了,也充分證明了Struts的實力,但在這段實作中,查找name定義的對象這點在前面幾次的源碼剖析中已經很明确了(使用的是TagUtils.java中的lookup方法)
但得到這個對象後,Struts是如何讀出key值集合和key值對應的對象的呢?代碼在此:
=========================================================
// Add the required request parameters
boolean question = temp.indexOf(?) >= 0;
//這裡的params變量就是我們輸入的Map類型的對象
//就是這句代碼可以得到key值集合
Iterator keys = params.keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
Object value = params.get(key);
if (value == null) {
if (!question) {
url.append(?);
question = true;
} else {
url.append(separator);
}
url.append(this.encodeURL(key));
url.append(=); // Interpret null as "no value"
} else if (value instanceof String) {
if (!question) {
url.append(?);
question = true;
} else {
url.append(separator);
}
url.append(this.encodeURL(key));
url.append(=);
url.append(this.encodeURL((String) value));
} else if (value instanceof String[]) {
String values[] = (String[]) value;
for (int i = 0; i < values.length; i++) {
if (!question) {
url.append(?);
question = true;
} else {
url.append(separator);
}
url.append(this.encodeURL(key));
url.append(=);
url.append(this.encodeURL(values[i]));
}
} else {
if (!question) {
url.append(?);
question = true;
} else {
url.append(separator);
}
url.append(this.encodeURL(key));
url.append(=);
url.append(this.encodeURL(value.toString()));
}
}
以上是看一個網友的Blog上得來的,自己正在被這個問題困擾,在那本<struts程式員查詢辭典>,關于<html:link>标簽的name屬性上是這麼說明的:指定其元素作為查詢字元串參數添加到目前連結的URL中的java.util.map對象的名字.如果還指定了property屬性,該屬性定義的對象中的某個字段将調用一個擷取值的方法,來傳回其元素作為查詢字元串參數被添加到目前連接配接的URL的java.util.map對象.
偶最終的實作方法,無奈,有時間再研究吧!
<a href="../legalaid/legalAidSeAction.do?action=select7&id=<bean:write name=" target="_blank" rel="external nofollow" legalaid3" property="ID"/>&t19_n04=<bean:write name="legalaid3" property="t19_n04"/>">
<bean:write name="legalaid3" property="t19_c02"/>
</a>