Struts 2之HelloWorld(下)

七.完成程序的国际化 因为一个企业应用经常要面对多区域的用户,因此,程序国际化是一个企业应用必须实现的功能.Struts2提供了非常好的程序国际化的支持. (1) 定义国际化资源文件 程序国际化设计思想是非常简单的,其主要的思想就是:程序界面中需要输出国际化信息的地方,我们不要再页面中直接输出信息,而是输出一个key值,该key值在不同的语言下对应不同的字符串.当程序需要显示的时候,程序将根据不同的语言环境,加载该key对应语言环境下的字符串,这样就可以完成程序的国际化. 为了给本应用增加程序国际化支持(支持中文和英文),则应该提供两份语言资源文件,下面是本应用程序所使用的中文语言环境下的资源文件的代码: view plaincopy to clipboardprint? 1. loginPage=登录页面 2. errorPage=错误页面 3. succPage=成功页面 4. failTip=对不起,您不能够登录 5. viewLink=查看图书列表 6. bookPageTitle=所有图书列表 7. bookName=书名 8. user=用户名 9. pass=密码 10. login=登录 loginPage=登录页面 errorPage=错误页面 succPage=成功页面 failTip=对不起,您不能够登录 viewLink=查看图书列表 bookPageTitle=所有图书列表 bookName=书名 user=用户名 pass=密码 login=登录 因为资源文件中包含了非西欧字符,因此必须使用native2ascii命令来处理该文件,将上面的文件保存在WEB-INF/classes路径下,文件名称为”messageResource.properties”保存该文件后,使用native2ascii命令来处理该文件,处理该文件的命令格式为: view plaincopy to clipboardprint? 1. native2ascii messageResource.properties messageResources_zh_CN.properties native2ascii messageResource.properties messageResources_zh_CN.properties 上面命令将包含非西欧字符的资源文件处理成ASCII格式,处理完成后生成了一份新的文件:messageResource_zh_CN.properties文件.这个文件的文件名符合资源文件的命名格式,资源文件的文件名的命名格式为: view plaincopy to clipboardprint? 1. basename_语言代码_国家代码.properties basename_语言代码_国家代码.properties 当请求来自简体中文的语言环境的时候,系统将自动的使用这种资源文件的内容输出. 除此之外,还应该提供如下英文语言环境下的资源文件: view plaincopy to clipboardprint? 1. loginPage=Login Page 2. errorPage=Error Page 3. succPage=Welcome Page 4. failTip=Sorry,you can't log in! 5. viewLink=View Books 6. bookPageTitle=All Books List 7. bookName=Book Name 8. user=User Name 9. pass=Password 10. login=Login loginPage=Login Page errorPage=Error Page succPage=Welcome Page failTip=Sorry,you can't log in! viewLink=View Books bookPageTitle=All Books List bookName=Book Name user=User Name pass=Password login=Login 将上面的资源文件保存在/WEB-INF/classes路径下面,文件名字为”messageResource_cn_US.properties”.当请求来自美国的时候,系统自动使用这份资源文件内容输出. (2) 加载资源文件 Struts2支持在JSP页面当中临时加载资源文件,也支持通过全局属性来加载资源文件,通过全局属性加载资源文件更加简单,本应用使用全局属性加载Struts2国际化资源文件. 加载资源文件可以通过struts.properties文件来定义,本应用的struts.properties文件仅有一行代码: view plaincopy to clipboardprint? 1. //定义Struts 2的资源文件的baseName是messageResource 2. struts.custom.i18n.resources=messageResource //定义Struts 2的资源文件的baseName是messageResource struts.custom.i18n.resources=messageResource 在struts.properties文件中增加上面的代码定义之后,表明该应用使用的资源文件的baseName为”messageResource”这与我们的前面保存的资源文件的baseName是一直的. Struts2默认加载WEB-INF/classes下面的资源文件,如果将该资源文件放在/WEB-INF/classes中的子路径下面,则需要修改struts.properties中的定义如下: view plaincopy to clipboardprint? 1. struts.custom.i18n.resources=supermos.messageResource struts.custom.i18n.resources=supermos.messageResource (3) 输出国际化信息 为了让程序可以显示国际化信息,则需要在JSP页面中输出key,而不是直接输出字符串常量. Struts2中提供了如下两种方式来输出国际化信息 ①:使用s:text标签来输出国际化信息. ②使用表达式方式输出国际化信息. 因此,我们再次修改表现层的JSP页面,使用国际化标签输出国际化信息.修改后的showBook.jsp页面代码如下: view plaincopy to clipboardprint? 1. <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> 2. 3. <%@taglib uri="/struts-tags" prefix="s"%> 4. 5. 6. 7. <s:property value="%{getText('bookPageTitle')}"/> 8. 9. 10. 11. 12. 13.

14. 15.

16. 17. 18. 19. 20.
21. 22. 23. 24.
25. 26. 27.
28.
29. 30. 31.

32. 33. <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%@taglib uri="/struts-tags" prefix="s"%>

<s:property value="%{getText('bookPageTitle')}"/>

我们发现,上面的JSP页面不再包含任何直接字符串,而是全部通过来输出国际化信息. 我们可以通过调整系统语言环境来观看本系统的运行状况. 八.增加数据校验 在上面的应用中,即使浏览器输入任何的用户名,密码系统也会处理用户的请求,在我们的整个Helloworld应用中,这种空用户名,空密码的问题不会引起太大的问题,但是如果数据需要保存到数据库,或者需要根据用户输入的用户名,密码查询数据,这些数据就可能会引发异常. 为了避免用户的输入引起底层的异常,通常,我们会在进行业务逻辑的操作之前,先执行基本的数据校验. (1) 继承ActionSupport ActionSupport类是一个工具类,它已经实现了Action接口,除此之外,它还实现了Validateable接口,提供了数据的校验功能.通过继承该ActionSupport类,可以简化Struts2的Action开发. 在Validatable接口中定义了一个validate()方法,重写该方法,如果校验表单输入域出现错误,则将错误添加到ActionSupport类中的fieldErrors域中,然后通过OGNL表达式负责输出. 为了让Struts2增加输入数据校验功能,改写程序中的LoginAction,增加重写validate方法,修改后的LoginAction类代码如下: view plaincopy to clipboardprint? 1. package com.supermos.app; 2. 3. import com.opensymphony.xwork2.Action; 4. import com.opensymphony.xwork2.ActionContext; 5. import com.opensymphony.xwork2.ActionSupport; 6. 7. public class LoginAction extends ActionSupport implements Action { 8. private String username; 9. private String password; 10. 11. public String getUsername() { 12. return username; 13. } 14. 15. public void setUsername(String username) { 16. this.username = username; 17. } 18. 19. public String getPassword() { 20. return password; 21. } 22. 23. public void setPassword(String password) { 24. this.password = password; 25. } 26. 27. public String execute() throws Exception { 28. 29. if ("supermos".equalsIgnoreCase(username) 30. && "ziwen".equalsIgnoreCase(password)) { 31. // 通过ActionContext对象访问Web应用的Session 32. ActionContext.getContext().getSession().put("user", getUsername()); 33. return SUCCESS; 34. } else { 35. return ERROR; 36. } 37. } 38. 39. // 完成输入校验需要重写的validate方法 40. public void validate() { 41. // 如果用户名为空,或者用户名为空字符串 42. if (getUsername() == null || getUsername().trim().equals("")) { 43. // 添加表单校验错误 44. addFieldError("username", "user.required"); 45. } 46. // 如果密码为空,或者用户名为空字符串,添加表单校验错误 47. if (getPassword() == null || getPassword().trim().equals("")) { 48. // 添加表单校验错误 49. addFieldError("password", "password.required"); 50. } 51. } 52. } package com.supermos.app; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport implements Action { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute() throws Exception { if ("supermos".equalsIgnoreCase(username) && "ziwen".equalsIgnoreCase(password)) { // 通过ActionContext对象访问Web应用的Session ActionContext.getContext().getSession().put("user", getUsername()); return SUCCESS; } else { return ERROR; } } // 完成输入校验需要重写的validate方法 public void validate() { // 如果用户名为空,或者用户名为空字符串 if (getUsername() == null || getUsername().trim().equals("")) { // 添加表单校验错误 addFieldError("username", "user.required"); } // 如果密码为空,或者用户名为空字符串,添加表单校验错误 if (getPassword() == null || getPassword().trim().equals("")) { // 添加表单校验错误 addFieldError("password", "password.required"); } } } 上面的Action重写了validate方法,该方法会在执行系统的execute方法之前执行,如果执行该方法之后,Action类的fieldErrors中已经包含了数据校验的错误,请求将被转发到input逻辑视图处. 为了在校验失败之后,系统能够将试图转入input处,必须在配置Action时候配置input属性,下面是修改之后的loginAction的配置片段: view plaincopy to clipboardprint? 1. 2. 5. 6. 7. 8. /login.jsp 9. /success.jsp 10. /fail.jsp 11. 12. 13. /login.jsp 14. /showBook.jsp 15. 16. 17. /login.jsp /success.jsp /fail.jsp /login.jsp /showBook.jsp 运行测试一下,我们发现我们并未在输入页面输出这些校验错误信息,但是页面上却自己输出了..这是因为struts2的标签,上面的JSP页面中表单使用的不是HTML表单,而是使用了标签,这种标签已经具备了输出校验错误的能力.(Struts 2的默认已经提供了输出校验错误的能力) 但是上面的程序还有一个问题:校验信息的国际化,查看上面的Action代码发现,重写validate方法的时候,如果发生校验失败的问题,校验错误的提示信息时以硬编码的形式写死了..这样就是去了国际化的能力. 实际上,ActionSupport类已经提供了国际化信息的能力,它提供了一个getText(String key)的方法,该方法用于从资源文件中获取国际化信息,为了让校验信息支持国际化,再次改写Action里的validate方法,修改之后的validate方法代码如下: view plaincopy to clipboardprint? 1. package com.supermos.app; 2. 3. import com.opensymphony.xwork2.Action; 4. import com.opensymphony.xwork2.ActionContext; 5. import com.opensymphony.xwork2.ActionSupport; 6. 7. public class LoginAction extends ActionSupport implements Action { 8. private String username; 9. private String password; 10. 11. public String getUsername() { 12. return username; 13. } 14. 15. public void setUsername(String username) { 16. this.username = username; 17. } 18. 19. public String getPassword() { 20. return password; 21. } 22. 23. public void setPassword(String password) { 24. this.password = password; 25. } 26. 27. public String execute() throws Exception { 28. 29. if ("supermos".equalsIgnoreCase(username) 30. && "ziwen".equalsIgnoreCase(password)) { 31. // 通过ActionContext对象访问Web应用的Session 32. ActionContext.getContext().getSession().put("user", getUsername()); 33. return SUCCESS; 34. } else { 35. return ERROR; 36. } 37. } 38. 39. // 完成输入校验需要重写的validate方法 40. public void validate() { 41. // 如果用户名为空,或者用户名为空字符串 42. if (getUsername() == null || getUsername().trim().equals("")) { 43. // 添加表单校验错误 44. addFieldError("username", getText("user.required")); 45. } 46. // 如果密码为空,或者用户名为空字符串,添加表单校验错误 47. if (getPassword() == null || getPassword().trim().equals("")) { 48. // 添加表单校验错误 49. addFieldError("password", getText("password.required")); 50. } 51. } 52. } package com.supermos.app; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport implements Action { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute() throws Exception { if ("supermos".equalsIgnoreCase(username) && "ziwen".equalsIgnoreCase(password)) { // 通过ActionContext对象访问Web应用的Session ActionContext.getContext().getSession().put("user", getUsername()); return SUCCESS; } else { return ERROR; } } // 完成输入校验需要重写的validate方法 public void validate() { // 如果用户名为空,或者用户名为空字符串 if (getUsername() == null || getUsername().trim().equals("")) { // 添加表单校验错误 addFieldError("username", getText("user.required")); } // 如果密码为空,或者用户名为空字符串,添加表单校验错误 if (getPassword() == null || getPassword().trim().equals("")) { // 添加表单校验错误 addFieldError("password", getText("password.required")); } } } 在上面的validate方法中,添加校验错误提示的时候,并不是直接给出了错误的字符串,而是调用了getText方法来获取错误提示.在国际化资源文件中添加这两条提示信息.(ActionSupport增加了让提示信息国际化的能力,ActionSupport提供的getText方法可以根据资源文件加载获得国际化提示信息.) (2) 使用Struts2的校验框架 上面的方法是通过重写ActionSupport类的validate方法来实现的,这种方法虽然不错,但是需要大量重写validate方法,毕竟重复书写相同的代码不是一件吸引人的事情. 就像Struts1一样,Struts2也允许通过定义配置文件来完成数据的校验,Struts2的校验框架实际上是基于Xwork的validator框架: 下面还是使用原来的Action类(即不重写validate方法),却增加了一个校验配置文件,校验配置文件通过使用Struts2已有的校验器,完成对表单域的校验.Struts2提供了大量的数据校验器,包括表单域校验器和非表单域校验器两种. 本应用主要使用了requiredstring校验器,该校验器是一个必填校验器---指定某个表单域必须输入. 下面是校验规则的定义文件: view plaincopy to clipboardprint? 1. 2. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 定义完该校验规则文件之后,该文件的命名应该遵守如下规则: ActionName-validate.xml:其中ActionName就是需要校验的Action的类名 因此上面的校验规则文件就应该命名为”LoginAction-validate.xml”且,该文件应该与Action类的class文件位于同一个路径下. 当然,在struts.xml文件的Action定义中,一样需要定义input的逻辑视图名,并将input逻辑视图映射到login.jsp表单. 如果不输入用户名,密码而提交表单,将再次看到如图2.14所示的界面.在这种校验方式下,无需书写校验代码,只要通过配置文件配置指定的校验规则就可以了.因此提供了更好的可维护性.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值