天空下的雨

用乐观的生活,品味非凡人生。 通用网址(手机):blog.sh96.cn

的存档

19

关于前端开发博客和技术网站收录

罗列常去的或不常去但也去过的博客和技术网站!

技术门户:
博客园: http://www.cnblogs.com
目前最活跃的.NET技术社区,.NET程序员必去的网站之一。

CSDN:http://www.csdn.net
刚学程序那会经常去论坛问问题,现在很少去。

infoQ:   http://www.infoq.com/cn/
infoq的中文站,软件开发中比较创新的一些内容,涵盖JAVA、.NET、Ruby等一些企业级架构的东西,里面的东西大多有深度,不常去。

蓝色理想:http://www.blueidea.com/
网站设计人员之家,主要关于网站页面设计和前端体验开发,通常搜CSS内容会搜到这里。

团队博客:
淘宝网用户体验设计UED
http://ued.taobao.com/blog/

口碑网用户体验设计UED
http://ued.koubei.com/

阿里软件UED团队
http://www.alisoftued.com

19楼UED团队
http://ued.dukuai.com/blog/

用户为中心的设计(UCD),UCD大社区
http://ucdchina.com/

站长、IT相关
落伍者论坛:http://www.im286.com/
中国站长的集聚地,最大站长社区

站长网:http://www.admin5.com/
中国站长经常吹嘘的地方

中国站长站:http://www.chinaz.com/
站长的全面资讯

DoNews:http://www.donews.com/
IT社区-媒体平台

草根网:http://www.20ju.com/
主要是关于IT资讯的内容,涵盖网站设计,运营,技术,招聘等。。

个人技术博客:
cssrain http://www.cssrain.cn  
懒人开发人员一定要去看看哦,资源超多,很多效果例子。特别是jquery。

李会军:http://www.dotneteye.cn  
去过博客园的应该都知道吧,神仙级专家。

赵劼:http://www.cnblogs.com/JeffreyZhao/  
同上,为博客员知名专家,特佩服他!

01

PHP中如何将变量跟字符串连接?

ASP能用连接符&连接变量和字符,对于初学者,我们在PHP语言下怎么解决这个问题呢?下面天空下的雨给个例子吧

例如这几个变量,与字符串相连接。
$a="aaa";
$b="bbb";
$c="ccc";

$echo "我们要这里是输出a的变量:$a变量";

经测试,很显然上面的方式是不能达到效果的,在php里面是用点(.)来表示的。

$echo "我们要这里是输出a的变量:".$a."变量";

27

ASP/PHP在线发送内容到邮箱的实例和完整代码

PHP发送订单或留言可以使用phpmailer的类来实现,可以使用变量来扩展。很多朋友遇到使用phpmailer的问题,第一有些虚拟主机是不支持的,第二正确的配置非常重要,第三邮箱不支持。错误分析:提示connect_host通常表示连接SMTP服务器配置错误或PHP服务器不支持此操作,提示recipients_failedaaa@test.com,是发送邮箱配置错误。

其实很简单这里就不多说了,下面是经过调试成功的代码和phpmailer类下载,供大家参考。

下载地址(天空下的雨修改版16K):phpmailer.rar

<?php
/*******************************
*   天空下的雨 调试
*******************************/
require_once("class.phpmailer.php");    'phpmailer类调用

$mail = new PHPMailer();   //建立对象
$mail->IsSMTP();               // 发送类型 SMTP
$mail->Host = "smtp.126.com"; // SMTP服务器
$mail->SMTPAuth = true;         // 是否验证
$mail->Username = "aaa@126.com";   // 用户名(普通邮件认证不需要加 @域名)
$mail->Password = "123456";        // 邮箱密码
$mail->From = "aaaa@126.com";      // 发件人邮箱,与SMTP服务器一致
$mail->FromName = "发件人名字" ;  // 发件人

阅读全文>>

01

JSP实现标题加省略号效果 函数实现

制作动态网页中经常用碰到标题很长,我们只想显示一部分内容,JSP实现的方法如下。

以下是我用JSP写的一个JavaBean,函数strcut(String str,int len)就是字符串截断函数了,参数str用于给出源字符串,len决定截断后的长度,返回值就是截断之后的字符串,长度超过len的就加上...

import java.sql.*;
public class fun
{
public String strcut(String str,int len)
{
if(str.length()>len)
{
String resultstr;
resultstr=str.substring(0,len)+"...";
return resultstr;
}
else
{
return str;
}
}
}

07

优化SQL数据库读取 实战经验

大家都在讨论关于数据库优化方面的东东,刚好参与开发了一个数据仓库方面的项目,以下的一点东西算是数据库优化方面的学习+实战的一些心得体会了,拿出来大家共享。欢迎批评指正阿!

SQL语句:
是对数据库(数据)进行操作的惟一途径;
消耗了70%~90%的数据库资源;独立于程序设计逻辑,相对于对程序源代码的优化,对SQL语句的优化在时间成本和风险上的代价都很低;
可以有不同的写法;易学,难精通。

SQL优化:
固定的SQL书写习惯,相同的查询尽量保持相同,存储过程的效率较高。
应该编写与其格式一致的语句,包括字母的大小写、标点符号、换行的位置等都要一致

ORACLE优化器:
在任何可能的时候都会对表达式进行评估,并且把特定的语法结构转换成等价的结构,这么做的原因是
要么结果表达式能够比源表达式具有更快的速度
要么源表达式只是结果表达式的一个等价语义结构
不同的SQL结构有时具有同样的操作(例如:= ANY (subquery) and IN (subquery)),ORACLE会把他们映射到一个单一的语义结构。

1 常量优化:
常量的计算是在语句被优化时一次性完成,而不是在每次执行时。下面是检索月薪大于2000的的表达式:
sal > 24000/12
sal > 2000
sal*12 > 24000
如果SQL语句包括第一种情况,优化器会简单地把它转变成第二种。
优化器不会简化跨越比较符的表达式,例如第三条语句,鉴于此,应尽量写用常量跟字段比较检索的表达式,而不要将字段置于表达式当中。否则没有办法优化,比如如果sal上有索引,第一和第二就可以使用,第三就难以使用。

2 操作符优化:
优化器把使用LIKE操作符和一个没有通配符的表达式组成的检索表达式转换为一个“=”操作符表达式。
例如:优化器会把表达式ename LIKE 'SMITH'转换为ename = 'SMITH'
优化器只能转换涉及到可变长数据类型的表达式,前一个例子中,如果ENAME字段的类型是CHAR(10), 那么优化器将不做任何转换。
一般来讲LIKE比较难以优化。

其中:
~~ IN 操作符优化:
     优化器把使用IN比较符的检索表达式替换为等价的使用“=”和“OR”操作符的检索表达式。
     例如,优化器会把表达式ename IN ('SMITH','KING','JONES')替换为
ename = 'SMITH' OR ename = 'KING' OR ename = 'JONES‘

~~ ANY和SOME 操作符优化:
     优化器将跟随值列表的ANY和SOME检索条件用等价的同等操作符和“OR”组成的表达式替换。
     例如,优化器将如下所示的第一条语句用第二条语句替换:
     sal > ANY (:first_sal, :second_sal)
     sal > :first_sal OR sal > :second_sal
     优化器将跟随子查询的ANY和SOME检索条件转换成由“EXISTS”和一个相应的子查询组成的检索表达式。
     例如,优化器将如下所示的第一条语句用第二条语句替换:
     x > ANY (SELECT sal FROM emp WHERE job = 'ANALYST')
     EXISTS (SELECT sal FROM emp WHERE job = 'ANALYST' AND x > sal)

~~ ALL操作符优化:
     优化器将跟随值列表的ALL操作符用等价的“=”和“AND”组成的表达式替换。例如:
     sal > ALL (:first_sal, :second_sal)表达式会被替换为:
     sal > :first_sal AND sal > :second_sal
     对于跟随子查询的ALL表达式,优化器用ANY和另外一个合适的比较符组成的表达式替换。例如
     x > ALL (SELECT sal FROM emp WHERE deptno = 10) 替换为:
     NOT (x <= ANY (SELECT sal FROM emp WHERE deptno = 10))
     接下来优化器会把第二个表达式适用ANY表达式的转换规则转换为下面的表达式:
     NOT EXISTS (SELECT sal FROM emp WHERE deptno = 10 AND x <= sal)

~~ BETWEEN 操作符优化:
     优化器总是用“>=”和“<=”比较符来等价的代替BETWEEN操作符。
     例如:优化器会把表达式sal BETWEEN 2000 AND 3000用sal >= 2000 AND sal <= 3000来代替。

~~ NOT 操作符优化:
     优化器总是试图简化检索条件以消除“NOT”逻辑操作符的影响,这将涉及到“NOT”操作符的消除以及代以相应的比较运算符。
     例如,优化器将下面的第一条语句用第二条语句代替:
     NOT deptno = (SELECT deptno FROM emp WHERE ename = 'TAYLOR')
     deptno <> (SELECT deptno FROM emp WHERE ename = 'TAYLOR')
     通常情况下一个含有NOT操作符的语句有很多不同的写法,优化器的转换原则是使“NOT”操作符后边的子句尽可能的简单,即使可能会使结果表达式包含了更多的“NOT”操作符。
     例如,优化器将如下所示的第一条语句用第二条语句代替:
     NOT (sal < 1000 OR comm IS NULL)
     NOT sal < 1000 AND comm IS NOT NULL sal >= 1000 AND comm IS NOT NULL

如何编写高效的SQL:
     当然要考虑sql常量的优化和操作符的优化啦,另外,还需要:

1 合理的索引设计:
例:表record有620000行,试看在不同的索引下,下面几个SQL的运行情况:
语句A
SELECT count(*) FROM record
WHERE date >'19991201' and date < '19991214‘ and amount >2000

语句B
SELECT count(*) FROM record
WHERE date >'19990901' and place IN ('BJ','SH')

语句C
SELECT date,sum(amount) FROM record
group by date
1 在date上建有一个非聚集索引
A:(25秒)
B:(27秒)
C:(55秒)
分析:
date上有大量的重复值,在非聚集索引下,数据在物理上随机存放在数据页上,在范围查找时,必须执行一次表扫描才能找到这一范围内的全部行。
2 在date上的一个聚集索引
A:(14秒)
B:(14秒)
C:(28秒)
分析:
在聚集索引下,数据在物理上按顺序在数据页上,重复值也排列在一起,因而在范围查找时,可以先找到这个范围的起末点,且只在这个范围内扫描数据页,避免了大范围扫描,提高了查询速度。
3 在place,date,amount上的组合索引
A:(26秒)
C:(27秒)
B:(< 1秒)
分析:
这是一个不很合理的组合索引,因为它的前导列是place,第一和第二条SQL没有引用place,因此也没有利用上索引;第三个SQL使用了place,且引用的所有列都包含在组合索引中,形成了索引覆盖,所以它的速度是非常快的。
4 在date,place,amount上的组合索引
A: (< 1秒)
B:(< 1秒)
C:(11秒)
分析:
这是一个合理的组合索引。它将date作为前导列,使每个SQL都可以利用索引,并且在第一和第三个SQL中形成了索引覆盖,因而性能达到了最优。
缺省情况下建立的索引是非聚集索引,但有时它并不是最佳的;合理的索引设计要建立在对各种查询的分析和预测上。一般来说:
有大量重复值、且经常有范围查询(between, >,< ,>=,< =)和order by、group by发生的列,考虑建立聚集索引;
经常同时存取多列,且每列都含有重复值可考虑建立组合索引;在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。
组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。

2 避免使用不兼容的数据类型:
例如float和INt、char和varchar、bINary和varbINary是不兼容的。数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。例如:
SELECT name FROM employee WHERE salary > 60000
在这条语句中,如salary字段是money型的,则优化器很难对其进行优化,因为60000是个整型数。我们应当在编程时将整型转化成为钱币型,而不要等到运行时转化。

3 IS NULL 与IS NOT NULL:
不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何在WHERE子句中使用is null或is not null的语句优化器是不允许使用索引的。

4 IN和EXISTS:
EXISTS要远比IN的效率高。里面关系到full table scan和range scan。几乎将所有的IN操作符子查询改写为使用EXISTS的子查询。
例子:
语句1
SELECT dname, deptno FROM dept
WHERE deptno NOT IN
(SELECT deptno FROM emp);
语句2
SELECT dname, deptno FROM dept
WHERE NOT EXISTS
(SELECT deptno FROM emp
WHERE dept.deptno = emp.deptno);
明显的,2要比1的执行性能好很多
因为1中对emp进行了full table scan,这是很浪费时间的操作。而且1中没有用到emp的INdex,
因为没有WHERE子句。而2中的语句对emp进行的是range scan。

5 IN、OR子句常会使用工作表,使索引失效:
如果不产生大量重复值,可以考虑把子句拆开。拆开的子句中应该包含索引。

6 避免或简化排序:
应当简化或避免对大型表进行重复的排序。当能够利用索引自动以适当的次序产生输出时,优化器就避免了排序的步骤。以下是一些影响因素:
索引中不包括一个或几个待排序的列;
group by或order by子句中列的次序与索引的次序不一样;
排序的列来自不同的表。
为了避免不必要的排序,就要正确地增建索引,合理地合并数据库表(尽管有时可能影响表的规范化,但相对于效率的提高是值得的)。如果排序不可避免,那么应当试图简化它,如缩小排序的列的范围等。

7 消除对大型表行数据的顺序存取:
在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。比如采用顺序存取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询 10亿行数据。避免这种情况的主要方法就是对连接的列进行索引。例如,两个表:学生表(学号、姓名、年龄??)和选课表(学号、课程号、成绩)。如果两个表要做连接,就要在“学号”这个连接字段上建立索引。
还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引,但某些形式的WHERE子句强迫优化器使用顺序存取。下面的查询将强迫对orders表执行顺序操作:
SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008
虽然在customer_num和order_num上建有索引,但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。因为这个语句要检索的是分离的行的集合,所以应该改为如下语句:
SELECT * FROM orders WHERE customer_num=104 AND order_num>1001
UNION
SELECT * FROM orders WHERE order_num=1008
这样就能利用索引路径处理查询。

8 避免相关子查询:
一个列的标签同时在主查询和WHERE子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次。查询嵌套层次越多,效率越低,因此应当尽量避免子查询。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行。

9 避免困难的正规表达式:
MATCHES和LIKE关键字支持通配符匹配,技术上叫正规表达式。但这种匹配特别耗费时间。例如:SELECT * FROM customer WHERE zipcode LIKE “98_ _ _”
即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。如果把语句改为SELECT * FROM customer WHERE zipcode >“98000”,在执行查询时就会利用索引来查询,显然会大大提高速度。
另外,还要避免非开始的子串。例如语句:SELECT * FROM customer WHERE zipcode[2,3] >“80”,在WHERE子句中采用了非开始子串,因而这个语句也不会使用索引。

10 不充份的连接条件:
例:表card有7896行,在card_no上有一个非聚集索引,表account有191122行,在account_no上有一个非聚集索引,试看在不同的表连接条件下,两个SQL的执行情况:
SELECT sum(a.amount) FROM account a,card b WHERE a.card_no = b.card_no
(20秒)
将SQL改为:
SELECT sum(a.amount) FROM account a,card b WHERE a.card_no = b.card_no and a.account_no=b.account_no
(< 1秒)
分析:
在第一个连接条件下,最佳查询方案是将account作外层表,card作内层表,利用card上的索引,其I/O次数可由以下公式估算为:
外层表account上的22541页+(外层表account的191122行*内层表card上对应外层表第一行所要查找的3页)=595907次I/O
在第二个连接条件下,最佳查询方案是将card作外层表,account作内层表,利用account上的索引,其I/O次数可由以下公式估算为:
外层表card上的1944页+(外层表card的7896行*内层表account上对应外层表每一行所要查找的4页)= 33528次I/O
可见,只有充份的连接条件,真正的最佳方案才会被执行。
多表操作在被实际执行前,查询优化器会根据连接条件,列出几组可能的连接方案并从中找出系统开销最小的最佳方案。连接条件要充份考虑带有索引的表、行数多的表;内外表的选择可由公式:外层表中的匹配行数*内层表中每一次查找的次数确定,乘积最小为最佳方案。
不可优化的WHERE子句
例1
下列SQL条件语句中的列都建有恰当的索引,但执行速度却非常慢:
SELECT * FROM record WHERE substrINg(card_no,1,4)='5378'
(13秒)
SELECT * FROM record WHERE amount/30< 1000
(11秒)
SELECT * FROM record WHERE convert(char(10),date,112)='19991201'
(10秒)
分析:
WHERE子句中对列的任何操作结果都是在SQL运行时逐列计算得到的,因此它不得不进行表搜索,而没有使用该列上面的索引;如果这些结果在查询编译时就能得到,那么就可以被SQL优化器优化,使用索引,避免表搜索,因此将SQL重写成下面这样:
SELECT * FROM record WHERE card_no like '5378%'
(< 1秒)
SELECT * FROM record WHERE amount< 1000*30
(< 1秒)
SELECT * FROM record WHERE date= '1999/12/01'
(< 1秒)

11 存储过程中,采用临时表优化查询:

1.从parven表中按vendor_num的次序读数据:
SELECT part_num,vendor_num,price FROM parven ORDER BY vendor_num
INTO temp pv_by_vn
这个语句顺序读parven(50页),写一个临时表(50页),并排序。假定排序的开销为200页,总共是300页。
2.把临时表和vendor表连接,把结果输出到一个临时表,并按part_num排序:
SELECT pv_by_vn,* vendor.vendor_num FROM pv_by_vn,vendor
WHERE pv_by_vn.vendor_num=vendor.vendor_num
ORDER BY pv_by_vn.part_num
INTO TMP pvvn_by_pn
DROP TABLE pv_by_vn
这个查询读取pv_by_vn(50页),它通过索引存取vendor表1.5万次,但由于按vendor_num次序排列,实际上只是通过索引顺序地读 vendor表(40+2=42页),输出的表每页约95行,共160页。写并存取这些页引发5*160=800次的读写,索引共读写892页。
3.把输出和part连接得到最后的结果:
SELECT pvvn_by_pn.*,part.part_desc FROM pvvn_by_pn,part
WHERE pvvn_by_pn.part_num=part.part_num
DROP TABLE pvvn_by_pn
这样,查询顺序地读pvvn_by_pn(160页),通过索引读part表1.5万次,由于建有索引,所以实际上进行1772次磁盘读写,优化比例为30∶1。

好了,搞定。
其实sql的优化,各种数据库之间都是互通的

24

在JSP中用bean简单封装数据库操作

首先,封装数据库操作,目的就是为了隐藏Java.sql包内的类,在编码中去掉核心的数据库操作代码。以杜绝直接数据库操作轻易带来的资源未释放问题。同时也减少了数据库操作的编码量。下面给大家一个简单的例子:

1、先用Bean来封装数据库操作

import Java.sql.*;
public class sql_data
{
    //声明变量
    String sDBDriver="sun.jdbc.odbc.JdbcOdbcDriver";   //数据库驱动
    String sConnStr="jdbc:odbc:book";    //使用桥对数据库连接
    Connection conn=null;
    ResultSet rs=null;

    //加载驱动
    public void sql_data()
    {
        try{
            class.forName(sDBDriver);
        }
        catch(Java.lang.ClassNotFoundException e)
        {
            System.err.println(e.getMessage());
        }
    }

    //数据插入
    public void executeInsert(String sql)
    {
        try
        {
            conn=DriverManager.getConnection(sConnStr);
            Statement stmt=conn.createStatement();
            stmt.executeUpdate(sql);
        }
        catch(SQLException ex)
        {
            System.err.println(ex.getMessage());
        }
    }

    //数据查询
    public ResultSet executeQuery(String sql)
    {
        rs=null;
        try
        {
            conn=DriverManager.getConnection(sConnStr);
            Statement stmt=conn.createStatement();
            rs=stmt.executeQuery(sql);
        }
        catch(SQLException ex)
        {
            System.err.println(ex.getMessage());
        }
    }

    //数据删除
    public void executeDelete(String sql)
    {
        try
        {
            conn=DriverManager.getConnection(sConnStr);
            Statement stmt=conn.createStatement();
            stmt.executeUpdate(sql);
        }
        catch(SQLException ex)
        {
            System.err.println(ex.getMessage());
        }
    }
}

2、在JSP页面中调用Bean:

……
<jsp:useBean id="sqlbean" class="book.sql_data"/>  <!-- 调用Bean的数据封装类 -->

<%!String sql,name;%>

<%

sqlbean.sql_data();   //连接数据库
sql="select * from table";
ResultSet rs=sqlbean.executeQuery(sql);

while(rs.next()){
  name=rs.getString("name");
%>

……
name1:<%=name%>  name2: <%=rs.getString("name")%>
……

<%
}
rs.close();
%>

10

SSH框架模式中的实用分页Java(Struts + Spring + Hibernate)

分页每个项目里面差不多都会用到 
我以前耶找了很多个,刚刚找到一个很好用的分页 (baallynn )

先是一个page的bean:
package com.leatherstore.other;
public class Page { 
    /** 是否有上一页 */
    private boolean hasPrePage; 
    /** 是否有下一页 */
    private boolean hasNextPage; 
    /** 每页的数量 */
    private int everyPage; 
    /** 总页数 */
    private int totalPage; 
    /** 当前页*/
    private int currentPage; 
    /** 起始点 */
    private int beginIndex; 
    /** 总记录数*/
    private int totalCount; 

public int getTotalCount() {
return totalCount;
}

public void setTotalCount(int totalCount) {
this.totalCount = totalCount;

    public Page(){ 
    } 
    
      public Page(int everyPage){
        this.everyPage = everyPage;
    } 

    public Page(boolean hasPrePage, boolean hasNextPage, 
                    int everyPage, int totalPage,
                    int currentPage, int beginIndex,int totalCount) {
        this.hasPrePage = hasPrePage;
        this.hasNextPage = hasNextPage;
        this.everyPage = everyPage;
        this.totalPage = totalPage;
        this.currentPage = currentPage;
        this.beginIndex = beginIndex;
        this.totalCount = totalCount;
    } 
    public int getBeginIndex() {
        return beginIndex;
    } 
    public void setBeginIndex(int beginIndex) {
        this.beginIndex = beginIndex;
    } 
    public int getCurrentPage() {
        return currentPage;
    } 
    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    } 

    public int getEveryPage() {
        return everyPage;
    } 
    public void setEveryPage(int everyPage) {
        this.everyPage = everyPage;
    } 

    public boolean getHasNextPage() {
        return hasNextPage;
    } 

    public void setHasNextPage(boolean hasNextPage) {
        this.hasNextPage = hasNextPage;
    } 

    public boolean getHasPrePage() {
        return hasPrePage;
    } 

    public void setHasPrePage(boolean hasPrePage) {
        this.hasPrePage = hasPrePage;
    } 

    public int getTotalPage() {
        return totalPage;
    } 

    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }
}

然后构建一个page的工厂PageUtil:
package com.leatherstore.other;
public class PageUtil {
/**
* Use the origin page to create a new page
*
* @param page
* @param totalRecords
* @return
*/
public static Page createPage(Page page, int totalRecords) {
return createPage(page.getEveryPage(), page.getCurrentPage(),
totalRecords);
}

/**
* the basic page utils not including exception handler
*
* @param everyPage
* @param currentPage
* @param totalRecords
* @return page
*/
public static Page createPage(int everyPage, int currentPage,
int totalRecords) {
everyPage = getEveryPage(everyPage);
currentPage = getCurrentPage(currentPage);
int beginIndex = getBeginIndex(everyPage, currentPage);
int totalPage = getTotalPage(everyPage, totalRecords);
boolean hasNextPage = hasNextPage(currentPage, totalPage);
boolean hasPrePage = hasPrePage(currentPage);

return new Page(hasPrePage, hasNextPage, everyPage, totalPage,
currentPage, beginIndex, totalRecords);
}

private static int getEveryPage(int everyPage) {
return everyPage == 0 ? 10 : everyPage;
}

private static int getCurrentPage(int currentPage) {
return currentPage == 0 ? 1 : currentPage;
}

private static int getBeginIndex(int everyPage, int currentPage) {
return (currentPage - 1) * everyPage;
}

private static int getTotalPage(int everyPage, int totalRecords) {
int totalPage = 0;

if (totalRecords % everyPage == 0)
totalPage = totalRecords / everyPage;
else
totalPage = totalRecords / everyPage + 1;

return totalPage;
}

private static boolean hasPrePage(int currentPage) {
return currentPage == 1 ? false : true;
}

private static boolean hasNextPage(int currentPage, int totalPage) {
return currentPage == totalPage || totalPage == 0 ? false : true;
}

}


然后建一个专用的bean:

package com.leatherstore.hibernate.domain;

import java.util.List;

import com.leatherstore.other.Page;

public class Result {
private Page page;  //分页信息
private List content;  //每页显示的集合 
    public Result() {
        super();
    } 
    public Result(Page page, List content) {
        this.page = page;
        this.content = content;
    } 
    public List getContent() {
        return content;
    } 
    public Page getPage() {
        return page;
    } 
    public void setContent(List content) {
        this.content = content;
    } 
    public void setPage(Page page) {
        this.page = page;
    }
}

然后在数据访问层写两个方法:
ProductDAO:
public List getProductByPage(Page page); 
public int getProductCount();  //返回数据的总数
ProductDAO的接口实现ProductDAOImpl:
//为了在spring里统一编程风格:我用的回调的方法
public List getProductByPage(final Page page) {
return this.getHibernateTemplate().executeFind(new HibernateCallback(){
public Object doInHibernate(Session session) throws HibernateException, SQLException {
Query query=session.createQuery("from Productinfo");
query.setFirstResult(page.getBeginIndex()); //hibernate分页的精髓   呵呵
    query.setMaxResults(page.getEveryPage());
    return query.list();
}
});
}

public int getProductCount() {
List list=this.getHibernateTemplate().find("select count(*) from Productinfo");
return ((Integer)list.iterator().next()).intValue();
}

然后是业务层:
IProduct:
public Result listProduct(Page page);
然后IProduct接口的实现:IProductImpl:
private ProductDAO productDAO;
public void setProductDAO(ProductDAO productDAO){
this.productDAO=productDAO;
}

public Result listProduct(Page page) {
int totalRecords = this.productDAO.getProductCount();
page = PageUtil.createPage(page, totalRecords);
        List products = this.productDAO.getProductByPage(page);     
        return new Result(page, products);
}
然后再代理层:
ProductProxy:
IProduct pro=(IProduct)AppContext.getInstance().getappcontext().getBean("productServicewithTran");

public Result productlist(Page page){
try{
return pro.listProduct(page);
}catch(DataAccessException ex){
ex.printStackTrace();
return null;
}
}

呵呵 终于到productAction啦
显示前方法的代码
Page page = new Page();   //实例化一个page对象
page.setEveryPage(10);    //设置每页显示的条数
page.setCurrentPage(1);    //为第一页
Result result = pdp.productlist(page);
request.setAttribute("page", pageinfo);
request.setAttribute("productlist", list);
return mapping.findForward("showProduct");
接着就是jsp页面了
<logic:iterate id="product" name="productlist">
//中间迭代所要显示的数据
</logic:iterate>
<tr>
    <td width="80" height="30">&nbsp;</td>
    <logic:equal value="true" name="page" property="hasPrePage">
    <td width="150" height="30"><div align="right"><a href="../product.do?method=showProductByTag&index=first&msg=${msg }">首页</a></div></td>
    <td width="80" height="30"><div align="center"><a href="../product.do?method=showProductByTag&index=prew&pageno=${page.currentPage -1}&msg=${msg }">上一页</a></div></td>
    </logic:equal>
    <logic:notEqual value="true" name="page" property="hasPrePage">
    <td width="150" height="30"><div align="right">首页</div></td>
    <td width="80" height="30"><div align="center">上一页</div></td>
    </logic:notEqual>
    <logic:equal value="true" name="page" property="hasNextPage">
    <td width="80" height="30"><div align="center"><a href="../product.do?method=showProductByTag&index=next&pageno=${page.currentPage +1 }&msg=${msg }">下一页</a></div></td>
    <td width="80" height="30"><div align="center"><a href="../product.do?method=showProductByTag&index=end&pageno=${page.totalPage }&msg=${msg }">尾页</a></div></td>
    </logic:equal>
    <logic:notEqual value="true" name="page" property="hasNextPage">
    <td width="80" height="30"><div align="center">下一页</div></td>
    <td width="80" height="30"><div align="center">尾页</div></td>
    </logic:notEqual>
    <td height="30" colspan="3"><div align="center">页次${page.currentPage }/${page.totalPage }&nbsp;&nbsp;&nbsp;共${page.totalCount }条记录</div>      <div align="center"></div></td>
  </tr>
可以显示相应的页面信息
然后productAction里面的showProductByTag代码如下:
Page page = new Page();
page.setEveryPage(10);
String pagemark = request.getParameter("goto");
if (pagemark == null) {
String state = request.getParameter("index");
String pageno = request.getParameter("pageno");
System.out.println("pageno=" + pageno);
if ("first".equals(state)) {
page.setCurrentPage(1);
Result result = pdp.productlist(page);
request.setAttribute("page", result.getPage());
request.setAttribute("productlist", result.getContent());
} else if ("prew".equals(state)) {
page.setCurrentPage(Integer.parseInt(pageno));
Result result = pdp.productlist(page);
request.setAttribute("page", result.getPage());
request.setAttribute("productlist", result.getContent());
} else if ("next".equals(state)) {
page.setCurrentPage(Integer.parseInt(pageno));
Result result = pdp.productlist(page);
request.setAttribute("page", result.getPage());
request.setAttribute("productlist", result.getContent());
} else if ("end".equals(state)) {
page.setCurrentPage(Integer.parseInt(pageno));
Result result = pdp.productlist(page);
request.setAttribute("page", result.getPage());
request.setAttribute("productlist", result.getContent());
}
} else {
page.setCurrentPage(Integer.parseInt(pagemark));
Result result = pdp.productlist(page);
request.setAttribute("page", result.getPage());
request.setAttribute("productlist", result.getContent());
}
return mapping.findForward("showProduct");

完了,大功告成了! 虽然代码多了点,但我觉得这样挺好的。

30

Java开发者需坚守的十大基本准则【转自IT168】

  有许多标准和实践准则可适用于Java开发者,但此处要说的,是每个Java开发者需坚守的基本原则。

  一、为代码加注释。虽然每个人都知道这点,但有时却不自觉忘了履行,今天你“忘了”加注释了吗?虽然注释对程序的功能没什么“贡献”,但过一段时间,比如说两星期之后或者更长,回过头来看看自己的代码,说不定已经记不住它是干什么的了。如果这些代码是你个人的,那还算是走运了,不幸的是,当然了,大多数时候都是别人的不幸,很多时候大家都是在为公司写代码,写代码的人也许早已经离开了公司,但别忘了一句古话,有来有往嘛,为他人,也为我们自己,请为你的代码加上注释。

  二、不要让事情复杂化。程序员有时候总是对简单问题想出复杂的解决方案,比如说,在只有五个用户的程序中引入EJB、对程序实现了并不需要的框架(framework),之类的还有属性文件、面向对象解决方案、多线程等等。为什么要这样做呢?也许我们并不知道是否这样会更好,但这样做也许可以学到一些新东西,或者让自己更感兴趣一些。如果是不知道为什么这样做,建议多请教经验丰富的程序员,如果是为了个人的目的,麻烦让自己更专业一点。

  三、始终牢记——“少即是好(Less is more)并不总是对的”。代码效率虽然很重要,但在许多解决方案中,编写更少的代码并不能改善这些代码的效率,请看下面这个简单的例子:

if(newStatusCode.equals("SD") && (sellOffDate == null ||
todayDate.compareTo(sellOffDate)<0 || (lastUsedDate != null &&
todayDate.compareTo(lastUsedDate)>0)) ||
(newStatusCode.equals("OBS") && (OBSDate == null ||
todayDate.compareTo(OBSDate)<0))){
newStatusCode = "NYP";
}

  能看明白if条件语句是干什么的吗?能想出来是谁写的这段代码吗?如果把它分成两段独立的if语句,是不是更容易理解呢,下面是修改后的代码:

if(newStatusCode.equals("SD") && (sellOffDate == null ||
todayDate.compareTo(sellOffDate)<0 || (lastUsedDate != null &&
todayDate.compareTo(lastUsedDate)>0))){
newStatusCode = "NYP";
}else
if(newStatusCode.equals("OBS") && (OBSDate == null ||
todayDate.compareTo(OBSDate)<0))
{
newStatusCode = "NYP";
}

  是不是读起来容易多了呢,在此只是多加了一个if和两个花括号,但代码的可读性与可理解性就一下子提高了一大截。

  四、请不要硬编码。开发者经常有意“忘记”或忽略掉这点,因为有些时候开发日程逼得实在太紧。其实,多写一行定义静态变量的代码能花多少时间呢?

public class A {
public static final String S_CONSTANT_ABC = "ABC";
public boolean methodA(String sParam1){
if (A.S_CONSTANT_ABC.equalsIgnoreCase(sParam1)){
return true;
}
return false;
}
}

  现在,每次需要将“ABC”与其他变量进行比较时,不必记住实际代码,直接引用A.S_CONSTANT_ABC就行了,而且在今后需要进行修改时,也可在一处修改,不会翻遍整个源代码逐个修改了。

  五、不要“创造”自己的框架(framework)。确切来说,有数以千计的各种框架存在,而且大多数是开源的,这些框架都是优秀的解决方案,可用于日常程序开发中,我们只需使用这些框架的最新版本就行了,至少表面上要跟上形势吧。被大家广为接受的最为明显的一个例子就是Struts了,这个开源web框架非常适合用在基于web的应用程序中。是不是想开发出自己的Struts呢,还是省点力气吧,回头看看第二条——不要让事情复杂化。另外,如果正在开发的程序只有3个窗口,就不要使用Struts了,对这种程序来说,不需要那么多的“控制”。

  六、不要使用println及字符串连接。通常为了调试方便,开发者喜欢在可能的所有地方都加上System.out.println,也许还会提醒自己回过头来再来删除,但有些时候,经常会忘了删除或者不愿意删除它们。既然使用System.out.println是为了测试,那么测试完之后,为什么还要留着它们呢,因为在删除时,很可能会删除掉真正有用的代码,所以不能低估System.out.println危害啊,请看下面的代码:

public class BadCode {
public static void calculationWithPrint(){
double someValue = 0D;
for (int i = 0; i <10000; i++) {
System.out.println(someValue = someValue + i);
}
}
public static void calculationWithOutPrint(){
double someValue = 0D;
for (int i = 0; i < 10000; i++) {
someValue = someValue + i;
}
}
public static void main(String [] n) {
BadCode.calculationWithPrint();
BadCode.calculationWithOutPrint();
}
}

  从测试中可以发现,方法calculationWithOutPrint()执行用了0.001204秒,作为对比,方法calculationWithPrint()执行可是用了10.52秒。

  要避免浪费CPU时间,最好的方法是引入像如下的包装方法:

public class BadCode {
public static final int DEBUG_MODE = 1;
public static final int PRODUCTION_MODE = 2;
public static void calculationWithPrint(int logMode){
double someValue = 0D;
for (int i = 0; i < 10000; i++) {
someValue = someValue + i;
myPrintMethod(logMode, someValue);
}
}
public static void myPrintMethod(int logMode, double value) {
if (logMode > BadCode.DEBUG_MODE) { return; }
System.out.println(value);
}
public static void main(String [] n) {
BadCode.calculationWithPrint(BadCode.PRODUCTION_MODE);
}
}

  另外,字符串连接也是浪费CPU时间的一个大头,请看下面的示例代码:

public static void concatenateStrings(String startingString) {
for (int i = 0; i < 20; i++) {
startingString = startingString + startingString;
}
}
public static void concatenateStringsUsingStringBuffer(String startingString) {
StringBuffer sb = new StringBuffer();
sb.append(startingString);
for (int i = 0; i < 20; i++) {
sb.append(sb.toString());
}
}

  在测试中可发现,使用StringBuffer的方法只用了0.01秒执行完毕,而使用连接的方法则用了0.08秒,选择显而易见了。

  七、多关注GUI(用户界面)。再三强调,GUI对商业客户来说,与程序的功能及效率同等重要,GUI是一个成功程序的最基本部分,而很多IT经理往往都没注意到GUI的重要性。在现实生活中,许多公司可能为了节省开支,没有雇用那些有着设计“用户友好”界面丰富经验的网页设计者,此时Java开发者只能依赖他们自身的HTML基本功及在此领域有限的知识,结果,很多开发出来的程序都是“计算机友好”甚于“用户友好”。很少有开发者同时精通软件开发及GUI设计,如果你在公司“不幸”被分配负责程序界面,就应该遵守下面三条原则:

  1、 不要再发明一次轮子,即不做无用功。现有的程序可能会有类似的界面需求。
  2、 先创建一个原型。这是非常重要一步,用户一般想看到他们将使用的东西,而且可以先利用这个原型征求用户的意见,再慢慢修改成用户想要的样子。
  3、 学会换位思考。换句话来说,就是从用户的角度来审查程序的需求。举例来讲,一个汇总的窗口可以跨页或者不跨页,作为一个软件开发者,可能会倾向于不跨页,因为这样简单一些。但是,从用户的角度来看,可能不希望看到上百行数据都挤在同一页上。

  八、文档需求不放松。每个商业需求都必须记录在案,这可能听上去像童话,似乎在现实生活中很难实现。而我们要做的是,不管开发时间多紧迫,不管最终期限多临近,对每个商业需求都必须记录在案。

   九、单元测试、单元测试、单元测试。关于什么是单元测试的最好方法,在此不便细说,只是强调,单元测试一定要完成,这也是编程中最基本的原则。当然了,如果有人帮你做单元测试自然是最好,如果没有,就自己来做吧,当创建一个单元测试计划时,请遵守以下三条最基本的原则:

  1、 先于编写类代码之前编写单元测试。
  2、 记录单元测试中的代码注释。
  3、 测试所有执行关键功能的公有方法,这里不是指set和get方法,除非它们是以自己独特方式执行set和get方法。

  十、质量,而不是数量。有些时候因为产品问题、期限紧迫、或一些预料之外的事情,导致常常不能按时下班,但一般而言,公司不会因为雇员经常加班而对之表扬和奖励,公司只看重高质量的工作。如果遵守了前九条原则,你会发现自己写出的代码bug少且可维护性高,无形中质量提高了一大步。

25

今天解决了困扰很久的JAVA数据库乱码问题

现在把它分享出来吧,

第一步:进入安装Tomcat文件夹 >> conf 目录>> 找到 server.xml

修改server.xml配置文件,在Server标签中加入URIEncoding="UTF-8"

<Server URIEncoding="UTF-8" port="8005" shutdown="SHUTDOWN">

第二步:建立一个.filter的类,实现过滤字符

Fil .java

package sun.filter;
import java.io.IOException;
import javax.servlet.*;

public class Fil implements Filter {

 public void destroy() 
         {
            }

 public void doFilter(ServletRequest arg0, ServletResponse arg1,
   FilterChain arg2) throws IOException, ServletException
            {
                  // 将Request 、Response都转化为utf-8编码
                   arg0.setCharacterEncoding("UTF-8");  
                  arg1.setCharacterEncoding("UTF-8");                
                  arg2.doFilter(arg0, arg1);
            }

 public void init(FilterConfig arg0) throws ServletException
          {
              }        
}

第三步: 在网站配置文件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">
 
  <filter>
  <filter-name>encoding</filter-name>
  <filter-class>sun.filter.Fil</filter-class>
  </filter>
 
  <servlet>
    <servlet-name>userpass</servlet-name>
    <servlet-class>sun.sta.userpass</servlet-class>
  </servlet>

<filter-mapping>
     <filter-name>encoding</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
   
  <servlet-mapping>
    <servlet-name>userpass</servlet-name>
    <url-pattern>/userpass</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

23

checkbox在JSP实现批量删除的过程中的取值问题

在一些文章发布系统中,常常用到批量删除。

这时就用到SQL语句:delete from 表名 where 字段名 in (参数1,参数2,参数3......)

用checkbox控件传值是一个很好的选择,但是在取值过程中与ASP有些不同,ASP直接使用

request.Form(checkbox的名字)就能实现:   参数1,参数2,参数3......    格式的排列

在JSP中还需要一定处理,以下为实现的一种方式,代码如下:

客户端:

<BODY>
<CENTER><H4>checkBox批量删除</H4></CENTER>
<HR>
   <FORM METHOD="POST" ACTION="test.jsp">
   <INPUT TYPE="checkbox" NAME="name" value="1"> 条目1<BR>
   <INPUT TYPE="checkbox" NAME="name" value="2"> 条目2<BR>
   <INPUT TYPE="checkbox" NAME="name" value="3"> 条目3<BR>
   <INPUT TYPE="checkbox" NAME="name" value="4"> 条目4<BR>
   <INPUT TYPE="checkbox" NAME="name" value="5"> 条目5<BR>
   <INPUT TYPE="checkbox" NAME="name" value="6"> 条目6<BR>
   <INPUT TYPE="checkbox" NAME="name" value="7"> 条目7<BR>
   <INPUT TYPE="submit" value="提交">
   </FORM>
</BODY>

服务器端:

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%
String[] name=request.getParameterValues("name");//取值,字符串数组存值
String str=name[0].toString();
for(int i=1;i<name.length;i++){
str=str+","+name[i];   //转化为字符串,添加逗号
}
out.print("str=");
out.print(str);
%>