Chinaunix首页 | 论坛 | 博客
  • 博客访问: 334838
  • 博文数量: 329
  • 博客积分: 2633
  • 博客等级: 少校
  • 技术积分: 3633
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-22 15:43
文章分类

全部博文(329)

文章存档

2013年(244)

2012年(46)

2011年(39)

我的朋友

分类: 系统运维

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

   

注意:forwardname必须为success,path为切换语言后跳转的页面.

3).jsp

简体中文

繁体中文

English

其实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

基于strutsWEB应用系统通常情况下应该避免JSP页面之间的跳转。因为这样跳转的用户请求没有经过Struts的处理,会导致很多在Struts框架中进行的处理不起的作用。对于每个用户的请求,strutsRequestProcessor将会进行一系列的处理,其中包括了国际化,权限,缓存等多方面。如果采用页面之间的直接跳转会导致很多内容都需要自己处理。

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类,它和页面中的动作或Servlet中的RequestDispatcherinclude()方法执行的功能一样的。在基于struts框架结构的应用中,最好不要在标记中直接引用另一个JSP页面,而是通过IncludeAciton来实现页面之间的引用,这样比较安全等等。IncludeAction的使用和Forward基本相同,在页面中还可以通过标记来调用。

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.javaDispatchAction的作用简单地说就是把原来我们写在多个acton里的操作放在同一个action里处理。举个例子就是如果在你的系统中有文章的管理操作,那么通常有以下操作:添加文章、察看文章、搜索文章等等,这样的话一般你会写 三个action[ArtilceSaveActionArticleViewActionArticleSearchAction ]分别处理各个操作,虽然说这样看起来是非常清晰、流畅的操作,但是你会发现在三个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 LookupDispatchActionDispatchAction的子类。他们从功能上有许多相似的地方。通常它主要应用于“在一个表单中有多个提交按钮而这些按钮又有一个共同的名字”,这些按钮的名字要和具体的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端的请求: 

此时页面有两个按钮,按钮1View The Article”,按钮2Delete The Atricle

当提交按钮1时调用EditArticleAction里的view方法;

当提交按钮2时调用EditArticleAction里的delete方法;

以下还有一点说明;

如果我有一个按钮要触发actionAA方法,但是在该action没有AA方法,此时将抛出异常;如果该action中有两个AA方法,则会调用第一个。

 

8. MappingDispatchAction

这个action子类帮助将相关的功能组织到一个Action中。MappingDispatchAction1.2新加的, 也继承自DispatchAction. 它实现的功能和上面两个区别较大, 是通过struts-config.xml将多个action-mapping映射到同一个Action类的不同方法上。MappingDispatchAction类在struts-extras-1.3.10.jar中需要将struts-extras-1.3.10.jar放入。与LookupDispatchActionDispatchAction不同,MappingDispatchAction类并不通过请求参数来指定动作,而是将一个Struts动作对应于一个Action方法。下面的例子演示了如何使用MappingDispatchAction类来将 Struts动作和Action方法相对应。

1).Action类的实现代码:

下面的代码有两个Action方法:test1test2。还有一个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 {

        // 处理默认动作,如果没有处理直接返回一个nullActionForward

}

}

2).struts-config.xml的配置

我们可以使用如下的代码来配置MyMappingDispatchAction类:

3).URL访问

可以通过如下的URL来访问test1test2方法,分别会调用MyMappingDispatchAction类的test1test2方法:

    :8080/samples/pdf.do

    :8080/samples/html.do

阅读(1691) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~