Struts1教程之ActionMapping_动力节点Java学院整理

首先断点走出了processpath方法,

这个方法是用来截取字符串的,今天我们来看怎样获得ActionMapping的方法---processMapping。

在此之前简单说一下ActionMapping,它的源代码中可以看出,其中最重要的属性和我们的mvc小实例中的ActionMapping类似,都是有path、type还有forwardMap,主要是对应的struts-config配置文件而来,这个就是保存这个配置文件的信息到内存中。

具体的mvc小实例的ActionMapping代码如下:

package com.cjq.servlet; 

import java.util.Map; 

public class ActionMapping { 

  private String path; 

  private Object type; 

  private Map forwardMap; 

  public String getPath() {
    return path;
  } 

  public void setPath(String path) {
    this.path = path;
  } 

  public Object getType() {
    return type;
  } 

  public void setType(Object type) {
    this.type = type;
  } 

  public Map getForwardMap() {
    return forwardMap;
  } 

  public void setForwardMap(Map forwardMap) {
    this.forwardMap = forwardMap;
  } 

}

而Struts中的Actionconfig(因为ActionMapping是继承这个ActionConfig的,所以我们来看ActionConfig更加直接)的代码如下:

从这两部分代码来看,更加印证了我在开篇写的mvc小实例是一个struts框架的雏形。

讲完ActionMapping的一些内容后,相信对ActionMapping有所了解,那么系统是如何生成ActionMapping和如何找到ActionMapping的呢?这就是今天要说的整体:

我们看下web.xml中有一个<load-on-startup>2</load-on-startup>  配置信息,这个信息就是说明了但服务器已启动就动态读取struts-config配置文件把配置文件的信息put到ActionMapping中。所以当我们运行服务器的时候,我们在内存中已经存在对应struts-config配置文件信息对应的ActionMapping。今天就是要通过processMapping读取这个ActionMapping类。

进入断点调试,首先在processMapping方法上设置断点。

进入源代码中:

/**
   * <p>Select the mapping used to process theselection path for this request
   * If no mapping can be identified, createan error response and return
   * <code>null</code>.</p>
   *
   * @param request The servlet request weare processing
   * @param response The servlet response weare creating
   * @param path The portion of the requestURI for selecting a mapping
   *
   * @exception IOException if an input/outputerror occurs
   */
  protectedActionMapping processMapping(HttpServletRequestrequest,
                     HttpServletResponse response,
                     String path)
    throws IOException { 

    // Is there a mapping for this path?
    ActionMapping mapping = (ActionMapping)
      moduleConfig.findActionConfig(path); 

    // If a mapping is found, put it in the request and return it
    if (mapping != null) {
      request.setAttribute(Globals.MAPPING_KEY, mapping);
      return (mapping);
    } 

    // Locate the mapping for unknown paths (if any)
    ActionConfig configs[] = moduleConfig.findActionConfigs();
    for (int i = 0; i < configs.length; i++) {
      if (configs[i].getUnknown()) {
        mapping = (ActionMapping)configs[i];
        request.setAttribute(Globals.MAPPING_KEY, mapping);
        return (mapping);
      }
    } 

    // No mapping can be found to process this request
    String msg = getInternal().getMessage("processInvalid");
    log.error(msg + " " + path);
    response.sendError(HttpServletResponse.SC_NOT_FOUND, msg); 

    return null;
  }

首先我们传入我们在上一步截取的路径,通过moduleConfig的findAction方法来查找ActionConfig,并且返回ActionMapping。具体代码是:

ActionMapping mapping =(ActionMapping)
   moduleConfig.findActionConfig(path); 

如果找到,那么就讲ActionMapping存放到request的context中。代码:

if (mapping != null) {
      request.setAttribute(Globals.MAPPING_KEY, mapping);
      return (mapping);
    } 

如果没有通过path找到mapping,则在Actionconfig中遍历为未知路径寻找mapping,如果找到则存放到request中,如果没有找到,则返回错误信息,具体代码如下:

// Locate the mapping for unknownpaths (if any)
    ActionConfig configs[] = moduleConfigfindActionConfigs();
    for (int i = 0; i < configslength; i++) {
      if (configs[i].getUnknown()) {
        mapping = (ActionMapping)configs[i];
        request.setAttribute(Globals.MAPPING_KEY, mapping);
        return (mapping);
      }
    } 

    // No mapping can be found to process this request
    String msg = getInternal().getMessage("processInvalid");
    log.error(msg + " " + path);
    response.sendError(HttpServletResponse.SC_NOT_FOUND, msg); 

    return null;

来看下ActionServlet中的一个方法processActionForm,当我们在截取字符串,再根据字符串取得ActionMapping(这是前两篇文章中介绍的)之后,我们就要用利用ActionMapping来创建ActionForm了,并且把ActionForm放到request或session中管理。

先来看具体struts中processActionForm方法的具体实现:

/** 

   * <p>Retrieve and return the <code>ActionForm</code> associatedwith 

   * this mapping, creating and retaining oneif necessary. If there is no 

   * <code>ActionForm</code> associated with this mapping,return 

   * <code>null</code>.</p> 

   * 

   * @param request The servlet request weare processing 

   * @param response The servlet response weare creating 

   * @param mapping The mapping we are using 

   */ 

  protectedActionForm processActionForm(HttpServletRequestrequest, 

                     HttpServletResponse response, 

                     ActionMapping mapping) { 

    // Create (if necessary) a form bean to use 

    ActionForm instance = RequestUtilscreateActionForm 

      (request, mapping, moduleConfig, servlet); 

    if (instance == null) { 

      return (null); 

    } 

    // Store the new instance in the appropriate scope 

    if (log.isDebugEnabled()) { 

      log.debug(" Storing ActionForm bean instance in scope '" + 

        mapping.getScope() + "' under attribute key '" +
       mapping.getAttribute() + "'"); 

    } 

    if ("request".equals(mapping.getScope())) { 

      request.setAttribute(mapping.getAttribute(), instance); 

    } else { 

      HttpSession session =requestgetSession(); 

      session.setAttribute(mapping.getAttribute(), instance); 

    } 

    return (instance); 

}

这个方法的大体流程是:根据ActionMapping中的name名称查找ActionForm,如果配置了ActionForm,那么就到request或session中查找,如果在request或session中存在已经创建的ActionForm,那么将返回。如果不存在那么会根据ActionForm的完成路径采用反射进行创建,再将创建好的ActionForm放到request或session中,之后返回ActionForm。

具体我们可以跟随断点调试来看看这个方法是如何运行的。

先设置断点,之后进入processActionForm方法。

第一个步骤就是创建ActionForm:

// Create (if necessary) a formbean to use 

    ActionForm instance = RequestUtils.createActionForm 

      (request, mapping, moduleConfig, servlet); 

    if (instance == null) { 

      return (null); 

    } 

通过调用RequestUtils.createActionForm的方法把ActionMapping中的ActionForm字符串生成对象,并且返回。进入这段代码中:

publicstaticActionForm createActionForm( 

      HttpServletRequest request, 

      ActionMapping mapping, 

      ModuleConfig moduleConfig, 

      ActionServlet servlet) { 

    // Is there a form bean associated with this mapping? 

    String attribute = mappinggetAttribute(); 

    if (attribute == null) { 

      return (null); 

    } 

    // Look up the form bean configuration information to use 

    String name = mapping.getName(); 

    FormBeanConfig config =moduleConfigfindFormBeanConfig(name); 

    if (config == null) { 

      log.warn("No FormBeanConfig found under '"+ name + "'"); 

      return (null); 

    } 

    ActionForm instance = lookupActionForm(request,attribute, mappinggetScope()); 

    // Can we recycle the existing form bean instance (if there is one)? 

    try { 

      if (instance != null && canReuseActionForm(instance,config)) { 

        return (instance); 

      } 

    } catch(ClassNotFoundException e) { 

      log.error(servlet.getInternal().getMessage("formBean",config.getType()), e); 

      return (null); 

    } 

    return createActionForm(config,servlet); 

}

方法首先定义变量name,并且从mapping中获取值,String name = mapping.getName();也就是我们实例中的LoginForm字符串。之后通过调用FormBeanConfig config =moduleConfig.findFormBeanConfig(name);这句话把相应的LoginForm字符串生成相应的对象。

这里要说明的是我们在struts-config配置文件中,配置过这样一个标签信息:

<form-beans> 

    <form-bean name="loginForm" type=".struts.LoginActionForm"/> 

  </form-beans> 

这个标签在服务器一启动的时候就会利用digester读取这里的配置信息,并且放在FormBeanConfig类中,这样我们可以通过上面那一句话就可以把LoginForm字符串生成相应的对象。

之后调用了ActionForm instance = lookupActionForm(request,attribute, mapping.getScope());这个方法,这个方法主要是查找scope属性中有没有存在ActionForm。具体实现:

if ("request".equals(scope)){ 

      instance = (ActionForm)request.getAttribute(attribute); 

    } else { 

      session = request.getSession(); 

      instance = (ActionForm)session.getAttribute(attribute); 

    }

这里判断scope属性值是否为request,如果是则从request中读出ActionForm,如果不是则从session中读出。程序如果是第一次执行,那么ActionForm会是为空的。因为这里的ActionForm为空,所以就进入了if判断语句中,最后通过调用return createActionForm(config, servlet);创建ActionForm并且返回。

之后processActionForm就会把返回来的ActionForm放入request或者session中。具体实现就是:

if ("request".equals(mapping.getScope())){ 

      request.setAttribute(mapping.getAttribute(), instance); 

    } else { 

      HttpSession session =request.getSession(); 

      session.setAttribute(mapping.getAttribute(), instance); 

    }

到此为止,ActionForm就创建完成,当ActionForm创建完成之后,就要用其他的方法来往ActionForm中赋值了

(0)

相关推荐

  • struts1登录示例代码_动力节点Java学院整理

    Struts1框架实例-登录实例: 1.实例开始工作-导入jar包,在官网上下载struts1框架包,解压之后导入工程的: 2.之后配置web.xml(这里的具体配置方法可以参见struts1框架包中的实例文件夹webapps中的实例代码中web.xml文件的配置方法): 具体如下: <span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?> &

  • Struts1和struts2的区别_动力节点Java学院整理

    Struts2其实并不是一个陌生的Web框架,Struts2是以Webwork的设计思想为核心,吸收了Struts1的优点,因此,可以认为Struts2是Struts1和Webwork结合的产物. 简单来说二者的区别是: 一个是Stuts1 ,一个是Stuts2,这是最大的区别,技术方面,Stuts1有个核心控制器,但是只提供了一个接口,也就是execute,还要配置actionform之类的,很麻烦,所以依赖性比较强:而Stuts2是针对拦截器开发的,也就是所谓的AOP思想,可以配置多个act

  • Java中struts2和spring MVC的区别_动力节点Java学院整理

    1.Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易实现restful url,而struts2的架构实现起来要费劲,因为Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了. 2.SpringMVC的方法之间基本上独立的,独享request respons

  • Struts1之url截取_动力节点Java学院整理

    Struts1之url截取 先我们来对ActionServlet深层次进行分析.我们用断点的调试的方式来看底层源码.因为这个实例是post方式提交,所以将断点设置到doPost方法上. 我们debug运行程序,进入doPost里面的方法: 这个方法非常重要是ActionServlet运行的核心方法. 我们进入这个方法: 再继续进入: 我们赫然发现了这样一个方法就是processPath方法,这个方法就是截取字符串的方法.这个方法的源代码如下: /** * <p>Identify and ret

  • Struts1简介和入门_动力节点Java学院整理

    本文为大家分享了Struts1简介和入门的学习资料,供大家参考,具体内容如下 1. 框架 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法.也就是说框架是一个半成品的应用程序. 我们所面对的应用程序一般都是分为两部分,一部分是业务相关的组件部分,另一部分是和业务无关的组件部分.而我们知道和业务相关的组件部分的重用性是非常低的,这也是显而易见的事情:而和业务无关的组件部分,如验证.异常.程序流程控制等等服务组件的复用性是非常高的.所以当人们在不同的应

  • struts1之简单mvc示例_动力节点Java学院整理

    先看MVC模式流程图(其实MVC设计模式就是java中的model2.): 就像图上所标识的C层主要是Servlet层控制页面跳转,M层就是具体的业务处理逻辑,而JSP就是所谓的V层.MVC是有别于我们所说的三层,我们平常所说的三层是UI层.BLL层.DAL层,具体的区别如图: 从图上能看出来,JSP和Servlet构成了UI层,而Model层分成了BLL层和DAL层(也就是业务逻辑和数据持久层). 从理论上认清了MVC设计模式之后,下面开始动手敲一个MVC设计模式示例代码: JSP索引页面in

  • struts1之ActionServlet详解_动力节点Java学院整理

    在web.xml中我们除了配置ActionServlet还配置了一些初始化参数信息,首先我们看第一个config参数,这里配置的是/WEB-INF/struts-config.xml,因为要下面传递一个这样一个配置信息,这个xml文件名是struts1标准的名字,所以这里这个初始化信息完全可以删除,如果不用这个标准名称这里就必须要在这里配置.现在我们配置的是标准名字,所以我们可以删除,这是为什么呢?这里要看ActionServlet源代码才可以. 从图片上我们能看到ActionServlet中已

  • Struts1教程之ActionMapping_动力节点Java学院整理

    首先断点走出了processpath方法, 这个方法是用来截取字符串的,今天我们来看怎样获得ActionMapping的方法---processMapping. 在此之前简单说一下ActionMapping,它的源代码中可以看出,其中最重要的属性和我们的mvc小实例中的ActionMapping类似,都是有path.type还有forwardMap,主要是对应的struts-config配置文件而来,这个就是保存这个配置文件的信息到内存中. 具体的mvc小实例的ActionMapping代码如下

  • mybatis教程之resultmap_动力节点Java学院整理

    SQL 映射XML 文件是所有sql语句放置的地方.需要定义一个workspace,一般定义为对应的接口类的路径.写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如: <mappers> <mapper resource="com/bjpowernode/manager/data/mappers/UserMapper.xml" /> <mapper resource="com/bjpowernode/manage

  • Java线程之join_动力节点Java学院整理

    join()介绍 join() 定义在Thread.java中. join() 的作用:让"主线程"等待"子线程"结束之后才能继续运行.这句话可能有点晦涩,我们还是通过例子去理解: // 主线程 public class Father extends Thread { public void run() { Son s = new Son(); s.start(); s.join(); ... } } // 子线程 public class Son extends

  • Java异常继承结构解析_动力节点Java学院整理

    Java异常类层次结构图: 异常的英文单词是exception,字面翻译就是"意外.例外"的意思,也就是非正常情况.事实上,异常本质上是程序上的错误,包括程序逻辑错误和系统错误.比如使用空的引用.数组下标越界.内存溢出错误等,这些都是意外的情况,背离我们程序本身的意图.错误在我们编写程序的过程中会经常发生,包括编译期间和运行期间的错误,在编译期间出现的错误有编译器帮助我们一起修正,然而运行期间的错误便不是编译器力所能及了,并且运行期间的错误往往是难以预料的.假若程序在运行期间出现了错误

  • Nginx简介_动力节点Java学院整理

    1.什么是Nginx Nginx来自俄罗斯的Igor Sysoev在为Rambler Media(http://www.rambler.ru/)工作期间,使用C语言开发了Nginx.Nginx作为Web服务器,一直为俄罗斯著名的门户网站Rambler Media提供着出色.稳定的服务. Igor Sysoev将Nginx的代码开源,并且赋予其最自由的2-clause BSD-like license许可证.由于Nginx使用基于事件驱动的架构能够并发处理百万级别的TCP连接,高度模块化的设计和自

  • web压力测试工具_动力节点Java 学院整理

    0. Grinder –  Grinder是一个开源的JVM负载测试框架,它通过很多负载注射器来为分布式测试提供了便利. 支持用于执行测试脚本的Jython脚本引擎HTTP测试可通过HTTP代理进行管理.根据项目网站的说法,Grinder的 主要目标用户是"理解他们所测代码的人--Grinder不仅仅是带有一组相关响应时间的'黑盒'测试.由于测试过程可以进行编码--而不是简单地脚本 化,所以程序员能测试应用中内部的各个层次,而不仅仅是通过用户界面测试响应时间. 1. Pylot -Pylot 是

  • 深入理解Java中的final关键字_动力节点Java学院整理

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使用final关键字的实例.final经常和static一起使用来声明常量,你也会看到final是如何改善应用性能的. final关键字的含义? final在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如

  • Java线程安全的常用类_动力节点Java学院整理

    线程安全类 在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的.在jdk1.2之后,就出现许许多多非线程安全的类. 下面是这些线程安全的同步的类: vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用.在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的. statck:堆栈类,先进后出 hashtable:就比hashmap多了个线程安全 除了这些之外,其他的集合大都是非线程安全的类和接口. 线程安全的类其方法是同步

  • Java中HashSet和HashMap的区别_动力节点Java学院整理

    什么是HashSet? HashSet实现了Set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象.如果我们没有重写这两个方法,将会使用这个方法的默认实现.. public boolean add(Object o)方法用来在Set中添加元素,当元素值重复时则会立即返回false,如果成功添加的话会返回true. 什

  • 十大常见Java String问题_动力节点Java学院整理

    本文介绍Java中关于String最常见的10个问题: 1. 字符串比较,使用 "==" 还是 equals() ? 简单来说, "==" 判断两个引用的是不是同一个内存地址(同一个物理对象). 而 equals 判断两个字符串的值是否相等. 除非你想判断两个string引用是否同一个对象,否则应该总是使用 equals()方法. 如果你了解 字符串的驻留 ( String Interning ) 则会更好地理解这个问题 2. 对于敏感信息,为何使用char[]要比

随机推荐