이 콘텐츠는 선택한 언어로 제공되지 않습니다.

1.9.2. Bookmarkable search results page


The blog example has a small form at the top right of each page that allows the user to search for blog entries. This is defined in menu.xhtml, which is included by the Facelets template template.xhtml:
<div id="search"> 
  <h:form> 
    <h:inputText value="#{searchAction.searchPattern}"/> 
    <h:commandButton value="Search" action="/search.xhtml"/> 
  </h:form> 
</div>
Copy to Clipboard Toggle word wrap
To implement a bookmarkable search results page, after the search form submission is processed, we must perform a browser redirect. Because the JSF view ID is used as the action outcome, Seam automatically redirects to the view ID when the form is submitted. We could also have defined a navigation rule as follows:
<navigation-rule> 
  <navigation-case> 
    <from-outcome>searchResults</from-outcome> 
    <to-view-id>/search.xhtml</to-view-id> 
    <redirect/> 
  </navigation-case> 
</navigation-rule>
Copy to Clipboard Toggle word wrap
In that case, the form would have looked like this:
<div id="search"> 
  <h:form> 
    <h:inputText value="#{searchAction.searchPattern}"/> 
    <h:commandButton value="Search" action="searchResults"/> 
  </h:form> 
</div>
Copy to Clipboard Toggle word wrap
However, to get a bookmarkable URL like http://localhost:8080/seam-blog/search/, the values submitted with the form must be included in the URL. There is no easy way to do this with JSF, but with Seam, only two features are required: page parameters and URL rewriting. Both are defined here in WEB-INF/pages.xml:
 <pages>
  <page view-id="/search.xhtml">
    <rewrite pattern="/search/{searchPattern}"/> 
    <rewrite pattern="/search"/>

    <param name="searchPattern" value="#{searchService.searchPattern}"/>

  </page>
  ...
</pages>
			
			
			

Copy to Clipboard Toggle word wrap
The page parameter instructs Seam to link the searchPattern request parameter to the value held by #{searchService.searchPattern}, whenever the search page is requested, and whenever a link to the search page is generated. Seam takes responsibility for maintaining the link between URL state and application state.
The URL for a search on the term book would ordinarily be http://localhost:8080/seam-blog/seam/search.xhtml?searchPattern=book. Seam can simplify this URL by using a rewrite rule. The first rewrite rule, for the pattern /search/{searchPattern}, states that whenever a URL for search.xhtml contains a searchPattern request parameter, that URL can be compressed into a simplified URL. So, the earlier URL (http://localhost:8080/seam-blog/seam/search.xhtml?searchPattern= book) can instead be written as http://localhost:8080/seam-blog/search/book.
As with page parameters, rewriting URLs is bidirectional. This means that Seam forwards requests for the simplified URL to the correct view, and it automatically generates the simplified view — users need not construct URLs. The entire process is handled transparently. The only requirement for rewriting URLs is to enable the rewrite filter in components.xml:
<web:rewrite-filter view-mapping="/seam/*" />
Copy to Clipboard Toggle word wrap
The redirect takes us to the search.xhtml page:
<h:dataTable value="#{searchResults}" var="blogEntry">
 <h:column>
   <div>
      <s:link view="/entry.xhtml" propagation="none" 
              value="#{blogEntry.title}">
        <f:param name="blogEntryId" value="#{blogEntry.id}"/>
      </s:link>
      posted on 
      <h:outputText value="#{blogEntry.date}">
        <f:convertDateTime timeZone="#{blog.timeZone}" 
                           locale="#{blog.locale}" type="both"/>
      </h:outputText>
    </div>
  </h:column>
</h:dataTable>
Copy to Clipboard Toggle word wrap
Again, this uses "pull"-style MVC to retrieve the search results with Hibernate Search.
@Name("searchService")
public class SearchService {
   
  @In
  private FullTextEntityManager entityManager;
   
  private String searchPattern;
   
  @Factory("searchResults")
  public List<BlogEntry> getSearchResults() {
  if (searchPattern==null || "".equals(searchPattern) )
    {
      searchPattern = null;
      return entityManager.createQuery(
                "select be from BlogEntry be order by date desc"
              ).getResultList();
    }
      else
        {
          Map<String,Float> boostPerField = new HashMap<String,Float>();
          boostPerField.put( "title", 4f );
          boostPerField.put( "body", 1f );
          String[] productFields = {"title", "body"};
          QueryParser parser = new MultiFieldQueryParser(productFields, 
                               new StandardAnalyzer(), boostPerField);
          parser.setAllowLeadingWildcard(true);
          org.apache.lucene.search.Query luceneQuery;
          try
            {
              luceneQuery = parser.parse(searchPattern);
            }
          catch (ParseException e)
            {
              return null;
            }

          return entityManager
            .createFullTextQuery(luceneQuery, BlogEntry.class)
            .setMaxResults(100)
            .getResultList();
        }
    }

    public String getSearchPattern()
    {
      return searchPattern;
    }

    public void setSearchPattern(String searchPattern)
    {
      this.searchPattern = searchPattern;
    }

}
Copy to Clipboard Toggle word wrap
맨 위로 이동
Red Hat logoGithubredditYoutubeTwitter

자세한 정보

평가판, 구매 및 판매

커뮤니티

Red Hat 문서 정보

Red Hat을 사용하는 고객은 신뢰할 수 있는 콘텐츠가 포함된 제품과 서비스를 통해 혁신하고 목표를 달성할 수 있습니다. 최신 업데이트를 확인하세요.

보다 포괄적 수용을 위한 오픈 소스 용어 교체

Red Hat은 코드, 문서, 웹 속성에서 문제가 있는 언어를 교체하기 위해 최선을 다하고 있습니다. 자세한 내용은 다음을 참조하세요.Red Hat 블로그.

Red Hat 소개

Red Hat은 기업이 핵심 데이터 센터에서 네트워크 에지에 이르기까지 플랫폼과 환경 전반에서 더 쉽게 작업할 수 있도록 강화된 솔루션을 제공합니다.

Theme

© 2026 Red Hat