博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手写springmvc框架
阅读量:6511 次
发布时间:2019-06-24

本文共 7821 字,大约阅读时间需要 26 分钟。

  hot3.png

一、定义注解

package com.ayo.annotation;import java.lang.annotation.*;/** * 模拟springmvc的@Controller注解 */@Documented //JAVADOC@Target(ElementType.TYPE)   //作用于类上@Retention(RetentionPolicy.RUNTIME) //限制Annotation的生命周期,我这里自定义的注解显然需要运行时保留public @interface Controller {    /**     * 作用于该类上的注解有一个value属性,说白了就是Controller的名称     * @return     */    public String value();}
package com.ayo.annotation;import java.lang.annotation.*;/** * @Qualifier提供依赖注入 */@Documented@Target(ElementType.FIELD)  //作用于字段上,实现注入@Retention(RetentionPolicy.RUNTIME)public @interface Qualifier {    public String value();}
package com.ayo.annotation;import java.lang.annotation.*;/** * dao层注解 */@Documented@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Repository {    public String value();}
package com.ayo.annotation;import java.lang.annotation.*;/** * RequestMapping提供url地址处理映射 */@Documented@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface RequestMapping {    public String value();}
package com.ayo.annotation;import java.lang.annotation.*;/** * 业务层注解 */@Documented@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Service {    public String value();}

二、写一个DispatcherServlet

package com.ayo.servlet;import com.ayo.annotation.*;import com.ayo.controller.UserController;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.annotation.WebInitParam;import javax.servlet.annotation.WebServlet;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.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@WebServlet(name = "dispatcherServlet", urlPatterns = "/*", loadOnStartup = 1, initParams = {
@WebInitParam(name = "base-package", value = "com.ayo")})public class DispatcherServlet extends HttpServlet{ //扫描的基包 private String basePackage = ""; //基包下面所有的带包路径权限定类名 private List
packageNames = new ArrayList
(); //注解实例化,注解上的名称:实例化对象 private Map
instanceMap = new HashMap
(); //带包路径的权限定名称:注解上的名称 private Map
nameMap = new HashMap
(); //url地址和方法的映射关系,springmvc就是方法调用链 private Map
urlMethodMap = new HashMap
(); //Method和权限定类名映射关系, 主要是为了通过method找到该方法的对象利用反射执行 private Map
methodPackageMap = new HashMap
(); @Override public void init(ServletConfig config) throws ServletException { basePackage = config.getInitParameter("base-package"); try { //扫描基包得到全部的带包路径权限定名 scanBasePackage(basePackage); //把带有@Controller/@Service/@Repository的类实例化放入map中,key为注解上的名字 instance(packageNames); //Spring IOC注入 springIOC(); //完成URL地址与方法的映射关系 handleUrlMethodMap(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } /** * 扫描基包 * @param basePackage */ private void scanBasePackage(String basePackage){ //注意为了得到基包下面的URL路径,需要对basePackage包转换,将.替换为/ URL url = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/")); File basePackageFile = new File(url.getPath()); System.out.println("scan:" + basePackageFile); File[] childFiles = basePackageFile.listFiles(); for (File file : childFiles){ if (file.isDirectory()){ scanBasePackage(basePackage + "." + file.getName()); }else if (file.isFile()){ packageNames.add(basePackage + "." + file.getName().split("\\.")[0]); } } } /** * 实例化 * @param packageNames * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ private void instance(List
packageNames) throws ClassNotFoundException, IllegalAccessException, InstantiationException { if (packageNames.size() < 1){ return; } for (String string : packageNames){ Class
c = Class.forName(string); if(c.isAnnotationPresent(Controller.class)){ Controller controller = c.getAnnotation(Controller.class); String controllerName = controller.value(); instanceMap.put(controllerName, c.newInstance()); nameMap.put(string, controllerName); System.out.println("Controller:" + string + ", value:" + controller.value()); }else if (c.isAnnotationPresent(Service.class)){ Service service = c.getAnnotation(Service.class); String serviceName = service.value(); instanceMap.put(serviceName, c.newInstance()); nameMap.put(string, serviceName); System.out.println("Service:" + string + ",value:" + service.value()); }else if (c.isAnnotationPresent(Repository.class)){ Repository repository = c.getAnnotation(Repository.class); String repositoryName = repository.value(); instanceMap.put(repositoryName, c.newInstance()); nameMap.put(string, repositoryName); System.out.println("Repository:" + string + ",value:" + repository.value()); } } } /** * 依赖注入 * @throws IllegalAccessException */ private void springIOC() throws IllegalAccessException { for (Map.Entry
entry : instanceMap.entrySet()){ Field[] fields = entry.getValue().getClass().getDeclaredFields(); for (Field field : fields){ if (field.isAnnotationPresent(Qualifier.class)){ String name = field.getAnnotation(Qualifier.class).value(); field.setAccessible(true); field.set(entry.getValue(), instanceMap.get(name)); } } } } /** * url映射处理 * @throws ClassNotFoundException */ private void handleUrlMethodMap() throws ClassNotFoundException { if (packageNames.size() < 1){ return; } for (String string : packageNames){ Class
c = Class.forName(string); if (c.isAnnotationPresent(Controller.class)){ Method[] methods = c.getMethods(); StringBuffer baseUrl = new StringBuffer(); if (c.isAnnotationPresent(RequestMapping.class)){ RequestMapping requestMapping = c.getAnnotation(RequestMapping.class); baseUrl.append(requestMapping.value()); } for (Method method : methods){ if (method.isAnnotationPresent(RequestMapping.class)){ RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); baseUrl.append(requestMapping.value()); urlMethodMap.put(baseUrl.toString(), method); methodPackageMap.put(method, string); } } } } } @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 uri = req.getRequestURI(); String contextPath = req.getContextPath(); String path = uri.replaceAll(contextPath, ""); Method method = urlMethodMap.get(path); if (method != null){ //通过method拿到controller对象,准备反射执行 String packageName = methodPackageMap.get(method); String controllerName = (String)nameMap.get(packageName); //拿到controller对象 UserController userController = (UserController)instanceMap.get(controllerName); try { method.setAccessible(true); method.invoke(userController); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }}

三、写个controller、service、dao

package com.ayo.controller;import com.ayo.annotation.Controller;import com.ayo.annotation.Qualifier;import com.ayo.annotation.RequestMapping;import com.ayo.service.UserService;@Controller("userController")@RequestMapping("/user")public class UserController {    @Qualifier("userServiceImpl")    private UserService userService;    @RequestMapping("/insert")    public void insert(){        userService.insert();    }}
package com.ayo.service;public interface UserService {    public void insert();}
package com.ayo.dao;public interface UserDao {    public void insert();}

参考自:微信公众号--java进阶架构师。

 

转载于:https://my.oschina.net/ayo123/blog/3018702

你可能感兴趣的文章
异步函数
查看>>
jQuery 选择器
查看>>
Openstack的vnc界面定制
查看>>
软考 2018年下半年卷 错题知识点记录
查看>>
仿网易邮箱5.0版UI
查看>>
winsow xp不能安装软件, 提示"中断" 是因为设置了 软件限制策略
查看>>
as3调用外部应用程序 as调用外部exe文件as3调用bat文件 未测试
查看>>
jQuery清空标签内容--防止内存泄露
查看>>
关于 HandlerMethodArgumentResolver 类 以及 WebArgumentResolver 类 自定义解析参数
查看>>
30个php操作redis常用方法代码例子
查看>>
如何上传本地代码到码云
查看>>
Dubbo整合SpringBoot
查看>>
帝国CMS Table '***.phome_ecms_news_data_' doesn't exist
查看>>
dotnet/coreclr
查看>>
百度广告联盟api probuf协议对接
查看>>
【转】 集群、负载均衡、分布式的区别与联系
查看>>
Java自定义异常类以及异常拦截器
查看>>
x264预设类参数详解
查看>>
这样就算会了PHP么?-10
查看>>
css基础之 联网使用bootstrap
查看>>