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

手写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

手写springmvc框架ioc容器(简易版),实现实体类参数接收,并实现基于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;}@Overridepublic 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配置文件
手写springmvc框架ioc容器(简易版),实现实体类参数接收,并实现基于yaml配置文件

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配置文件

基本包

在这里插入图片描述

下面是相关代码,具体项目可以到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<parameterTypes.length;j++){     String simpleName = parameterTypes[j].getSimpleName();     switch (simpleName){  case "HttpServletRequest":      args[j] = req;      break;  case "HttpServletResponse":      args[j]=resp;      break;  case "String":      RequestParam requestParam = getRequestParamAnnotationByIndex(parameterAnnotations,j);      String param_Name = requestParam.value();      String str = req.getParameter(param_Name);      if (!isEmpty(str)){   args[j] = str;      }      break;  case "Integer":      RequestParam requestParam1 = getRequestParamAnnotationByIndex(parameterAnnotations,j);      String param_Name1 = requestParam1.value();      String parameter = req.getParameter(param_Name1);      if (!isEmpty(parameter)){   args[j] = (Integer)Integer.parseInt(parameter);      }      break;  default:      for (String s:classNameList){   if (s.endsWith(simpleName)){simpleName = s;   }      }      Class t = null;      try {    t = Class.forName(simpleName);      } catch (ClassNotFoundException e) {   e.printStackTrace();   System.out.println("未找到参数实体类");      }      Object o = null;      try {   o = t.newInstance();      } catch (InstantiationException e) {   e.printStackTrace();      } catch (IllegalAccessException e) {   e.printStackTrace();   System.out.println("实体类实例化失败");      }      Field[] declaredFields = t.getDeclaredFields();      for (Field field : declaredFields){   String filed_name = field.getName();   Class 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;    }}