- 浏览: 28274 次
- 性别:
- 来自: 上海
最新评论
-
hongtenzone:
你好,请提供以下源码下载,或发一下我邮箱好吗?mailto:h ...
hibernate search 和lucene结合使用实例 -
青梅子:
要是文件配全就好了……
hibernate search 和lucene结合使用实例 -
luanyongsdau:
请问您能给我发一份工程的压缩包吗? lyongjn@gmail ...
hibernate search 和lucene结合使用实例 -
jespring:
你好使用hibernate search 建索引时被锁了,怎么 ...
hibernate search 和lucene结合使用实例 -
keynescao:
请问下在apache中怎样配置才可以像你这样直接访问 http ...
结合Apache和Tomcat实现集群和负载均衡
以下的代码是根据api帮助文档作出的一个简单实例,在应用方面可以实现创建索引,搜索,过滤和高亮的功能。
整体的环境为:spring2.5.6,hibernate3.3.1,struts2.0.8,lucene2.4.1
第一步,首先是web.xml配置文件,由于使用了ssh2的架构,所以不得不在web.xml里配置一些东西
第二步,配spring配置文件和hibernate文件
这是可以使用hibernate annotation注释的sessionFactory的属性配置的一部分,注意下面的2个使用索引的属性配置,提供文件索引的保存路径和读取方式(fsdirectory,文件索引,另外一种是ramdirectory,内存索引)
spring的配置文件没有什么特别的,和普通ssh配置没有什么两样
第三步配struts配置文件,由于也是普通配置,没有特别之处,就不贴出来了。
第四步,写实体类,由于采用hibernate search方法搜索,所以直接利用hibernate annotation注释去定义索引的一些配置信息。关于index的基本都属于索引的配置
第六步,写service方法,包括建索引,根据关键字用索引查,过滤,设置权重,高亮等等工作
整体的环境为:spring2.5.6,hibernate3.3.1,struts2.0.8,lucene2.4.1
第一步,首先是web.xml配置文件,由于使用了ssh2的架构,所以不得不在web.xml里配置一些东西
]<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- spring的配置文件路径 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring/*.xml</param-value> </context-param> <!--Hibernate Open Session in View Filter--> <filter> <filter-name>hibernateFilter</filter-name> <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter </filter-class> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>*.action</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>*.jsp</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- Spring 刷新Introspector防止内存泄露 --> <listener> <listener-class> org.springframework.web.util.IntrospectorCleanupListener </listener-class> </listener> <!-- Struts Action Mapping--> <filter> <filter-name>struts-cleanup</filter-name> <filter-class> org.apache.struts2.dispatcher.ActionContextCleanUp </filter-class> </filter> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> </filter> <filter-mapping> <filter-name>struts-cleanup</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.jsp</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <!-- spring自带的字符转换过滤器,转换成utf-8的格式 --> <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> <!-- 随服务器启动,自动调用对应的servlet创建索引文件 --> <servlet> <servlet-name>CreateHibernateIndex</servlet-name> <servlet-class>com.test.servlet.CreateHibernateIndex</servlet-class> <load-on-startup>20</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CreateHibernateIndex</servlet-name> <url-pattern>/servlet/CreateHibernateIndex</url-pattern> </servlet-mapping> <!-- session超时定义,单位为分钟 --> <session-config> <session-timeout>20</session-timeout> </session-config> <!-- 默认首页定义 --> <welcome-file-list> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> </web-app>
第二步,配spring配置文件和hibernate文件
这是可以使用hibernate annotation注释的sessionFactory的属性配置的一部分,注意下面的2个使用索引的属性配置,提供文件索引的保存路径和读取方式(fsdirectory,文件索引,另外一种是ramdirectory,内存索引)
<prop key="hibernate.search.default.directory_provider"> org.hibernate.search.store.FSDirectoryProvider </prop> <prop key="hibernate.search.default.indexBase"> ${hibernate.search.default.indexBase} </prop>
spring的配置文件没有什么特别的,和普通ssh配置没有什么两样
第三步配struts配置文件,由于也是普通配置,没有特别之处,就不贴出来了。
第四步,写实体类,由于采用hibernate search方法搜索,所以直接利用hibernate annotation注释去定义索引的一些配置信息。关于index的基本都属于索引的配置
package com.test.model; import static javax.persistence.GenerationType.IDENTITY; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Transient; import org.hibernate.search.annotations.Analyzer; import org.hibernate.search.annotations.DateBridge; import org.hibernate.search.annotations.DocumentId; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Index; import org.hibernate.search.annotations.Indexed; import org.hibernate.search.annotations.Resolution; import org.hibernate.search.annotations.Store; import org.wltea.analyzer.lucene.IKAnalyzer; /** * Product entity. */ @Entity @Table(name = "product", catalog = "hibernate_search_test") @Indexed(index = "Product") @Analyzer (impl = IKAnalyzer.class ) public class Product implements java.io.Serializable { // Fields /** * */ private static final long serialVersionUID = -7005490272739421758L; private Integer id; private String proTitle; private String proDescn; private String proPrice; private Integer proType; private Date proTime; private String findResult; // Constructors /** default constructor */ public Product() { } // Property accessors @Id @GeneratedValue(strategy = IDENTITY) @Column(name = "id") @DocumentId public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @Column(name = "pro_title") @Field(name = "pt", index = Index.TOKENIZED, store = Store.YES) public String getProTitle() { return this.proTitle; } public void setProTitle(String proTitle) { this.proTitle = proTitle; } @Column(name = "pro_descn") @Field(name = "pd", index = Index.TOKENIZED, store = Store.YES) public String getProDescn() { return this.proDescn; } public void setProDescn(String proDescn) { this.proDescn = proDescn; } @Column(name = "pro_price") public String getProPrice() { return this.proPrice; } public void setProPrice(String proPrice) { this.proPrice = proPrice; } @Column(name = "pro_type") public Integer getProType() { return this.proType; } public void setProType(Integer proType) { this.proType = proType; } @Temporal(TemporalType.DATE) @Column(name = "pro_time") @Field(name = "t", index = Index.UN_TOKENIZED, store = Store.YES) @DateBridge(resolution = Resolution.DAY) public Date getProTime() { return this.proTime; } public void setProTime(Date proTime) { this.proTime = proTime; } //封装搜索出的高亮内容 @Transient public String getFindResult() { return findResult; } public void setFindResult(String findResult) { this.findResult = findResult; } }
第六步,写service方法,包括建索引,根据关键字用索引查,过滤,设置权重,高亮等等工作
package com.test.service; import java.io.File; import java.io.StringReader; import java.util.Date; import java.util.List; import javax.annotation.Resource; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Token; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.document.DateTools; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.DateTools.Resolution; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.CachingWrapperFilter; import org.apache.lucene.search.Filter; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.QueryWrapperFilter; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermRangeQuery; import org.apache.lucene.search.TopScoreDocCollector; import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.highlight.Formatter; import org.apache.lucene.search.highlight.Highlighter; import org.apache.lucene.search.highlight.QueryScorer; import org.apache.lucene.search.highlight.SimpleFragmenter; import org.apache.lucene.search.highlight.SimpleHTMLFormatter; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.search.FullTextQuery; import org.hibernate.search.FullTextSession; import org.hibernate.search.Search; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springside.modules.orm.hibernate.HibernateDao; import org.springside.modules.service.EntityManager; import org.wltea.analyzer.lucene.IKAnalyzer; import com.test.dao.ProductDao; import com.test.model.Product; @Transactional @Service public class ProductService extends EntityManager<Product, Integer> { @Resource(name = "productDao") private ProductDao productDao; @Override protected HibernateDao<Product, Integer> getEntityDao() { // TODO Auto-generated method stub return productDao; } @SuppressWarnings("unchecked") public List<Product> QueryByIndex(String words, String startDate,String endDate) throws Exception { FullTextSession fullTextSession = Search.createFullTextSession(productDao.getSession()); /*Query IKQuery = IKQueryParser.parseMultiField(new String[] { "proTitle", "proDescn" }, new String[] { words, words }, new BooleanClause.Occur[] { Occur.SHOULD, Occur.SHOULD }); Query luceneQuery = MultiFieldQueryParser.parse(new String[] { words, words }, new String[] { "pro_title", "pro_descn" }, new BooleanClause.Occur[] { Occur.SHOULD, Occur.SHOULD }, new StandardAnalyzer());*/ BooleanQuery bQuery = new BooleanQuery(); Analyzer analyzer = new IKAnalyzer(); //设置对域采用的某种分词器的QueryParser对象 QueryParser qp; //设置了关键字的查询您对象 //Query q; qp = new QueryParser(Version.LUCENE_CURRENT,"pt",analyzer); Query q1 = qp.parse(words); q1.setBoost(1.5f); bQuery.add(q1, Occur.SHOULD); qp = new QueryParser(Version.LUCENE_CURRENT,"pd",analyzer); Query q2 = qp.parse(words); q2.setBoost(1.0f); bQuery.add(q2, Occur.SHOULD); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(bQuery,Product.class); // 添加是或者否的条件到query中 boolean filterResult = false; BooleanQuery bQueryForFilter = new BooleanQuery(); if (!startDate.equalsIgnoreCase("") && !endDate.equalsIgnoreCase("")) { // 时间过滤 // RangeFilter rangefilter = new RangeFilter("pro_time", // "20090927","20090929", false, false); // 只能使用一个过滤器,所以只能用下面的RangeQuery,然后将所有query封装到一个过滤条件中 TermRangeQuery rangeQuery = new TermRangeQuery("t",startDate,endDate,true,true); bQueryForFilter.add(rangeQuery, BooleanClause.Occur.MUST); filterResult = true; } if (filterResult) { // 将booleanQuery封装到Filter中 Filter filter = new CachingWrapperFilter(new QueryWrapperFilter(bQueryForFilter)); fullTextQuery.setFilter(filter); } List<Product> result = fullTextQuery.list(); String findResult; //根据上边已经写好的query封装出一个查询计分器 QueryScorer qs1 = new QueryScorer(q1); QueryScorer qs2 = new QueryScorer(q2); //设置高亮的模板,其实就是在关键字两边加一对html的格式标签,下面是最基本的加粗。 Formatter formatter = new SimpleHTMLFormatter("<b>", "</b>"); Highlighter highlighter1 = new Highlighter(formatter,qs1); Highlighter highlighter2 = new Highlighter(formatter,qs2); String text; //下面通过将上面根据关键字,过滤条件和权重排序等找出的结果集做一次循环,进行高亮,把高亮后得到的 //一个字符串,封装如每个实体类中的一个额外字段,方便在页面输出。 for(Product product:result){ text = product.getProTitle() ; findResult = highlighter1.getBestFragment(analyzer,"pt", text); if(findResult==null){ text = product.getProDescn() ; highlighter2.setTextFragmenter(new SimpleFragmenter(30)); findResult = highlighter2.getBestFragment(analyzer,"pd", text); } product.setFindResult(findResult); } return result; } //下面的方法是用hibernate search的方法来创建索引 public void createIndexByHibernateSearch() { long startTime = new Date().getTime(); int BATCH_SIZE = 1000; FullTextSession s = Search.createFullTextSession(productDao.getSession()); // Transaction tr = s.beginTransaction(); s.setFlushMode(FlushMode.MANUAL); s.setCacheMode(CacheMode.IGNORE); ScrollableResults results = s.createQuery("from Product").setFetchSize(BATCH_SIZE).scroll(ScrollMode.FORWARD_ONLY); int index = 0; while (results.next()) { index++; s.index(results.get(0)); // index each element if (index % BATCH_SIZE == 0) { // s.flushToIndexes(); //apply changes to indexes s.clear(); // clear since the queue is processed } } s.clear(); long endTime = new Date().getTime(); logger.warn("建立Product索引 , 这花费了" + (endTime - startTime) + " 毫秒来把文档增加到索引里面去!"); // tr.commit(); } //下面的方法是用lucene的方式来创建索引文件,不过用这种方式创建索引后,也只能使用lucene的方式去进行搜索 @SuppressWarnings("deprecation") public void createIndexByLucene() { try { File fsDir = new File("E:\\indexes\\product"); Analyzer analyzer = new IKAnalyzer(); /* // 内存索引 RAMDirectory ramDir = new RAMDirectory(); IndexWriter ramWriter = new IndexWriter(ramDir, luceneAnalyzer, true, IndexWriter.MaxFieldLength.UNLIMITED); */ IndexWriter fsWriter = new IndexWriter( FSDirectory.open(fsDir), analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED ); fsWriter.setMaxBufferedDocs(1000); fsWriter.setMergeFactor(1000); List<Product> productList = find("from Product"); int size = productList.size(); long startTime = new Date().getTime(); Document doc; for (Product product : productList) { doc = new Document(); doc.add(new Field("pro_title", product.getProTitle(),Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("pro_descn", product.getProDescn(),Field.Store.YES, Field.Index.ANALYZED)); if(product.getProTime()!=null) doc.add(new Field("pro_time",DateTools.dateToString( product.getProTime(), Resolution.DAY),Field.Store.YES, Field.Index.NOT_ANALYZED)); fsWriter.addDocument(doc); // 先缓存入内存索引,后写入文件索引 /* ramWriter.addDocument(doc); int i = 1; i++; if (i % 100 == 0 || i == size) { logger.warn("i:" + i); ramWriter.close(); fsWriter.addIndexesNoOptimize(new Directory[] { ramDir }); ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); }*/ } // 自动优化合并索引文件 fsWriter.optimize(); fsWriter.close(); long endTime = new Date().getTime(); System.out.println("一共" + size + ",这花费了" + (endTime - startTime) + " 毫秒来把文档增加到索引里面去!"); } catch (Exception e) { e.printStackTrace(); } } public void SearchByLucene(){ createIndexByLucene(); File fsDir = new File("E:\\luceneIndexes\\product"); Analyzer analyzer = new IKAnalyzer(); try{ // 索引查询 IndexReader reader = IndexReader.open(FSDirectory.open(fsDir), true); // only searching, so read-only=true IndexSearcher isearcher = new IndexSearcher(reader); BooleanQuery booleanQuery = new BooleanQuery(); QueryParser parser; Query query; parser = new QueryParser(Version.LUCENE_CURRENT,"pro_title",analyzer); query = parser.parse("大灯");// 检索词 query.setBoost(1.5f); booleanQuery.add(query, Occur.SHOULD); parser = new QueryParser(Version.LUCENE_CURRENT,"pro_descn",analyzer); query = parser.parse("大灯");// 检索词 query.setBoost(1.0f); booleanQuery.add(query, Occur.SHOULD); BooleanQuery filterBooleanQuery = new BooleanQuery(); TermRangeQuery rangeQuery = new TermRangeQuery("pro_time","20090101","20091101",true,true); filterBooleanQuery.add(rangeQuery, BooleanClause.Occur.MUST); // 将booleanQuery封装到Filter中 Filter filter = new CachingWrapperFilter(new QueryWrapperFilter(filterBooleanQuery)); TopScoreDocCollector collector = TopScoreDocCollector.create(100,true); isearcher.search(booleanQuery,filter,collector); ScoreDoc[] hits = collector.topDocs(0,100).scoreDocs; QueryScorer qs = new QueryScorer(new TermQuery(new Term("pro_title","大灯"))); for(ScoreDoc h:hits){ Document d = isearcher.doc(h.doc); String text = d.get("pro_title") ; Formatter formatter = new SimpleHTMLFormatter("<b>", "</b>"); Highlighter hl = new Highlighter(formatter,qs); System.out.println(hl.getBestFragment(analyzer,"pro_title", text)); //System.out.println("doc:"+h.doc+" \tscore:"+h.score+" \t"+d.get("pro_title")); } System.out.println("命中:" + hits.length); isearcher.close(); }catch(Exception e){ e.printStackTrace(); } } // 查看分词效果 @SuppressWarnings("deprecation") public static void showAnalyzerResult(Analyzer analyzer, String s) throws Exception { StringReader reader = new StringReader(s); TokenStream ts = analyzer.tokenStream(s, reader); Token t = ts.next(); while (t != null) { System.out.print(t.termText() + " "); t = ts.next(); } System.out.println(); } public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); ProductService service = (ProductService) ctx.getBean("productService"); service.SearchByLucene(); } }
评论
6 楼
hongtenzone
2013-03-04
你好,请提供以下源码下载,或发一下我邮箱好吗?
mailto:hongtenzone@foxmail.com
mailto:hongtenzone@foxmail.com
5 楼
青梅子
2012-09-02
要是文件配全就好了……
4 楼
luanyongsdau
2011-05-16
请问您能给我发一份工程的压缩包吗?
lyongjn@gmail.com,十分感谢,我根据你的例子做了一天了,没有调。
lyongjn@gmail.com,十分感谢,我根据你的例子做了一天了,没有调。
3 楼
jespring
2010-08-12
你好使用hibernate search 建索引时被锁了,怎么办?
我看了doc后
DirectoryProvider orderProvider = fullTextSession.getSearchFactory().getDirectoryProviders(Cat.class)[0];
ReaderProvider readerProvider = fullTextSession.getSearchFactory().getReaderProvider();
IndexReader reader = readerProvider.openReader(orderProvider);
但是reader没有isLock方法。
hibernate search 如何得到IndexWriter
我看了doc后
DirectoryProvider orderProvider = fullTextSession.getSearchFactory().getDirectoryProviders(Cat.class)[0];
ReaderProvider readerProvider = fullTextSession.getSearchFactory().getReaderProvider();
IndexReader reader = readerProvider.openReader(orderProvider);
但是reader没有isLock方法。
hibernate search 如何得到IndexWriter
2 楼
qiren83
2010-07-28
有无 compass+hibernate search+lucene的文章呀
1 楼
qiren83
2010-07-25
你好 谢谢提供
另问可以提供打包下载吗?
谢了
另问可以提供打包下载吗?
谢了
相关推荐
hibernate search 和lucene结合使用实例
hibernate-search小例子,myeclipse工程文件,有jar包,只要有mysql和myeclipse就可以直接运行。文章在http://blog.csdn.net/hortond。对文件索引和数据库感兴趣的可以下来看看,lucene是个很强大的全文搜索引擎。
2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...
2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...
开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...