资源描述
*,*,*,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,单击此处编辑母版标题样式,第七章 MVC框架技术Struts2,本章要点,Struts2配置及应用程序原理,Action的设计方法与结果类型,服务器端的输入验证,Struts2国际化、标签库和OGNL表达式,拦截器、文件上传和下载,7.1 Struts2概述,Struts框架的历史,Struts在经历了1.x的若干版本后,最终发展到2.0版本,也就是我们常说的Struts2。它是Struts和WebWork相互结合的产物,代表了WEB框架的最新技术和规范。本书中Struts2的内容以最新的Struts2.2.3版本为准。,Struts2 下载与配置,下载Struts2,Struts2的下载地址为http:/struts.apache.org。目前可下载到的最新版本是struts2.2.3。下载后得到压缩包struts-2.2.3-lib.zip。解压后的文件夹中包含一个“struts-2.2.3lib”文件夹,该文件夹包含了Struts2的类库。,在NetBeans中使用Struts2,在web.xml中加入如下Struts2核心控制器(过滤器)的配置。,struts2,org.apache.struts2.dispatcher.ng.filter.,StrutsPrepareAndExecuteFilter,struts2,*.action,struts2,*.jsp,案例7-1 使用Struts2实现博客网站中的用户登录,使用Struts2实现控制层,可以简化控制层的设计。为了逐渐介绍Struts2的知识,这里先实现用户登录功能。,技术要点,按照Struts2的Action的格式定义一个Action类来做为控制类,替换原来用Servlet实现的控制类。这种类可以是普通类,也可以是ActionSurpport的子类。,Struts2的Action需要在struts.xml文件中进行配置。,Struts2的MVC原理,Struts2组件,核心过滤器与web.xml,Action:,Struts2中Action属于控制层,它可以是任何的POJO对象,默认调用的方法是execute()。,struts.properties,系统在读取核心配置文件之前,首先加载了核心jar包中的default.properties文件,这个文件中定义了Struts2所使用的基本属性,然后会自动在classpath上去查找struts.,properties文件。struts.properties是应用程序给出的属性配置文件,可以通过这个文件来设置属性,以修改在default.properties中定义的默认值。例如:,struts.locale=zh_CN,struts.i18n.encoding=gbk,struts.devMode=true,struts.xml文件,struts.xml是Struts2的核心配置文件,可以配置常量、action、package、result和拦截器等内容。struts.xml中action必须配置在package中。Struts2使用package来管理action、拦截器等核心组件。package就是多个action、多个拦截器、多个拦截器引用组成的集合。,Struts2的中文乱码问题,中文乱码问题一般是指当请求参数有中文时,无法在Action中得到正确的中文。Struts2中有2种办法可以解决这个问题:,设置JSP页面的pageEncoding=utf-8,就不会出现中文乱码。,如果JSP页面的pageEncoding=gbk ,那么需要修改如下属性:,struts.locale=zh_CN,struts.i18n.encoding=gbk,可以增加一个属性文件struts.properites,把属性的设置写在属性文件中。属性文件要放在源包下。,7.2,Action与结果类型,Action的实现类,在Struts2中,Action的设计是非常关键的。Struts2中对Action对象没有特殊要求, Action可以是任意的Java对象,它和Web对象之间没有直接关系,所以这样的Action是非常易于测试的,这也是Struts2中Action的最大优点。,普通的Java对象作为Action,继承ActionSupport实现Action,模型驱动(ModelDriven)的Action,属性驱动的Action,在Action中访问Web对象,通过ActionContext访问,ActionContext类位于com.opensymphony.xwork2中,它提供一系列相关方法用于访问保存在ServletContext、HttpSession、HttpServletRequest中的信息,并且存储在Map中。ActionContext是一个局部线程变量,不用担心Action的线程安全。,ActionContext常用的方法:,public static ActionContext getContext():获得ActionContext 对象。,public Map getParameters():从请求对象(HttpServletRequest)中获取请求参数。,public Map getApplication():获取ServletContext中保存的Attribute。,public Map getSession():获取HttpSession中保存的Attribute。,直接访问Web对象,Struts2框架提供org.apache.struts2.ServletActionContext辅助类来获得web对象。,HttpServletRequest request = ServletActionContext.getRequest();,HttpServletResponse response = ServletActionContext.getResponse();,HttpSession session = request.getSession();,ServletContext application = ServletActionContext.getServletContext();,通过IoC访问Servlet对象,在Struts2中,可以通过IoC(依赖注入)将Servlet对象注入到Action中,这一切都是由一组接口决定的,这一组接口有一个共同点,名称都由Aware结尾。,例如,实现如下接口,将以Map类型向Action注入保存在ServletContext中的Attribute集合:,public interface,ApplicationAware ,public void,setApplication(Map application);,此外,还有SessionAware、ServletResponseAware、ServletRequestAware、ParameterAware等接口。,多方法的Action,前面所定义的Action都是通过execute()方法处理请求。在实际的应用中,如果为每个业务逻辑定义一个Action,虽然实现方便,但是Action数量多,struts.xml中需要配置的内容也多,使系统非常庞杂。实际上,可以用一个Action处理多个业务请求。,以YbUserAction为例,可以为每个操作定义一个方法,这些方法的格式和execute()方法一样。,public,class,YbUserAction ,public,String login(),throws,Exception ,public,String register(),throws,Exception ,多方法Action的配置及调用方法有如下几种:,为Action配置method属性,动态方法调用,动态方法调用是指采用如下格式调用Action中对应的方法:,控制名!方法名.action,动态方法调用在内部是通过拦截器处理的,因此在使用动态方法调用前,要使Struts2允许动态方法调用。这需要在属性配置文件中将struts.enable.DynamicMethodInvocation属性的值设为true:,struts.enable.DynamicMethodInvocation=true,使用通配符映射方式,在struts.xml文件中配置action元素时,它的name、class、method属性都可支持通配符,这种通配符的方式是另一种形式的动态方法调用。当使用通配符定义action的name属性时,相当于用一个元素action定义了多个逻辑Action。例如:,如上,用户请求的URL的模式是YbUser_*。同时method属性值为一个表达式1,表示它的值是name属性值中第一个*的值。例如,用户请求的URL为YbUser_login.action时,将调用YbUserAction类的login()方法;用户请求的URL为YbUser_register.action时,将调用YbUserAction类的register()方法。,Result类型,在配置文件中,action的result子元素用于配置Action跳转的目的地,其基本格式为: 。Action某业务方法的返回值与result的name值相对应,以此来表明该方法执行完将跳转到哪个页面。type可以有多种选择,Struts2支持各种视图技术,例如JSP、JSF、XML等,默认的是JSP。,7.3 输入验证,使用validate()方法,要进行输入验证,Action类要继承ActionSupport,并重写validate()方法。,当请求Action的时候,请求中的参数会自动去填充Action的模型中的同名属性,如果能够从字符串自动转换成相应的Java数据类型,则转换成功,否则会抛出异常。如果类型转换成功,则填充属性,并在调用业务方法前,执行validate()方法来判断所有输入数据的合法性,例如长度是否够,是否是空值等。,输入验证可以针对不同的业务方法,例如,对登录进行输入验证,vaidate()方法可以命名成validateLogin()。如果同时有validate()方法,执行的顺序是先调用validateLogin(),再调用validate(),前面的方法验证没通过,后面的方法不再执行。,使用验证文件验证,使用validate()方法进行输入验证的弊端是显而易见的,由于使用了硬编码的方法,将验证逻辑嵌入到Action的实现类中,使Action变得更加臃肿,同时提高了Action和输入验证之间的耦合度。Struts2框架还提供了一种基于验证文件的输入验证方式,将验证规则保存在特定的验证文件中,使得验证规则同Action之间实现分离,提高了系统的维护性。,验证文件的命名,一般情况下,验证文件的命名规则是:Action类名-validation.xml。如果一个Action有多个逻辑处理方法,要为某个特定方法做验证,可采用如下方式命名:Action类名-Action逻辑名-validation.xml(其中,Action逻辑名,是指struts.xml中的对应该处理方法的action配置中的name值)。可匹配通配符的方式,以区分不同的方法,具体可参考案例7-2。,配置文件要和Action放在相同的文件夹内。运行时,先加载action类名-validation.xml,然后加载action类名-Action逻辑名-validation.xml文件。,校验器,Struts2提供了大量的内置校验器,可在xwork-core-2.2.3.jar的com.opensymphony.,xwork2.validator.validators下找到如下配置文件:default.xml,里面列出了所有的内置校验器。校验器的配置风格有两种:字段校验器和非字段校验器。,案例7-2 实现客户登录和注册验证(使用配置文件验证),在博客系统中对登录表单和注册表单提交的数据实现在服务器端验证,验证的方法采用基于配置文件的数据验证。,技术要点,在控制类所在包下建立两个验证文件。文件名分别命名为YbUserAction-YbUser_login-validation.xml和YbUserAction-YbUser_register-validation.xml。,控制类继承ActionSurpport类。,在struts.xml中配置名称为input的结果。,7.4 Struts2国际化、标签库和OGNL表达式,Struts2国际化,国际化是指应用程序运行时,可根据用户端请求来自的国家/地区、语言的不同而显示不同的界面。国际化是商业系统中不可或缺的一部分。,资源文件,Struts2框架通过资源文件的方式来实现国际化。程序界面中,需要输出国际化信息的地方,不要在页面上直接输出,而是通过key值来输出,该key值在不同的语言环境中对应不同的字符串。语言资源文件有一组key-value对组成。例如:,hello=你好!,msg=你好!,0,1,针对不同的语言环境,需要定义不同的资源文件。资源文件放在【源包】下,全局资源文件的命名可以有以下三种形式:,baseName_language_country.properties,baseName_language.properties,baseName.properties,在Struts2中需要指出所使用资源文件的baseName。有两种方式。,在struts.xml中定义个常量,其中的value值即为baseName。,在属性文件中配置strlcustom.i18n.resources。strlcustom.i18n.resources常量中设置的值为资源文件的baseName(基本名称)。,struts.custom.i18n.resources=resources,国际化使用,JSP页面的国际化,主要使用标签。例如:,$d,或,$d,Action中实现信息的国际化,主要是通过getText(String key)方法实现的。例如:,this.addFieldError(username, this.getText(username.invalid);,this.addActionError(this.getText(username.invalid);,xml验证框架中错误信息的国际化。,或,$getText(name.invalid),struts表单的国际化(前提是theme属性不能设置为simple),使用key属性。例如:,案例7-3 实现登录界面的国际化,实现登录界面的国际化。运行效果如图7-3和7-4所示。,技术要点,将登录界面所有标题文本换成国际化方法显示。主要使用标签显示。,建立两个资源文件一个是resources_zh_CN.properties存放中文界面标题;resources_en_US.properties存放英文界面标题。,在界面上增加两个超级链接,用于将参数数request_locale的值传递给Action,以切换不同语言界面。,常用Struts2标签,Struts2框架的标签库可以分为3类:,用户界面标签(UI标签),主要用于生成HTML元素的标签。,非用户界面标签,主要用于数据访问、逻辑控制等。,AJAX标签,该标签用来支持AJAX技术。,其中,用户界面标签(UI标签),可以分为下面两类:,表单标签,表单标签主要用于生成HTML页面的Form元素,以及普通表单元素标签。,非表单标签,用于生成页面上的tree、tab页等。,非用户界面标签,也可以分为两类:,数据标签,主要包含用于输出值栈(ValueStack)中的值、完成国际化等功能的标签。,控制标签,主要包含用于实现分支、循环等流程控制的标签。,在JSP页面中使用标签库指令后,就可以使用所有的Struts2标签了。,Struts2的OGNL,OGNL(Object Graphic Navigation Language,对象图导航语言),是一种功能强大的表达式语言,可以通过简单的表达式来访问Java对象中的属性。它是Struts2框架的默认表达式语言,增强了Struts2的数据访问能力,简化了代码。,Struts2框架中的ActionContext是OGNL的根对象,即Action对象是OGNL的根对象。假设在Action中有1个属性类型是对象Student(name, age),变量名是stu,那么访问属性name的OGNL表达式为stu.name。,7.5 文件上传和下载,Struts2框架默认使用Common-fileUpload组件实现文件上传,该组件将解析出HttpServletRequest请求中的文件域信息,并使用IO流方式,将文件保存在服务器的指定位置。,使用Struts2的文件上传功能,需要在Web应用中引入两个JAR文件,即commons-io-2.0.1.jar和commons-fileupload-1.2.2.jar。,利用Struts2上传文件,上传文件过滤,Struts 2提供了一个内置的文件上传拦截器fileUpload,通过配置该拦截器可以轻松地实现文件过滤。在Action配置中引用fileUpload拦截器时,可以为其指定两个参数:,allowedTypes,指定允许上传的文件类型,多个文件类型之间以英文逗号(,)隔开。,maximumSize,指定允许上传的文件大小,单位是字节。,上传文件常量配置,在属性文件struts.properties中,可以配置如下两个常量:,struts.multipart.saveDir 指定临时文件的存放位置。,struts.multipart.maxSize 指定整个表达请求内容的最大字节数。,使用Struts2下载文件,文件下载可以通过配置struts.xml中result的类型来实现,,案例7-4 实现博客网站的相册管理,采用Struts2技术实现博客网站中的相册功能。相册管理运行界面如图7-5所示,上传照片界面如图7-6所示,相册浏览界面如图7-7所示。,技术要点,使用Struts2的Action作为控制类。并利用Struts2的文件上传功能。,利用Struts2文件上传拦截器限定上传文件类型。,7.6 拦截器,拦截器,拦截器(Interceptor)是Struts2的核心组成部分。很多功能都是构建在拦截器基础之上的,例如文件的上传和下载、国际化、转换器和数据校验等。Struts2利用内建的拦截器完成了框架内的大部分操作。,拦截器动态拦截Action调用的对象,它提供了一种机制,使开发者可以定义一个特定的功能模块,这个模块可以在Action执行之前或者之后运行,也可以在一个Action执行之前阻止Action执行。,Struts2架构的Action被一个或者多个拦截器(拦截器栈)所包围,所有的用户请求都会被拦截器所拦截,然后交给Action处理,处理结果以逻辑视图方式返回给用户。而这个调用执行流程,是由Struts2的配置文件来实现的。,自定义拦截器,自定义一个拦截器需要三步:,(1)自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。,(2)在struts.xml中注册上一步中定义的拦截器。,(3)在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。,Struts2中Interceptor接口的定义如下:,public interface Interceptor extends Serializable ,void destroy();,void init();,String intercept(ActionInvocation invocation) throws Exception;,案例7-5 使用拦截器实现博客网站的权限验证,权限验证是应用系统不可缺少的组成部分。以相册管理为例,上传照片、相册管理、删除照片这些功能只能由博主使用。为此需要验证用户是否已登录,是否为博主。这可以使用Struts2的拦截器功能。,技术要点,采用方法拦截器,使得当访问ybPictureAction的manage,add以及delete方法时被拦截。这些方法只有博主才能访问。,在拦截器器方法中首先看Session中是否保存过用户对象,即用户是否登录;然后再看用户对象中blogId和请求参数中的blogId是否相等,以判断用户是否是当前博客的博主。,若用户已登录且是博主,则重新调用原功能,否则转到注册界面。,
展开阅读全文