Stripes是一个以让程序员的web开发简单而高效为准则来设计的基于动作的开源Java web框架。本文将介绍Stripes与其它如Struts之类基于动作的框架的区别和其提供的一些存在于Ruby on Rails之中的简单性。

  Stripes是一个以让程序员的web开发简单而高效为准则来设计的基于动作的开源Java web框架。传统的Java web开发着眼于借去耦(Decoupling)来实现其灵活性,但导致多个的配置文件,额外的对象,和其他资源的分散。这些困难造成相当多的程序员的更高的学习时间和低下的效率。其结果是有些Java程序员被一些非Java的框架所吸引去了:Ruby on Rails或者Django。一些Java web框架,如Stripes,正在开始从这些非Java框架中汲取其成功经验:简单而高效的开发。本文将介绍Stripes与其它如Struts之类基于动作的框架的区别和其提供的一些存在于Ruby on Rails之中的简单性。

  图1是典型的用Stripes写的 应用 程序中的正常事件流程和组件。

 
图 1 典型Stripes流程

  如你所见,其流程基本上就是一个MVC框架。Stripes和其他的基于动作的框架的一个主要的区别是没有一个外部的配置文件。我们随后将看到,Stripes用annotation和约定而非配置来提高产出和减少杂乱。

   编写你的第一个Stripe动作(Action)

  让我们现在就开始通过创建Hello World例程来了解Stripes框架和理解其运作。HelloWorldAction类将提示用户输入姓氏和名字然后在另一个 View 里面显示,首先我们来编写controller类。

public class HelloWorldAction implements ActionBean
{
 @ValidateNestedProperties(
 {
  @Validate(field = "firstName", required = true, on = {"hello"}), 
  @Validate(field = "age", required = true, minvalue = 13, on = {"hello"})
 })
 private Person person; 
 private ActionBeanContext context; 
 @DefaultHandler public Resolution index()
 {
  return new ForwardResolution("Hello.jsp");
 }
 public Resolution hello() 
 {
  return new ForwardResolution("SayHello.jsp");
 }
 public void setPerson(String person) {this.person = person;}
 public String getPerson() { return person;}
 public void setContext(ActionBeanContext c) {this.context = c; }
 public ActionBeanContext getContext() {return context; }}

  Controller类是一个实现了Stripes特有接口ActionBean的POJO(Plain Old Java Object,译注:读破粥)。所有的Stripes动作类都要实现这一接口以让StripesDispatcher servlet在运行服务时为其注入一个ActionBeanContext对象。ActionBeanContext对象可以让你存取的对象如request、response、和servlet context等servlet API。大多数时候在Stripes应用中是不用读取这些底层API对象的。

  ActionBeanContext类还提供当前动作的状态并可以添加信息消息和错误消息到当前动作中。ActionBeanContext的变量和其读写方法可以放在一个基类里面,因为所有的Stripes动作都要实现之。

  Controller类的其他部分对于任何Java程序员来说都是很面熟的。有一个Person对象和其读写方法是用来读写用户的姓名给view的。虽然这仅仅是一个简单的嵌套对象,Stripes可以通过Java集合、泛型支持、和下标化的属性来实现更复杂完善的数据捆绑。因为Stripes可以处理复杂数据捆绑,你的领域对象(Domain Object)可以在其他需要它们的层重用。例如:通过Stripes你可以很容易的收集一个领域对象的信息,然后用其他的POJO框架,如Hibernate或者EJB3来对其进行持久化。

  Person对象变量上有一个Stripes验证annotation用来保证用户在激活hello方法的时候已经输入了姓名。如果用户没有输入这两个必需的变量,原始页会被返回,并显示一个相关的错误消息。该验证只有在hello事件被申请的时候才会被激活,因为annotation的属性中指定了(on = {"hello"})。Stripes还会使用实用默认法则,根据验证方法和变量名称产生一个错误信息。例如,如果Person类的firstName变量在提交的时候没有提供,用户将看到:

Person First Nameis  a required field.

  这条消息是通过将Person.firstName进行刻读化处理后得到的。如果有必要,这些错误消息可以被重载来提供更多的客户自定义功能。

  另外还有一个Integer类型的变量age,是Person对象的一个属性。Stripes首先试图对request中命为person.age的parameter转换为Integer类型,并将其捆绑到Person对象上。在Person对象的age变量被付值以后,Stripes将验证该Integer值是否小于13。如果用户输入了一个字符串而非整数,用户得到这个消息:

The value (Mark) entered in field Person Age mustbe a  valid number.

  若是用户输入了一个小于13的整数,用户将看到这个消息:

The minimum allowed value for Age is 13.

  同样地,我们没有必要为这些错误消息提供任何外部的配置文件。Annotation提供的验证与你的变量在同一个位置上,使得程序员定位验证、理解验证的内容、和对验证进行维护变动更容易。

  这个Stripes动作还有两个可被激活的方法(称为事件)。事件是ActionBean类中有如下特征的方法:

public Resolution eventName

  请注意index方法被标注为@DefaultHandler annotation。因为在本动作中有多个事件,其中一个必须被指定为默认事件。如果调用本动作的URL没有指定哪个事件,Stripes则查找标注有@DefaultHandler annotation的事件,并执行。

   显示层(View)

  现在让我们给Hello World例程加上显示层的逻辑。Stripes默认支持JSP为显示层的标准技术,不过你也可以用其他的显示层技术,比如FreeMaker。除了Stripes的tag库以外,没有什么新的东西要学。Hello.jsp是初始的显示,可以让用户输入和提交姓名。

<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld" %>
......
<stripes:errors/> 
<stripes:form beanclass="com. myco. web. stripes. action. example. HelloWorldAction"> Say hello to: <br> First name: 
<stripes:text name="person.firstName"/> <br> Age:<stripes:text name="person.age"/><br> 
<stripes:submit name="hello" value="Say Hello"/> 
</stripes:form>
......

  这个JSP易读 易维 护。而Stripes用于form和input的tag跟对应的HTML代码非常相似。stripes:form tag包含一个beanclass属性,其值为我们前面定义的controller类的完整类名。我们可以用stripes:form中的action属性来替换beanclass属性,但是beanclass属性可以让你在以后对Stripes动作进行重构的时候更加方便。如果你要用在stripes:form tag中使用action属性,方法如下:

<stripes:form action="/example/HelloWorld.action">

  有一个stripes:input tag指定了一个名为person.firstName属性,其作用是将其储存的输入值付给controller的Person对象的firstName变量中。最后,stripes:submit tag指定一个name属性来告诉Stripes的HelloWorldAction类使用哪一个事件。

  我们现在已经完成了提交姓名的值给HelloWorldAction,剩下的就是在另一个view中将其反馈给用户了。

<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld" %>
......
<stripes:errors/>
<h2>Hello ${actionBean.person.firstName} your age is ${actionBean.person.age} </h2> <p/>
<stripes:link beanclass="com.myco.web.stripes.action. example.HelloWorldAction"> Say Hello Again 
</stripes:link>
......

  本JSP将自己通过一个对动作的引用读取person的姓名信息并显示。为达到这一目的,Stripes自动在request的属性中添加一个名为actionBean动作对象,以供JSTL存取。最后,我们用了一个strips:link tag来建立一个返回HelloWorldAction地链接从而可以让我们输入不同的姓名。我们以可以通过如下办法显式地创建一个指向index事件的stripes:link:

<stripes:link beanclass="com.myco.web.stripes.action. example.HelloWorldAction" event="index">
Say Hello Again
</stripes:link>

  因为我们已经用annotation把index方法标记为@DefaultHandler,Stripes无须event属性也知道要执行哪一个方法。

 用约定、不用配置文件

  我们现在有了Java组件,我们该做配置了,把动作映射的一个URL上,并将其连接到我们的两个view上面去。等一下!我们在用Stripes,我们不需要外部配置文件!

  虽然这听来好像好得不像是真的,但这的确是Stripes的一项最具生产效率的功能。Stripes使用约定而非配置文件来映射动作到URL上。我们也无须使用一个外部配置文件来把view映射到一个个标记名字上。这意味着程序员不用再为了一个标记名字——比方说SUCCESS——的实际来源,而在配置文件中跳来跳去了。没有必要在Java和view组件的外部进行配线,因而导致更好地维护性和更高的生产率。

  Stripes是如何提供隐式的URL映射而无需在外部配置每一个动作或者而外的annotation呢?这个可以从Stripes在web.xml中的配置以及它是如何通过实用默认法建立URL映射来解释。首先,我们来看看Servlet过滤器:StripesFilter。其在web.xml中的默认配置如下:

<filter> 
<display-name>Stripes Filter</display-name>
<filter-name>StripesFilter</filter-name>
<filter-class> net.sourceforge.stripes.controller.StripesFilter </filter-class> 
<init-param> 
<param-name>ActionResolver.UrlFilters</param-name>
<param-value>/WEB-INF/classes</param-value>
</init-param>
</filter>

  当Servlet容器启动的时候,StripesFilter对其init-param元素执行初始化。其中最重要的init-param元素就是ActionResolver.UrlFilters参数。这个参数告诉Stripes到哪里查找跟Stripes有关的类。这个例子里面,Stripes将查找/WEB-INF/classes目录下的所有实现ActionBean接口的类。每一个被找到的类和其绑定的URL都将被加入一个 Map 中。

  让我们来看看Stripes是如何处理我们的HelloWorldAction动作为例子吧。因为HelloWorldAction类位于/WEB-INF/classes目录下,所以会被认为是一个Stripes servlet。在我们的例子当中,其完整类名是com.myco.web.stripes.action.example.HelloWorldAction。随后,其完整类名将按照如下法则被翻译成一个URL绑定。

  1. 将含有www、web、stripes、和action的部分及其以前的内容删掉。在我们的例子有三个上述单词,所以我们得到了example.HelloWorldAction。

  2. 如果类名中包涵带Action或Bean的尾巴,删掉。因为我们的类名以Action结尾,我们得到了example.HelloWorld。

  3. 将.替换为/,我们得到了example/HelloWorld。

  4. 最后,添加上一个尾缀(默认是.action)从而完成了URL绑定。最后的结果是example/HelloWorld.action。

  现在Stripes找到了ActionBean类并为其创建了一个URL绑定,然后存放在一个java.util.Map<String, Class<? extends ActionBean>>之中。其中key参数是URL绑定,value参数是实现ActionBean的类名。下面是我们的例子中的Map:

  URL绑定:/example/HelloWorld.action
  ActionBean类:com.myco.web.stripes.action.example.HelloWorldAction

  我们要看的第二个组件是Stripes如何把URL绑定翻译成你正在做的这个ActionBean类。这是Stripes调度servlet的职责,在web.xml中的配置如下:

<servlet>
<servlet-name>StripesDispatcher</servlet-name> 
<servlet-class>
net.sourceforge.stripes.controller.DispatcherServlet </servlet-class> 
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping> 
<servlet-name>StripesDispatcher</servlet-name> 
<url-pattern>*.action</url-pattern>
</servlet-mapping>

  StripesDispatcher的一个职责就是将URL解析为Stripes的ActionBean类。当用户激活URL http://host/uri/example/HelloWorld.action的时候,Stripes调度servlet将在URL映射表中查询并找到com.myco.web.stripes.action.example.HelloWorldAction类,并实例化产生该类的一个实例。最后,index方法被激活,因为在annotation中它被定义为默认局柄而在该URL中并没有指定一个事件。

  如果我们想要直接执行HelloWorldAction中的hello方法怎么办?应该象下面这个URL这样把事件的名字放在request的参数中:

http://host/uri/example/HelloWorld.action?hello=&firstName=Mark&age=13

  请注意我们没有给hello这个request参数名指定任何值。在这个情况下,StripesDispatcher会把hello这个这个request参数名和HelloWorldAction类中个一个带有public Resolution hello()签名的函数识别并映射。该方法名城在初始化的时候为了性能而缓存在另一个Map中。

  我们已经看到Stripes的基础以及如果创建简单的动作和一些该框架是如何运作的细节。通过在web.xml中的初始化,我们能够避免用多个单独的XML配置文件来把我们的显示层组建写在一起。这很重要,原因如下:首先,如果你需要任何改动,你可以看到一个URL就立即知道你该查看哪一个类。其次,我们不需要任何单独的工具来在你的配置文件过大而且不可管理的时候帮助你。通过消除掉配置文件,我们不再需要给框架一大堆的metadata。最后,我们不再需要为一个独立的用来描述我们的组件是如果相互关联的文件来一刻不停维护了。

   Ajax

  要不要更高级的功能?那我们就来看看Stripes是怎么处理Ajax的。我们将把先前的Hello World例程改成使用Ajax调用Stripes动作。本例子的 源代码 可以在本文资源中找到。首先,我们对Hello.jsp作改动使其引用Prototype JavaScript函数库。我们还要为Ajax调用增加一个JavaScript函数,并更改提交按钮为其添加一个onclick事件:

<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld" %>
...... 
<script src="${pageContext.request.contextPath}/js/prototype.js" type="text/javascript">
</script> 
<script type="text/javascript"> 
function sayHelloAjax(){
 var myAjax = new Ajax.Updater('hello', "<stripes:url beanclass="com. myco. web. stripes. action. example. HelloWorldAction" event="sayHelloAjax"/>", { method: 'get', parameters: Form.serialize('helloForm') }); 
 }
 </script>
 ......
 <stripes:errors/> 
 <stripes:form beanclass="com. myco. web. stripes. action. example. HelloWorldAction" id="helloForm">
 Say hello to: 
  <br> First name:
  <stripes:text name="person.firstName"/><br>
  Age:<stripes:text name="person.age"/><br>
  <stripes:button name="helloAjax" value="Say Hello" οnclick="sayHelloAjax()"/> 
   <div id="hello"></div> 
 </stripes:form> ......

  stripes:button有一个onclick事件将会调用HelloWorldAction类中的sayHelloAjax方法并将其结果返回在一个叫hello的div tag中。下面是我们要在HelloWorldAction中介绍的一个新方法:

public Resolution sayHelloAjax()
{
 return new ForwardResolution("SayHelloAjax.jsp"); 
}

  这个方法没有多少工作,因为Stripes已经承担了姓名内容的绑定。因此,本方法唯一的责任就是转发到一个叫SayHelloAjax.jsp的页面片断上去。该叶面片段的内容如下:

<h2>Hello ${actionBean.person.firstName} your age is ${actionBean.person.age}!</h2>

   Spring整合

  Stripes还内置了对Spring支持。你可以自动地将Spring bean诸如到你的动作中。按照Stripes的风格,除了Spring上下文配置文件以外不需要任何外部配置文件。如果我们Spring的配置文件如下:

<bean id="personService" parent="abstractTxDefinition">
<property name="target"> 
<bean class="com.myco.service.impl.PersonServiceImpl"/> 
</property>
</bean>

  要把person服务注入到一个Stripes动作中,得增加一个跟Spring bean的名字一致的属性和setter。Stripes提供了@SpringBean annotation来查询正确的Spring bean以注入到动作之中。下面是我们要在动作类中包含的例子:

private PersonService personService;
@SpringBeanpublic void setBlogService(BlogService blogService) 
{
this.blogService = blogService;
}

  本文无法囊括Stripes的所有高级功能。但是,Stripes有非常完整的文档。Stripes还包含了一个与Tiles类似但无需外部配置文件的layout管理器。另外,拦截器还可以用于生命周期事件的各处、文件上载等等等等。

   结论

  Stripes是一个既强大又简单的Java web框架。Stripes利用了Java 5的annotation和泛型功能,从而使得Java程序员避免维护外部配置文件并增加工作效率。Stripes可以简化困难的web开发工作,并使得简单的工作更加简单!

利用Stripes实现Java Web开发相关推荐

  1. 基于Stripes框架进行Java Web开发

    Mark Eagle是美国乔治亚州亚特兰大市MATRIX Resources有限公司的一位资深软件工程师,拥有Sun公司的SCP和SCWCD认证.Mark本人非常喜欢使用开源软件进行软件开发,并且多次 ...

  2. Java Web开发API Boy如何进阶?

    导语 | Java Web后台开发基本都离不开Spring生态这一套,Spring框架功能极其强大,会帮忙做许多工作,我们通常只需要在一个函数(包含request和response两个入参)中写处理逻 ...

  3. java web 开发之写在前面(0)

    java是sun公司(现在属于Oracle公司)推出的能够跨越多平台的.可以执行最高的一种面向对象的编程语言,也是目前最先进.特征最丰富.功能最强大的计算机语言.利用java可以编写桌面应用程序,we ...

  4. 如何搭建java web环境_搭建java WEB开发环境和应用

    搭建java WEB开发环境和应用 更新时间:2009年06月07日 02:28:56   作者: 使用Tomcat服务器,使用DBCP数据源搭建Web开发环境 一 使用Tomcat服务器,使用DBC ...

  5. 追新求快的时代,别让 Java Web 开发必备工具 Tomcat 变成“熟悉的陌生人”!

    作者 | 码哥字节 来源 | MageByte技术团队 Tomcat 发展这么多年,已经比较成熟稳定.在如今『追新求快』的时代,Tomcat 作为 Java Web 开发必备的工具似乎变成了『熟悉的陌 ...

  6. java web开发初学_2018年学习Web开发的绝对初学者指南

    java web开发初学 This post was originally published on Coder-Coder.com. 该帖子最初发布在Coder-Coder.com上 . If yo ...

  7. Java框架JSON-RPC项目demo代码实战 + JAVA WEB配置虚拟目录(转自21天java web开发)

    Java框架JSON-RPC项目demo代码实战 备注  JAVA WEB配置虚拟目录(转自21天java web开发) https://blog.csdn.net/wjxbj/article/det ...

  8. [Java Web整合开发王者归来·刘京华] 1、 Java Web开发

    目录: 1.Web技术简介 2.动态网站与静态网站 3.Java Web开发模式 4.JavaScript简介 1.Web技术简介 PS: 最近还有更凶残的技术,即整个操作系统都是基于Web的,如火狐 ...

  9. 230套java web开发PDF书籍和CHM参考手册资料大全 免费下载

    230套java web开发PDF书籍和CHM参考手册资料大全 免费下载 下载地址:http://yun.baidu.com/s/169jYH 文章来源:HTML5星空http://www.html5 ...

最新文章

  1. rpa操作excel_RPA的功能与技术剖析
  2. sbt+Scala IDE建立Scala项目
  3. 关于listen的第二个参数backlog的一些问答见解
  4. hexo右下角弄一个live2d的卡通动画小人
  5. [转载]VC++程序员应当如何阅读ADO文档
  6. 计算机中丢失msc,mscvr120.dll32位/64位版_修复计算机中丢失msvcr120.dll
  7. 【Java】求100以内的斐波那契数列
  8. dnf丢失clientbase_clientbase.dll
  9. 动作捕捉系统用于模仿学习
  10. Mac ssh: connect to host XXX.XXX.XXX.XXX port XX: Operation timed out的问题解决
  11. 2022-2028全球光纤束行业调研及趋势分析报告
  12. TCP——粘包/拆包
  13. android部分代码片段(例:判断设备为手机,获取mac地址,软键盘,唤醒屏幕等)
  14. CAD制图初学入门:CAD机械软件中如何构造孔?
  15. 什么是Java你了解吗
  16. 行动力强大的人,都是“二进制”的
  17. PS-InSAR大坝稳定性监测
  18. 社会保障类毕业论文文献有哪些?
  19. Laravel 如何实现中英文国际化
  20. 电脑直接安装centOS

热门文章

  1. 构造Linux的图形化安装程序(1)(转)
  2. mysql数据库事务隔离级别的查看、设置、以及隔离级别有效范围的设置
  3. 经典软件测试基础面试问答
  4. 笔记本电脑如何查看已经连的无线网络WIFI密码
  5. 日媒 Jungle City 专访:打造让区块链技术易于使用的开发者平台 | ArcBlock 媒体
  6. 计算机要通过手机传播,教你一个手机电脑互传功能的小妙招,比蓝牙传输快千倍...
  7. keil与source insght项目重命名
  8. eXact测量密度、网点、叠印率
  9. illustrator插件--常用功能开发--查找白色叠印--js脚本开发--AI插件
  10. 苹果生产日期对照表2020_【穿戴】AirPodsPro出现声音问题 你中招了么?苹果:免费更换|airpods|pixel|无线耳机|谷歌...