学struts2有感
看到struts2.x,原以为是struts1x的改版,学习了struts2.x才知道,它是webWork的更新版本,核心就是webWork,webWork是另一个opensymphony开发组织,也挺优秀的,感觉struts2.x比起struts1.x优秀多了,只是struts1.x出现的比较早,所以用struts1.x开发的还比较多,一时难以接收。
struts2.x相比struts1.x的优势:
从体系结构来看:struts2大量使用拦截器来出来请求,从而允许与 业务逻辑控制器 与 servlet-api分离,避免了侵入性;而struts1.x 在action中明显的侵入了servlet-api.
从线程安全分析:struts2.x是线程安全的,每一个对象产生一个实例,避免了线程安全问题;而struts1.x在action中属于单线程。
性能方面:struts2.x测试可以脱离web容器,而struts1.x依赖servlet-api,测试需要依赖web容器。
请求参数封装对比:struts2.x使用ModelDriven模式,这样我们 直接 封装model对象,无需要继承任何struts2的基类,避免了侵入性。
标签的优势:标签库几乎可以完全替代JSTL的标签库,并且 struts2.x支持 强大的ognl表达式。
当然,在 文件上传,数据校验 等方面也 方便了好多。在这就不想谈了。
一个比较优秀的 框架 可以 帮着 我们 更高效,稳定的开发 合格的产品,不过我们也不要 依赖框架,我们只要理解了思想,设计模式,我们可以自己扩展 功能,
不然 就要 永远让别人牵着走了!
<s:bean id="course" name="com.frank.utils.Course"/>
<s:doubleselect list="#course.courses.keySet()"
doubleName="学科"
doubleList='#course.courses[top]'
label="学科列表" />
</s:form>
在Course类中定义 Map<String,List<String>> courses= new HashMap<String,List<String>>();
设置好 就可以 实现连动了,以前做项目 用javascript连动 确实有些麻烦,感觉现在简化了好多。
我从体系结构 谈到 侵入性,是从架构设计模式的角度来说的。大家有兴趣可以看一下 有关设计模式的书籍,当然工作中也不要 为了设计模式 而开发,最主要的就是在规定时间里完成 任务优先。
从struts1.x的源代码 处理action中有一个synchronized,就可以看出来是单线程的,这样安全性 和性能上相对差一些, 小公司有些软件可以不考虑要是做大了,使用框架前必须要考虑好的。
当然 其他 的只是 我的理解,难免有些出入,就是 有些 有经验 的程序员,他们 在开发 中 知识点 也不可能全部掌握, 代码 或者框架没有 决定性的好与坏,只是 合适 与 更 合适 吧了,站的角度 不同,观点也不同,希望 大家 能 站在软件需求的角度看问题,这样我们 才会 把软件 做的更出色!
另外有些在head中加入<s:hread theme="ajax"/>就可以 把你用的标签显现ajax效果,我感觉datetimepicker的标签 也挺好用的,我用的版本没有取消,也许你太追潮流了吧!
<s:set name="bs" value="#{'a':{'1','2','3'},'b':{'4','5','6'},'c':{'7','8','9'}}"></s:set> <s:form name="myform" action="x"> <s:doubleselect label="请选择您的他ushu" name="author" list="#bs.keySet()" doubleList="#bs[top]" doubleName="book" /> </s:form>
查看HTML源文件:
<form id="x" name="myform" action="x" method="post"><table id="x_author" onchange="x_authorRedirect(this.options.selectedIndex)"> <option value="a">a</option> <option value="b">b</option> <option value="c">c</option></select><br /><select name="book" id="x_book"></select><script type="text/javascript"> var x_authorGroup = new Array(3 + 0); for (i = 0; i < (3 + 0); i++) x_authorGroup[i] = new Array(); x_authorGroup[0][0] = new Option("1", "1"); x_authorGroup[0][1] = new Option("2", "2"); x_authorGroup[0][2] = new Option("3", "3"); x_authorGroup[1][0] = new Option("4", "4"); x_authorGroup[1][1] = new Option("5", "5"); x_authorGroup[1][2] = new Option("6", "6"); x_authorGroup[2][0] = new Option("7", "7"); x_authorGroup[2][1] = new Option("8", "8"); x_authorGroup[2][2] = new Option("9", "9"); var x_authorTemp = document.myform.x_book; x_authorRedirect(0); function x_authorRedirect(x) { var selected = false; for (m = x_authorTemp.options.length - 1; m >= 0; m--) { x_authorTemp.options[m] = null; } for (i = 0; i < x_authorGroup[x].length; i++) { x_authorTemp.options[i] = new Option(x_authorGroup[x][i].text, x_authorGroup[x][i].value); } if ((x_authorTemp.options.length > 0) && (! selected)) { x_authorTemp.options[0].selected = true; } }</script> </td></tr> </table></form>然后去看了一下struts-tags.tld找到org.apache.struts2.views.jsp.ui.DoubleSelectTag
看了一路的源代码,STRUTS2是预先定义了一个doubleselect.ftl的东西
代码如下:
<#include "/${parameters.templateDir}/simple/select.ftl" /><#assign startCount = 0/><#if parameters.headerKey?? && parameters.headerValue??> <#assign startCount = startCount + 1/></#if><#if parameters.emptyOption??> <#assign startCount = startCount + 1/></#if><br /><select<#rt/> name="${parameters.doubleName?default("")?html}"<#rt/><#if parameters.disabled?default(false)> disabled="disabled"<#rt/></#if><#if parameters.doubleTabindex??> tabindex="${parameters.doubleTabindex?html}"<#rt/></#if><#if parameters.doubleId??> id="${parameters.doubleId?html}"<#rt/></#if><#if parameters.doubleCss??> name="code">public class HierInfoTag extends TagSupport {/** * Logger for this class */private static final Logger logger = Logger.getLogger(HierInfoTag.class);Long selectedValue;Long parentId;@Overridepublic int doStartTag() throws JspException {return SKIP_BODY;}@Overridepublic int doEndTag() throws JspException {String html = "";SysHierInfo info = HierInfoService.findHierInfo(parentId);for (Iterator iter = info.getChildren().iterator(); iter.hasNext();) {SysHierInfo child = (SysHierInfo) iter.next();html += "<option value='" + child.getId() + "'";if (selectedValue != null&& selectedValue.equals(child.getId()))html += " selected ";html += ">" + child.getName() + "</option>";}try {this.pageContext.getOut().write(html.toString());} catch (IOException e) {logger.error("tag HierInfoTag error", e);}return EVAL_PAGE;}public void setSelectedValue(Long selectedValue) {this.selectedValue = selectedValue;}public void setParentId(Long parentId) {this.parentId = parentId;}}使用方法:
<tr> <td height="30" valign="middle" valign="middle" onchange="[b]changeProvince(this);[/b]"><site:option selectedValue="${hierInfoConstants.SV_PROVINCE_ZJ}" parentId="${hierInfoConstants.SV_COUNTRY_CHINA}" /></select></td> <td width="8%" valign="middle" valign="middle" /> </select></td> </tr>AJAX[使用了YUI]:
function changeProvince(el){var provinceId = el.options[el.options.selectedIndex].value;var uri = "<c:url value="/utils.do?m=cities&provinceId="/>"+provinceId+"×tamp="+new Date().toString();Connect.asyncRequest("GET",uri,{success:function(o){Dom.getAncestorByTagName(document.forms.reg.cityId,"td").innerHTML = "<select name='cityId'>"+o.responseText+"</select>";},failure : function(o) {},argument :null});}我并不觉得我的东西很复杂,想法,重用性已经很高,JS只需要拷贝改变一下变量名和URL即可。同样的,我还封装了生成CHECKBOX的标签,就不列举代码了。这样的封装,我甚至可以封装除2级、3级、4级的级联选择,但如果你选去拓展STRUTS2的doubleselect我想你得先花点功夫去研究他的源代码。 struts也就一个控制器而已,在JAVAEE里核心的东西还是要看DAO层的,前面S1 S2都不要紧啦,用得好就行。关键还得看数据层~~ SPRING也就一个花架子。数据层会让你的系统崩溃,但我想表示层永远没这个可能。。。 17 楼 yuanke 2009-07-31 是啊,说的不错,做实际中做项目 还是简单怎么来,有时候框架也就是个架子,ext在公司也做过,感觉是有点消耗内存,不过做出来界面挺酷的,呵呵! 18 楼 ranLoD 2009-08-02 恰巧我最痛恨的就是struts自带标签怎么办了,<s:form>这一套一套背死个人呢 19 楼 treblesoftware 2009-08-03 STRUTS2还是很好用,很简单的,把它有些鸡胁功能去掉之后,确实很简单。