??xml version="1.0" encoding="utf-8" standalone="yes"?> Ctrl+Shift+/ 加上D|?**/ Ctrl+Shift+\ 取消D|?**/ Ctrl+/ 加上行注释或取消行注?/p>
自动汇入所需要的cdQCtrl+Shift+O 取消自动validationQ?br />
取消ҎQ?nbsp;windows-->perferences-->myeclipse-->validation 按new Remote Site,Name?svn , URL?a >http://subclipse.tigris.org/update,一直next到finished为止 4.JTest 重量U的商业工具 使用感觉: 安装上插件后,对自q目q行?发现警告太多?有点发蒙的感?不过把警告看一?觉得都很有道?有些也确实是一些错? 代码查错推荐使用Findbugs和PMD,代码书写规范推荐使用CheckStyleq行?q样不仅能查Z些基本的错误,也能提高目的代码质?Ҏ高自q代码水^也是非常? 推荐目l徏立统一的规?代码复查的时候就使用q些工具,省时省力. 实乃居家旅行,杀货必备之工具?(因ؓ肯定有h要骂?呵呵,也是你找"?的工? 首先,Z一个简单的新闻pȝ,要想做全文检?新闻pȝ的管理等在这里不在具体提?下面列出新闻对象的类:
快速执行程序:Ctrl + F11W一ơ执行时Q它会询问您执行模式Q设|好后,以后只要按这个热键,它就会快速执行?/p>
除开Manual下面的复选框全部选中之外Q其他全部不?nbsp;
手工验证ҎQ?nbsp;
在要验证的文件上Q单击鼠标右?->myeclipse-->run validation
]]>
目前版本0.9.1,有for eclipse的插? |址?a >http://findbugs.sourceforge.net.
工作原理:查程序生成的class的工?
界面:独立q行的提供图形界?很友?有bug报告.
可用?大多数提C有?值得?br />
插g:
可以讄基本和检查的错误cd.
插g保存讄有问?我是关闭目后台修改了配|文?在装入才成功改了配置?
bug临时解决: 使用独立的findbugs讄规则,然后到C:\Documents and Settings\XXX\下找.Findbugs_prefs,然后改名覆盖eclipse project下的.fbprefs (先关闭你的project)
配置没有查找功能,不过~写能让我们很快扑ֈ某个规则
2.PMD:主要是查?/strong>
目前版本3.2,有for eclipse以及其他ide的插?|址?a >http://pmd.sourceforge.net
工作原理:查源?
可用?一部分值得修改,有些q于严格
界面:独立q行的是命o行界?命o比较?
插g:可以配置规则,有一个独立的H口昄提示,?U提C?很友?br />
使用:建立自己的规?然后用于实际使用?
3.CheckStyle:主要查代码规?/strong>
目前版本4.0 beta 5,有for eclipse的插?|址?a >http://checkstyle.sourceforge.net.
工作原理:查源?对javadoc,书写格式{进行检?
规则定义:默认的规则是sun的编码规?不过按照sun的规则则q于严格,而且每个公司也有自己的规?和sun的不?所以需要自定义规范.
目前版本7.0.7,有for eclipse的插?|址?a >http://www.parasoft.com/
不推荐?不过功能强大,可以q行代码?可以自动生成单元试和进行单元测?(不过是太慢?而且生成的单元测试没太大用?
当然PMD和CheckStyle的规范太严格,最后还是配|了一?
通过Ҏ警告,感觉q是不错,臛_可以说自q代码可以通过工具的检了.
当然基础代码和项目代码还是不一L,基础代码往往比较复杂,所以和普通项目代码的规范应该有所不同.有些规则只能用在普通代码上,用在基础cM码上往往没法处理.
其他
]]>
?E序用会C些工L,不在此列?用户可以自己实现.
package com.jscud.website.newsinfo.bean;
import java.sql.Timestamp;
import com.jscud.util.DateTime;
import com.jscud.util.StringFunc;
import com.jscud.website.newsinfo.NewsConst;
/**
* 一个新?
*
* @author scud(飞云侠) http://www.jscud.com
*
*/
public class NewsItem
{
private int nid; //新闻~号
private int cid; //cd~号
private String title;//标题
private int showtype; //内容cd:目前支持url和html
private String content;//内容
private String url;//对应|址,如果内容cd是url的话
private Timestamp addtime; //增加旉
private int click; //点击?br />
//对应的get,set函数,较多不在列出,可以使用工具生成
//......
/**
* 按照cd格式?br />
*/
public String getShowContent()
{
String sRes = content;
if(showtype == NewsConst.ShowType_HTML)
{
}
return sRes;
}
public String getTarget()
{
if(showtype == NewsConst.ShowType_URL)
{
return "_blank";
}
else
return "";
}
/**
* 静态Html文g的\径及其名?br />
*/
public String getHtmlFileName()
{
int nYear = DateTime.getYear_Date(getAddtime());
int nMonth = DateTime.getMonth_Date(getAddtime());
String sGeneFileName =
"/news/" + getCid() + "/" + nYear + "/" + nMonth +"/" + getNid() + ".htm";
return sGeneFileName;
}
/**
* 静态Html文g的\?br />
*/
public String getHtmlFilePath()
{
int nYear = DateTime.getYear_Date(getAddtime());
int nMonth = DateTime.getMonth_Date(getAddtime());
String sGeneFilePath =
getCid() + "_" + nYear + "_" + nMonth;
return sGeneFilePath;
}
}
可以看到,我们需要对标题和内容进行检?Zq个目的,我们首先需要来研究一下lucene.
在Lucene?如果要进行全文检?必须要先建立索引然后才能q行?当然实际工作中还会有删除索引和更新烦引的工作.
在此之前,介绍一个最基本的类(摘抄?a href="http://m.tkk7.com/cap/archive/2005/07/17/7849.html">http://m.tkk7.com/cap/archive/2005/07/17/7849.html):
Analyzer 文g的分析器Q听h别扭Q还是叫Analyzer好了)的抽象,q个cȝ来处理分?对中文尤光要,转换大小?Computer->computer,实现查询大小写无?Q{换词?computers->computer),消除stop words{?q负责把其他格式文档转换为纯文本{?
在lucene?一般会使用StandardAnalyzer来分析内?它支持中文等多字节语a,当然可以自己实现Ҏ的解析器.StandardAnalyzer目前对中文的处理是按照单字来处理?q是最单的办法,但是也有~点,会组合出一些没有意义的l果?
首先我们来了解徏立烦?建立索引包含2U情?一U是l一条新d立烦?另外的情冉|在开始或者一定的旉l批量的新闻建立索引,所以ؓ了通用,我们写一个通用的徏立烦引的函数:
(一般一cȝ索引都放在一个目录下,q个配置可以在函C定义,也可以写在配|文件中,通过参数传递给函数.)
/** * 生成索引. * * @param doc 目标文档 * @param indexDir 索引目录 */ public static void makeIndex(Document doc, String indexDir) { List aList = new ArrayList(); aList.add(doc); makeIndex(aList, indexDir); } /** * 生成索引. * * @param doc 生成的document. * @param indexDir 索引目录 */ public static void makeIndex(List docs, String indexDir) { if (null == docs) { return; } boolean indexExist = indexExist(indexDir); IndexWriter writer = null; //d一条文?br />
for (int i = 0; i < docs.size(); i++) //索引完成后的处理 |
可以看到,建立索引用到cLIndexWrite,它可以新建烦引或者追加烦?但是需要自己判?判断是通过IndexReaderq个cL实现?函数如下:
/** * 查烦引是否存? * @param indexDir * @return */ public static boolean indexExist(String indexDir) { return IndexReader.indexExists(indexDir); } |
如果每次都是新徏索引的话,会把原来的记录删?我在使用的时候一开始就没有注意?后来观察了一下烦引文?才发现这个问?
q可以看?建立索引是给用户的Document对象建立索引,Document表示索引中的一条文档记?那么我们如何建立一个文档那?以新ȝlؓ?代码如下:
/** * 生成新闻的Document. * * @param aNews 一条新? * * @return lucene的文档对?br /> */ public static Document makeNewsSearchDocument(NewsItem aNews) { Document doc = new Document(); doc.add(Field.Keyword("nid", String.valueOf(aNews.getNid()))); doc.add(Field.Text("title", aNews.getTitle())); //对Htmlq行解析,如果不是html,则不需要解?或者根据格式调用自q解析Ҏ String content = parseHtmlContent(aNews.getContent()); doc.add(Field.UnStored("content", content)); doc.add(Field.Keyword("addtime", aNews.getAddtime())); //可以加入其他的内?例如新闻的评论等 doc.add(Field.UnStored("other", "")); //讉Kurl String newsUrl = "/srun/news/viewhtml/" + aNews.getHtmlFilePath() + "/" + aNews.getNid() + ".htm"; doc.add(Field.UnIndexed("visiturl", newsUrl)); return doc; } |
通过上面的代?我们把一条新闻{换ؓlucene的Document对象,从而进行烦引工?在上面的代码?我们又引入了lucene中的Field(字段)c?Document文档像数据库中的一条记?它有很多字段,每个字段是一个Field对象.
从别的文章摘抄一D关于Field的说?摘抄?a href="http://m.tkk7.com/cap/archive/2005/07/17/7849.html">http://m.tkk7.com/cap/archive/2005/07/17/7849.html):
[quote]
cd Analyzed Indexed Stored 说明
Field.Keyword(String,String/Date) N Y Y q个Field用来储存会直接用来检索的比如(~号,姓名,日期{?
Field.UnIndexed(String,String) N N Y 不会用来索的信息,但是索后需要显C的,比如,g序列?文档的url地址
Field.UnStored(String,String) Y Y N 大段文本内容,会用来检?但是索后不需要从index中取内容,可以Ҏurl去load真实的内?
Field.Text(String,String) Y Y Y ?获取都需要的内容,直接放index?不过q样会增大index
Field.Text(String,Reader) Y Y N 如果是一个Reader, lucene猜测内容比较?会采用Unstored的策?
[/quote]
我们可以看到新闻的编h直接用来索的,所以是Keywordcd的字D?新闻的标题是需要检索和昄用的,所以是Textcd,而新ȝ内容因ؓ是Html格式?所以在l过解析器的处理?使用的UnStored的格?而新ȝ旉是直接用来检索的,所以是KeyWordcd.Z在新ȝ引后用户可以讉K到完整的新闻面,q设|了一个UnIndexedcd的访问地址字段.
(对Htmlq行解析的处理稍后在q行讲解)
Z条新d立烦引需要两个步?获取Document,传给makeIndex函数,代码如下:
public static void makeNewsInfoIndex(NewsItem aNews) { if (null == aNews) { return; } makeIndex(makeNewsSearchDocument(aNews),indexDir); } |
建立索引的工作就q行完了,只要在增加新d调用 makeNewsInfoIndex(newsitem); 可以徏立烦引了.
如果需要删除新?那么也要删除对应的烦?删除索引是通过IndexReadercL完成?
/** * 删除索引. * @param aTerm 索引删除条g * @param indexDir 索引目录 */ public static void deleteIndex(Term aTerm, String indexDir) { List aList = new ArrayList(); aList.add(aTerm); deleteIndex(aList, indexDir); } /** IndexReader reader = null; |
删除索引需要一个条?cM数据库中的字D|?例如删除一条新ȝ代码如下:
public static void deleteNewsInfoIndex(int nid) { Term aTerm = new Term("nid", String.valueOf(nid)); deleteIndex(aTerm,indexDir); } |
通过新闻的ID,可以删除一条新?
如果需要更新新?如何更新索引? 更新索引需要先删除索引然后新徏索引2个步?其实是把上面的代码l合h,例如更新一条新?
public static void updateNewsInfoIndex(NewsItem aNews) { if (null == aNews) { return; } deleteNewsInfoIndex(aNews.getNid()); makeNewsInfoIndex(aNews); } |
x,索引的徏立更新和删除告一D落?其中扚w更新新闻的代码如?
(扚w更新应该在访问h数少或者后台程序在夜间执行)
public static void makeAllNewsInfoIndex(List newsList) { List terms = new ArrayList(); List docs = new ArrayList(); for (int i = 0; i < newsList.size(); i++) deleteIndex(terms,indexDir); |
|址? http://htmlparser.sourceforge.net ,当前版本?.5.
下蝲下来,试用一?感觉不错,完全能满lucene解析Html的需?
q几天脓出luceneq行全文索的代码.(索本站的文章{?.
试用代码如下,供大家参?
package com.jscud.test; import java.io.BufferedReader; import org.htmlparser.Node; import com.jscud.util.LogMan; //一个日志记录类 /** public class ParseHtmlTest public static void main(String[] args) throws Exception String content = readTextFile(aFile, "GBK"); test1(content); test2(content); test3(content); test4(content); test5(aFile); //讉K外部资源,相对?br /> test5(" System.out.println("===================================="); } /** //讄~码 HtmlPage visitor = new HtmlPage(myParser); myParser.visitAllNodesWith(visitor); String textInPage = visitor.getTitle(); System.out.println(textInPage); /** HtmlPage visitor = new HtmlPage(myParser); myParser.visitAllNodesWith(visitor); String textInPage = visitor.getTitle(); System.out.println(textInPage); /** TextExtractingVisitor visitor = new TextExtractingVisitor(); myParser.visitAllNodesWith(visitor); String textInPage = visitor.getExtractedText(); System.out.println(textInPage); /** myParser = Parser.createParser(content, "GBK"); NodeFilter textFilter = new NodeClassFilter(TextNode.class); //暂时不处?meta OrFilter lastFilter = new OrFilter(); nodeList = myParser.parse(lastFilter); Node[] nodes = nodeList.toNodeArray(); for (int i = 0; i < nodes.length; i++) String line = ""; line = linknode.getLink(); if (isTrimEmpty(line)) System.out.println(line); /** myParser = Parser.createParser(content, null); nodes = myParser.extractAllNodesThatAre(TextNode.class); //exception could be thrown here for (int i = 0; i < nodes.length; i++) } /** try String dataLine = ""; ins.close(); return sbStr.toString(); /** /** }
|
手工调用jdbc的connection事务Ҏ和用JTA接口都属于编E式开发,在EJB中叫BMT(Bean理事务)?br /> JTA最重要的接口就是UserTransaction和它的六个方?beginQcommitQrollbackQgetStatusQsetRollbackonlyQsetTransactionTimeout?br /> E序需要UserTransaction时可以从JNDI领取Q不qJNDI名随应用服务器不同而不同。EJB3里可以直接用个@Resource注入?/p>
前面都是铺垫Q这个才是主打的事务模型Q如EJB的CMT(容器理事务)和Sprin?/p>
其中EJB2.0QSpring1.0在部|描q符和applicationContext.xml中定义,而EJB3.0和Spring2.0则采用annotation?/p>
q里JavaEE与Spring的定义基本相同:
可见QRequired是默认的讄QSupports是只L法的最佳选择?/p>
U别低安全效率也低。隔ȝ别需要相兌源支持,如重复读在Oracle里会降为ReadCommited。Spring里默认的DefaultU别完全看数据源的脸色行事?/p>
EJB里,想rollback只能sessionContext.setRollbackOnly()Q或者抛出EJBException?EJB3q可以annotation讄某些自定义Exception可以触发rollback)
在Spring里,同样只会rollback unchecked exception(RuntimeExcption及子c?Q而checked exception(Exception及子c?是不会rollback的,除非你特别声明?/p>
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW,rollbackFor = {MyException1.class,MyException2.class})
因此所有在service层方法中用throws定义的ExceptionQ都必须在事务定义中q行rollback讑֮?请勿善忘)
所有在service层方法中c被atch处理了的异常Q又希望容器辅助rollback的话Q必重抛一个预定义的RuntimeException的子cR?请勿回望)
Spring不希望编E式事务理?br /> Spring也不希望使用EJB CMT--CMT依赖于EJB而无法用于POJOQ依赖于JTA全局事务对单数据源场景造成了浪费,而且rollback机制比较ȝQ必MؓEJBException或手工setRollbackOnly())?br /> 因此Spring通过AOP实现了对POJO的整套宣告式事务体系Q对jdbc,hibernate,jpa,jms{local数据源和JTA实现了统一的事务管理机Ӟ而且支持本地资源与JTA在配|文件的切换,而且改进了rollback机制?/p>
1Q一个本C务管理器Q?/p>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean>
2QSpring׃把请求都转发到应用服务器的JTA对象上(注意此时数据源也需要改为用JNDI从应用服务器获取)?/p>
<bean id="myTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
3Q应用服务器专有的类型的JTA事务理器:
<bean id="myTxManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"/>
最好将hibernate.cfg.xml文g存放于项目的根目录下?br />
4Q生?hbm.xml文g。File->New->Other->Hibernate->Hibernate Mapping FileQ出现如下界面:
在填写完Password后,点击Refresh按钮Q就会在Tables中列出所有可以访问的数据库表Q然后选中要ؓ其生?hbm.xml文g的表Q点击FinishQ即会生成对应的.hbm.xml文gQ比如我上面选择的是Mobileuser表,׃生成Mobileuser.hbm.xml文g?br />
Q?Q从.hbm.xml文g自动生成实体cR?br />
在Package Explorer中选中Mobileuser.hbm.xml文gQ右?>Hibernate Synchronizer->Synchronize Files Q即可生成对应的实体cdDAOcR如果你仅仅惌实体c,那么可以在Project->Properies->Hibernate Synchronizer->Data Access Objects Q将“I would like to have DAOs created for me”的钩选项L卛_?br />
Q?Q在hibernate.cfg.xml文g中添加对应的mapping resource?br />
在Package Explorer中选中Mobileuser.hbm.xml文gQ右?>Hibernate Synchronizer->Add Mapping ReferenceQ即会在
hibernate.cfg.xml中自动生成如下配|:
Q?Q修改自动生成的hibernate.cfg.xml文g。需要在hibernate.cfg.xml文g的首部添加:
比较J琐的是Q每ơ自动修改hibernate.cfg.xml文g后,都要重新dq个xml片断?br />
万事具备Q现在可以写个测试来验一下了Q?/p>
web.xml中添加的servlet映射表明Q所有匹?#8220;/services/*”的urlh全部交给org.codehaus.xfire.transport.http.XFireConfigurableServlet来处理?br />
Q?Q编写需要发布ؓWebService的Javac,q个例子中是一个非常简单的MathService.java?/p>
Q?Q在WebContent\META-INF目录下新?strong>xfire文g?/strong>Q然后在xfire目录下添加一个XFire使用的配|文件services.xmlQ该配置文g中的内容反映了要哪些javacd布ؓweb服务。本例中的services.xml内容如下Q?br />
Q?Q在IE中输?http://localhost:8080/XFireZhuweiTest/services/MathService?wsdl 会得到正的web服务描述文档?/p>
Q?0Q测试刚发布的webService。我使用C#动态调用Web服务Q?/p>
Q关于C#动态调用Web服务Q请参见q里Q?br />
执行后,弹出对话框,昄l果??
CREATE procedure pagination
@str_sql varchar(1000) = '*', -- 执行的SQL 不含Order by 内容
@str_orderfield varchar(255)='''', -- 排序的字D名
@page_size int = 10, -- 大?nbsp;
@page_index int = 0, -- 늠
@order_type int, -- 讄排序cd, ?-1 值则降序
@total_count int output -- q回记录L, ?0 值则q回
as
---------------------
-- 获取指定늚数据--
---------------------
declare @strsql varchar(5000) -- 主语?br />
declare @strtmp varchar(5000) -- 临时变量
declare @strorder varchar(400) -- 排序字串
declare @cruRow int -- 当前行号
--执行Ll计
exec getRowCount @str_sql,@total_count output
set @strtmp = ' select * from ' +
' (select top ' + convert(varchar(10),@page_size) + ' * from ' +
' (select top ' + convert(varchar(10),(@page_index + 1) * @page_size) +' * from '+ -- N+1?br />
' ('+ @str_sql +') Src '
--排序方向
if @order_type !=0
begin
set @strsql= @strtmp +
' order by @str_orderfield asc) a ' +
' order by @str_orderfield desc)b' +
' order by @str_orderfield asc'
end
else
begin
set @strsql= @strtmp +
' order by @str_orderfield desc) a ' +
' order by @str_orderfieldasc)b' +
' order by @str_orderfield desc'
end
exec (@strsql)
GO
----------------------------------------------------------------------------
2.分页存储q程执行中用到的行数l计
create procedure getRowCount
@sql nvarchar(2000),
@count int output
as
begin
--------------------
-- 获取数据总行?--
--------------------
declare @tmpsql nvarchar(2000)
set @tmpsql='select @count=count(*) from ('+ @sql +') a'
execute sp_executesql @tmpsql,N'@count int output',@count output
end
GO