资料:
(1)注解Annotation实现原理与自定义注解例子:
https://www.cnblogs.com/acm-bingzi/p/javaAnnotation.html
我的:
步骤一:自定义注解
/src/com/test/annotation/Controller.java
package com.test.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE)//表示该自定义注解作用于类 @Retention(RetentionPolicy.RUNTIME)//表示运行期也保留该自定义注解,因此可以使用反射机制读取该注解的信息 @Documented//表示是否将注解信息添加在java文档中 public @interface Controller {}
/src/com/test/annotation/RequestMapping.java
package com.test.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE})//表示该自定义注解作用于类和方法 @Retention(RetentionPolicy.RUNTIME)//表示运行期也保留该自定义注解,因此可以使用反射机制读取该注解的信息 @Documented//表示是否将注解信息添加在java文档中 public @interface RequestMapping { //映射名 String name() default ""; //路径名集合 String value() default "";//参数成员只能用byte,short,char,int,long,float,double,boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组 //提交方式集合 RequestMethod method() default RequestMethod.GET; }
/src/com/test/annotation/RequestMethod.java
package com.test.annotation; public enum RequestMethod { GET, POST, PUT, DELETE; }
步骤二:注解处理类
/src/com/test/annotation/ClassUtil.java
package com.test.annotation; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class ClassUtil { /** * 通过包名获取包内所有类 * * @param pkg * @return */ public static List<Class<?>> getAllClassByPackageName(Package pkg) { String packageName = pkg.getName(); // 获取当前包下以及子包下所以的类 List<Class<?>> returnClassList = getClasses(packageName); return returnClassList; } /** * 通过接口名取得某个接口下所有实现这个接口的类 */ public static List<Class<?>> getAllClassByInterface(Class<?> c) { List<Class<?>> returnClassList = null; if (c.isInterface()) { // 获取当前的包名 String packageName = c.getPackage().getName(); // 获取当前包下以及子包下所以的类 List<Class<?>> allClass = getClasses(packageName); if (allClass != null) { returnClassList = new ArrayList<Class<?>>(); for (Class<?> cls : allClass) { // 判断是否是同一个接口 if (c.isAssignableFrom(cls)) { // 本身不加入进去 if (!c.equals(cls)) { returnClassList.add(cls); } } } } } return returnClassList; } /** * 取得某一类所在包的所有类名 不含迭代 */ public static String[] getPackageAllClassName(String classLocation, String packageName) { // 将packageName分解 String[] packagePathSplit = packageName.split("[.]"); String realClassLocation = classLocation; int packageLength = packagePathSplit.length; for (int i = 0; i < packageLength; i++) { realClassLocation = realClassLocation + File.separator + packagePathSplit[i]; } File packeageDir = new File(realClassLocation); if (packeageDir.isDirectory()) { String[] allClassName = packeageDir.list(); return allClassName; } return null; } /** * 从包package中获取所有的Class * * @param pack * @return */ public static List<Class<?>> getClasses(String packageName) { // 第一个class类的集合 List<Class<?>> classes = new ArrayList<Class<?>>(); // 是否循环迭代 boolean recursive = true; // 获取包的名字 并进行替换 String packageDirName = packageName.replace('.', '/'); // 定义一个枚举的集合 并进行循环来处理这个目录下的things Enumeration<URL> dirs; try { dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); // 循环迭代下去 while (dirs.hasMoreElements()) { // 获取下一个元素 URL url = dirs.nextElement(); // 得到协议的名称 String protocol = url.getProtocol(); // 如果是以文件的形式保存在服务器上 if ("file".equals(protocol)) { // 获取包的物理路径 String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); // 以文件的方式扫描整个包下的文件 并添加到集合中 findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); } else if ("jar".equals(protocol)) { // 如果是jar包文件 // 定义一个JarFile JarFile jar; try { // 获取jar jar = ((JarURLConnection) url.openConnection()).getJarFile(); // 从此jar包 得到一个枚举类 Enumeration<JarEntry> entries = jar.entries(); // 同样的进行循环迭代 while (entries.hasMoreElements()) { // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 JarEntry entry = entries.nextElement(); String name = entry.getName(); // 如果是以/开头的 if (name.charAt(0) == '/') { // 获取后面的字符串 name = name.substring(1); } // 如果前半部分和定义的包名相同 if (name.startsWith(packageDirName)) { int idx = name.lastIndexOf('/'); // 如果以"/"结尾 是一个包 if (idx != -1) { // 获取包名 把"/"替换成"." packageName = name.substring(0, idx).replace('/', '.'); } // 如果可以迭代下去 并且是一个包 if ((idx != -1) || recursive) { // 如果是一个.class文件 而且不是目录 if (name.endsWith(".class") && !entry.isDirectory()) { // 去掉后面的".class" 获取真正的类名 String className = name.substring(packageName.length() + 1, name.length() - 6); try { // 添加到classes classes.add(Class.forName(packageName + '.' + className)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } } } catch (IOException e) { e.printStackTrace(); } } } } catch (IOException e) { e.printStackTrace(); } return classes; } /** * 以文件的形式来获取包下的所有Class * * @param packageName * @param packagePath * @param recursive * @param classes */ private static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, List<Class<?>> classes) { // 获取此包的目录 建立一个File File dir = new File(packagePath); // 如果不存在或者 也不是目录就直接返回 if (!dir.exists() || !dir.isDirectory()) { return; } // 如果存在 就获取包下的所有文件 包括目录 File[] dirfiles = dir.listFiles(new FileFilter() { // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) public boolean accept(File file) { return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); } }); // 循环所有文件 for (File file : dirfiles) { // 如果是目录 则继续扫描 if (file.isDirectory()) { findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes); } else { // 如果是java类文件 去掉后面的.class 只留下类名 String className = file.getName().substring(0, file.getName().length() - 6); try { // 添加到集合中去 classes.add(Class.forName(packageName + '.' + className)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } }
Action封装类
/src/com/test/annotation/MyAction.java
package com.test.annotation; import java.lang.reflect.Method; public class MyAction { private String path;//路径 private RequestMethod requestMethod;//提交方式 private Class<?> clazz;//类 private Method method;//方法 public MyAction(String path,RequestMethod requestMethod,Class<?> clazz,Method method){ this.path = path; this.requestMethod = requestMethod; this.clazz = clazz; this.method = method; } @Override public String toString() { return "MyAction {\"path\":" + path + ", \"requestMethod\":" + requestMethod + ", \"clazz\":" + clazz + ", \"method\":" + method + "}"; } //setter和getter }
注解处理器
/src/com/test/annotation/ActionsUtil.java
package com.test.annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /* * 注解处理器 */ public class ActionsUtil { //Controller注解类 private static final Class<Controller> CONTROLLER = Controller.class; //RequestMapping注解类 private static final Class<RequestMapping> REQUEST_MAPPING = RequestMapping.class; //映射集合 private static List<MyAction> actionList=new ArrayList<MyAction>(); /**获取某个包下的所有控制器的所有action*/ public static List<MyAction> getActionsByPackageName(String packageName){ List<Class<?>> clazzs = ClassUtil.getClasses(packageName); //遍历 for(Class<?> clazz:clazzs){ /**判断 该类 是否被Controller注解标记,如果没有,继续下一个*/ if(!clazz.isAnnotationPresent(CONTROLLER)){ continue; } /**获取某个控制器的所有action*/ setActionsListByClazz(clazz); } return actionList; } /**获取某个控制器的所有action*/ private static void setActionsListByClazz(Class<?> clazz){ /**判断 该类 是否被RequestMapping注解标记,如果有,则获取注解值作为 路径前缀*/ String pathPre = ""; if(clazz.isAnnotationPresent(REQUEST_MAPPING)){ //如果有,则获取注解值 RequestMapping mapping = clazz.getAnnotation(REQUEST_MAPPING); pathPre = mapping.value(); pathPre =(('/'==pathPre.charAt(0))?pathPre:("/"+pathPre)); } /**获取 类 的 方法 集合*/ Method[] ms = clazz.getDeclaredMethods(); for(Method m:ms){ //判断 该方法 是否被RequestMapping注解标记 //如果有,则获取注解对象,并拼接path if (m.isAnnotationPresent(REQUEST_MAPPING)) { RequestMapping mapping = m.getAnnotation(REQUEST_MAPPING); String value = mapping.value(); //如果value为空字符串或null,则继续下一个方法 if("".equals(value)||null==value){ continue; } //----获取方法的参数名、参数类型 //----Map<String,Class<?>> params =new HashMap<String,Class<?>>(); //----m.getParameterAnnotations() //----留待以后做 String path = pathPre + "/" + (('/'==value.charAt(0))?(value.substring(1)):value); //创建一个MyAction对象 MyAction action = new MyAction(path,mapping.method(),clazz,m); actionList.add(action); } } } //处理请求 public static Object HandleRequest(Class<?> clazz,Method method,String jsonParam) throws Exception{ //利用反射调用某控制器的某方法 Object obj = clazz.newInstance(); return method.invoke(obj, jsonParam); } }
步骤三:模拟springmvc的请求调度类
/src/com/test/controller/UserController.java
package com.test.controller; import com.test.annotation.Controller; import com.test.annotation.RequestMapping; import com.test.annotation.RequestMethod; @Controller @RequestMapping("user") public class UserController { @RequestMapping(value="login",method=RequestMethod.GET) public String login(){ return "hello"; } @RequestMapping(value="register",method=RequestMethod.GET) public String register(){ return "hello"; } }
/src/com/test/dispatcher/HandlerServlet.java
package com.test.dispatcher; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.test.annotation.ActionsUtil; import com.test.annotation.MyAction; //模拟springMvc的请求调度器 @WebServlet("/") public class HandlerServlet extends HttpServlet { private static final long serialVersionUID = 1L; /**调用ActionsUtil工具获取actions*/ private static List<MyAction> actions = null; public HandlerServlet() { super(); /**调用ActionsUtil工具获取并初始化actions*/ actions =ActionsUtil.getActionsByPackageName("com.test.controller"); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try{ //获取method String method = request.getMethod(); //获取path String path = request.getServletPath(); System.out.println(path); if(path.endsWith(".html")||path.endsWith(".jsp")){ response.setStatus(200); response.setCharacterEncoding("utf8");//指定字符编码 PrintWriter out = response.getWriter();//编写页面 out.println("<html><head><title>你好,你使用的是请求调度</title></head><body>你好,你使用的是请求调度</body></html>"); out.flush(); out.close(); }else{ //遍历action for(int i=0;i<actions.size();i++){ MyAction action = actions.get(i); //判断路径、提交方法 是否匹配 if(path.trim().equals("/service"+action.getPath().trim())&&method.trim().equals(action.getRequestMethod().toString())){ //利用反射执行某控制器的某方法 String jsonParam = request.getParameter("jsonParam"); //利用反射调用某控制器的某方法 Object obj = action.getClazz().newInstance(); try{ String target = null; //如果参数为空 if(null==jsonParam){ target = (String) action.getMethod().invoke(obj); }else{ target = (String) action.getMethod().invoke(obj, jsonParam); } //如果参数匹配,则响应为200 response.setStatus(200); request.getRequestDispatcher(target+".html").forward(request, response); }catch(Exception e){ //如果参数不匹配,则响应为400 response.setStatus(400); } }else{ //如果路径不匹配,则响应为404 response.setStatus(404); } } } }catch(Exception e){ e.printStackTrace(); //返回500 } } }