Struts2源码试读1-filter

一直没对struts好好研究过,最近拿出来好好看看。

首先,struts1和struts2还是有很大区别的,鉴于struts1的项目越来越少,就直接跳过。struts2是WebWork的升级版,不过与其这么说不如说struts2是webwork的再封装,让他“看上去”更像struts,但是骨子里却是webwork。

struts属于apache的开源项目,可以直接从http://struts.apache.org/上下载源码包,不过如果想了解更多包括WebWork的内容则需要进一步下载webword的源码包,地址为http://www.opensymphony.com/xwork/download.action。

这边不过多赘述struts2的每个包有什么作用了,从项目运行的开始一步步分析struts2是如何运行并得到结果的。

struts说白了也还是个web项目,所以没什么特别的东西。在我的理解,框架只是让我们更加方便、快捷的开发,框架里屏蔽了部分复杂却又不实用的东西,增加了部分常用东西。看一个web项目,首先就是查看web.xml中的定义。

<filter>
  	<filter-name>struts2</filter-name>
  	<filter-class>
  		org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  	</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>struts2</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

上面就是常见的struts的xml配置,而关键就是配置了一个Filter,过滤器。顾名思义,过滤器就是用于过滤请求的,它的功能,个人觉得可以近似为一个uri rewrite,当然,它还只属于一个代码的入口,不像WebServer的重写规则那么强大,但功能上是很近似的。

所以在Filter里,可能会做一些错误页重定向(例如50X,40X等页面的定向),当然也可以根据uri判断是哪个接口,调用并返回,这就是一般MVC框架单一入口的思想。

package demo.struts.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

public class MyFilter implements Filter
{

    public void destroy()
    {
        // TODO Auto-generated method stub
    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
    {

        //将ServletRequest变成HttpServletRequest
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        // TODO Auto-generated method stub
        //        System.out.println("in Filter" + (new Date()).getTime());


        //这里使用uri获取当前请求
        System.out.println(RequestUtils.getUri(request));
        //真正的struts通过namespace和actionName区分action的name和对应的类,通过method区分调用的方法
        chain.doFilter(request, response);//这句是关键,表示接口放行,通过filterChain执行

    }

    public void init(FilterConfig filterConfig) throws ServletException
    {
        // TODO Auto-generated method stub
        System.out.println("in init" + (new Date()).getTime());

    }

}

上面给出了一个最简单的Filter的写法,首先Filter需要复写接口Filter,并重写init、doFilter、destroy方法。init方法在项目启动时运行,destroy在项目结束时运行(可以认为是构造和析构),比较关键的是doFilter方法,该方法在所有http请求时都会运行。

不难想到,首先通过获取uri和struts.xml的配置获得ActionMap,如果map成功则执行ActionClass,否则就执行chain.doFilter(request, response);

当然,实际的struts也是这么实现的。

package org.apache.struts2.dispatcher.ng.filter;

import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
import org.apache.struts2.dispatcher.ng.PrepareOperations;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Executes the discovered request information.  This filter requires the {@link StrutsPrepareFilter} to have already
 * been executed in the current chain.
 */
public class StrutsExecuteFilter implements StrutsStatics, Filter {
    protected PrepareOperations prepare;
    protected ExecuteOperations execute;

    protected FilterConfig filterConfig;

    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    protected synchronized void lazyInit() {
        if (execute == null) {
            InitOperations init = new InitOperations();
            Dispatcher dispatcher = init.findDispatcherOnThread();
            init.initStaticContentLoader(new FilterHostConfig(filterConfig), dispatcher);

            prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
            execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
        }

    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (excludeUrl(request)) {
            chain.doFilter(request, response);
            return;
        }

        // This is necessary since we need the dispatcher instance, which was created by the prepare filter
        if (execute == null) {
            lazyInit();
        }

        ActionMapping mapping = prepare.findActionMapping(request, response);

        //if recusrion counter is > 1, it means we are in a "forward", in that case a mapping will still be
        //in the request, if we handle it, it will lead to an infinte loop, see WW-3077
        Integer recursionCounter = (Integer) request.getAttribute(PrepareOperations.CLEANUP_RECURSION_COUNTER);

        if (mapping == null || recursionCounter > 1) {
            boolean handled = execute.executeStaticResourceRequest(request, response);
            if (!handled) {
                chain.doFilter(request, response);
            }
        } else {
            execute.executeAction(request, response, mapping);
        }
    }

    private boolean excludeUrl(HttpServletRequest request) {
        return request.getAttribute(StrutsPrepareFilter.REQUEST_EXCLUDED_FROM_ACTION_MAPPING) != null;
    }

    public void destroy() {
        prepare = null;
        execute = null;
        filterConfig = null;
    }

}

当然在初始化时,struts使用了lazyinit模式,减轻在初始时的压力,节省资源。延迟加载的主要是两个对象,prepare和execute,两个都是工具性质的操作类,一个是用于获取ActionMapper的,一个用于执行Action的。

Filter作为struts的入口,是所有接口的一个过滤器,(当然也可以理解为一个拦截器,此处是为了过滤struts请求,交给struts处理)。过滤出请求之后,根据请求的uri定位到struts资源,唤起ActionSupport的execute方法。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现码+数据集+超详细注释.zip
提供的码资涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些码资特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资都能为你提供宝贵的学习和实践机会。通过学习和运行这些码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些码资进行课程实践、课外项目或毕业设计。通过分析和运行码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保码资的可运行性和易用性,特别注意了以下几点:首先,每份码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些码资,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值