struts2實戰:全文搜索引擎
轉載請注明出處:https://blog.csdn.net/zbf8441372本文對自己開發的基於lucene和J2EE技術的搜索引擎開發經驗進行簡單總結。今後可能會從性能的角度總結lucene開發經驗。當數據上TB級別後,分布式lucene以及結合分布式文件係統(如HDFS)或NoSQL等問題應該會成為我的技術關鍵點。而本文主要介紹struts2.0的關鍵特性和實踐經驗。
1. struts如何獲得前台參數?
struts2通過struts.xml,使struts中的action或者intercepter與某一jsp對應
<package name="main" extends="struts-default"> <global-results> <result name="search">/test.jsp</result> </global-results> <action name="DoSearch" method="searchResult"> <result name="success">/search.jsp</result> <result name="error">/nobook.jsp</result> </action> </package>
最簡單的是前台可以是一個form表單。這個表單可以是用html的標簽寫,也可以是用struts的標簽寫。表達對應一個action,並傳回一個帶參數的url。
前台的url通過 ActionName?var1=xx&var2=yy 的形式傳給特定action如:
/DoSearch?sk=物理&type=title
這裏的ActionName會在struts.xml裏匹配,找到對應的action.java。
傳進去的參數,如sk和type,需要在action.java裏以同一名稱聲明,並設置getter, setter函數。區別於servlet通過request.getParameterName()的後台讀取前台參數方式,struts的getter和setter將完成這些步驟。
2. 前台如何讀取struts內容?
第一種:struts標簽傳。
<li>總共花費 <font color="red" ><s:text name="time"></s:text></font> ms, 找到 <font color="red" ><s:text name="count"></s:text></font>條記錄</li>
<s:iterator value="booklist" > 作者:${BookAttributes.creator} <br /> 分類:${BookAttributes.CRC} <br /> ISBN:${BookAttributes.ISBN} <br /> 出版日期:${BookAttributes.date} <br /> <!-- do something--> </s:iterator>
以上兩種是常用的通過struts標簽來傳輸變量到前台的方式。但是,有時候無法滿足我們的需求。
比如:如何在一個iterator內,加入另一個遍曆?action的兩個list需要在一個遍曆內輸出結果,而且list裏每一個對象又是一個類。
我的解決方法是用request來處理。
有幾點要知道的是:
1. struts的變量是如何用標簽付到前台的?
是用setter函數,或者說本質上就是request來做的。
2. 標簽不是完全可以滿足action變量往前台輸送嗎?
不是的。這裏涉及到Java對象, Js對象, Action內的對象在同一個jsp頁麵內到底能怎樣互通。每個action對應唯一一個jsp,action的標簽按上麵第一個問題說的,本質上是reuqest根據setter函數來回傳的,同時,這個回傳標簽也可以賦給一個html標簽的value值:
<input type=hidden value="<s:text name='sk'></s:text>" ></input>(用hidden的原因是,這個是我藏起來讓js代碼去用的方式,可能比較蠢,但是很簡單好操作)
但是,struts標簽無法賦給js變量,無法賦給<% %>內的java變量,他永遠隻是個setter方法,當你的值是一個對象,比如一個List時,你這樣賦的結果,就是一個list.toString()的值,對象的屬性不能獲取,對象在標簽下就死掉了。有的人會說,那就用iterator啊。是的,但是我遇到的問題是iterator下,我需要得到兩個list的遍曆。
所以我的方法是結合request,把action中第二個list變量讀給java,處理之後傳給需要的vaue。見下文。
第二種:用request。
一般可以用struts標簽傳就用struts標簽傳。因為那是struts的特性。這種request的方式是最原始的方式。
記得要在jsp聲明導入包
<%@page import="org.apache.struts2.ServletActionContext"%>然後因為action隻唯一在一個jsp裏書寫,所以
request.getAttribute()
直接獲得值。
iterator下,我需要得到兩個list的遍曆的時候,我就在iterator之前,先聲明一個計數值
<% int i = 0; %> <s:iterator value="booklist" > <% i ++; %> </s:iterator>
這樣就可以對action中任意多的list進行同時遍曆,並且java代碼來直接操作各種動作。
看個實例:
<% // 通過循環變量i和request,從action讀取list,用java處理成正確的url。struts標簽沒辦法做雙重循環,也取不了list內的類的某個變量 List<BookAttributes> ba = (ArrayList<BookAttributes>)request.getAttribute("booklist"); String cata1 = ba.get(i).getCRC().substring(0, 1); String cata2 = ba.get(i).getCRC().substring(0, 2); String cata3 = ba.get(i).getCRC().substring(0, 3); String url1 = "Classify.action?CateId=" + cata1; String url2 = "Classify.action?CateId=" + cata2; String url3 = "Classify.action?CateId=" + cata3; i ++; %> <span id=m_fl><a href=<%=url1%>>${BookAttributes.firstCat}</a>-><a href=<%=url2%>>${BookAttributes.secondCat}</a>-><a href=<%=url3%>>${BookAttributes.thirdCat}</a></span><br>
第三種:異步json取。
這種方法在下麵敘述。
3. struts2如何實現異步交互?
struts配置裏可以把action以json格式返回,不指定jsp頁麵。
<package name="test" extends="json-default"> <action name="ShowAddup" > <result type="json"></result> </action> <action name="ShowBaidu" > <result type="json"></result> </action> </package>
同時,前台可以用Ajax或者Jquery封裝過的Ajax來提交url,並且在回調函數的data內獲得action裏所有的標量
下麵代碼演示了getJSON方法傳參並且通過DOM或者jquery等操作把回調函數內的data裏的相應變量寫到js的某些特定標簽內。這裏麵對於js,jquery的靈活操作和使用就不介紹了,例子中可以看到一些處理方式。
$.getJSON( url3 ,function(data,state){ var pagelist = data.pagelist; var pagecontentlist = data.pagecontentlist; var num = pagecontentlist.length; $("#listbooks").hide(); //$("#pagecontent").innerHTML = ''; document.getElementById("pagecontent").innerHTML=" "; // 清空處理 document.getElementById("pagecontent").style.marginLeft="35px"; document.getElementById("pagecontent").style.marginRight="20px"; for (var i = 0; i < num; i ++) { $("#pagecontent").append("<font color=blue style='font-size:13px;'><b>出現的書頁在: " + pagelist[i].substring(0,7) + "頁<b/></color>"); $("#pagecontent").append("<br/>"); if (pagecontentlist[i].length > 450) { pagecontentlist[i] = pagecontentlist[i].substring(0, 450); $("#pagecontent").append("<font color=Chocolate>該頁的內容為: </font><font color=darkgrey style='font-size:12px; letter-spacing:0px;'><br />" + pagecontentlist[i] + "</color> " ); $("#pagecontent").append("<font color=LightSkyBlue style='font-size:13px;'><b><u>more(閱讀全文)...</u></b></font> <br/> <br/>"); } else { $("#pagecontent").append("<font color=lightblue>該頁的內容為: </font><font color=darkgrey style='font-size:12px; letter-spacing:0px;'><br />" + pagecontentlist[i] + "</color> <br/> <br/>" ); } yit(document.body, sk); // 再加亮下 } } , "json");
jquery是js的庫。提供一篇介紹比較清楚的文章, 你就可以很清楚了解到jquery可以為前台做什麼:Jquery學習筆記
上麵的
$.getJSON();
隻是一種,其他方法詳見:深入理解jQuery中$.get、$.post、$.getJSON和$.ajax的用法
異步方法,第一,帶來了更好的用戶體驗。第二,我在搜索的時候,form形式的直接傳遞隻能處理一個action,當我需要進行搜索的同時進行別的操作,比如對搜索結果進行統計的時候,我就不能把兩件事放在同一個action裏做,因為統計會延時搜索結果的輸出,搜索結果必定是ms內的事。這時候,就需要一個請求,對應多個action做。
當時在解決這個問題的時候,繞了很多彎路。簡單的說,action唯一對應一個書寫jsp,而jsp內可以有映射多個action,當然多個action可以指定寫在一個jsp裏。這個基本出發點一定要清晰。這樣的話,異步,同步的調用,返回的結果如何在前台顯示都可迎刃而解,具體各種方式我也在前麵說明了。
對struts,jquery,js,ajax的使用是一邊開發一邊學著用的,以上是我開發過程中總結的一些使用方式和注意點。struts的action同樣可以用spring的bean來管理,struts的intercepter也是一塊內容,我是沒有涉及到的。詳見:Struts2攔截器的使用 或者大家可以查別的資料。
對struts2.0的總體使用感覺是,代碼比servlet少很多,配置很靈活,各種標簽需要熟練掌握,比如上麵沒有提到,可以用這樣的方式來傳遞url給action:
<s:url id='url' action='Classify'> <s:param name="CateId" value="%{'N'}"></s:param> </s:url> <s:a href="%{url}">自然科學總論</s:a> <s:url id='url' action='Classify'> <s:param name="CateId" value="%{'O'}"></s:param> </s:url> <s:a href="%{url}">數理化</s:a> <s:url id='url' action='Classify'> <s:param name="CateId" value="%{'P'}"></s:param> </s:url> <s:a href="%{url}">天文、地球</s:a>
展示上的問題都克服了之後,再從性能的角度來分析lucene的使用。
最後再給一篇比較簡明易懂的文章:struts2+jquery+json集成
鑒於我拙劣的表達,附上上麵的幾份參考資料:
深入理解jQuery中$.get、$.post、$.getJSON和$.ajax的用法
最後更新:2017-04-02 17:09:25