17.一比一纯手写SpringMVC框架

注册HandlerUrlMapping

URL注册HandlerUrlMapping

package com.mayikt.init;

import com.mayikt.ext.MayiktController;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
* @author songchuanfu
* @qq 1802284273
*/
@Component
public class MayiktAbstractHandlerUrlMapping implements ApplicationContextAware, InitializingBean {
    @Autowired
    private ApplicationContext applicationContext;
    
    @Override
    public void afterPropertiesSet() throws Exception {
        // 1.从IOC容器中查找所有的bean对象
        String[] beanDefinitionNames = this.applicationContext.getBeanDefinitionNames();
        // 2.判断类上是否有加上@Component注解
        // 3.如果类上有加上@Component注解, 则获取对应的value值  为 url
        Arrays.stream(beanDefinitionNames).forEach((beanName) -> {
            Object handler = this.applicationContext.getBean(beanName);
            if (handler != null) {
                Class<?> handlerClass = handler.getClass();
                //3.判断该类上是否有加上该控制器注解
                Component componentController = handlerClass.getDeclaredAnnotation(Component.class);
                if (componentController != null) {
                    String url = componentController.value();
                    MayiktComponentRegistContainer.getRegistUrl().put(url + ".do", handler);
                }
            }
        });
    }
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        
    }
}



package com.mayikt.init;

import java.util.HashMap;
import java.util.Map;

/**
* @author songchuanfu
* @qq 1802284273
*/
public class MayiktComponentRegistContainer {
    private static Map<String, Object> registUrl = new HashMap<>();

    public static Map<String, Object> getRegistUrl() {
        return registUrl;
    }
}

package com.mayikt.init.handler;

import com.mayikt.ext.MayiktHandlerExecutionChain;
import com.mayikt.ext.MayiktHandlerMapping;
import com.mayikt.init.MayiktComponentRegistContainer;

import javax.servlet.http.HttpServletRequest;

/**
* @author songchuanfu
* @qq 1802284273
*/
public class BeanNameUrlHandlerMapping implements MayiktHandlerMapping {
    @Override
    public MayiktHandlerExecutionChain getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        // 根据请求URL从 springmvc容器中查找对应的Handler
        Object handler = MayiktComponentRegistContainer.getRegistUrl().get(requestURI);
        MayiktHandlerExecutionChain mayiktHandlerExecutionChain =
                new MayiktHandlerExecutionChain(handler);
        return mayiktHandlerExecutionChain;
    }
}

HandlerMethodMapping注册HandlerUrlMapping

package com.mayikt.init;

import com.mayikt.ext.MayiktController;
import com.mayikt.ext.MayiktRequestMapping;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
* @author songchuanfu
* @qq 1802284273
*/
@Component
public class MayiktAbstractHandlerMethodMapping implements ApplicationContextAware, InitializingBean {
    private ApplicationContext applicationContext;

    /**
     * 初始化 url与具体控制类方法 映射
     * spring控制类名称 handler
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        //1.从ioc容器获取所有bean的对象名称
        String[] beanDefinitionNames = this.applicationContext.getBeanDefinitionNames();
        //2.从ioc容器获取到具体bean对象
        Arrays.stream(beanDefinitionNames).forEach((beanName) -> {
            Object handler = this.applicationContext.getBean(beanName);
            if (handler != null) {
                Class<?> handlerClass = handler.getClass();
                //3.判断该类上是否有加上该控制器注解
                MayiktController mayiktController = handlerClass.getDeclaredAnnotation(MayiktController.class);
                if (mayiktController != null)
                    detectHandlerMethods(handler, handlerClass);
            }
        });


    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    private void detectHandlerMethods(Object handler, Class<?> handlerClass) {
        // 4.使用java反射机制获取所有的方法 判断方法上是否有加上MayiktRequestMapping
        Method[] declaredMethods = handlerClass.getDeclaredMethods();
        Arrays.stream(declaredMethods).forEach((method -> {
            //判断方法上是否有加上MayiktRequestMapping
            MayiktRequestMapping mayiktRequestMapping = method.getDeclaredAnnotation(MayiktRequestMapping.class);
            if (mayiktRequestMapping != null) {
                // 注册url
                // map集合 key url value 控制类、方法
                String reqURL = mayiktRequestMapping.value();
                // 注册存放url
                MayiktMappingRegistContainer.getRegistUrl().put(reqURL+".do", new MayiktMappingRegistration(handler, method, reqURL));
            }
        }));
    }
}

package com.mayikt.init;

import java.util.HashMap;
import java.util.Map;

/**
* @author songchuanfu
* @qq 1802284273
*/
public class MayiktMappingRegistContainer {
    private static Map<String, MayiktMappingRegistration> registUrl = new HashMap<>();

    public static Map<String, MayiktMappingRegistration> getRegistUrl() {
        return registUrl;
    }


}

package com.mayikt.init.handler;

import com.mayikt.ext.MayiktHandlerExecutionChain;
import com.mayikt.ext.MayiktHandlerMapping;
import com.mayikt.init.MayiktAbstractHandlerMethodMapping;
import com.mayikt.init.MayiktMappingRegistContainer;
import com.mayikt.init.MayiktMappingRegistration;

import javax.servlet.http.HttpServletRequest;

/**
* @author songchuanfu
* @qq 1802284273
*/
public class RequestMappingHandlerMapping extends MayiktAbstractHandlerMethodMapping implements MayiktHandlerMapping {
    @Override
    public MayiktHandlerExecutionChain getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        // 根据请求URL从 springmvc容器中查找对应的Handler
        MayiktMappingRegistration mayiktMappingRegistration = MayiktMappingRegistContainer.getRegistUrl().get(requestURI);
        if (mayiktMappingRegistration == null) {
            return null;
        }
        MayiktHandlerExecutionChain mayiktHandlerExecutionChain =
                new MayiktHandlerExecutionChain(mayiktMappingRegistration);
        return mayiktHandlerExecutionChain;
    }
}

适配器

package com.mayikt.init.adapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @author songchuanfu
* @qq 1802284273
*/
public interface MayiktHandlerAdapter {
    Object handle(HttpServletRequest request, HttpServletResponse response, Object handler);


    boolean supports(Object handler);
}

package com.mayikt.init.adapter;

import com.mayikt.ext.IMayiktController;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @author songchuanfu
* @qq 1802284273
*/
public class MayiktSimpleControllerHandlerAdapter implements MayiktHandlerAdapter {
    @Override
    public Object handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        IMayiktController mayiktController = (IMayiktController) handler;
        return mayiktController.handleRequest(request, response);
    }

    @Override
    public boolean supports(Object handler) {
        return handler instanceof IMayiktController;
    }
}
package com.mayikt.init.adapter;

import com.mayikt.init.MayiktMappingRegistration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* @author songchuanfu
* @qq 1802284273
*/
public class MayiktRequestMappingHandlerAdapter implements MayiktHandlerAdapter {
    @Override
    public Object handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        MayiktMappingRegistration mappingRegistration = (MayiktMappingRegistration) handler;
        // 使用反射机制调用handlerMethod
        Method handlerMethod = mappingRegistration.getHandlerMethod();
        Object handlerInfo = mappingRegistration.getHandler();
        try {
            Object result = handlerMethod.invoke(handlerInfo, null);
            return result;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public boolean supports(Object handler) {
        return handler instanceof MayiktMappingRegistration;
    }
}

MayiktDispatcherServlet

package com.mayikt.servlet;

import com.mayikt.adapter.MayiktHandlerAdapter;
import com.mayikt.adapter.MayiktSimpleControllerHandlerAdapter;
import com.mayikt.adapter.ReqHandlerMethodAdapter;
import com.mayikt.ext.IController;
import com.mayikt.ext.container.MayiktMappingRegistration;
import com.mayikt.ext.handlermapping.MayiktBeanNameUrlHandlerMapping;
import com.mayikt.ext.handlermapping.MayiktHandlerExecutionChain;
import com.mayikt.ext.handlermapping.MayiktHandlerMapping;
import com.mayikt.ext.handlermapping.MayiktRequestMappingHandlerMapping;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
* @author songchuanfu
* @qq 1802284273
*/
@WebServlet("*.do")
public class MayiktDispatcherServlet implements Servlet {
    /**
     * handlerMappings
     */
    private List<MayiktHandlerMapping> handlerMappings;
    private List<MayiktHandlerAdapter> handlerAdapters;

    @Override
    public void init(ServletConfig config) throws ServletException {
        initHandlerMapping();
        initHandlerAdapter();
    }

    private void initHandlerMapping() {
        handlerMappings = new ArrayList<>();
        handlerMappings.add(new MayiktBeanNameUrlHandlerMapping());
        handlerMappings.add(new MayiktRequestMappingHandlerMapping());
    }

    private void initHandlerAdapter() {
        handlerAdapters = new ArrayList<>();
        handlerAdapters.add(new MayiktSimpleControllerHandlerAdapter());
        handlerAdapters.add(new ReqHandlerMethodAdapter());
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        PrintWriter writer = res.getWriter();
        try {
            //1.根据请求路径查找对应的handler责任链
            MayiktHandlerExecutionChain handlerExecutionChain = getHandler(request);
            if (handlerExecutionChain == null) {
                response.setStatus(404);
                return;
            }
            // 2.根据责任链handler得到具体的适配器 适配器 调用handle
            MayiktHandlerAdapter handlerAdapter = getHandlerAdapter(handlerExecutionChain.getHandler());
            Object result = handlerAdapter.handle(request, response, handlerExecutionChain.getHandler());
            writer.print(result);
            //
// 获取到对应的handler
//            Object handler = handlerExecutionChain.getHandler();
//            if (handler instanceof IController) {
//                //
//                IController iController = (IController) handler;
//                Object result = iController.handleRequest(request, response);
//                writer.print(result);
//                return;
//            }
//            if (handler instanceof MayiktMappingRegistration) {
//                MayiktMappingRegistration mayiktMappingRegistration = (MayiktMappingRegistration) handler;
//                Method handlerMethod = mayiktMappingRegistration.getHandlerMethod();
//                // java反射机制执行方法
//                Object result = handlerMethod.invoke(mayiktMappingRegistration.getHandler(), null);
//                writer.print(result);
//                return;
//            }
        } catch (Exception e) {

        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    protected MayiktHandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (MayiktHandlerMapping handlerMapping : handlerMappings) {
            MayiktHandlerExecutionChain handler = handlerMapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

    protected MayiktHandlerAdapter getHandlerAdapter(Object handler) {
        for (MayiktHandlerAdapter handlerAdapter : handlerAdapters) {
            if (handlerAdapter.supports(handler)) {
                return handlerAdapter;
            }
        }
        return null;
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}
 

相关代码

📎手写springmvc相关代码.rar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值