`
yuanke
  • 浏览: 69705 次
  • 性别: Icon_minigender_2
  • 来自: 临沂
社区版块
存档分类
最新评论

学struts2有感

    博客分类:
  • J2EE
阅读更多
         看到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表达式。

   当然,在 文件上传,数据校验 等方面也 方便了好多。在这就不想谈了。

   一个比较优秀的 框架 可以 帮着 我们 更高效,稳定的开发 合格的产品,不过我们也不要 依赖框架,我们只要理解了思想,设计模式,我们可以自己扩展 功能,

不然 就要 永远让别人牵着走了! 

  

  
19
4
分享到:
评论
19 楼 treblesoftware 2009-08-03  
STRUTS2还是很好用,很简单的,把它有些鸡胁功能去掉之后,确实很简单。
18 楼 ranLoD 2009-08-02  
恰巧我最痛恨的就是struts自带标签怎么办了,<s:form>这一套一套背死个人呢
17 楼 yuanke 2009-07-31  
   是啊,说的不错,做实际中做项目 还是简单怎么来,有时候框架也就是个架子,ext在公司也做过,感觉是有点消耗内存,不过做出来界面挺酷的,呵呵!
16 楼 energykey 2009-07-31  
我只是没有把JS也封装了,因为平时开发封装到这个层次感觉已经很好用了,再说这里用到了AJAX,不想因为封装了YUI而太耦合。我现在用EXT的话把对应的CONNECT改成Ext.request{}即可。或者直接Ext.get("cityId").load(url);
struts2的标签太多,我都没来得及看完呢~,主要是现在用freemarker+ext了,很多你说的这种东西ext都有组件了。。。而且还有样式,,,。。。当然我不是又推销EXT来了,EXT太占网速了,,,没办法,公司有牛人要用啊,STRUTS2也是牛人选择的,呵呵,建议做WEB的还是别用。不过我自己接的外包项目都还是习惯用strtus1+jsp+jstl~

说了这么多,主要是这两天比较闲啦,~ struts也就一个控制器而已,在JAVAEE里核心的东西还是要看DAO层的,前面S1 S2都不要紧啦,用得好就行。关键还得看数据层~~ SPRING也就一个花架子。数据层会让你的系统崩溃,但我想表示层永远没这个可能。。。
15 楼 energykey 2009-07-31  
没有调查就没有发言权。

我特地去亲自体验了一番这个doubleselect。

我的测试代码:
JSP
 <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 class="wwFormTable">
    	<tr>
    <td class="tdLabel"><label for="x_author" class="label">请选择您的他ushu:</label></td>
    <td
>
<select name="author" 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??>
 class="${parameters.doubleCss?html}"<#rt/>
</#if>
<#if parameters.doubleStyle??>
 style="${parameters.doubleStyle?html}"<#rt/>
</#if>
<#if parameters.title??>
 title="${parameters.title?html}"<#rt/>
</#if>
<#if parameters.multiple?default(false)>
 multiple="multiple"<#rt/>
</#if>
<#if parameters.get("doubleSize")??>
 size="${parameters.get("doubleSize")?html}"<#rt/>
</#if>
<#if parameters.doubleMultiple?default(false)>
 multiple="multiple"<#rt/>
</#if> 
>
</select>
<script type="text/javascript">
<#assign itemCount = startCount/>
    var ${parameters.id}Group = new Array(${parameters.listSize} + ${startCount});
    for (i = 0; i < (${parameters.listSize} + ${startCount}); i++)
    ${parameters.id}Group[i] = new Array();

<@s.iterator value="parameters.list">
    <#if parameters.listKey??>
        <#assign itemKey = stack.findValue(parameters.listKey)/>
    <#else>
        <#assign itemKey = stack.findValue('top')/>
    </#if>
    <#if parameters.listValue??>
        <#assign itemValue = stack.findString(parameters.listValue)/>
    <#else>
        <#assign itemValue = stack.findString('top')/>
    </#if>
    <#assign doubleItemCount = 0/>
    <@s.iterator value="${parameters.doubleList}">
        <#if parameters.doubleListKey??>
            <#assign doubleItemKey = stack.findValue(parameters.doubleListKey)/>
        <#else>
            <#assign doubleItemKey = stack.findValue('top')/>
        </#if>
        <#assign doubleItemKeyStr = doubleItemKey.toString() />
        <#if parameters.doubleListValue??>
            <#assign doubleItemValue = stack.findString(parameters.doubleListValue)/>
        <#else>
            <#assign doubleItemValue = stack.findString('top')/>
        </#if>
    ${parameters.id}Group[${itemCount}][${doubleItemCount}] = new Option("${doubleItemValue}", "${doubleItemKeyStr}");

        <#assign doubleItemCount = doubleItemCount + 1/>
    </@s.iterator>
    <#assign itemCount = itemCount + 1/>
</@s.iterator>

    var ${parameters.id}Temp = document.${parameters.formName}.${parameters.doubleId};
<#assign itemCount = startCount/>
<#assign redirectTo = 0/>
<@s.iterator value="parameters.list">
    <#if parameters.listKey??>
        <#assign itemKey = stack.findValue(parameters.listKey)/>
    <#else>
        <#assign itemKey = stack.findValue('top')/>
    </#if>
    <#if tag.contains(parameters.nameValue, itemKey)>
        <#assign redirectTo = itemCount/>
    </#if>
    <#assign itemCount = itemCount + 1/>
</@s.iterator>
    ${parameters.id}Redirect(${redirectTo});
    function ${parameters.id}Redirect(x) {
    	var selected = false;
        for (m = ${parameters.id}Temp.options.length - 1; m >= 0; m--) {
            ${parameters.id}Temp.options[m] = null;
        }

        for (i = 0; i < ${parameters.id}Group[x].length; i++) {
            ${parameters.id}Temp.options[i] = new Option(${parameters.id}Group[x][i].text, ${parameters.id}Group[x][i].value);
            <#if parameters.doubleNameValue??>
            	if (${parameters.id}Temp.options[i].value == '${parameters.doubleNameValue}') {
            		${parameters.id}Temp.options[i].selected = true;
            		selected = true;
            	}
            </#if>
        }

        if ((${parameters.id}Temp.options.length > 0) && (! selected)) {
           	${parameters.id}Temp.options[0].selected = true;
        }
    }
</script>


这证实了我昨天的猜测,STRUTS2将所有数据一次加载进一个HashMap<String,List<String>>里,然后丢进valueStack,交给freemarker动态生成javascript,所以前台看到的效果都是javascript本地完成的,不存在 任何服务端交涉。对于小数据量的级联选择,用这个标签的确是很方便的~里面连JS都封装了,,,的确强大。
但大数据量的东西还是不要用这个了。

我昨天说的<site:option/>的标签,是我自己封装的一个jsp标签
源码如下:
public class HierInfoTag extends TagSupport {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(HierInfoTag.class);

	Long selectedValue;
	Long parentId;

	@Override
	public int doStartTag() throws JspException {
		return SKIP_BODY;
	}

	@Override
	public 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" class="font_1">省  份:                          </td>
                        <td width="17%" valign="middle" class="font_1">
						<select name="provinceId" onchange="[b]changeProvince(this);[/b]">
							<site:option selectedValue="${hierInfoConstants.SV_PROVINCE_ZJ}" parentId="${hierInfoConstants.SV_COUNTRY_CHINA}"  />
						</select>
						</td>
                        <td width="8%" valign="middle" class="font_1">城市: </td>
                        <td width="56%" valign="middle" class="font_1">
                        <select name="cityId">
                         <site:option parentId="${hierInfoConstants.SV_PROVINCE_ZJ}"  />
                        </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+"&timestamp="+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我想你得先花点功夫去研究他的源代码。
14 楼 yuanke 2009-07-30  
当然具体问题,具体分析,java类中 封装 可以 封装成 静态的,网页直接<s:include value="/*.jsp"/>,就可实现 重用性。虽然<site:option selectValue="1001" parentId="100"/>没有用过,绝不可能一句话实现联动,有些可疑性,要不你写个简单的例子吧?大家也好见识一下,学习一下!
  另外有些在head中加入<s:hread theme="ajax"/>就可以 把你用的标签显现ajax效果,我感觉datetimepicker的标签 也挺好用的,我用的版本没有取消,也许你太追潮流了吧!
   
   
  
13 楼 energykey 2009-07-30  
如果你用JSP,用STRUTS2的标签我没什么意见,里面确实封装了很多易用的功能,甚至有些JS才能实现的功能都呗封装了。但是我还是不提倡使用STRUTS2的标签,比如STRUTS2刚开始出来有一个datetimepicker的标签,到后来又取消掉了,你怎样选择?不更新struts2?放弃原来的标签,更新struts2?所以,即便要用,最好也用一些基本的,通用的。

但是你列出来的这个东西我想也有不妥的地方。

我不知道你说的这个标签具体怎么实现的,我也没用过,但从“在Course类中定义  Map<String,List<String>> courses= new HashMap<String,List<String>>(); ”
这句话可以看出,你是一次性全部加载到内存中的。

还是用JS实现比较妥当,你的这个数据量小还好说,如果有100个学科,每个学科下面有100个子项,就是100*100=1W项,这样的数据被加载到内存中,试想一下,每个REQUEST都会加载一次,那么1W个用户同时访问呢?当然实际情况1W个同时的可能性较小,能有个500差不多了,但如果这样的标签被滥用,有N个这样的标签存在【且不谈其他的标签】,恭喜你,你的服务器等着崩溃吧。。。

当然我不是有意来抨击你的哈。。。

我也不知道我理解你的意思没,你说的这个“连动”,我望文生义,应该就是比如选择省份然后显示该省份下对应的城市吧?如果不是这样,那就当我没说了~

框架的封装我觉得是针对大多数人,是不可能考虑到具体的需求的,说实话还不如自己根据项目需求写出JSP TAG来的方便呢,你说的这个以前我只要一个<site:option selectValue="1001" parentId="100"/>就解决了,而且是AJAX的。
12 楼 yuanke 2009-07-30  
   当然 这只是我的理解,难免有些不足,很高兴网友提出不同的见解。
    是啊,在开发中不同的人习惯不一样,在struts2标签上,也许用的不多,就感觉不出来 好用了,举个例子 <s:doubleselect/> ,给开发人员省去了不少力气
    实现连动n级:<s:form name="Login" action="Course.action">
     <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,就可以看出来是单线程的,这样安全性 和性能上相对差一些, 小公司有些软件可以不考虑要是做大了,使用框架前必须要考虑好的。
    当然 其他 的只是 我的理解,难免有些出入,就是 有些 有经验 的程序员,他们  在开发 中 知识点 也不可能全部掌握, 代码 或者框架没有 决定性的好与坏,只是  合适 与 更 合适 吧了,站的角度 不同,观点也不同,希望 大家 能 站在软件需求的角度看问题,这样我们 才会 把软件 做的更出色!
   
11 楼 energykey 2009-07-30  
sunnymoon 写道
JSTL是官方标准,不依整于具体框架。

强烈同意。。。!!!我向来不用框架提供的标签。JSTL基本上都够用了。

我现在也在用STRUTS2,也用到了FTL,但是说实话,好处也有,坏处也有。楼主写的东西都太飘渺了,你这几句话随便找本书上面都写得有。

一看就是没有真正去理解,对比。

“从体系结构来看:struts2大量使用拦截器来出来请求,从而允许与 业务逻辑控制器 与 servlet-api分离,避免了侵入性;而struts1.x 在action中明显的侵入了servlet-api. ”
--这个估计你是看书的吧,这个的根本好处是什么?其实就是一点,方便了测试,测试不用外卖启动WEB容器加断点,我问问大家,实际开发过程中有多少人会去写测试?我想还是用LOG4J的人比较多吧?出了状况一看LOG便知道。。。



“从线程安全分析:struts2.x是线程安全的,每一个对象产生一个实例,避免了线程安全问题;而struts1.x在action中属于单线程。 ”
--你真正理解这句话的含义了?

“性能方面:struts2.x测试可以脱离web容器,而struts1.x依赖servlet-api,测试需要依赖web容器。 ”
--这个跟性能有什么关系,理论上来讲,脱离依赖的确是个好事情,但开发过程中我还是会经常用到一些SERVLET-API,,这其实也有不方便的,比如,struts1.x里action其实就是个servlet,我在前端用ajax访问一个action的某方法,然后通过response.getwriter().write(0)表示失败,write(1)表示成功,或者直接write message.
但struts2就没这么方便,要返回数据给AJAX,只有通过JSON的方式实现,这么说了,我现在也基本习惯了,也有好处,比如可能返回许多序列的数据,那么这种情况用response就很麻烦了。。。用JSON的话,前面只要解析一下就生成JS对象了。。

“请求参数封装对比:struts2.x使用ModelDriven模式,这样我们 直接 封装model对象,无需要继承任何struts2的基类,避免了侵入性。 ”
--这个有个很烦的地方,就是你没有给字段赋值或者请求参数种不存在某些字段,LOG就会不断的打印could not find property...方便是方便了,但看LOG就知道,每一个请求都会默认所有字段进行类型转换然后赋值,有些时候我只要一个ID的值而已,性能上绝对浪费。
而struts1.x可以利用spring提供的RequestUtil.populate(bean)方法自动的将请求参数封装进一个POJO,多么方便,然后把这个POJO直接丢进业务层。我从来都没有用过FORM,所以不存在书本上所书的什么FORM冗余。。。但综合考虑来讲,还是STRUTS2的好一点,你要记住框架都是先为了开发方便,任何框架都会牺牲性能,最好的方式就是直接写底层代码,用JDBC,性能绝对OK。比如你用个HIBERNATE,如果不做优化,性能绝对大幅下降的。


“标签。。。”,这个前面已经说了,我到现在还没用到什么标签,现在用FTL,前台要说明,后台就丢什么,不需要什么标签。逻辑最大化从页面脱离到代码。

文件上传,,,也就是封装了一个commons-upload,这个我相信做多了的朋友自己也应该写过封装了吧?

“个比较优秀的 框架 可以 帮着 我们 更高效,稳定的开发 合格的产品,不过我们也不要 依赖框架,我们只要理解了思想,设计模式,我们可以自己扩展 功能, ”

--这句话说的还不错。扩展功能其实就是依赖框架了,没有框架你的这些扩展还有用么?不可能什么都不依赖的,像我以前写的JSP TAG,现在用FTL了,不久没用了么,,,。。。

10 楼 ykyeah 2009-07-30  
说的好是好,可是要是能弄一个例子出来就更好了
9 楼 myseo 2009-07-29  
从线程安全分析:struts2.x是线程安全的,每一个对象产生一个实例,避免了线程安全问题;而struts1.x在action中属于单线程
===========
。。。。是单实例 NO单线程,LZ
8 楼 treblesoftware 2009-07-29  
总结的好!学习了。
7 楼 lucky16 2009-07-29  
现在学的是struts1.2
过段时间就可以转webwork了!
6 楼 kevin.du 2009-07-28  
最近也在学习struts2  但是没有博主学得这么有深度   对struts的核心interceptor尤其理解不了
5 楼 King.Arthur 2009-07-28  
什么是单线程哦
4 楼 sunnymoon 2009-07-28  
JSTL是官方标准,不依整于具体框架。
3 楼 soft901 2009-07-28  
OGNL是非常强大,强大的有点不知所措.
2 楼 jansel 2009-07-28  
标签的优势:标签库几乎可以完全替代JSTL的标签库,并且 struts2.x支持 强大的ognl表达式


Struts2的标签优势嘛,有!逻辑标签很好用。不知道LZ有没有使用过UI标签,试一下吧。
1 楼 grape927 2009-07-27  
之前用的是struts1.2,之后先自学Webwork2.X,再学struts2.X觉得很容易!

相关推荐

Global site tag (gtag.js) - Google Analytics