您的位置:首页 > 编程语言 > Java开发

Struts2原理及源码分析

2015-03-22 20:26 183 查看
struts介绍

strtus2是WebWork的升级版,是一个运行稳定、性能优异、设计成熟的web框架,而struts则实现了MVC思想中的controller模块,而控制器实际上是由两部分组成,即拦截所有用户的请求,处理请求的通用代码都是由核心控制器完成的。在struts框架下,用户请求不再向JSP页面发送,而是由控制器StrutsPrepareAndExceptionFilter来将请求forword到指定JSP页面生成响应。

struts原理流程

客户端初始化一个指向Servlet容器的请求

这个请求经过一个系列的过滤器

StrutsPrepareAndExcuteFilter被调用,它会询问ActionMapper来决定这个请求调用某个Action

ActionMapper决定调用那个action,FilterDispatcher把请求的处理交给ASctionProxy

ActionProxy通过调用Configuration Manager询问框架的配置文件,找到需要调用的Action类

创建ActionInvocation的实例

ActionInvocation实例使用命名模式来调用,在调用Acion的过程前后都会涉及到相关的拦截器(intercepter)的调用

一旦action执行完毕,ActionInvocation负责根据struts.xml的配置找到相应的返回对应的返回结果,这个结果是一个需要被表示的JSP

FilterDispatcher

struts的核心过滤器,负责处理最初的请求

四大责任:

执行action:判断是否需要执行action,需要执行则该action则应该放在核心过滤器的最前面

清空actionContext上下文:自动清理,确保没有内存泄露

服务静态的内容:加载常用的javascript文件

中断请求生命周期中的XWORKS拦截器

ActionMapper

用来负责在Http请求和action调用之间进行一个映射

为了帮助处理按钮和其他相关的需求,这个mapper(我们希望,其他ActionMapper也能这样)具有这样的功能:使用一些预定义的前缀命名一个按钮,这些按钮会引发执行行为.这四个前缀是:

Method 前缀- method:default

Action 前缀- action:dashboard

Redirect 前缀- redirect:cancel.jsp

Redirect-action 前缀- redirect-action:cancel

除了这四个前缀,这个mapper也明白 foo!bar的action命名方式,或者扩展方式(例如 foo!bar.action) ,或者前缀方式(例如 action:foo!bar).这个语法告诉mapper映射到名称为foo的action和对应的方法bar.

实现自己的ActionMapper,通过method参数将请求转发到具体的action,需继承DefaultActionMapper


ActionProxy&ActionInvocation

Action的一个代理,由ActionProxyFactory创建,它本身不包括Action实例,默认实现DefaultActionProxy是由ActionInvocation持有Action实例。ActionProxy作用是如何取得Action,无论是本地还是远程。而ActionInvocation的作用是如何执行Action,拦截器的功能就是在ActionInvocation中实现的。

ConfigurationProvider&Configuration

ConfigurationProvider就是Struts2中配置文件的解析器,Struts2中的配置文件主要是尤其实现类XmlConfigurationProvider及其子类StrutsXmlConfigurationProvider来解析。

trutsPrepareAndExecuteFilter中的方法:

void init(FilterConfig filterConfig) 继承自Filter,过滤器的初始化

doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 继承自Filter,执行过滤器

void destroy() 继承自Filter,用于资源释放

void postInit(Dispatcher dispatcher, FilterConfig filterConfig) Callback for post initialization(一个空的方法,用于方法回调初始化)

web容器一启动,就会初始化核心过滤器StrutsPrepareAndExecuteFilter,并执行初始化方法,初始化方法如下:

复制代码

1 public void init(FilterConfig filterConfig) throws ServletException {

2 InitOperations init = new InitOperations();

3 Dispatcher dispatcher = null;

4 try {

5 //封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中

6 FilterHostConfig config = new FilterHostConfig(filterConfig);

7 //初始化struts内部日志

8 init.initLogging(config);

9 //创建dispatcher ,并初始化

10 dispatcher = init.initDispatcher(config);

11 init.initStaticContentLoader(config, dispatcher);

12 //初始化类属性:prepare 、execute

13 prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);

14 execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);

15 this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);

16 //回调空的postInit方法

17 postInit(dispatcher, filterConfig);

18 } finally {

19 if (dispatcher != null) {

20 dispatcher.cleanUpAfterInit();

21 }

22 init.cleanup();

23 }

24 }

复制代码

关于封装filterConfig,首先看下FilterHostConfig ,源码如下:

复制代码

1 public class FilterHostConfig implements HostConfig {

2

3 private FilterConfig config;

4 //构造方法

5 public FilterHostConfig(FilterConfig config) {

6 this.config = config;

7 }

8 //根据init-param配置的param-name获取param-value的值

9 public String getInitParameter(String key) {

10 return config.getInitParameter(key);

11 }

12 //返回初始化参数名的迭代器

13 public Iterator getInitParameterNames() {

14 return MakeIterator.convert(config.getInitParameterNames());

15 }

16 //返回Servlet上下文

17 public ServletContext getServletContext() {

18 return config.getServletContext();

19 }

20 }

复制代码

  只有短短的几行代码,getInitParameterNames是这个类的核心,将Filter初始化参数名称有枚举类型转为Iterator。此类的主要作为是对filterConfig 封装。

  接下来,看下StrutsPrepareAndExecuteFilter中init方法中dispatcher = init.initDispatcher(config);这是初始化dispatcher的,是通过init对象的initDispatcher方法来初始化的,init是InitOperations类的对象,我们看看InitOperations中initDispatcher方法:

1 public Dispatcher initDispatcher( HostConfig filterConfig ) {

2 Dispatcher dispatcher = createDispatcher(filterConfig);

3 dispatcher.init();

4 return dispatcher;

5 }

  创建Dispatcher,会读取 filterConfig 中的配置信息,将配置信息解析出来,封装成为一个Map,然后根绝servlet上下文和参数Map构造Dispatcher :

复制代码

1 private Dispatcher createDispatcher( HostConfig filterConfig ) {

2 //存放参数的Map

3 Map
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: