To understand the Spring MVC run the process, I realized the handwriting of Spring MVC

Introduction

github Code: HTTPS: //github.com/erlieStar/servlet-learning
V3 branch

Using a servlet 3.0 web.xml so we do not have, and takes notes

Defined Note

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
    String value() default "";
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
    String value() default "";
}

Defined central controller

Substantially all of the logic in this class, the following main process

  1. Creating DispatcherServlet time, tomcat will call the init () method, url mapping in which initialization processing method and corresponding
  2. When a request for the method to get from the corresponding uriInvokeInfoMap, if there is a corresponding method, the reflection method is called to get the page name, the page address stitching, forwarded to the appropriate page, otherwise 404
@WebServlet(urlPatterns="/", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {

    // 保存所有的handler
    private List<Object> beanList = new ArrayList<>();
    // 保存 uri 和 handler 的映射关系
    private Map<String, InvokeInfo> uriInvokeInfoMap = new HashMap<>();

    private static final String SLASH = "/";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uri = req.getRequestURI();
        String contextPath = req.getContextPath();
        // 去掉项目路径
        uri = uri.replace(contextPath, "");
        System.out.println(uri);
        if (uri == null) {
            return;
        }
        InvokeInfo invokeInfo = uriInvokeInfoMap.get(uri);
        if (invokeInfo == null) {
            resp.getWriter().write("404");
            return;
        }
        String pageName = (String)methodInvoke(invokeInfo.getBean(), invokeInfo.getMethod());
        viewResolver(pageName, req, resp);
    }

    // 视图解析器
    public void viewResolver(String pageName, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String prefix = "/";
        String suffix = ".jsp";
        req.getRequestDispatcher(prefix + pageName + suffix).forward(req, resp);
    }

    // 反射执行方法
    private Object methodInvoke(Object object, Method method) {
        try {
            return method.invoke(object);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void init() throws ServletException {
        // 获取指定包下的Class对象
        List<Class<?>> classList = ClassUtil.getAllClassByPackageName("com.javashitang.controller");
        // 找到所有标注了@Controller的类
        findAllConrollerClass(classList);
        // 初始化 uri 和 handler 的映射关系
        handlerMapping();
    }


    public void findAllConrollerClass(List<Class<?>> list) {
        list.forEach(bean -> {
            // 将被@Controller注解修饰的类放到beanList
            if (bean.isAnnotationPresent(Controller.class)) {
                try {
                    beanList.add(bean.newInstance());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    // 根据url找到相应的处理类
    public void handlerMapping() {
        for (Object bean : beanList) {
            Class<? extends Object> classInfo = bean.getClass();
            // 获取类上的@RequestMapping信息
            RequestMapping beanRequestMapping = classInfo.getDeclaredAnnotation(RequestMapping.class);
            String baseUrl = beanRequestMapping != null ? beanRequestMapping.value() : "";
            Method[] methods = classInfo.getDeclaredMethods();
            for (Method method : methods) {
                System.out.println(method.getName());
                // 获取方法上的@RequestMapping信息
                RequestMapping methodRequestMapping = method.getDeclaredAnnotation(RequestMapping.class);
                if (methodRequestMapping != null) {
                    String requestUrl = SLASH + baseUrl + SLASH + methodRequestMapping.value();
                    // 为了处理@Controller和@RequestMapping value 中加了 / 前缀的情况
                    requestUrl = requestUrl.replaceAll("/+", "/");
                    InvokeInfo invokeInfo = new InvokeInfo(bean, method);
                    uriInvokeInfoMap.put(requestUrl, invokeInfo);
                }
            }
        }
    }
}

The method and corresponding to a bit class does packaging

public class InvokeInfo {

    private Object bean;
    private Method method;

    public InvokeInfo(Object bean, Method method) {
        this.bean = bean;
        this.method = method;
    }
}

start testing

@Controller
@RequestMapping("index")
public class IndexController {

    @RequestMapping("user")
    public String user() {
        return "user";
    }
}

Visit the following connections displayed correctly

http://localhost:8080/show/index/user

Welcome attention

Here Insert Picture Description

Reference blog

[1] https://my.oschina.net/liughDevelop/blog/1622646
[2] https://www.malaoshi.top/show_1EFutw6imbI.html

Published 385 original articles · won praise 1471 · Views 900,000 +

Guess you like

Origin blog.csdn.net/zzti_erlie/article/details/105020358