- 浏览: 2611982 次
- 性别:
- 来自: 小胖儿的大城
文章分类
最新评论
-
ni4wangba0:
ni4wangba0 写道亲测,算法有问题。对不起,其实是我自 ...
谈谈"求线段交点"的几种算法(js实现,完整版) -
ni4wangba0:
亲测,算法有问题。
谈谈"求线段交点"的几种算法(js实现,完整版) -
kers007:
苹果不让Webapp 在appstore 里发布,我不知道对 ...
苹果真的要在 AppStore 里封杀 WebApp 吗? -
striveandlive:
fins = js大牛
[原创]GT-Template, 一个超轻量级的js模板工具. -
AlwaysYang:
基础扎实的才能行走天下。
关于body的"大小"在ie和ff下的一些基础知识
目前流行的新型的MVC框架 几乎都在"增强单元测试能力"上做了很多文章.
目的就是让 Controller 可以脱离web容器单独进行单元测试.
大多数采用的方法都是使 Controller 中的方法的参数 和 返回值 与 j2ee特有的类(如HttpXXXX)无关.
例如 传入的 是若干个 HashMap ,返回的是纯的字符串.
这样在单元测试的时候,只要new一个Controller,准备一些装有测试数据的Map,
然后执行相关的Controller方法,再然后看看返回值,就可以了.
显然,流行的Struts 1.X (>=1.2) 是不具备这样的特性的.
如果您现在有一个遗留的使用Struts 1.X(>=1.2) 的系统,或者因为人力资源的原因,不能立即引入ww或Struts2.x,
那么如何让您的Action类似的可测性了呢(其实除了可测试性,这样的改进往往也会大大的减少代码的开发量).
下面我就把我的一些心得写出来,和大家一起分享,欢迎大家拍砖.
注意:以下讨论均以改造 DispatchAction 为例(不使用DispatchAction的情况应该比较少吧 呵呵).
先说明一下改造的目的:
简化开发,减少代码量
增强单元测试能力
全面兼容现有DispatchAction(这点很重要)
一个传统的 DispatchAction 代码结构
对于上面的代码大家再熟悉不过了,我们现在要做的事情就是通过改造,让上面的action方法变成下面的样子.
上面的代码是一个最终的目标,我们先一步一步来.
首先这种改造我们一定要从 Struts 提供的 DispatchAction 做起.
总体思路很明显:
自己写个类 继承 DispatchAction ,并且添加或修改一些方法, 然后项目中的其他的DispatchAction都继承这个自己写的DispatchAction类.
简单说一下Struts 的 DispatchAction的工作流程.
首先 它也是一个action,所以请求来了 他会自动去执行execute方法
execute方法内部做一些操作后,会调用 dispatchMethod 方法
dispatchMethod方法会,调用getMethod方法 来取得欲执行的方法,并且执行之
改造的核心就是围绕最关键的dispatchMethod方法.
而由于我们要"全面兼容现有DispatchAction",所以对于getMethod我们不做修改,而是选择增加一个类似的方法 getMethodTD
首先写一个新的 .DispatchAction基类,他继承org.apache.struts.actions.DispatchAction.
首先来看一下这个 getMethodTD 方法.
原getMethod(String name)方法的作用是:
取得一个名字为name,参数类型为 ActionMapping , ActionForm , HttpServletRequest ,HttpServletResponse 的一个方法.
而这个新写的 getMethodTD 方法的作用是:
取得一个名字为name,参数类型为 TDServletWrapper 的一个方法.
这个大家和 原getMethod一对比就能看出来作用和差异了,注意那个cacheKey=TD_METHODCACHE_PREFIX+name,这个是必须的,不能直接用name做key.
其中这个 TDServletWrapper 就是封装的一个"可以"与web容器脱离的对象,注意,这里用的是可以.而不是直接就脱离了.
对此后面再做解释.
要添加的 getMethodTD 方法添加完了.
下面来看一下重点 改造 dispatchMethod方法:
原dispatchMethod方法的流程其实很简单:
1 调用 getMethod(name)方法,取得真正要执行的方法 并执行(传入的参数类型为 ActionMapping , ActionForm , HttpServletRequest ,HttpServletResponse ).
2 返回 方法执行的 结果 (返回结果类型为 ActionForward ).
改造后的目的是:
1 调用 getMethodTD(name)方法,取得真正要执行的方法并执行(传入的参数类型为TDServletWrapper ).
2 取得 方法执行的 结果 (返回结果类型为 String ).
3 根据这个返回的String, 创建ActionForward对象,并返回
但是我们还有一个目的是"兼容",所以最后确定的流程是
1 调用 getMethod(name)方法,取得真正要执行的方法,如果取得,则按原方式继续.
2 如果没有取得 调用 getMethodTD(name)方法,取得真正要执行的方法,若取得则执行.
3 根据返回结果的类型不同 做不同的操作.
这样做完后,我们的action就可以支持下面的任何一种类型的方法了:
下面简单说一下 TDServletWrapper .
这个类实际上就是封装了 ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response,
同时提供了一些用来简化开发的方法,例如
public String getParameter(String key,String ifNull);
public Integer getIntegerParameter(String key);
public void bind(Object bean);
等等.
不再具体叙述,看一下代码就应该都明白了.
TDServletWrapper 是一接口,他有两个实现:
TDServletWrapperTestImpl 为测试专用的,是一个与web容器无关的实现.
他主要就是利用"模拟"request response的方式来处理
目前他的实现还不是很完全(例如没有模拟session等),大家可以根据自己的需求来补充.
大家也可以根据这个原理 不用TDServletWrapper ,而完全的使用Map等,
总之,通过dispatchMethod的改造,几乎可以实现你全部的合理的想法(别超出Struts1的能力极限就行),我在这里提供的只是一个思路而已.
经过上面的改造,一个可测试的action就诞生了:
测试的可以这样写:
至此全部改造完毕.
这样的改造对于大家来说也许没什么意义,不过多少也是一种尝试.
由于Struts1.X(>=1.2)的 局限性,以及我个人能力的局限性,很多改造还不够彻底 不够合理,
对于前者我无能为力,对于后者,还恳请大家多多指正我的不足 谢谢了先.
上次发了一篇对 spring jdbctemplate的改造,这次又发了一篇对 struts 1 的改造,
(其实我那个ecside 也是对老版extremecomponents的改造)
也许很多人会觉得我太落伍了,这些老掉牙的东西还改造个什么劲儿啊 呵呵
其实,很多时候,对于我来说,改造就是一个智力游戏,在一些现有的东西实现一些自己的新的想法,这样的感觉总是快乐的.
而且,我们的项目就是用的老技术 老东西,在不能换新东西的情况下,努力的挖掘现有东西的剩余价值,也许更具有实际意义.
:D
为什么要用struts2?
struts2还真的很好吗?它还会像struts1一样,火热流行起来吗?
说什么,都是假的,拭目以待吧~
现在java真的是缺少一个足够优秀的web mvc框架.
曾经最辉煌过的struts1.x,只不过是机遇好,以至于长期以来压过了相对更优秀的webwork.
不管怎么说struts1.x还辉煌过.
看不出struts2有什么前景.
看贴不认真,口头批评一下。
目的就是让 Controller 可以脱离web容器单独进行单元测试.
大多数采用的方法都是使 Controller 中的方法的参数 和 返回值 与 j2ee特有的类(如HttpXXXX)无关.
例如 传入的 是若干个 HashMap ,返回的是纯的字符串.
这样在单元测试的时候,只要new一个Controller,准备一些装有测试数据的Map,
然后执行相关的Controller方法,再然后看看返回值,就可以了.
显然,流行的Struts 1.X (>=1.2) 是不具备这样的特性的.
如果您现在有一个遗留的使用Struts 1.X(>=1.2) 的系统,或者因为人力资源的原因,不能立即引入ww或Struts2.x,
那么如何让您的Action类似的可测性了呢(其实除了可测试性,这样的改进往往也会大大的减少代码的开发量).
下面我就把我的一些心得写出来,和大家一起分享,欢迎大家拍砖.
注意:以下讨论均以改造 DispatchAction 为例(不使用DispatchAction的情况应该比较少吧 呵呵).
先说明一下改造的目的:
简化开发,减少代码量
增强单元测试能力
全面兼容现有DispatchAction(这点很重要)
一个传统的 DispatchAction 代码结构
public class MyClassicAction extends DispatchAction { // 一个添加user的操作 public ActionForward addUser(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 1 取得参数 ... // 2 执行相关的BO DAO方法 // 3 取得执行后的返回值 if (添加成功) { return mapping.findForward("Succee"); } return mapping.findForward("Fail"); // 还有一种情况是 返回 new ActionForward(....). } }
对于上面的代码大家再熟悉不过了,我们现在要做的事情就是通过改造,让上面的action方法变成下面的样子.
// 一个添加user的操作 public String addUser( 传入与web容器无关的参数 ) throws Exception { // 1 取得参数 ... // 2 执行相关的BO DAO方法 // 3 取得执行后的返回值 if (添加成功) { return "Succee"; } return "Fail"; // 对于action中返回 new ActionForward(....).的情况,我们可以设定另外一种特殊的前缀. // 例如 return "NEW:/addUserFail.jsp"; }
上面的代码是一个最终的目标,我们先一步一步来.
首先这种改造我们一定要从 Struts 提供的 DispatchAction 做起.
总体思路很明显:
自己写个类 继承 DispatchAction ,并且添加或修改一些方法, 然后项目中的其他的DispatchAction都继承这个自己写的DispatchAction类.
简单说一下Struts 的 DispatchAction的工作流程.
首先 它也是一个action,所以请求来了 他会自动去执行execute方法
execute方法内部做一些操作后,会调用 dispatchMethod 方法
dispatchMethod方法会,调用getMethod方法 来取得欲执行的方法,并且执行之
改造的核心就是围绕最关键的dispatchMethod方法.
而由于我们要"全面兼容现有DispatchAction",所以对于getMethod我们不做修改,而是选择增加一个类似的方法 getMethodTD
首先写一个新的 .DispatchAction基类,他继承org.apache.struts.actions.DispatchAction.
public class TDDispatchAction extends DispatchAction { protected Class[] typesTD = {TDServletWrapper.class }; protected final static String TD_METHODCACHE_PREFIX="TD_METHODCACHE_PREFIX"; protected final static String TD_DEFAULT_METHOD="defaultMethod"; protected final static String TD_NEW_FORWARD_PREFIX="NEW:"; protected Method getMethodTD(String name) throws NoSuchMethodException { String cacheKey=TD_METHODCACHE_PREFIX+name; synchronized (methods) { Method method = (Method) methods.get(cacheKey); if (method == null) { method = clazz.getMethod(name, typesTD); methods.put(cacheKey, method); } return (method); } } // 对unspecified这个方法的扩展实际上与本次讨论无关,只是为我们框架加的一个小功能 // 提供一个默认的方法.也就是说,如果您的action中,有名为 defaultMethod 的方法,那么无需在请求的参数中加入相关信息,就会自动执行. protected ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return dispatchMethod(mapping, form, request, response, TD_DEFAULT_METHOD); } protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String name) throws Exception { // 后面再说 } }
首先来看一下这个 getMethodTD 方法.
原getMethod(String name)方法的作用是:
取得一个名字为name,参数类型为 ActionMapping , ActionForm , HttpServletRequest ,HttpServletResponse 的一个方法.
而这个新写的 getMethodTD 方法的作用是:
取得一个名字为name,参数类型为 TDServletWrapper 的一个方法.
这个大家和 原getMethod一对比就能看出来作用和差异了,注意那个cacheKey=TD_METHODCACHE_PREFIX+name,这个是必须的,不能直接用name做key.
其中这个 TDServletWrapper 就是封装的一个"可以"与web容器脱离的对象,注意,这里用的是可以.而不是直接就脱离了.
对此后面再做解释.
要添加的 getMethodTD 方法添加完了.
下面来看一下重点 改造 dispatchMethod方法:
原dispatchMethod方法的流程其实很简单:
1 调用 getMethod(name)方法,取得真正要执行的方法 并执行(传入的参数类型为 ActionMapping , ActionForm , HttpServletRequest ,HttpServletResponse ).
2 返回 方法执行的 结果 (返回结果类型为 ActionForward ).
改造后的目的是:
1 调用 getMethodTD(name)方法,取得真正要执行的方法并执行(传入的参数类型为TDServletWrapper ).
2 取得 方法执行的 结果 (返回结果类型为 String ).
3 根据这个返回的String, 创建ActionForward对象,并返回
但是我们还有一个目的是"兼容",所以最后确定的流程是
1 调用 getMethod(name)方法,取得真正要执行的方法,如果取得,则按原方式继续.
2 如果没有取得 调用 getMethodTD(name)方法,取得真正要执行的方法,若取得则执行.
3 根据返回结果的类型不同 做不同的操作.
// 改造的 dispatchMethod方法,重点看 //TD...字样所在的代码段 protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String name) throws Exception { if (name == null) { return this.unspecified(mapping, form, request, response); } Method method = null; //TD: Modified by Wei Zijun boolean useTDMethod=false; try { // 按传统方式取 action方法 method = getMethod(name); } catch (NoSuchMethodException ex) { try { // 没取到的话 再按新方式取 action方法 method = getMethodTD(name); // 标识一下到底是使用的原始方法 还是新方法 useTDMethod=true; } catch (NoSuchMethodException e) { String message = messages.getMessage("dispatch.method", mapping.getPath(), name); log.error(message, e); String userMsg = messages.getMessage("dispatch.method.user", mapping.getPath()); throw new NoSuchMethodException(userMsg); } } ActionForward forward = null; try { //TD: Modified by Wei Zijun Object forwardR=null; if (!useTDMethod){ // 如果是原始 action 方法 Object[] args = { mapping, form, request, response }; forwardR= method.invoke(this, args); }else{ // 如果是新 action 方法 // TDServletWrapperFactory.getInstance创建一个封装的对象 Object[] args = { TDServletWrapperFactory.getInstance(mapping, form,request, response) }; forwardR= method.invoke(this, args); } if (forwardR!=null){ if (forwardR instanceof ActionForward){ forward=(ActionForward)forwardR; }else{ // 如果返回值是字符串: // 以 TD_NEW_FORWARD_PREFIX("NEW:")开头,则new ActionForward; // 否则 调用 mapping.findForward. if ( (String.valueOf(forwardR) ).toUpperCase().startsWith(TD_NEW_FORWARD_PREFIX)){ forward = new ActionForward(String.valueOf(forwardR).substring(TD_NEW_FORWARD_PREFIX.length()) ); }else{ forward = mapping.findForward(String.valueOf(forwardR)); } } } } catch (ClassCastException e) { String message = messages.getMessage("dispatch.return", mapping.getPath(), name); log.error(message, e); throw e; } catch (IllegalAccessException e) { String message = messages.getMessage("dispatch.error", mapping.getPath(), name); log.error(message, e); throw e; } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof Exception) { throw ((Exception) t); } else { String message = messages.getMessage("dispatch.error", mapping.getPath(), name); log.error(message, e); throw new ServletException(t); } } return (forward); }
这样做完后,我们的action就可以支持下面的任何一种类型的方法了:
// 传统方式 public ActionForward testSubmit(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception; // 新方式 public String testSubmit1(TDServletWrapper servletWrapper) throws Exception; // 以下两者是则中方式. public String testSubmit2(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception; public ActionForward testSubmit3(TDServletWrapper servletWrapper) throws Exception;
下面简单说一下 TDServletWrapper .
这个类实际上就是封装了 ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response,
同时提供了一些用来简化开发的方法,例如
public String getParameter(String key,String ifNull);
public Integer getIntegerParameter(String key);
public void bind(Object bean);
等等.
不再具体叙述,看一下代码就应该都明白了.
TDServletWrapper 是一接口,他有两个实现:
TDServletWrapperTestImpl 为测试专用的,是一个与web容器无关的实现.
他主要就是利用"模拟"request response的方式来处理
目前他的实现还不是很完全(例如没有模拟session等),大家可以根据自己的需求来补充.
大家也可以根据这个原理 不用TDServletWrapper ,而完全的使用Map等,
总之,通过dispatchMethod的改造,几乎可以实现你全部的合理的想法(别超出Struts1的能力极限就行),我在这里提供的只是一个思路而已.
经过上面的改造,一个可测试的action就诞生了:
public class MyClassicAction extends TDDispatchAction { // 一个添加user的操作 public ActionForward addUser(TDServletWrapper servletWrapper) throws Exception { UserInfoVO vo=new UserInfoVO(); servletWrapper.bind(vo); // 校验,并执行相关DAO操作 if ( 添加成功 ) { return "Succee"; } return "Fail"; } }
测试的可以这样写:
public static void testAddUser() throws Exception { // 创建一个action对象 TestAction test=new TestAction(); //准备一些测试数据 放入map里,模仿request的Parameters Map requestParameters=new HashMap(); requestParameters.put("userName", "asdqe"); requestParameters.put("password", "mghjghj"); requestParameters.put("userRole", "1"); requestParameters.put("email", "ut_email"); requestParameters.put("gender", "1"); requestParameters.put("age", "22"); // TDServletWrapperFactory.getTestInstance 方法用来取得一个脱离web容器的 TDServletWrapper对象 ) Assert.isTrue("Sucess".equals(test.testSubmit1(TDServletWrapperFactory.getTestInstance(requestParameters))) ); }
至此全部改造完毕.
这样的改造对于大家来说也许没什么意义,不过多少也是一种尝试.
由于Struts1.X(>=1.2)的 局限性,以及我个人能力的局限性,很多改造还不够彻底 不够合理,
对于前者我无能为力,对于后者,还恳请大家多多指正我的不足 谢谢了先.
上次发了一篇对 spring jdbctemplate的改造,这次又发了一篇对 struts 1 的改造,
(其实我那个ecside 也是对老版extremecomponents的改造)
也许很多人会觉得我太落伍了,这些老掉牙的东西还改造个什么劲儿啊 呵呵
其实,很多时候,对于我来说,改造就是一个智力游戏,在一些现有的东西实现一些自己的新的想法,这样的感觉总是快乐的.
而且,我们的项目就是用的老技术 老东西,在不能换新东西的情况下,努力的挖掘现有东西的剩余价值,也许更具有实际意义.
:D
- action.rar (4.7 KB)
- 描述: 源码,但是不包含示例代码
- 下载次数: 207
评论
20 楼
heimu
2008-06-08
两年前还没2的时候做过相似的事情,直接重写处理分发请求的TilesRequestProcessor
19 楼
spiritfrog
2008-06-08
现在看起来fins的这篇struts1的改造还是颇有意义的:
丢弃了requset和response,form, action变得能够摆脱web容器被单元测试
谢谢了,对我的启发和帮助都很大。
丢弃了requset和response,form, action变得能够摆脱web容器被单元测试
谢谢了,对我的启发和帮助都很大。
18 楼
supttkl
2008-04-14
如Struts不是用form验证,和validate验证。那么form就是冗余的!
form.getUser();=request.getParemeter("user");
那么可以封装一个DynaForm来简单的封装下request
public class DynaForm{
private HttpServletRequest request;
public DynaForm(HttpServletRequest request){
this.request=request;
}
public getString(String name){
return request.getParemeter(name);
}
getInt
getDate
.......
}
form.getUser();=request.getParemeter("user");
那么可以封装一个DynaForm来简单的封装下request
public class DynaForm{
private HttpServletRequest request;
public DynaForm(HttpServletRequest request){
this.request=request;
}
public getString(String name){
return request.getParemeter(name);
}
getInt
getDate
.......
}
17 楼
leeking
2007-09-27
挺麻烦啊看起来.
16 楼
anxingyu_1984
2007-09-26
有必要借鉴struts2
15 楼
williamy
2007-09-26
MVC能怎么样?搞不出什么花样的!
自己随便写个都比它好用,
要不是因为它名气大,我还不用它呢
自己随便写个都比它好用,
要不是因为它名气大,我还不用它呢
14 楼
ruderal
2007-09-26
传说中的Struts2不就是另一个版本的WebWork么?
既然你觉得WebWork相对更优秀,那前景就相对更光明咯..哈...
既然你觉得WebWork相对更优秀,那前景就相对更光明咯..哈...
13 楼
yyjn12
2007-09-05
bluemeteor 写道
Fins为啥不直接用ww2或者struts2?
为什么要用struts2?
struts2还真的很好吗?它还会像struts1一样,火热流行起来吗?
说什么,都是假的,拭目以待吧~
现在java真的是缺少一个足够优秀的web mvc框架.
曾经最辉煌过的struts1.x,只不过是机遇好,以至于长期以来压过了相对更优秀的webwork.
不管怎么说struts1.x还辉煌过.
看不出struts2有什么前景.
12 楼
flash
2007-09-05
bluemeteor 写道
Fins为啥不直接用ww2或者struts2?
看贴不认真,口头批评一下。
11 楼
bluemeteor
2007-09-04
Fins为啥不直接用ww2或者struts2?
10 楼
williamy
2007-09-04
粗看题目,很感兴趣,因为在下的框架就是struts1.2.4上修改的,不过本来就可以测试阿,能说明一下你的出发点不?
9 楼
downpour
2007-08-22
意义不如在Struts1中引入OGNL设值来的大。
8 楼
sam1982
2007-08-22
呵呵.我这阵子在帮公司改造一个项目,struts层的设计跟你类似.呵呵.我一直就觉得action的参数太分散了,就应该当做一个对象来对待.
7 楼
王牌海盗
2007-07-06
不错,学习了。能让初学者深入理解struts的原理。
6 楼
i_love_sc
2007-06-26
很不错。感谢楼主。
5 楼
fins
2007-06-25
其实大家也可以把这个看作一个 小实验
没必要去深究它的实际意义 因为也许他只对我们公司 我们部门有意义
这篇帖子写成这样,主要目的也是帮助新手明白了一下struts的dispatchaction的简单原理 呵呵 可以看作struts源码的一种解读
当然 仅限于初学者.
:D
没必要去深究它的实际意义 因为也许他只对我们公司 我们部门有意义
这篇帖子写成这样,主要目的也是帮助新手明白了一下struts的dispatchaction的简单原理 呵呵 可以看作struts源码的一种解读
当然 仅限于初学者.
:D
4 楼
fins
2007-06-25
恩 这也是在这样的公司的一个坏处
我们公司的框架就是 基于 struts spring的
但是使用的开发人员 几乎感觉不到他们的存在
自己写的代码里 很少能引入 struts spring的类
这样做有好处 也有坏处
我们公司的框架就是 基于 struts spring的
但是使用的开发人员 几乎感觉不到他们的存在
自己写的代码里 很少能引入 struts spring的类
这样做有好处 也有坏处
3 楼
realreal2000
2007-06-25
这样做对于新入门的人好处是容易上手,但是对于他的成长就不是很好,毕竟这样的参考书,就只有改写的人才有
2 楼
fins
2007-06-25
减少代码量 其实这个只是一部分
这个是根据我们框架的需求弄的
其实我们框架的dispatch里还做了好多事情呢
这个是根据我们框架的需求弄的
其实我们框架的dispatch里还做了好多事情呢
1 楼
insky
2007-06-25
弱弱问一句,这样做的目的是为了什么?仅仅为了单独进行单元测试?Struts是可以单元测试的啊 引入strutsTest包就可以,功能也都能满足需求啊
发表评论
-
一个商业公司如果要支持一个开源项目的话,它需要做哪些工作啊?
2009-12-07 16:55 4959一个商业公司如果要支持一个开源项目的话,它需要做哪些工作呢? ... -
如何让jxl (jexcelapi) 支持更多的数据
2009-01-08 23:52 4519jxl (jexcelapi) 一直是我比较喜欢的 java版 ... -
在java中"模拟" XMLHttpRequest
2008-11-03 12:17 13098这里所说的"模拟" 是指 : 在java中 ... -
利用google docs进行"轻量级过程管理".
2008-08-28 13:21 0利用google docs进行" ... -
[请教]jxl生成xls时,支持"合并"或"磁盘缓存"吗(导出大数据量时)
2008-07-28 09:37 6941jxl 由于其小巧 易用的特点, 逐渐已经取代了 POI-ex ... -
不错的国产开源免费的php框架: FleaPHP
2008-07-28 01:58 8521之前用他开发过一个小的网站 开发过程非常轻松愉快 体验也很好 ... -
GT-FrontController, 一个简陋的MVC控制器的设计思路
2008-07-06 23:53 2734在给GT-Grid做前后台结合的例子时, 为了"快速 ... -
h2database 普及系列一: 简介
2008-05-06 19:10 22124这不是一个新东西,但是 ... -
JSF 与 "我的伟大发明" ---- 关于B/S UI开发的胡言乱语
2008-04-10 14:25 14484这篇帖子后面的回复和 ... -
初看JSF后的胡言乱语
2008-04-10 09:31 4584最近看了一点jsf ---- 只 ... -
Help,如何在J2EE环境下使用Sqlite以及如何将sqlite打入war包
2008-03-27 09:46 3791需求是这样的 希望j2ee应用(基于应用 而不是整个服务器) ... -
请记住: i AM SoLiD. (关于View的事件触发顺序)
2007-11-16 04:11 2630View 提供了若干事件. 在渲染 布局 展现 相关事件的触 ... -
Android SDK下, 如何在程序中输出日志 以及如何查看日志.
2007-11-15 22:38 9846Android SDK下, 如何在程序中输出日志 以及如何查看 ... -
小胖加入Android Fans的 大军了 呵呵
2007-11-15 13:30 3146决定开始研究 Android 了. 以前研究过 j2me 对 ... -
老帖: findbugs简介
2007-11-02 10:09 3568这个时候说 findbugs ??? ... -
世上没有B/S系统,只有B系统和S系统.
2007-09-12 13:45 34368先说些与标题貌似无关的话. 随着prototype DWR ... -
[求助]有没有哪个缓存组件支持 基于访问频率的清理策略
2007-08-29 18:30 2407目前缓存清理策略几乎都是基于 存活期 和 活跃期 还有缓存队列 ... -
[发布2007-08-06]Ajax向导组件 WebWizard Component Beta1
2007-08-06 15:55 5000/****************************** ... -
寻求一个eclipse下更好的snippet插件(或代码模板管理插件 或代码生成器)
2007-07-26 11:12 4262eclipse自带一个snippet插件,但是功能有限. 只支 ... -
JProfiler与tomcat整合的视频演示
2007-06-20 12:16 8700这类东西看官方文档 或者google都能有答案 但是我最近为 ...
相关推荐
此外,培训不应被视为一种可有可无的活动,而应被视为一种投资,这种投资在短期内可能看不到直接的回报,但在长期内对企业文化的塑造、员工满意度的提升以及整体业务绩效的改善具有重大影响。 培训的有效性取决于多...
“小议”一词表明这篇文章是对张炉集扬水站自动化改造的深入讨论,可能是从专业角度出发,分析改造的必要性、方案设计、实施步骤以及预期效果。.rar文件格式通常用于压缩文档,这里包含的PDF文档很可能是详细的报告...
小议我国的价格听证制度-论文.zip
法治思想起源小议.docx
"数字电视存储技术小议.pdf" 数字电视存储技术小议.pdf 是一篇关于数字电视存储技术的文章,主要介绍了数字电视存储技术的发展历程、当前状态和未来趋势。文章首先介绍了数字电视存储技术的发展历程,指出数字电视...
该池在运行结束时会自动销毁所有`autorelease`对象,但仅调用`release`方法,若对象的引用计数大于1,则仍会导致内存泄露。 #### 总结 iOS内存管理的核心在于理解对象生命周期、引用计数机制以及自动释放池的使用...
小议关于农网升级改造工作动员会议.doc
基于信息化手段的设计说明教学小议.docx
#### 2001年:“二十世纪人向二十一世纪人的建言—小议__” - **考查知识点**:考查考生对未来社会发展趋势的预测能力和批判思维。 - **备考建议**:可以结合时代背景和个人理解,提出对未来社会建设的具体建议。 ...
在探讨张炉集扬水站自动化改造的文档中,我们可以看到对扬水站基本情况的介绍,包括其地理位置、主要设备、工作状态以及改造的目的。具体来说,扬水站位于聊城市东昌府区水务局下属的位山三干渠右岸,具备一定的技术...
Linux管理员密码的破解与防止破解的小议.docx
融合出版在人工智能教育中的实践探索小议.pdf
因此,它们不构成直接侵权,但因有机会知道或应当知道直接侵权行为的存在,且有能力删除侵权内容,故构成了对信息网络传播权的间接侵权。这种间接侵权责任的前提是用户的直接侵权行为,同时要求网站经营者有能力和...
它通过对分布在网络中的多种检索工具进行全局控制,实现了跨平台的搜索能力。 ### 二、元搜索引擎的工作原理 元搜索引擎的工作流程通常包括以下步骤: 1. **接收用户的查询请求**:用户在元搜索引擎的界面上输入...
网络文学的非物质劳动性主要体现在作品的生产和流通方式上,这一特性改变了传统文学的创作模式。网络文学作品的物质载体极少,主要以电子文档...这种变化不仅改变了文学创作的生态,也对整个文化产业产生了深远影响。
1. **基础扎实**:高中政治的基础知识包括概念、原理、关系和观点,这些都是构成整个学科体系的基石。复习时,必须逐字逐句阅读课本,包括前言、后记、正文和注解,确保没有遗漏任何知识点。对未理解或掌握不牢的...
因此,我国应当借鉴国际经验,将幼儿教育提升到国家战略的高度,加大对私立幼儿园的支持力度,建立健全相关的法规和标准,同时提供适当的政策扶持,促进私立幼儿园的规范和健康发展。 总结来说,私立幼儿园是我国...