手写简易版SpringIoc、SpringMvc

1 工程目录

在这里插入图片描述

2 pom

 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <path>/</path>
                    <port>8080</port>
                </configuration>
            </plugin>
        </plugins>
    </build>

3 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>Rosh Created Web Application</display-name>


    <servlet>
        <servlet-name>roshmvc</servlet-name>
        <servlet-class>com.rosh.mvcframework.servlet.RoshDispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>application.properties</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet-mapping>
        <servlet-name>roshmvc</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>


</web-app>

4 application.properties

scanPackage=com.rosh.demo

5 注解

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RoshService {
    
    
    String value() default "";
}

@Target({
    
    ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RoshRequestParam {
    
    
    String value() default "";
}

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


@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RoshController {
    
    

    String value() default "";
}

@Target({
    
    ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RoshAutowired {
    
    
    String value() default "";
}

6 RoshDispatcherServlet

package com.rosh.mvcframework.servlet;

import com.rosh.mvcframework.annotation.RoshAutowired;
import com.rosh.mvcframework.annotation.RoshController;
import com.rosh.mvcframework.annotation.RoshRequestMapping;
import com.rosh.mvcframework.annotation.RoshService;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;

public class RoshDispatcherServlet extends HttpServlet {
    
    


    private Properties contextConfig = new Properties();

    private List<String> classNames = new ArrayList<>();

    private Map<String, Object> ioc = new HashMap<>();

    private Map<String, Method> handlerMapping = new HashMap<>();


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

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

        //调用
        try {
    
    
            doDispatch(req, resp);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    
    

        //绝对路径
        String url = req.getRequestURI();
        //相对路径
        String contextPath = req.getContextPath();
        url = url.replaceAll(contextPath, "").replaceAll("/+", "/");

        if (this.handlerMapping.containsKey(url)) {
    
    

            Method method = this.handlerMapping.get(url);
            //beanname
            String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName());
            //参数
            Map<String, String[]> parameterMap = req.getParameterMap();

            method.invoke(ioc.get(beanName), new Object[]{
    
    req, resp, parameterMap.get("name")[0]});
        } else {
    
    
            resp.getWriter().write("404 Not Found!!!!");
        }


    }


    @Override
    public void init(ServletConfig config) throws ServletException {
    
    

        //1 加载配置文件
        doLoadConfig(config.getInitParameter("contextConfigLocation"));
        //2 扫描相关类
        doScanner(contextConfig.getProperty("scanPackage"));
        //3 初始化扫描到的类,并且将他们放入到IOC容器中
        doInstance();
        //4 完成依赖注入
        doAutowired();
        //5 初始化HandlerMapping
        initHandlerMapping();

        System.out.println("Rosh Spring framework is init.");
    }

    /**
     * 映射
     */
    private void initHandlerMapping() {
    
    
        if (!ioc.isEmpty()) {
    
    
            for (Map.Entry<String, Object> entry : ioc.entrySet()) {
    
    
                Class<?> clazz = entry.getValue().getClass();
                if (clazz.isAnnotationPresent(RoshController.class)) {
    
    
                    String baseUrl = "";
                    if (clazz.isAnnotationPresent(RoshRequestMapping.class)) {
    
    
                        RoshRequestMapping requestMapping = clazz.getAnnotation(RoshRequestMapping.class);
                        baseUrl = requestMapping.value();
                    }
                    //获取所有public 方法
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
    
    
                        if (method.isAnnotationPresent(RoshRequestMapping.class)) {
    
    
                            RoshRequestMapping requestMapping = method.getAnnotation(RoshRequestMapping.class);
                            String url = (baseUrl + "/" + requestMapping.value()).replaceAll("/+", "/");
                            handlerMapping.put(url, method);
                        }
                    }

                }

            }
        }


    }

    /**
     * 自动注入
     */
    private void doAutowired() {
    
    
        if (!ioc.isEmpty()) {
    
    

            for (Map.Entry<String, Object> entry : ioc.entrySet()) {
    
    
                //所有字段
                Field[] fields = entry.getValue().getClass().getDeclaredFields();
                for (Field field : fields) {
    
    
                    if (field.isAnnotationPresent(RoshAutowired.class)) {
    
    
                        RoshAutowired autowired = field.getAnnotation(RoshAutowired.class);
                        String beanName = autowired.value();
                        if ("".endsWith(beanName)) {
    
    
                            beanName = field.getType().getName();
                        }
                        field.setAccessible(true);
                        try {
    
    
                            //反射机制,动态赋值
                            field.set(entry.getValue(), ioc.get(beanName));
                        } catch (IllegalAccessException e) {
    
    
                            e.printStackTrace();
                        }
                    }
                }
            }
        }


    }

    /**
     * 初始化
     */
    private void doInstance() {
    
    

        if (classNames.isEmpty()) {
    
    
            return;
        }

        try {
    
    
            for (String className : classNames) {
    
    
                Class<?> clazz = Class.forName(className);
                //判断注解
                if (clazz.isAnnotationPresent(RoshController.class)) {
    
    
                    Object o = clazz.newInstance();
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    ioc.put(beanName, o);
                } else if (clazz.isAnnotationPresent(RoshService.class)) {
    
    

                    //1 默认beanName
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    //2 自定义beanName
                    RoshService roshService = clazz.getAnnotation(RoshService.class);
                    if (!"".endsWith(roshService.value())) {
    
    
                        beanName = roshService.value();
                    }
                    Object o = clazz.newInstance();
                    ioc.put(beanName, o);
                    //3 根据类型自动赋值
                    for (Class<?> i : clazz.getInterfaces()) {
    
    
                        if (!ioc.containsKey(i.getName())) {
    
    
                            ioc.put(i.getName(), o);
                        }
                    }
                }
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

    }

    private String toLowerFirstCase(String simpleName) {
    
    
        char[] chars = simpleName.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }

    /**
     * 扫描出相关的类
     */
    private void doScanner(String scanPackage) {
    
    
        //获取类文件url
        URL url = this.getClass().getClassLoader().getResource(scanPackage.replaceAll("\\.", "/"));
        //读取当前类文件
        File rootFile = new File(url.getFile());
        //遍历
        for (File file : rootFile.listFiles()) {
    
    
            if (file.isDirectory()) {
    
    
                doScanner(scanPackage + "." + file.getName());
            } else {
    
    
                if (!file.getName().endsWith(".class")) {
    
    
                    continue;
                }
                //获取类名
                String className = scanPackage + "." + file.getName().replace(".class", "");
                classNames.add(className);
            }

        }

    }

    /**
     * 加载配置文件
     */
    private void doLoadConfig(String contextConfigLocation) {
    
    
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
    
    
            contextConfig.load(is);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (is != null) {
    
    
                try {
    
    
                    is.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }

    }


}

7 业务类

@RoshController
@RoshRequestMapping("/student")
public class StudentController {
    
    

    @RoshAutowired
    private StudentService studentService;


    @RoshRequestMapping("/query")
    public void query(HttpServletRequest req, HttpServletResponse resp,
                      @RoshRequestParam("name") String name) {
    
    
        String result = "<h1>My name is " + name + "</h1>";
        try {
    
    
            resp.getWriter().write(result);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }


}


public interface StudentService {
    
    
}

@RoshService
public class StudentServiceImpl implements StudentService {
    
    
}


8 测试

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34125999/article/details/109302461