看完了框架之间的联系之后,下面开始看每一个类是怎么实现的,主要是两个类,HelloWorld和Login。
HelloWorld
首先是HelloWorld,在example.xml中有这一段代码。
<action name="HelloWorld2" class="example.HelloWorld2">
<result name ="success">/example/HelloWorld.jsp</result>
</action>
意思是当HelloWorld中excute方法后会返回success,然后执行HelloWorld.jsp,jsp中是这样的。(大家忽略HelloWorld2中的2,我只是重命名了一下而已= =)下面是jsp文件。
<head>
<title><s:text name="HelloWorld.message"/></title>
</head>
<body>
<h2><s:property value="message"/></h2>
<h3>Languages</h3>
<ul>
<li>
<s:url id="url" action="HelloWorld">
<s:param name="request_locale">en</s:param>
</s:url>
<s:a href="%{url}">English</s:a>
</li>
<li>
<s:url id="url" action="HelloWorld">
<s:param name="request_locale">es</s:param>
</s:url>
<s:a href="%{url}">Espanol</s:a>
</li>
</ul>
</body>
头部用了<s:text>标签,name=’HelloWorld.message’这个是OGNL的语法(详细见《深入浅出struts2》),通过这一句可以直接访问package.properties文件中的属性值。
在body里面有这一句<h2><s:property value="message"/></h2>,这里有一个message属性,这个属性来源于调用jsp的HelloWorld.action。因为在HelloWorld.class里面已经设置了message的值,因此这里可以调用getter获得message。如果是在浏览器中直接请求HelloWorld.jsp或者是通过其他方法来调用HelloWorld.jsp是不会显示这个message属性的。就是没有了struts is up and running这一行。
这里用<s:url>创建了一个新的url,并且创建超链接,点击后触发相应的动作。<url>标签里面的Locale是用于实现国际化的,国际化之后es代表的是西班牙。将这个参数传进去后就可以自动将语言实现英文和西文之间的切换。当然实现西文切换需要有相应的package_es.properties对应使用。
运行结果是这样的。
开始做实验。将HelloWorld.jsp改成下面这样
<head>
<title><s:text name="HelloWorld.message"/></title>
</head>
<body>
<h2><s:property value="message"/></h2>
<h2><s:property value="HelloWorld.message"/></h2>
<h3>Languages</h3>
<ul>
<li>
<s:url id="url" action="example.logTest">
<s:param name="request_locale">en</s:param>
</s:url>
<s:a href="%{url}">Englishlalala</s:a>
</li>
<li>
<s:url id="url" action="example/Test">
<s:param name="request_locale">es</s:param>
</s:url>
<s:a href="%{url}">Espanol</s:a>
</li>
<li>
${message}
<li>
</ul>
</body>
运行的结果是
当点击Englishlalala的时候就会触发logTest动作(这个动作我自己在example.xml中添加了)。点击Test就会报404错误,因此动作的格式应该是PACAKGE.ACTIONNAME.并且在body上方没有显示HelloWorld.message.这说明了property标签不能获取配置文件里面的数据,只能获得动作属性的值(HelloWorld.class中的message属性)
同样的获取属性的方法还有${message},也可以更快捷的获得属性,这个叫做EL语言。
Welcome.jsp和Login
进入到Welcome页面后点击sign On会跳转到Login_input.action,如果不输入直接submit就会直接跳转到Login.action,并且显示的是User Name is required。如果随便输入用户名密码后就会定向到在Login.action中定义的redirectAction中。
首先,这里不输入会跳转是触发了validation.intercepter. 我们看到Login-validation.xml
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="requiredstring"/>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message key="requiredstring"/>
</field-validator>
</field>
</validators>
这里定义了两个字段,并且有两个字段的验证器,这里第二个key=”requiredstring”是定义在资源文件里面的,而第一个requiredstring是struts自带的验证拦截器。这里的username和password字段名都来自资源文件,分别对应下图的属性值。getText()方法是从属性文件中取得相应的属性值。
<s:form action="Login">
<s:textfield key="username"/>
<s:password key="password" />
<s:submit/>
</s:form>
当没有输入不成功的时候,就会触发<result name = input>,至于为毛叫input我也不造。根据example.xml的设定会转到Login.jsp。但是很明显我们是没有看到Login.jsp中有显示XXX is required的代码,因此这里会显示的原因完全是在validation中的功劳,显示的是requiredstring的属性值。
举个栗子,如果在属性文件中加入一个新的属性字段string,值为NULL,然后把代码修改成这样
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="string"/>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<!-- <message key="requiredstring"/>-->
<message> Please </message>
</field-validator>
</field>
</validators>
结果就会是这样。
但是这个Message会以什么样的样式显示出来,又会显示在什么地方,能不能自我定制Message的地方,是怎么调用显示的,这些技术细节全部都在原代码中被隐藏了,因此我觉得struts2实在是太不安全了。
其次这里还有一个问题,在Login.java中是没有定义Input方法的,因此这里咋Welcome.jsp中点击SignOn后触发的Login_Input动作 会跳转到Login.jsp是我无法理解的。难道又是struts2内部配置的?靠。
ExampleSupport
最后说一下这个神秘的父类,其实就是继承了ActionSupport类,这个类凡是action都要继承的。就这么简单
调用资源文件
两种方法
(1) 在jsp 中: <s:textname="key"/>
(2) 在Java 中:使用ActionSupport类的getText(.....)方法,这个getText方法package.properties中也可以看到,但是这个不是直接在资源文件中解释的,将值返回到java类之后再解释再获取一遍properties中的值的。
于是,可恶的sturts-blank2就看完了。还有Log4j啊,国际化啊这些知识以后再看。