从零写一个Java WEB框架(六)Controller层优化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GG_and_DD/article/details/80766217
  • 该系列,其实是对《架构探险》这本书的实践。本人想记录自己的学习心得所写下的。
  • 从一个简单的Servlet项目开始起步。对每一层进行优化,然后形成一个轻量级的框架。
  • 每一篇,都是针对项目的不足点进行优化的。
  • 项目已放上github

本篇

前几篇的优化都没有涉及到Controller层。本篇开始将开始实现对Controller层的优化。由于上篇的IOC,创建了类容器。基于这个类容器,就可以很轻松地完成对Controller的优化了。
为了Controller解耦,还是决定使用请求容器(存放请求路径与处理方法映射关系),建立一个转换器。根据获取HttpRequest中的请求路径和参数,从请求容器里面去获取到相对应的方法。达到一个解耦的目的。
本篇主要实现功能:
- 封装请求信息
- 封装类和方法信息
- 将请求信息和方法信息形成K-V映射关系存到Map容器中

Controller 层实现目的:
根据Action注解实现请求路径和方法的绑定。

@Controller
public class CustomerServlet {


//    获取所有用户信息
    @Action("get:/customer_show/getList")
    public String getList() {
        //TODO
        return null;
    }


//    根据id获取用户信息
    @Action("get:/customer_show/getCustomer")
    public String getList(Integer id) {
        //TODO
        return null;
    }
}

功能实现

Request类 封装请求信息

/*
*
*   封装请求信息
*
*   思路:
*   1. 封装请求的信息, 正常的请求信息是: get:/customer_show
*      需要拆分成 requestMethod = get
*               requestPath  = /customer_show
*
*   2. 因为需要将请求信息放在Map中,以Request的对象为key,因为是对象作为key,
*       所以重写hashcode()和equals()方法,主要改变Map判断key的时候发挥作用。
* */
public class Request {

    /*
     *  请求方法
     * */
    private String requestMethod;

    /*
     *  请求路径
     * */
    private String requestPath;

    public Request(String requestMethod, String requestPath) {
        this.requestMethod = requestMethod;
        this.requestPath = requestPath;
    }

    public String getRequestMethod() {
        return requestMethod;
    }

    public String getRequestPath() {
        return requestPath;
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof Request) {
            Request r = (Request) o;
            //进行判断
            if (r.getRequestMethod().equals(this.requestMethod) &&
                    r.getRequestPath().equals(this.requestPath)) {
                return true;
            }
        }

        return false;

    }


    // 主要思路就是利用两个变量的hashCode,而不是对象的hashCode。

    @Override
    public int hashCode() {
        return Objects.hash(this.requestPath, this.requestMethod);
    }
}

Handler 类 封装Action注解的类和方法

/*
*  封装Action信息
*  封装类 和方法
* */
public class Handler {

    /*
    *  Controller注解 类
    * */
    private Class<?> controllerClass;

    /*
     *  Action注解的 方法
     * */
    private Method actionMethod;

    public Handler(Class<?> controllerClass, Method actionMethod) {
        this.controllerClass = controllerClass;
        this.actionMethod = actionMethod;
    }

    public Class<?> getControllerClass() {
        return controllerClass;
    }

    public Method getActionMethod() {
        return actionMethod;
    }
}

ControllerHelper 类 建立有个Map容器用来存放request和handler的映射关系

/*
 *  控制类助手类
 * */
public class ControllerHelper {
    /*
     *  思路:
     *  1、遍历所有Controller 注解的类
     *  2、遍历每个类中的方法,找出有Action注解的方法
     *  3、从Action 注解中获取URL映射
     *  4、将URL映射存到Request对象,将该类和方法存到Handler对象
     *  5、存到Map集合中。 key---Request  value---Handler
     * */

    /*
     *  定义一个Map容器,存放Request和Handler的映射关系
     * */
    private final static Map<Request, Handler> ACTION_MAP =
            new HashMap<>();

    static{
        //获取所有具有Controoler注解的类
        Set<Class<?>> controllerClassSet = ClassHelper.getControllerClassSet();
        if (CollectionUtils.isNotEmpty(controllerClassSet)) {
            //遍历类
            for (Class<?> c : controllerClassSet) {
                //获取该类下的所有方法
                Method[] declaredMethods = c.getDeclaredMethods();
                if (declaredMethods != null) {
                    //遍历方法
                    for (Method m : declaredMethods) {
                        if (m.isAnnotationPresent(Action.class)) {
                            Action action = m.getAnnotation(Action.class);
                            //获取Action注解中的URL值
                            String mapping = action.value();
                            //验证URL映射值
                            if (mapping.matches("\\w+:/\\w*")) {
                                //将URL分割成Method 和path
                                String[] split = mapping.split(":");
                                if (split != null && split.length == 2) {
                                    //获取请求方法与请求路径
                                    String method=split[0];
                                    String path = split[1];
                                    Request request = new Request(method, path);
                                    Handler handler = new Handler(c, m);
                                    //存进 Map
                                    ACTION_MAP.put(request, handler);
                                }
                            }
                        }
                    }
                }


            }
        }
    }


    public static Handler getHandler(String requestMethod, String requestPath) {
        Request request = new Request(requestMethod, requestPath);
        return ACTION_MAP.get(request);
    }
}

Loader 类
因为是框架,所以很多都是配置类,需要在项目启动的时候就需要加载,所以需要写一个Loader类,只需要调用这么一个类就可以加载框架的配置类了。

/*
*  加载相应的Helper类
* */
public final class HelperLoader {

    public  static void init() {
       Class<?>[] classList={
               ClassHelper.class,
               BeanHelper.class,
               ConfigHelper.class,
               ControllerHelper.class,
               IOCHelper.class
       };
        for (Class c : classList) {
            ClassUtil.loadClass(c.getName(), true);
        }
    }
}   

总结

一个Action的容器就建立起来了。下一章节就需要建立一个转发器,根据HttpRequest的请求路径和参数从Action容器中找到对应的处理方法。

猜你喜欢

转载自blog.csdn.net/GG_and_DD/article/details/80766217
今日推荐