在jdbc配置logSlowQueries信息

2011年12月15日 没有评论

MySql服务器端本身可以通过配置以日志的方式记录下来那些耗时的sql语句,对给系统调优提供一些参考信息,同样java的jdbc Driver也支持这样的功能,只需要在jdbc中增加logSlowQueries和配置即可slowQueryThresholdMillis,其中logSlowQueries参数设置是否打印出慢sql,slowQueryThresholdMillis定义一个时间,单位是毫秒,超过这个时间的就是慢sql,也就会打印出来。例如jdbc配置如下:

jdbc:mysql://localhost:3306/database_name?autoReconnect=true&useUnicode=true&characterEncoding=utf8
&logSlowQueries=true&slowQueryThresholdMillis=0

MyBatis的mapper接口中方法的多参数问题

2011年12月8日 2 条评论

MyBatis的mapper接口不需要自己实现,框架会自动帮我们实现,到时候直接调用就可以了。定义的mapper接口中的方法可以有多个参数吗?答案是肯定。在Ibatis时代是自己通过代码实现如何调用xml中定义的statement,接受的参数只能是一个,所以处理的办法通常是用Map的方式。当然这个也能使用在MyBatis上,不过MyBatis提供更加简单的方法。下面就通过例子来说明。

Mapper接口

public interface TestMapper {

	Object meth1(String para1, String para2);

	/**
	 * p1、p2可以是任何合法的java命名方式
	 * xml中可以根据此标示来获取到具体传入的值
	 */
	Object meth2(@Param("p1")String para1, @Param("p2")String para2);
}

mapper.xml

     <select id="meth1" resultType="int">
     	select count(*) from test
     	where col1 = #{0}
     	and clo2 = #{1}
     </select>

     <select id="meth2" resultType="int">
     	select count(*) from test
     	where col1 = #{p1}
     	and clo2 = #{p2}
     </select>

上述两种方法都行的通,上述statement中不需要指定parameterType。如果不使用@Param注解方式,那么可以通过#{0}、#{1}的方式来获取参数的值,注意function中的第一个参数是0;使用了注解就按注解中定义的名字来取。推荐使用注解的方式。在方法重构时,例如增加、减少或调整参数的顺序,如果使用非注解的方式,在修改xml时就显得比较麻烦,可能里面的${0}、${1}、${2}都需要调整,而且不明确,特别是参数较多的情况下。

Struts2接受枚举类型参数

2011年12月6日 没有评论

strtus2的版本为2.2.3.1,默认是支持转换枚举型参数。有一个问题,例如在action中声明了一个枚举类型的变量testEnum,在action中有该变量对应的get、set方法,如果页面传入的值不是枚举类型中指定的值,这时action中的testEnum为null,但在前端的freemarker模板中通过${testEnum}又能获取到这个值,也就是前面页面传入值,此时并没有调用action的中getTestEnum方法,这个时候应该是从ValueStack中取到的,因为在请求action的时候,已经把请求的参数放入了ValueStack。如果页面上需要action处理后的判断testEnum是不是为null,就不能直接使用<#if testEnum??>了,这个时候就必须还要判断一下testEnum的对象类型,具体的方法参看:freemarker中判断对象类型

分类: Java 标签: ,

freemarker如何判断对象类型

2011年12月6日 没有评论

在freemarker中似乎没有instanceOf这个方法,有时候页面上需要来判断变量的类型,可以使用变通的方法,如下

    <#if myVar.class.simpleName == "Object Type">
        ...
    </#if>

MyBatis3自定义typeHandlers

2011年11月28日 没有评论

mybatis3中默认了标准的java类型的typeHandlers,对枚举类型也内置了一个叫EnumTypeHandler的处理器,但是有一个问题,如果在数据库里面的字段类型是SMALLINT、TYININT、INTEGER等数据类型,默认的EnumTypeHandler就不能处理了,http://asialee.iteye.com/blog/1013238,这个地方有比较详细的说明。解决这个问题有两种方法,一是修改数据库字段的类型为枚举类型,并且枚举值用字符表示;另外一种方法就是自己实现一个typeHandlers。实现的方法很简单,官方的手册上就一个例子。配置的时候需要注意,不光只在 MapperConfig.xml 配置

<typeHandlers>
<typeHandler javaType="String" jdbcType="VARCHAR"
handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>

还需要在对应的字段在resultMap中配置jdbcType属性,而且select的返回结果类型不能使用resultType,必须用resultMap,否则mybatis就无法应用用自定义的typeHandlers。为何一定要配置jdbcType呢?因为MyBatis为POJO中字段设置typeHandlers是根据在javaType和jdbcType来确定的,javaType可以根据POJO来获取,MyBatis不会审视数据库元信息来决定jdbcType,如果没有指定,那么都是按null来处理,因而获取typeHandlers通过javaType了,就算在MapperConfig.xml中配置的全局typeHandlers也无法正确应用。

另外一种配置是直接在resultMap中指定对应字段的typeHandlers,这样可以不在MapperConfig.xml配置typeHandlers和设置jdbcType。

官方文档中有如下说明:

使用这样的类型处理器将会覆盖已经存在的处理Java的String类型属性和VARCHAR参数及结果的类型处理器。要注意MyBatis不会审视数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指定那是VARCHAR类型的字段,来绑定到正确的类型处理器上。这是因为MyBatis直到语句被执行都不知道数据类型的这个现实导致的。

由于没有很好的理解“不会审视数据库元信息来决定使用哪种类型”导致走了很多弯路,一直无法使用自定义的typehandler。

Tomcat-6.0.33之APR based Apache Tomcat Native library

2011年11月25日 没有评论

最近使用tomcat 6.0.33这个版本,启动的时候有个提示:

The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path:...

tomcat可以整合本地apr,在处理静态资源的时候速度更快,总而言之就是使用本地的apr库提升处理效率。在网上一查,很多人提到了这个问题,解决这个问题其实很简单,但window和linux处理方法不太一样。下面就分别给出解决方法。

  • window平台

在window下启动的时候会提示was not found on the java.library.path: C:\Tools\jdk1.6.0_29\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS …,这个根据每个人的环境不同,可能给出的路径也不太一样,只要把Native library拷贝到上述路径之一即可,Native library是什么呢,网上有提供下载,其实不要那么麻烦,在tomcat的bin目录下就有,文件名是:tcnative-1.dll。例如我把这个文件拷贝到C:\Tools\jdk1.6.0_29\bin下,然后再启动tomcat就没有上述的提示了。

  • linux平台

linux下比较复杂一点,因为tomcat包中没有提供编译好的so文件,所以需要自己编译,tomcat发行版中提供了源码,文件为tomcat的bin/tomcat-native.tar.gz,另外编译时候需要依赖APR 1.2、OpenSSL,如果机器上没有安装,可以使用 yum -y install apr-devel openssl-devel 来进行安装。解压tomcat-native.tar.gz后会得到一个tomcat-native-1.1.20-src的目录,Native library的源文件位于tomcat-native-1.1.20-src/jni/native下,进入该目录,执行./configure,可能会看到configure: error: APR could not be located. Please use the –with-apr option.的错误提示,这个时候用–with-apr制定一下apr的位置即可,我使用的是

./configure --with-apr=/usr/bin/apr-1-config

,顺利通过,然后执行 make && make install 编译就算搞定,此时应该可以在/usr/local/apr/lib/下看到一个名为 libtcnative-1.so 的文件,拷贝该文件到tomcat启动时提示的任何一个路径即可。

更多关于apr的信息可以查看官方资料,地址:http://tomcat.apache.org/tomcat-5.5-doc/apr.html

eclipse的Toggle Block Selection Mode功能

2011年11月25日 没有评论

用eclipse3.6一段时间了,今天无意中发现了Toggle Block Selection Mode功能,其用途就是文本编辑器支持块选择模式。何为块选择模式呢,就是类似于ultraedit的列模式。似乎这个功能在eclipse3.5版本就推出来了的。

这个功能其实蛮有用的,比如一个文件有很多行,现在只想把每行前面的10个字符复制出来,那么在块选择模式下就很容易做到了;另外在html之类的文件中可以辅助找出html标签是否不匹配,前提的html文件写的比较规范。

启用此功能的快捷键为:Alt+Shift+A,通过这个它可以在快选择模式和普通模式间进行切换。

分类: Java 标签:

深入理解struts2的namespace

2011年11月23日 没有评论

struts2提供了一个命名空间的概念,可以通过package的namespace属性来设置,使用它可以避免action的名字冲突,同时也可以在逻辑上给action分类。关于namesapce的很多信息,可以参考strtus的官方文档,地址是:http://struts.apache.org/2.2.3.1/docs/namespace-configuration.html

个人觉得,这个里面还是很多信息没有表达清楚。例如该文档最后有一段话如下:

Namespaces are not a path!
Namespace are not hierarchical like a file system path. There is one namespace level. For example if the URL /barspace/myspace/bar.action is requested, the framework will first look for namespace /barspace/myspace. If the action does not exist at /barspace/myspace, the search will immediately fall back to the default namespace “”. The framework will not parse the namespace into a series of “folders”. In the Namespace Example, the bar action in the default namespace would be selected.

大概意思就是说,如果在某个命令空间下没有找到对应的action,然后就直接去缺省的命名空间下。但事实真的如此吗?

通过一些测试,发现似乎遵循如下的规则:

1.假设请求路径的URI,例如url是:http://www.netingcn.com/path1/path2/test.do

2.首先寻找namespace为/path1/path2的package,如果存在这个package,则在这个package中寻找名字为test的action,若找到则执行,否则转步骤5;如果不存在这个package则转步骤3。

3.寻找namespace为/path1的package,如果存在这个package,则在这个package中寻找名字为test的action,若找到则执行,否则转步骤5;如果不存在这个package则转步骤4。

4. 寻找namespace为/的package,如果存在这个package,则在这个package中寻找名字为test的action,若找到则执行,转步骤5;如果不存在转步骤5。

5. 如果存在缺省的命名空间,就在该package下查找名字为test的action,若找到则执行,否则页面提示找不到action;否则提示面提示找不到action。

上述一个很重要的地方就是一旦找到对应的namespace的package就停止向上级路径查找了,另外缺省命名空间(package中没有指明namespace属性或namespace属性值为空)的package的可以不存在。

以前一直比较困惑的是,当访问http://www.netingcn.com/test.do成功,那类似http://www.netingcn.com/x/test.do,http://www.netingcn.com/x/y/test.do也能正常访问,而且执行的同一个action。而上述的试验结果可以很好的解释这个疑惑了。但是个人觉得这样的设计不是太好,决定去源码看个究竟,在org.apache.struts2.dispatcher.mapper.DefaultActionMapper找到关于如何在namespace中查找action的操作,有如下代码:

    protected void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) {
        String namespace, name;
        int lastSlash = uri.lastIndexOf("/");
        if (lastSlash == -1) {
            namespace = "";
            name = uri;
        } else if (lastSlash == 0) {
            // ww-1046, assume it is the root namespace, it will fallback to
            // default
            // namespace anyway if not found in root namespace.
            namespace = "/";
            name = uri.substring(lastSlash + 1);
        } else if (alwaysSelectFullNamespace) {
            // Simply select the namespace as everything before the last slash
            namespace = uri.substring(0, lastSlash);
            name = uri.substring(lastSlash + 1);
        } else {

注意到其中alwaysSelectFullNamespace这个信息,原来它属于struts.properties常用配置的一项,其作用是控制是否一直在最后一个slash之前的任何位置选定namespace。由于struts2默认是设置是false,所以导致按照上述试验结果成功,当把alwaysSelectFullNamespace在strtus.properties中设置为true时,此时struts2查找action就不会递归路径去查找package,而是直接找路径对应的package,如果没有找到就去默认命名空间下查找,这就是官方文档中所采用的说法。

个人建议把alwaysSelectFullNamespace设置为true,明确指定action在属于命名空间的package中,不会操作url路径随便输入的问题,同时执行效率也会略有提高。

使用neuxs搭建maven私服

2011年11月18日 评论已被关闭

私服的好处很多,可以在私服上建立公司内部仓库,把公司的内部构件部署上去供其他人或项目使用;能够部署第三方构件,某些第三方构建在公共的仓库中没有,如果项目中需要使用,就可以把第三方构建部署到自己的私服上,这样mavne中就能正常使用了;在没有私服的情况,项目开发的每个人都需要从远程的中央库下载依赖的构建,浪费带宽不说,效率还低;等等……。

  • 安装nexus

1、下载

下载地址:http://nexus.sonatype.org/downloads/,这里列出了所有版本,挑一个最新版本来使用。Nexus提供了两种安装方式,一种是内嵌Jetty的bundle,只要你有JRE就能直接运行。第二种方式是WAR,你只须简单的将其发布到web容器中即可使用。为了方便就直接选用bundle版本。本文下载的是nexus-oss-webapp-1.9.2.3-bundle.tar.gz 。

2、安装

在指定的目录解压下载的文件

tar xvf nexus-oss-webapp-1.9.2.3-bundle.tar.gz

解压后会看到两个文件夹,分别是nexus-oss-webapp-1.9.2.3和sonatype-work,前者包含了nexus的运行环境和应用程序,后者包含了你自己的配置和存储构件的地方。nexus-oss-webapp-1.9.2.3/conf/plexus.properties中可以修改端口信息已经工作区的路径。

3、启动nexus
进入nexus-oss-webapp-1.9.2.3/bin/jsw/目录,然后根据OS的版本进入相应的目录,在linux下,运行./nexus start即启动了服务,直接运行./nexus会看到提示信息。neuxs默认监听端口是8081,此时在浏览器中运行访问http://nexus-server-ip:8081/nexus应该可以看到neuxs的界面。

  • 配置nexus

新搭建的neuxs环境只是一个空的仓库,需要手动和远程中心库进行同步,nexus默认是关闭远程索引下载,最重要的一件事情就是开启远程索引下载。登陆nexus系统,默认用户名密码为admin/admin123。 点击左边Administration菜单下面的Repositories,找到右边仓库列表中的三个仓库Apache Snapshots,Codehaus Snapshots和Maven Central,然后再没有仓库的configuration下把Download Remote Indexes修改为true。然后在这三个仓库上分别右键,选择Repari Index,这样Nexus就会去下载远程的索引文件。

新建公司的内部仓库,步骤为Repositories –> Add –> Hosted Repository,在页面的下半部分输入框中填入Repository ID和Repository Name即可,比如分别填入myrepo和 my repository,另外把Deployment Policy设置为Allow Redeploy,点击save就创建完成了。

修改neuxs仓库组

Nexus中仓库组的概念是Maven没有的,在Maven看来,不管你是hosted也好,proxy也好,或者group也好,对我都是一样的,我只管根据groupId,artifactId,version等信息向你要构件。为了方便Maven的配置,Nexus能够将多个仓库,hosted或者proxy合并成一个group,这样,Maven只需要依赖于一个group,便能使用所有该group包含的仓库的内容。

neuxs-1.9.2.3中默认自带了一个名为“Public Repositories”组,点击该组可以对他保护的仓库进行调整,把刚才建立的公司内部仓库加入其中,这样就不需要再在maven中明确指定内部仓库的地址了。同时创建一个Group ID为public-snapshots、Group Name为Public Snapshots Repositories的组,把Apache Snapshots、Codehaus Snapshots和Snapshots加入其中。

到这里neuxs的安装配置就完成了,下面介绍如何在mavne中使用自己的私服。 阅读全文…

分类: Java, Linux 标签: ,

maven部署构件至Nexus私服

2011年11月17日 没有评论

首先在Nexus中创建一个自己私有的仓库,步骤为Repositories –> Add –> Hosted Repository,在页面的下半部分输入框中填入Repository ID和Repository Name即可,比如分别填入myrepo和 my repository,点击save就创建完成了。

如果要把构建部署至私服中,需要在构建的 pom.xml 文件增加 distributionManagement 配置项,有多种协议可以用来部署构建,这里主要讲两种。

  • 第一种配置如下:
<project>
	[...]	
	<distributionManagement>
		<repository>
			<id>myrep</id>
			<name>my repository</name>
			<url>file:/usr/local/mvn-private-server/nexus-oss-webapp-1.9.2.3/./../sonatype-work/nexus/storage/myrep/</url>
		</repository>
	</distributionManagement>
	[...]
</project>

说明:其中id就是需要部署构建的仓库Id,name似乎不重要,可以随便输入,url就是仓库的configuration中Default Local Storage Location项的对应的信息。采用此种方法,服务器不会对部署操作进行认证,同时配置也把仓库的物理存储地址完全暴露,感觉不是太好。

  • 第二种配置如下:
<project>
	[...]	
	<distributionManagement>
	  <repository>
		<id>tagphi</id>
		<url>http://nexus-server-ip:8081/nexus/content/repositories/myrep</url>
	  </repository>
	</distributionManagement>
	[...]
</project>

说明:上述的distributionManagement信息可以在对于的仓库的Summary中找到。

配置好后,此时执行mvn deploy,部署应该不会成功,根据提示信息,重新执行 mvn deploy -e 或 mvn deploy -X,此时能看到具体的错误信息,报Return code is: 401错,这个是因为发布者没有权限,需要把用户认证信息配置在maven的settings.xml中,该文件在mavne安装包下的conf目录下,这是一个全局配置,同时可以把该文件复制到 userdir/.m2 目录下,这样配置就只对当前用户生效。在settings.xml文件中servers段中添加如下信息

    <server>
      <id>myrep</id>
      <username>deployment</username>
      <password>password</password>
    </server>

其中id就是部署仓库的id,username是作为部署用户,Nexus系统默认的deployment,密码为deployment123,可以在security — users中找到,如果需要设置密码,在用户列表中找到该用户,在该用户上点击右键,会出来一个菜单供重置密码或修改密码。此时在执行 mvn deploy,应该可以看到成功发布了。当第二次执行 mvn deploy 又失败,这次失败原因是Return code is: 400,该错误的原因是在创建仓库时在configuration中的Deployment Policy设置为了Disable Redeploy,修改为Allow Redeploy即可。

无觅相关文章插件,快速提升流量