`
longgangbai
  • 浏览: 7341055 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

struts2.0学习总结

阅读更多

1:在action中定义的变量,在jsp页面中显示用:<s:property value="变量名" />

2:在页面中实现自动增加的序号用iterator的statuts的index属性 eg:

<s:iterator value="#request.inOutAccountList" id="data" status="listStat">

<s:property value="#listStat.index+1"/>

</s:iterator>

3:在action类中取得request和session对象的方法

Map session = ActionContext.getContext().getSession();
HttpServletRequest request = ServletActionContext.getRequest ();

设置它们的值的方法

session.put("operation", "add");
request.setAttribute("name", name);

页面中取得它们的值:

<s:property value="#session.operation"/>
<s:property value="#request.name"/>

4:页面中奇偶行样式不一样的控制方法:

<tr class="<s:if test='#listStat.odd == true '>tableStyle-tr1</s:if><s:else>tableStyle-tr2</s:else>" >

5:单选框和复选框的使用方法

1):可以设置默认选中值,注意list的值的设置,通过这种方式使key和value不一样,这种方法比较常用(checkboxlist or radio)

<s:radio name="uncarInsPolicy.policyStateCode"
list="#{'5':'通过' , '2':'不通过'}"
listKey="key"
listValue="value"
value='5'
/>

2):这里的key和value的值是一样的(checkboxlist or radio)

<s:checkboxlist
list="{'Red', 'Blue', 'Green'}"
name="favoriteColor"/>

6:struts2 中的标签会生成类似由<tr><td></td></tr>构成的字串(具体什么标签生成什么,可以查看生成后的页面的源代码)如果不限制这些多余代码的生成,页面将变得无法控制,所以一般我们是不希望它生成多余的代码的,具体的设置方法如果,在struts.xml中统一配置
<constant name="struts.ui.theme" value="simple"/>加上该句即可
也可以通过在页面中将tag的theme属性设为"simple"取消其默认的表格布局
不过最好是:自定义一个theme,并将其设为默认应用到整个站点,如此一来就可以得到统一的站点风格

7:jsp页面中格式化日期的方法

<s:date name="unCarInsModificationInfo.createTime" format="yyyy-MM-dd" nice="false"/>这样就可以将日期格式化为yyyy-MM-dd的形式

8:默认情况下,当请求action发生时,Struts运行时(Runtime)根据struts.xml里的Action映射集(Mapping),实例化action对应的类,并调用其execute方法。当然,我们可以通过以下两种方法改变这种默认调用

1)在classes/sturts.xml中新建Action,并指明其调用的方法
比如想调用action类中的

public String aliasAction() {
message ="自定义Action调用方法";
return SUCCESS;
}
则在classes/sturts.xml中加入下面代码:
<action name="AliasHelloWorld" class="tutorial.HelloWorld" method="aliasAction">
<result>/HelloWorld.jsp</result>
</action>
既可用action名调用该方法了

2)(比较常用)

访问Action时,在Action名后加上“!xxx”(xxx为方法名)。

9:Struts 2.0有两个配置文件,struts.xml和struts.properties都是放在WEB-INF/classes/下。
struts.xml用于应用程序相关的配置
struts.properties用于Struts 2.0的运行时(Runtime)的配置

10:在action类中取得web下某一文件夹物理路径(绝对路径)的方法
filePath = ServletActionContext.getServletContext().getRealPath("/upLoadFiles")

11:要想返回的页面不是一个直接JSP页面而是要先通过返回action中的方法读取相应的数据再返回到jsp页面,有两种方法

1)在struts.xml中这么设置

<result name="list" type="redirect-action">sysmanage/UserBaseInfoAction!findUserBaseInfo.action</result>

2)在action中返回时直接调用这个方法即可

return findList();

12:设置checkboxlist中默认值的方法

<s:checkboxlist name="skills1"
="Skills 1"
list="{ 'Java', '.Net', 'RoR', 'PHP' }"
value="{ 'Java', '.Net' }" />
<s:checkboxlist name="skills2"
label="Skills 2"
list="#{ 1:'Java', 2: '.Net', 3: 'RoR', 4: 'PHP' }"
listKey="key"
listValue="value"
value="{ 1, 2, 3 }"/>

13:二级级连下拉框

<s:set name="foobar"
value="#{'Java': {'Spring', 'Hibernate', 'Struts 2'}, '.Net': {'Linq', ' ASP.NET 2.0'}, 'Database': {'Oracle', 'SQL Server', 'DB2', 'MySQL'}}" />
<s:doubleselect list="#foobar.keySet()"
doubleName="technology"
doubleList="#foobar[top]"
label="Technology" />

在Struts1.*中,要想访问request、response以及session等Servlet对象是很方便的,因为它们一直是作为形参在各个方法之间进行传递的,而在Struts2中我们就很难看到它们的芳踪了,因为我们获得表单中的值都是通过预先设置好了的get方法来得到的,那么如果有些参数我们必须通过request.getParametre或者session.getAttribute来得到,那么应该怎么做呢?按照Max的教程上的说法,可以分为两种:IoC方式和非IoC方式,如何理解这两种方式的区别呢?IoC是Spring里面的特征之一,字面意思是反转控制,说白了就是依赖注入,比方说类A依赖类B,那么就主动的给A注入一个类B的对象,下面看一下这两种方法的具体实现。

1.非Ioc方式

这种方式主要是利用了com.opensymphony.xwork2.ActionContext类以及org.apache.struts2.ServletActionContext类,具体的方法如下所示。

获得request对象:

A.HttpServletRequest request = ServletActionContext.getRequest ();

B.ActionContext ct= ActionContext.getContext()

   HttpServletRequest request=

(HttpServletRequest)ct.get(ServletActionContext.HTTP_REQUEST);

获得session对象:

在Struts2中底层的session都被封装成了Map类型,我们称之为SessionMap,而平常我们所说的session则是指HttpSession对象,具体的获得方法如下所示。

A.Map session=ActionContext.getSession();

B.Map session=(Map)ActionContext.getContext().get(ActionContext.SESSION);

得到这个SessionMap之后我们就可以对session进行读写了,如果我们想得到原始的HttpSession可以首先得到HttpServletRequest对象,然后通过request.getSession()来取得原始的HttpSession对象。一般情况下SessionMap已经可以完成所有的工作,我们不必再去碰底层的session了。

2.IoC方式

这种方式相对来说变化就比较少了,具体流程如下所示。

获得request对象:

第一步:让action实现ServletRequestAware接口

第二步:在action中声明一个HttpServletRequest类型的实例变量

第三步:在action中实现ServletRequestAware接口的setServletRequest方法,实现方式很简单,如下所示。

         private HttpServletRequest request;

publicvoid setServletRequest(HttpServletRequest request) {

            this.request = request;

    }

获得Session对象(注意,此时的session是SessionMap类型):

第一步:让action实现SessionAware接口

第二步:在action中声明一个HttpServletRequest类型的实例变量

第三步:在action中实现SessionAware接口的setSession方法,实现方式很简单,如下所示。

 

 

struts2中的 ThreadLocal模式

设计模式(Design pattern)是经过程序员反复实践后形成的一套代码设计经验的总结。设计模式随着编程语言的发展,也由最初的“编程惯例”逐步发展成为被反复使用、并为绝大多数程序员所知晓的、完善的理论体系。我们使用设计模式(Design pattern)的初衷,是使代码的重用度提高、让代码能够更容易被别人理解以及保证代码的可靠性。毫无疑问,在程序中使用设计模式无论是对于程序员自身还是对于应用程序都是双赢的结果。正确地使用设计模式,能够使我们编程真正实现工程化和规范化,并且在一定程度上指导着框架的设计和实现。

在深入探讨Struts2所依赖的核心技术之前,我们将首先带领读者领略一下在整个Struts2框架之中所使用到的一些最常用的设计模式。理解这些设计模式的运用场景和内部机理,也将为日后我们对这些核心技术的分析打下坚实的基础。

4.1 ThreadLocal模式

ThreadLocal模式,严格意义上来说并不能称之为一种设计模式,因为它只是一个用来解决多线程程序中数据共享问题的一个解决方案。尽管如此,ThreadLocal模式却贯穿了整个Struts2和XWork框架,成为Struts2框架进行“解耦”设计的核心依赖技术。那么,为什么要在Struts2中引入ThreadLocal模式呢?这不得不从Web开发中的线程安全问题谈起。

4.1.1线程安全问题的由来

在传统的Web开发中,我们处理Http请求最常用的方式是通过实现Servlet对象来进行Http请求的响应。Servlet是J2EE的重要标准之一,规定了Java如何响应Http请求的规范。通过HttpServletRequest和HttpServletResponse对象,我们能够轻松地与Web容器交互。

当Web容器收到一个Http请求时,Web容器中的一个主调度线程会从事先定义好的线程池中分配一个当前工作线程,将请求分配给当前的工作线程,由该线程来执行对应的Servlet对象中的service方法。如果这个工作线程正在执行的时候,Web容器收到另外一个请求,主调度线程会同样从线程池中选择另一个工作线程来服务新的请求。Web容器本身并不关心这个新的请求是否访问的是同一个Servlet实例。因此,我们可以得出一个结论:对于同一个Servlet对象的多个请求,Servlet的service方法将在一个多线程的环境中并发执行。

所以,Web容器默认采用单实例(单Servlet实例)多线程的方式来处理Http请求。这种处理方式能够减少新建Servlet实例的开销,从而缩短了对Http请求的响应时间。但是,这样的处理方式会导致变量访问的线程安全问题。也就是说,Servlet对象并不是一个线程安全的对象。下面的测试代码将证实这一点:

public class ThreadSafeTestServlet extends HttpServlet  {  
  // 定义一个实例变量,并非一个线程安全的变量  
  private int counter = 0;  
  
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        doPost(req, resp);  
  }  
	  
      public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
	  // 输出当前Servlet的信息以及当前线程的信息
       System.out.println(this + ":" + Thread.currentThread());  
	  // 循环,并增加实例变量counter的值
	  for (int i = 0; i < 5; i++) {  
	       System.out.println("Counter = " + counter);  
	       try {  
	           Thread.sleep((long) Math.random() * 1000);  
	           counter++;  
	       } catch (InterruptedException exc) {  
	       }  
	  }  
   }  
}  



这里参阅了网络上一段著名的对Servlet线程安全性进行测试的代码(http://zwchen.iteye.com/blog/91088)。运行之后,我们可以看一下这个例子的输出:

sample.SimpleServlet@11e1bbf:Thread[http-8081-Processor23,5,main] 
Counter = 60 
Counter = 61 
Counter = 62 
Counter = 65 
Counter = 68 
Counter = 71 
Counter = 74 
Counter = 77 
Counter = 80 
Counter = 83 

sample.SimpleServlet@11e1bbf:Thread[http-8081-Processor22,5,main] 
Counter = 61 
Counter = 63 
Counter = 66 
Counter = 69 
Counter = 72 
Counter = 75 
Counter = 78 
Counter = 81 
Counter = 84 
Counter = 87 

sample.SimpleServlet@11e1bbf:Thread[http-8081-Processor24,5,main] 
Counter = 61 
Counter = 64 
Counter = 67 
Counter = 70 
Counter = 73 
Counter = 76 
Counter = 79 
Counter = 82 
Counter = 85 
Counter = 88



通过上面的输出,我们可以得出以下三个Servlet对象的运行特性:

1. Servlet对象是一个无状态的单例对象(Singleton),因为我们看到多次请求的this指针所打印出来的hashcode值都相同

2. Servlet在不同的线程(线程池)中运行,如http-8081-Processor22和http-8081-Processor23等输出值可以明显区分出不同的线程执行了同一段Servlet逻辑代码。

3. Counter变量在不同的线程中共享,而且它的值被不同的线程修改,输出时已经不是顺序输出。也就是说,其他的线程会篡改当前线程中实例变量的值,针对这些对象的访问不是线程安全的。


【有关线程安全的概念范畴】

谈到线程安全,对于许多初学者来说很容易引起概念上的混淆。线程安全,指的是在多线程环境下,一个类在执行某个方法时,对类的内部实例变量的访问安全与否。因此,对于下面列出来的2类变量,不存在任何线程安全的说法:

1)方法签名中的任何参数变量。
2)处于方法内部的局部变量。

任何针对上述形式的变量的访问都是线程安全的,因为它们都处于方法体的内部,由当前的执行线程独自管理。



这就是线程安全问题的由来:在传统的基于Servlet的开发模式中,Servlet对象内部的实例变量不是线程安全的。在多线程环境中,这些变量的访问需要通过特殊的手段进行访问控制。

解决线程安全访问的方法很多,比较容易想到的一种方案是使用同步机制,但是出于对Web应用效率的考虑,这种机制在Web开发中的可行性很低,也违背了Servlet的设计初衷。因此,我们需要另辟蹊径来解决这一困扰我们的问题。

4.1.2 ThreadLocal模式的实现机理

在JDK的早期版本中,提供了一种解决多线程并发问题的方案: java.lang.ThreadLocal类。ThreadLocal类在维护变量时,实际使用了当前线程(Thread)中的一个叫做ThreadLocalMap的独立副本,每个线程可以独立修改属于自己的副本而不会互相影响,从而隔离了线程和线程,避免了线程访问实例变量发生冲突的问题。

ThreadLocal本身并不是一个线程,而是通过操作当前线程(Thread)中的一个内部变量来达到与其他线程隔离的目的。之所以取名为ThreadLocal,所期望表达的含义是其操作的对象是线程(Thread)的一个本地变量。如果我们看一下Thread的源码实现,就会发现这一变量,如代码清单4-2所示:

public class Thread implements Runnable {
 // 这里省略了许多其他的代码
ThreadLocal.ThreadLocalMap threadLocals = null;
}



这是JDK中Thread源码的一部分,从中我们可以看出ThreadLocalMap跟随着当前的线程而存在。不同的线程Thread,拥有不同的ThreadLocalMap的本地实例变量,这也就是“副本”的含义。接下来我们再来看看ThreadLocal.ThreadLocalMap是如何定义的,以及ThreadLocal如何来操作它,如代码清单4-3所示:

public class ThreadLocal<T> {

// 这里省略了许多其他代码

// 将value的值保存于当前线程的本地变量中
public void set(T value) {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 调用getMap方法获得当前线程中的本地变量ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    // 如果ThreadLocalMap已存在,直接使用
    if (map != null)
         // 以当前的ThreadLocal的实例作为key,存储于当前线程的
         // ThreadLocalMap中,如果当前线程中被定义了多个不同的ThreadLocal
         // 的实例,则它们会作为不同key进行存储而不会互相干扰
         map.set(this, value);
    else
         // ThreadLocalMap不存在,则为当前线程创建一个新的
         createMap(t, value);
}

 // 获取当前线程中以当前ThreadLocal实例为key的变量值
public T get() {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 获取当前线程中的ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        // 获取当前线程中以当前ThreadLocal实例为key的变量值
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null)
            return (T)e.value;
    }
    // 当map不存在时,设置初始值
    return setInitialValue();
}

// 从当前线程中获取与之对应的ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

 // 创建当前线程中的ThreadLocalMap
void createMap(Thread t, T firstValue) {
    // 调用构造函数生成当前线程中的ThreadLocalMap
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

// ThreadLoaclMap的定义
static class ThreadLocalMap {
    // 这里省略了许多代码
}
}



从上述代码中,我们看到了ThreadLocal类的大致结构和进行ThreadLocalMap的操作。我们可以从中得出以下的结论:

1. ThreadLocalMap变量属于线程(Thread)的内部属性,不同的线程(Thread)拥有完全不同的ThreadLocalMap变量。

2. 线程(Thread)中的ThreadLocalMap变量的值是在ThreadLocal对象进行set或者get操作时创建的。

3. 在创建ThreadLocalMap之前,会首先检查当前线程(Thread)中的ThreadLocalMap变量是否已经存在,如果不存在则创建一个;如果已经存在,则使用当前线程(Thread)已创建的ThreadLocalMap。

4. 使用当前线程(Thread)的ThreadLocalMap的关键在于使用当前的ThreadLocal的实例作为key进行存储。


ThreadLocal模式,至少从两个方面完成了数据访问隔离,有了横向和纵向的两种不同的隔离方式,ThreadLocal模式就能真正地做到线程安全:

纵向隔离 —— 线程(Thread)与线程(Thread)之间的数据访问隔离。这一点由线程(Thread)的数据结构保证。因为每个线程(Thread)在进行对象访问时,访问的都是各自线程自己的ThreadLocalMap。

横向隔离 —— 同一个线程中,不同的ThreadLocal实例操作的对象之间的相互隔离。这一点由ThreadLocalMap在存储时,采用当前ThreadLocal的实例作为key来保证。

ThreadLocal模式并不是什么高深的学问,它甚至从JDK1.2开始就存在于Java世界中。由此可见,我们掌握一种知识的最终目的是熟练而合理地运用它。

【深入比较ThreadLocal模式与synchronized关键字】

ThreadLocal模式与synchronized关键字都是用于处理多线程并发访问变量的问题。只是两者处理问题的角度和思路不同。

1)ThreadLocal是一个Java类,通过对当前线程(Thread)中的局部变量的操作来解决不同线程的变量访问的冲突问题。所以,ThreadLocal提供了线程安全的共享对象机制,每个线程(Thread)都拥有其副本。

2)Java中的synchronized是一个保留字,它依靠JVM的锁机制来实现临界区的函数或者变量在访问中的原子性。在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。此时,被用作“锁机制”的变量是多个线程共享的。

同步机制采用了“以时间换空间”的方式,提供一份变量,让不同的线程排队访问。而ThreadLocal采用了“以空间换时间”的方式,为每一个线程都提供了一份变量的副本,从而实现同时访问而互不影响。


4.1.3 ThreadLocal模式的应用场景

在分析了ThreadLocal的源码之后,我们来看看ThreadLocal模式最合适的业务场景。在一个完整的“请求-响应”过程中,主线程的执行过程总是贯穿始终。当这个主线程的执行过程中被加入了ThreadLocal的读写时,会对整个过程产生怎样的影响呢?我们根据之前源码分析的结果,并结合分层开发模式,把整个流程画下来,如图4-1所示:



从上面图中我们可以看到,由于ThreadLocal所操作的是维持于整个Thread生命周期的副本(ThreadLocalMap),所以无论在J2EE程序程序的哪个层次(表示层、业务逻辑层或者持久层),只要在一个Thread的生命周期之内,存储于ThreadLocalMap中的对象都是线程安全的(因为ThreadLocalMap本身仅仅隶属于当前的执行线程,是执行线程内部的一个属性变量。我们用图中的阴影部分来表示这个变量的存储空间)。而这一点,正是被我们用于来解决多线程环境中的变量共享问题的核心技术。ThreadLocal的这一特性也使其能够被广泛地应用于J2EE开发中的许多业务场景。

【数据共享 OR 数据传递?】

ThreadLocal模式由于利用了Java自身的语法特性而显得异常简单和便利,因而被广泛应用于J2EE开发,尤其是应对跨层次的资源共享,例如在Spring中,就有使用ThreadLocal模式来管理数据库连接或者Hibernate的Session的范例。
在一些比较著名的论坛中,有着很多关于使用ThreadLocal模式来做数据传递的讨论。事实上,这是对ThreadLocal模式的一个极大的误解。读者需要注意的是,ThreadLocal模式解决的是同一线程中隶属于不同开发层次的数据共享问题,而不是在不同的开发层次中进行数据传递。

1)ThreadLocal模式的核心在于实现一个共享环境(类的内部封装了ThreadLocal的静态实例)。所以,在操作ThreadLocal时,这一共享环境会跨越多个开发层次而随处存在。

2)随处存在的共享环境造成了所有的开发层次的共同依赖,从而使得所有的开发层次都耦合在了一起,从而变得无法独立测试。

3)数据传递应该通过接口函数的签名显式声明,这样才能够从接口声明中表达接口所表达的真正含义。ThreadLocal模式位于实现的内部,从而使得接口与接口之间无法达成一致的声明契约。


Struts2的解耦合的设计理念使得Struts2的MVC实现成为了使用ThreadLocal模式的天然场所。在第三章中,我们已经介绍了一些基本概念,Struts2通过引入XWork框架,将整个Http请求的过程拆分成为与Web容器有关和与Web容器无关的两个执行阶段。而这两个阶段的数据交互就是通过ThreadLocal模式中的线程共享副本安全地进行。在其中,我们没有看到数据传递,存在的只是整个执行线程的数据共享。

4.1.4 ThreadLocal模式的核心元素

仔细分析上一节的示意图(图4-1),我们可以发现,要完成ThreadLocal模式,其中最关键的地方就是创建一个任何地方都可以访问到的ThreadLocal实例(也就是执行示意图中的菱形部分)。而这一点,我们可以通过类的静态实例变量来实现,这个用于承载静态实例变量的类就被视作是一个共享环境。我们来看一个例子,如代码清单4-4所示:

public class Counter {
	
// 新建一个静态的ThreadLocal变量,并通过get方法将其变为一个可访问的对象
    private static ThreadLocal<Integer> counterContext = new ThreadLocal<Integer>() {
	 protected synchronized Integer initialValue() {
	         return 10;
	 }
};
	
// 通过静态的get方法访问ThreadLocal中存储的值
public static Integer get() {
	return counterContext.get();
}
	
// 通过静态的set方法将变量值设置到ThreadLocal中
public static void set(Integer value) {
	counterContext.set(value);
}
	
// 封装业务逻辑,操作存储于ThreadLocal中的变量
public static Integer getNextCounter() {
    counterContext.set(counterContext.get() + 1);
    return counterContext.get();
}
    
}



在这个Counter类中,我们实现了一个静态的ThreadLocal变量,并通过get方法将ThreadLocal中存储的值暴露出来。我们还封装了一个带有业务逻辑的方法getNextCounter,操作ThreadLocal中的值,将其加1,并返回计算后的值。

此时,Counter类就变成了一个数据共享环境,我们也拥有了实现ThreadLocal模式的关键要素。有了它,我们来编写一个简单的测试,如代码清单4-5所示:

public class ThreadLocalTest extends Thread {
      
public void run() {
for(int i = 0; i < 3; i++){
    System.out.println("Thread[" + Thread.currentThread().getName() + "],counter=" + Counter.getNextCounter());
}
}
}



这是一个简单的线程类,循环输出当前线程的名称和getNextCounter的结果,由于getNextCounter中的逻辑所操作的是ThreadLocal中的变量,所以无论同时有多少个线程在运行,返回的值将仅与当前线程的变量值有关,也就是说,在同一个线程中,变量值会被连续累加。这一点可以通过如下的测试代码证实:

public class Test {

public static void main(String[] args) throws Exception {
		
	ThreadLocalTest testThread1 = new ThreadLocalTest();
	ThreadLocalTest testThread2 = new ThreadLocalTest();
	ThreadLocalTest testThread3 = new ThreadLocalTest();
		
	testThread1.start();
	testThread2.start();
	testThread3.start();
		
}
}



我们来运行一下上面的代码,并看看输出结果:

Thread[Thread-2],counter=11
Thread[Thread-2],counter=12
Thread[Thread-2],counter=13
Thread[Thread-0],counter=11
Thread[Thread-0],counter=12
Thread[Thread-0],counter=13
Thread[Thread-1],counter=11
Thread[Thread-1],counter=12
Thread[Thread-1],counter=13



上面的输出结果也证实了,counter的值在多线程环境中的访问是线程安全的。从对例子的分析中我们可以再次体会到,ThreadLocal模式最合适的使用场景:在同一个线程(Thread)的不同开发层次中共享数据。

从上面的例子中,我们可以简单总结出实现ThreadLocal模式的两个主要步骤:

1. 建立一个类,并在其中封装一个静态的ThreadLocal变量,使其成为一个共享数据环境。

2. 在类中实现访问静态ThreadLocal变量的静态方法(设值和取值)。


建立在ThreadLocal模式的实现步骤之上,ThreadLocal的使用则更加简单。在线程执行的任何地方,我们都可以通过访问共享数据类中所提供的ThreadLocal变量的设值和取值方法安全地获得当前线程中安全的变量值。

这两个步骤,我们之后会在Struts2的实现中多次提及,读者只要能充分理解ThreadLocal处理多线程访问的基本原理,就能对Struts2的数据访问和数据共享的设计有一个整体的认识。

讲到这里,我们回过头来看看ThreadLocal模式的引入,到底对我们的编程模型有什么重要的意义呢?

downpour 写道结论 使用ThreadLocal模式,可以使得数据在不同的编程层次得到有效地共享。

这一点,是由ThreadLocal模式的实现机理决定的。因为实现ThreadLocal模式的一个重要步骤,就是构建一个静态的共享存储空间。从而使得任何对象在任何时刻都可以安全地对数据进行访问。

downpour 写道结论 使用ThreadLocal模式,可以对执行逻辑与执行数据进行有效解耦。

这一点是ThreadLocal模式给我们带来的最为核心的一个影响。因为在一般情况下,Java对象之间的协作关系,主要通过参数和返回值来进行消息传递,这也是对象协作之间的一个重要依赖。而ThreadLocal模式彻底打破了这种依赖关系,通过线程安全的共享对象来进行数据共享,可以有效避免在编程层次之间形成数据依赖。这也成为了XWork事件处理体系设计的核心。

分享到:
评论

相关推荐

    Struts2.0学习Struts2.0文档

    ### Struts 2.0 学习指南与关键技术解析 #### 一、Struts 2.0 框架概述 Struts 2.0 是一个基于MVC(Model-View-Controller)设计模式的开源Web应用框架,它在Struts 1.x的基础上进行了大幅度的改进和完善。自推出...

    struts2.0学习笔记,代码整理

    总结,Struts2.0是一个强大且成熟的Web开发框架,它提供了完整的MVC实现,丰富的插件支持,以及灵活的配置选项。通过深入学习和实践,开发者能够更好地理解和利用这个框架,构建高效、可维护的Java Web应用。

    struts 2.0 详细配置

    2. **为什么学习 Struts 2?** - 在现代 Web 开发中,Struts 2 框架提供了一种高效且模块化的应用构建方式。 - 它支持 MVC 设计模式,能够帮助开发者更好地组织代码结构。 - MVC 模式下: - 控制器(Controller)...

    Struts2.0大结合

    总结,学习Struts2.0不仅需要掌握其基本概念和配置,还需要理解拦截器机制,熟练使用Struts2.0提供的标签库,以及如何与其他框架如Spring进行集成。通过不断地实践和项目经验积累,才能真正掌握这个强大的Web开发...

    struts2.0中文教程

    总结来说,"struts2.0中文教程"涵盖了Struts2.0的各个方面,包括Action、拦截器、OGNL、视图技术、控制器、异常处理和插件集成等,是学习和掌握Struts2.0框架的重要参考资料。通过深入学习,开发者可以更好地利用...

    Struts2.0培训笔记

    通过深入学习和实践Struts2.0,开发者可以提高开发效率,创建出结构清晰、易于维护的Web应用。在实际项目中,理解并熟练运用MVC模式、拦截器、Action与结果、配置方式、异常处理以及国际化等核心概念,将对提升项目...

    struts2.0标签使用

    在探讨Struts2.0标签库的使用时,我们首先需要了解Struts2.0框架的基本概念及其在MVC架构中的角色。Struts2.0是基于Java的一...对于想要深入学习Struts2.0框架的开发者来说,熟练掌握其标签库的使用是非常重要的一步。

    struts2.0 spring2.0 hibernate3.0整合开发快速入门-3

    通过以上内容的学习,我们可以了解到Struts2.0、Spring2.0与Hibernate3.0整合开发的基本概念和步骤。这三个框架相互配合,可以极大地提高Java Web应用的开发效率和维护性。在实际项目中,还需要结合具体的业务需求和...

    struts2.0的总结

    ### Struts2.0核心知识点总结 #### 一、简介 Struts2 是一款基于 Java 的开源 MVC(Model-View-Controller)框架,用于构建动态的 Web 应用程序。相较于 Struts1.x 版本,Struts2 提供了更强大的功能与灵活性,它...

    struts2.0jar包

    Struts2.0 jar包是Java Web开发中的一个重要组件,它是Apache Struts框架的一个特定版本。Struts2是一个基于MVC(Model-View...通过学习和掌握Struts2.0,开发者能够更好地理解和实践MVC模式,提高开发效率和代码质量。

    struts2.0培训机构-修订版+日常练习

    在这个“struts2.0培训机构-修订版+日常练习”资料包中,你将找到一系列与Struts2.0相关的学习资源,包括PPT和PDF文档,以及可能的代码示例或练习题。 1. **PPT讲解**:通常,PPT是讲师用来传授课程内容的主要工具...

    struts2.0学习资料

    总结,Struts2.0的学习涉及到了框架的基础配置、国际化、文件上传、拦截器、结果类型以及OGNL表达式的运用等多个方面。通过深入学习和实践,你将能够熟练地利用Struts2构建高效、可维护的Java Web应用。

    struts2.0教程

    总结,Struts2.0是一个强大且灵活的MVC框架,它的核心概念、新特性和丰富的插件库使其在企业级Web开发中广受欢迎。通过深入学习提供的教程和源码,开发者可以掌握Struts2.0的核心技术,从而提高开发效率和代码质量。

    Struts2.0中文教程

    总结来说,Struts2.0教程将引导你掌握这个框架的基本使用,包括但不限于标签的使用、EL表达式的理解、数据库操作的实现以及拦截器和异常处理的原理。通过学习,你可以快速构建出功能丰富的Java Web应用程序。

    网络商城j1051_struts2.0

    总结,网络商城“j1051_struts2.0”项目是Struts2.0框架的一个实例展示,通过该项目,开发者不仅可以掌握Struts2.0的基础知识,还能了解到如何将这些知识应用到实际的电商系统开发中。在实践中,不断探索和优化,将...

    struts2.0基础学习

    总结,Struts2.0作为Java Web开发的重要工具,其基础学习涵盖了MVC模式的理解、配置文件的编写、Action和拦截器的使用、数据绑定与校验、视图展示、国际化和主题设置等多个方面。通过深入学习和实践,开发者可以构建...

    struts2.0+freemarker实例.rar

    总结起来,Struts2.0和FreeMarker的结合使用,能帮助开发者构建清晰的MVC架构,提高代码的可读性和可维护性。通过学习和实践这样的实例,你可以更好地掌握这两个工具的用法,提升Java Web开发能力。

    搭建Struts2.0开发和运行环境

    ### 搭建Struts2.0开发和运行环境 #### 一、概述 本文将详细介绍如何搭建Struts2.0的开发与运行环境。Struts2是基于MVC架构的开源框架,广泛用于Java Web应用程序的开发。通过本指南,您将能够成功配置所需的工具与...

Global site tag (gtag.js) - Google Analytics