手写一个简单的spring mvc解析器

     spring mvc的运行流程如下图所示

   在这里我们只实现基本功能,对流程做一定的简化。我们需要以下几个步骤:

      加载配置文件

      获取所有的class名称

      获取需要注入的实例

      缓存方法映射

      注入bean

  第一步,加载配置文件,首先在resource目录下新建application.properties文件,并创建自己的servlet,配置web.xml

application.properties文件

#设置扫描根目录,此处为了简化,直接使用properties文件
baseScanPackage=com.study.mvc

自定义的servlet

...
// DispatcherServlet类继承HttpServlet,并覆写doGet、doPost方法

public class DispatcherServlet extends HttpServlet { private static final String Context_CONFIG_LOCATON = "contextConfigLocation"; private Properties properties = new Properties();
    //缓存读取到的class
    private Set<String> classNames = new HashSet<>();

//缓存className与class实例的对应关系
private Map<String, Object> iocMap = new HashMap<>();
//缓存url与controller的映射关系
private Map<String, Object> controllerMap = new HashMap<>();
//缓存url与其对应方法的映射关系
private Map<String, Method> handMappingMap = new HashMap<>(); @Override public void init(ServletConfig servletConfig) throws ServletException { String configPath = servletConfig.getInitParameter(Context_CONFIG_LOCATON); try { //加载配置文件 doLoadConfig(configPath); //获取所有class名称 String baseScanPackage = properties.getProperty("baseScanPackage"); doLoadClassNames(baseScanPackage); //获取需要注入的实例 doLoadIocMap(); //方法映射 doHandMapping(); //注入bean doIoc(); } catch (Exception e) { throw new RuntimeException(e); } super.init(); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doDispatcher(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doDispatcher(req, resp); }
//实际调用的路由方法
private void doDispatcher(HttpServletRequest req, HttpServletResponse resp) { String url = req.getRequestURI(); System.out.println(url); Method method = handMappingMap.get(url); Object controller = controllerMap.get(url); try {
Parameter[] parameters
= method.getParameters(); if (parameters != null && parameters.length > 0) { Object[] args = new Object[parameters.length];
//根据requestParam封装参数
for (int i = 0; i < parameters.length; i++) { if (parameters[i].isAnnotationPresent(RequestParam.class)) { RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); args[i] = req.getParameter(requestParam.value()); continue; } args[i] = null; } method.invoke(controller, args); } else { method.invoke(controller); } resp.getWriter().print("success"); } catch (Exception e) { e.printStackTrace(); } } ... }

web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>


<!--定义自己的servlet--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>com.study.mvc.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>application.properties</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>

猜你喜欢

转载自www.cnblogs.com/wkzhao/p/10274593.html