查看mysql版本的四种方法 - 风生水起 - 博客园

mikel阅读(1169)

来源: 查看mysql版本的四种方法 – 风生水起 – 博客园

1:在终端下:mySQL -V。 以下是代码片段:

  [shengting@login ~]$ mySQL -V
mysql Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i686)

2:在mysql中:mysql> status;
以下是代码片段:
mysql> status;
————–
mysql Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i686)
Connection id:          416
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ”
Using delimiter:        ;
Server version:         3.23.56-log
Protocol version:       10
Connection:             Localhost via UNIX socket
Client characterset:    latin1
Server characterset:    latin1
UNIX socket:            /tmp/mysql_3311.sock
Uptime:                 62 days 21 hours 21 min 57 sec
Threads: 1 Questions: 584402560 Slow queries: 424 Opens: 59664208 Flush tables: 1 Open tables: 64 Queries per second avg: 107.551

3:在help里面查找
以下是代码片段:
[shengting@login ~]$ mysql –help | grep Distrib
mysql Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i686)

4:使用mysql的函数
以下是代码片段:
mysql> select version();
+————-+
| version()   |
+————-+
| 3.23.56-log |
+————-+
1 row in set (0.00 sec)

Hibernate中报错:'hibernate.dialect' must be set when no Connection avalable

mikel阅读(1397)

Hibernate中报错:Caused by: org.hibernate.HibernateException: ‘hibernate.dialect’ must be set when no Connection available

解决办法:
在applicationContent.xml中的hibernate配置中加入mySQL5的方言属性:

<bean id=“sessionFactory”

class=“org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>

<property name=“dataSource” ref=“dataSource” />

<property name=“packagesToScan”>

<list>

<value>com.huayadai.appkeeper.orm</value>

</list>

</property>

<property name=“hibernateProperties”>

<value>hibernate.dialect=org.hibernate.dialect.MySQL5Dialect</value>

</property>

</bean>

Eclipse中查看jar包中的源码 - - 博客频道 - CSDN.NET

mikel阅读(1438)

来源: Eclipse中查看jar包中的源码 – – 博客频道 – CSDN.NET

Java Decompiler Plugin For Eclipse IDE

1. 下载JAD ,
1.5.8版本的jad在 http://www.softpedia.com/progDownload/JAD-Download-85911.html 

将展开后的jad.exe放到某个目录,例如 c:/jad/jad.exe

2. 下载JADClipse插件

http://sourceforge.net/projects/jadclipse/files/ 
将展开后的net.sf.jadclipse_3.3.0.jar放入Eclipse的plugins子目录下

3. 启动Eclipse
注意:eclipse需要重新启动

4. 配置Jadclipse, 在 Windows – Preferences – Java – JadClipse下
配置Jad的路径为 C:/jad/jad.exe;

只需编辑这一个值就ok了

 

如下图所示

 

5:eclipse重新启动,即可。

 

6:

In Eclipse, try F3 into any class which does not has the source, Jad will decompile it automatically.

see examples :

Java代码  收藏代码
  1. *jadclipse*/// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
  2. // Jad home page: http://www.kpdus.com/jad.html
  3. // Decompiler options: packimports(3) radix(10) lradix(10) 
  4. // Source File Name:   JSObject.java
  5. package netscape.JavaScript;
  6. import java.applet.Applet;
  7. import sun.plugin.JavaScript.JSContext;
  8. // Referenced classes of package netscape.JavaScript:
  9. //            JSException
  10. public abstract class JSObject
  11. {

 

 

运行过程中可能出现的错误:

1:

 

Java代码  收藏代码
  1. /*jadclipse*/
  2. /*
  3. DECOMPILATION REPORT
  4. Decompiled from: C:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar
  5. Total time: 16 ms
  6. Jad reported messages/errors:
  7. Exit status: 0
  8. Caught exceptions:
  9. java.io.IOException: Cannot run program “jad” (in directory “C:\Documents and Settings\Administrator\.net.sf.jadclipse\1262594305781”): CreateProcess error=2, ϵͳÕҲ»µ½ָ¶
  10. at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
  11. at java.lang.Runtime.exec(Runtime.java:593)
  12. at net.sf.jadclipse.JadDecompiler.decompile(JadDecompiler.java:160)
  13. Decompiled from: /opt/ATG/ATG10.0.2/DAS/lib/servlet.jar
  14. Total time: 26 ms
  15. Jad reported messages/errors:
  16. Exit status: 0
  17. Caught exceptions:
  18. java.io.IOException: Cannot run program “jad” (in directory “/home/citrisys/.net.sf.jadclipse/1311068558030″): java.io.IOException: error=2, No such file or directory
  19. at java.lang.ProcessBuilder.start(ProcessBuilder.java:475)

错误原因:

Make sure your “jad.exe ” in existed in that folder.

配置Jadclipse, 在 Windows – Preferences – Java – JadClipse下
配置Jad的正确路径。

其他:

Juno Eclipse版本需要

配置文件关联关系,在Preference中file associations中配置*.class & *.class without source 的default editors为jad,到此就可以使用jad的反编译功能了。

 配置所需的jar包和程序http://download.csdn.net/detail/zljjava/4284865

proxool配置过程中出现问题解决 - 阿里巴巴专栏

mikel阅读(1181)

来源: proxool配置过程中出现问题解决 – 阿里巴巴专栏

 

在spring里配置proxool0.9.1时,
<bean id="proxoolDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name="alias">
<value>${proxool.alias}</value>
</property>
<property name="driver">
<value>${proxool.driver}</value>
</property>
<property name="driverUrl">
<value>${proxool.url}</value>
</property>
<property name="user">
<value>${proxool.username}</value>
</property>
<property name="password">
<value>${proxool.password}</value>
</property>
<property name="minimumConnectionCount">
<value>${proxool.minimumConnectionCount}</value>
</property>
<property name="maximumConnectionCount">
<value>${proxool.maximumConnectionCount}</value>
</property>
<property name="prototypeCount">
<value>${proxool.prototypeCount}</value>
</property>
<property name="simultaneousBuildThrottle">
<value>${proxool.simultaneousBuildThrottle}</value>
</property>
<property name="maximumActiveTime">
<value>${proxool.maximumActiveTime}</value>
</property>
<property name="trace">
<value>${proxool.trace}</value>
</property>
<property name="verbose">
<value>${proxool.verbose}</value>
</property>
<property name="houseKeepingTestSql">
<value>${proxool.houseKeepingTestSql}</value>
</property>
<property name="statistics">
<value>${proxool.statistics}</value>
</property>
<property name="statisticsLogLevel">
<value>${proxool.statisticsLogLevel}</value>
</property>
<property name="testBeforeUse">
<value>${proxool.testAfterUse}</value>
</property>
<property name="testAfterUse">
<value>${proxool.testAfterUse}</value>
</property>
<!--
<property name="maximumConnectionLifeTime">
<value>600</value>
</property>
<property name="houseKeepingSleepTime">
<value>${proxool.houseKeepingSleepTime}</value>
</property>
<property name="maximumConnectionLifeTime">
<value>${proxool.maximumConnectionLifeTime}</value>
</property>
-->
</bean>
最后三个属性是不支持的,spring会报错:
org.springframework.beans.NotWritablePropertyException: Invalid property 'houseKeepingSleepTime' of bean class [org.logicalcobwebs.proxool.ProxoolDataSource]: Bean property 'houseKeepingSleepTime' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:751)

查看proxool源码得知:
org.logicalcobwebs.proxool.ProxoolDataSource.java

public class ProxoolDataSource implements DataSource ObjectFactory {
private static final Log LOG = LogFactory.getLog(ProxoolDataSource.class);

private int loginTimeout;
private PrintWriter logWriter;

private String alias;
private String driver;
private String fatalSqlExceptionWrapperClass;
private long houseKeepingSleepTime;
private String houseKeepingTestSql;
private long maximumActiveTime;
private int maximumConnectionCount;
private long maximumConnectionLifetime;;
private int minimumConnectionCount;
private long overloadWithoutRefusalLifetime;
................


/**
* @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime
*/
public void setHouseKeepingSleepTime(int houseKeepingSleepTime) {
this.houseKeepingSleepTime = houseKeepingSleepTime;
}

这两个地方不一至,一个是long,一个是int,造成了以上的问题
修改源码发现在jdk1.6下无法编译,换成jdk1.5编译通过
需要导入包:apache 工具包等proxool官方有说明
jakarta.apache.org/commons/logging/ – commons-logging-1.0.4.jar
avalon.apache.org/framework – avalon-framework-4.1.2.jar

原作者在写时可能没有考虑到spring的注入机制,只考虑到一般的调用,spring的注入是规则是方法参数的类型必须与变量声明的类型一至,所有在spring中无法注入。现在改了以下方法参数类型:

setHouseKeepingSleepTime(int houseKeepingSleepTime) 改为 setHouseKeepingSleepTime(long houseKeepingSleepTime)
setMaximumConnectionLifetime(int maximumConnectionLifetime) 改为 setMaximumConnectionLifetime(long maximumConnectionLifetime)
setRecentlyStartedThreshold(int recentlyStartedThreshold) 改为 setRecentlyStartedThreshold(long recentlyStartedThreshold)
setOverloadWithoutRefusalLifetime(int overloadWithoutRefusalLifetime) 改为 setOverloadWithoutRefusalLifetime(long overloadWithoutRefusalLifetime)


private void populatePropertiesFromReference(Reference reference) {
RefAddr property = reference.get(ProxoolConstants.ALIAS_PROPERTY);
if (property != null) {
setAlias(property.getContent().toString());
}
property = reference.get(ProxoolConstants.DRIVER_CLASS_PROPERTY);
if (property != null) {
setDriver(property.getContent().toString());
}
property = reference.get(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY);
if (property != null) {
setFatalSqlExceptionWrapperClass(property.getContent().toString());
}
property = reference.get(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY);
if (property != null) {
//setHouseKeepingSleepTime(Integer.valueOf(property.getContent().toString()).intValue());
setHouseKeepingSleepTime(Long.valueOf(property.getContent().toString()).longValue());
}
property = reference.get(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY);
if (property != null) {
setHouseKeepingTestSql(property.getContent().toString());
}
property = reference.get(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY);
if (property != null) {
setMaximumConnectionCount(Integer.valueOf(property.getContent().toString()).intValue());
}
property = reference.get(ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME_PROPERTY);
if (property != null) {
//setMaximumConnectionLifetime(Integer.valueOf(property.getContent().toString()).intValue());
setMaximumConnectionLifetime(Long.valueOf(property.getContent().toString()).longValue());
}
property = reference.get(ProxoolConstants.MAXIMUM_ACTIVE_TIME_PROPERTY);
if (property != null) {
//setMaximumActiveTime(Long.valueOf(property.getContent().toString()).intValue());
setMaximumActiveTime(Long.valueOf(property.getContent().toString()).longValue());
}
property = reference.get(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY);
if (property != null) {
setMinimumConnectionCount(Integer.valueOf(property.getContent().toString()).intValue());
}
property = reference.get(ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY);
if (property != null) {
//setOverloadWithoutRefusalLifetime(Integer.valueOf(property.getContent().toString()).intValue());
setOverloadWithoutRefusalLifetime(Long.valueOf(property.getContent().toString()).longValue());
}
property = reference.get(ProxoolConstants.PASSWORD_PROPERTY);
if (property != null) {
setPassword(property.getContent().toString());
}
property = reference.get(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY);
if (property != null) {
setPrototypeCount(Integer.valueOf(property.getContent().toString()).intValue());
}
property = reference.get(ProxoolConstants.RECENTLY_STARTED_THRESHOLD_PROPERTY);
if (property != null) {
//setRecentlyStartedThreshold(Integer.valueOf(property.getContent().toString()).intValue());
setRecentlyStartedThreshold(Long.valueOf(property.getContent().toString()).longValue());
}
property = reference.get(ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE_PROPERTY);
if (property != null) {
setSimultaneousBuildThrottle(Integer.valueOf(property.getContent().toString()).intValue());
}
property = reference.get(ProxoolConstants.STATISTICS_PROPERTY);
if (property != null) {
setStatistics(property.getContent().toString());
}
property = reference.get(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY);
if (property != null) {
setStatisticsLogLevel(property.getContent().toString());
}
property = reference.get(ProxoolConstants.TRACE_PROPERTY);
if (property != null) {
setTrace("true".equalsIgnoreCase(property.getContent().toString()));
}
property = reference.get(ProxoolConstants.DRIVER_URL_PROPERTY);
if (property != null) {
setDriverUrl(property.getContent().toString());
}
property = reference.get(ProxoolConstants.USER_PROPERTY);
if (property != null) {
setUser(property.getContent().toString());
}
property = reference.get(ProxoolConstants.VERBOSE_PROPERTY);
if (property != null) {
setVerbose("true".equalsIgnoreCase(property.getContent().toString()));
}
property = reference.get(ProxoolConstants.JMX_PROPERTY);
if (property != null) {
setJmx("true".equalsIgnoreCase(property.getContent().toString()));
}
property = reference.get(ProxoolConstants.JMX_AGENT_PROPERTY);
if (property != null) {
setJmxAgentId(property.getContent().toString());
}
property = reference.get(ProxoolConstants.TEST_BEFORE_USE_PROPERTY);
if (property != null) {
setTestBeforeUse("true".equalsIgnoreCase(property.getContent().toString()));
}
property = reference.get(ProxoolConstants.TEST_AFTER_USE_PROPERTY);
if (property != null) {
setTestAfterUse("true".equalsIgnoreCase(property.getContent().toString()));
}
// Pick up any properties that we don't recognise
Enumeration e = reference.getAll();
while (e.hasMoreElements()) {
StringRefAddr stringRefAddr = (StringRefAddr) e.nextElement();
String name = stringRefAddr.getType();
String content = stringRefAddr.getContent().toString();
if (name.indexOf(ProxoolConstants.PROPERTY_PREFIX) != 0) {
delegateProperties.put(name content);
}
}
}

早期这个类型都是int的,可能后来为了可以设置可大于int型10位以上的数字才改为long的,因为如果是毫秒级的话,10位int的最大数是2147483647也就是只能表示596个小时,也就是24天。看了一下源码,好像5个long的变量有改其中一个,另外4个没改,是作者忘记了?还是另有原因?

另外,这里改源码只是方便我这里用spring注入配置,如果是通过手工调用获取连接的,改了设置参数时,要在数字后加一个L或l来表示long.

Spring学习11-Spring使用proxool连接池 管理数据源_苍蝇也是肉呀_新浪博客

mikel阅读(881)

Spring学习11-Spring使用proxool连接池 管理数据源_苍蝇也是肉呀_新浪博客,苍蝇也是肉呀,

来源: Spring学习11-Spring使用proxool连接池 管理数据源_苍蝇也是肉呀_新浪博客

Spring
一、Proxool连接池简介及其配置属性概述
Proxool是一种Java数据库连接池技术。是sourceforge下的一个开源项目,这个项目提供一个健壮、易用的连接池,最为关键的是这个连接池提供监控的功能,方便易用,便于发现连接泄漏的情况。
目前是和DBCP以及C3P0一起,最为常见的三种JDBC连接池技术。
日前,Hibernate官方宣布由于Bug太多不再支持DBCP,而推荐使用 Proxool或C3P0。
要使用Proxool首先要导入Proxool.jar,此jar包
可以在下载的Hibernate包中hibernate-release-4.1.7.Final\lib\optional\proxool\中找到;也可以到官网:http://nchc.dl.sourceforge.net/sourceforge/proxool/proxool-0.9.1-source.zip下载它的源码,下载完后解压,把proxool.jar和proxool-cglib.jar放入你要配置的项目的lib目录下. 。
 
  simultaneous-build-throttle:
是指在任一时刻,可以(同时)建立的最大连接数,也就是说,就是已经请求的、但还没可用的新连接数量。因为连接可以用多线程建立,从决定要建立连接到连接 可用是需要一定时间的,所以我们需要一些方式来避免大量的线程想同时建立连接。(我们本应该找一个更聪明的方式来解决这个问题,总有一天我们会找到的)默 认值是 10
当我使用140个用户,进行压力测试时,发现偶尔,会有多于10个要求同时建立连接的请求,当请求数量超过限定的数值时,会出现连接失败的情况。
因此结论就是,当数据库并发连接可能会比较高的应用,这个值应该适当的设大一点。
如果并发请求很高,可能出现的bug为

Caused by: java.SQL.SQLException: We are already in the process of making 11 connections and the number of simultaneous builds has been throttled to 10

maximum-active-time:

如果一个线程活动时间超过这个数值,线程会被杀死。所以要确保这个数值设置得比最慢的响应时间长。默认是5分钟。守护进程会把连接池中多余的可用线程(未 用的、超过这个时间的)杀死,最终保留的连接数量就是minimum-connection-count规定的数量。守护进程会根据house- keeping-sleep-time参数设置的时间隔定时检查。

maximum-connection-lifetime:
指一个连接最大的存活时间(毫秒为单位),超过这个时间,连接会被杀死。默认值是4小时。

overload-without-refusal-lifetime:
这个参数帮助我们确定连接池的状态,如果在这个时间阀值内(单位为毫秒)拒绝了一个连接,就认为是过载了。默认值是60。

alias:
数据源的别名

driver-url:url连接串,须确定用户名和密码

driver-class:
驱动名

username:用户名(proxool没有使用,但是不能没有)

password:密码(proxool没有使用,但是不能没有)

maximum-new-connections:
没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受

test-before-use:
如果连接池在运行当中,出现网络或者数据库故障而无法连接到数据库,在恢复正常以后,由于连接是在连接池中持久保存的,会出现连接仍然不可用的情况,这时连接池里的连接实际上都是坏连接,怎么让连接池可以自动重连清除这些坏连接呢? 只要配置了test-before-use 参数,即每次取出连接都检查连接是否可用,就可以做到让连接池实现在故障恢复后自动重连接

需要注意一点,对于MySQL数据库还必须在连接参数里加上autoReconnect=true 参数,否则即使打开了test-before-use 参数,仍然不能重连接!

fatal-sql-exception:
它是一个逗号分割的信息片段.当一个SQL异常发生时,他的异常信息将与这个信息片段进行比较.如果在片段中存在,那么这个异常将被认为是个致命错误(Fatal SQL Exception ).这种情况下,数据库连接将要被放弃.无论发生什么,这个异常将会被重掷以提供给消费者.用户最好自己配置一个不同的异常来抛出.

fatal-sql-exception-wrapper-class:
正如上面所说,你最好配置一个不同的异常来重掷.利用这个属性,用户可以包装SQLException,使他变成另外一个异常.这个异常或者继承 SQLException或者继承字RuntimeException.proxool自带了2个实现:’org.logicalcobwebs.proxool.FatalSQLException’ 和’org.logicalcobwebs.proxool.FatalRuntimeException’ .后者更合适.

house-keeping-sleep-time:
proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒)

house keeper 保留线程处于睡眠状态的最长时间,house keeper 的职责就是检查各个连接的状态,并判断是否需要销毁或者创建.

house-keeping-test-sql:
如果发现了空闲的数据库连接.house keeper 将会用这个语句来测试.这个语句最好非常快的被执行.如果没有定义,测试过程将会被忽略。

一般mysql可用select SYSDATE ,Oracle可用 select sysdate from dual 或者 select 1 from dual

injectable-connection-interface: 允许proxool实现被代理的connection对象的方法.

injectable-statement-interface: 允许proxool实现被代理的Statement 对象方法.
injectable-prepared-statement-interface: 允许proxool实现被代理的PreparedStatement 对象方法.
injectable-callable-statement-interface: 允许proxool实现被代理的CallableStatement 对象方法.
jndi-name: 数据源的名称

maximum-active-time: 如果housekeeper 检测到某个线程的活动时间大于这个数值.它将会杀掉这个线程.所以确认一下你的服务器的带宽.然后定一个合适的值.默认是5分钟.
maximum-connection-count:
The maximum number of connections to the database. Default is 15.
最大的数据库连接数.默认是15
minimum-connection-count: 最小的数据库连接数,默认是5

prototype-count:
连接池中可用的连接数量.如果当前的连接池中的连接少于这个数值.新的连接将被建立(假设没有超过最大可用数).例如.我们有3个活动连接2个可用连接,而我们的prototype-count是4,那么数据库连接池将试图建立另外2个连接.这和 minimum-connection-count不同. minimum-connection-count把活动的连接也计算在内.prototype-count 是spare connections 的数量.

statistics: 连接池使用状况统计。 参数“10s,1m,1d”
statistics-log-level: 日志统计跟踪类型。 参数“ERROR”或 “INFO”

trace: 如果为true,那么每个被执行的SQL语句将会在执行期被log记录(Debug LEVEL).你也可以注册一个ConnectionListener (参看ProxoolFacade)得到这些信息.
verbose: 详细信息设置。 参数 bool 值

二、Spring中配置Proxool连接池管理数据源方式与步骤

方式一、
   在Spring的”applicationContext.xml”中的dataSource bean定义——

<bean id=”dataSource”
   class=”org.logicalcobwebs.proxool.ProxoolDataSource”>
   <property name=”driver”>
       <value>com.mysql.jdbc.Driver</value>
   </property>
   <property name=”driverUrl”>
       <value>jdbc:mysql://localhost:3306/dbname?user=yourname&amp;password=yourpass</value>
   </property>
   <property name=”user” value=”yourname” />
   <property name=”password” value=”yourpass” />
   <property name=”alias” value=”Pool_dbname” />
   <property name=”houseKeepingSleepTime” value=”90000″ />
   <property name=”prototypeCount” value=”0″ />
   <property name=”maximumConnectionCount” value=”50″ />
   <property name=”minimumConnectionCount” value=”2″ />
   <property name=”simultaneousBuildThrottle” value=”50″ />
   <property name=”maximumConnectionLifetime” value=”14400000″ />
   <property name=”houseKeepingTestSql” value=”select CURRENT_DATE” />
</bean>

   第一种方式需要把用户名和密码写在连接串里面,ProxoolDataSource类提供的user,password属性似乎没有什么用。无论提供什么,它都会以空用户名、密码去连接数据库。这可能是Proxool RC0.93的一个bug,实在让人恼火,不知道最新的0.9.1有没有fix这个bug。不过配置中的user,password两个属性还必须设置,否则hibernate会报空指针错误。

 方式二:
   步骤一:在Spring的”applicationContext.xml”中的dataSource bean定义——

<bean id=”dataSource”
   class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
   <property name=”driverClassName”>
       <value>org.logicalcobwebs.proxool.ProxoolDriver</value>
   </property>
   <property name=”url”>
       <value>proxool.Pool_dbname</value>
   </property>
</bean>

    步骤二、预先在”web.xml”先配置好Proxool连接池,配置如下:
<!–管理proxool配置文件–>
<servlet>
   <servlet-name>proxoolServletConfigurator</servlet-name>
   <servlet-class>      org.logicalcobwebs.proxool.configuration.ServletConfigurator
   </servlet-class>
   <init-param>
       <param-name>xmlFile</param-name>
       <param-value>WEB-INF/proxool.xml</param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
</servlet>
<!–查看proxool运行情况,也可以不作配置的
<servlet>
<servlet-name>proxooladmin</servlet-name>
<servlet-class>
  org.logicalcobwebs.proxool.admin.servlet.AdminServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>proxooladmin</servlet-name>
<url-pattern>/proxooladmin</url-pattern>
</servlet-mapping>
–>

<servlet>
   <servlet-name>context</servlet-name>
   <servlet-class>
       org.springframework.web.context.ContextLoaderServlet
   </servlet-class>
   <load-on-startup>2</load-on-startup>
</servlet>

注意:  把<load-on-startup>的值设为1,值越小级别就越高,就先被加载初始化。一定要先于applicationContext.xml的加载;第二种方式下Spring的上下文加载如果想使用listener方式(Struts2要求),
则与连接池有关的Bean全得延迟初始化。因为listener比servlet优先初始化,
如果相关Bean不是lazy-init的话,则启动服务器时会出现Bean找不到连接定义的异常:
Problem 
   org.logicalcobwebs.proxool.ProxoolException: Attempt to refer to unregistered pool by its 
   alias ‘db’ 。

listener方式如下:
<listener>
<listener-class>
     org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

步骤三、在/WEB-INF/下添加proxool的配置文件:proxool.xml
proxool的配置文件可以采用xmlFile”proxool.xml”或者propertyFile”proxool.properties”

“proxool.xml”格式如下

<?xml version=”1.0″ encoding=”UTF-8″?>
<proxool-config>
   <proxool>
      <alias>Pool_dbname</alias>
      <driver-url>jdbc:mysql://localhost:3306/dbname</driver-url>
      <driver-class>com.mysql.jdbc.Driver</driver-class>
      <driver-properties>
      <property name=”user” value=”yourname”/>
      <property name=”password” value=”yourpass”/>
      </driver-properties>
      <house-keeping-sleep-time>60000</house-keeping-sleep-time>
      <maximum-connection-count>20</maximum-connection-count>
      <minimum-connection-count>2</minimum-connection-count>
      <prototype-count>0</prototype-count>
      <simultaneous-build-throttle>20</simultaneous-build-throttle>
      <house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
      <statistics>15s,10m,1d</statistics>
      <statistics-log-level>INFO</statistics-log-level>
   </proxool>
   <proxool>
    <!–可以配置多个库–>
   </proxool>
</proxool-config>

“proxool.properties”格式如下:

jdbc-0.proxool.alias=Pool_dbname
jdbc-0.proxool.driver-url=jdbc:mysql://localhost:3306/dbname
jdbc-0.proxool.driver-class=com.mysql.jdbc.Driver
jdbc-0.user=yourname
jdbc-0.password=yourpass
jdbc-0.proxool.house-keeping-sleep-time=60000
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE
jdbc-0.proxool.maximum-connection-count=10
jdbc-0.proxool.minimum-connection-count=3
jdbc-0.proxool.maximum-connection-lifetime=18000000
jdbc-0.proxool.prototype-count=3
jdbc-0.proxool.simultaneous-build-throttle=10
jdbc-0.proxool.recently-started-threshold=60000
jdbc-0.proxool.overload-without-refusal-lifetime=50000
jdbc-0.proxool.maximum-active-time=60000
jdbc-0.proxool.verbose=true
jdbc-0.proxool.trace=true
jdbc-0.proxool.fatal-sql-exception=Fatal error

jdbc-2.proxool.alias=Pool_dbname2
……
<!–可以配置多个库–>
至此,已完成所有配置。
———————————————————–

个人比较倾向于第二种配置方式,
1:可以避免在Spring的”applicationContext.xml”中写一大堆参数,
尤其是避免了driverUrl中带用户名密码(这会显示在proxool包中带的
org.logicalcobwebs.proxool.admin.servlet.AdminServlet输出的页面中)
2:proxool连接池可以在tomcat启动时就初始化好,可以提高第一次访问web时的连接速度。

三、更详细的配置示例
1、更详细的proxool.xml的配置属性说明:
<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!–
Properties for Proxool Configurator testing. Defines the same parameters as
TestHelper.buildCompleteAlternativeProperties()
–>
<something-else-entirely xmlns=”http://sumthin.else.entirely” xmlns:proxool=”The latest version is available at http://proxool.sourceforge.net/xml-namespace”>
   <proxool:proxool>
       <proxool:alias>xml-test-ns</proxool:alias>
       <proxool:driver-url>jdbc:hsqldb:db/test</proxool:driver-url>
       <proxool:driver-class>org.hsqldb.jdbcDriver</proxool:driver-class>
       <proxool:driver-properties>
           <proxool:property name=”user” value=”sa”/>
           <proxool:property name=”password” value=””/>
       </proxool:driver-properties>
       <proxool:house-keeping-sleep-time>40000</proxool:house-keeping-sleep-time>
       <proxool:house-keeping-test-sql>select CURRENT_DATE</proxool:house-keeping-test-sql>
       <proxool:maximum-connection-count>10</proxool:maximum-connection-count>
       <proxool:minimum-connection-count>3</proxool:minimum-connection-count>
       <proxool:maximum-connection-lifetime>18000000</proxool:maximum-connection-lifetime>
      <!– 5 hours –>
       <proxool:simultaneous-build-throttle>5</proxool:simultaneous-build-throttle>
       <proxool:recently-started-threshold>40000</proxool:recently-started-threshold>
       <proxool:overload-without-refusal-lifetime>50000</proxool:overload-without-refusal-lifetime>
       <proxool:maximum-active-time>60000</proxool:maximum-active-time>
       <proxool:verbose>true</proxool:verbose>
       <proxool:trace>true</proxool:trace>
       <proxool:fatal-sql-exception>Fatal error</proxool:fatal-sql-exception>
       <proxool:prototype-count>2</proxool:prototype-count>
   </proxool:proxool>
   <nothing-to-do-with-proxool>
       <proxool:proxool>
           <proxool:alias>xml-test-ns-2</proxool:alias>
           <proxool:driver-url>jdbc:hsqldb:db/test</proxool:driver-url>
           <proxool:driver-class>org.hsqldb.jdbcDriver</proxool:driver-class>
           <proxool:driver-properties>
               <proxool:property name=”user” value=”sa”/>
               <proxool:property name=”password” value=””/>
           </proxool:driver-properties>
           <proxool:house-keeping-sleep-time>40000</proxool:house-keeping-sleep-time>
           <proxool:house-keeping-test-sql>select CURRENT_DATE</proxool:house-keeping-test-sql>
           <proxool:maximum-connection-count>10</proxool:maximum-connection-count>
           <proxool:minimum-connection-count>3</proxool:minimum-connection-count>
           <proxool:maximum-connection-lifetime>18000000</proxool:maximum-connection-lifetime>
    <!– 5 hours –>
           <proxool:simultaneous-build-throttle>5</proxool:simultaneous-build-throttle>
           <proxool:recently-started-threshold>40000</proxool:recently-started-threshold>
           <proxool:overload-without-refusal-lifetime>50000</proxool:overload-without-refusal-lifetime>
           <proxool:maximum-active-time>60000</proxool:maximum-active-time>
           <proxool:verbose>true</proxool:verbose>
           <proxool:trace>true</proxool:trace>
           <proxool:fatal-sql-exception>Fatal error</proxool:fatal-sql-exception>
           <proxool:prototype-count>2</proxool:prototype-count>
       </proxool:proxool>
   </nothing-to-do-with-proxool>
</something-else-entirely>

  属性列表说明:

fatal-sql-exception: 它是一个逗号分割的信息片段.当一个SQL异常发生时,他的异常信息将与这个信息片段进行比较.如果在片段中存在,那么这个异常将被认为是个致命错误(Fatal SQL Exception ).这种情况下,数据库连接将要被放弃.无论发生什么,这个异常将会被重掷以提供给消费者.用户最好自己配置一个不同的异常来抛出.

fatal-sql-exception-wrapper-class:正如上面所说,你最 好配置一个不同的异常来重掷.利用这个属性,用户可以包装SQLException,使他变成另外一个异常.这个异常或者继承SQLException或 者继承字RuntimeException.proxool自带了2个实 现:’org.logicalcobwebs.proxool.FatalSQLException’ 和’org.logicalcobwebs.proxool.FatalRuntimeException’ .后者更合适.

house-keeping-sleep-time: house keeper 保留线程处于睡眠状态的最长时间,house keeper 的职责就是检查各个连接的状态,并判断是否需要销毁或者创建.

house-keeping-test-sql: 
如果发现了空闲的数据库连接.house keeper 将会用这个语句来测试.这个语句最好非常快的被执行.如果没有定义,测试过程将会被忽略。

injectable-connection-interface: 允许proxool实现被代理的connection对象的方法.

injectable-statement-interface:
允许proxool实现被代理的Statement 对象方法.

injectable-prepared-statement-interface: 允许proxool实现被代理的PreparedStatement 对象方法.

injectable-callable-statement-interface: 允许proxool实现被代理的CallableStatement 对象方法.

jmx:

jmx-agent-id: 略

jndi-name:
数据源的名称

maximum-active-time: 如果housekeeper 检测到某个线程的活动时间大于这个数值.它将会杀掉这个线程.所以确认一下你的服务器的带宽.然后定一个合适的值.默认是5分钟.

maximum-connection-count:
最大的数据库连接数.

maximum-connection-lifetime: 一个线程的最大寿命.

minimum-connection-count: 最小的数据库连接数

overload-without-refusal-lifetime:

prototype-count: 连接池中可用的连接数量.如果当前的连接池中的连接少于这个数值.新的连接将被建立(假设没有超过最大可用数).例如.我们有3个活动连接2个可用连接,而我们的prototype-count是4,那么数据库连接池将试图建立另外2个连接.这和 minimum-connection-count不同. minimum-connection-count把活动的连接也计算在内.prototype-count 是spare connections 的数量.

recently-started-threshold: 

simultaneous-build-throttle: 

statistics:  连接池使用状况统计。 参数“10s,1m,1d”

statistics-log-level:
  日志统计跟踪类型。 参数“ERROR”或 “INFO”

test-before-use:

test-after-use:

trace: 如果为true,那么每个被执行的SQL语句将会在执行期被log记录(Debug LEVEL).你也可以注册一个ConnectionListener (参看ProxoolFacade)得到这些信息.
verbose: 详细信息设置。 参数 bool 值  
2.更详细的在web.xml中配置管理proxool的servlet
<?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”>
<servlet>
<servlet-name>ServletConfigurator</servlet-name>
<servlet-class>
   org.logicalcobwebs.proxool.configuration.ServletConfigurator
</servlet-class>
<init-param>
   <param-name>xmlFile</param-name>
   <param-value>WEB-INF/proxool.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet>
<servlet-name>Admin</servlet-name>
<servlet-class>
   org.logicalcobwebs.proxool.admin.servlet.AdminServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Admin</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
<!– 配置受保护域,只有Tomcat管理员才能察看连接池的信息 –>
<security-constraint>
<web-resource-collection>
     <web-resource-name>proxool</web-resource-name>
     <url-pattern>/admin</url-pattern>
</web-resource-collection>
<auth-constraint>
    <role-name>manager</role-name>
    </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>proxool manager Application</realm-name>
</login-config>
<security-role>
   <description>The role that is required to log in to the Manager Application</description>
    <role-name>manager</role-name>
</security-role>
<error-page>
   <error-code>401</error-code>
   <location>/401.jsp</location>
</error-page>
</web-app>

android 用VideoView播放本地视频文件 - 懒虫一个V - 博客频道 - CSDN.NET

mikel阅读(947)

 

来源: android 用VideoView播放本地视频文件 – 懒虫一个V – 博客频道 – CSDN.NET

在VideoView设置uri的时候,加上”Android:resource//你的应用包名”+视频文件在R文件中的ID名称

videoView = (VideoView) this.findViewById(R.id.VideoView01);
MediaController controller = new MediaController(this);
this.videoView.setMediaController(controller);
//下面Android:resource://是固定的,org.dengzh是我的包名,不是.Java文件package名称,R.raw.movie_1是id名称
videoView.setVideoURI(Uri.parse(“Android.resource://org.dengzh/”+R.raw.movie_1));

手动编译打包执行java类(javac,java,jar使用) - IT男 - ITeye技术网站

mikel阅读(1512)

来源: 手动编译打包执行java类(javac,java,jar使用) – IT男 – ITeye技术网站

做一个手动编译打包执行java类例子

首先进入zipCompressorByAnt 下面的操作都是在这个目录下进行的

目录结构如下,src里面存放了我们的java类,lib里是我们要用到的包,我们的目地是首先把java类编译成class文件放在当前class目录下并包含包路径,然后把class文件打成jar放在lib下

首先们要建一个class文件,javac编译的时候不会生成目录除了类中含有的包名目录外,然后用如下的命令就可以生成class文件,并放在我们指定的目录下

Java代码  收藏代码
  1. javac -encoding utf-8 -Djava.ext.dirs=./lib  -d class src/com/yan/compress/*.java

对上面的命令进行说明
-encoding utf-8 指定编码,如果不指定就以平台的编码为准
-Djava.ext.dirs=./lib 指定编译的时候调用的类
-d class 指定要生成到的目录
src/com/yan/compress/*.java 这就是具体要编译的类了,星号表示这个目录下的所有的java文件,如果在这个目录下有多个java文件,那么装分别生成class文件到指定目录

命令执行后就可以看到class目录中就有了我们编译过的类

第二步生成jar文件

Java代码  收藏代码
  1. jar -cf lib/abc.jar class/com/yan/compress/ZipCompressorByAnt.class

对命令进行一个说明
-c 就是要生成jar包
-f后面跟指定的包名lib/abc.jar
class/com/yan/compress/ZipCompressorByAnt.class  类文件

命令执行后就可以看到在lib目录下多了一个abc.jar包

第三步就是执行这个类

Java代码  收藏代码
  1. java -Djava.ext.dirs=./lib    com.yan.compress.ZipCompressorByAnt  20130804

-Djava.ext.dirs=./lib 指定要用到的包

com.yan.compress.ZipCompressorByAnt 带包名的类
2013-08-04 参数,如果需要参数的话就可以带参数

到这里一个手工编译类的例子就完成了,下面就对命令的一些细节进行一些扩展

如果在编译的时候想一下子编译多个类,并且这些类不在一个文件夹里怎么办
假设除了下面的要编译的类个还有在a/*.java b/*.java  c/*.java 一些文件
其实也简单就看命令

Java代码  收藏代码
  1. javac -encoding utf-8 -Djava.ext.dirs=./lib  -d class src/com/yan/compress/*.java a/*.java b/*.java c/*.java

ASP.NET MVC Controller的激活 - 眼神与背影 - 博客园

mikel阅读(1598)

来源: ASP.NET MVC Controller的激活 – 眼神与背影 – 博客园

最近抽空看了一下ASP.NET MVC的部分源码,顺带写篇文章做个笔记以便日后查看。

在UrlRoutingModule模块中,将请求处理程序映射到了MvcHandler中,因此,说起Controller的激活,首先要从 MvcHandler入手,MvcHandler实现了三个接口:IHttpAsyncHandler, IHttpHandler, IRequiresSessionState。 其处理逻辑主要实现在同步和异步的ProcessRequest方法中,总的来说,该方法在执行的时候,大致经历以下几个步骤:

  1. 预处理(在响应头中添加版本信息并去除未赋值的可选路由参数)
  2. 通过ControllerBuilder获取ControlerFactory,并使用Controller工厂创建Controller
  3. 根据是否是异步处理,调用Controller中相应的方法(ExecuteCore或BeginExecute)
  4. 释放Controller

其中第一步在ProcessRequestInit方法中进行处理,本文主要是分析第两步中的controller是如何创建出来的。

Controller的创建是通过ControllerFactory实现的,而ControllerFactory的创建又是在ControllerBuilder中完成的,因此我们先了解一下ControllerBuilder的工作原理。

ControllerBuilder

从源码中可以看出,在ControllerBuilder类中,并没有直接实现对controller工厂的创 建,ControllerFactory的创建实际上是委托给一个继承自IResolver接口的SingleServiceResolver类的实例来 实现的,这一点从GetControllerFactory方法中可以看出,它是通过调用SingleServiceResolver对象的 Current属性来完成controller工厂的创建的。

public IControllerFactory GetControllerFactory()
{
    return _serviceResolver.Current;  //依赖IResolver接口创建工厂
}

并且在源码中还发现,SingleServiceResolver类是internal级别的,这意味着外部无法直接访问,那么 ControllerBuilder是如何借助SingleServiceResolver来实现工厂的注册呢?继续看代 码,ControllerBuilder类和SingleServiceResolver类都有一个Func<IControllerFactory>类型的委托字段,我们姑且称为工厂委托,

//ControllerBuilder.cs
private Func<IControllerFactory> _factoryThunk = () => null;  //工厂委托
//SingleServiceResolver.cs
private Func<TService> _currentValueThunk;  //工厂委托

该委托实现了工厂的创建,而通过SetControllerFactory方法仅仅是更改了ControllerBuilder类的工厂委托字段,并没有更改SingleServiceResolver类的工厂委托字段,

public void SetControllerFactory(IControllerFactory controllerFactory)
{
    if (controllerFactory == null)
    {
        throw new ArgumentNullException("controllerFactory");
    }

    _factoryThunk = () => controllerFactory;  //更改ControllerBuilder的工厂委托字段
}

因此必须将相应的更改应用到SingleServiceResolver类中才能实现真正的注册,我们知道,如果是单纯的引用赋值,那么更改一个引用并不会对另外一个引用造成改变,比如:

Func<object> f1 = ()=>null;
Func<object> f2 = f1;  //f1与f2指向同一个对象
object o = new object();
f1 = ()=>o;  //更改f1后,f2仍然指向之前的对象
bool b1 = f1() == o;   //true
bool b2 = f2() == null;  //true,  f1()!=f2()

所以,ControllerBuilder在实例化SingleServiceResolver对象的时候,并没有将自身的工厂委托字段直接赋值给 SingleServiceResolver对象的对应字段(因为这样的话SetControllerFactory方法注册的委托无法应用到 SingleServiceResolver对象中),而是通过委托来进行了包装,这样就会形成一个闭包,在闭包中进行引用,如下所示:

Func<object> f1 = ()=>null;
Func<object> f2 = ()=>f1();  //通过委托包装f1,形成闭包
object o = new object();
f1 = ()=>o;  //更改f1后,f2与f1保持同步
bool b1 = f1() == o;  //true
bool b2 = f2() == o;  //true,  f1()==f2()

//ControllerBuilder.cs
internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
{
    _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
                                              () => _factoryThunk(),  //封装委托,闭包引用
                                              new DefaultControllerFactory { ControllerBuilder = this },
                                              "ControllerBuilder.GetControllerFactory");
}

这样SingleServiceResolver对象中的工厂委托就会与ControllerBuilder对象中的对应字段保持同步了,SetControllerFactory方法也就达到了替换默认工厂的目的。

闭包引用测试代码:

using System;

class Program
{
    public static void Main(string[] args)
    {
        Func<object> f1 = ()=>null;
        Func<object> f2 = f1;  //f1与f2指向同一个对象
        object o = new object();
        f1 = ()=>o;  //更改f1后,f2仍然指向之前的对象
        bool b1 = f1() == o;   //true
        bool b2 = f2() == null;  //true,  f1()!=f2()

        Print("直接赋值:");
        Print(f1(),"f1() == {0}");
        Print(f2(),"f2() == {0}");
        Print(f1() == f2(),"f1() == f2() ? {0}");

        Func<object> ff1 = ()=>null;
        Func<object> ff2 = ()=>ff1();  //通过委托包装f1,形成闭包
        object oo = new object();
        ff1 = ()=>oo;  //更改f1后,f2与f1保持同步
        bool bb1 = ff1() == oo;  //true
        bool bb2 = ff2() == oo;  //true,  f1()==f2()

        Print("委托赋值:");
        Print(ff1(),"ff1() == {0}");
        Print(ff2(),"ff2() == {0}");
        Print(ff1() == ff2(),"ff1() == ff2() ? {0}");
        
        Console.ReadLine();
    }

    static void Print(object mess,string format = "{0}")
    {
        string message = mess == null ? "null" : mess.ToString();
        Console.WriteLine(string.Format(format,message));
    }
}

下面看一下SingleServiceResolver类是如何实现对象的创建的,该类是个泛型类,这意味着可以构造任何类型的对象,不仅限于 ControllerFactory,实际上在MVC中,该类在很多地方都得到了应用,例如:ControllerBuilder、 DefaultControllerFactory、BuildManagerViewEngine等,实现了对多种对象的创建。

SingleServiceResolver

该类实现了IResolver接口,主要用来提供指定类型的实例,在SingleServiceResolver类中有三种方式来创建对象:

1private Lazy<TService> _currentValueFromResolver;  //内部调用_resolverThunk
2private Func<TService> _currentValueThunk;  //委托方式
3private TService _defaultValue;   //默认值方式

private Func<IDependencyResolver> _resolverThunk;  //IDependencyResolver方式

从Current方法中可以看出他们的优先级:

public TService Current
{
    get { return _currentValueFromResolver.Value ?? _currentValueThunk() ?? _defaultValue; }
}

_currentValueFromResolver实际上是对_resolverThunk的封装,内部还是调用_resolverThunk来实现对象的构造,所以优先级是:_resolverThunk > _currentValueThunk > _defaultValue,即:IDependencyResolver方式 > 委托方式 > 默认值方式。

SingleServiceResolver在构造函数中默认实现了一个DefaultDependencyResolver对象封装到委托字段_resolverThunk中,该默认的Resolver是以Activator.CreateInstance(type)的方式创建对象的,但是有个前提,指定的type不能是接口或者抽象类,否则直接返回null。
在ControllerBuilder类中实例化SingleServiceResolver对象的时候指定的是IControllerFactory接 口类型,所以其内部的SingleServiceResolver对象无法通过IDependencyResolver方式创建对象,那么创建 ControllerFactory对象的职责就落到了_currentValueThunk(委托方式)和_defaultValue(默认值方式)这两个方式上,前面说过,SingleServiceResolver类中的委托字段实际上是通过闭包引用ControllerBuilder类中的相应委托来创建对象的,而在ControllerBuilder类中,这个对应的委托默认是返回null,

private Func<IControllerFactory> _factoryThunk = () => null;

因此,默认情况下SingleServiceResolver类的第二种方式也失效了,那么此时也只能依靠默认值方式来提供对象了,在ControllerBuilder类中这个默认值是DefaultControllerFactory:

internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
{
    _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
                                              () => _factoryThunk(),
                                              new DefaultControllerFactory { ControllerBuilder = this }, //默认值
                                              "ControllerBuilder.GetControllerFactory");
}

所以,在默认情况下是使用DefaultControllerFactory类来构造Controller的。
在创建SingleServiceResolver对象的时候,可以从三个地方判断出真正创建对象的方法是哪种:

new SingleServiceResolver<IControllerFactory>(   //1、看泛型接口,如果为接口或抽象类,则IDependencyResolver方式失效
    () => _factoryThunk(),  //2、看_factoryThunk()是否返回null,如果是则委托方式失效
    new DefaultControllerFactory { ControllerBuilder = this },  //3、以上两种都失效,则使用该默认值
    "ControllerBuilder.GetControllerFactory");

通过以上创建对象的过程可以得知,有两种方式可以替换默认的对象提供器:

  1. 替换默认的DependencyResolver,可以通过DependencyResolver类的静态方法SetResolver方法来实现:
    CustomDependencyResolver customResolver = new  CustomDependencyResolver();
    DependencyResolver.SetResolver(customResolver);

    将以上语句放在程序启动的地方,例如:Application_Start

  2. 通过前面介绍的ControllerBuilder类的SetControllerFactory方法

注:第一种方式的优先级更高。

ControllerFactory

通过ControllerBuilder创建出ControllerFactory对象后,下面就要利用该对象完成具体Controller的创建,ControllerFactory都实现了IControllerFactory接口,通过实现CreateController方法完成对Controller的实例化,CreateController的内部逻辑非常简单,就两步:获取Controller类型,然后创建Controller对象。

获取Controller类型

根据控制器名称获取控制器Type的过程,有必要深入了解一下,以便于我们在日后遇到相关问题的时候能够更好的进行错误定位。获取类型的逻辑都封装在GetControllerType方法中,该过程根据路由数据中是否含有命名空间信息,分为三个阶段进行类型搜索:

  • 首先,如果当前路由数据中存在命名空间信息,则在缓存中根据控制器名称和命名空间搜索对应的类型,如果找到唯一一个类型,则返回该类型,找到多个直接抛异常
  • 其次,如果当前路由数据中不存在命名空间信息,或在第一阶段的搜索没有找到对应的类型,并且UseNamespaceFallback==true,此时会获取ControllerBuilder中设置的命名空间信息,利用该信息和控制器名称在缓存中进行类型搜索,如果找到唯一一个类型,则返回该类型,找到多个直接抛异常
  • 最后,如果路由数据和ControllerBuilder中都没有命名空间信息,或者在以上两个阶段都没有搜索到对应的Controller类型,那么会忽略命名空间,在缓存中仅按照控制器名称进行类型搜索,如果找到唯一一个类型,则返回该类型,找到多个直接抛异常

因此,命名空间的优先级是:RouteData > ControllerBuilder

在缓存中搜索类型的时候,如果是第一次查找,会调用ControllerTypeCache.EnsureInitialized方法将保存在硬盘 中的Xml缓存文件加载到一个字典类型的内存缓存中。如果该缓存文件不存在,则会遍历当前应用引用的所有程序集,找出所有public权限的 Controller类型(判断条件:实现IController接口、非抽象类、类名以Controller结尾),然后将这些类型信息进行xml序列化,生成缓存文件保存在硬盘中,以便于下次直接从缓存文件中加载,同时将类型信息分组以字典的形式缓存在内存中,提高搜索效率,字典的key为ControllerName(不带命名空间)。

Controller类型搜索流程如下图所示:

获取Controller类型

创建Controller对象

获取Controller类型以后,接下来就要进行Controller对象的创建。在DefaultControllerFactory类的源码 中可以看到,同ControllerBuilder类似,该类的构造函数中也实例化了一个SingleServiceResolver对象,按照之前介绍 的方法,我们一眼就可以看出,该对象是利用默认值的方式提供了一个DefaultControllerActivator对象。

_activatorResolver = activatorResolver ?? new SingleServiceResolver<IControllerActivator>(  //1、泛型为接口,IDependencyResolver方式失效
                     () => null,  //2、返回了null,委托方式失效
                     new DefaultControllerActivator(dependencyResolver),  //3、以上两种方式均失效,则使用该提供方式
                     "DefaultControllerFactory constructor");

实际上DefaultControllerFactory类仅实现了类型的搜索,对象的真正创建过程需要由 DefaultControllerActivator类来完成,默认情况下,DefaultControllerActivator创建 Controller的过程是很简单的,因为它实际上使用的是一个叫做DefaultDependencyResolver的类来进行 Controller创建的,在该类内部直接调用Activator.CreateInstance(serviceType)方法完成对象的实例化。

从DefaultControllerFactory和DefaultControllerActivator这两个类的创建过程可以发现,MVC 提供了多种方式(IDependencyResolver方式、委托方式 、默认值方式)来提供对象,因此在对MVC相关模块进行扩展的时候,也有多种方式可以采用。

Controller中的数据容器

Controller中涉及到几个给view传值的数据容器:TempData、ViewData和ViewBag。前两者的不同之处在于 TempData仅存储临时数据,里面的数据在第一次读取之后会被移除,即:只能被读取一次;ViewData和ViewBag保存的是同一份数据,只不 过ViewBag是动态对象,对ViewData进行了封装。

public dynamic ViewBag
{
    get
    {
        if (_dynamicViewDataDictionary == null)
        {
            _dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData); //封装ViewData
        }
        return _dynamicViewDataDictionary;
    }
}  

下面简单说一下TempData的实现原理。

TempData

首先看下MSDN上是如何解释的:

你可以按使用 ViewDataDictionary 对象的相同方式使用 TempDataDictionary 对象传递数据。 但是,TempDataDictionary 对象中的数据仅从一个请求保持到下一个请求,除非你使用 Keep 方法将一个或多个键标记为需保留。 如果键已标记为需保留,则会为下一个请求保留该键。
TempDataDictionary 对象的典型用法是,在数据重定向到一个操作方法时从另一个操作方法传递数据。 例如,操作方法可能会在调用 RedirectToAction 方法之前,将有关错误的信息存储在控制器的 TempData 属性(该属性返回 TempDataDictionary 对象)中。 然后,下一个操作方法可以处理错误并呈现显示错误消息的视图。

TempData的特性就是可以在两个Action之间传递数据,它会保存一份数据到下一个Action,并随着再下一个Action的到来而失 效。所以它被用在两个Action之间来保存数据,比如,这样一个场景,你的一个Action接受一些post的数据,然后交给另一个Action来处 理,并显示到页面,这时就可以使用TempData来传递这份数据。

TempData实现了IDictionary<string, object=””>接口,同时内部含有一个IDictionary<string, object=””>类 型的私有字段,并添加了相关方法对字典字段的操作进行了控制,这明显是代理模式的一个应用。因为TempData需要在Action之间传递数据,因此要 求其能够对自身的数据进行保存,TempData依赖ITempDataProvider接口实现了数据的加载与保存,默认情况下是使用 SessionStateTempDataProvider对象将TempData中的数据存放在Session中。

下面看一下TempData是如何控制数据操作的,TempDataDictionary源码中有这样一段定义:

internal const string TempDataSerializationKey = "__tempData";

private Dictionary<string, object> _data;
private HashSet<string> _initialKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> _retainedKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

私有字典字段_data是真正存放数据的地方,哈希集合_initialKeys和_retainedKeys用来标记数据,_initialKeys中存放尚未被读取的数据key,_retainedKeys存放可以被多次访问的key。
TempDataDictionary对数据操作的控制行为主要体现在在读取数据的时候并不会立即从_data中删除对应的数据,而是通过 _initialKeys和_retainedKeys这两个hashset标记每条数据的状态,最后在通过ITempDataProvider进行保存 的时候再根据之前标记的状态对数据进行过滤,这时才去除已访问过的数据。

相关的控制方法有:TryGetValue、Add、Keep、Peek、Remove、Clear

1、TryGetValue

public bool TryGetValue(string key, out object value)
{
    _initialKeys.Remove(key);
    return _data.TryGetValue(key, out value);
}

该方法在读取数据的时候,会从_initialKeys集合中移除对应的key,前面说过,因为_initialKeys是用来标记数据未访问状态 的,从该集合中删除了key,之后在通过ITempDataProvider保存的时候就会将数据从_data字典中删除,下一次请求就无法再从 TempData访问该key对应的数据了,即:数据只能在一次请求中使用。

2、Add

public void Add(string key, object value)
{
    _data.Add(key, value);
    _initialKeys.Add(key);
}

添加数据的时候在_initialKeys中打上标记,表明该key对应的数据可以被访问。

3、Keep

public void Keep(string key)
{
    _retainedKeys.Add(key);
} 

调用Keep方法的时候,会将key添加到_retainedKeys中,表明该条记录可以被多次访问,为什么可以被多次访问呢,可以从Save方法中找到原因:

public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider)
{
    // Frequently called so ensure delegate is stateless
    _data.RemoveFromDictionary((KeyValuePair<string, object> entry, TempDataDictionary tempData) =>
        {
            string key = entry.Key;
            return !tempData._initialKeys.Contains(key) 
                && !tempData._retainedKeys.Contains(key);
        }, this);

    tempDataProvider.SaveTempData(controllerContext, _data);
}

可以看出,在保存的时候,会从_data中取出每一条数据,判断该数据的key是否存在于_initialKeys和_retainedKeys 中,如果都不存在才会从_data中移除,所以keep方法将key添加到_retainedKeys后,该数据就不会被删除了,即:可以在多个请求中被 访问了。

4、Peek

public object Peek(string key)
{
    object value;
    _data.TryGetValue(key, out value);
    return value;
}

从代码中可以看出,该方法在读取数据的时候,仅仅是从_data中进行了获取,并没有移除_initialKeys集合中对应的key,因此通过该方法读取数据不影响数据的状态,该条数据依然可以在下一次请求中被使用。

5、Remove 与 Clear

public bool Remove(string key)
{
    _retainedKeys.Remove(key);
    _initialKeys.Remove(key);
    return _data.Remove(key);
}

public void Clear()
{
    _data.Clear();
    _retainedKeys.Clear();
    _initialKeys.Clear();
}

这两个方法没什么多说的,只是在删除数据的时候同时删除其对应的状态。

Proxool houseKeepingSleepTime bug修正 - - ITeye技术网站

mikel阅读(1557)

来源: Proxool houseKeepingSleepTime bug修正 – – ITeye技术网站

修正后jar包在附件内

 

异常代码:

Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property ‘houseKeepingSleepTime’ of bean class [org.logicalcobwebs.proxool.ProxoolDataSource]: Bean property ‘houseKeepingSleepTime’ is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

译:在类org.logicalcobwebs.proxool.ProxoolDataSource],中 houseKeepingSleepTime属性无效,houseKeepingSleepTime属性不可写或 houseKeepingSleepTime有一个无效的settter方法,houseKeepingSleepTime的setter方法的参数类型 匹配getter方法的返回值类型吗

 

官方源码:

/**
* @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime
*/
public long getHouseKeepingSleepTime() {
return houseKeepingSleepTime;
}

/**
* @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime
*/
public void setHouseKeepingSleepTime(int houseKeepingSleepTime) {
this.houseKeepingSleepTime = houseKeepingSleepTime;
}

修正代码:

/**
* @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime
*/
public long getHouseKeepingSleepTime() {
return houseKeepingSleepTime;
}

/**
* @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime
*此处将int类型改为long类型
*/
public void setHouseKeepingSleepTime(long houseKeepingSleepTime) {
this.houseKeepingSleepTime = houseKeepingSleepTime;
}

修正后jar包在附件内

 

spring中以dataSource方式使用proxool连接池 - goodhumor的专栏 - 博客频道 - CSDN.NET

mikel阅读(1366)

来源: spring中以dataSource方式使用proxool连接池 – goodhumor的专栏 – 博客频道 – CSDN.NET

 spring中以dataSource方式使用proxool连接池

(by goodhumor)

方式一:
在Spring的”applicationContext.xml”中的dataSource bean定义——

<bean id=”dataSource”
    class=”org.logicalcobwebs.proxool.ProxoolDataSource”>
    <property name=”driver”>
        <value>com.mySQL.jdbc.Driver</value>
    </property>
    <property name=”driverUrl”>
        <value>jdbc:mySQL://localhost:3306/dbname?user=yourname&amp;password=yourpass</value>
    </property>
    <property name=”user” value=”yourname” />
    <property name=”password” value=”yourpass” />
    <property name=”alias” value=”Pool_dbname” />
    <property name=”houseKeepingSleepTime” value=”90000″ />
    <property name=”prototypeCount” value=”0″ />
    <property name=”maximumConnectionCount” value=”50″ />
    <property name=”minimumConnectionCount” value=”2″ />
    <property name=”simultaneousBuildThrottle” value=”50″ />
    <property name=”maximumConnectionLifetime” value=”14400000″ />
    <property name=”houseKeepingTestSql” value=”select CURRENT_DATE” />
</bean>

第一种方式需要把用户名和密码写在连接串里面,
ProxoolDataSource类提供的user,password属性似乎没有什么用。
无论提供什么,它都会以空用户名、密码去连接数据库。
这可能是Proxool RC0.93的一个bug。
不过配置中的user,password两个属性还必须设置,否则hibernate会报空指针错误。

方式二:
在Spring的”applicationContext.xml”中的dataSource bean定义——

<bean id=”dataSource”
    class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
    <property name=”driverClassName”>
        <value>org.logicalcobwebs.proxool.ProxoolDriver</value>
    </property>
    <property name=”url”>
        <value>proxool.Pool_dbname</value>
    </property>
</bean>

 

第二种方式需要预先在”web.xml”先配置好Proxool连接池,配置如下:

 

<servlet>
    <servlet-name>proxoolServletConfigurator</servlet-name>
    <servlet-class>
        org.logicalcobwebs.proxool.configuration.ServletConfigurator
    </servlet-class>
    <init-param>
        <param-name>xmlFile</param-name>
        <param-value>WEB-INF/proxool.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
    <servlet-name>context</servlet-name>
    <servlet-class>
        org.springframework.web.context.ContextLoaderServlet
    </servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

注意,第二种方式下Spring的上下文加载如果想使用listener方式(Struts2要求),
则与连接池有关的Bean全得延迟初始化。因为listener比servlet优先初始化,
如果相关Bean不是lazy-init的话,则启动服务器时会出现Bean找不到连接定义的异常。

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
其中proxool的配置文件可以采用xmlFile”proxool.xml”或者propertyFile”proxool.properties”

“proxool.xml”格式如下:

<?xml version=”1.0″ encoding=”UTF-8″?>
<proxool-config>
   <proxool>
      <alias>Pool_dbname</alias>
      <driver-url>jdbc:mysql://localhost:3306/dbname</driver-url>
      <driver-class>com.mysql.jdbc.Driver</driver-class>
      <driver-properties>
      <property name=”user” value=”yourname”/>
      <property name=”password” value=”yourpass”/>
      </driver-properties>
      <house-keeping-sleep-time>60000</house-keeping-sleep-time>
      <maximum-connection-count>20</maximum-connection-count>
      <minimum-connection-count>2</minimum-connection-count>
      <prototype-count>0</prototype-count>
      <simultaneous-build-throttle>20</simultaneous-build-throttle>
      <house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
      <statistics>15s,10m,1d</statistics>
      <statistics-log-level>INFO</statistics-log-level>
   </proxool>
   <proxool>
    <!–可以配置多个库–>
   </proxool>
</proxool-config>

“proxool.properties”格式如下:

jdbc-0.proxool.alias=Pool_dbname
jdbc-0.proxool.driver-url=jdbc:mysql://localhost:3306/dbname
jdbc-0.proxool.driver-class=com.mysql.jdbc.Driver
jdbc-0.user=yourname
jdbc-0.password=yourpass
jdbc-0.proxool.house-keeping-sleep-time=60000
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE
jdbc-0.proxool.maximum-connection-count=10
jdbc-0.proxool.minimum-connection-count=3
jdbc-0.proxool.maximum-connection-lifetime=18000000
jdbc-0.proxool.prototype-count=3
jdbc-0.proxool.simultaneous-build-throttle=10
jdbc-0.proxool.recently-started-threshold=60000
jdbc-0.proxool.overload-without-refusal-lifetime=50000
jdbc-0.proxool.maximum-active-time=60000
jdbc-0.proxool.verbose=true
jdbc-0.proxool.trace=true
jdbc-0.proxool.fatal-sql-exception=Fatal error

jdbc-2.proxool.alias=Pool_dbname2
……
<!–可以配置多个库–>

———————————————————–

个人比较倾向于第二种配置方式,
一来可以避免在Spring的”applicationContext.xml”中写一大堆参数,
尤其是避免了driverUrl中带用户名密码(这会显示在proxool包中带的
org.logicalcobwebs.proxool.admin.servlet.AdminServlet输出的页面中)

二来proxool连接池可以在tomcat启动时就初始化好,可以提高第一次访问web时的连接速度。