Struts应用系统案例设计编程讲解(4)

来源:互联网 发布:专业流程图软件 编辑:程序博客网 时间:2024/06/07 09:30
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

  4 表现层的实现

  表现层主要使用Struts框架完成,Struts分两个部分,一部分是视图View的实现,基本是JSP页面。另外一部分是控制器部分,具体是Action类的继承者,通过Action类的实现将前台界面用户输入的表单数据打包成基本对象,递送到后台处理。

  在图4-11中,pageAction负责两种页面的输出。一个是创建页面;另一个是编辑页面。由于这两个页面数据结构类似,因此采取统一的Action控制输出。当用户填写好创建页面或编辑页面的表单数据后,单击确认按钮后提交,系统将由SavePageAction负责表单数据的处理和保存。

  在SavePageAction中,主要是从用户输入的表单数据PageForm中获取数据,检查合法性,然后将这些数据封装成基本业务对象(Menu或Bodu等),委托给PageHandler实现真正的逻辑处理。而从图4-10中可以看到PageHandler以后的处理过程。

 

  图4-11 表现层的流程图

  关于Struts的开发工具,Jbuilder 8以后版本支持Struts开发,也可以使用其他工具甚至文本编辑器进行相关JSP 和Javabean的编辑。Struts的使用涉及面比较多,而且有不少类似“暗沟”的机制,只要耐心地去理解,相信会熟练掌握。

  1 Struts相关设置

  1.创建一个自己的项目目录。

  要在自己硬盘上建立如下图结构的目录系统:

  CMS

  |

  |--- WEB-INF

  | |

  | |--- classes

  | |

  | |--- lib

  |

  |--- navlink (菜单JSP所在目录)

  |--- template (布局模板目录)

  |--- admin (管理目录)

  |--- body (页面内容所在目录)

  2.加入所需要的Strutss1.1文件。

  将Struts中的*.tld文件加入WEB-INF目录下:

  Strutss-bean.tld

  Strutss-html.tld

  Strutss-logic.tld

  Strutss-nested.tld

  Strutss-template.tld

  Strutss-tiles.tld

  Struts的*.jar的库文件加入lib目录下。

  3.建立web.xml文件如下。

 

 

 

  内容管理系统

 

  action

  org.apache.Strutss.action.ActionServlet

 

  config

  /WEB-INF/Strutss-config.xml

 

 

  debug

  2

 

  2

 

 

  action

  *.do

 

 

  /WEB-INF/Strutss-bean.tld

  /WEB-INF/Strutss-bean.tld

 

 

  /WEB-INF/Strutss-html.tld

  /WEB-INF/Strutss-html.tld

 

 

  /WEB-INF/Strutss-logic.tld

  /WEB-INF/Strutss-logic.tld

 

 

  /WEB-INF/Strutss-template.tld

  /WEB-INF/Strutss-template.tld

 

 

  关于编码问题。由于Java是跨平台的,Java在进行需要读取文件或显示等操作时,往往是按照运行平台的默认编码方式。在中文Winodws平台是GBK, 在Linux平台是ISO8859-1。由于在项目中用到很多组件框架,比如Strutss等,这些软件的默认编码方式都可能是ISO8859-1。英语环境下的人们还没习惯用UTF-8,那么就很容易造成在整个项目系统中编码不统一,从而导致乱码。

  统一编码就成了编写支持中文系统的重要而且棘手的任务,本项目中将使用UTF-8为统一编码。这包括几个方面:JSP输入输出、Javabeans的编译、数据库或文件系统的访问、配置文件的设置。

  2 创建PageForm

  Struts中需要一个ActionForm,它实际是一个Javabean,字段都是JSP中form的一些字段,如果有过JSP/Javabeans开发经验的人会使用下列代码:

 

 

 

  这里UserInfoBean的字段对应HTML中Form表单的字段,从而在Form提交时,表单字段自动映射到UserInfoBean的字段。如果不清楚,可以参阅有关JSP/Javabeans的章节。

  将要建立的PageForm其实就是类似UserInfoBean的Javabean:

  //pageForm是继承Struts中的ActionForm的

  public class PageForm extends ActionForm {

  // Page的Id

  private Integer id;

  //Page的名字,就是菜单的名字

  private String name;

  //Page的Html内容

  private String htmlText;

  //Page的标题

  private String title;

  public void setId(Integer id) { this.id = id; }

  public Integer getId() { return id; }

  public void setName(String name) { this.name = name; }

  public String getName() { return name; }

  public void setHtmlText(String htmlText) { this.htmlText = htmlText; }

  public String getHtmlText() { return htmlText; }

  public void setTitle(String title) { this.title = title; }

  public String getTitle() { return title; }

  /**

  * 下面是设置校验,进行表单的错误检查

  * 如果本方法返回是null,Struts将不会进行错误输出

  * 如果不为空,将会输出错误,错误内容是error.name.required的值

  */

  public ActionErrors validate(ActionMapping actionMapping,

  HttpServletRequest httpServletRequest) {

  ActionErrors errors = new ActionErrors();

  //如果没有输入页面的名字,需要报错

  if ( (name == null) || (name.length() < 1)){

  Debug.logVerbose(" error: name is required ", module);

  errors.add("name", new ActionError("error.name.required"));

  }

  //如果没有输入页面的标题,需要报错

  if ( (title == null) || (title.length() < 1)){

  errors.add("title", new ActionError("error.title.required"));

  }

  return errors;

  }

  //复位,将数据清空

  public void reset(ActionMapping actionMapping,

  HttpServletRequest httpServletRequest) {

  this.id = null;

  this.name = null;

  this.title = null;

  this.htmlText = null;

  }

  }

  在PageForm中validate方法要启用,需要几个步骤:

  首先在validate方法中加入字段检验,如果返回不为空,Struts将启动错误输出。

  然后,为Strutss错误输出做准备工作,比如上面的name为空,则Struts会到一个ApplicationResources.properties 文件中查询error.name.required对应的值。

  在ApplicationResources.properties输入error.name.required的值:

  error.name.required=

  • need name
  •   error.title.required=

  • need title
  •   error.id.required=

  • need id
  •   error.action.required=

  • need action
  •   # 下面是错误输出时的标题和尾部,可以自己定制

      errors.footer=


      errors.header=

    Validation Error

    You must correct the following error

      这样,Struts会取得error.name.required对应的值

  • need name
  • 输出。那么输出到哪里?当然是JSP页面,只要在需要错误输出的JSP页面中增加如下语句:

     

      至于具体位置加在JSP页面的哪个部位,则取决于页面设计了。

      注意,最后还有最重要的一步,必须告诉Struts这个ApplicationResources.properties在什么位置。一般ApplicationResources.properties是放在项目的classes目录下和具体的class绑定在一起。

      在WEB-INF下建立Strutss-config.xml文件,这是Struts最重要的核心配置文件,需要在其中加入:

      <Strutss-config>

     

     

     

     

      Strutss-config>

      在Struts-config.xml中,定义了一个FormBean是PageForm。它实际是PageForm类。同时,还需要告诉Struts,ApplicationResources.properties是在类classess目录的com/jdon/cms/events目录下,和com.jdon.cms.events的其他类在一起。

      3 创建PageAction

      Action是和控制器Servlet在一起工作的,Action是整个系统中关键的、起调度控制作用的类。

      在Action类中,将要处理前面页面输入本类的参数,进行相关业务逻辑运算。然后根据结果,从Strutss-config.xml中根据用户定制的Forward页面,将Forward页面推到用户的浏览器中去。

      PageAction是控制页面输出的,使用pageAction.do?action=create 或pageAction.do? action=edit控制create或edit页面输出,前者会输出createPage.jsp,后者则会输出editPage.jsp。

      PageAction中主要实现两种功能:

      · 如果要求输出的是编辑页面,那么就需要将编辑的数据首先显示出来。

      · 查询Strutss-config.xml,决定输出新增页面还是编辑页面。

      PageAction主要代码如下:

      public class PageAction extends Action {

      public ActionForward execute(ActionMapping mapping,

      ActionForm form,

      HttpServletRequest request,

      HttpServletResponse response) {

      String action = request.getParameter("action");

      //清除之前的Attribute中的数据

      FormBeanUtil.remove(mapping, request);

      //获得pageForm对象并在attribute中保存起来,实现第一个功能

      extractPageForm(action, mapping, form, request);

      //根据action的值,从mapping中查询出决定跳转的页面,然后直接跳转

      if (action.equals(PageEvent.DELETE))

      return (mapping.findForward("deletePage"));

      else if (action.equals(PageEvent.EDIT))

      return (mapping.findForward("editPage"));

      else

      return (mapping.findForward("createPage"));

      }

      …

      }

      其中extractPageForm方法主要是实现PageAction的第一个功能,主要内容如下:

      private void extractPageForm(action, ActionMapping mapping, ActionForm form,

      HttpServletRequest request){

      //获得id

      Integer id = new Integer(request.getParameter("id"));

      //通过PageHandler来获得该id的数据

      PageHandler pageHandler = new PageHandler();

      Page page = pageHandler.getPage(id);

      //使用Javabean复制功能,将page对象中和pageForm一样的字段

      //复制到pageForm中,这是一个自动方便的转换工具

      PropertyUtils.copyProperties(pageForm, page);

      }

      PageAction中跳转页面的功能是通过mapping.findForward实现的,这个方法是从ActionMapping中获取跳转页面,而ActionMapping的数据是在Strutss-config.xml中设置的:

     

     

      type="com.jdon.cms.events.PageAction"

      validate="false"

      scope="request"

      path="/pageAction">

     

     

     

     

     

      在action-mappings中指定了“/admin/createPage.jsp”等几个跳转的JSP文件。

      PageAction的第一个功能实现是事先创建好一个ActionForm实例,根据id查询数据源,获得相应的数据并将其赋值到这个实例中,名称为pageForm。

      这样,就得到了一个装有数据的pageForm实例,PageAction在自己结束后,如何让editPage.jsp自动获取这个有数据的pageForm,这里有一个Hook钩子,Struts是通过使用Servlet的request或session的attribute来作为中转储存空间的。

      如果当前的Scope是request,那么使用

      request.setAttribute(actionMapping.getAttribute(), pageForm);

      如果当前Scope是session,那么使用

      session.setAttribute (actionMapping.getAttribute(), pageForm);

      那么,actionMapping.getAttribute()的值是什么?这是在Strutss-config.xml里的action-mapping中设置的,设置attribute="pageForm"。

      注意这里没有设置通常的name="pageForm",这两者是有区别的。

      由于没有设置name="pageForm",那么需要同时设定validate="false"。因为这个Action没有与ActionForm相联系,所以不要实现校验功能。

      关于使用Action的注意点: Action其实是Servlet的一部分,而Servlet本质就是线程,在默认情况下,Action只有一个实例对象,以多线程方式为所有请求服务,因此编写Action类必须考虑线程安全性:

      · 使用局部变量,不要用类变量。

      · 要考虑资源争夺的问题。

      · 对于Exception的捕获,捕获后输出日志系统,而不要使用throw抛出。

      4 创建page.jsp页面

      在JSP中消除Java代码分两个步骤:

      · 能够在Action中实现的功能移动到Action中实现。

      · 使用Struts标签语句替代Java代码实现的功能。在JSP中使用Struts特殊标签语句,参考http://jakarta.apache.org/Strutss/userGuide/dev_html.html。

      page.jsp是将createPage.jsp和editPage.jsp的功能合并在一起,因为这两个页面的数据布局和结构非常相似。page.jsp代码如下:

     

      <%@ page contentType="text/html; charset=UTF-8" %>

      <%@ taglib uri="/WEB-INF/Strutss-logic.tld" prefix="logic" %>

      <%@ taglib uri="/WEB-INF/Strutss-template.tld" prefix="template" %>

      <%@ taglib uri="/WEB-INF/Strutss-bean.tld" prefix="bean" %>

      <%@ taglib uri="/WEB-INF/Strutss-html.tld" prefix="html" %>

      <%@ taglib uri="/WEB-INF/app.tld" prefix="app" %>

     

     

     

     

     

      scope="request" value="create">

      新增页面

     

     

     

      scope="request" value="edit">

      编辑页面

     

     

     

      scope="request" value="delete">

      删除页面

     

     

     

     

     

     

      scope="request" value="create">

     

    新增页面

     

     

      scope="request" value="edit">

     

    编辑页面/

     

     

      删除本页

     

     

     

     

     

     

     

      scope="request" value="create">

     

     

     

     

     

      页面名称:

     

      页面标题:

     

      页面内容:

     

     

     

     

     

     

      从上面JSP页面看出来,这个页面中已经全部没有了Java代码,代替以特有的标签语句,其中典型html:text语法如下:

     

      相当于以前的代码:

      <% if (pageForm.getName() ! = null) %>

      ”>

      <% else %>

     

      由此可见,标签库使用是简单方便的。一开始有很多人并不喜欢标签库,从而在JSP中嵌入Java,这种倾向导致的危险是非常大的。可以毫不夸张地说,这样做最终会将Java体系的优越性丧失殆尽。

      5 自定义标签库

      在page.jsp中,还自定义了一个自己特定的标签:

     

      删除本页

     

      这相当于:

     

      /pageAction.do?action=delete&id=<%id%>" >

      删除本页

     

      可见,为了完全取消JSP中的Java代码,必要时,要亲自动手定制标签库。下面看看如何实现。

      在page.jsp的顶部引入了app.tld:

      <%@ taglib uri="/WEB-INF/app.tld" prefix="app" %>

      这需要在WEB-INF目录下建立app.tld:

     

      1.0

      1.1

      Application Tag Library

      http://jakarta.apache.org/taglibs/

     

     

     

      linkHtml

     

      com.jdon.cms.tags.LinkHtmlTag

     

     

     

      name

      true

      true

     

     

      page

      true

      true

     

     

     

      在这个app.tld中定义了linkHtml标签,这样在page.jsp中就可以使用

      。

      其中page和name是两个属性参数,需要输入到类com.jdon.cms.tags.LinkHtmlTag进行处理的。实际上app.tld是在JSP页面和Javabean之间作了一个连接。编写LinkHtmlTag的代码:

      public class LinkHtmlTag extends TagSupport {

      protected String name = null;

      protected String page = null;

      public String getName() { return (this.name); }

      public void setName(String name) { this.name = name; }

      public String getPage() { return (this.page); }

      public void setPage(String page) { this.page = page; }

      /**

      * 生成标签开始 也就是在JSP中写

      *

      */

      public int doStartTag() throws JspException {

      //相当于在JSP中写入<%request.getContextPath()%>

      HttpServletRequest request =

      (HttpServletRequest) pageContext.getRequest();

      StringBuffer url = new StringBuffer(request.getContextPath());

      url.append(page);

      //根据name属性值,获取pageForm对象

      PageForm pageForm = null;

      try {

      pageForm = (PageForm) pageContext.findAttribute(name);

      } catch (ClassCastException e) {

      pageForm = null;

      }

      if (page.indexOf("?") < 0)

      url.append("?");

      else

      url.append("&");

      url.append("id=");

      url.append(pageForm.getId());

      // 产生连接内容,相当于在JSP中写入:

      //

      HttpServletResponse response =

      (HttpServletResponse) pageContext.getResponse();

      StringBuffer results = new StringBuffer("

      results.append(response.encodeURL(url.toString()));

      results.append("/">");

      // 将results字符串输出到JSP页面 JspWriter writer = pageContext.getOut();

      try {

      writer.print(results.toString());

      } catch (IOException e) {

      throw new JspException("LinkHtmlTag error");

      }

      return (EVAL_BODY_INCLUDE);

      }

      /**

      * 生成替代JSP页面中代码

      * 这里是以替代

      */

      public int doEndTag() throws JspException {

      JspWriter writer = pageContext.getOut();

      try {

      writer.print("");

      } catch (IOException e) {

      throw new JspException ("LinkHtmlTag error");

      }

      return (EVAL_PAGE);

      }

      public void release() {

      super.release();

      this.page = null;

      }

      }

      标签库表面上好像比较繁琐,没有在JSP直接写Java代码来得直接方便。但是,J2EE的整个体系本身的特点就是细化、细分,这也符合面向对象分派和封装的原则,因此在J2EE中到处可以看到一点一点的“碎片”,XML配置文件和Java代码在J2EE中往往是自然地组合在一起。当然,这样带来的缺点是增加了复杂性。

      6 创建SavePageAction

      上面的page.jsp是向savePageAction.do提交表单Form的,SavePageAction也是一个Action,主要负责将表单提交的数据实现保存。

      SavePageAction和PageAction的用途不一样。后者是主要控制创建或编辑功能页面的输出。这两种Action基本包括了Action的用途,在其他项目中可以参照这两个Action做法,其实这也算一个模式了吧?这个模式主要是对数据创建或编辑功能适用。

      为了激活savePageAction.do,需要在Strutss-config.xml中的action-mappings加入:

     

      type="com.jdon.cms.events.SavePageAction"

      validate="true"

      input="/admin/pageError.jsp"

      scope="request"

      path="/savePageAction" />

      应该注意到这里使用了name="pageForm",不同于PageAction中使用的attribute="pageForm",两者目的各有不同,因为PageForm和SavePageAction联系了在一起,当page.jsp向SavePageAction提交表单数据时,Strutss将数据保存在PageForm对应的字段中,如果validate又设置为true,那么就会执行PageForm中的validate方法。SavePageAction可以从PageForm中获取page.jsp中的表单数据。

      这里还有一层含义,因为page.jsp中提交Action是savePageAction.do,而上面关于savePageAction.do的设置是使用com.jdon.cms.events.SavePageAction类,同时name是pageForm,那么就是说pageForm指向的实例是page.jsp 的FormAction了,或者说是Form Bean,这也说明了为什么在page.jsp显示之前,PageAction将包含数据的PageForm实例保存在request或session的attribute中,而page.jsp在显示时,会自动读取PageForm实例中的数据。

      在上面的action-mappings配置中,激活了校验功能。如果Struts校验发现了错误,Struts将会输出错误,那么错误输出哪个JSP页面?就是input中输入的值/admin/pageError.jsp,这里专门做了一个出错页面pageError.jsp。当然不能忘记在pageError.jsp中加入

      SavePageAction主要是委托业务逻辑层的PageHandler再通过数据层实现数据保存和持久化:

      public class SavePageAction extends Action {

      public ActionForward execute(ActionMapping actionMapping,

      ActionForm actionForm,

      HttpServletRequest request,

      HttpServletResponse response) {

      …

      //生成PageEvent

      PageEvent pageEvent = new PageEvent();

      Page page = new Page();

      try {

      //将pageForm中的数据复制到Page对象中

      PropertyUtils.copyProperties(page, pageForm);

      //使PageEvent装载Page数据对象

      pageEvent.setPage(page);

      //设置操作类型是创建还是编辑

      pageEvent.setAction(pageForm.getAction());

      }

      catch (Exception e) {

      Debug.logError("copyProperties Error:" + e, module);

      }

      //委托pageHandler实现具体数据操作

      PageHandler pageHandler = new PageHandler();

      if (pageHandler.perform(pageEvent)){

      Debug.logVerbose("update page success " , module);

      return actionMapping.findForward("pageOk");

      }else

      return actionMapping.findForward("pageError");

      }

      }

      当然页面提交后台实现操作后,如果成功,SavePageAction就向前台用户界面输出pageOk.jsp页面,表示操作成功。

      至此,本项目中关于Page的内容操作流程基本结束,下面将讨论模板的实现。

      7 Tile模板

      在前面设计中,一个页面被分为几个区域:标题栏、页尾栏、菜单栏以及内容栏部分。如何使用Tile将这几个部分组合在一起?

      Tile的页面组装配置可以在JSP,也可以在tiles-defas.xml中。

      关于在JSP中定义已经在前面介绍中看到,只要输入下列语句:

     

     

     

     

     

      tiles:insert就类似JSP的include,在这个JSP运行时,Strutss-Tiles将分别将header.jsp body.jsp和footer.jsp一起输出。

      但是,如果每次将其他不变部分都写入JSP,也将是比较琐碎的事情,在配置文件tiles-defs.xml中定义将更加灵活,还可以有继承的概念。

      在WEB-INF下建立tiles-defs.xml文件,当然建立好tiles-defs.xml后,还要记得告诉Strutss-Tiles,那么就要在Strutss-config.xml中加入下列语句:

      Strutss.tiles.TilesPlugin">

     

     

      这表示将要使用插件TilesPlugin,插件的配置文件是/WEB-INF/tiles-defs.xml。

      下面建立/WEB-INF/tiles-defs.xml:

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

      在tiles-defs.xml中,定义了一个叫site.mainLayout的页面,实际页面是来自相对目录/template/no1/layout/下的classicLayout.jsp。

      那么应该在classicLayout.jsp中定义整个页面的大体布局,如下:

      <%@ page contentType="text/html; charset=UTF-8" %>

      <%@ taglib uri="/WEB-INF/Strutss-tiles.tld" prefix="tiles" %>

     

     

     

     

     

     

     

     

     

     

      &nbsp;

     

     

     

     

     

     

     

     

     

      &nbsp;

     

     

     

     

     

      在上面布局中,分别使用tiles:insert 来代替这里的区域,这个页面布局模板是可以自己调换,例如可以将菜单栏搬迁到右边或上下边,这些都可以根据美工师设计要求进行设计,一旦确定4个部分后,只要使用tiles:insert来放置在这些HTML语法中,将来JSP显示时,Strutss-Tiles会用实际的页面自动替代这些tiles:insert。例如:

     

     

      表示分别用相对目录/tempalte/no1/下header.jsp和footer.jsp替代部分。

      那么,菜单部分使用什么JSP来替代?

      8 创建cmsMenu.jsp

      菜单不像header.jsp那样,可能不是动态变化的。由于管理员随时可能会增加或删除页面,那么肯定引起指向页面的菜单按钮的变化,所以菜单的显示是需要和本项目中的逻辑处理层联系在一起的。

      在上面的tiles-defs.xml中有一句定义菜单的配置:

     

      这表示菜单是从目录navlink下的cmsMenu.jsp中读取的,因此需要创建cmsMenu.jsp:

      <%

      //获得PageFactory指向

      PageFactory pageFactory = PageFactory.getInstance();

      //从pageFactory中获得Navlink实例

      Navlink navlink = pageFactory.getNavlink();

      request.setAttribute("navlink", navlink);

      %>

      <%-- 遍历 Navlink对象中menus集合,取出com.jdon.cms.Menu 对象 --%>

     

      property="menus" type="com.jdon.cms.Menu" >

      <%

      String link = menu.getLink();

      %>

     

      "><%=menu.getName()%>

     

     

      cmsMenu.jsp是将页面Page的Navlink中menus集合逐个读出来,然后从上向下显示。当然具体显示方式(如并排显示)可以自己定制。这个JSP含有Java代码,因此需要重整一下。类似前面章节Page操作一样,使用ActionForm或标识库实现优化。

      9 创建index.jsp

      为了验证上述配置和设计,可以在根目录下创建index.jsp作为模拟显示,测试观察效果。在index.jsp中写入:

      <%@ page contentType="text/html; charset=UTF-8" %>

      <%@ taglib uri="/WEB-INF/Strutss-tiles.tld" prefix="tiles" %>

     

      这表示,在这里插入tiles-defs中的site.index.page页面,而site.index.page是从tiles-defa.xml中得知,正好继承的是site.mainLayout,而site.mainLayout指向classicLayout.jsp,得到index.jsp的效果图如图4-12所示。

     

      图4-12 index.jsp的效果图

      可见,使用Tiles实现本项目中的模板功能是成功的。当管理员创建一个新的页面时,本系统将依次创建菜单、HTML内容以及模板JSP,在模板JSP中只要写入index.jsp中类似内容。例如,管理员创建了一个叫“产品和服务”的新页面,得到的页面id是2,那么在2.jsp中程序会自动写入:

     

     

     

     

      这样,图4-12屏幕中的“This is body”部分将被管理员输入的有关“产品和服务”的实际内容所代替。

      10 小技巧

      在J2EE应用中经常需要知道某个文件的绝对路径,如何能从Web容器中自动获得某文件的绝对路径?

      例如上节中,1.jsp中body指向的是“/data/1.jsp”,在相对目录data下的1.jsp是系统程序自动生成的。也就是说使用了File有关API操作,而File操作必须提供绝对路径。例如,在项目系统建立c:/cms下,目录结构见前面章节,那么“/data/1.jsp”的绝对路径应该是c:/cms/data/1.jsp。注意,如果有本地文件操作,那么系统就不能打包成*.war,必须提供完整的目录路径。

      那么如何获取根目录c:/cms?通过配置文件设定也可以,但是不灵活,每次移动项目都要修改配置文件。

      Servlet中有servlet.getServletContext().getRealPath(pathname);,可以得到pathname的绝对路径,因为每个Web应用中,肯定有WEB-INF/web.xml文件,而通过上句就可以获得web.xml的绝对路径。经过简单处理就可以获得系统的绝对路径。

      但是在哪里执行语句:servlet.getServletContext().getRealPath(“web.xml”)?

      专门写个初始化的Servlet不是很合适;如果在JSP中写入显然不很规范。 Strutss 1.1提供了Plug-in功能,一般是在系统启动先执行Plug-in,前面定义的tiles-defa.xml就是通过Plug-in启动使用的。

      只要创建一个类FileEnvPlugIn来继承org.apache.Strutss.action.PlugIn,在init方法中将系统的绝对根目录获得就可以了。有兴趣者可以进一步参考Plu

    <script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
    <script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>