- Struts2 对文件的上传和下载提供了很好的支持,上传时直接用 java.io.File 来接收,下载时也无需自己去设置相应的 Stream 响应头,它提供了 org.apache.struts2.dispatcher.StreamResult 给 Action 使用。它反映到 struts.xml 配置里就是type="stream" 的 result,由 result 去负责把文件内容写入响应中去。Action 的执行方法在 result 之前执行,所以你可以借此控制下载权限,本文也演示了如何判断文件是否存在,不存在则导向到 FileNotFound 页面。StreamResult 中有哪些相关的配置参数可以参考它的源代码: Read More
- 本文通过一个简单的例子,说明如何去扩展XML配置,它大致需要的几个步骤。具体的需求是使用自定义标签定义一个简单的bean,这个bean有一个或多个属性,标签定义完成后,可以在其他项目中用自定义标签来定义该bean。
Spring 2.0版本支持扩展XML配置,着实兴奋了一下,在我看来,Spring作为目前最流行的框架,不能扩展用户自定义的配置,实在是Spring的一个很不爽的地方,的方式用起来比较通用,起码到目前为止符合大部分人的使用习惯,并且能完成Spring所有的配置操作,但是对于第三方的提供商或则会经常扩展Spring功能的开发者来说,使用这样的配置方式或许不是他们最想要的,他们需要使组件的配置更加直观、易阅读、易扩展……试想使用下面的配置方式。 Read More - 现在越来越多的项目用 Slfj,而与它结合最好的 Log4j 替代品就是 Logback,下面是 Logback 的一个可供参考的基本的配置文件 logback.xml,可以控制台和文件同时输出,文件可进行两种类型的归档,分天存储日志,或按文件大小压缩日志归档。
Logback 和 Log4J 同出一人之手,而作者的专注点也在 Logback,Logback 有更好的性能,特别是在现代 Java 程序中。
一般是 rollingPolicy 和 triggeringPolicy 搭配使用,rollingPolicy 负责做什么,triggeringPolicy 管理什么时候做,而 FixedWindowRollingPolicy 本身就实现了 TriggeringPolicy 接口,所以它能够自我管理,不需要别人来推动就会做的。 Read More - 我们在使用 Struts2 的时候一定有用过它的 ModelDriven 类型的 Action,它适于把零散的属性自动组装到一个 JavaBean 中,它的 Model 就相当于 Struts1 的 FormBean。你的 Action 必须实现 com.opensymphony.xwork2.ModelDriven 接口及它的 getModel() 方法,当然要声明一个存储 Model 对象的属性,这个属性将会被压入到 ValueStack 中。
你也可以自然或不自觉在 Action 中加入一个 setModel() 方法,试图在执行期修改当前的 Model 对象,比如像下面这样的 IndexAction 代码: Read More - 用 用 jreloader 动态重新加载改变的类而不用重启 JVM 来避免因 classes 目录中的文件改动而不停重启 Tomcat。但是却会出现如下的问题:
Feb 15, 2011 3:51:06 PM org.apache.catalina.core.StandardContext filterStart
SEVERE: Exception starting filter struts2
java.lang.NoClassDefFoundError: Lorg/apache/velocity/app/VelocityEngine;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
at java.lang.Class.getDeclaredFields(Class.java:1743)
at com.opensymphony.xwork2.inject.ContainerImpl.addInjectors(ContainerImpl.java:89)
at com.opensymphony.xwork2.inject.ContainerImpl$1.create(ContainerImpl.java:71)
at com.opensymphony.xwork2.inject.ContainerImpl$1.create(ContainerImpl.java:67)
at com.opensymphony.xwork2.inject.util.ReferenceCache$CallableCreate.call(ReferenceCache.java:150)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) Read More - 在 Struts2 中要使用 Ajax 获得 Json 数据我认为目前还是 struts2-json-plugin 了。当然你你可以用手工用像 XStream、Google Gson、Jackson 这样的工具手工把 Java 对象转换成 Json 字符串再写往 Response 去,要写的代码自然多不了,还得留心字符集与 content type。而 struts2-json-plugin 毫无疑问是与 Struts2 最亲近了,只需你配置一些属性就能得到你想的结果。
本想分几篇逐步介绍如何使用 struts2-json-plugin 的,然而就在现在发现官方的 struts2-json-plugin 指南已经很详细了,所以干脆翻译一下 http://struts.apache.org/2.2.1.1/docs/json-plugin.html,同时自己加深对它的理解。 Read More - Struts2 的 <s:component> 标签可以让你消磨掉自定义标签的意愿,它可以指定一个模板文件,我比校亲赖于 ftl 文件,然后用 <s:param> 给上参数,其他的事情交给 freemarker 去处理了,而且在 ftl 文件能够直接以 <@s.textfield ..../> 的形式使用 Struts2 的标签。
比如,jsp 文件里这么使用 <s:component> 标签:
<s:component template="/components/status.ftl" theme="simple">
<s:param name="status" value="#status"/>
</s:component>
把 status.ftl 要放在 WEB-INF/classes/template/simple/components/status.ftl。当然你可以应用 <s:component> 的 templateDir 属性使 status.ftl 放在别的位置上,但可能会带来别的麻烦。 Read More - 前些日子折腾过这一话题,而且在 Struts2 中 OGNL 如何更简单的访问静态变量和静态方法 记述了其中的原理,也对实现作了初步的猜想,但没给出实际的答案。这里将会给出,探寻的过程中有过不少尝试,下面也将把解决的过程描述出来,仍有不少迷域之处。先交待一下答案,必须在一个自定义的 PreResultListener 里压入静态方法或静态变量所在类的对象实例,在返回结果之前方能保证它们是在栈顶的。
解决此问题的一个明确目标就是要把静态方法或静态变量所在类的对象实例压到 ValueStatic 已知的位置上,当然最应该就是在栈顶,其他的栈数据,如当前 Action 实例或 Model 对象应该在它们之下,这样的话,你就能用 @vs@, 或 @vs1@... 这样的方式明确访问哪个类的静态成员。
最简单方法,前篇也讲过,在 Action 的 execute() 方法中往 ValueStatic 中压入的值会在栈顶--在 Action 实例和 Model 实例之上。 Read More - 在 Spring 中为 javabean 注入属性文件中的属性值一般人都知道的,可以通过 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 引入一个属性文件,然后给 bean 指定属性的时候就可以用 ${jdbc.url} 方式赋值了。比如在 Spring 中是这样的配置:
1<bean id="propertyConfigurer" 2 class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 3 <property name="locations"> 4 <list> 5 <value>classpath:jdbc.properties</value> 6 </list> 7 </property> 8</bean> 9 10<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 11 destroy-method="close"> 12 <property name="url" value="${jdbc.url}"/> 13 <property name="username" value="${jdbc.username}"/> 14</bean>
只是有时候我们需要给 bean 赋上系统属性(System.getProperties() ) 中的值或环境变量(System.getenv() ) 中的值,根据程序所处的环境产生不同的行为,这样我们无法事先在某个 properties 文件预先设定好值的。 Read More - 以前一篇中写到了 hibernate 调用存储过程,这里介绍 Spring 借道 JdbcTemplate 如何调用数据库存储过程。还是以前面的那个 DB2 存储过程为例,该过程的代码如下:
1CREATE procedure selectAllUsers(IN piAge INTEGER) 2DYNAMIC RESULT SETS 1 3BEGIN 4 DECLARE temp_cursor1 CURSOR WITH RETURN TO CLIENT FOR 5 SELECT * FROM test where age < piAge; 6 OPEN temp_cursor1; 7END;
这个过程中最后一行直接打开了一个游标,也就是返回了一个结果集。调用存储过程的方法应该看看 org.springframework.jdbc.core.JdbcTemplate 的各个 execute() 方法,具体点就是带了 CallableStatementCallback<T> 参数的那两个 execute(),究底的话又归结为其中之一。 Read More