非常粗糙的模仿spring扫描注解,先定义三个注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Controller { }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RequestMapping { String value(); }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Service { }
在监听中进行扫描并加入到context容器之中
public void contextInitialized(ServletContextEvent servletContextEvent) { //获取容器配置并初始化 ServletContext servletContext = servletContextEvent.getServletContext(); String initParameter = servletContext.getInitParameter("context"); Context.setContextPath(initParameter); //首次加载context Context context = Context.getContext(); //加载所有controller AnnotationScanner.getAnnotationScanner().scan(Controller.class); //加载所有service AnnotationScanner.getAnnotationScanner().scan(Service.class); //加载所有配置扫描的bean AnnotationScanner.getAnnotationScanner().beanConfigScan(); //扫描requestmapping方法 AnnotationScanner.getAnnotationScanner().scan(RequestMapping.class); }
扫描类
public class AnnotationScanner { private final String CONTROLLER_SCAN="controller-scan"; private final String SERVICE_SCAN="service-scan"; private final String BEAN_SCAN="bean-scan"; private static AnnotationScanner annotationScanner = new AnnotationScanner(); private AnnotationScanner(){} public static AnnotationScanner getAnnotationScanner(){ return annotationScanner; } public List scanByAnnotation(String path,Class anonotation){ List annotationClazz = new LinkedList<Class>(); try { URL resource = AnnotationScanner.class.getClassLoader().getResource(path.replaceAll("\\.", "/")); File file = new File(resource.toURI()); File[] files = file.listFiles(new FileFilter() { @Override public boolean accept(File f) { if(f.isDirectory()){ scanByAnnotation(path,anonotation); }else{ try { String classPath = path + "." + f.getName().replaceAll("\\.class", ""); Class<?> aClass = AnnotationScanner.class.getClassLoader().loadClass(classPath); if (aClass.isAnnotationPresent(anonotation)){ annotationClazz.add(aClass); } }catch (Exception e){ e.printStackTrace(); } } return false; } }); }catch (Exception e){ e.printStackTrace(); } return annotationClazz ; } public List scanByBasePackage(String path){ List annotationClazz = new LinkedList<Class>(); try { URL resource = AnnotationScanner.class.getClassLoader().getResource(path.replaceAll("\\.", "/")); File file = new File(resource.toURI()); File[] files = file.listFiles(new FileFilter() { @Override public boolean accept(File f) { if(f.isDirectory()){ scanByBasePackage(path); }else{ try { String classPath = path + "." + f.getName().replaceAll("\\.class", ""); Class<?> aClass = AnnotationScanner.class.getClassLoader().loadClass(classPath); annotationClazz.add(aClass); }catch (Exception e){ e.printStackTrace(); } } return false; } }); }catch (Exception e){ e.printStackTrace(); } return annotationClazz ; } public Map getBeansMap(List<Class> list){ Map map = new HashMap<String ,Object >(); list.forEach(l->{ try { Object o = l.newInstance(); map.put(l.getName(),o); } catch (Exception e) { e.printStackTrace(); } }); return map ; } //根据class进行扫描 public void scan(Class clazz){ Context context = Context.getContext(); if(clazz.getName().equalsIgnoreCase(Controller.class.getName())){ List list = AnnotationScanner.getAnnotationScanner().scanByAnnotation((String) context.getElement(CONTROLLER_SCAN), Controller.class); context.addElement("controller",AnnotationScanner.getAnnotationScanner().getBeansMap(list)); } if(clazz.getName().equalsIgnoreCase(Service.class.getName())){ List list = AnnotationScanner.getAnnotationScanner().scanByAnnotation((String) context.getElement(SERVICE_SCAN), Service.class); context.addElement("service",AnnotationScanner.getAnnotationScanner().getBeansMap(list)); } if (clazz.getName().equalsIgnoreCase(RequestMapping.class.getName())){ scanRequestMapping(); } } public void scan(String basePath ){ Context context = Context.getContext(); List list = AnnotationScanner.getAnnotationScanner().scanByBasePackage(basePath); Map beansMap = getBeansMap(list); context.addElement("bean",beansMap); } //扫描bean public void beanConfigScan( ){ String basePath = (String) Context.getContext().getElement(BEAN_SCAN); scan(basePath); } //扫描所有被RequestMapping注解的方法,并且加入到Context容器里面(默认必须标记在Controller类下) public void scanRequestMapping(){ Map map = (Map)Context.getContext().getElement("controller"); System.out.println(map); Map requestmapping = new HashMap<String ,Object >(); map.forEach((k,v)->{ //获取类下的所有方法 Method[] declaredMethods = v.getClass().getDeclaredMethods(); //获取类上的注解并且遍历RequestMapping注解,有的话,加入到map里面 for(Method method:declaredMethods){ if (method.isAnnotationPresent(RequestMapping.class)){ RequestMapping annotation = method.getAnnotation(RequestMapping.class); //ReuqestMapping上注解的路径 String value = annotation.value(); ReflectBean reflectBean = new ReflectBean(value, v, method); //加入到mapping map 中 requestmapping.put(value,reflectBean); } } //把扫描到的注解方法加入到context中 Context.getContext().addElement("requestmapping",requestmapping); }); } }
测试效果,项目要做登录,先定义一个登录接口进行测试
@Controller public class GlobalController { //实现自动注入 need to do @RequestMapping("login") public Object login(HttpServletRequest request , HttpServletResponse response){ String name = request.getParameter("name"); return GlobalResponse.ok(new HashMap<>(),"登录成功"); } }
这个是web.xml下配置的唯一一个servlet,反射调用requestmapping中对应path的方法
public class DispatcherServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doRequest(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doRequest(req, resp); } protected void doRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ Context context = Context.getContext(); Map requestmapping = (Map)context.getElement("requestmapping"); System.out.println(requestmapping); //找到对应的requestmapping String action = request.getParameter("action"); if(MyUtils.haskey(action,requestmapping)){ ReflectBean reflectBean = (ReflectBean) requestmapping.get(action); try { Object invoke = reflectBean.getMethod().invoke(reflectBean.getObject(), request, response); writeAndClose(response,JsonUtils.getJson(invoke)); }catch (Exception e){ e.printStackTrace(); } }else{ writeAndClose(response, JsonUtils.getJson(GlobalResponse.nok("拒绝访问"))); } } private void writeAndClose(HttpServletResponse response , String json) throws IOException { PrintWriter writer = response.getWriter(); writer.write(json); writer.close(); } }
ajax访问测试
var urll = "http://10.10.12.150:8080/door_war/action";
$.ajax({
type:"post",
//xhrFields:{withCredentials:true},
url:urll,
data:{
action:"login",
name:'test',
password:'a123456'
},
success:function(res){
console.log(res)
}
});
前端返回
{issuccess: true, message: "登录成功", exception: null, data: {…}, recordcount: 0}
基本上算是成功了
来源:oschina
链接:https://my.oschina.net/u/3702441/blog/3208969