??xml version="1.0" encoding="utf-8" standalone="yes"?>97久久超碰,99只有精品,51精品久久久久久久蜜臀 http://www.aygfsteel.com/conans/category/32511.html你越挣扎我就兴?/description>zh-cn Sun, 09 Aug 2009 23:11:08 GMT Sun, 09 Aug 2009 23:11:08 GMT 60 Struts2采用convention-plugin实现雉|?/title> http://www.aygfsteel.com/conans/articles/289508.htmlCONAN CONAN Sun, 02 Aug 2009 14:28:00 GMT http://www.aygfsteel.com/conans/articles/289508.html 最q开始关注struts2的新Ҏ,从这个版本开始,Struts开始用convention-plugin代替codebehind-plugin来实现struts的零配置?br />
配置文g_了,的确是简便了开发过E,但是Q我们熟悉的配置H然disappear了,真是一下很不适应。跟着潮流走吧Q看看该怎样来搞定convention-plugin?br />
使用Convention插gQ你需要将其JAR文g攑ֈ你应用的WEB-INF/lib目录中,你也可以在你Maven目的POM文g中添加下面包依赖
< dependency >
< groupId > org.apache.struts </ groupId >
< artifactId > struts2-convention-plugin </ artifactId >
< version > 2.1.6 </ version >
</ dependency >
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>2.1.6</version>
</dependency>
雉|ƈ不是没有配置Q而是通过U定大于配置的方式,大量通过U定来调度页面的跌{而得配|大大减。所以,首先应该了解下convention-plugin的约定:
1.
默认所有的l果面都存储在WEB-INF/content下,你可以通过讄struts.convention.result.pathq个属性的值来改变到其他\径。如Q?/p>
< constant name = "struts.convention.result.path" value = "/WEB-INF/page" />
<constant name="struts.convention.result.path" value="/WEB-INF/page" />
则将路径配置CWEB-INF/page 下?br />
2.
默认包\径包含action,actions,struts,struts2的所有包都会被struts作ؓ含有Actioncȝ路径来搜索。你可以通过讄struts.convention.package.locators属性来修改q个配置。如Q?/p>
< constant name = "struts.convention.package.locators" value = "web,action" />
<constant name="struts.convention.package.locators" value="web,action" />
则定义了在项目中Q包路径包含web和action的将被视为Action存在的\径来q行搜烦?br />
Com.ustb.web.*/com.ustb.action.*都将被视为含有Action的包路径而被搜烦?br />
3.
接着QConvention从前一步找到的package以及其子package中寻?com.opensymphony.xwork2.Action
的实C及以Actionl尾的类Q?/p>
com.example.actions.MainAction
com.example.actions.products.Display ( implements com.opensymphony.xwork2.Action)
com.example.struts.company.details.ShowCompanyDetailsAction
com.example.actions.MainAction
com.example.actions.products.Display (implements com.opensymphony.xwork2.Action)
com.example.struts.company.details.ShowCompanyDetailsAction
4.
命名I间。从定义?package.locators标示开始到包结束的部分Q就是命名空间。D个例子:
Com.ustb.web.user.userAction的命名空间是Q?#8221;/user”。Com.ustb.web.user.detail.UserAction的命名空间是Q?#8221;/user/detail”
5.
Convention通过如下规则定URL的具体资源部?Lcd的Action部分。然后将每个分部的首字母{为小写,?#8217;-’分割Q你可以讄struts.convention.action.name.separator
?/p>
< constant name = "struts.convention.action.name.separator" value = "-" />
<constant name="struts.convention.action.name.separator" value="-" />
q是举个例子Q?br />
UserAction->user UserDetailAction
->user-detail。结合上面的。对于com.ustb.web.user.detail.UserDetailActionQ映的url是/WEB-INF/content/user/detail/user-detail.jsp
6.
struts支持.jsp .html .htm
.vm格式的文件?br />
下面是actiong和结果模版的映射关系Q?strong>
URL
Result
File that could match
Result Type
/hello
success
/WEB-INF/content/hello.jsp
Dispatcher
/hello
success
/WEB-INF/content/hello-success.htm
Dispatcher
/hello
success
/WEB-INF/content/hello.ftl
FreeMarker
/hello-world
input
/WEB-INF/content/hello-world-input.vm
Velocity
/test1/test2/hello
error
/WEB-INF/content/test/test2/hello-error.html
Dispatcher
以上的内Ҏ自struts2的文?a target="_blank">http://struts.apache.org/2.1.6/docs/convention-plugin.html
当然Q简单的通过默认的方式来q行配置不能完全满实际目的需要。所q,convention的零配置是非常灵zȝ?br />
通过@Action注释
对如下例子:
package com.example.web;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport {
@Action ( "action1" )
public String method1() {
return SUCCESS;
}
@Action ( "/user/action2" )
public String method2() {
return SUCCESS;
}
}
package com.example.web;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport {
@Action("action1")
public String method1() {
return SUCCESS;
}
@Action("/user/action2")
public String method2() {
return SUCCESS;
}
}
Ҏ?/strong>
默认调用路径
默认映射路径
method1
/hello!method1.action .
/WEB-INF/content/hello.jsp
method2
/hello!method2.action.
/WEB-INF/content/hello.jsp
通过@Action注释?/span>
Ҏ?/strong>
@Action注释后调用\?/strong>
@Action注释 后映\?/strong>
method1
/action1!method1.action.
/WEB-INF/content/action1.jsp
method1
/user/action2!method2.action
/WEB-INF/content/user/action2.jsp
通过@Actions注释
package com.example.web;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
public class HelloAction extends ActionSupport {
@Actions ({
@Action ( "/different/url" ),
@Action ( "/another/url" )
})
public String method1() {
return “error”;
}
package com.example.web;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
public class HelloAction extends ActionSupport {
@Actions({
@Action("/different/url"),
@Action("/another/url")
})
public String method1() {
return “error”;
}
我们可以通过Q?span style="font-size: medium;">/different/url!method1.action
?/span> /another/url!method1.action
来调?strong>method1
Ҏ?br />
对应的映\径分别是/WEB-INF/content/different/url-error.jsp;
/WEB-INF/content/another/url-error.jsp
可能误导了大Ӟ一个方法被@Action注释后,只是多了一U调用方式,而不是说覆盖了原来的调用方式。比如对于如下例子:
package com.example.web;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
public class HelloAction extends ActionSupport {
@Action ( "/another/url" )
public String method1() {
return “error”;
}
package com.example.web;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
public class HelloAction extends ActionSupport {
@Action("/another/url")
public String method1() {
return “error”;
}
我们调用method1Ҏ可以通过两种方式Q?br />
1 /hello!method1.action
映射 urlQ?strong>/WEB-INF/content/hello-error.jsp
2 /another/url!method1.action
映射 urlQ?span style="font-size: small;">/WEB-INF/content/another/url-error.jsp
可见Q两U方式均可对method1Ҏq行调用Q唯一的区别就是,两种调用的映是不一LQ所以,惌转到不同的界面,q是一个非常好的选择?br />
通过@Namespace
注释
package com.example.web;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
@Namespace ( "/other" )
public class HelloWorld extends ActionSupport {
public String method1() {
return “error”;
}
@Action ( "url" )
public String method2() {
return “error”;
}
@Action ( "/different/url" )
public String method3() {
return “error”;
}
}
package com.example.web;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
@Namespace("/other")
public class HelloWorld extends ActionSupport {
public String method1() {
return “error”;
}
@Action("url")
public String method2() {
return “error”;
}
@Action("/different/url")
public String method3() {
return “error”;
}
}
通过 /other/hello-world!method1.action
讉Kmethod1
Ҏ?br />
通过 /other/url!method2.action
讉Kmethod2
Ҏ
通过 /different /url!method3.action
讉Kmethod3 Ҏ
与@Action 注释不同的是Q该注释覆盖了默认的namespace(q里?#8217;/’)Q此时再?span style="font-size: small;">hello!method1.action
已经不能讉Kmethod1 ?
@Results和@Result
1 全局的(globalQ?/strong>
全局results可以被actioncM所有的action分nQ这Uresults在actioncM使用注解q行声明?/p>
package com.example.actions;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
@Results ({
@Result (name= "failure" , location= "/WEB-INF/fail.jsp" )
})
public class HelloWorld extends ActionSupport {
public String method1() {
return “failure”;
}
@Action ( "/different/url" )
public String method2() {
return “failure”;
}
}
package com.example.actions;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
@Results({
@Result(name="failure", location="/WEB-INF/fail.jsp")
})
public class HelloWorld extends ActionSupport {
public String method1() {
return “failure”;
}
@Action("/different/url")
public String method2() {
return “failure”;
}
}
当我们访?/span> /hello -world !method1.action Ӟq回 /WEB-INF/fail.jsp
当我们访?/span> /hello -world !method2.action Ӟq回 /WEB-INF/fail.jsp
当我们访?/span> /different/url!method2.action
Ӟq回 /WEB-INF/fail.jsp
2 本地的(localQ?/strong>
本地results只能在actionҎ上进行声明?/p>
package com.example.actions;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
public class HelloWorld extends ActionSupport {
@Action (value= "/other/bar" ,results={ @Result (name = "error" , location = "www.baidu.com" ,type= "redirect" )})
public String method1() {
return “error”;
}
}
package com.example.actions;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
public class HelloWorld extends ActionSupport {
@Action(value="/other/bar",results={@Result(name = "error", location = "www.baidu.com",type="redirect")})
public String method1() {
return “error”;
}
}
当我们调?/span> /hello
-world !method1.action Ӟq回 /WEB-INF/content/hello-error.jsp
当我们调?/span> /other/bar!method1.action
Ӟq回 www.baidu.com
]]>Struts2开发环境搭? http://www.aygfsteel.com/conans/articles/283364.htmlCONAN CONAN Sat, 20 Jun 2009 08:16:00 GMT http://www.aygfsteel.com/conans/articles/283364.html
搭徏最单的开发环?
完善Library的管理方?
在上面搭建环境的q程中,我们发现QLibrary的管理存在着一定问题。这个问题主要表CؓQ?
1.
不容易做Library的版本管理。如果Library的版本需要升U,那么我们不得不重新copy一份新的jar包,q且借助IDE重新指定目?
classpath。这U劳动,对于一个项目还可以接受Q如果你?0多个目Q那么jar包的复制工作会让你很头疼?
2.
每个目都会有Library的副本。这一点让人非常恼火。实际上Q对于一个公司或者一个项目组而言Q用的技术体pd本不变。然而,每个目?
Library却是分开的。不仅如此,每个目都要从svn中下载大量的相同的Library文gQ给我们的硬盘造成极大的空间浪贏V对于那些频J?
Branch的项目来_q些Library的下载简直就是噩梦?
所以,我们需要一?strong>集中式的Library理方式。而这一Ҏl在Javaeye的v阔天I版Ȁ烈得讨论q用maven来进行管理还是自行管理?
Readonly 写道
׃ncd可以用IDE reference project解决Q公司内部项目给常用的lib建立一个projectQ从CVS上check
outQ其他工E项目都依赖q个project可以了Qant build也直接引用这个项目的jar可以,目体积照样只有几百K?
——一个讨厌antQ更加讨厌maven的h
我比较赞同Readonly老大的说法而們于自行管理。mavenq样的高U货Q偶实在是用不来啊。那么我们就来看看如何用共享类库来q行Library理?
1. 首先建立一个共享类?/strong>
建立一个共享类库,项目中需要共享的Libraryq行恰当的分cR同Ӟ为每个加入到Library中的jar包进行统一的格式化的命名方
式。例如:spring/spring-2.5.5.jar{等。这L好处在于Q一旦jar包的版本有更斎ͼ可以加入新的jar包而保留原来的。在目
中,可以通过引用不同版本的jar包来对Libraryq行版本理?
以下是我个人徏立的一个共享类库,大家可以参考:
svn://www.demo2do.com/library
2. checkout׃ncdQƈ其导入到IDE中作Z个Library工程
3. Z的项目指定classpathQ引用的jar包存在于Library工程?/strong>
在这里,我们可以看到Q原来项目中的lib目录被删除,jar包也被删除。在目中所引用的jar包是Library目中的jar包?
【小l?/strong>
完成了上q所有的步骤之后QLibraryp集中理hQ而每个项目也不会再变得那么庞大。当Ӟ开发环境的搭徏完全取决于个人的习惯Q所以用各自喜Ƣ的方式吧,不要让环境问题束~你们的手脚?br />
转自Qhttp://www.javaeye.com/wiki/struts2/1321-struts2-development-environment-to-build
]]> LightURL——打造零配置的Struts2开发方?/title> http://www.aygfsteel.com/conans/articles/231367.htmlCONAN CONAN Fri, 26 Sep 2008 12:03:00 GMT http://www.aygfsteel.com/conans/articles/231367.html 背景
Struts2已经日益成ؓWeb层比较主的开发框Ӟ它来源于Webwork2Q是一个非怼U的MVC框架。在Webwork2设计之处QAnnotation和Ruby on Railsq没有像现在那么火,所以整个框架在配置斚wq是沿用了Web框架惯用的XML作ؓ主要的配|方式?
随着时代的发展,对于WebE序员来_如何化配|成了一个很重要的课题。在q方面,Struts2也有一些探索。在Struts2的官方网站上Q我们可以找C些优U的plugin来做q些工作Q?
http://cwiki.apache.org/S2PLUGINS/codebehind-plugin.html
http://cwiki.apache.org/S2PLUGINS/smarturls-plugin.html
LightURL的目的是Z吸取q些优秀的plugin的优点,q支持更方便的配|方式?
安装
1. struts2-lighturl-plugin.jar加入到classpath?
2. 配置你的web.xml
<!-- Struts Filter -->
<filter>
<filter-name>struts</filter-name>
<filter- class >com.demo2do.lighturl.LightURLFilter</filter- class >
</filter>
<!-- Struts URL Definition -->
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Struts Filter -->
<filter>
<filter-name>struts</filter-name>
<filter-class>com.demo2do.lighturl.LightURLFilter</filter-class>
</filter>
<!-- Struts URL Definition -->
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3. 需要指定你的action package所在位|和一些基本配|?
q一步一般在struts.properties中完成。你可以Z个struts.properties的配|文Ӟq放到classpath下,q指定如下配|?
## action package config
lighturl.action.packages=com.demo2do.lighturl.action
## action mapping implementation class
struts.mapper. class =com.demo2do.lighturl.LightURLActionMapper
## default parent package
lighturl.action. default .parent. package =struts-config
## define your entity package (optional)
# lighturl.entity. package =com.demo2do.lighturl.entity
## action package config
lighturl.action.packages=com.demo2do.lighturl.action
## action mapping implementation class
struts.mapper.class=com.demo2do.lighturl.LightURLActionMapper
## default parent package
lighturl.action.default.parent.package=struts-config
## define your entity package (optional)
# lighturl.entity.package=com.demo2do.lighturl.entity
在完成以上的步骤后,lighturl的所有配|即告完成,现在你已l可以用所有lighturl所提供的特性?
Namespace, ActionName和URL映射
lighturl所提供的最基本的特性是Ҏ你的Action所在的packageQ确定namespace和actionNameQƈq行对应的URL映射?
举例说明Q你在上面所讲述的struts.properties中,已经指定了你的action package
lighturl.action.packages=com.demo2do.lighturl.action
lighturl.action.packages=com.demo2do.lighturl.action
那么Q如果你有以下的Actionc,那么lighturl根据如下的规则来确定每个ActioncL对应的namespaceQactionName和url映射关系
1. Ҏlighturl.action.packages的配|的packageC的Actioncȝ相对package来确定namespaceQ如果其中有驼峰法命名,那么转化?-"q接的单?
com.demo2do.lighturl.action.Index ----> /
com.demo2do.lighturl.action.user.Search ----> /user
com.demo2do.lighturl.action.blog.category.Index ----> /blog/category
com.demo2do.lighturl.action.accoutDetail.View ----> /account-detail
2. Actioncȝcd转化成actionName。如果碰到的ActioncM"Action"l尾Q则L末尾?Action"Q如果其中有驼峰法命?那么转化?-"q接的单?
com.demo2do.lighturl.action.Index ----> index
com.demo2do.lighturl.action.user.SearchAction ----> search
com.demo2do.lighturl.action.blog.CategoryBlog ----> category-blog
3. namespace与actionNameDv来,成构成映射到具体Actioncȝurl
http://host:port/app/user/index ---> com.demo2do.lighturl.action.user.Index
http://host:port/app/blog/category-blog ---> com.demo2do.lighturl.action.blog.CategoryBlog
上面的这UURL匚w方式Q我UC为:package匚w
Ҏ形式的URL
应该说根据package来进行Action映射Q可以解决绝大多Curl到action的映配|问题。不q有的时候,我们可能需要支持一些特DŞ式的url。LightURL在默认情况下Q支持下?U特DŞ式的URL
1. 支持名为Index的Action直接映射到package?
q种匚w我称之ؓQ?strong>Namespace匚w
。这一个特性很直观。如果你在某个Action的package下面有一个名为Index的Actionc,那么如果你直接访问这个packageQ那么你可以讉K到这个类Q?
com.demo2do.lighturl.action.Index ---> http://host:port/app/
com.demo2do.lighturl.action.user.Index ---> http://host:port/app/user
com.demo2do.lighturl.action.blog.category.Index ---> http://host:port/app/blog/category
2. 支持cM: /entity/${id}形式的URL
q种匚w我通常UC为:entity匚w 。这个特性也比较单,如果你有某个entityQƈ且在你的Action package下有一个与entity同名的package。同时在q个package下有一个叫View的ActionQ那么上qŞ式的URL会被映射到该Action?
com.demo2do.lighturl.action.user.View ---> http://host:port/app/user/3456
com.demo2do.lighturl.action.blog.View ---> http://host:port/app/user/1113
你可以通过在struts.properties中指定你entity所在的package来对哪些url可以具备q些Ҏ,如果你输入的url不在你所指定的package中含有entityQ那么这个url无法被识别?
针对有些情况Q数据库的主键可能不是数字。此Ӟ你可以通过自己实现com.demo2do.lighturl.config.EntityPrimaryKeyIdentifier的接口来指定你的url中id具备什么特炏V默认的实现是将主键识别为数字?
使用Annotation来指定映?/strong>
除了上述q些基本Ҏ以外,q可以通过Annotaion来指定URL映射。目前情况下QLightURL所支持的Annotation有两U类?
1. URL完整匚w
URL完整匚w是指如果某个url完整匚w于Annotation中所指定的内容,那么q个URL被映射到Annotation所在的Actioncȝmethod
package com.demo2do.lighturl.action.user;
import com.demo2do.lighturl.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;
public class Search extends ActionSupport {
private static final long serialVersionUID = -1728616675239859226L;
@Override
@Action ( "/all/search-user" )
public String execute() throws Exception {
return super .execute();
}
}
package com.demo2do.lighturl.action.user;
import com.demo2do.lighturl.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;
/**
* @author Downpour
*
*/
public class Search extends ActionSupport {
private static final long serialVersionUID = -1728616675239859226L;
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ActionSupport#execute()
*/
@Override
@Action("/all/search-user")
public String execute() throws Exception {
return super.execute();
}
}
例如Q上q的ActioncL一个AnnotationQ那么这个Action和method被映射到对应的URL:http://host:port/app/all/search-user?
注意Q此Ӟ虽然从url上来看,q是一个没有什么规则的urlQ但是其所对应的namespace和actionNameq是Ҏcom.demo2do.lighturl.action.user.Search来进行计的?
2. URL Template
URL Template是指Qurl可以匚wAnnotaion中指定的某种URL TemplateQƈ其中的可变部分作ؓ参数映射到Action中?
package com.demo2do.lighturl.action.blog;
import com.demo2do.lighturl.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;
public class Category extends ActionSupport {
private static final long serialVersionUID = -1535992103374733252L;
private Long id;
private int year;
private int month;
private int day;
@Override
@Action ( "/blogs/${year}/${month}/${day}" )
public String execute() throws Exception {
return super .execute();
}
@Action ( "/blog/${id}/edit" )
public String edit() throws Exception {
return super .execute();
}
}
package com.demo2do.lighturl.action.blog;
import com.demo2do.lighturl.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;
/**
* @author Downpour
*
*/
public class Category extends ActionSupport {
private static final long serialVersionUID = -1535992103374733252L;
private Long id;
private int year;
private int month;
private int day;
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ActionSupport#execute()
*/
@Override
@Action("/blogs/${year}/${month}/${day}")
public String execute() throws Exception {
return super.execute();
}
@Action("/blog/${id}/edit")
public String edit() throws Exception {
return super.execute();
}
// setters and getters
}
在上q的例子中,可以发现Q在Annotation中所指定的内Ҏ一个URL TemplateQ如果你有一个urlQ可以匹配上面的URL TemplateQ那么url匹配到q个Action的methodQƈ且将对应位置的值注入到Action中的同名参数中?
针对上面的例子:
http://host:port/app/blogs/2008/08/07被映射到这个Action的executeQƈ?008Q?8?7分别映射到yearQmonth和day中?
http://host:port/app/blog/2345/edit被映射到Action的editҎQƈ?345映射到id中作为参?
URL的匹配顺序与重复配置的校?/strong>
在上面的例子中,介绍了那么多的url映射到Action中的方式。他们之间可能会出现冲突Q有些冲H,LightURL会在pȝ启动时ؓ你检查出来,q强制要求你U正它,而有些冲H,则通过优先U匹配的方式q行?
下列冲突被认ؓ是你必须在系l启动前p行纠正的Q?
1. Annotation中定义的URL Template互相之间冲突
例如Q?blogs/${year}/${month}/${day}?blogs/${category}/${id}/edit是冲突的?
2. Annotation中定义的URL Template与其他Annotation中定义的完全匚wURL冲突
例如Q?blogs/${year}/${month}?blogs/category/index是冲突的?
3. Annotation中定义的URL Template与Ş?entity/${id}的url定义冲突
例如Q?user/${id}形式的Annotation定义可能会与pȝ默认支持的冲H?
在其他情况下Q如果你定义的URL映射互相直接有冲H,那么LightURL根据某个顺序进行URL匚wQƈ扑ֈW一个匹配的映射方式Q然后放弃查找。这个顺序ؓQ?
1. 首先q行Namespace匚w Q如果url恰好能匹配某个namespaceQƈ且其对应的package下有Index作ؓActionQ那么直接进行匹配?
2. 其次查看所有的Annotation定义中,是否存在完整的URL匚w Q如果找刎ͼ那么q行直接匚w?
3. 接着q行package匚w Q将url分解成相应的namespace和actionNameQ与已有的配|进行匹配,如果扑ֈQ那么直接匹配?
4. 然后q行entity匚w Q看看url是否形如:/entity/${id}Q如果是Q那么直接匹配?
5. 最后进行Annotation定义?strong>Url Template匚w ?
如果所有的五种情况都无法进行匹配,那么q个URL无法被LightURL识别Ql交由Struts2q行后箋处理?
上面所描述的内定w是Url到Action的映。下面的部分Q描q的是如何在Action执行完毕之后Q{到相应的l果view?
Codebehind
LightURL支持codebehind。有关codebehind的相关知识,可以参考struts2的相x档:
http://struts.apache.org/2.x/docs/codebehind-plugin.html
有了codebehind的支持,那么从Action转到cMjspQftl或者vm的view层组件就不需要Q何配|,只要W合一定的命名规范Q就可以直接q行转向?
ResultCode的识?/strong>
但是在很多情况下Q我们需要的是全方位的Resultcd的支持。例如,有的时候我们需要返回JSON ResultQ有的时候,我们可能需要RedirectC个新的Action。此Ӟ我们不得不ؓ此增加一些配|,或者借助Annotation来完成?
为此QLightURL提供了一U根据ResultCodeq行识别的命名方式来匚w你所指定的Result?
以JSON ResultZQ你可以q么写:
package com.demo2do.lighturl.action.user;
import com.demo2do.lighturl.entity.User;
import com.opensymphony.xwork2.ActionSupport;
public class Index extends ActionSupport {
private static final long serialVersionUID = -5017825114664788765L;
private User user;
@Override
public String execute() throws Exception {
return "j:user" ;
}
}
package com.demo2do.lighturl.action.user;
import com.demo2do.lighturl.entity.User;
import com.opensymphony.xwork2.ActionSupport;
/**
* @author Downpour
*
*/
public class Index extends ActionSupport {
private static final long serialVersionUID = -5017825114664788765L;
private User user;
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ActionSupport#execute()
*/
@Override
public String execute() throws Exception {
return "j:user";
}
// setters and getters
}
在这里,你可以发玎ͼresultCode变成了j:user。那么此ӞLightURL会将q个resultCode识别成:误回JSON ResultQƈ且JSON的Result的root为user对象?
再例如:
package com.demo2do.lighturl.action.user;
import com.demo2do.lighturl.entity.User;
import com.opensymphony.xwork2.ActionSupport;
public class Index extends ActionSupport {
private static final long serialVersionUID = -5017825114664788765L;
private User user;
@Override
public String execute() throws Exception {
return "r:/user/add-user" ;
}
}
package com.demo2do.lighturl.action.user;
import com.demo2do.lighturl.entity.User;
import com.opensymphony.xwork2.ActionSupport;
/**
* @author Downpour
*
*/
public class Index extends ActionSupport {
private static final long serialVersionUID = -5017825114664788765L;
private User user;
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ActionSupport#execute()
*/
@Override
public String execute() throws Exception {
return "r:/user/add-user";
}
// setters and getters
}
在这里,"r:/user/add-user"会被识别成:误回Redirect Result。Redirect的URL?user/add-user?
LightURL默认情况下,实现了对Redirect Result和JSON Result的ResultCode识别Qƈ他们的前缀分别定制为:"r:"("redirect:")或?j:"("json:")?
当然Q你可以Ҏ你自q情况Q实C自己的ResultCode的识别程序,你只需要实现com.demo2do.lighturl.result.ResultCodeConfig接口卛_。ƈ在struts.properties中指定你希望LightURLq行ResultCode匚w的顺序?
lighturl.result.code.config=yourpackage.ResultCodeConfigImpl1,yourpackage.ResultCodeConfigImpl2
lighturl.result.code.config=yourpackage.ResultCodeConfigImpl1,yourpackage.ResultCodeConfigImpl2
q样QLightURL会根据你所指定的顺序,依次q行ResultCode的匹配,直到扑ֈW一个匹配的Result TypeZ?
当然Q默认情况下QLightURL的匹配顺序ؓQ?
codebehind -> 你自定义的ResultCode识别实现 -> json -> redirect
]]>Struts2教程Q-W二章 Struts2的工作机制及分析 http://www.aygfsteel.com/conans/articles/214089.htmlCONAN CONAN Thu, 10 Jul 2008 11:29:00 GMT http://www.aygfsteel.com/conans/articles/214089.html 阅读全文 ]]> Struts2与Struts1.x的深度比?/title> http://www.aygfsteel.com/conans/articles/213756.htmlCONAN CONAN Wed, 09 Jul 2008 11:12:00 GMT http://www.aygfsteel.com/conans/articles/213756.html Struts 作ؓ MVC 2 ?/span>Web 框架Q自推出以来不断受到开发者的q捧Q得到广泛的应用。作为最成功?/span>Web 框架Q?/span>Struts 自然拥有众多的优点: MVC 2 模型的用、功能齐全的标志库( Tag Library Q、开放源代码?/span>
但是Q正所?/span>“ 没有最好,只有更好 ” Q?/span>Struts1.x 自n也有不少的缺点:需要编写的代码q多Q容易引?/span>“ cȝ?/span>” 、单元测试困难。这些缺炚w着 Web 的发展越来越明显。这׃生了 Struts 2 Q它的诞生能很好的解决上q问题?/span>
在本文中Q笔者将?/span>Struts2 ?/span>Struts1.x q两U框架进行详l的比较。比较将涉及到这两种框架?/span>Action 、验证、类型{换及如何开发等斚w的内宏V希望通过q样的比较,让读者了解这两种框架各自的特点,以便于在自己的项目中Q根据实际情况,快的过渡到 Struts2 的时代。本文的内容Z Struts2.0.6 ?/span>
一?span>
引言
Struts 的第一个版本是?/span>2001 q?/span>5 月䆾发布的。它的最初设x通过l合 JSP ?/span>Servlet Q Web 应用的视囑֒业务 / 应用逻辑得以清晰地分d来。在 Struts 之前Q最常见的做法是?/span>JSP 中加入业务和应用逻辑Q或者在 Servlet 中通过 println() 来生成视图?/span>
自从W一版发布以来, Struts 实际上已成ؓ业界公认?/span>Web 应用标准。它的炙手可热也己带来了改进和变_所以不但要跟上?/span>Web 应用框架不断变化的需求,而且要与日渐增多竞争Ȁ烈的众多框架的特性相融合?/span>
到最后,产生了几个下一?/span>Struts 的解x案。其中两个最受瞩目的Ҏ?/span>Shale ?/span>Struts Ti ?/span>Shale 是一个基于构件的框架Qƈ在最q成?/span>Apache 的顶U项目。?/span>Struts Ti 则是?/span>Struts 的成功经验基上l坚持对前端控制器( Front Controller Q和 MVC Q?/span>model-view-controller Q模式进行改q?/span>
WebWork 目是在 2002 q?/span>3 月发布的Q它?/span>Struts 式框架进行了革命性改q,引进了不新的思想、概念和功能Q但和原 Struts 代码q不兼容?/span>WebWork 是一个成熟的框架Q经q了好几ơ重大的改进与发布?/span>
?/span>2005 q?/span>12 月, WebWork ?/span>Struts Ti 宣布合ƈ。与此同Ӟ Struts Ti 改名?/span>Struts Action Framework 2.0 Q成?/span>Struts 真正的承者?/span>
最后要注意的是Qƈ不是?/span>Struts ?/span>WebWork 目已经停止开发了。由于h们对q两个项目的兴趣仍然很高Q而且也有很多开发者仍然愿意用它们,因此q两个项目还在l开发中Ql修?/span>Bug Q改q功能和l箋d新功能?/span>
二?span> Action 的区?/span>
对于有着丰富?/span>Struts1.x 开发经验的朋友来说Q都十分的清?/span>Action 是整?/span>Struts 框架的核心内容,当然 Struts2 也不例外。不q, Struts1.x ?/span>Struts2 ?/span>Action 模型很大的区别?/span>
Struts2 ?/span>Struts1.x 的差别,最明显的就?/span>Struts2 是一?/span>pull-MVC 架构。这是什么意思呢Q从开发者角度看Q就是说需要显C给用户的数据可以直接从 Action 中获取,而不?/span>Struts1.x 那样Q必L相应?/span>Bean 存到 Page ?/span>Request 或?/span>Session 中才能获取?/span>Struts1.x 必须l承 org.apache.struts.action.Action 或者其子类Q表单数据封装在 FormBean 中?/span>Struts 2 无须l承Mcd或实CQ何接口,表单数据包含?/span>Action 中,通过 Getter ?/span>Setter 获取Q如下面?/span>ActionForStruts2 的代码示例)?/span>
虽然Q在理论?/span>Struts2 ?/span>Action 无须实现M接口或者是l承M的类Q但是,在实际编E过E中Qؓ了更加方便的实现 Action Q大多数情况下都会?/span>com.opensymphony.xwork2.ActionSupport c,q且重蝲Q?/span>Override Q此c里?/span>String execute() Ҏ。如下所C:
package ActionDiffer;
import java.text.DateFormat;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class ActionForStruts2 extends ActionSupport {
private String message;
public String getMessage() {
return message;
}
@Override
public String execute() {
message = " This is hello from strtuts2. Now is: " + DateFormat.getInstance().format( new Date());
return SUCCESS;
}
}
首先Q从 ActionForStruts2 可以看出Q返回的对象不是 ActionForward Q而是 String 。如果你不喜Ƣ以字符串的形式出现在你的代码中Q有?/span>Helper 接口 Action 可以以常量方式提供常见结果,?/span>“success” ?/span>“none” ?/span>“error” ?/span>“input” ?/span>“login” ?/span>
另外Q?/span> 按照惯例Q在 Struts1.x 中只?/span>“execute” Ҏ能调?/span>Action, 但在 Struts2 中ƈ非必要,M声明?/span>public String methodName() ҎQ都能通过配置来调?/span>Action ?/span>
最后,?/span>Struts1.x 最大的革命性的不同是, Struts2 处理 Action q程中调用的ҎQ?/span>“execute” ҎQ是不带参数的。那如何获取所需要的对象呢?{案是?/span>IoC Q反转控Ӟ Inversion of Control) Q也?/span>“ 依赖注入Q?/span>Dependency Injection Q?/span>” 的模式(x多地了解q方面信息请?/span>Martin Fowler 的文?/span>http://www.martinfowler.com/articles/injection.html Q?/span>Spring 框架使得q个模式行hQ然?/span>Struts2 的前w( WebWork Q也同时应用上了q个模式?/span>
三?span> IoC
IoC(Inversion of Control Q以下译为控制反转)Q随着 Java C中轻量容器Q?/span>Lightweight Contianer Q的推广而越来越为大家耳熟能详。在此,无需再多费唇舌来解释 “ 什么是控制反{ ” ?/span>“ Z么需要控制反?/span>” 。因Z联网上已l有非常多的文章对诸如此cȝ问题作了_ֽ而准的回答。读者可以去M?/span>Rod Johnson ?/span>Juergen Hoeller 合著的?/span>Expert one-on-one J2EE Development without EJB 》或 Martin Fowler 所写的?/span>Inversion of Control Containers and the Dependency Injection pattern 》?/span>
众所周知Q?/span>Struts2 是以 Webwork 2 作ؓ基础发展出来。而在 Webwork 2.2 之前?/span>Webwork 版本Q其自n有一套控制反转的实现Q?/span>Webwork 2.2 ?/span>Spring 框架 的如火如荼发展的背景下,军_攑ּ控制反{功能的开发,转由 Spring 实现。值得一提的是, Spring 实是一个值得学习的框Ӟ因ؓ有越来越多的开源组Ӟ?/span>iBATIS {)都放弃与 Spring 重叠的功能的开发。因此, Struts2 推荐大家通过 Spring 实现控制反{?/span>
Z更好C解反转控Ӟ下面来看一个例子,如何利用 IoC ?/span>Action 处理q程中可以访问到当前h HttpServerRequest 对象?/span>
在例子中Q用的依赖注入机制是接口注入。就如其名称一P接口注入需要的是已l被实现了的接口。这个接口包含了相应属性的 setter Qؓ Action 提供倹{例子中使用?/span>ServletRequestAware 接口Q如下:
public interface ServletRequestAware {
public void setServletRequest(HttpServletRequest request);
}
当承这个接口后Q原本简单的 Action 看v来有点复杂了Q但是这时可以获?/span>HttpServerRequest 对象来用了?/span>
public class IoCForStruts2 implements ServletRequestAware {
private HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public String execute() throws Exception {
// 可以开始?/span>request 对象q行工作?/span>
return Action.SUCCESS;
}
}
看v来现在这些属性是cȝ别的Qƈ不是U程安全的,会出现问题。其实在 Struts2 里ƈ没有问题Q因为每个请求过来的时候都会生一个新?/span>Action 对象实例Q它q没有和其他h׃n一个对象,所以不需要考虑U程安全问题?/span>
四?span> 拦截?/span>
Interceptor Q以下译为拦截器Q,?/span>AOP Q?/span>Aspect-Oriented Programming Q中用于在某个方法或字段被访问之前,q行拦截然后在之前或之后加入某些操作。拦截是 AOP 的一U实现策略?/span>
?/span>Webwork 的中文文档的解释?/span>—?/span>拦截器是动态拦?/span>Action 调用的对象。它提供了一U机制可以开发者定义在一?/span>action 执行的前后执行的代码Q也可以在一?/span>action 执行前阻止其执行。同时也提供了一U可以提?/span>action 中可重用的部分的方式?/span>
Struts1.x 的标准框架中不提供Q何Ş式的拦截器,虽一个名?/span>SAIF 的附加项目则实现了这L功能Q但它的适用的范围还很有限?/span>
拦截器是 Struts2 的一个强有力的工P有许多功能( feature Q都是构Z它之上,?/span>国际?/span> ?/span>转换?/span> Q?/span>校验 {。谈到拦截器Q还有一个流行的?/span>—?/span>拦截器链Q?/span>Interceptor Chain Q在 Struts2 中称为拦截器?/span>Interceptor Stack Q。拦截器铑ְ是将拦截器按一定的序联结成一条链。在讉K被拦截的Ҏ或字D|Q拦截器链中的拦截器׃按其之前定义的顺序被调用?/span>
Struts 2 的拦截器实现相对比较单。当h到达 Struts2 ?/span>ServletDispatcher Ӟ Struts 2 会查N|文Ӟq根据其配置实例化相对的拦截器对象,然后串成一个列表( list Q,最后一一地调用列表中的拦截器Q如?/span>1 所C?/span>
拦截器调用序列器
Struts 2 已经提供丰富多样功能齐全的拦截器实现。读者可以到 struts2-all-2.0.6 .jar ?/span>struts2-core-2.0.6.jar 包的 struts-default.xml 查看关于默认的拦截器与拦截器铄配置?/span>
作ؓ “ 框架Q?/span>framework Q?/span>” Q可扩展性是不可~少的,因ؓ世上没有放之四v而皆准的东西。虽Ӟ Struts 2 为我们提供如此丰富的拦截器实玎ͼ但是qƈ不意x们失d定义拦截器的能力Q恰恰相反,?/span>Struts 2 自定义拦截器是相当容易的一件事?/span>
五?span> Struts2 ?/span> Struts1.x 的全面比?/span>
Z?/span>Struts2 ?/span>Strtus1.x q行全面的比较,让读者了解这两种框架各自的优~点Q以便于在自q目中,Ҏ实际情况Q选择合适的框架Q对它们两者进行比较,ȝ了如下表分析比较?/span>
Ҏ?/span>
Struts1.x
Struts2
Action c?/span>
Struts1.x 要求 Action c要扩展自一个抽象基cR?/span>Struts1.x 的一个共有的问题是面向抽象类~程而不是面向接口编E?/span>
Struts2 ?/span>Action cdC一?/span>Action 接口Q连同其他接口一h实现可选择和自定义的服务?/span>Struts2 提供一个名?/span>ActionSupport 的基cL实现一般用的接口。当Ӟ Action 接口不是必须的。Q何?/span>execute Ҏ?/span>POJO 对象可以被当?/span>Struts 2 ?/span>Action 对象来用?/span>
U程模型
Struts1.x Action cL单例c,因ؓ只有一个实例来控制所有的h。单例类{略造成了一定的限制Qƈ且给开发带来了额外的烦恹{?/span>Action 资源必须是线E安全或者同步的?/span>
Struts2 Action 对象为每一个请求都实例化对象,所以没有线E安全的问题。(实践中, servlet 容器l每一个请求生许多丟弃的对象Qƈ且不会导致性能和垃圑֛攉题)?/span>
Servlet 依赖
Struts1.x ?/span>Action cM赖于 servlet API Q当 Action 被调用时Q以 HttpServletRequest ?/span>HttpServletResponse 作ؓ参数传给 execute Ҏ?/span>
Struts2 ?/span>Action 和容器无兟?/span>Servlet 上下文被表现为简单的 Maps Q允?/span>Action 被独立的试?/span>Struts2 ?/span>Action 可以讉K最初的h ( 如果需要的?/span>) 。但是,可能避免或排除其他元素直接讉K HttpServletRequest ?/span>HttpServletResponse ?/span>
易测?/span>
试 Struts1.x 的主要问题是 execute Ҏ暴露?/span>Servlet API q得测试要依赖于容器)。第三方的扩展,?/span>Struts TestCase Q提供了一?/span>Struts1 的模拟对象(来进行测试)?/span>
Struts2 ?/span>Action 可以通过初始化、设|属性、调用方法来试。依赖注入的支持也是试变得更简单?/span>
捕获输入
Struts1.x 使用 ActionForm 对象来捕莯入。象 Action 一P所有的 ActionForm 必须扩展基类。因为其他的 JavaBean 不能作ؓ ActionForm 使用Q开发者经常创建多余的cL捕获输入?/span>DynaBeans 可以被用来作为替?/span>ActionForm 的类来创建。但是,开发者可能是在重新描q?/span>( 创徏 ) 已经存在?/span>JavaBean Q仍然会D有冗余的 javabean Q?/span>
Struts2 直接使用 Action 属性作入属性,消除了对W二个输入对象的需求。输入属性可能是有自?/span>( ?/span>) 属性的 rich 对象cd?/span>Action 属性能够通过 web 面上的 taglibs 讉K?/span>Struts2 也支?/span>ActionForm 模式?/span>rich 对象cdQ包括业务对象,能够用作输入 / 输出对象。这U?/span>ModelDriven Ҏ简化了 taglib ?/span>POJO 输入对象的引用?/span>
表达式语a
Struts1.x 整合 JSTL Q所以它使用 JSTL 的表辑ּ语言。表辑ּ语言有基本的囑Ş对象UdQ但是对集合和烦引属性的支持很弱?/span>
Struts2 使用 JSTL Q但是也支持一个更强大和灵zȝ表达式语aQ- "Object Graph Notation Language" (OGNL) ?/span>
值绑定到面
Struts1.x 使用标准 JSP 机制来绑定对象到面上下文?/span>
Struts2 使用“ ValueStack ”技术,?/span>taglib 能够讉KD不需要把你的面Q?/span>view Q和对象l定h?/span>ValueStack {略允许通过一pd名称相同但类型不同的属性重用页面( view Q?/span>
cd转换
Struts1.x ?/span>ActionForm 属性经帔R?/span>String ?/span>Struts 1.x 使用 Commons-Beanutils 来进行类型{换。{换每一个类Q而不是ؓ每一个实例配|?/span>
Struts2 使用 OGNL q行cd转换。提供基本和常用对象的{换器?/span>
验证
Struts1.x 支持?/span>ActionForm ?/span>validate Ҏ中手动校验,或者通过 Commons Validator 的扩展来校验。同一个类可以有不同的校验内容Q但不能校验子对象?/span>
Struts2 支持通过 validate Ҏ?/span>XWork 校验框架来进行校验?/span>XWork 校验框架使用为属性类cd定义的校验和内容校验Q来支持 chain 校验子属?/span>
Action 执行控制
Struts1.x 支持每一个模块有单独?/span>Request Processors Q生命周期)Q但是模块中的所?/span>Action 必须׃n相同的生命周期?/span>
Struts2 支持通过拦截器堆栈( Interceptor Stacks Qؓ每一?/span>Action 创徏不同的生命周期。堆栈能够根据需要和不同?/span>Action 一起用?/span>
六?span> l论
前面已经要介l了 Struts2 的v源,q详l对比了 Struts2 ?/span>Struts1.x 的差异,读?/span>应该?/span>Struts2 的基有所了解?/span>—?/span>包括高层的框架概念和基础的请求流E,q理?/span>Struts1.x ?/span>Struts2 两者之间在 Action 斚w的差别, Struts2 加强了对拦截器与 IoC 的支持,而在 Struts1.x 中,q些Ҏ是很难惌的?/span>
同时Q读者应该明白: Struts2 ?/span>WebWork 的升U,而不?/span>Struts 1.x 的升U。虽?/span>Struts 2 提供了与 Struts1.x 的兼容,但已l不?/span>Struts1.x 的升U。对于已?/span>Struts1.x 开发经验的开发者而言Q?/span>Struts1.x 的开发经验对?/span>Struts2 q没有太大的帮助Q相反,对于已经?/span>WebWork 开发经验的开发者而言Q?/span>WebWork 的开发经验对 Struts2 的开发将有很好的借鉴意义?/span>
]]>我的struts2目性能调优三步? http://www.aygfsteel.com/conans/articles/212190.htmlCONAN CONAN Wed, 02 Jul 2008 12:10:00 GMT http://www.aygfsteel.com/conans/articles/212190.html
一Q根据struts2官方的性能调优说明q行了一些参数的修改?br />
http://struts.apache.org/2.x/docs/performance-tuning.html
http://cwiki.apache.org/WW/performance-tuning.html
Turn off logging and devMode.(关闭logging和Devmode)
q个当然没问题,但是全部关闭logging不现实,我只是关闭了struts2相关package的logging
Do not use interceptors you do not need.
把struts.xml中不需要的interceptorl统删除
Use the correct HTTP headers (Cache-Control & Expires).
不确定应该如何修?br />
Copy the static content from the Struts 2 jar when using the Ajax theme (Dojo) or the Calendar tag.
关于q点Q后面会提到
Create a freemarker.properties file in your WEB-INF/classes directory.
照做
Create the freemarker.properties file and add the following setting (or whatever value you deem fitting):
template_update_delay=60000
照做
Enable Freemarker template caching
As of Struts 2.0.10, setting the property struts.freemarker.templatesCache to true will enable the Struts internal caching of Freemarker templates. This property is set to false by default.
照做
q行上述修改后,发现面打开的速度q没有明昄提高.
二,此时我已l基本锁定网|开速度慢的原因与ajax(或者说是dojo)有关。因为dojo的js库大概有450K左右Q先试使用gzip压羃javascriptQ减传输量Q看能否加快面的加载速度
在Tomcat的server.xml的connector中添加如下配|,Ȁzgzip功能
compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/javascript,application/x-javascript,application/javascript"
q行上述修改后,发现面打开的速度q是没有明显的提?
三,l过上述两个实验Q觉得应该是struts2所闭的dojo的性能问题了。于是引入JQuery.
JQuery的js文g最是55K, gzip后应该更,面的响应速度明显改善Q一个数量以上的提高)Q主要原因在于与服务器交互的处理上极大地提升了效率。而且面处理代码更加z明了?br />
最后,我删除了所有的<s:head theme="ajax"/>?<s:head/>(如果面中加?lt;s:head />Q那么在Struts2生成的html中后包含dojo.js)Q用JQuery来完成所有的Ajax和javascript功能?br />
]]> Struts2(Webwork2)一些实战开发技?/title> http://www.aygfsteel.com/conans/articles/210934.htmlCONAN CONAN Thu, 26 Jun 2008 11:55:00 GMT http://www.aygfsteel.com/conans/articles/210934.html 一Q?使用反射动态取?/span> Pojo 的属?/span>
q一招在一些特D的场合下非常管用.比如_用户在第一个页面,选择了某个实体其中要昄出来的几个属性,那个q个时候用反射是非怸错的选择Q少了大?/span> if 语句Q?/span>
Java代码
package com.leo.util;
import java.lang.reflect.Method;
public class HelloWorldBean {
private String word;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public HelloWorldBean() {
name = "superleo";
word = "Hello World!!!";
}
public String getProperty(String name) throws Exception {
if (name != null && !name.equals("")) {
Character ch = name.charAt(0);
name = Character.toUpperCase(ch) + name.substring(1, name.length());
Class cls = Class.forName("com.leo.util.HelloWorldBean");
Method meth = cls.getMethod("get" + name, null);
Object retobj = meth.invoke(this, null);
return (String) retobj;
}
throw new RuntimeException();
}
public static void main(String[] args) throws Exception {
HelloWorldBean bean = new HelloWorldBean();
bean.setName("superleo");
bean.setWord("name");
System.out.println(bean.getProperty("name"));
System.out.println(bean.getProperty("word"));
}
}
package com.leo.util;
import java.lang.reflect.Method;
public class HelloWorldBean {
private String word;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public HelloWorldBean() {
name = "superleo";
word = "Hello World!!!";
}
public String getProperty(String name) throws Exception {
if (name != null && !name.equals("")) {
Character ch = name.charAt(0);
name = Character.toUpperCase(ch) + name.substring(1, name.length());
Class cls = Class.forName("com.leo.util.HelloWorldBean");
Method meth = cls.getMethod("get" + name, null);
Object retobj = meth.invoke(this, null);
return (String) retobj;
}
throw new RuntimeException();
}
public static void main(String[] args) throws Exception {
HelloWorldBean bean = new HelloWorldBean();
bean.setName("superleo");
bean.setWord("name");
System.out.println(bean.getProperty("name"));
System.out.println(bean.getProperty("word"));
}
}
OK Q假设我们在 HelloAction 使用了这?/span> HelloWorldBean Qƈ且运行后Q蟩转到相应面Q你可以q样d HelloWorldBean ?/span> word ?/span> name 属性了Q?/span>
Html代码
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<body>
<h3>
正常ҎQ?lt;s:property value="helloWorld.name" /> <br />
<s:property value="helloWorld.word" /> <br />
反射ҎQ?lt;s:property value="helloWorld.getProperty('name')" /> <br />
<s:property value="helloWorld.getProperty('word')" />
</h3>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<body>
<h3>
正常ҎQ?lt;s:property value="helloWorld.name" /> <br />
<s:property value="helloWorld.word" /> <br />
反射ҎQ?lt;s:property value="helloWorld.getProperty('name')" /> <br />
<s:property value="helloWorld.getProperty('word')" />
</h3>
</body>
</html>
对于公共属性,q可以将此方法移到父cR?/span>
?/span> iterator q代 Map 对象
q对昄 Hibernate 多表q接的查询结果非常管用?
以前Q在使用 Hibernate 的时候,因ؓ涉及到多个表查询是很普遍的,每个表取一些字D,xC在面Q比较好的办法是新徏一?/span> VO 对象Q专门用来显C查询的l果Q但~点是Q如果这L查询很多Q?/span> VO cM来多Q如果不断的往一?/span> VO 增加字段的话Q那么这?/span> VO 也越来越大,构造函C特别夸张Q,׃来看一个例子:
Java代码
List list = session.createQuery("select new MyVO(a.name, b.name, c.id) from .....").list();
q样q回?/span> List 直接可以在面上用 iterator 标签q代了,但假如现在要?/span> 10 呢?不仅 HQL 语句要修改,而且 MyVO 也要修改Q下面是一U更好的做法Q?/span>
Java代码
List list = session.createQuery("select new Map(a.name as fristName, b.name as secondName, c.id as id from .....").list();
q里改用 Map 了,注意每个属性都?#8220; as ”重新启了一个别名,q个非常重要Q否则在面昄Ӟ很费Ԍ
现在来看面调用代码Q?/span>
Html代码
<s:iterator value="list" id="maps">
<tr class="row1">
<input type="checkbox" name="ids" value="<s:property value="#maps.get('id')" />" />
<td align="center"><s:property value="#maps.get('fristName')" /></td>
<td align="center"><s:property value="#maps.get('secondName')" /></td>
</tr>
</s:iterator>
<s:iterator value="list" id="maps">
<tr class="row1">
<input type="checkbox" name="ids" value="<s:property value="#maps.get('id')" />" />
<td align="center"><s:property value="#maps.get('fristName')" /></td>
<td align="center"><s:property value="#maps.get('secondName')" /></td>
</tr>
</s:iterator>
注意上面的页面中 Map 的取值就是当?/span> hql 语句?#8220; as ”后的别名Q?/span>
虽然相对于以往?/span> JSTL 来说Q要写的标签代码更多了,但强大的 OGNL 表达式也让你在视囑ֱ拥有更强大的灉|性与扩展性.
序无关Q如果你使用?/span> select new List(...) 也能辑ֈcM效果Q但因ؓ List 是有序的Q所以在面昄非常不灵z,不推荐用.
?/span> if 标签判断汉字问题
q个问题具体原因不明Q先看下面一D代码:
Java代码
<s:if test="user.name == 'E序'">
...
<s:if test="user.name == 'E序'">
...
q样q user.name {于“E序”也是无法通过的,需要修Ҏ以下代码Q?/span>
Html代码
<s:if test="user.name == "'E序"'">
...
<s:if test="user.name == "'E序"'">
...
如果“E序”是你pȝ的一个常量,更推荐的作法是:
Html代码
<s:if test="user.name == @com.leo.util.Constants@TYPE ">
...
<s:if test="user.name == @com.leo.util.Constants@TYPE ">
...
我不知道原因是不是因为版本问题?希望有知道的Q回复一下.
?/span> iterator 双重循环
q个也很常用Q相信很多h都轻车熟路,那我们来回顾一下。假?/span> lists 装的都是 Group 对象Q?/span> Group 持有一?/span> List<User> 那个我们接下来可以:
Html代码
<ww:iterator value="lists" id="top">
<ww:iterator value="users" id="sub">
l名Q?lt;s:property value="#top.name" />Q成员名Q?lt;s:property value="#sub.name" />
</ww:iterator>
应该lLQ?lt;s:property value="users.size" />
</ww:iterator>
<ww:iterator value="lists" id="top">
<ww:iterator value="users" id="sub">
l名Q?lt;s:property value="#top.name" />Q成员名Q?lt;s:property value="#sub.name" />
</ww:iterator>
应该lLQ?lt;s:property value="users.size" />
</ww:iterator>
上面的写法有很多U,但效果都是一LQ有兴趣可以多看?/span> OGNL ?/span>
q有一些没有及时整理好Q下ơ统一再给大家分n一下.
]]> Struts2利用stream直接输出Excel http://www.aygfsteel.com/conans/articles/210375.htmlCONAN CONAN Tue, 24 Jun 2008 11:41:00 GMT http://www.aygfsteel.com/conans/articles/210375.html 在利用网展C查询结果,l常会遇到要求导出成Excel的需求。采用这U方法可以定制输出的格式和内容(q不支持合ƈ单元格和公式Q,生成真正的Excel格式Q不是csvQ的Excel?br />
一、struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.i18n.encoding" value="UTF-8"/>
<package name="demo" extends="struts-default">
<action name="excel" method="execute" class="demo.ExcelAction">
<result name="excel" type="stream">
<param name="contentType">application/vnd.ms-excel</param> <!-- 注意q里的ContentType -->
<param name="inputName">excelStream</param> <!-- q里需要和Action里的变量名一?-->
<param name="contentDisposition">filename="standard.xls"</param>
<param name="bufferSize">1024</param>
</result>
</action>
</package>
</struts>
二、Struts2?Action
package demo;
public class ExcelAction {
private InputStream excelStream; // 需要生成getter和setter
public String execute() throws Exception {
StringBuffer excelBuf = new StringBuffer();
excelBuf.append("BookName").append("\t").append("Year").append("\t").append("author").append("\n");
excelBuf.append("Thinking in Java").append("\t").append("2001").append("\t").append("Eckel").append("\n");
excelBuf.append("Spring in action").append("\t").append("2005").append("\t").append("Rod").append("\n");
String excelString = excelBuf.toString();
logger.debug("result excel String: " + excelString);
excelStream = new ByteArrayInputStream(excelString.getBytes(), 0, excelString.length());
return "excel";
}
// getter and setter
...
}
三、Jsp面
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<s:head />
</head>
<body>
<s:form action="" method="post">
<s:submit key="button.submit"/>
</s:form>
</body>
</html>
]]> 再谈Struts2囄按钮标签的用:囄根\径无法取得,使用传统Ҏ http://www.aygfsteel.com/conans/articles/209893.htmlCONAN CONAN Sun, 22 Jun 2008 11:07:00 GMT http://www.aygfsteel.com/conans/articles/209893.html
<s:submit type="image" value="user_doDelete.action" label="删除指定用户"
src="myroot/images/btn/btn_delete.jpg" cssClass="button_image"
onclick="return CheckSelectForDelete();" action="user" method="doDelete"/></td>
在这里面的src有个问题是必须带着目的rootQ如上例中的myrootQ一旦项目的讉K路径变了Q就ȝ了,昄不出囄来了Q传l的Ҏ是加<%=request.getContextPath()%>,但是在Struts2标签中不能这么引用?br />
?.0.11的时候还可以?br />
${pageContext.request.contextPath},但是必须使用theme=ajaxQ我q不想用Q?br />
?.1.2的时候ajax从标准标{ֺ中分出去了,想用也不行了?br />
现在只能不用Submit标签了,但是q想用它的一些功能,主要是那个action,method了,通过分析生成的代码ȝ新的Ҏ如下Q?br />
<input type="image" alt="删除指定用户"
src="<%=request.getContextPath() %>/images/btn/btn_del.gif"
id="doDelete" name="action:user!doDelete"
class="button_image" onclick="return CheckSelectForDelete();"/>
无他Q就是把标签中的action和method合ƈhQ加到name中去了其它的照旧?
]]> Spring和struts2的整?/title> http://www.aygfsteel.com/conans/articles/209888.htmlCONAN CONAN Sun, 22 Jun 2008 11:00:00 GMT http://www.aygfsteel.com/conans/articles/209888.html
在Struts2中整合Spring的IoC支持是一件十分简单的事情。让我们一步一步来实现Q?br />
1Q复制struts2-spring-plugin-x-x-x.jar和相应的spring.jar?WEB-INF/lib目录下?br />
2Q在struts.properties中设|struts.objectFactory属性?br />
struts.properties
struts.objectFactory = spring
或者是在XML文g中进行常量配|?br />
struts.xml
<struts>
<constant name="struts.objectFactory" value="spring" />
</struts>
3Q配|Spring监听?br />
web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
通过Spring配置来注册对?br />
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<bean id="personManager" class="com.acme.PersonManager"/>
</beans>
当然你也可以拥有更多的Spring配置文g。在web.xml中进行下列设|,从而Spring的ApplicationContext通过匚w所l定模式的文件来初始化对?br />
<!-- 用来定位Spring XML文g的上下文配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value>
</context-param>
4Q修改你的Struts配置文g
struts.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-default.xml"/>
<package name="default" extends="struts-default">
<action name="foo" class="com.acme.Foo">
<result>foo.ftl</result>
</action>
</package>
<package name="secure" namespace="/secure" extends="default">
<action name="bar" class="bar">
<result>bar.ftl</result>
</action>
</package>
</struts>
默认情况下,Spring从下面的文g中寻找ؓbar所做的配置
applicationConext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<bean id="bar" class="com.my.BarClass" singleton="false"/>
...
</beans>
5Q好了,现在你的Struts2和Springp正常的一起工作了。有几个配置技术点需要详l说明下Q装配模式。你可以通过讄修改struts.properties中下列属性的值来改变装配模式?br />
struts.objectFactory.spring.autoWire = type
该参数可供选择的设|值有
name
按照你的action的属性的名字和Spring里的bean的名字匹配,如果匚wp动装配。这?strong>~省?/strong>
type
按照你的action的属性的cdQ在Spring注册的bean中查找,如果相同p动装配。这需要你在Spring中仅注册了一个此cd的bean
auto
Spring会试图自动监来扑ֈ最好的Ҏ自动装配你的action
constructor
Spring会自动装配bean的构造函数的参数
是否使用cȝ存。你可以通过讄修改struts.properties中下列属性的值来改变是否使用Spring自n的类~存机制。可以设定的gؓtrue或falseQ默认ؓtrue?br />
struts.objectFactory.spring.useClassCache = false
]]> Struts2中的单Form多图片提交按?Submit)的? http://www.aygfsteel.com/conans/articles/209883.htmlCONAN CONAN Sun, 22 Jun 2008 10:55:00 GMT http://www.aygfsteel.com/conans/articles/209883.html 在Struts2里面一个Form中如果有多个提交按钮Q比如添加,更新Q保存等Q?br />
q些按钮使用一个ActionQ调用不同的ҎQƈ且在调用前要执行一个JavaScript的检查?br />
怎么用这个提交按钮?
l过ȝ如下Q?br />
先在form标签头指定Action的命名空_
<s:form namespace="/system/usermanager" >
然后如下调用Q?br />
<s:submit type="image" id="FIND" value="FIND" label="按指定条件检索用户信?
src="/issframe/images/btn/btn_find.jpg" cssClass="button_image"
onclick="return CheckInputForRequired();" action="user" method="doSearch"/>
上面是一个图片提交按钮的CZQ因Z般在目中都是用图片按?)
在onclick中执行javascriptQ记得不要漏掉return?br />
action是你要调用的Action在Struts2的配|文件中定义的那个name
例如Q?lt;action name="user_*" class="com.system.action.ManagerUserAction" method="{1}">
注意不包括通配W?"_"或?!"{??br />
mothed是ActioncM定义的对应的Ҏ了?
]]> strust2实践ȝ http://www.aygfsteel.com/conans/articles/209884.htmlCONAN CONAN Sun, 22 Jun 2008 10:55:00 GMT http://www.aygfsteel.com/conans/articles/209884.html
2Q在面中实现自动增加的序号用iterator的statuts的index属?egQ?
<s:iterator value="#request.inOutAccountList" id="data" status="listStat">
<s:property value="#listStat.index+1"/>
</s:iterator>
3:在actioncM取得request和session对象的方?
Map session = ActionContext.getContext().getSession();
HttpServletRequest request = ServletActionContext.getRequest ();
讄它们的值的Ҏ
session.put("operation", "add");
request.setAttribute("name", name);
面中取得它们的|
<s:property value="#session.operation"/>
<s:property value="#request.name"/>
4:面中奇偶行样式不一L控制ҎQ?
<tr class="<s:if test='#listStat.odd == true '>tableStyle-tr1</s:if><s:else>tableStyle-tr2</s:else>" >
5:单选框和复选框的用方?
1):可以讄默认选中|注意list的值的讄Q通过q种方式使key和value不一Pq种Ҏ比较常用(checkboxlist or radio)
<s:radio name="uncarInsPolicy.policyStateCode"
list="#{'5':'通过' , '2':'不通过'}"
listKey="key"
listValue="value"
value='5'
/>
2):q里的key和value的值是一L(checkboxlist or radio)
<s:checkboxlist
list="{'Red', 'Blue', 'Green'}"
name="favoriteColor"/>
6:struts2 中的标签会生成类似由<tr><td></td></tr>构成的字Ԍ具体什么标{成什么,可以查看生成后的面的源代码Q如果不限制q些多余代码的生成,面变得无法控Ӟ所以一般我们是不希望它生成多余的代码的Q具体的讄Ҏ如果Q在struts.xml中统一配置
<constant name="struts.ui.theme" value="simple"/>加上该句卛_
也可以通过在页面中tag的theme属性设?simple"取消光认的表格布局
不过最好是Q自定义一个themeQƈ其设ؓ默认应用到整个站点,如此一来就可以得到l一的站炚w?
7Qjsp面中格式化日期的方?
<s:date name="unCarInsModificationInfo.createTime" format="yyyy-MM-dd" nice="false"/>q样可以将日期格式化ؓyyyyQMMQdd的Ş?
8Q默认情况下Q当haction发生ӞStrutsq行ӞRuntimeQ根据struts.xml里的Action映射?Mapping)Q实例化action对应的类Qƈ调用其executeҎ。当Ӟ我们可以通过以下两种Ҏ改变q种默认调用
1Q在classes/sturts.xml中新建ActionQƈ指明其调用的Ҏ
比如惌用actioncM?
public String aliasAction() {
message ="自定义Action调用Ҏ";
return SUCCESS;
}
则在classes/sturts.xml中加入下面代码:
<action name="AliasHelloWorld" class="tutorial.HelloWorld" method="aliasAction">
<result>/HelloWorld.jsp</result>
</action>
既可用action名调用该Ҏ?
2Q(比较常用Q?
讉KActionӞ在Action名后加上“!xxx”Qxxx为方法名Q?
9QStruts 2.0有两个配|文Ӟstruts.xml和struts.properties都是攑֜WEB-INF/classes/下?
struts.xml用于应用E序相关的配|?
struts.properties用于Struts 2.0的运行时QRuntimeQ的配置
10:在actioncM取得web下某一文g夹物理\径(l对路径Q的Ҏ
filePath = ServletActionContext.getServletContext().getRealPath("/upLoadFiles")
11Q要惌回的面不是一个直接JSP面而是要先通过q回action中的Ҏd相应的数据再q回到jsp面Q有两种Ҏ
1Q在struts.xml中这么设|?
<result name="list" type="redirect-action">sysmanage/UserBaseInfoAction!findUserBaseInfo.action</result>
2Q在action中返回时直接调用q个Ҏ卛_
return findListQ)Q?
12Q设|checkboxlist中默认值的Ҏ
<s:checkboxlist name="skills1"
="Skills 1"
list="{ 'Java', '.Net', 'RoR', 'PHP' }"
value="{ 'Java', '.Net' }" />
<s:checkboxlist name="skills2"
label="Skills 2"
list="#{ 1:'Java', 2: '.Net', 3: 'RoR', 4: 'PHP' }"
listKey="key"
listValue="value"
value="{ 1, 2, 3 }"/>
13Q二Uq下拉框
<s:set name="foobar"
value="#{'Java': {'Spring', 'Hibernate', 'Struts 2'}, '.Net': {'Linq', ' ASP.NET 2.0'}, 'Database': {'Oracle', 'SQL Server', 'DB2', 'MySQL'}}" />
<s:doubleselect list="#foobar.keySet()"
doubleName="technology"
doubleList="#foobar[top]"
label="Technology" />
]]>
վ֩ģ壺
|
ׯ |
ʶ |
|
˫Ѽɽ |
ˮ |
|
» |
|
Դ |
̨ |
ǭ |
ͷ |
|
|
|
½ |
|
|
ֻ |
㶫ʡ |
ɽʡ |
|
|
罭 |
Т |
|
ͳ |
ī |
|
°Ͷ |
|
¸ |
Դ |
|
ǰ |
|
Դ |
|
ֺ |
̩ |