关于连接bean中可能发生多线程的问题请教,欢迎大家一起讨论

04-08-25 摩卡碳烧

收费信息综合查询,即在市局可以查到各分局的收费信息。

单位名称    数据库     DataSource      所在应用服务器
某市局      db_0       jdbc/test       192.168.1.0
A分局       db_1       jdbc/test1      192.168.1.1
B分局       db_2       jdbc/test2      192.168.1.2 
C分局       db_3       jdbc/test3      192.168.1.3
D分局       db_4       jdbc/test4      192.168.1.4
E分局       db_5       jdbc/test5      192.168.1.5

/////////////////////////////////////////////////////////////////////////
192.168.1.0上的resin.conf内容如下:

<resource-ref>
  <res-ref-name>jdbc/test</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.0:5000/db_0"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test1</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.1:5000/db_1"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test2</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.2:5000/db_2"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test3</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.3:5000/db_3"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test4</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.4:5000/db_4"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test5</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.5:5000/db_5"/>
  ....................
</resource-ref>


////////////////////////////////////////////////////////////////////////

package com.kysoft.jndi;
/**
 * Title:        DbFactory
 * Description:  数据库连接的实现类
 * Copyright:    Copyright (c) 2004
 */

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;


public class DbFactory {
    
    private static DataSource ds = null; //****
    private static Object initDSLock = new Object();
    
    public DbFactory() 
    {}

    /**
     * 在后台管理中需要获得数据库了连接
     * @return Connection
     */
    private static DataSource lookupDS(String dsName) 
    {                 
        if (ds == null) 
        {
            synchronized (initDSLock)
            {
                if (ds == null) 
                {
                    try 
                    {
                      Context ctx =(Context)new InitialContext().lookup("java:comp/env");
                      ds = (DataSource)ctx.lookup(dsName);
                    } 
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
        return ds;
    }
    

    //protected
    public static Connection getConnection(String dsName) 
    {
        Connection conn = null;
        try {
                conn = lookupDS(dsName).getConnection(); 
        }       
        catch (Exception e) {
            e.printStackTrace();
        }
        return conn;    
     }


    public static void closeDB(
        ResultSet rs,
        PreparedStatement pstmt,
        Statement stmt,
        Connection con) {
        try {
            if (rs != null)
                rs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (pstmt != null)
                pstmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (stmt != null)
                stmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (con != null)
                con.close();                
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    public static void cleanDS()
    {
           if(ds!=null){
              ds=null;
           }
    }
     
}


//////////////////////////////////////////////////////////////////////////////
query.jsp
<%

  com.kysoft.jndi.DbFactory DbFactory=null; 
  Connection conn=null;
  Statement stmt=null;
  ResultSet rs=null;
  String    dbparm=null;
//查询每一个分局的收费情况


//模拟各个分局的DataSource
String dw_array[]=new String[]{"jdbc/test1","jdbc/test2","jdbc/test3","jdbc/test4","jdbc/test5"};

//循环每一个分局
for(int i=0;i<dw_array.length;i++)
{
    dbparm=dw_array[i]; //取得DS,例如:jdbc/test1
    DbFactory.cleanDS(); //清除DS
    conn=DbFactory.getConnection(dbparm);//得到当前分局的数据库连接
    /*
      因为jsp是多线程,连接bean中private static DataSource ds,所以,很有可能当第二个统计线程发生时,他的ds被其它线程篡改,以致连接到错误的数据库中。
    */
    stmt=conn.createStatement();
    rs=stmt.executeQuery("select sum(money) from table");
    out.println("第"+i+"分局汇总金额="+rs.getInt(1));
    .........
    .........

    DbFactory.closeDB(rs,null,stmt,conn);//关闭数据库连接
}

%>


请问,bean中应该怎么处理,才会避免这种情况发生?而且使效率还最优。
<p>

Azure_2003
2004-08-26 09:52
最好使用ThreadLocal类,为每个线程建立一个jdbc连接副本,这样线程就比较安全了,不共享有时是比较安全的,可以考虑把你的下面的代码换成这样:

 //protected    
public static Connection getConnection(String dsName) {
		Connection conn = null;
		try {
			conn = lookupDS(dsName).getConnection();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
<p>[code]

换成:

<p>[code]
private static ThreadLocal threadLocal=new ThreadLocal();
	
public static Object getConnection(String dsName) {
		Connection conn = null;
		try {
			conn = lookupDS(dsName).getConnection();
			threadLocal.set(conn);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return threadLocal.get();
	}

摩卡碳烧
2004-08-26 10:39
完整的部门树结构应该是这样的

单位名称 数据库 DataSource 所在应用服务器

某市局 db_0 jdbc/test 192.168.1.0

A分局 db_1 jdbc/test1 192.168.1.1

A1所 同上 同上 同上

A2所 同上 同上 同上

....

An所 同上 同上 同上

B分局 db_2 jdbc/test2 192.168.1.2

B1所 同上 同上 同上

B2所 同上 同上 同上

....

Bn所 同上 同上 同上

C分局 db_3 jdbc/test3 192.168.1.3

D分局 db_4 jdbc/test4 192.168.1.4

E分局 db_5 jdbc/test5 192.168.1.5

所以,如果当查询的单位恰好是几个相同的DS相邻的话,我可以在循环所有被查单位的时候,

如果当前DS和上一个单位的DS没变化,我可以不用DbFactory.cleanDS(); 继续使用

同一DS资源(static),直到DS变化时,才cleanDS。

有朋友这样建议我:

你这个DataSource声明为static已经没有任何意义.应该声明一个static HashMap,然后for循环生成ds,

hm.put("jdbc/test1",ds);

然后取的时候根本"jdbc/test1"得到ds,如果是空的话重新生成再put进去.

虽然ds不是static的,但因为hm是static的,只要原来put的时候不空,可以保证多个用户从hm得到的ds是同一ds.象你这样,虽然ds是static的,但实际每次都重新查找重新赋值,仅仅句柄是static的.原来查找的ds根本没有被缓存下来,没有任何意义.

Azure_2003
2004-08-26 12:53
你的朋友说的是对的,你需要的东西就是数据库连接池,也许你的系统结构还需要优化一下

jProgramer
2004-09-09 12:35
我看见你的源代码里:

"private static DataSource ds = null; //****"

我发现一个问题,我有一个Time类,原文件如下:

*****************************************************************

package dgbeans;

import java.util.*;

public class SystemTimeOperate{

private static Calendar systemTime = Calendar.getInstance();

private static String strMonth = "";

private static String strCharacter = "abcdefghijklmnopqrstuvwxyz";

//private GregorianCalendar g;

/**

* <br>入口参数: 无

* <br>出口参数: 无

* <br>功能介绍: 构造函数

*/

public SystemTimeOperate(){

//g = new GregorianCalendar();

systemTime = Calendar.getInstance();

}

/**

* <br>入口参数: 无

* <br>出口参数: int

* <br>功能介绍: 获得当天所在四位数字年份

*/

private int getYear(){

systemTime = Calendar.getInstance();

return systemTime.get(systemTime.YEAR);

}

/**

* <br>入口参数: 无

* <br>出口参数: int

* <br>功能介绍: 获得当天所在月份

*/

private int getMonth(){

systemTime = Calendar.getInstance();

int intMonth = 0;

switch(systemTime.get(systemTime.MONTH)){

case 0:

intMonth = 1; break;

case 1:

intMonth = 2; break;

case 2:

intMonth = 3; break;

case 3:

intMonth = 4; break;

case 4:

intMonth = 5; break;

case 5:

intMonth = 6; break;

case 6:

intMonth = 7; break;

case 7:

intMonth = 8; break;

case 8:

intMonth = 9; break;

case 9:

intMonth = 10; break;

case 10:

intMonth = 11; break;

case 11:

intMonth = 12; break;

}

return intMonth;

}

/**

* <br>入口参数: 无

* <br>出口参数: 无

* <br>功能介绍: 设置月份字符

*/

private void setStringMonth(){

systemTime = Calendar.getInstance();

switch(systemTime.get(systemTime.MONTH)){

case 0:

strMonth = "A"; break;

case 1:

strMonth = "B"; break;

case 2:

strMonth = "C"; break;

case 3:

strMonth = "D"; break;

case 4:

strMonth = "E"; break;

case 5:

strMonth = "F"; break;

case 6:

strMonth = "G"; break;

case 7:

strMonth = "H"; break;

case 8:

strMonth = "I"; break;

case 9:

strMonth = "J"; break;

case 10:

strMonth = "K"; break;

case 11:

strMonth = "L"; break;

}

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 获得月份字符

*/

public String getCharMonth(){

setStringMonth();

return strMonth;

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 获得年份字符

*/

public String getCharYear(){

int i = getYear();

String s = String.valueOf(strCharacter.charAt(i-2001));

return s;

}

/**

* <br>入口参数: 无

* <br>出口参数: int

* <br>功能介绍: 获得当天日期

*/

public int getDate(){

systemTime = Calendar.getInstance();

return systemTime.get(systemTime.DATE);

}

/**

* <br>入口参数: 无

* <br>出口参数: int

* <br>功能介绍: 获得当天小时

*/

private int getHour(){

systemTime = Calendar.getInstance();

return systemTime.get(systemTime.HOUR_OF_DAY);

}

/**

* <br>入口参数: 无

* <br>出口参数: int

* <br>功能介绍: 获得当前分钟数

*/

private int getMinute(){

systemTime = Calendar.getInstance();

return systemTime.get(systemTime.MINUTE);

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 获得当天星期

*/

public String getDay(){

systemTime = Calendar.getInstance();

String strDay = "";

switch(systemTime.get(systemTime.DAY_OF_WEEK)){

case 1:

strDay = "星期日"; break;

case 2:

strDay = "星期一"; break;

case 3:

strDay = "星期二"; break;

case 4:

strDay = "星期三"; break;

case 5:

strDay = "星期四"; break;

case 6:

strDay = "星期五"; break;

case 7:

strDay = "星期六"; break;

}

return strDay;

}

/**

* <br>入口参数: 无

* <br>出口参数: int

* <br>功能介绍: 获得当天的时间是一年时间的第多少天

*/

private int getDAY_OF_YEAR(){

systemTime = Calendar.getInstance();

return systemTime.get(systemTime.DAY_OF_YEAR);

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 显示时间:YYYY年MM月DD日星期N

*/

public String getYMDD(){

return(getYear() + "年" + getMonth() + "月" + getDate() + "日" + getDay());

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 显示时间:YYYY年MM月DD日

*/

public String getYMD(){

return(getYear() + "年" + getMonth() + "月" + getDate() + "日");

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 显示时间:YYYY年MM月DD日小时

*/

public String getYMDH(){

return(getYear() + "年" + getMonth() + "月" + getDate() + "日" + getHour() +"时");

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 显示时间:YYYY年MM月DD日小时分钟

*/

public String getYMDHM(){

return(getYear() + "年" + getMonth() + "月" + getDate() + "日" + getHour() +"时" + getMinute() + "分");

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 得到当前日期转化为YYYY格式

*/

public String getStrY(){

String strYYYY = Integer.toString(getYear());

return strYYYY;

}//end getStrYMD()

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 得到当前日期转化为YYYYMM格式

*/

public String getStrYM(){

String strYYYY = "";

String strMM = "";

strYYYY = Integer.toString(getYear());

if(getMonth()<10)

strMM = "0" + Integer.toString(getMonth());

else

strMM = Integer.toString(getMonth());

return (strYYYY + strMM);

}//end getStrYMD()

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 得到当前日期转化为YYYYMMDD格式

*/

public String getStrYMD(){

String strYYYY = "";

String strMM = "";

String strDD = "";

strYYYY = Integer.toString(getYear());

if(getMonth()<10)

strMM = "0" + Integer.toString(getMonth());

else

strMM = Integer.toString(getMonth());

if(getDate()<10)

strDD = "0" + Integer.toString(getDate());

else

strDD = Integer.toString(getDate());

return (strYYYY + strMM + strDD);

}//end getStrYMD()

/**

* <br>入口参数: YYYYMMDD格式日期

* <br>出口参数: String

* <br>功能介绍: YYYYMMDD格式转化为YYYY年MM月DD日格式

*/

public String getYMD(String strYYYYMMDD){

String strYear = "";

String strMonth = "";

String strDate = "";

int i;

for(i=0;i<4;i++){

strYear = strYear + strYYYYMMDD.charAt(i);

}

if(strYYYYMMDD.charAt(4)=='0')

strMonth = strMonth + strYYYYMMDD.charAt(5);

else

strMonth = strMonth + strYYYYMMDD.charAt(4) + strYYYYMMDD.charAt(5);

if(strYYYYMMDD.charAt(6)=='0')

strDate = strDate + strYYYYMMDD.charAt(7);

else

strDate = strDate + strYYYYMMDD.charAt(6) + strYYYYMMDD.charAt(7);

return(strYear + "年" + strMonth + "月" + strDate + "日");

}//end getYMD(String strYYYYMMDD)

/**

* <br>入口参数: YYYYMMDDHH格式日期

* <br>出口参数: String

* <br>功能介绍: YYYYMMDDHH格式转化为YYYY年MM月DD日HH时格式

*/

public String getYMDH(String strYYYYMMDDHH){

String strYear = "";

String strMonth = "";

String strDate = "";

String strHour = "";

int i;

for(i=0;i<4;i++){

strYear = strYear + strYYYYMMDDHH.charAt(i);

}

if(strYYYYMMDDHH.charAt(4)=='0')

strMonth = strMonth + strYYYYMMDDHH.charAt(5);

else

strMonth = strMonth + strYYYYMMDDHH.charAt(4) + strYYYYMMDDHH.charAt(5);

if(strYYYYMMDDHH.charAt(6)=='0')

strDate = strDate + strYYYYMMDDHH.charAt(7);

else

strDate = strDate + strYYYYMMDDHH.charAt(6) + strYYYYMMDDHH.charAt(7);

if(strYYYYMMDDHH.charAt(8)=='0')

strHour = strHour + strYYYYMMDDHH.charAt(9);

else

strHour = strHour + strYYYYMMDDHH.charAt(8) + strYYYYMMDDHH.charAt(9);

return(strYear + "年" + strMonth + "月" + strDate + "日" + strHour + "时");

}//end getYMD(String strYYYYMMDD)

/**

* <br>入口参数: YYYYSMMSDD日期

* <br>出口参数: String

* <br>功能介绍: YYYYSMMSDD格式转化为YYYYMMDD格式 S="/"

*/

public String changeYMD(String strYYYYSMMSDD){

String strTempYYYYMMDD = "";

for(int i=0;i<4;i++){

strTempYYYYMMDD = strTempYYYYMMDD + strYYYYSMMSDD.charAt(i);

}

strTempYYYYMMDD = strTempYYYYMMDD + strYYYYSMMSDD.charAt(5) + strYYYYSMMSDD.charAt(6) + strYYYYSMMSDD.charAt(8) + strYYYYSMMSDD.charAt(9);

return strTempYYYYMMDD;

}

/**

* <br>入口参数: YYYY/MM/DD格式日期

* <br>出口参数: boolean

* <br>功能介绍: 判断用户是否按照YYYY/MM/DD格式输入日期

*/

public boolean isYYYYSMMSDD(String strYYYYSMMSDD){

boolean isYYYYSMMSDD = true;

String strTemp = "0123456789";

//System.out.println(strYYYYSMMSDD.length());

if((strYYYYSMMSDD.length()==10)){

for(int i=0;i<10;i++){

if((i==4)||(i==7)){

if(!(strYYYYSMMSDD.charAt(i)=='/'))

isYYYYSMMSDD = false;

}

else{

if(strTemp.indexOf(strYYYYSMMSDD.charAt(i))==-1)

isYYYYSMMSDD = false;

}

}//end for 循环

}

else

isYYYYSMMSDD = false;

return isYYYYSMMSDD;

}//end isYYYYSMMSDD(String strYYYYSMMSDD)

/**

* <br>入口参数: YYYYMMDD格式日期

* <br>出口参数: boolean

* <br>功能介绍: 判断用户是否按照YYYYMMDD格式输入日期

*/

public boolean isYYYYMMDD(String strYYYYMMDD){

boolean isYYYYMMDD = true;

boolean is8Num = false;

String strTemp = "0123456789";

int Year = 2002;

int Month = 1;

int DateID = 1;

if(strYYYYMMDD.length()==8){

for(int i=0;i<8;i++){

if(strTemp.indexOf(strYYYYMMDD.charAt(i))==-1)

isYYYYMMDD = false;

else

is8Num = true;

}//end for 循环

if(is8Num){

//8位数字第一个不能是0

if(Integer.parseInt(strYYYYMMDD.substring(0))==0){

isYYYYMMDD = false;

}

else{

Year = Integer.parseInt(strYYYYMMDD.substring(0,4));

if((Year<2000)||(Year>2030)){

isYYYYMMDD = false;

}

if(Integer.parseInt(strYYYYMMDD.substring(5))==0)

Month = Integer.parseInt(strYYYYMMDD.substring(4,5));

else

Month = Integer.parseInt(strYYYYMMDD.substring(4,6));

if((Month<1)||(Month>12)){

isYYYYMMDD = false;

}

if(Integer.parseInt(strYYYYMMDD.substring(7))==0)

DateID = Integer.parseInt(strYYYYMMDD.substring(6,7));

else

DateID = Integer.parseInt(strYYYYMMDD.substring(6,8));

if((DateID<1)||(DateID>31)){

isYYYYMMDD = false;

}

if(!checkMonthDate(Year,Month,DateID))

isYYYYMMDD = false;

}//end 8位数字的操作

}//end if(is8Num)

}//end 是8个字符串的操作

else

isYYYYMMDD = false;

return isYYYYMMDD;

}//end isYYYYSMMSDD(String strYYYYSMMSDD)

//判断月份和日子的匹配

private boolean checkMonthDate(int Year,int Month,int DateID){

boolean b = true;

if((Month==1)||(Month==3)||(Month==5)||(Month==7)||(Month==8)||(Month==10)||(Month==12)){

if((DateID>31)||(DateID<1)){

b = false;

}

}

else if (Month==2){

if(((Year-2000)%4)==0){

if((DateID>29)||(DateID<1))

b = false;

}

else{

if((DateID>28)||(DateID<1))

b = false;

}

}

else if((Month==4)||(Month==6)||(Month==9)||(Month==11)){

if((DateID>30)||(DateID<1)){

b = false;

}

}

else

b = false;

return b;

}

/**

* <br>入口参数: 开始日期 中止日期 时间数

* <br>出口参数: boolean

* <br>功能介绍: 判断得到两个时间之间的数值是否<=dayNum,如果true则可以显示。

*/

public boolean isDifferent(String beginTime ,String endTime,int dayNum){

boolean b = true;

if((!isYYYYMMDD(beginTime))||(!isYYYYMMDD(endTime)))

b = false;

else{

int beginDaysNum = getNewTimeFrom20000101(beginTime);

int endDaysNum = getNewTimeFrom20000101(endTime);

int i = endDaysNum - beginDaysNum;

showInfo(" " + i);

//如果相差日期大于比较的日期,则不在选取范围之内,否则在选取范围之内,可以显示。

if((i>dayNum)||(i<0))

b = false;

}

return b;

}//end isDifferent()

private int getNewTimeFrom20000101(String strYYYYMMDD){

int YYYY = Integer.parseInt(strYYYYMMDD.substring(0,4));

int MM = 0;

int DD = 0;

if(strYYYYMMDD.charAt(4)=='0')

MM = Integer.parseInt(String.valueOf(strYYYYMMDD.charAt(5)));

else

MM = Integer.parseInt(strYYYYMMDD.substring(4,6));

if(strYYYYMMDD.charAt(6)=='0')

DD = Integer.parseInt(String.valueOf(strYYYYMMDD.charAt(7)));

else

DD = Integer.parseInt(strYYYYMMDD.substring(6,8));

GregorianCalendar gg = new GregorianCalendar(YYYY,MM,DD);

int YYYYNum = gg.get(gg.YEAR)-2000;

int i = (int)(YYYYNum/4);

int Days = 365*YYYYNum + i + gg.get(gg.DAY_OF_YEAR);

return Days;

}

public void showInfo(String s){

System.out.println("info :" + s);

}

/**

* <br>入口参数: 开始日期tim 间隔天数num

* <br>出口参数: tim前num天的日期

* <br>功能介绍: 计算日期tim前num日的日期

*/

public String beforedate(String tim,int num){

Date tim1=new Date(Integer.parseInt(tim.substring(0,4))-1900,Integer.parseInt(tim.substring(4,6))-1,Integer.parseInt(tim.substring(6)));

long tin=tim1.getTime();

long nun=num;

tin-=nun*86400*1000;

Date tim3=new Date(tin);

String str="";

num=tim3.getYear();

str+=(num+1900);

num=tim3.getMonth();

if(num<9){

str+=0;

str+=(num+1);

}

else{

str+=(num+1);

}

num=tim3.getDate();

if(num<10){

str+=0;

str+=num;

}

else{

str+=num;

}

return str;

}

/**

* <br>入口参数: 开始日期tim 间隔天数num

* <br>出口参数: tim后num天的日期

* <br>功能介绍: 计算日期tim后num日的日期

*/

public String afterdate(String tim,int num){

Date tim1=new Date(Integer.parseInt(tim.substring(0,4))-1900,Integer.parseInt(tim.substring(4,6))-1,Integer.parseInt(tim.substring(6)));

long tin=tim1.getTime();

long nun=num;

tin+=nun*86400*1000;

Date tim3=new Date(tin);

String str="";

num=tim3.getYear();

str+=(num+1900);

num=tim3.getMonth();

if(num<9){

str+=0;

str+=(num+1);

}

else{

str+=(num+1);

}

num=tim3.getDate();

if(num<10){

str+=0;

str+=num;

}

else{

str+=num;

}

return str;

}

/**

* <br>入口参数: 开始日期tim1 结束日期tim2

* <br>出口参数: tim1和tim2之间相隔天数

* <br>功能介绍: 计算日期tim1和tim2之间相隔天数

*/

public String distance(String tim1,String tim2){

Date tim3=new Date(Integer.parseInt(tim1.substring(0,4))-1900,Integer.parseInt(tim1.substring(4,6))-1,Integer.parseInt(tim1.substring(6)));

long tin1=tim3.getTime();

Date tim4=new Date(Integer.parseInt(tim2.substring(0,4))-1900,Integer.parseInt(tim2.substring(4,6))-1,Integer.parseInt(tim2.substring(6)));

long tin2=tim4.getTime();

long tin=0;

if(tin1>tin2)

tin=tin1-tin2;

else

tin=tin2-tin1;

tin/=(86400*1000);

String str="";

str+=tin;

return str;

}

/**

* <br>入口参数: 无

* <br>出口参数: String

* <br>功能介绍: 得到当前时间(小时分钟)转化为hh:mm格式

*/

public String getHM(){

String strHM = "" + getHour() + ":" + getMinute();

return strHM;

}//end getHM()

/*

public static void main(String args[]){

SystemTimeOperate n = new SystemTimeOperate();

//n.showInfo(""+n.getNewTimeFrom20000101("20000201"));

//n.getNewTimeFrom20000101("20000201");

n.showInfo(""+n.afterdate("20021112",365*3));

}

*/

} /* SystemTimeOperate */

*****************************************************************

index.jsp文件里的相关代码:<jsp:useBean id="time" scope="page" class="time.SystemTimeOperate"/>

<%

String timenow=time.getStrYMD();

String txrq_year=timenow.substring(0,4);

String month=timenow.substring(4,6);

String date=timenow.substring(6,8);

String week=convertString(time.getDay());

%>

[htmlcode]

今天是<%=month%>月<%=date%>日 星期<%=week%> 欢迎进入办公管理系统 祝您工作顺利!

[code/end]

关键的疑问:“private static Calendar systemTime = Calendar.getInstance();”也是一个静态的属性,我使用的服务器是Tomcat5.0,在调试过程中,发现先启动Tomcat,后改变了服务器的系统时间,index.jsp里取得的时间还是原来未改变服务器的系统时间之前的时间,无论刷新页面和重新打开index.jsp结果都一样,重启Tomcat后,index.jsp显示的时间才是修改后的时间,后来我将:“private static Calendar systemTime = Calendar.getInstance();”改为:“private Calendar systemTime = Calendar.getInstance();”后,只要修改系统时间后,刷新页面后时间就会和系统修改后的时间同步。我想是不是Tomcat启动后,第一次运行index.jsp后,将“private static Calendar systemTime ”保存在服务器内存中,对于后续的请求使用的全是一个private static Calendar systemTime 对象?你的DataSource对象也是static 的,会不会也有可能发生这种情况?就是说,两个或两个以上的用户在访问你的网页时,DataSource的状态是怎样的??

是否会所有的用户都在使用同一个DataSource???

猜你喜欢