这个例子使用Struts2+Spring2+Hibernate3组合来配合Compass2+Lucene2实现全文检索功能。
这个工程是在MyEclipse6下开发的。数据库使用MySQL5。
新建数据库,库名:compass。
/* MySQL Data Transfer Source Host: localhost Source Database: compass Target Host: localhost Target Database: compass Date: 2008-6-8 10:27:30 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for books -- ---------------------------- CREATE TABLE `books` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `NM` varchar(100) DEFAULT NULL, `CNT` text, `ISBN` char(10) DEFAULT NULL, `PBLDT` date DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=gbk; -- ---------------------------- -- Records -- ---------------------------- INSERT INTO `books` VALUES ('1', 'Lucene IN Action 中文版', '这是一本关于Java的查询引擎的书。', '7121032171', '2007-01-01'); INSERT INTO `books` VALUES ('2', 'Spring 2.0 技术手册', '林信良写的一本关于Spring的书。', '7121039580', '2007-04-01'); INSERT INTO `books` VALUES ('4', '林信良学Lunece', '林信良学习Lunece的一本书', '1234567890', '2008-06-01'); INSERT INTO `books` VALUES ('9', 'Hibernate 深入浅出', '这是一本关于Hibernate的好书。', '7121006707', '2005-06-01'); INSERT INTO `books` VALUES ('10', 'Hibernate IN Action 中文版', '这是一本关于Hibernate的中文书', '1212121212', '2008-07-10'); INSERT INTO `books` VALUES ('11', 'Hibernate + Spring 中文系统', 'Hibernate + Spring 中文系统', '1234512345', '2008-06-06'); INSERT INTO `books` VALUES ('12', 'Hibernate 深入浅出2', 'Hibernate 深入浅出2', '2343454567', '2008-05-01'); INSERT INTO `books` VALUES ('13', 'Hibernate IN Action 中文版2', 'Hibernate IN Action 中文版2', '8888006707', '2009-06-01');
配置文件:
1.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>compass</display-name>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml,
/WEB-INF/serviceContext.xml,
/WEB-INF/dataAccessContext.xml,
/WEB-INF/compassContext.xml
</param-value>
</context-param>
<filter>
<filter-name>compass</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>compass</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
=========================================================================
2.log4j.properties
#Log4j
log4j.rootLogger=error, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p %c - %m%n
log4j.logger.org.compass=error
=========================================================================
3.jdbc.properties
#DataSource
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/compass?characterEncoding=gbk
jdbc.username=root
jdbc.password=root
jdbc.initialPoolSize=10
jdbc.minPoolSize=5
jdbc.maxPoolSize=30
jdbc.acquireIncrement=5
jdbc.maxIdleTime=10
jdbc.maxStatements=0
#Hibernate
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.jdbc.batch_size=20
hibernate.generate_statistics=true
=========================================================================
4.paoding-dic-home.properties
paoding.dic.home=C:/paoding/dic
paoding.dic.detector.interval=60
=========================================================================
5.struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<package name="soutyuu" extends="struts-default">
<action name="*book" class="com.cecltd.web.BookAction" method="{1}">
<result name="insert">jsp/insert.jsp</result>
<result name="search">jsp/search.jsp</result>
</action>
</package>
</struts>
=========================================================================
6.compass.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<compass-core-config
xmlns="http://www.compass-project.org/schema/core-config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.compass-project.org/schema/core-config
http://www.compass-project.org/schema/compass-core-config-2.0.xsd">
<compass name="default">
<connection>
<file path="C:/target" />
</connection>
<searchEngine>
<analyzer name="MyAnalyzer" type="CustomAnalyzer"
analyzerClass="net.paoding.analysis.analyzer.PaodingAnalyzer">
</analyzer>
</searchEngine>
</compass>
</compass-core-config>
=========================================================================
7.applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/jdbc.properties</value>
</property>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="initialPoolSize">
<value>${jdbc.initialPoolSize}</value>
</property>
<property name="minPoolSize">
<value>${jdbc.minPoolSize}</value>
</property>
<property name="maxPoolSize">
<value>${jdbc.maxPoolSize}</value>
</property>
<property name="acquireIncrement">
<value>${jdbc.acquireIncrement}</value>
</property>
<property name="maxIdleTime">
<value>${jdbc.maxIdleTime}</value>
</property>
<property name="maxStatements">
<value>${jdbc.maxStatements}</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>com/cecltd/domain/Book.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
${hibernate.dialect}
</prop>
<prop key="hibernate.show_sql">
${hibernate.show_sql}
</prop>
<prop key="hibernate.jdbc.batch_size">
${hibernate.jdbc.batch_size}
</prop>
<prop key="hibernate.generate_statistics">
${hibernate.generate_statistics}
</prop>
</props>
</property>
<property name="eventListeners">
<map>
<entry key="merge">
<bean
class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener" />
</entry>
</map>
</property>
</bean>
<bean id="compass" class="org.compass.spring.LocalCompassBean">
<property name="resourceLocations">
<list>
<value>classpath:com/cecltd/domain/Book.cmd.xml</value>
<value>classpath:com/cecltd/domain/Book.cpm.xml</value>
</list>
</property>
<property name="configLocation">
<value>/WEB-INF/compass.cfg.xml</value>
</property>
<property name="transactionManager">
<ref local="transactionManager" />
</property>
</bean>
<bean id="hibernateGpsDevice" class="org.compass.spring.device.hibernate.dep.SpringHibernate3GpsDevice">
<property name="name">
<value>hibernateDevice</value>
</property>
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop">
<property name="compass">
<ref bean="compass" />
</property>
<property name="gpsDevices">
<list>
<bean
class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">
<property name="gpsDevice" ref="hibernateGpsDevice" />
</bean>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
</beans>
=========================================================================
8.serviceContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="bookService" class="com.cecltd.service.impl.BookServiceImpl">
<property name="bookDao">
<ref bean="bookDao" />
</property>
<property name="bookCps">
<ref bean="bookCps" />
</property>
</bean>
</beans>
=========================================================================
9.dataAccessContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="bookDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="bookDaoTarget" />
</property>
<property name="transactionAttributes">
<props>
<prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="bookDaoTarget" class="com.cecltd.dao.jdbc.BookDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
</beans>
=========================================================================
10.compassContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="bookCps" class="com.cecltd.compass.impl.BookCpsImpl">
<property name="compass">
<ref bean="compass" />
</property>
</bean>
</beans>
=========================================================================
11.Book.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.cecltd.domain.Book" table="Books">
<id name="id" column="ID">
<generator class="native" />
</id>
<property name="name" column="NM" />
<property name="content" column="CNT" />
<property name="isbn" column="ISBN" />
<property name="pbl_dt" type="timestamp" column="PBLDT" />
</class>
</hibernate-mapping>
=========================================================================
12.Book.cpm.xml
<?xml version="1.0"?>
<!DOCTYPE compass-core-mapping PUBLIC
"-//Compass/Compass Core Mapping DTD 2.0//EN"
"http://www.compass-project.org/dtd/compass-core-mapping-2.0.dtd">
<compass-core-mapping package="com.cecltd.domain">
<class name="Book" alias="${book.book}">
<id name="id" />
<constant>
<meta-data>type</meta-data>
<meta-data-value>java</meta-data-value>
</constant>
<property name="name">
<meta-data>${book.name}</meta-data>
</property>
<property name="content">
<meta-data>${book.content}</meta-data>
</property>
<property name="isbn">
<meta-data>${book.isbn}</meta-data>
</property>
<property name="pbl_dt">
<meta-data>${book.pbl_dt}</meta-data>
</property>
</class>
</compass-core-mapping>
=========================================================================
13.Book.cmd.xml
<?xml version="1.0"?>
<!DOCTYPE compass-core-meta-data PUBLIC
"-//Compass/Compass Core Meta Data DTD 2.0//EN"
"http://www.compass-project.org/dtd/compass-core-meta-data-2.0.dtd">
<compass-core-meta-data>
<meta-data-group id="book" displayName="Book Meta Data">
<description>Book Meta Data</description>
<uri>http://compass/book</uri>
<alias id="book" displayName="Book">
<uri>http://compass/book/alias/book</uri>
<name>book</name>
</alias>
<meta-data id="name" displayName="Name">
<uri>http://compass/book/name</uri>
<name>name</name>
</meta-data>
<meta-data id="content" displayName="Content">
<uri>http://compass/book/content</uri>
<name>content</name>
</meta-data>
<meta-data id="isbn" displayName="Isbn">
<uri>http://compass/book/isbn</uri>
<name>isbn</name>
</meta-data>
<meta-data id="pbl_dt" displayName="Pbl_dt">
<uri>http://compass/book/pbl_dt</uri>
<name format="yyyy-MM-dd">pbl_dt</name>
</meta-data>
</meta-data-group>
</compass-core-meta-data>
=========================================================================
JSP文件:
1.index.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<html>
<head>
<title>页面加载中,请稍后......</title>
<meta http-equiv="refresh" content="1;URL=/compass/initbook.action">
</head>
</html>
2.insert.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<s:head theme="ajax" />
<body>
<s:form action="insertbook.action" method="post">
<s:textfield key="name" label="书名" size="95" />
<s:textarea key="content" label="摘要" rows="10" cols="73" />
<s:textfield key="isbn" label="ISBN" size="13" maxlength="10" />
<s:datetimepicker name="pbl_dt" label="出版日"
displayFormat="yyyy-MM-dd" />
<s:submit value=" 注册 " />
</s:form>
</body>
</html>
3.search.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>结果显示</title>
</head>
<body>
<s:form action="searchbook.action" method="post">
<s:textfield key="query" label="关键字" size="118" />
<s:submit value=" 搜索 " onclick="this.form.action='searchbook.action'" />
<s:submit value=" 返回 " onclick="this.form.action='gobackbook.action'" />
<table id="dtTable" width="800" border="1" cellpadding="0"
cellspacing="0" style="BORDER-COLLAPSE: collapse"
borderColor=#000000>
<thead>
<tr bgcolor="orange" height="30px">
<th width="25%">
书名
</th>
<th width="45%">
概要
</th>
<th width="15%">
ISBN
</th>
<th width="15%">
出版日
</th>
</tr>
</thead>
<tbody>
<s:iterator value="datalist" status="rs">
<tr align="center" height="26px">
<td>
<s:property value="name" />
</td>
<td>
<s:property value="content" />
</td>
<td>
<s:property value="isbn" />
</td>
<td>
<s:property value="pbl_dt" />
</td>
</tr>
</s:iterator>
</tbody>
</table>
</s:form>
</body>
</html>
=========================================================================
Java文件
1.Book.javapackage com.cecltd.domain; import java.io.Serializable; import java.util.Date; public class Book implements Serializable { private static final long serialVersionUID = -5275017032598185911L; private Integer id; private String name; private String content; private String isbn; private Date pbl_dt; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public Date getPbl_dt() { return pbl_dt; } public void setPbl_dt(Date pbl_dt) { this.pbl_dt = pbl_dt; } }2.BookAction.javapackage com.cecltd.web; import java.text.SimpleDateFormat; import java.util.List; import com.cecltd.domain.Book; import com.cecltd.service.BookService; import com.opensymphony.xwork2.ActionSupport; public class BookAction extends ActionSupport { private static final long serialVersionUID = -3245236770369400667L; public static final String INSERT = "insert"; public static final String SEARCH = "search"; private BookService bookService; public BookAction(BookService bookService) { this.bookService = bookService; } public String insert() throws Exception { Book book = new Book(); book.setName(getName()); book.setContent(getContent()); book.setIsbn(getIsbn()); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); book.setPbl_dt(format.parse(getPbl_dt())); bookService.insertBook(book); return SEARCH; } public String search() throws Exception { List list = bookService.searchBook(getQuery()); setDatalist(list); return SEARCH; } public String init() throws Exception { return INSERT; } public String goback() throws Exception { return INSERT; } private String name; private String content; private String isbn; private String pbl_dt; private String query; private List datalist; public String getQuery() { return query; } public void setQuery(String query) { this.query = query; } public List getDatalist() { return datalist; } public void setDatalist(List datalist) { this.datalist = datalist; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public String getPbl_dt() { return pbl_dt; } public void setPbl_dt(String pbl_dt) { this.pbl_dt = pbl_dt; } }
3.BookService.javapackage com.cecltd.service; import java.util.List; import com.cecltd.domain.Book; public interface BookService { public List searchBook(String query); public void insertBook(Book book); }
4.BookServiceImpl.javapackage com.cecltd.service.impl; import java.util.List; import com.cecltd.compass.BookCps; import com.cecltd.dao.BookDao; import com.cecltd.domain.Book; import com.cecltd.service.BookService; public class BookServiceImpl implements BookService { private BookDao bookDao; private BookCps bookCps; public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } public void setBookCps(BookCps bookCps) { this.bookCps = bookCps; } public void insertBook(Book book) { bookDao.insertBook(book); } public List searchBook(String query) { return bookCps.searchBook(query); } }
5.BookDao.javapackage com.cecltd.dao; import com.cecltd.domain.Book; public interface BookDao { public void insertBook(Book book); }
6.BookDaoImpl.javapackage com.cecltd.dao.jdbc; import org.springframework.orm.hibernate3.HibernateTemplate; import com.cecltd.dao.BookDao; import com.cecltd.domain.Book; public class BookDaoImpl extends HibernateTemplate implements BookDao { public void insertBook(Book book) { save(book); } }
7.BookCps.javapackage com.cecltd.compass; import java.util.List; public interface BookCps { public List searchBook(String query); }
8.BookCpsImpl.javapackage com.cecltd.compass.impl; import java.util.ArrayList; import java.util.List; import org.compass.core.CompassHits; import org.compass.core.CompassQuery; import org.compass.core.CompassTemplate; import org.compass.core.CompassTransaction; import com.cecltd.compass.BookCps; import com.cecltd.domain.Book; public class BookCpsImpl extends CompassTemplate implements BookCps { public List searchBook(String query) { CompassTransaction tx = getCompass().openSession().beginTransaction(); //CompassHits hits = find("name:"+ query); CompassHits hits = getCompass().openSession().queryBuilder().queryString("content:"+ query).toQuery(). addSort("isbn", CompassQuery.SortPropertyType.STRING, CompassQuery.SortDirection.REVERSE).hits(); List list = new ArrayList (); int len = hits.getLength(); for (int i = 0; i < len; i++) { list.add((Book)hits.data(i)); } tx.commit(); return list; } }注意,因为该系统中使用到了庖丁解牛中文分词方法,需要自行下载安装并放置在配置文件中所指明的地方。
庖丁解牛:http://groups.google.com/group/paoding/browse_thread/thread/9771c8d495786fee
另外还有IKAnalyzer:http://groups-beta.google.com/group/SegWord/web/segword