用spring mvc框架的模拟实现来学习反射和注解

来源:互联网 发布:tensorflow 人脸检测 编辑:程序博客网 时间:2024/04/27 08:35

1、springmvc架构
这里写图片描述

2、相应注解详解
2.1、Controller注解 Controlle类上面的注解
2.2、Service注解 业务层对象上面的注解
2.33、Qualitify注解 在controller层里面,扫面含有此注解的字段,然后根据字段注入Service bean对象
2.44、HandlerMapping注解 处理方法上面的注解

3、编写流程(这里我们主要写框架的核心部分,所以不能做到像springmvc那样详尽):

1、先定义上面四个注解
2、全包扫描(在init()方法里面完成)
3、将扫描到含有Controller和service注解的类保存到一个map集合(classMap),key为当前注解的value值,value为当前类的实例对象。
4、将扫描到的Qualitify注解的字段,注入相应的值,值为classMap.get(key),其中key的值是扫描到Qualitify的value值。因为此key就是对应service注解的实例对象。
5、最后将要扫描Controller注解,然后在扫描handlerMapping注解,这一步为了构建请求地址,并且通过请求地址可以找到对应的方法的method对象和Controller注解对应类的实例对象。
首先,找到controller对象,通过集合(classmap)调用get(controller注解的value)方法得到对应的Controller类的实例对象,接下来扫描的是方法上面的注解,如果方法上面有HandlerMapping注解,然后构建ServletContext(项目名称,例如/上下文路径/资源具体路径)后面的url,如何构建呢?即Controller注解的value值加上HandllerMapping注解的value值,然后,在将此url作为key,然后扫描到的方法的Method对象作为value保存到一个Map(methodMap)集合,并且将此url作为key,controller注解对应的实例对象作为value,保存在classMap集合中。
6、此时就可以通过请求的url后面的路径映射到一个相应的method对象并且得到相应的controller类的实例。

代码部分:
包结构:
这里写图片描述

代码:

/** * Controller注解 *  * */@Target({ElementType.TYPE})//作用在类上@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Controller {    String value() default "";}
/** * Quatifier注解 *  * */@Target({ElementType.FIELD})//作用在字段上@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Quatifier {    String value() default "";}
/** * RequestMapping注解 *  * */@Target({ElementType.METHOD})//作用在方法上@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface RequestMapping {    String value() default "";}
/** * Servic注解 *  * */@Target({ElementType.TYPE})//作用在类上@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Service {    String value() default "";}
@Controller("SpringMvcController")public class SpringMvcController {    /**     * 把UserService实例对象注入进来     * */    @Quatifier("UserServiceImpl")    private UserService us;    @RequestMapping("insert.action")      public String insert(HttpServletRequest request, HttpServletResponse response, String param) {          us.insert(null);          try {            request.getRequestDispatcher("/index.jsp").forward(request, response);        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (ServletException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return null;      }      @RequestMapping("delete.action")      public String delete(HttpServletRequest request, HttpServletResponse response, String param) {           us.delete(null);          return null;      }      @RequestMapping("update.action")      public String update(HttpServletRequest request, HttpServletResponse response, String param) {           us.update(null);          return null;      }      @RequestMapping("select.action")      public String select(HttpServletRequest request, HttpServletResponse response, String param) {           us.select(null);          return null;      }  }
public interface UserService {     int insert(Map map);       int delete(Map map);       int update(Map map);       int select(Map map);  }
@Service("UserServiceImpl")public class UserServiceImpl implements UserService{    @Override    public int insert(Map map) {        System.out.println("调用了插入方法");        return 0;    }    @Override    public int delete(Map map) {        System.out.println("调用了删除方法");        return 0;    }    @Override    public int update(Map map) {        System.out.println("调用了更新方法");        return 0;    }    @Override    public int select(Map map) {        System.out.println("调用了查询方法");        return 0;    }}

核心控制器,只需在web.xml文件中配置它就可以了。

public class DispatcherServlet extends HttpServlet{    private static final long serialVersionUID = 1L;    //保存扫描到的所有包名     List<String> packageNames = new ArrayList<String>();      //所有类的实例,key是注解的value,value是注解对应的类的实例对象    Map<String, Object> instanceMap = new HashMap<String, Object>();    /**     * 处理器映射到的方法对象集合     * key是地址栏上项目上下文后面接上的地址     * value是对应的方法对象也就是Method对象     * */    Map<String, Object> handerMap = new HashMap<String, Object>();    @Override    public void init() throws ServletException {        //扫描包中的文件         scanPackage("com.bjsxt.springmvc");        try {            //将注解和对应的实例对象保存在集合当中            filterAndInstance();        } catch (Exception e) {            e.printStackTrace();        }        //建立映射关系        handderMap();        //依赖注入        ioc();    }    //建立映射关系    private void handderMap() {        if (instanceMap.size() <= 0) {            return;        }        for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {            //判断类上是否有Controller注解,在做下一步操作            if (entry.getValue().getClass().isAnnotationPresent(Controller.class)) {                Controller controller = (Controller)entry.getValue().getClass().getAnnotation(Controller.class);                String cvalue = controller.value();                //拿到controller注解对应的对象                Object ctlObj = instanceMap.get(cvalue);                Method[] methods = entry.getValue().getClass().getMethods();                for (Method method : methods) {                    //迭代方法,判断方法上面是否有requestMapping注解                    if (method.isAnnotationPresent(RequestMapping.class)) {                        String value = ((RequestMapping)method.getAnnotation(RequestMapping.class)).value();                        String urlKey = "/"+cvalue+"/"+value;                        //将地址和方法对象建立关系                        handerMap.put(urlKey, method);                        //将地址和对象也建立映射关系。                        instanceMap.put(urlKey, ctlObj);                    }else{                        continue;                    }                }            }        }    }    //属性的注入    private void ioc() {        //如果集合为空,直接跳出此方法的执行        if (instanceMap.isEmpty()) {            return;        }        for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {            Field[] fields = entry.getValue().getClass().getDeclaredFields();            //迭代所有注解            for (Field field : fields) {                field.setAccessible(true);                //判断字段上面是否有Quatifier注解                if (field.isAnnotationPresent(Quatifier.class)) {                    //拿到注解                    Quatifier quatifier = field.getAnnotation(Quatifier.class);                    //拿到注解对应的value值                    String value = quatifier.value();                    try {                        //注入相应的值                        field.set(entry.getValue(),instanceMap.get(value));                    } catch (IllegalArgumentException e) {                        e.printStackTrace();                    } catch (IllegalAccessException e) {                        e.printStackTrace();                    }                }            }        }    }    /**     * 扫描包下的所有文件     * */    private void scanPackage(String packagePath) {        String loc = "/"+replaceTo(packagePath);        System.out.println("扫描的地址:"+loc);        URL url = this.getClass().getClassLoader().getResource(loc);        System.out.println("url"+url);        String filePath = url.getFile();        File f = new File(filePath);        String[] fileList = f.list();        //迭代fileList        for (String path : fileList) {            File eachFile = new File(filePath+"/"+path);            //判断是否是一个目录            if (eachFile.isDirectory()) {                //到这里说明他是一个目录,我们还需要对子目录进行扫描                scanPackage(packagePath+"."+eachFile.getName());            }else{                 //获得加后缀名的完整包名                String packName = packagePath+"."+eachFile.getName();                //去除文件后缀名,可得到包名+类名                String pName = packName.substring(0, packName.lastIndexOf(".class"));                packageNames.add(pName);                System.out.println("所有的包名加类名:"+packageNames);            }        }    }    //扫描     private void filterAndInstance()throws Exception {           if (packageNames.size() <=0) {            return;        }         for (String className : packageNames) {             //加载实例            Class<?> cName = Class.forName(className.replace(".class", "").trim());            //判断是否有Controller注解            if (cName.isAnnotationPresent(Controller.class)) {                Object instance = cName.newInstance();                //获得注解对象                Controller controller = (Controller) cName.getAnnotation(Controller.class);                String key = controller.value();                //把注解的value的值作为key,对应的实例对象作为value                instanceMap.put(key, instance);                //判断是否有Service注解            }else if(cName.isAnnotationPresent(Service.class)){                Object instance = cName.newInstance();                Service service = (Service)cName.getAnnotation(Service.class);                String key = service.value();                instanceMap.put(key, instance);            }            else{                continue;            }        }     }    //将所有的 . 转换成 /    private String replaceTo(String packagePath) {        return packagePath.replaceAll("\\.", "/");    }    @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 url = req.getRequestURI();        System.out.println("uri的路径"+url);        //获得上下文路径,通常是项目名        String context = req.getContextPath();        //去掉上下文        String path = url.replace(context, "");        System.out.println(path);        Method m = (Method) handerMap.get(path);        System.out.println(m);        //打印地址栏上去掉contextPath之后的url        System.out.println(path);        try {            //获得路径对应到的controller对象            Object obj = instanceMap.get(path);            System.out.println(obj);            //通过反射调用方法            m.invoke(obj, req,resp,null);        } catch (IllegalAccessException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalArgumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (InvocationTargetException e) {            // TODO Auto-generated catch block            e.printStackTrace();         }    }}

web.xml

    <servlet>        <servlet-name>DispatcherServlet</servlet-name>        <servlet-class>com.bjsxt.springmvc.servlet.DispatcherServlet</servlet-class>    </servlet>    <servlet-mapping>        <servlet-name>DispatcherServlet</servlet-name>        <url-pattern>*.action</url-pattern>    </servlet-mapping>
阅读全文
0 0
原创粉丝点击