分类: 系统运维
2012-03-25 13:10:36
本文介绍了以下的struts用到的类:
PropertyUtils
DownloadAction
LocaleAction
ForwardAction
IncludeAction
DispatchAction
LookupDispatchAction
MappingDispatchAction
1.PropertyUtils
一般我们使用:
public ActionForward addresult(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response){
RegistrationForm one = (RegistrationForm) form;
String userid=one.getUserId();
String password=one.getPassword();
}
但是上述方式是类型转换的,有缺点:
1).没有动态表单
2).紧密耦合。非常强烈地与ActionForm类耦合在一起,阻止了Action与其他ActionForm的重用。
因此我们可以使用PropertyUtils:
public ActionForward addresult(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response){
String userid=PropertyUtils.getProperty(form,”userid”);
String password= PropertyUtils.getProperty(form,”password”);
}
但是使用PropertyUtils也有缺点,它的缺点和使用动态的bean有些类似,将失去编译时检查的机会。实际上,将在编译时检查和类的松散耦合之间做出权衡折中。
然而在大多数情况下,这是利大于弊的。因此,除非有一个更好的理由,请使用PropertyUtils来访问表单或bean的属性,长期使用它,会使代码在长期运行中都保持较好的可维护性。
2.DownloadAction
下载一个静态文件很简单,只要将其链接放到网上的页面中即可。然而,经常会出现这样的情形,即请求的数据是根据请求动态产生的。此时,必须自己处理下载过程。
这并不困难(需要编写一个有效的HTTP头部,然后通过execute()方法把数据放进HttpServletResponse对象中),但它稍微有些繁琐。新引入的(从版本1.2.6以后)的DownloadAction大大简化了这个工作。所需要提供的就是:
1).一个包含了要下载的数据的InputStream。
2).一个“内容类型”字符串(比如,text/html或者image/png),它描述了数据的格式。
DownloadAction有一个内部的静态接口,名为StreamInfo:
Public static interface StreamInfo{
Public abstract String getContentType();
Public abstract InputStream()throws IOException;
}
这个接口通过getContentType()暴露内容类型,通过getInputStream()暴露InputStream。要使用这个DownloadAction,需要:
1).实现StreamInfo接口
2).通过子类化DownloadAction而且覆盖其getStreamInfo()方法来暴露它。
3).在struts-config.xml文件中配置一个表单处理器,但不需要配置
DownloadAction有两个内部类,FileStreamInfo(下载静态文件)和ResourceStreamInfo(下载一个位于Web应用程序的根目录中的文件),每一个都实现了StreamInfo接口。
大多数情况下,我们都偏爱使用http链接,但是如果不想暴露对被下载文件的链接,会发现这是非常有用的。
以下是三个例子:
1).通用的在下模式
import java.io.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.apache.struts.actions.DownloadAction;
public class MyDownloadAction extends DownloadAction{
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
InputStream input=……;
String contentType = ……;
rerturn new StreamInfo{
public String getContentType(){return contentType;}
public InputStream getInputStream(){return input;}
}
}
}
2).FileStreamInfo Example
//Example of using the with a file. This example picks up the file name from the parameter attribute in the strust-config.xml action mapping.
import java.io.File;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DownloadAction;
public class ExampleFileDownload extends DownloadAction{
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
// Download a "pdf" file - gets the file name from the Action Mapping's parameter
String contentType = "application/pdf";
File file= new File(mapping.getParameter());
return new FileStreamInfo(contentType, file);
}
}
3).ResourceStreamInfo Example
//Example of using the with a web application resource. This example picks up the web application resource path from the parameter attribute in the strust-config.xml action mapping.
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DownloadAction;
public class ExampleResourceDownload extends DownloadAction {
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
// Download a "jpeg" file - gets the file name from the
// Action Mapping's parameter
String contentType= "image/jpeg";
String path= mapping.getParameter();
ServletContext application = servlet.getServletContext();
return new ResourceStreamInfo(contentType, application, path);
}
}
4).Byte Array Example
//Example of using the with a Byte Array. This example creates a inner class which implements the interface. (we should include this in the implementation)
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DownloadAction;
public class ExampleByteArrayDownload extends DownloadAction {
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
String contentType = "application/pdf";// Download a "pdf" file
byte[] myPdfBytes = null; // Get the bytes from somewhere
return new ByteArrayStreamInfo(contentType, myPdfBytes);
}
protected class ByteArrayStreamInfo implements StreamInfo {
protected String contentType;
protected byte[] bytes;
public ByteArrayStreamInfo(String contentType, byte[] bytes) {
this.contentType = contentType;
this.bytes = bytes;
}
public String getContentType() {
return contentType;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(bytes);
}
}
}
3.LocaleAction
国际化的时候我们在服务器端需要切换场所,LocalAction是另一种方法来切换场所。LocalAction的方式,并不一定要写一些java代码来使用LocalAction
struts应用程序的语言, 默认与浏览器的语言相同。下面我们利用localeAction来切换语言.
1).在struts-config.xml中添加一个 动态actionFrom
......
........//其它的formbean
2).配置Action
注意:forward的name必须为success,path为切换语言后跳转的页面.
3).jsp
其实LocaleAction这样实现:
package org.apache.struts.webapp.validator;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public final class LocaleAction extends Action {
private Log log = LogFactory.getFactory().getInstance(this.getClass().getName());
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
// Extract attributes we will need
HttpSession session = request.getSession();
Locale locale = getLocale(request);
String language = null;
String country = null;
String page = null;
try {
language = (String)
PropertyUtils.getSimpleProperty(form, "language");
country = (String)
PropertyUtils.getSimpleProperty(form, "country");
page = (String)
PropertyUtils.getSimpleProperty(form, "page");
} catch (Exception e) {
log.error(e.getMessage(), e);
}
if ((language != null && language.length() > 0) &&
(country != null && country.length() > 0)) {
locale = new java.util.Locale(language, country);
} else if (language != null && language.length() > 0) {
locale = new java.util.Locale(language, "");
}
session.setAttribute(Globals.LOCALE_KEY, locale);
if (null==page) return mapping.findForward("success");
else return new ActionForward(page);
}
}
4.ForwardAction
基于struts的WEB应用系统通常情况下应该避免JSP页面之间的跳转。因为这样跳转的用户请求没有经过Struts的处理,会导致很多在Struts框架中进行的处理不起的作用。对于每个用户的请求,struts的RequestProcessor将会进行一系列的处理,其中包括了国际化,权限,缓存等多方面。如果采用页面之间的直接跳转会导致很多内容都需要自己处理。
1).在struts中配置ForwardAction
type="org.apache.struts.actions.ForwardAction"
parameter="/index.jsp"
/>
其中path属性是Action的匹配路径,type属性说明实现Action的类,parameter属性用于指定往哪转发,也就是转发的目的URI。这三个属性是必须的,其它的可以省略。
2).使用forward进行页面跳转的配置方法如下
forward="/index.jsp"
/>
3).forward属性和ForardAction在页面中使用时是没有区别的,并且在通常情况下struts对这两种形式的跳转的处理也是相同的。但是使用自己的RequestProcessor并且覆盖了父类的processForwardConfig()方法时,这两种方式就存在一定的区别了。
5.IncludeAction
IncludeAction类的意义类似于ActionForward类,它和页面中的
1). IncludeAction
IncludeAction的配置
type="org.apache.struts.actions.IncludeAction"
parameter="/include.jsp"
/>
2).include属性:Struts也可以通过使用include属性来在Action的配置文件中直接定义被引用的页面。如:
include="/include.jsp"
/>
6.DispatchAction
DispatchAction来自org.apache.struts.actions.DispatchAction.java。DispatchAction的作用简单地说就是把原来我们写在多个acton里的操作放在同一个action里处理。举个例子就是如果在你的系统中有文章的管理操作,那么通常有以下操作:添加文章、察看文章、搜索文章等等,这样的话一般你会写 三个action[ArtilceSaveAction,ArticleViewAction,ArticleSearchAction ]分别处理各个操作,虽然说这样看起来是非常清晰、流畅的操作,但是你会发现在三个action理由太多的相同的东西。现在利用 DispatchAction,我们可以把“相似”的action放在一个action里操作。下面以上边的三个action和到一个action里为例:
import ****;
import org.apache.struts.actions.DispatchAction;
public class ArticleAction extends DispatchAction{
/** AritcleAddAction */
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
...
...
}
/** ArticleViewAction */
public ActionForward view(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
...
...
}
/** ArticleSearchAction */
public ActionForward search(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
...
...
}
好了,该action的框架已经完成,但是要想可用,还要有一步不可少的操作,那就是更改你的action mapping,还以上边的例子,如下:
input="/article/***.jsp"
parameter="method"
scope="request"
type="com.***.ArticleAction"
validate="false">
看到上边你会发现,它和我们通常的写法多个一项:“parameter="method"”,这是有道理的并且非常重要:DispatchAction会根据具体的method值来确定调用add,view 或者search ,如下面的来自client的请求,article.do?method=add 则会触发添加文章的操作。
7.LookupDispatchAction
LookupDispatchAction来自org.apache.struts.actions.LookupDispatchAction.java 。LookupDispatchAction是DispatchAction的子类。他们从功能上有许多相似的地方。通常它主要应用于“在一个表单中有多个提交按钮而这些按钮又有一个共同的名字”,这些按钮的名字要和具体的action mapping中的parameter的值对应。
如下代码截取自struts-config.xml:
1).
type="com.****.EditArticleAction"
name="AtricleForm"
scope="request"
parameter="action">
2). jsp页面的表单部分
3).那么相应的ApplicationResources.properties中就会有如下片断:
button.view=View The Article
button.delete=Delete The Atricle
此时还并为完成,在LookupDispatchAction中有一个抽象方法:
protected abstract Map getKeyMethodMap();
这个方法你应该在EditArticleAction中实现,如下:
protected Map getKeyMethodMap(){
Map map = new HashMap();
map.put("button.view", "view");
map.put("button.delete", "delete");
return map;
}
好了,假设在你的EditArticleAction有如下方法:
public ActionForward view(ActionMapping mapping, ActionForm form,
HttpServletRequest request,HttpServletResponse response)throws IOException,
ServletException {
//......
//......
return mapping.findForward("success");
}
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException {
//......
//......
return mapping.findForward("success");
}
下面实例几个假设client端的请求:
此时页面有两个按钮,按钮1“View The Article”,按钮2“Delete The Atricle”
当提交按钮1时调用EditArticleAction里的view方法;
当提交按钮2时调用EditArticleAction里的delete方法;
以下还有一点说明;
如果我有一个按钮要触发action的AA方法,但是在该action没有AA方法,此时将抛出异常;如果该action中有两个AA方法,则会调用第一个。
8. MappingDispatchAction
这个action子类帮助将相关的功能组织到一个Action中。MappingDispatchAction是1.2新加的, 也继承自DispatchAction. 它实现的功能和上面两个区别较大, 是通过struts-config.xml将多个action-mapping映射到同一个Action类的不同方法上。MappingDispatchAction类在struts-extras-1.3.10.jar中需要将struts-extras-1.3.10.jar放入。与LookupDispatchAction、DispatchAction不同,MappingDispatchAction类并不通过请求参数来指定动作,而是将一个Struts动作对应于一个Action方法。下面的例子演示了如何使用MappingDispatchAction类来将 Struts动作和Action方法相对应。
1).Action类的实现代码:
下面的代码有两个Action方法:test1和test2。还有一个unspecified方法用来处理默认动作。
import org.apache.struts.actions.MappingtDispatchAction;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import java.util.*;
public class MyMappingDispatchAction extends MappingDispatchAction
{
public ActionForward test1(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
// 定义一个名为pdf方法
}
public ActionForward test2(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
// 定义一个html方法
}
public ActionForward unspecified(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// 处理默认动作,如果没有处理直接返回一个null的ActionForward
}
}
2).struts-config.xml的配置
我们可以使用如下的代码来配置MyMappingDispatchAction类:
3).URL访问
可以通过如下的URL来访问test1和test2方法,分别会调用MyMappingDispatchAction类的test1和test2方法:
:8080/samples/pdf.do
:8080/samples/html.do