• 02手写简易SpringMVC


    手写简易SpringMVC

    思路分析:

    1.启动tomcat

    2.spi机制加载spring容器,扫描包,生成bean,并且将注解解析到Map<String,RequestMappingInfo> map中

    3.get/post请求时,.

    • 根据url获取对应的RequestMappingInfo对象
    • 去匹配对应的适配器HandlerAdapter
    • 根据适配器类型选择合适的适配器去执行方法,返回数据
    • 将数据解析成json并写回前端

    实现流程

    项目结构如下

    image

    添加依赖pom.xml

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
    
        <!--使用maven tomcat插件时,当前依赖需要注释掉,不然会产生冲突。-->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.31</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>8.5.31</version>
        </dependency>
    
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.74</version>
        </dependency>
    </dependencies>
    
    <build>
        <finalName>customize-springmvc</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    

    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>
      
    </web-app>
    

    启动Tomcat

    package com.yoocar.springmvc;
    
    import org.apache.catalina.startup.Tomcat;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan("com.yoocar.springmvc")
    public class Start {
    
        public static void main(String[] args) throws Exception {
            // 创建Tomcat应用对象
            Tomcat tomcat = new Tomcat();
            // 设置Tomcat的端口号
            tomcat.setPort(8888);
            tomcat.addWebapp("/", "D:\\workspace\\springMVC-study\\customize-springmvc\\src\\main\\webapp");
            //启动tomcat容器
            tomcat.start();
            //等待
            tomcat.getServer().await();
    
        }
    }
    

    三个常用注解

    RequestMapping

    package com.yoocar.springmvc.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface RequestMapping {
    
        String value() default "";
    }
    

    RequestMappingInfo

    package com.yoocar.springmvc.servlet;
    
    import java.lang.reflect.Method;
    
    /**
     * 存放RequestMapping注解信息
     */
    public class RequestMappingInfo {
    
    
        //表示RequestMapping注解标识的方法
        private Method method;
    
        //表示RequestMapping注解的value属性,即url
        private String uri;
    
        //表示执行RequestMapping注解标识的方法的bean
        private Object obj;
    
        public Object getObj() {
            return obj;
        }
    
        public void setObj(Object obj) {
            this.obj = obj;
        }
    
        public Method getMethod() {
            return method;
        }
    
        public void setMethod(Method method) {
            this.method = method;
        }
    
        public String getUri() {
            return uri;
        }
    
        public void setUri(String uri) {
            this.uri = uri;
        }
    }
    

    RequestParam

    package com.yoocar.springmvc.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface RequestParam {
    
        String value() default "";
    }
    

    ResponseBody

    package com.yoocar.springmvc.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ResponseBody {
    }
    

    处理注解的

    spi机制加载spring容器

    package com.yoocar.springmvc.init;
    
    import com.yoocar.springmvc.Start;
    import com.yoocar.springmvc.servlet.DispatcherServlet;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import javax.servlet.ServletContainerInitializer;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletRegistration;
    import java.util.Set;
    
    //spi机制
    public class Myinit implements ServletContainerInitializer{
    
        @Override
        public void onStartup(Set<Class<?>> c,ServletContext servletContext) {
            AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Start.class);
    
            DispatcherServlet servlet = new DispatcherServlet(ac);
            ServletRegistration.Dynamic dy = servletContext.addServlet("app",servlet);
            dy.setLoadOnStartup(1);
            dy.addMapping("*.do");
    
        }
    
    }
    

    DispatcherServlet

    import com.yoocar.springmvc.init.handlerAdapter.HandlerAdapter;
    import com.yoocar.springmvc.init.handlerMapping.HandlerMapping;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Collection;
    import java.util.Map;
    
    public class DispatcherServlet extends HttpServlet {
    
        //适配器
        static Collection<HandlerAdapter> handlerAdapters ;
    
        //映射器
        static Collection<HandlerMapping> handlerMappings ;
    
        public DispatcherServlet() {
        }
    
        public DispatcherServlet(AnnotationConfigApplicationContext ac) {
            //组件初始化
            Map<String, HandlerMapping> handlerMappingMaps = ac.getBeansOfType(HandlerMapping.class);
            handlerMappings = handlerMappingMaps.values();
    
            Map<String, HandlerAdapter> handlerAdapterMaps = ac.getBeansOfType(HandlerAdapter.class);
            handlerAdapters = handlerAdapterMaps.values();
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
            //获取映射器
            Object handlerMapping = getHandlerMapping(req);
            if(handlerMapping == null){
                System.out.println("未匹配到handlerMapping");
                return;
            }
            //获取适配器
            HandlerAdapter handlerAdapter = getHandlerAdapter(handlerMapping);
            if(handlerAdapter == null){
                System.out.println("未匹配到handlerAdapter");
                return;
            }
            //使用适配器(处理器)去处理
            Object result = handlerAdapter.handle(req,resp,handlerMapping);
            PrintWriter writer = resp.getWriter();
            writer.println(result);
            writer.flush();
            writer.close();
        }
    
        protected Object getHandlerMapping(HttpServletRequest request) {
            if (this.handlerMappings != null) {
                for (HandlerMapping mapping : this.handlerMappings) {
                    Object handler = mapping.getHandlerMapping(request.getRequestURI());
                    if (handler != null) {
                        return handler;
                    }
                }
            }
            return null;
        }
    
        protected HandlerAdapter getHandlerAdapter(Object handlerMapping) {
            if (this.handlerAdapters != null) {
                for (HandlerAdapter adapter : this.handlerAdapters) {
                    boolean flag = adapter.supports(handlerMapping);
                    if (flag) {
                        return adapter;
                    }
                }
            }
            return null;
        }
    
    }
    
  • 相关阅读:
    BZOJ 3754 Tree之最小方差树
    【CSS】318- CSS实现宽高等比自适应容器
    【Vuejs】317- 提升90%加载速度——Vuecli下的首屏性能优化
    【H5】316- 移动端H5跳坑指南
    【每周小回顾】2- 一起回顾上周精彩内容
    【Webpack】315- 手把手教你搭建基于 webpack4 的 vue2 多页应用
    【Web技术】314- 前端组件设计原则
    【JS】313- 复习 回流和重绘
    【JS】312- 复习 JavaScript 严格模式(Strict Mode)
    【Canvas】311- 解决 canvas 在高清屏中绘制模糊的问题
  • 原文地址:https://www.cnblogs.com/lusaisai/p/15983096.html
Copyright © 2020-2023  润新知