前面说完了Spring、Hibernate,很自然今天轮到struts了。struts的核心原理就是通过拦截器来处理客户端的请求,经过拦截器一系列的处理后,再交给Action。下面先看看struts官方的工作原理图:

图1 struts原理图

简单分析一下:首先客户端发来HttpServletRequest请求,传递给FilerDispatcher(ActionMapper是访问静态资源(struts的jar文件等)时用的,平时很少用),然后FilerDispatcher会为我们创建一个ActionProxy,ActionProxy会通过ConfigurationManager获得struts.xml文件中的信息,ActionProxy拥有一个ActionInvocation实例,通过调用ActionInvocation的invoke()方法,来挨个处理Interceptor,最后处理Action,接着Result返回,再逆序经过Interceptor,最后得到HttpServletResponse返回给客户端。

如果不太明白呢,那就看看下面这张时序图,也许你就懂了:

图2 struts原理时序图

上面的时序图逻辑就比较清晰了,我就不过多解释了。看完struts的原理图,我们还是需要通过代码来进一步了解它具体是怎么实现的。首先,我们需要一个ActionInvocation:

package com.tgb.struts;
import java.util.ArrayList;
import java.util.List; public class ActionInvocation {
List<Interceptor> interceptors = new ArrayList<Interceptor>();
int index = -1;
Action a = new Action(); public ActionInvocation() {
this.interceptors.add(new FirstInterceptor());
this.interceptors.add(new SecondInterceptor());
} public void invoke() {
index ++;
if(index >= this.interceptors.size()) {
a.execute();
}else { this.interceptors.get(index).intercept(this);
}
}
}

我们实现的ActionInvocation是将Interceptor写在里面的,但实际上是通过反射加载的,原理同之前写的Spring与Hibernate的博客,相同的代码就不在这里占用篇幅了,也没啥意思。不知道怎么实现的朋友请查看前面几篇博客。

接下来是我们的Interceptor接口以及两个简单的实现:

package com.tgb.struts;

public interface Interceptor {
public void intercept(ActionInvocation invocation) ;
} package com.tgb.struts; public class FirstInterceptor implements Interceptor { public void intercept(ActionInvocation invocation) {
System.out.println("FirstInterceptor Begin...");
invocation.invoke();
System.out.println("FirstInterceptor End...");
} } package com.tgb.struts; public class SecondInterceptor implements Interceptor { public void intercept(ActionInvocation invocation) {
System.out.println("SecondInterceptor Begin...");
invocation.invoke();
System.out.println("SecondInterceptor End...");
} }

然后就是我们的Action:

package com.tgb.struts;

public class Action {
public void execute() {
System.out.println("Action Run...");
}
}

最后是我们的客户端调用:

package com.tgb.struts;

public class Client {
public static void main(String[] args) {
new ActionInvocation().invoke();
}
}

差点忘了,还有我们最后的执行结果:

FirstInterceptor Begin...
SecondInterceptor Begin...
Action Run...
SecondInterceptor End...
FirstInterceptor End...

通过上面的执行结果,我们可以很清楚的看到,请求来的时候会按照顺序被所有配置的拦截器拦截一遍,然后返回的时候会按照逆序再被拦截器拦截一遍。这跟数据结构中的“栈”非常类似(FIFO-先进先出),数据结构我不太懂,也许这样比喻有些不妥。各位根据自己的认识理解吧。

最近一直在研究这三大框架,折腾半天它们都离不开集合,离不开反射。其实它们道理都是想通的,搞懂一个,其他的也就很好懂了。等着吧,早晚咱们自己写一个更好用的。

菜鸟学SSH(十六)——Struts2内部是如何工作的的更多相关文章

  1. 最佳新秀SSH十六Struts2它是如何工作的内部

    前面说完了Spring.Hibernate,非常自然今天轮到struts了.struts的核心原理就是通过拦截器来处理client的请求,经过拦截器一系列的处理后,再交给Action.以下先看看str ...

  2. 菜鸟学SSH(六)——Spring事务管理

    Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作.今天一起学习一下Spring的事务管理.Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.Tran ...

  3. 二十六个月Android学习工作总结【转】

    原文:二十六个月Android学习工作总结 1.客户端的功能逻辑不难,UI界面也不难,但写UI花的时间是写功能逻辑的两倍.     2.写代码前的思考过程非常重要,即使在简单的功能,也需要在本子上把该 ...

  4. 菜鸟学SSH(三)——Struts2国际化自动检测浏览器语言版

    前几天发了一篇Struts国际化的博客——<菜鸟学习SSH(二)——Struts2国际化手动切换版>,有网友提了一个意见,见下图: 于是就有了下面修改的版本: web.xml <?x ...

  5. 菜鸟学SSH(十四)——Spring容器AOP的实现原理——动态代理

    之前写了一篇关于IOC的博客——<Spring容器IOC解析及简单实现>,今天再来聊聊AOP.大家都知道Spring的两大特性是IOC和AOP,换句话说,容器的两大特性就是IOC和AOP. ...

  6. 菜鸟学SSH(四)——Struts2拦截器

    什么是拦截器 拦截器(Interceptor)是Struts 2的一个强有力的工具,有许多功能都是构建于它之上,如国际化(前两篇博客介绍过).转换器,校验等. 拦截器是动态拦截Action调用的对象. ...

  7. 菜鸟学SSH(二)——Struts2国际化手动切换版

    国际化(internationalization,i18n)和本地化(localization,l10n)指让产品(出版物,软件,硬件等)能够适应非本地环境,特别是其他的语言和文化.程序在不修改内部代 ...

  8. 菜鸟学SSH(十八)——Hibernate动态模型+JRebel实现动态创建表

    项目用的是SSH基础框架,当中有一些信息非常相似,但又不尽同样.假设每个建一个实体的话,那样实体会太多.假设分组抽象,然后继承,又不是特别有规律.鉴于这样的情况.就打算让用户自己配置要加入的字段,然后 ...

  9. 菜鸟学SSH(十)——Hibernate核心接口

    在使用Hibernate的时候,我们通常都会用的Configuration.SessionFactory.Session.Transaction.Query和Criteria等接口.通过这些接口可以, ...

随机推荐

  1. Shell脚本学习之sed详解

    在编写shell脚本的过程中,我们经常需要使用sed流编辑器和awk对文本文件进行处理. 一.什么是sed? sed 是一种在线编辑器,它一次处理一行内容.sed是非交互式的编辑器.它不会修改文件,除 ...

  2. java非web应用修改 properties/xml配置文件后,无需重启应用即可生效---自动加载

    实现时主要使用Commons-Configuration.jar包,还需要commons-lang,disgestor,beanutils,collections等, package propFile ...

  3. Java概述与开发环境

    1.Java语言既是编译又是解释型的特点 Java没有设计成编译型语言,因为编译型语言效率高, 但可移植性差. Java也没有设计成纯解释型的语言, 因为解释型效率太低. 编译成class文件, 解释 ...

  4. hduoj1073--Online Judge

    做道题,并没有太多的技巧,关键在与对Accepted,presented error 和wa的判断,第一步如果两者完全一样,那么很定是AC了 ,否则如果去掉多余换行,空格,制表后还有不同说明是数据 不 ...

  5. keras中的loss、optimizer、metrics

    用keras搭好模型架构之后的下一步,就是执行编译操作.在编译时,经常需要指定三个参数 loss optimizer metrics 这三个参数有两类选择: 使用字符串 使用标识符,如keras.lo ...

  6. 给我一对公钥和私钥,我就能破解此RSA

    RSA密码系统如果暴露了一套公钥和私钥,那么这套密码系统就全部失效了.因为根据公钥和私钥可以完成大整数的分解.暴露了两个质数. 记公钥为e,私钥为d,因为ed%phi=1,所以就得到了一个k=ed-1 ...

  7. Python学习笔记(八)—— 使用dict和set

    一.dict 1.定义: Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度 2.优势: di ...

  8. HDU 4632 Palindrome subsequence (区间DP)

    Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/ ...

  9. 微信支付中的jsapi返回提示信息

    jsapi中跳转到微信支付中触发的方法是js中的getBrandWCPayRequest方法. 改方法中的返回结果msg提示信息如下: err_msg:get_brand_wcpay_request: ...

  10. [bug]WCF 内存入口检查失败 Memory gates checking failed

    bug描述 异常信息:内存入口检查失败,因为可用内存(xxx 字节)少于总内存的 xx%.因此,该服务不可用于传入的请求.若要解决此问题,请减少计算机上的负载,或调整 serviceHostingEn ...