纯手写springmvc框架ioc容器(简易版),实现实体类参数接收,并实现基于yaml配置文件

基于注解yaml配置手动实现简单的springmvc,实现bean注入功能,mvc实体类参数接收

    • 项目github地址:https://github.com/kongGe55/spring-mvc-test
    • 整个项目只依赖了javaweb相关jar包
    • 不完善的地方
    • 使用方法和springmvc一样,只不过配置文件要在resource下,名称application.yaml
  • 实现效果
    • 实体类参数注入效果
    • bean自动注入效果
    • 基本包
  • 下面是相关代码,具体项目可以到gihub下载https://github.com/kongGe55/spring-mvc-test
    • 首先是相关注解
    • 然后是核心的DispatcherServlet相关代码
    • BeanFactory bean工厂接口
    • SpringMvcBeanFactory工厂类
    • handler处理器接口
    • HttpRequestHandler处理器类
    • HandlerMapping处理器映射类

项目github地址:https://github.com/kongGe55/spring-mvc-test

整个项目只依赖了javaweb相关jar包


    
      junit
      junit
      4.11
      test
    
    
      org.apache.tomcat
      servlet-api
      6.0.29
      provided
    
    
    
      org.yaml
      snakeyaml
      1.17
    
    
      com.fasterxml.jackson.core
      jackson-core
      2.9.8
    
    
      com.fasterxml.jackson.core
      jackson-databind
      2.9.8
    
  

不完善的地方

  1. 实体类参数接受只支持String类型和Interger,后期可以加上其他参数类型接收,支持类型有限;
  2. 只支持注解
  3. 还很多不完善的地方望指正,我也是在学习反射的使用

使用方法和springmvc一样,只不过配置文件要在resource下,名称application.yaml

在这里插入图片描述
配置web.xml


  Archetype Created Web Application
  
    DispacherServlet
    com.ji.spring.springmvc.servlet.DispatcherServlet
    1
  
  
    DispacherServlet
    /
  

applicetion配置

springmvc :
  application :
#    要扫描的包名
     scanPackage : com.ji.test

实现效果

实体类参数注入效果

实体类

public class User {
	private String name;
	private Integer age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + "]";
	}
	
}

测试controller

@Controller
@RequestMapping("test")
public class TestController {
    @AutoWired
    private TestService testService;
    @RequestMapping("demo")
    public void success(){
        System.out.println("访问成功!111111111111111111111");
    }
    @RequestMapping("user")
    public User user(@RequestParam("age")Integer i,@RequestParam("name") String name ,User user) {
    	System.out.println(user);
        System.out.println(i);
        System.out.println();
        System.out.println(name);
        return user;
    }
}

访问效果
纯手写springmvc框架ioc容器(简易版),实现实体类参数接收,并实现基于yaml配置文件_第1张图片
纯手写springmvc框架ioc容器(简易版),实现实体类参数接收,并实现基于yaml配置文件_第2张图片

bean自动注入效果

controller

@Controller
@RequestMapping("user")
public class UserController {
    @AutoWired
    private UserService userService;
    @RequestMapping("findUser")
    public List findUser(HttpServletResponse response) throws IOException {
        List list = userService.findUser();
        return list;
    }
}

这里返回数据自动进行了处理
Service

@Component("userService") //也可以直接用@Service注解
public class UserService {
    public List findUser(){
        User user1 = new User();
        user1.setAge(23);
        user1.setName("测试1");
        User user2 = new User();
        user2.setAge(23);
        user2.setName("测试2");
        User user3 = new User();
        user3.setAge(55);
        user3.setName("测试3");
        List list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        return list;
    }
}

访问效果
纯手写springmvc框架ioc容器(简易版),实现实体类参数接收,并实现基于yaml配置文件_第3张图片

基本包

纯手写springmvc框架ioc容器(简易版),实现实体类参数接收,并实现基于yaml配置文件_第4张图片

下面是相关代码,具体项目可以到gihub下载https://github.com/kongGe55/spring-mvc-test

首先是相关注解

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

}
------------------------------------------------
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
    String value();
}
--------------------------------------------------------
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
}
----------------------------------------------------------------


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

然后是核心的DispatcherServlet相关代码

package com.ji.spring.springmvc.servlet;

import com.ji.spring.core.annotation.AutoWired;
import com.ji.spring.core.annotation.Component;
import com.ji.spring.core.annotation.Service;
import com.ji.spring.springmvc.annotation.Controller;
import com.ji.spring.core.bean.SpringMvcBeanFactory;
import com.ji.spring.core.bean.BeanFactory;
import com.ji.spring.springmvc.annotation.RequestMapping;
import com.ji.spring.springmvc.annotation.RequestParam;
import org.yaml.snakeyaml.Yaml;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.KeyStore;
import java.util.*;


public class DispatcherServlet extends HttpServlet {
    private List classNameList = new ArrayList();
    private Map handlerMappings = new HashMap<>();
    HttpRequestHandler httpRequestHandler;
    @Override
    public void init() throws ServletException {
        //扫描包下的类
        try {
            initClassNameList();
        } catch (FileNotFoundException e) {
            System.out.println("没有找到配置文件");
        }
        //初始化bean容器
        initBeans();
        //初始化属性注入
        initWired();
        //初始化HandlerMapping
        initHandlerMapping();
        httpRequestHandler = new HttpRequestHandler();
    }

    private void initHandlerMapping() {
        //遍历bean容器
        SpringMvcBeanFactory beanFactory = (SpringMvcBeanFactory) SpringMvcBeanFactory.getBeanFactory();
        Set set = beanFactory.keySet();
        for (String key:set){
            Object bean = beanFactory.getBean(key);
            Class beanClass = bean.getClass();
            if (beanClass.isAnnotationPresent(Controller.class)){
                //如果是controller
                String url = "/";
                if (beanClass.isAnnotationPresent(RequestMapping.class)){
                    //判断类上RequestMapping路径
                    RequestMapping requestMapping = (RequestMapping) beanClass.getAnnotation(RequestMapping.class);
                    String tem = requestMapping.value();
                    url = url+tem+"/";
                }
                //判断方法上RequestMapping路径
                Method[] methods = beanClass.getDeclaredMethods();
                for (Method method:methods){
                    if (method.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
                        String s = methodAnnotation.value();
                        String url_tem = url;
                        url_tem += s;
                        url_tem.replaceAll("//", "/");
                        HandlerMapping handlerMapping = new HandlerMapping(bean,method);
                        handlerMappings.put(url_tem,handlerMapping);
                    }
                }
            }
        }
    }

    private Object[] searchParam(Method method, HttpServletRequest req, HttpServletResponse resp) {
        //获取方法上的参数类型并生成参数
        Class[] parameterTypes = method.getParameterTypes();
        Object[] args = new Object[parameterTypes.length];
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        for (int j=0;j fieldType = field.getType();
                        field.setAccessible(true);
                        if(fieldType == String.class){
                            if (!isEmpty(req.getParameter(filed_name))){
                                try {
                                    field.set(o,req.getParameter(filed_name));
                                } catch (IllegalAccessException e) {
                                    e.printStackTrace();
                                    System.out.println("实体类参数注入失败");
                                }
                            }
                        }else if (fieldType == Integer.class){
                            if (!isEmpty(req.getParameter(filed_name))){
                                try {
                                    String parameter1 = req.getParameter(filed_name);
                                    Integer i = Integer.parseInt(parameter1);
                                    field.set(o,i);
                                } catch (IllegalAccessException e) {
                                    e.printStackTrace();
                                    System.out.println("实体类参数注入失败");
                                }
                            }
                        }
                    }
                    args[j] = o;
            }
        }
        return args;
    }

    private RequestParam getRequestParamAnnotationByIndex(Annotation[][] parameterAnnotations,int j) {
        for (Annotation annotation :parameterAnnotations[j]){
            Class type = annotation.annotationType();
            if ("RequestParam".equals(type.getSimpleName())){
                return (RequestParam) annotation;
            }
        }
        return null;
    }
    //获取参数注解上索引对应参数的RequestMapping注解


    private void initWired() {
        SpringMvcBeanFactory beanFactory = (SpringMvcBeanFactory) SpringMvcBeanFactory.getBeanFactory();
        Set set = beanFactory.keySet();
        for (String key:set){
            Object bean = beanFactory.getBean(key);
            Field[] fields = bean.getClass().getDeclaredFields();
            if (fields.length>0){
                for (Field field:fields){
                    if (field.isAnnotationPresent(AutoWired.class)){
                        String value = field.getAnnotation(AutoWired.class).value();
                        field.setAccessible(true);
                        try {
                            if (!"".equals(value)) {
                                field.set(bean, beanFactory.getBean(value));
                            }

                            field.set(bean, beanFactory.getBean(field.getName()));
                        }
                        catch (IllegalAccessException e) {
                            e.printStackTrace();
                            System.out.println("bean注入失败");
                        }
                    }
                }
            }
        }
    }
    private void initBeans() {
        //获取bean工厂
        BeanFactory beanFactory = SpringMvcBeanFactory.getBeanFactory();
        for (String className:classNameList){
            Class bean = null;
            try {
                bean = Class.forName(className);
            } catch (ClassNotFoundException e) {
                System.out.println("没有找到类");
            }
            if (bean.isAnnotationPresent(Controller.class)||bean.isAnnotationPresent(Service.class)){
                Object o = null;
                try {
                    o = bean.newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                    System.out.println("生成实例化对象失败");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                beanFactory.setBean(o);
            }
            if (bean.isAnnotationPresent(Component.class)){
                Component annotation = (Component) bean.getAnnotation(Component.class);
                Object o = null;
                try {
                    o = bean.newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                if ("".equals(annotation.value())){
                    beanFactory.setBean(o);
                }else {
                    String name = annotation.value();
                    beanFactory.setBeanByName(name,o);
                }
            }
        }
    }

    private void initClassNameList() throws FileNotFoundException {
        //获取配置文件
        URL resource = DispatcherServlet.class.getClassLoader().getResource("application.yaml");
        Yaml yaml = new Yaml();
        Map load = (Map) yaml.load(new FileInputStream(resource.getFile()));
        Map application = (Map) load.get("springmvc");
        Map scanPackage_map = (Map) application.get("application");
        String scanPackage = (String) scanPackage_map.get("scanPackage");
        scanClassList(scanPackage);
    }

    private void scanClassList(String scanPackage) {
        URL url = DispatcherServlet.class.getClassLoader().getResource(scanPackage.replaceAll("\\.","/"));
        File file = new File(url.getFile());
        File[] files = file.listFiles();
        for (File file_path:files){
            if (file_path.isDirectory()){
                scanClassList(scanPackage+"."+file_path.getName());
            }else if (file_path.getName().endsWith(".class")){
                classNameList.add(scanPackage+"."+file_path.getName().replace(".class", ""));
            }
        }
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String requestURI = req.getRequestURI();
        HandlerMapping handlerMapping = handlerMappings.get(requestURI);
        if (handlerMapping==null){
            resp.getWriter().write("404 NOT FOUND");
            return;
        }
        Object instance = handlerMapping.getController();
        Method method = handlerMapping.getMethod();
        Object[] args = searchParam(method, req, resp);
        httpRequestHandler.invoke(instance,method,args,req,resp);
    }
    //判断字符串是否为空
    public static boolean isEmpty(String s){
        return (!"".equals(s)&&s!=null)?false:true;
    }
}

BeanFactory bean工厂接口

package com.ji.spring.core.bean;

public interface BeanFactory {
    void setBean(Object o);
    Object getBean(String beanName);
    void setBeanByName(String str,Object o);
}

SpringMvcBeanFactory工厂类

package com.ji.spring.core.bean;

import java.util.HashMap;

public class SpringMvcBeanFactory extends HashMap implements BeanFactory{

    //单例
    private static BeanFactory springMvcBeanFactory;
    private void setSpringMvcBeanFactory(){};
    public synchronized static BeanFactory getBeanFactory(){
        if (springMvcBeanFactory == null){
            springMvcBeanFactory = new SpringMvcBeanFactory();
        }
        return springMvcBeanFactory;
    }
    @Override
    public void setBean(Object object) {
        String name = object.getClass().getSimpleName();
        name = firstWordToLowerCase(name);
        this.put(name, object);
    }
    @Override
    public void setBeanByName(String name,Object object){
        this.put(name, object);
    }


    @Override
    public Object getBean(String beanName) {
        return this.get(beanName);
    }
    //首字母小写
    public  static  String firstWordToLowerCase(String str){
        String str_ = str.substring(0,1).toLowerCase()+str.substring(1);
        return str_;
    }
}

handler处理器接口

public interface Handler {
    void invoke(Object instance, Method method, Object[] args, HttpServletRequest req, HttpServletResponse resp) throws Exception;
}

HttpRequestHandler处理器类

package com.ji.spring.springmvc.servlet;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

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

public class HttpRequestHandler implements Handler{

    public void invoke(Object instance, Method method, Object[] args, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Object invoke = null;
        Class type = method.getReturnType();
        try {
                invoke = method.invoke(instance, args);

        } catch (IllegalAccessException e) {
            e.printStackTrace();
            System.out.println("方法未声明public");
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        if (invoke!=null){
            ObjectMapper objectMapper = new ObjectMapper();
            String s = objectMapper.writeValueAsString(invoke);
            resp.setHeader("Content-Type", "application/json;charset=UTF-8");
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().write(s);
        }
    }

}

HandlerMapping处理器映射类

package com.ji.spring.springmvc.servlet;

import java.lang.reflect.Method;


public class HandlerMapping {
    private Object controller;
    private Method method;

    public HandlerMapping() {
    }

    public HandlerMapping(Object controller,Method method) {
        this.controller = controller;
        this.method = method;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Object getController() {
        return controller;
    }

    public void setController(Object controller) {
        this.controller = controller;
    }

}

你可能感兴趣的:(手写springmvc,手写bean自动注入)