反射+注解的使用
测试目录结构
扫描工具
package com.utils; import java.io.File; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; /** * 扫描工具类,用于扫描指定包下面的所有类,包括子包 * @author xdzy */ public class ScanUtil { /** * 存放所有类的类名 */ private static List<String> list = new ArrayList<String>(); /** * 扫描 * @param packagePath * @return */ public static List<String> scanPackage(String packages) { String[] packs = packages.split(","); for (String pack : packs) { String path = toPackagePath(pack); try { toClassPath(path); } catch (Exception e) { e.printStackTrace(); } } return list; } /** * 将路径转换成包名 * @param packagePath * @return */ private static String toPackagePath(String packagePath) { packagePath = packagePath.replace(".", File.separator); return getRealPath()+packagePath; } /** * 遍历目录将类名存入List中 * @param classPath * @throws Exception */ private static void toClassPath(String classPath) throws Exception { classPath = URLDecoder.decode(classPath, "utf-8"); // listFiles()获取路径下的所有文件或文件夹,返回的是一个File[]数组 File[] fs = new File(classPath).listFiles(); if (fs != null) { for (File file : fs) { // file.isDirectory()方法判断当前额的file对象是否是一个文件夹 if (file.isDirectory()) { // 获取文件夹的绝度路径 // 递归调用 toClassPath(file.getAbsolutePath()); } else { // 将文件名转换成完整类名 String path = toClassName(file); if (path != null) { list.add(path); } } } } } /** * 将文件名转换成完整类名 * @param file * @return * @throws Exception */ private static String toClassName(File file) throws Exception { if (file.getName().endsWith(".class")) { String path = URLDecoder.decode(getRealPath(), "utf-8"); path = new File(path).getAbsolutePath() + File.separator; path = file.getAbsolutePath().substring(path.length(), file.getAbsolutePath().length()); String className = path.replace(File.separator, "."); className = className.substring(0, className.length() - 6); return className; } else { return null; } } /** * 获取当前项目的classes目录 * @return */ private static String getRealPath(){ return ScanUtil.class.getClassLoader().getResource("").getPath(); } public static void main(String[] args) throws Exception{ ScanUtil.scanPackage("org.evergreen.web"); for (String string : list) { System.out.println(string); } } }
自定义注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface UrlMapper { String value() default ""; }
中央处理器(servlet)
package com.servlet; import com.annotation.UrlMapper; import com.utils.ScanUtil; import javax.servlet.ServletConfig; 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 java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author: xdzy * @date: 2018/8/31 15:44 * @description: 根据请求url找到相应类里面的相应注解,然后执行相应方法 */ @WebServlet("/") public class DispatcherServlet extends HttpServlet { //String表示url;Method表示方法名 private static final Map<String, Method> mapper=new HashMap<>(); //扫描指定文件夹下的类 private List<String> scan(String packageName){ //返回指定文件夹下所有的类的路径 return ScanUtil.scanPackage(packageName); } //根据扫描到的类获取该类里面的方法上面的注解 private void resolve(List<String> classNames){ //遍历所有的类路径 for(String className:classNames){ try{ //获取该类的Class对象 Class<?> clazz=Class.forName(className); //获取该类的所有方法名 Method[] methods=clazz.getMethods(); //遍历所有的方法 for (Method method:methods){ //判断该方法上面是否有该注解 if(method.isAnnotationPresent(UrlMapper.class)){ //获取当前方法上注解的value值,也就是请求的url String url=method.getDeclaredAnnotation(UrlMapper.class).value(); //放到集合中 mapper.put(url,method); } } }catch (ClassNotFoundException e){ throw new RuntimeException(e.getMessage()); } } } //根据url调用具体方法 private void invokeTargetMethod(HttpServletRequest request, HttpServletResponse response, Method method){ try { //先获取定义该方法的类实例 Object instance = method.getDeclaringClass().newInstance(); //进行方法的回调 method.invoke(instance, request, response); } catch (InstantiationException e) { throw new RuntimeException(e.getMessage()); } catch (IllegalAccessException e) { throw new RuntimeException(e.getMessage()); } catch (InvocationTargetException e) { throw new RuntimeException(e.getMessage()); } } @Override public void init(ServletConfig config) throws ServletException { //1. 全局的扫描 List<String> classNames = scan(""); //2. 解析类并缓存类中带有注解的方法 resolve(classNames); System.out.println("DispatcherServlet初始化完成..."); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求的url,这个path其实就对应了mapper中的key String path = request.getServletPath(); //根据key取出相应的method并调用处理请求 invokeTargetMethod(request, response, mapper.get(path)); } }
测试类
package com.servletTest; import com.annotation.UrlMapper; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author: xdzy * @date: 2018/9/1 11:41 * @description: 用户所有操作 */ public class UserController { @UrlMapper("/login") public void login(HttpServletRequest request, HttpServletResponse response){ System.out.println("login..."); String name = request.getParameter("userName"); System.out.println(name); } @UrlMapper("/addUser") public void addUser(HttpServletRequest request, HttpServletResponse response){ System.out.println("addUser..."); String name = request.getParameter("userName"); System.out.println(name); } }