Blog信息 |
blog名称: 日志总数:1304 评论数量:2242 留言数量:5 访问次数:7594666 建立时间:2006年5月29日 |

| |
[Java Open Source]Integrate Compass, Appfuse, DisplayTag Tutorial Part 4 软件技术
lhwork 发表于 2007/1/23 9:01:30 |
The goal of this tutorial is to create the struts action that performs search functions
All codes in part 4 could be download here
I remove lib, extra, docs folder to reduce size.
Compass 1.0 src comes with sample coeds for web.
Since I use struts for web framework, I pick up codes there and do some modification ^^.
Step 1. Add Codes from Compass sample web to Appfuse.
1. Copy CompassSearchCommand.java, CompassSearchResults.java and add them to src/web ... /util/
You could find them in compass-1.1M1-with-dependencies\compass-1.1M1\src\main\src\org\compass\spring\web\mvc
Change the package name to org.myapp.webapp.util You could check the screen here. 2. Edit Constants.java, you should find it in src/dao
Add a new constant value below public static final Integer PAGE_SIZE = 10; This value determine the page size compass should uses. 3. Create "BaseCompassAction.java" under src/web ... /action/ and add codes below
------ start here ------ package org.myapp.webapp.action;
import org.compass.core.CompassDetachedHits;import org.compass.core.CompassHits;import org.compass.core.CompassQuery;import org.compass.core.CompassSession;import org.myapp.Constants;import org.myapp.webapp.util.CompassSearchCommand;import org.myapp.webapp.util.CompassSearchResults;
public class BaseCompassAction extends BaseAction{
private Integer pageSize = Constants.PAGE_SIZE; public Integer getPageSize() { return pageSize; }
public void setPageSize(Integer pageSize) { this.pageSize = pageSize; }
protected CompassSearchResults performSearch(CompassSearchCommand searchCommand, CompassSession session) { long time = System.currentTimeMillis(); CompassQuery query = buildQuery(searchCommand, session); CompassHits hits = query.hits(); CompassDetachedHits detachedHits; CompassSearchResults.Page[] pages = null; if (pageSize == null) { doProcessBeforeDetach(searchCommand, session, hits, -1, -1); detachedHits = hits.detach(); } else { int iPageSize = pageSize.intValue(); int page = 0; int hitsLength = hits.getLength(); if (searchCommand.getPage() != null) { page = searchCommand.getPage().intValue(); } int from = page * iPageSize; if (from > hits.getLength()) { from = hits.getLength() - iPageSize; doProcessBeforeDetach(searchCommand, session, hits, from, hitsLength); detachedHits = hits.detach(from, hitsLength); } else if ((from + iPageSize) > hitsLength) { doProcessBeforeDetach(searchCommand, session, hits, from, hitsLength); detachedHits = hits.detach(from, hitsLength); } else { doProcessBeforeDetach(searchCommand, session, hits, from, iPageSize); detachedHits = hits.detach(from, iPageSize); } doProcessAfterDetach(searchCommand, session, detachedHits); int numberOfPages = (int) Math.ceil((float) hitsLength / iPageSize); pages = new CompassSearchResults.Page[numberOfPages]; for (int i = 0; i < pages.length; i++) { pages[i] = new CompassSearchResults.Page(); pages[i].setFrom(i * iPageSize + 1); pages[i].setSize(iPageSize); pages[i].setTo((i + 1) * iPageSize); if (from >= (pages[i].getFrom() - 1) && from < pages[i].getTo()) { pages[i].setSelected(true); } else { pages[i].setSelected(false); } } if (numberOfPages > 0) { CompassSearchResults.Page lastPage = pages[numberOfPages - 1]; if (lastPage.getTo() > hitsLength) { lastPage.setSize(hitsLength - lastPage.getFrom()); lastPage.setTo(hitsLength); } } } time = System.currentTimeMillis() - time; CompassSearchResults searchResults = new CompassSearchResults(detachedHits.getHits(), time); searchResults.setPages(pages); return searchResults; } /** * Acts as an extension point for search controller that wish to build * different CompassQueries. <p/> The default implementation uses the * session to create a query builder and use the queryString option, i.e.: * <code>session.queryBuilder().queryString(searchCommand.getQuery().trim()).toQuery();</code>. * <p/> Some other interesting options might be to add sorting to the query, * adding other queries using a boolean query, or executing a different * query. */ protected CompassQuery buildQuery(CompassSearchCommand searchCommand, CompassSession session) { return session.queryBuilder().queryString(searchCommand.getQuery().trim()).toQuery(); }
/** * An option to perform any type of processing before the hits are detached. */ protected void doProcessBeforeDetach(CompassSearchCommand searchCommand, CompassSession session, CompassHits hits, int from, int size) {
}
/** * An option to perform any type of processing before the hits are detached. */ protected void doProcessAfterDetach(CompassSearchCommand searchCommand, CompassSession session, CompassDetachedHits hits) {
}}
------ end here------ Since I do not want to change codes in BaseAction. I create an action class extend from BaseAction. Put the Compass search related code in this class The original codes comes from CompassSearchController.java You could find it in compass-1.1M1-with-dependencies\compass-1.1M1\src\main\src\org\compass\spring\web\mvc
4. Edit "CompassAction.java", append a new ActionForward named "list"
You could copy below codes and overwrite exit CompassAction.java. ------ start here ------ package org.myapp.webapp.action;
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import org.compass.core.Compass;import org.compass.core.CompassCallback;import org.compass.core.CompassException;import org.compass.core.CompassHit;import org.compass.core.CompassSession;import org.compass.core.CompassTemplate;import org.compass.core.CompassTransaction;import org.compass.gps.CompassGps;import org.myapp.webapp.util.CompassSearchCommand;import org.myapp.webapp.util.CompassSearchResults;import org.springframework.util.StringUtils;
/** * * * @struts.action name="compassForm" path="/compass" scope="request" * validate="false" parameter="method" input="mainMenu" * * @struts.action-forward name="list" path="/WEB-INF/pages/compassList.jsp" * */public final class CompassAction extends BaseCompassAction { public ActionForward createIndex(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("Enter createIndex method"); CompassGps compassGps = (CompassGps) getBean("compassGps"); boolean isRun = compassGps.isRunning(); System.out.println("isRun : "+ isRun); if(!isRun){ compassGps.start(); } compassGps.index(); return mapping.findForward("list"); } public ActionForward deleteIndex(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("Enter deleteIndex method"); Compass compass = (Compass) getBean("compass"); CompassGps compassGps = (CompassGps) getBean("compassGps"); boolean isRun = compassGps.isRunning(); System.out.println("isRun : "+ isRun); if(isRun){ compassGps.stop(); } compass.getSearchEngineIndexManager().deleteIndex(); return mapping.findForward("list"); } public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return list(mapping, form, request, response); }
public ActionForward list(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("Enter list method"); String query = request.getParameter("query"); String pageStr = request.getParameter("page"); Integer page = Integer.parseInt(pageStr); final CompassSearchCommand searchCommand = new CompassSearchCommand(); searchCommand.setPage(page); searchCommand.setQuery(query); if (!StringUtils.hasText(searchCommand.getQuery())) { return mapping.findForward("list"); } Compass compass = (Compass) getBean("compass"); CompassSearchResults searchResults; searchResults = (CompassSearchResults) new CompassTemplate(compass).execute( CompassTransaction.TransactionIsolation.READ_ONLY_READ_COMMITTED, new CompassCallback() { public Object doInCompass(CompassSession session) throws CompassException { return performSearch(searchCommand, session); } }); CompassHit[] cha = searchResults.getHits(); System.out.println("hit length : "+ cha.length); request.setAttribute("CompassHits", cha); return mapping.findForward("list"); } }
------ end here------ Notice that I change extends from BaseAction to BaseCompassAction ^^ 5. Create Action Test. ant test it.
Create "CompassListActionTest.java" under test/web ... /action/ and add below codes ------ start here ------ package org.myapp.webapp.action;
import org.compass.core.CompassHit;
public class CompassListActionTest extends BaseStrutsTestCase {
public CompassListActionTest(String name) { super(name); }
protected void setUp() throws Exception { super.setUp(); getMockRequest().setUserRole("admin"); } /* * jack Contain the term jack in the default search field * jack london (jack or london) Contains the term jack or london, or both, in the default search field * +jack +london (jack and london) Contains both jack and london in the default search field * name:jack Contains the term jack in the name property (meta-data) * * name:jack -city:london (name:jack and not city:london) Have jack in the name property and don't have london in the city property * * name:"jack london" Contains the exact phrase jack london in the name property * name:"jack london"~5 Contain the term jack and london within five positions of one another * jack* Contain terms that begin with jack * jack~ Contains terms that are close to the word jack * * birthday:[1870/01/01 TO 1920/01/01] Have the birthday values between the specified values. Note that it is a lexicography range */ public void testList_1() throws Exception { setRequestPathInfo("/compass"); addRequestParameter("method", "list"); addRequestParameter("query", "title*"); addRequestParameter("page", "0"); actionPerform();
verifyForward("list"); verifyNoActionErrors(); CompassHit[] cha = (CompassHit[])request.getAttribute("CompassHits"); assertTrue(cha.length == 3); } public void testList_2() throws Exception { setRequestPathInfo("/compass"); addRequestParameter("method", "list"); addRequestParameter("query", "title:title01"); addRequestParameter("page", "0"); actionPerform();
verifyForward("list"); verifyNoActionErrors(); CompassHit[] cha = (CompassHit[])request.getAttribute("CompassHits"); assertTrue(cha.length == 1); } public void testList_3() throws Exception { setRequestPathInfo("/compass"); addRequestParameter("method", "list"); addRequestParameter("query", "title001"); addRequestParameter("page", "0"); actionPerform();
verifyForward("list"); verifyNoActionErrors(); CompassHit[] cha = (CompassHit[])request.getAttribute("CompassHits"); assertTrue(cha.length == 1); } }
------ end here------ Here I create three query strings for test, "title*", "title:title01", "title001" The length shoud be 3, 1, 1, according to our test data ^^ Summary
If all ok, now you have CompassHit[] in your request scope. Now we can layout the jsp ^^ Perfect ?, Maybe = = We appreiciate a layout lib like displaytag could help us layout easier In next part, we will integrate DisplayTag to help us layout. |
|
|