東川印記

一本東川,笑看爭龍斗虎;寰茫兦者,度橫佰昧人生。

Struts<学Ⅱ>

2009年3月10日星期二



Struts是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。由于Struts能充分满足应用开发的需求,简单易用,敏捷迅速,在过去的几年中颇受关注。Struts把Servlet、JSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间,所以说Struts是一个非常不错的应用框架。很多公司开发的产品都是基于此框架的。

当然,有朋友一提起编程就觉得头痛,是否如此呢?我想通过本期的struts教程,你便会有自己的结论哟!

本期struts教程本着从易用、实用的目的出发,带您手把手地完成公司开发中常用模块的开发,使你迅速上手struts。

主要通过以下六个模块:

一、登录验证实例

二、解决中文乱码问题实例

三、连数据库实例

四、国际化

五、验证数据实例

六、模块使用实例

七、制作简单留言板实例

使大家对struts能由浅入深的学习,最终撑握它。

万事开头难,就让我们一起来经历struts的开发吧,经过本系列的学习,你肯定能很快地驾驭它。给自己多几分信心吧!

闲话不多说,接下来就开始实战吧!!

一、普通的登录验证实例

效果图:

我们以结果为导向,首先大家先看看要完成的效果图,对接下来要做的事情有个清晰的认识。

1、如图键入:

 

显示结果如下图:

 


如果您输入的是合法的话,则如下图:

 


开发步骤:

A、首先建立一工程,选择web模块,最后再加载struts包即可。在工程中新建一包,命名为actions,在下面新建一类文件,命名为LoginAction,里面一定要重写execute方法,注意参数的顺序及返回类型都是不可以变化的。

在struts中action类起着控制转向的作用,当我们输入用户名与密码并点了提交按钮后,需要交给控制器来决断我们是转向到登陆成功页还是登陆失败页。LoginAction在此就起这么个功能,具体代码请依照如下所示:

public class LoginAction extends Action {

public ActionForward execute(ActionMapping actionMapping,

ActionForm actionForm,

HttpServletRequest servletRequest,

HttpServletResponse serveltResponse) {

LoginActionForm loginform = (LoginActionForm) actionForm;

String username = loginform.getUsername();

String userpass = loginform.getUserpass();

boolean flag = false;

String actionpath = "";

if (username.equals("123") && userpass.equals("123")) {

actionpath = "success";

} else {

actionpath = "error";

}

return actionMapping.findForward(actionpath);

}

}

在“LoginAction”中,我们得到一个ActionForm对象,并把它强转成LoginActionForm,

待我们处理,即通过ActionForm的匹配名称的表单自动封装机制,取得用户输入用户名、密码。

我们返回的结果将会被ActionFormward对象所包装,比如这儿的“success“表示用户合法,“error”表示用户不合法,这个字符串将决定着页面的流程控制。它并不是一个具体存在的页面,它是如何跟一个具体的页面关联上的呢?

呵呵,先不要急,我们来分析几点:

1、 你在操作时记住的概念:

Struts的核心是Action,而Action的核心就是一个配置文件——struts-config.xml。它既然是核心就很重要哦。

2、 Maping映射:

a) actionMapping.findForward(“映射名称”); 它返回的是一个ActionForward对象

b) struts-config.xml里面action节点下的:

实现机制:Struts会根据你传进actionMapping.findForward(“映射名称”),它会到你当前action节点下去找forward这个节点,并把你传进的参数与这个节点的name属性进行匹配。如果相等它就会跳到这个节点的path所指定的页面。

例:

Action:actionMapping.findForward(“success”)

Struts-config.xml:

如果是这种情况的话,它就会转发到success.jsp页面。

注意:

a) 方法的参数值和name节点的值对应,

b) Path所指定的页面,前面必须加上“/“

 

B、在前面我们提到了ActionForm,所以我们还需要建立一个类文件,这个类文件将封装页面用户输入的用户名、和密码。

注意:

1、这个类必须继承ActionForm类,它将完成与页面的自动封装。

2、类中的属性名称一定要和页面的输入框的名称对应,为了自动封装的匹配工作。

3、这个类中一定要提供所有与属性相匹配的set 和 get方法。

 

好,前面写了这些代码,看上去还是有些杂乱无章,怎么把它们关联起来呢?又怎么调用这些代码呢?呵呵,群龙不会无首的,下面就一起来关注struts的装配文件,它可是相当于struts的总司令哟!

 

C、核心部分,跳转控制Struts-config.xml部分

 

 

 

 

 

 

 

 

 

 

 

我们对struts.xml做一下相应的介绍吧,如下:

:用来配置一个ActionForm Bean。常用配置的几个属性:

name:指定该ActionForm Bean的唯一标识符,整个Struts框架用该标识符来引用这个Bean。该属性是必需的

   type:指定ActionForm类的全限定名。该属性是必需的

:用来描述特定的请求路径到相应的Action类的映射。常用配置的几个属性:

  input: 指定包含输入表单的URL路径。当表单验证失败时,将把请求转发到该URL。

  name: 指定和该Action关联的ActionForm Bean的名字。

  path: 指定访问Action的路径,它以“/”开头,没有扩展名。

  Scope: 指定ActionForm Bean的存在范围。(session | request)

  Validate:指定是否要先调用ActionForm Bean的validate()方法。默认值为true

Action的子元素常用配置的几个属性:

  name: 指定转发路径的逻辑名。必需的

  path: 指定转发(或重定向)的URI,必须以”/”开头。必需的

redirect:当此项为true时,表示执行重定向操作。为false时表示执行请求转发操作。默认值为false

 

D、页面login.jsp,用户登录页面,提供用户输入功能。具体代码如下所示:

 


请输入姓名:


请输入密码:

 

 

 

 

注意:

1、action后面的login.do就是struts-config.xml里面你要访问的action节点path的值哦

2、切记哦,如果你请求的URL的引用了formbean的话,这里的名称一定要对应哦。

还有success.jsp 、wrong.jsp分别代表登录成功和登录失败页面。就不再多说啦!

启动Tomcat,连接上您的应用程序网址,例如:http://localhost:8080/Struts1_Login/login.jsp,填入用户名、密码,并送出窗体,您的欢迎页面就会显示了。

怎么样,本章节是不是比较容易?其实struts就这么简单,能完成本章节的要求吧!现在你已经上手啦,接着往下学,我们会有越来越多的收获哟!!

 


二、解决中文乱码的问题实例

在进行web应用程序开发的过程中,中文问题经常困扰着很多程序员。因此,在接下来的两个课程的学习中,我将根据实践经验来谈一下web应用中的中文问题的解决方法。让大家不再为此而头痛。

我们就前那个登录验证的例子,进行进阶,处理中文乱码问题。前面例子中,只要用户名和密码都是123,才返回成功的页面。为了处理中文,我们判断只有用户名是张三才登陆成功。

一、程序进阶:

既然是中文乱码处理,页面的用户输入就是中文了,相应的action的if处理也要变成: if (username.equals("张三") && userpass.equals("123"));

效果图:

我们以结果为导向,首先大家先看看要完成的效果图,对接下来要做的事情有个清晰的认识。

1、如图键入:中文

 


显示结果如下图:

 


为什么会到错误页面呢?我们明明都写正确了呀,是的,没有错误,这是什么原因呢?

请看下图:

 


我们打印才发现原来username的值传到action中,成了乱码,这主要由于客户端和服务器端采用了不同的字符集,中文乱码我们没有处理。

二、解决办法:

A、直接转编码

我们新建一个包,命名为util,在包下新建一个类文件,命名为EncodingUtil,类的功能就是提供一个字符集转换的一个方法,具体代码如下所示:

package util;

public class Encoding {

public static String isToGB(String src) {

String strRet = null;

try {

strRet = new String(src.getBytes("ISO_8859_1"), "GBK");

} catch (Exception e) {

e.printStackTrace();

}

return strRet;

}

}

小结:这办法虽然能解决中文乱码,但是每次还得调用,是不是很不方便呢?如果忘记了调用这个方法,那程序又乱码了,维护起来很困难,下面我们看另一种解决方案。

B、继承RequestProcessor类

RequestProcessor类处理ActionServlet接收到的所有请求。根据它的处理方式,可将每个请求分解为多个小任务,分别由不同的方法执行。这就允许针对请求的各个单独部分自定义处理。

RequestProcessor类的部分方法如下:

processPath(): 获取客户端请求的路径URI

processMapping(): 根据请求URI获取所需的映射信息

processRoles(): 检查用户的角色是否允许他访问请求的资源

processActionForm(): 新建一个Form Bean或从请求会话中检索Form Bean

processForward(): 处理元素forward以匹配当前的请求路径

processValidate(): 调用Form Bean的validate()方法

processPreprocess(): 告诉请求处理器调用此方法后,是否应继续处理请求

processLocale(): 为请求选择一个语言环境

processActionCreate(): 实例化当前ActionMapping指定的类的实例

processActionPerform(): 将调用action的perform()或execute()方法

呵呵,发没发现RequestProcess类的所有方法都有一个前缀proess,接着往下看吧。

RequestProcessor在action之前,所以我们应着手RequestProcessor,要开发自己的RequestProcessor类,步骤如下:

(1) 创建一个继承org.apache.struts.action.RequestProcessor的类,在改类中显示定义一个无参,方法体为空的构造器。

(2) 重写所需的方法,加入我们的功能。

具体代码如下所示:

package servlets;

import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.RequestProcessor;

public class EncodingHandler extends RequestProcessor {

public boolean processPreprocess(HttpServletRequest servletRequest,

HttpServletResponse serveltResponse) {

try {

servletRequest.setCharacterEncoding("GBK");

System.out.println("请求被处理.");

} catch (UnsupportedEncodingException ex) {

ex.printStackTrace();

}

return true;

}

}

(3) 修改配置文件sturts-config.xml,在其中加入一个名为的元素,用以指定我们定制的RequestProcessor类。

 

 

 

 

 

 

 


path="/login"

name="loginActionForm"

scope="request"

type="actions.LoginAction">

 

 

 

 

 

 

上面就是我们自己的定义的RequestProcessor类,使用标签类定义。

如图:


小结:这样做呢?问题是解决了,每一个请求先经过这个方法,并转换了字符集再交给action做处理,这样我们不用在操心中文乱码,但RequestProcessor是与struts耦合在一块儿。如果不用struts框架,我们又该如何处理中文问题呢?是否又更好的办法呢?那就接着跟我往下看吧。

C、Filter来解决中文问题

Filter,是不是你脑子里闪现了这个词呢?下面就来看看如何用它来改写我们上一章节的例子吧!

(1) 首先在工程中新建一包,命名为filter,在下面新建一类文件,命名为EncodingServlet,并继承HttpServlet、实现Filter接口,注意并实现接口的方法。

在Servlet中filter起着过滤器的作用,当一个请求发送到服务器的时候,需要把请求首先交给filter来处理,然后交给action做处理。EncodingServlet负责处理请求的字符集,在此就起这么个功能,具体代码请依照如下所示:

package servlets;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServlet;

public class EncodingServlet extends HttpServlet implements Filter {

private static final long serialVersionUID = 1L;

public void doFilter(ServletRequest servletRequest,

ServletResponse serveltResponse, FilterChain filterChain) {

try {

servletRequest.setCharacterEncoding("GBK");

filterChain.doFilter(servletRequest, serveltResponse);

} catch (Exception ex) {

}

}

public void init(FilterConfig arg0) throws ServletException {

}

}

(2) 修改web.xml,加入我们的filter。

 

EncodingServlet

servlets.EncodingServlet

 

 

EncodingServlet

/*

 

小结:这个中文乱码处理用了fileter,而且适用与任何场合,比较实用。

怎么样,通过三个处理中文乱码的方案,有和感想呀,是不是程序很有意思呀,那就跟着我继续看看struts别的东东吧……

 


我们以结果为导向,首先大家先看看要完成的效果图,对接下来要做的事情有个清晰的认识。

1、如图键入:

 


显示结果如下图:

 


如果您输入的是不合法的话,则如下图:

 


修改步骤:

A、数据源配置

在struts-config.xml文件中有一元素是用来配置应用所需要的数据源,数据源负责建立和特定数据库的连接,许多数据源采用连接池的机制实现,即提高了数据库的访问性能。具体代码片段如下所示:

 

 

 

 

 

 

 

 

上面这段代码配置了与MySQL数据库的连接。元素的key是一个别名,用于在应用程序中去的一个连接,元素type用来指定数据源的实现类。上面使用的是Apache软件组织提供的DBCP数据源。所以你必须导入commons-dbcp.jar、commons-pool.ar、struts-legacy..jar这三个包和MySQL的驱动包:mysql-connector-java-5.0.5-bin.jar。

配置了数据源后,就可以在Action中访问数据源了。

代码如下所示:

//获取Servlet上下文对象

ServletContext ctx = servlet.getServletContext();

//获得数据源

DataSource ds = (DataSource) ctx.getAttribute("DataSource");

//获取数据库的连接

Connection conn = ds.getConnection();

B、修改Action

Action将取得数据源,得到一个数据库的连接,把页面传近来的用户名和密码,通过jdbc与数据库进行对比,如果存在转到“success.jsp”并显示其名称,否则到错误页面。

具体实现代码如下所示:

public class LoginAction extends Action {

public ActionForward execute(ActionMapping actionMapping,

ActionForm actionForm, HttpServletRequest request,

HttpServletResponse response) {

LoginActionForm loginform = (LoginActionForm) actionForm;

String username = loginform.getUsername();

String userpass = loginform.getUserpass();

ServletContext ctx = servlet.getServletContext();

DataSource ds = (DataSource) ctx.getAttribute("DataSource");

boolean flag = false;

String sql = "select * from user where username='" + username

+ "' and password='" + userpass + "'";

try {

Connection conn = ds.getConnection();

Statement st = conn.createStatement();

ResultSet rs = st.executeQuery(sql);

while (rs.next()) {

flag = true;

}

} catch (Exception e) {

e.printStackTrace();

}

String actionpath = "";

if (flag) {

request.setAttribute("username", username);

actionpath = "success";

} else {

actionpath = "error";

}

return actionMapping.findForward(actionpath);

}

}

C、修改页面

如果登录成功,通过EL显示用户名。

具体代码如下:

 

 

 

 

 

 

 


success.jsp demo

 

 


welcome

 

here,thanks

 

 

 


引入struts的标签,输出用户名称。

小结:怎么样出来你要的结果了吧,不过是使用的数据源配置,我个人认为让struts来管理不是太妥当,因为数据的相关操作应该属于持久层的管理,不应该由上一层管理(Controller),所以实际操作中建议不要这么做。

 

四、Struts 中的国际化

一、概念

I18N作为“国际化”的简称,其来源是明文单词“internationlization”的首末字符“i”和“n”之间的字符数为18。随着全球经济的遗体化为一种主流的趋势,软件开发者应该开发出支持多国语言、国家化的web应用程序吧。也就是一个web应用程序在运行时能够根据客户端请求所来自的国家和语言的不同显示不同的用户界面。这样,当需要在应用程序中添加对一种新的语言的支持时,不需要对已有的软件返工,无需修改应用程序的程序代码。

二、Struts对国家化的支持

在Struts框架中进行应用程序的国际化,支持重点在于应用程序的文本和图像表示。最重要的工作就是准备Resurce Bundle 资源包。事实上,准备资源包的过程,就是把对应不同语言的用户所涉及的文本和图片保存在多个文本文件中,客户端根据不同的环境需要进行更换。这些文件被称为“属性文件”,所有属性文件合在一起被称为资源包(Resource Bundle)。

Struts建立于Java平台之上,很容易建立国际化和本地化的应用程序。在这里你要熟悉的关键概念是:

1) Locale – 基础的支持国际化的java类是java.util.Locale。每个Locale代表一个特别的国家和语言的选择(加上一个可选的语言变量),以及一套格式假定,例如数字和日期等等。

2) ResourceBundle – java.util.ResourceBundle类提供支持多种语言消息的基本工具。查看文档中关于ResourceBundle类以及你的JDK版本的文档包中关于国际化的更多内容。

3) PropertyResourceBundle – 一个ResourceBundle类的标准实现允许你使用与初始化properties文件同样的键/值的语法来定义资源。这对于使用为用于一个web应用程序的消息准备资源包是非常方便的,因为这写消息通常都是面向文本的。

4) MessageFormat – java.text.MessageFormat类允许你使用运行时的指定的参数替换一个消息字符串中的一部分(在这种情况下,是一个从一个资源包得到的消息)。这在你创建一个句子的场合中是有用的,但是词会以不同的语言安照不同的顺序出现。消息中的占位符,字符串{0}用第一个运行时参数替换,{1}用第二个运行时参数替换,以此类推。

5) MessageResources – Struts的类org.apache.struts.util.MessageResources使你能够将一套资源包视做一个数据库,并且允许你为一个特定的Locale(通常是与当前用户相对应)请求一个特定的消息,而不是为服务器运行在其中的缺省的Locale请求消息。

三、示例

1、我们还在前面的登录实例进行加工。

2、在默认的applicationResources.properties文件中添加相应的消息文本。

label.username=username

label.password=password

button.submit=submit

button.reset=reset

3、创建临时中文资源文件:applicationResources_temp.propertyies

label.username=用户名

label.password=密码

button.submit=确定

button.reset=重置

4、对临时资源文件进行编码转换:

在JDK中提供了native2ascii命令,它能够实现字符编码转换。在DOS下执行以下命令,将生成按GBK以编码的中文资源文件:applicationResources_zh_CN.properties

native2ascii –encoding gbk applicationResources_temp.properties

applicationResources_zh_CN.properties

生成的applicationResources_zh_CN.properties的内容如下:

label.username="u7528"u6237"u540d

label.password="u5bc6"u7801

button.submit="u786e"u5b9a

button.reset="u91cd"u7f6e

当web用户的Locale为中文时,Struts框架将自动选择来自applicationResources_zh_CN.properties文件的消息文本。

 

5、创建英文的资源文件:

label.username=username

label.password=password

button.submit=submit

button.reset=reset

完成以上几个步骤后,在web 应用程序的根目录"WEB-INF目录"classes目录下应该有了三个资源文件:

默认资源文件:applicationResource.properties

中文资源文件:applicationResource_zh_CN.properties

英文资源文件:applicationResource_en.properties

6、创建struts的Resource Bundle

Struts配置文件中的元素定义了一个Resource Bundle。Resource Bundle的持久化消息文本存储在资源文件中,其扩展名为“.properties”,里面存放的都是“键/值”。

在struts-config.xml中对Resource Bundle的配置代码:

 

表示默认的资源文件应该是applicationResources.properties,存放在应用程序的根目录"WEB-INF目录"classes目录下。如果应用程序需要支持中文用户,要在相同目录下创建一个包涵中文消息的资源文件,文件名必须为applicationResource_zh_CN.properties。
7、修改login.jsp页面

 

 

 

 

 

 

 

 

">

">

 

:用于访问web应用资源的bean标签,显示Resource Boundle中的内容。

8、运行程序

1)如果你的浏览器默认设置为中文,你键入地址,将看到的页面如下:

 


2)把你的浏览器的设置为英文,然后刷新页面,如下图:

 

 

总结:国际化对于web应用程序来说很重要,如果你的web应用程序面对多个国家的话,要实现不同语言的切换,如果不使用国际化的话要么只有一种语言,要么在程序里面改,现在一切都方面了,不过java对中文的支持并不好,并不是什么地方都可以使用中文的,如在LookUpDispatchAction中就不能使用国际化哦。

 


五、Struts中验证数据实例

一、Struts的ActionForm的表单验证

ActionForm类用于在视图层和控制层之间传递HTML表单数据。控制层可以从ActionForm Bean中读取用户输入的表单数据,也可以把来自模型层的数据存放到ActionForm Bean中,然后把数据返回给视图。即ActionForm Bean从HTML表单中获取用户输入的数据并将传递给Action类,也可以把从业务层返回的数据用来填充ActionForm Bean,然后JSP页面用它来为HTML表单提供各种输出字段的数据。此外,ActionForm Bean还具有表单验证功能,可以过路不合法的数据。

ActionForm Bean有两种存在范围:request和session。如果ActionForm Bean存在于request范围,它仅在当前的请求/响应生命周期中有效。如果ActionForm Bean存在于session范围,同一个ActionForm Bean实例在整个HTTP会话中都有效。

在Struts框架中,使用ActionForm Bean来实现应用程序系统的非持久性数据存储和维护功能,它采用了自动填充属性和调用的机制。所以必须继承ActionForm类,并且包涵用户表单输入的属性,以及相应的get方法和set方法。另外,还可以根据需要重写父类的reset()和validate()方法,实现属性的重置和表单数据验证功能。

? validate()方法

这个方法主要负责检查数据的格式和语法,而不负责检查数据是否符合业务逻辑。

ActionForm基类中的validate()方法在默认情况下将返回null。如果创建了ActionForm的子类,那么应该在子类覆盖validate()方法。

? reset()方法

这个方法用于恢复ActionForm Bean 的属性的默认值。例如:把字符串属性设为null或某个初始值。

1、 修改前面我们写的LoginActionForm,如果你不清楚的话,请您先看前几个实例,具体代码如下:

public ActionErrors validate(ActionMapping actionMapping,

HttpServletRequest httpServletRequest) {

ActionErrors errors = new ActionErrors();

if (username == null|| username.equals("")) {

errors.add(ActionErrors.GLOBAL_MESSAGE,

new ActionError("loginform.error.username"));

}

if (userpass == null||userpass.equals("")) {

errors.add(ActionErrors.GLOBAL_MESSAGE,

new ActionError("loginform.error.password"));

}

return errors;

}

这个方法返回ActionErrors对象,如果返回的ActionErrors对象为null,或者不包含任何ActionMessage对象,就表示没有错误,数据验证通过。如果ActionErrors中包含ActionMessage对象,就表示发生了验证错误,此时就回把请求转发到你struts.xml里面元素input属性指定的web资源。

new ActionError("loginform.error.username");取得资源文件里面的键值,用于页面的输出。

2、 打开applicationResource.properties,加入如下信息:

loginform.error.username=please enter your username

loginform.error.password=please enter your password

因为我们前面做了国际化,所以打开applicationResource_zh_CN.properties文件,添加如下:

loginform.error.username=请输入用户名

loginform.error.password=请输入密码

3、 修改struts-config.xml文件


path="/login"

name="loginActionForm"

scope="request"

type="actions.LoginAction"

validate="true"

input="/login.jsp">

 

 

 

在元素中,name和scope属性分别指定ActionForm的名字和它的范围,valudate属性指定是否执行表单验证,而input属性表示验证失败,所要显示用户的内容。

4、 修改login.jsp,在元素添加,目的是显示错误信息,具体代码片段如下:

 

 

 

 

 

 

 

 


:用于输出消息。属性介绍如下:

n name:指定ActionMessages对象存放在request或session范围内的属性key。标签处理类将根据这一属性key来检索request或session范围的ActionMessages对象。

n message属性:指定消息的来源。如果为true,则从request或session范围内检索出属性key为Globals.MESSAGE_KEY的ActionMessages对象,此时name属性无效;如果为false,则根据name属性来检索ActionMessage对象,如果此时没有设置name属性,将采取默认值Globals.ERROR_KEY.message属性的默认值为false。

n id属性:用来命名从消息中检索出来的每个ActionMessage对象,它和标签的name属性匹配。

:表示显示javaBean或其属性的内容。

5、 运行

打开IE,键入如下地址:http://localhost:8080/Struts1_Login/login.jsp

不输入任何东西,我们直接点几击“确定”,如下:

 


二、Struts的Validator验证框架

Validator 目前是Jakarta Commons 项目的一部分,它也被包含在Struts主分发里面,可以直接使用Struts 中自带的Validator 库,也可以去网站上下载http://jakarta.apache.org/commons/

Struts框架能够通过ActionForm Bean的validate()方法对用户输入的表单数据进行验证。但是这种验证方式又有一定的局限性。必须由具体的代码来实现验证逻辑,如果验证逻辑发生了改变,就需要重新编写程序代码。此外,如果系统中有多个ActionForm Bean,并且他们包含一些相同的验证逻辑时,那么开发人员必须对每个ActionForm Bean进行重复开发呢?

Validator框架能够克服在ActionForm Bean中进行数据验证的局限性,它允许为Struts应用灵活的配置验证规则,无需编程。

Validator框架主要依赖于两个JAR文件:

? Jakarta-oro.jar

提供了一组处理文本的类,具有文本替换,过录和分割等功能。

? commons-validator.jar

提供了一个简单、可扩展的验证框架,包含了通用的验证方法和验证规则。

主要的Struts验证组件

组件
说明

验证器
处理原生和其它通用类型。基本验证器包括required,mask(匹配正则表达式),minLength,maxLength,range,nativetypes, date,email,和creditCard。也可以定义定制 (或者插件) 验证器。

资源文件
提供(本地化的)标注和消息。默认与Struts 共享消息资源。

XML 配置文件
根据需要定义针对字段的表单集和验证。验证器可以在一个单独的文件中定义。

JSP 标签
对给定的表单或Action 路径产生JavaScript 验证器。

ValidatorForm
根据FormBean 的名称自动验证属性(在运行时通过ActionMapping 参数传到validate 方法)。必须被扩展才能提供表单之上的期望属性的验证。

ValidatorActionForm
基于action 路径自动验证属性(在运行时通过ActionMapping参数传到validate 方法)。必须被扩展才能提供表单之上的期望属性的验证。


有些字段可能必须要求有数据输入。而邮政编码总是具有已知的长度。其它公共字段类型包括数值、日期、身份证号码等等。

验证器本身具有一些基本的验证器来处理这些公共需要,当然还有其它一些需要。如果你的验证不能被基本验证器或者正则表达式满足,你可以开发你自己的验证器并插入到包中。基本验证器支持其自身附带的基本插件。

安装和配置

Validator框架采用两个基于XML的配置文件来配置验证规则。一个是validator-rules.xml,另一个是validation.xml,这两个文件应该部署在对应于WEB应用程序的WEB-INF文件夹下,对应的两个jar文件也添加到WEB-INF/lib目录下。

1、 validation-rules.xml

在validation-rules.xml 文件中配置了一些全局性的验证规则,使得你在应用程序中使用校验而不用关注实现细节。这个配置文件是Validator 框架自带的,可以用在所有Struts应用中。它默认配置了许多很常用的规则,一般来说,不用去更改它,除非需要扩展或修改这些默认的验证规则。

建议:即使你需要扩展一些规则,也不要去修改validation-rules.xml,而是通过新的配置文件去定义你所扩展的校验规则。

validator-rules.xml文件的根元素是form-validation,它包含一到多个global元素,global元素包含一到多个validator 元素。

每一个validator 元素定义了一个唯一的验证规则。下面是validation-rules.xml 文件中的一个片断, (mask)验证规则:


classname="org.apache.struts.validator.FieldChecks"

method="validateMask"

methodParams="java.lang.Object,

org.apache.commons.validator.ValidatorAction,

org.apache.commons.validator.Field,

org.apache.struts.action.ActionMessages,

org.apache.commons.validator.Validator,

javax.servlet.http.HttpServletRequest"

depends=""

msg="errors.invalid"/>

1) name: 赋予验证规则的一个唯一的名称。

2) classname: 指的是具体实现验证规则的类。

3) method: 指包含具体实现类的方法。

 

4) methodParams: 声明method属性所指定的方法参数,多个参数之间用逗号分隔。

5) depends: 指定在调用当前的严整规则之前必须先调用的其他验证规则。多个则用逗号分隔。

6) msg: 指定来自于Resource Bundle中的消息key。当验证失败时,validator框架根据这个消息key到Resource Boundle中查找匹配的消息。

2、 validation.xml

Validator框架所需要的第二个配置文件是validation.xml,这个配置文件是具体应用(项目)所特定的,可以根据你的应用(项目)情况进行自定义配置。它描述了具体的ActionForm使用validation-rules.xml文件中的哪个验证规则进行验证。

一个自定义的验证规则如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

Validator.xml文件的根元素为元素,它包含两个子元素:和元素。

1) 元素可以定义子元素,它用来定义常量表达式。

2) 元素包含两个子元素:和

3) 元素用于为表单配置验证规则,它的name属性表示你验证formBean,必须和struts-config.xml里面FormBean名字保持一致。元素可以包含一个或多个子元素。

4) 元素是针对表单中字段的验证规则。Property属性用于指定FormBean中需要验证的字段的名称,depends属性用于指定字段的验证规则,多个用逗号分隔。

5) 元素表示出错时的主体信息,key 是你属性文件里面的key。

6) 主要是对前面元素包含的验证规则的定义。

3、插入Validator

每一个Struts应用需要知道是否使用了Validator框架,可以通过PlugIn(插件)机制将Validator框架配置到Struts应用中。

下面的代码演示了如何将Validator 作为一个插件加入到Struts 应用中,在Struts 应用的配置文件Struts-config.xml 中加入如下代码片段:

 


value="/WEB-INF/validator-rules.xml,/WEB-INF/validator.xml"/>

 

pathnames属性的值用来指定Validator 框架所使用的配置文件,多个配置文件之间用逗号分隔。

当应用启动的时候,Struts框架将调用ValidatorPlugIn的init()方法。Validator框架的配置文件将会加载到内存中供应用使用。在init()方法被调用之前,pathnames所指定的值将会传递给ValidatorPlugIn的实例,ValidatorPlugIn实例将会依据这个值去加载配置文件。

案例说明:根据前面的例子我们进行进阶,要求用户输入用户名、密码。并且用户名、密码是必须,若为空,则提示错误信息。

A、服务器段验证

1、修改FormBean

我们以前的是继承ActionForm,现在改成ValidatorForm,导入相应的包,并删除validator和reset方法。

2、修改struts-config.xml文件,具体代码如下:


path="/login"

name="loginActionForm"

scope="request"

type="org.zhoudq.webapp.action.LoginAction"

validate="true"

input="/login.jsp">

 

 

 

将validator改为true,告诉服务器对这个表单进行验证,input的值,是告诉服务器如果严整失败的话,将跳转的页面。

3、添加验证规则

在WEB-INF下创建validaton.xml这个文件,导入引用的dtd,添加如下内容:

 

 

 

 

 

 

 

 

 

 

 

 


3、修改Resource Boundle文件:

英文的资源文件:applicationResource_en_US.properties

errors.required={0} is required.

errors.minlength={0} can not be less than {1} characters.

errors.maxlength={0} can not be greater than {1} characters.

errors.invalid={0} is invalid.

errors.byte={0} must be a byte.

errors.short={0} must be a short.

errors.integer={0} must be an integer.

errors.long={0} must be a long.

errors.float={0} must be a float.

errors.double={0} must be a double.

errors.date={0} is not a date.

errors.range={0} is not in the range {1} through {2}

errors.creditcard={0} is an invalid credit card number.

errors.email={0} is an invalid e-mail address.

button.submit=Submit

button.reset=Reset

button.cancel=Cancel

label.username=UserName:

label.password=Password:

loginform.error.username=please enter your username

loginform.error.password=please enter your password

loginform.fail=invalidation name and password,login error!

中文的资源文件:applicationResource_zh_CN.properties

errors.required={0} 是必须的.

errors.minlength={0} 不能少于 {1} 个字符.

errors.maxlength={0} 不能多于 {1} 个字符.

errors.invalid={0} 是非法的.

errors.byte={0} 必须是 byte 类型.

errors.short={0} 必须是 short 类型.

errors.integer={0} 必须是 Integer 类型.

errors.long={0} 必须是 long 类型.

errors.float={0} 必须是 float 类型.

errors.double={0} 必须是 double 类型.

errors.date={0} 不是一个日期.

errors.range={0} 不在 {1}- {2} 之间.

errors.creditcard={0} 是一个非法的身份证号r.

errors.email={0} 是一个非法的油箱地址.

button.submit=确定

button.reset=重置

button.cancel=取消

label.username=用户名:

label.password=密码:

loginform.error.username=请输入用户名

loginform.error.password=请输入密码

loginform.fail=用户名或密码错误,登录失败!

5、在struts-config.xml添加validator

 


value="/WEB-INF/validator-rules.xml,/WEB-INF/validator.xml"/>

 

5、运行

打开IE,键入:http://localhost:8080/Struts1_Login/login.jsp,直接点确定,如下图:

 


B、客户端验证

这也表现了Validator验证框架的强大之处,又服务器生成javascript脚本,这样就直接在客户端进行验证了,从而减少了服务器的压力,万事有力又有避,这中方式服务器在生成脚本的同时又牺牲能性能,呵呵,看如何实现吧,一定很振奋吧.

1) 修改login.jsp页面

 

 

 

 

 

 

 


login

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a)表示生成js代码,formName属性指定验证表单的名字,必须和struts-config.xml里面的form一样。

b)

当用户提交表单的时候,就会调用标签生成的javascript脚本的方法,从而执行客户端的验证,其中的LoginActionForm是你FormBean的名字对用,必须和struts-config.xml里面的form一样,在这里面第一个字母大写哦。


六、Struts的模块使用实例

在使用Struts框架时,每个请求都由Action去处理,并且还要在struts-config.xml中加以设定,这样以来做小项目还行,在大型网站的开发中,有很多小组负责不同的模块,如果每一个小组要对一个struts-config.xml进行设定,将会导致struts-config.xml的版本控制问题。

您可以为每个小组分配不同的struts-config.xml设定文件,方法是在ActionServlet参数的config参数后面加上后缀,如果是config/admin,那么相应的配置文件的名字就是:struts-config-admin,他们的后缀名字必须对应,这样才能映射上。

例如我们可以把后台处理分配一个小组,设定具体代码如下所示:web.xml

 

action

org.apache.struts.action.ActionServlet

 

config

/WEB-INF/conf/struts-config.xml

 

 

config/admin

/WEB-INF/conf/struts-confg-admin.xml

 

 

debug

3

 

 

detail

3

 

0

 

config/admin:指定了admin模块的所使用的配置文件是struts-config-admin.xml,现在负责后台模块的开发人员只要管理自己的开发文档设定就行了,就像前面所说的一样,当ActionServlet收到请求时,它是根据模块你所指定的后缀,进行处理是哪个模块的请求。

例如:

http://localhost:8080/strutsmodel/admin/admin.do

这个URL,表示请求由strutsmodel工程的admin环境的admin.do来处理这个请求。这样以来前台和后台就分明了,各自开发各自的,各自管理自己的配置文件,达到松耦合的目的。

当ActionServlet请求接收请求,它判断URL中相对与context的前缀,例如上例中的admin,于是就知道应该使用admin模块。下面是struts-config-admin.xml:

……


path="/admin"

type="org.zhoudq.webapp.action.AdminAction" >

 

 

……

这样以来所有的path设定将自动被加上login前缀,例如必须使用以下的路径才可以正确的请求到AdminAction:

http://localhost:8080/strutsmodel/admin/admin.do

在模块中的Action在查找forward时,都是以所在模块,查找对应的struts-confg-XXX.xml的,例如上面的AdminAction在查找forward时,则会查找struts-config-admin.xml中的forward元素,也就是说,模块中的forward对象的查找都是相对于模块的路径的,而不是相对与环境上下文。

那么我们模块分配工作几已经搞定了,各个小组可以分别开工了,但是问题来了,那么如何从当前的模块换到另一个模块呢?

当您的项目分作很多个模块时,在使用者点某个链接时,您有两个方法可以在模块之间切换。

一、方法一

是使用相对与环境上下文的路径进行forward转发,您可以在当前的struts-config-XX.xml如下设定,例如是:struts-config-admin.xml中加入:

 


name="switchModuleToFront"

contextRelative="true"

path="/front/login.do"

redirect="true"/>

 

这个是全局可以找到的forward中设定的,下面是在action元素中设定如何转发模块,代码如下:

……


path="/admin"

type="org.zhoudq.webapp.action.AdminAction" >


name="admin"

contextRelative="true"

path="/front/login.do"

redirect="true"/>

 

……

上面这种配置就是通过forward元素转换到相应的模块,下面我们看另一种方法吧。

二、方法二

这种方法是我们通过配置Struts的一个特定的类SwitchAction,就能实现上面的要求了。并且需要两个参数:

1. prefix:用来指定模块的后缀名称

2. page:用来指定你的资源路径。

例如:

……

 


path="/switch"

type="org.apache.struts.actions.SwitchAction"/>

 

……

例如:

http://localhost:8080/strutsmodel/switch.do?prefix=/admin&page=/admin.do

这个是访问我们后台模块的admin.do资源。模块化决绝了我们开发中的不少问题吧,希望能帮助您解决一些问题,嘿嘿,加油吧……

 

id: 395423365
title: Struts<学Ⅱ>
publishTime: 1236665075346
classId: 88735822
moveForm: NONE

没有评论 :

发表评论