服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|JavaScript|

服务器之家 - 编程语言 - JAVA教程 - Struts1教程之ActionMapping_动力节点Java学院整理

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

2020-12-26 14:28lfsf802 JAVA教程

这篇文章主要介绍了Struts1教程之ActionMapping,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

首先断点走出了processpath方法,

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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更加直接)的代码如下:

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

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

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

从这两部分代码来看,更加印证了我在开篇写的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方法上设置断点。

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

进入源代码中:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
   * <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。具体代码是:

?
1
2
actionmapping mapping =(actionmapping)
   moduleconfig.findactionconfig(path);

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

?
1
2
3
4
if (mapping != null) {
      request.setattribute(globals.mapping_key, mapping);
      return (mapping);
    }

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 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方法的具体实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
 
   * <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:

?
1
2
3
4
5
6
7
8
9
10
11
// create (if necessary) a formbean to use
 
    actionform instance = requestutils.createactionform
 
      (request, mapping, moduleconfig, servlet);
 
    if (instance == null) {
 
      return (null);
 
    }

通过调用requestutils.createactionform的方法把actionmapping中的actionform字符串生成对象,并且返回。进入这段代码中:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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配置文件中,配置过这样一个标签信息:

?
1
2
3
4
5
<form-beans>
 
    <form-bean name="loginform" type=".struts.loginactionform"/>
 
  </form-beans>

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

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

?
1
2
3
4
5
6
7
8
9
10
11
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中。具体实现就是:

?
1
2
3
4
5
6
7
8
9
10
11
if ("request".equals(mapping.getscope())){
 
      request.setattribute(mapping.getattribute(), instance);
 
    } else {
 
      httpsession session =request.getsession();
 
      session.setattribute(mapping.getattribute(), instance);
 
    }

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

延伸 · 阅读

精彩推荐
  • JAVA教程java中的自增问题介绍

    java中的自增问题介绍

    下面小编就为大家带来一篇java中的自增问题介绍。小编觉得挺不错的,现在分享给大家。给大家一个参考。 ...

    jingxian2612020-04-12
  • JAVA教程java开发就业信息管理系统

    java开发就业信息管理系统

    这篇文章主要为大家详细介绍了java开发就业信息管理平台,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 ...

    wiseben3062020-05-20
  • JAVA教程JVM详解之汇编角度理解本地变量的生命周期

    JVM详解之汇编角度理解本地变量的生命周期

    这篇文章主要介绍了JVM详解之汇编角度理解本地变量的生命周期,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可...

    mrr4652020-07-29
  • JAVA教程java线程并发cyclicbarrier类使用示例

    java线程并发cyclicbarrier类使用示例

    CyclicBarrier类似于CountDownLatch也是个计数器,不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,当线程数达到了CyclicBarrier初始时规定的数...

    java技术网2742019-10-31
  • JAVA教程java解一个比较特殊的数组合并题

    java解一个比较特殊的数组合并题

    这篇文章主要介绍了java解一个比较特殊的数组合并题,需要的朋友可以参考下 ...

    Java教程网5532019-11-23
  • JAVA教程java基础知识I/O流使用详解

    java基础知识I/O流使用详解

    编程语言的I/O类库中常常使用流这个抽象的概念,它代表任何有能力产生数据的数据源对象或时有能力接收数据的接收端对象,本文为大家介绍Java中I/O系统...

    java技术网2952019-10-27
  • JAVA教程Springboot 实现数据库备份还原的方法

    Springboot 实现数据库备份还原的方法

    这篇文章主要介绍了Springboot 实现数据库备份还原的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考...

    Maolic3982020-09-21
  • JAVA教程IDEA配置java开发环境(maven、gradle、tomcat)

    IDEA配置java开发环境(maven、gradle、tomcat)

    这篇文章主要介绍了IDEA配置java开发环境(maven、gradle、tomcat),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    *大魔王*4782020-09-21