手把手写框架入门(一) | 核心拦截器DispatchFilter实现

前言

【课程目标】

深入理解Java Web核心开发
掌握框架开发的必备知识
具备自主编写Web开发框架的思路

【课程目标】

本教程内容基于伟大的Struct2框架原理进行学习,本教程只是个人学习的记录,仅供大家学习交流,不作为任何商业用途

【课程思想】

先构思整体基本设计思路,再逐一实现每个模块的具体逻辑,一开始不必要太在意细节,先让整个流程跑通,再慢慢优化框架

1Filter实现框架拦截

【课前思考】

1.Filter的作用是什么?
2.Filter什么时候加载
3.框架是如何根据用户请求找到对应的处理类和处理方法
4.框架是如何执行用户请求

1.1配置自定义Filter

想在项目中用上我们自己的框架,需要在web.xml中配置我们自己实现的Filter,容器在启动时会帮我们初始化该过滤器

 <filter>
    <filter-name>dispatchFilter</filter-name>
    <filter-class>com.eshare.core.filter.DispatchFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>dispatchFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

1.2创建一个Filter

该filter作为我们的请求的核心转发器,命名为DispatchFilter,帮我们转发请求到对应的Action中处理

该filter功能如下:
1.获取用户请求
2.根据用户请求找到对应的映射类(ActionMapping)
3.如果找到匹配的映射类,则执行用户请求,否则,继续执行其他环节

【思路】

1.通过ActionMapper去找到用户请求对应的映射类actionMapping
2.通过WebExecutor去执行actionMapping的对应的处理类和方法

模块:
1.ActionMapper 此处用于管理映射类
2.ActionMapping 此处用于管理处理类的全限定名、处理方法名
3.WebExecutor 此处用于根据对应的actionMapping统一执行用户请求

public class DispatchFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //filter执行过滤器
        System.out.println("dispatchFilter开始执行");
        //根据请求找到对应的mapping类
        ActionMapper actionMapper = new ActionMapper();
        ActionMapping mapping =actionMapper.findMapping(request);
        if(mapping!=null){
            WebExecutor executor = new WebExecutor();
            //执行用户请求
            executor.execute(request,response,mapping);
        }else {
            //非框架处理部分,继续执行其他环节
            chain.doFilter(request, response);
        }
    }
    public void destroy() {
    }
}

1.3创建一个ActionMapping

由第二节可以得知,ActionMapping在本章内容是用来管理具体处理类和处理方法的,所以它应该有属性去记录处理类的全限定名和处理方法的方法名,以便于以后框架反射执行处理方法

【思路】

ActionMapping主要用于映射配置的,要让框架获取到该类实例时,可以调用框架使用者用于处理请求的具体类和方法并且以某种形式响应给调用者,我们可以猜想反射需要用到的条件,就是全限定名和具体方法名,还有处理完成以什么形式响应给用户

属性:
1.className 处理类的全限定名

2.methodName 处理类的处理方法

3.result 返回结果(如jsp、file)

public class ActionMapping {
    /**
     * 类全限定名
     */
    private String className;
    /**
     * 方法名
     */
    private String methodName;
    /**
     * 返回结果
     */
    private String result;

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
}

1.4创建一个ActionMapper

由第二节可以得知,ActionMapper在本章内容就是用来管理映射类的,那么它需要有findMapping这样的方法用于查找映射类,这样可以根据用户的请求参数来查找到对应的映射类ActionMapping

PS:在本章暂时用硬编码方式实现基本功能,后面再做优化,本章例子使用PersonAction作为请求处理类

【思路】

通过ActionMapper的findMapping方法,根据用户的请求参数,查找到对应的映射类ActionMapping,然后返回该映射类

public class ActionMapper {
    public ActionMapping findMapping(ServletRequest request) {
        ActionMapping actionMapping = new ActionMapping();
        actionMapping.setClassName("com.eshare.action.PersonAction");
        actionMapping.setMethodName("hello");
        return actionMapping;
    }
}

1.5创建一个WebExecutor

由第二节可以得知,webExecutor在本章内容是用于根据具体的映射类actionMapping去执行用户请求,它应该有一个execute执行方法,用于执行actionMapping具体的处理方法,并响应给用户

【思路】

通过WebExecutor中的execute方法,框架可以统一反射调用映射类中的具体实现方法,来执行用户请求

public class WebExecutor {
    public void execute(ServletRequest request, ServletResponse response, ActionMapping mapping) {
        //获取执行请求的类名
        String className = mapping.getClassName();
        //获取执行请求的方法
        String methodName =mapping.getMethodName();
        try {
          Class clazz =  Class.forName(className);
           Object obj = clazz.newInstance();
           Method method =  clazz.getMethod(methodName,null);
            //执行方法
            method.invoke(obj,null);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

1.6创建测试类PersonAction

PersonAction在本章内容是用于模拟框架使用者自定义的处理类,它里面包含一个hello方法,是框架使用者自定义的一个方法,本章主要围绕着该方法,看框架如何通过请求一步步找到hello这方法,并执行

首先我们在test/java目录下创建一个PersonAction,避免代码结构混乱,因为主目录是用来存放框架代码

public class PersonAction {

    public String hello(){
        System.out.println("hello");
        boolean flag = false;
        if(flag){
            return "SUCCESS";
        }else {
            return "FAILE";
        }
    }
}

1.7最终工程目录结构

这里写图片描述

2测试Filter

2.1启动tomcat

2.2在浏览器输入URL

我的上下文路径是eshare
http://localhost:8080/eshare/hello

2.3查看控制台输出结果

这里写图片描述

3本章源码地址

Github:https://github.com/Evan43789596/FrameworkDesign.git

猜你喜欢

转载自blog.csdn.net/evan_leung/article/details/53237115