1月 18

查找方法

    public StudentInfo getStudent(int id) throws SQLException{ 
  StudentInfo studentInfo=null;
   
  String sql = "select id,name, sex, age from  [tb_Student] where id=?";
  PreparedStatement preparedStatement = conn.prepareStatement(sql);
  preparedStatement.setInt(1, id);
  ResultSet resultSet = preparedStatement.executeQuery(); 
  if(resultSet.next()){
   studentInfo=new StudentInfo();
   studentInfo.setId(resultSet.getInt("id"));
   studentInfo.setName(resultSet.getString("name")); 
   studentInfo.setSex(resultSet.getInt("sex"));
   studentInfo.setAge(resultSet.getInt("age")); 
  }  
  return studentInfo;
 }

调用方法

    AddTest addTest=new AddTest(); 
    
      StudentInfo studentInfo=new StudentInfo();
     studentInfo=addTest.getStudent(100);
     System.out.println(studentInfo.toString());

如果是查找多条

把if(resultSet.next()){ 换成 while(resultSet.next()){

加List返回就可以了

written by ocean

1月 18

更新方法

    public void updateStudent(StudentInfo studentInfo) throws SQLException{ 
 String sql = "update  [tb_Student] set name=? ,sex=?,age=? where id=?";
 PreparedStatement preparedStatement = conn.prepareStatement(sql);
 preparedStatement.setString(1, studentInfo.getName());
 preparedStatement.setInt(2, studentInfo.getSex());
 preparedStatement.setInt(3, studentInfo.getAge());
 preparedStatement.setInt(4, studentInfo.getId());
 preparedStatement.executeUpdate(); 
}

调用方法

    AddTest addTest=new AddTest();
     for(int index=120;index<130;index++){ 
      StudentInfo studentInfo=new StudentInfo();
      studentInfo.setId(index);
      studentInfo.setName("更新ysuhy"+index);
      studentInfo.setAge(999);
      studentInfo.setSex(index%2+10);
      addTest.updateStudent(studentInfo); 
     }

结论:

其实和增加,删除完全一样,除了sql

这点类似于.net

written by ocean

1月 18

删除方法

    public void deleteStudent(int id) throws SQLException{ 
  String sql = "delete from  [tb_Student] where id=?";
  PreparedStatement preparedStatement = conn.prepareStatement(sql);
  preparedStatement.setInt(1, id);
  preparedStatement.executeUpdate(); 
 }

调用

    AddTest addTest=new AddTest();
for(int index=150;index<160;index++){     
 addTest.deleteStudent(index);
}

结论:

其实和增加完全一样,除了sql

written by ocean

1月 18

添加方法

    public class AddTest {
 
   
 public AddTest(){
   
  this.conn=getConnValue();
 } 
 private Connection conn;
 
 public Connection getConnValue() {
  try {
   Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
   String url = "jdbc:sqlserver://127.0.0.1:1433;databaseName=DB_JavaTest";
   String username = "sa";
   String password = "*****";
   conn = DriverManager.getConnection(url, username, password);
  } catch (Exception e) {
   e.printStackTrace();
  }
  return conn;
 } 
  
 public void addStudent(StudentInfo studentInfo) throws SQLException{ 
  String sql = "insert into [tb_Student] (name, sex, age) values(?,?,?)";
  PreparedStatement preparedStatement = conn.prepareStatement(sql);
  preparedStatement.setString(1, studentInfo.getName());
  preparedStatement.setInt(2, studentInfo.getSex());
  preparedStatement.setInt(3, studentInfo.getAge());
  preparedStatement.executeUpdate(); 
 } 
}

调用

    AddTest addTest=new AddTest();
   for(int index=100;index<200;index++){ 
    StudentInfo studentInfo=new StudentInfo();
    studentInfo.setName("ysuhy"+index);
    studentInfo.setAge(26+index/3);
    studentInfo.setSex(index%2);
    addTest.addStudent(studentInfo); 
   }

written by ocean

1月 18

学习一下JDBC,第一步

连接数据库

不是太顺利,网上找了几个教程,发现我自己用起来都会有问题,也不知道是我自己的人品有问题还是这些人压根就没测试

先上代码

  public static void main(String[] args) throws SQLException {
  try {
   Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
   System.out.println("数据库驱动程序注册成功!");
   String url = "jdbc:sqlserver://127.0.0.1:1433;databaseName=DB_JavaTest";
   String user = "sa";
   String password = "我是密码";
   Connection conn = DriverManager.getConnection(url, user, password);
   System.out.println("数据库连接成功");
  } catch (Exception e) {
   e.printStackTrace();
   System.out.println("数据库连接失败");
  }
 }

 其中Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");是用来预加载jar包到内存中

可以理解为预热

DriverManager  根据url实例出对应的connection实例

 

在SQL Server 2000 中加载驱动和URL路径的语句是

String driverName = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
String dbURL = "jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sample";

而SQL Server 2005 中加载驱动和URL的语句则为

String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
String dbURL = "jdbc:sqlserver://localhost:1433; DatabaseName=sample";

 

最后说个很奇怪的问题

我用localhost连接一直出错,后来改成127.0.0.1OK了

 

written by ocean

1月 17

因为总是写一些采集器呀,多线程运算呀之类的东西

每次都需要手工去控制线程的开始,启动,结束,显示状态等,太麻烦了

今天整合了一下,提取出来一个类专门干这个,以后就方便了

记录如下

    
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
 
namespace XydSoft.FrameWork.Manager
{
    /// <summary>
    /// 多线程模板类
    /// Author:ysuhy   4965770@qq.com
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ThreadManager<T>
    {
        #region -- 私有属性 --
        /// <summary>
        /// 开始执行的时间
        /// </summary>
        private DateTime StartDateTime = DateTime.Now;
        /// <summary>
        /// 总任务数量
        /// </summary>
        private int TotalTask = 0;
        /// <summary>
        /// 锁定用
        /// </summary>
        private object obj = new object();
 
        /// <summary>
        /// 计数器
        /// </summary>
        private int count = 0;
        /// <summary>
        /// 计数器,内部使用
        /// </summary>
        private int Count
        {
            set
            {
                lock (this.obj)
                    this.count = value;
            }
            get
            {
                return this.count;
            }
        }
        /// <summary>
        /// 每隔多少秒输出一次,默认30秒
        /// </summary>
        private int IntervalDisplay = 30;
        /// <summary>
        /// 是否以单线程执行
        /// </summary>
        private bool IsSingleThread = false;
        /// <summary>
        /// 数据
        /// </summary>
        private List<T> Items = null;
        /// <summary>
        /// 委托方法
        /// </summary>
        private event Func<T, object> threadItemDo;
 
        /// <summary>
        /// 当前任务Title
        /// </summary>
        private string title = null;
        private string defaultString = "==========================================================================";
        #endregion
 
        #region -- 设置参数 --
        /// <summary>
        /// 设置每隔多少秒输出一次,默认30秒
        /// </summary>
        /// <param name="second"></param>
        public void SetIntervalDisplay(int second)
        {
            this.IntervalDisplay = second;
        }
        /// <summary>
        /// 设置是否以单线程执行
        /// </summary>
        /// <param name="isSingleThread"></param>
        public void SetIsSingleThread(bool isSingleThread)
        {
            this.IsSingleThread = isSingleThread;
        }
        /// <summary>
        /// 设置数据
        /// </summary>
        /// <param name="list"></param>
        public void SetData(List<T> list)
        {
            Items = list;
        }
        /// <summary>
        /// 设置委托方法
        /// </summary>
        /// <param name="threadItemDo"></param>
        public void SetFunction(Func<T, object> threadItemDo)
        {
            this.threadItemDo = threadItemDo;
        }
        /// <summary>
        /// 设置Task Title
        /// </summary>
        /// <param name="title"></param>
        public void SetTitle(string title)
        {
            this.title = title;
        }
        #endregion
 
        #region -- 线程执行方法 --
        /// <summary>
        /// 入口方法
        /// </summary>
        public void Start()
        {
            ThreadPool.SetMaxThreads(20, 20);
            this.Init();
 
            if (this.IsSingleThread)
                this.DoSingleThread();
            else
                this.DoMultiThread();
        }
        /// <summary>
        /// 初始化方法
        /// </summary>
        private void Init()
        {
            if (this.Items == null || this.Items.Count == 0)
                throw new Exception("参数不正确");
            if (threadItemDo == null)
                throw new Exception("委托方法不正确");
            this.Count = this.Items.Count;
            this.TotalTask = this.Count;
        }
        /// <summary>
        /// 单线程执行
        /// </summary>
        private void DoSingleThread()
        {
            foreach (var item in this.Items)
            {
                var param = (T)item;
                threadItemDo(param);
                Count--;
            }
        }
        /// <summary>
        /// 多线程执行
        /// </summary>
        private void DoMultiThread()
        {
            foreach (var item in this.Items)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object obj)
                {
                    var param = (T)obj;
                    threadItemDo(param);
                    Count--;
                }), item);
            }
            AutoResetEvent mainAutoResetEvent = new AutoResetEvent(false);
            RegisteredWaitHandle registeredWaitHandle = null;
            registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(new AutoResetEvent(false), new WaitOrTimerCallback(delegate(object obj, bool timeout)
            {
                int workerThreads = 0;
                int maxWordThreads = 0;
                int compleThreads = 0;
                ThreadPool.GetAvailableThreads(out workerThreads, out compleThreads);
                ThreadPool.GetMaxThreads(out maxWordThreads, out compleThreads);
                Console.WriteLine(Message());
                //当可用的线数与池程池最大的线程相等时表示线程池中所有的线程已经完成
                if (workerThreads == maxWordThreads)
                {
                    //Console.WriteLine("线程池里的线程都执行完了");
                    mainAutoResetEvent.Set();
                    registeredWaitHandle.Unregister(null);
                }
            }), null, this.IntervalDisplay * 1000, false);
            Console.WriteLine(defaultString);
            Console.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]" + this.title == null ? string.Empty : title + "====>Start");
            Console.WriteLine(defaultString);
            mainAutoResetEvent.WaitOne();
            Console.WriteLine(defaultString);
            Console.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]" + this.title == null ? string.Empty : title + "====>End");
            Console.WriteLine(defaultString);
        }
        /// <summary>
        /// 输出状态消息
        /// </summary>
        /// <returns></returns>
        private string Message()
        {
            var tp = (TimeSpan)(DateTime.Now - StartDateTime);
            string residueMsg = string.Empty;
            if (tp.TotalSeconds > 0)
            {
                if (TotalTask > Count)
                {
                    int residueSecond = (int)(Count / ((decimal)(TotalTask - Count) / (decimal)tp.TotalSeconds));
                    residueMsg = string.Format(",剩余时间:{0}:{1}:{2}", residueSecond / 3600, residueSecond / 60 % 60, residueSecond % 60);
                }
            }
            string msg = string.Format("[{5}][剩余任务:{0}{4},执行耗时:{1}:{2}:{3}]", this.Count, (int)(tp.TotalHours), tp.Minutes, tp.Seconds,
            residueMsg == string.Empty ? string.Empty : residueMsg, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            int n = (defaultString.Length - (msg.Length + 8));
            msg = "===" + msg;
            for (int index = 0; index < n - 3 - (residueMsg == string.Empty ? 0 : 4); index++)
                msg += "=";
            //msg = defaultString + "\r\n" + msg + "\r\n" + defaultString;
            return msg;
        }
        #endregion
    }
}

调用如下,确实很方便,我会把它整理到 XydSoft.FrameWork里面

List<IpInfo> list = new List<IpInfo>();
.....//此处加入数据
ThreadManager<IpInfo> threadManager = new ThreadManager<IpInfo>();
threadManager.SetFunction(a => {
    if (XXX)) {
        return a.IP + ":" + a.Port+"---OK";
    }
    return a.IP + ":" + a.Port + "---X";
});
threadManager.SetData(list);
threadManager.Start();

written by ocean

1月 17

ibatis是java下的一个orm组件

下载:http://code.google.com/p/mybatis/

引用jar包之后主要要有SqlSessionFactory对象

public class Util {
private static SqlSessionFactory sqlSessionFactory;
static {
String resource = "configuration.xml";
Reader reader = null;
try {
reader = Resources.getResourceAsReader(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
public static SqlSessionFactory getSessionFactory() {
return sqlSessionFactory;
}
}

configuration.xml 其实就是主要的配置文件

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE configuration 
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-config.dtd"> 
<configuration> 
<environments default="development"> 
<environment id="development"> 
<transactionManager type="JDBC"/> 
<dataSource type="POOLED"> 
<property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
<property name="url" value="jdbc:sqlserver://localhost;database=DB_JAVATest;"/> 
<property name="username" value="sa"/> 
<property name="password" value="password"/> 
</dataSource> 
</environment> 
</environments> 
<mappers> 
<mapper resource="sql/Student.xml"/> 
</mappers> 
</configuration>

实体很简单

public class StudentInfo {
 
private int id;
private String name;
private int sex;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
 
 
}

XML文件需要写一下相应的SQL

Student.xml

<?xml version="1.0" encoding="UTF-8" ?>    
<!DOCTYPE mapper    
PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"    
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">    
     
      
<mapper namespace="com.test.ibatis.StudentXML">  
   
    <select id="loadStudent" parameterType="int" resultType="com.test.ibatis.entity.StudentInfo">    
        select * from [tb_Student] where id = #{id}  
    </select>    
     
    <select id="findStudent" resultType="com.test.ibatis.entity.StudentInfo">
     select * from [tb_Student]
    </select>
     
    <insert id="insertStudent" parameterType="com.test.ibatis.entity.StudentInfo">
     insert into [tb_Student] (name, sex, age) values(#{name}, #{sex},#{age})
    </insert>
     
    <update id="updateStudent" parameterType="com.test.ibatis.entity.StudentInfo">
     update [Student] set name = #{name} where id = #{id}  
    </update>
     
    <delete id="deleteStudent" parameterType="int">
     delete from [tb_Student] where id =#{id}  
    </delete>
</mapper>

DAO

package com.test.ibatis.dao;
import org.apache.ibatis.session.SqlSession;
import com.test.ibatis.entity.StudentInfo;
public class StudentDAO {
  
  
 public void insertStudent(StudentInfo studentInfo) {
  SqlSession session = com.test.ibatis.Util.getSessionFactory()
    .openSession();
  try {
   session.insert("com.test.ibatis.StudentXML.insertStudent",
     studentInfo);
   session.commit();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   session.close();
  }
 }
  
  
  
 public StudentInfo loadStudentInfo(int id) {
  StudentInfo studentInfo = null;
  SqlSession session = com.test.ibatis.Util.getSessionFactory()
    .openSession(); 
  try { 
   studentInfo = (StudentInfo) session.selectOne("com.test.ibatis.StudentXML.loadStudent", 1);  
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   session.close();
  }
  return studentInfo;
 }
  
}

最后调用代码

StudentDAO studentDao = new StudentDAO();
for(int index=1;index<100;index++){ 
 StudentInfo studentInfo=new StudentInfo();
 studentInfo.setName("ysuhy"+index);
 studentInfo.setAge(26+index/3);
 studentInfo.setSex(index%2);
 studentDao.insertStudent(studentInfo);
}
 
StudentInfo studentInfo=studentDao.loadStudentInfo(1);  
System.out.println(studentInfo.getId());   
System.out.println(studentInfo.getName());

written by ocean

1月 11

我在上一篇文章中讲到了如何使用C#模拟用户登录具有验证码网站。今天我就换位思考一下,站在网站开发人员的角度讲一讲验证码的的一个安全问题:及时销毁网站中的验证码。

为了方便大家理解,这里我就以一个投票的应用网站为例进行说明。投票网站首先要防止的就是用户不断点击投票按钮来重复投票;当然,避免重复投票的解决办法有很多,比如记录IP、写入Session、Cookie甚至还有要求用户输入身份证号码等。但是你记录IP,那我就写一个程序来模拟发包,每投1票后自动换代理,然后继续投票,如果是写入到Session中那么我写个投票程序,每投1票就重新开启一个新的会话就是。如果是记入Cookie,那我该表Cookie的值再模拟投票发包,要输入身份证号进行验证?写个身份证号码生成程序也十分容易……

在投票机器人面前,记录IP、记录身份证号码、写入Session和Cookie等防作弊技术形同虚设。所以在投票网站中验证码功能必不可少。那么我们将验证码功能加入到网站投票中:

1.生成验证码图片的页面CreateImg.aspx,其后台代码为:

protected void Page_Load(object sender, EventArgs e)
   {
string checkCode = CreateCode(4);//生成随机是4位验证码
       Session["CheckCode"] = checkCode;//将验证码保存到Session中
       CreateImage(checkCode);//将验证码以图片的方式输出
   }  

2.在用户单击投票按钮后触发的事件:

OK,大功告成!这个程序逻辑上有问题吗?没有吧,验证码是生成的图片,图片是有干扰因素的,不会被程序识别,而且验证码的内容是保存到服务器的,逻辑处理也是错。似乎一切都那么完美,但是事实并不是这样,对于这样的投票网站,我的投票机器人仍然肆无忌惮的不断切换IP,不断刷票。(要做投票机器人的同志们注意啦,不要看到投票的地方是有验证码的就一筹莫展了哦,也许他的网站就存在以下描述的漏洞哦!)

漏洞就出在投票时对验证码进行验证后没有对服务器上Session中的验证码内容进行销毁。在平时使用IE浏览时,每投票一次后刷新页面,验证码生成页面被重新请求,所以Session值在请求验证码生成页时被替换,所以不会有什么问题。但是现在面对的是投票机器人,我的机器人在第一次请求时获得验证码的图片并展示给用户,用户肉眼识别验证码,然后输入程序的文本框中,由于服务器上验证码的内容并没有被销毁,而且投票程序也不会再请求验证码生成图片的URL,所以接下来每次使用相同的SessionID和用户输入的验证码值,服务器验证投票时  
if (Session["CheckCode"].ToString().ToLower() != txbCode.Text.ToLower())
都会返回false,验证码都是通过的,所以投票自然成功。终究是百密一疏啊!费尽心思防止投票作弊,最终却因为这一个地方的疏忽而前功尽弃,投票作弊成功,投票结果还是被投票机器人所左右。

也许有人想到了,那可以在Session中放置一个标记,如果投票成功了就将标记置“1”,下次请求时判断Session中标记为“1”就拒绝投票就是了。但是投票只是我这里举的一个例子,像论坛这种用验证码防止用户恶意灌水的总不可能限制用户只发一帖吧。论坛发帖时的验证码如果没有被及时销毁,那么我的灌水机器人就仍然可以到处肆意发帖了,哈哈哈哈。

要避免这个漏洞被利用还是很简单,只需要将上面的代码中投票完成后立即将验证码从服务器上销毁即可:

 

这样如果仍然使用相同的SessionID和验证码值,那么将会在 if (Session["CheckCode"] == null)这里判断出验证码已经过期,想成功投票?重新请求验证码页面获得验证码图片,然后重新输入验证码吧!
这个问题虽然看起来不以为然,但是正所谓“千里之堤毁于蚁穴”,只要验证码没有从服务器上销毁,那么页面上的验证码还是形同虚设,和验证码的图片地址为<img src="CreateCheckCode.aspx?code=af5d" alt="验证码">
这样把验证码直接暴露在HTML中或者直接使用文本而不是图片来表示验证码有什么区别呢?

另外有人提到,这里是Session保存验证码才会有这个问题,那完全基于Cookie加密的呢?在前面的文章中我也提到过Cookie加密的方式保存验证码的内容,但是今天我又仔细想了一下,得出结论:验证码内容不能保存到客户端,也就是说根本就不应该使用Cookie加密的方式,Cookie加密保存验证码明文是没有什么意义的,必须要在服务器端保存与验证码相关的信息(比如验证码明文或者验证码加密解密密钥)。为什么不能使用Cookie加密保存验证码?我举个简单的例子吧:

比如现在页面上显示的验证码是1234,同时抓包发现提交的时候Cookie中有值:“EncryptCode=asdf”这是验证码的明文经过加密后的密文,我不知道加密算法是什么,但是我每次程序提交时就将1234作为验证码的值同时将“EncryptCode=asdf”作为Cookie的一部分发送到服务器,那么服务器将1234加密后与发送过来的Cookie值“asdf”一比较,二者相同,验证通过!!!

所以我认为验证码的明文是不可能完全基于客户端的,必须要在服务器上保存与验证码相关的信息(验证码明文或密钥)。既然要在服务器上保存相关信息,那么就可能出现这个漏洞。当然这是我想遍了所有验证码明文保存的方法后得出的结论,我还不敢拍胸脯说这是100%正确的,如果大家认为这个结论不正确,那希望能够提出具体的情况。

希望大家若做过验证码的都再回头看看自己的验证码内容在服务器上及时销毁没有。这个错误很容易犯,我在某大公司的网站上都发现了这个漏洞,可见犯此错的网站绝对不在少数。

最后希望大家的网站更加安全,更加健壮。

 

转载:http://www.cnblogs.com/studyzy/archive/2008/06/04/1213192.html

written by ocean

1月 06

如何备份虚拟主机上的数据库备份到本地呢?

或者有的时候我们想要将本地的数据库还原到虚拟主机上的数据库内,我们应该怎么做呢?

 

sql server 2005只要知道数据库账号和密码就可以直接导入和导出,很方便。下面说说我的具体操作步骤吧:

1.如何将远程服务器上的数据库备份到本地呢?

首先在本地建一个数据库名为backup1,然后使用sql server 2005管理器远程连接远程数据库,

 

选中你的数据库右键=》任务=》导出数据=》服务器名称填入服务器的IP即可,

使用sqlserver身份认证,输入用户名和密码(运营商给你的用户名和密码),

选择你的数据库=》下一步=》服务器名称选择本地的服务器的名称或者IP,使用sql server 身份认证输入账号和密码,

选择backup1数据库=》复制一个或多个表和视图的数据=》下一步。。。下面的我也不多说了。

 

 

2.如何将还原远程服务器上的数据库呢?

 

方法很类似在本地建一个数据库名为backup2,然后把备份文件还原到backup2,

远程连接你的远程数据库(使用sql server 2005),

选中你的数据库右键=》任务=》导入数据=》正确设置backup2的数据库信息=》下一步=》

正确配置你的远程数据库信息=》然后按提示操作就OK了。

就这样我们完全没有必要再去找第三方工具了。。。

written by ocean

1月 06

分页条件查询并且获取数据,两种方法,Query和Query2是两种方法

另外我用的是最新的lucene.net 2.94版本的写法

是通过TopDocs2Data方法取最终数据的,相对以前版本好处是按需取数据,不用一次加载全部

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using XydSoft.Article.Entity;

using Lucene.Net.Search;

using Lucene.Net.Analysis;

using Lucene.Net.QueryParsers;

using Lucene.Net.Analysis.Standard;

using Lucene.Net.Index;

using XydSoft.Article.Common;

using System.IO;

using Lucene.Net.Documents;

namespace XydSoft.Article.Luncene

{

   /// <summary>

   /// 查询类

   /// 重要

   /// </summary>

   public class QueryIndexManager

   {

       /// <summary>

       /// 分页获取列表数据

       /// </summary>

       /// <param name="tag"></param>

       /// <param name="pageIndex"></param>

       /// <param name="pageSize"></param>

       /// <param name="totalRec"></param>

       /// <returns></returns>

       public static List<ArticleInfo> Query(string tag, int pageIndex, int pageSize, out int totalRec)

       {

           QueryParser parser = new QueryParser("Title", Common.CurrentAnalyzer);

           Query query = parser.Parse(tag);

           Sort sort = new Sort(new SortField("AddDate", SortField.DOC, false));

           TopDocs topDocs = Common.GenerateSearcher().Search(query, (Filter)null, pageIndex * pageSize, sort);

           totalRec = topDocs.TotalHits;

           if (pageIndex == 1)

               return TopDocs2Data(topDocs.ScoreDocs);

           return TopDocs2Data(topDocs.ScoreDocs, pageIndex, pageSize, totalRec);

       }

       private static List<DataSourceInfo> Query2(string tag, int pageIndex, int pageSize, out int totalRec)

       {

           Query query = new WildcardQuery(new Term("Title", "*" + tag + "*"));

           Sort sort = new Sort(new SortField("AddDate", SortField.AUTO, false));

           IndexSearcher searcher = new IndexSearcher(XydSoft.Article.Common.Const.LuceneIndexPath, true);

           Hits hits = searcher.Search(query, sort);

           totalRec = hits.Length();

           int start = (pageIndex – 1) * pageSize;

           int end = pageIndex * pageSize;

           if (end > totalRec)

               end = totalRec;

           List<DataSourceInfo> list = new List<DataSourceInfo>();

           for (int index = start; index < end; index++)

           {

               DataSourceInfo dataSourceInfo = new DataSourceInfo();

               dataSourceInfo.Title = hits.Doc(index).Get("Title");

               dataSourceInfo.ID = hits.Doc(index).Get("ID").ToInteger();

               dataSourceInfo.AddDate = hits.Doc(index).Get("AddDate").ToDateTime();

               list.Add(dataSourceInfo);

           }

           return list;

       }

       #region 获取最终的数据

       /// <summary>

       /// 获取最终的数据

       /// </summary>

       /// <param name="scoreDoc"></param>

       /// <param name="pageIndex"></param>

       /// <param name="pageSize"></param>

       /// <param name="totalRec"></param>

       /// <returns></returns>

       private static List<ArticleInfo> TopDocs2Data(ScoreDoc[] scoreDoc, int pageIndex, int pageSize, int totalRec)

       {

           int start = (pageIndex – 1) * pageSize;

           int end = pageIndex * pageSize;

           if (end > totalRec)

               end = totalRec;

           List<ArticleInfo> list = new List<ArticleInfo>();

           for (int index = start; index < end; index++)

           {

               Document doc = Common.GenerateSearcher().Doc(scoreDoc[index].doc);

               ArticleInfo articleInfo = new ArticleInfo();

               articleInfo.Title = doc.Get("Title");

               articleInfo.ID = doc.Get("ID").ToInteger();

               articleInfo.AddDate = doc.Get("AddDate").ToDateTime();

               list.Add(articleInfo);

           }

           return list;

       }

       /// <summary>

       /// 获取最终的数据

       /// </summary>

       /// <param name="docs"></param>

       /// <returns></returns>

       private static List<ArticleInfo> TopDocs2Data(ScoreDoc[] docs)

       {

           if (docs == null || docs.Length == 0)

               return null;

           List<ArticleInfo> list = new List<ArticleInfo>();

           foreach (ScoreDoc sd in docs)

           {

               Document doc = Common.GenerateSearcher().Doc(sd.doc);

               ArticleInfo articleInfo = new ArticleInfo();

               articleInfo.Title = doc.Get("Title");

               articleInfo.ID = doc.Get("ID").ToInteger();

               articleInfo.AddDate = doc.Get("AddDate").ToDateTime();

               list.Add(articleInfo);

           }

           return list;

       }

       #endregion

   }

}

written by ocean