反射+注解的使用

反射+注解的使用

测试目录结构

扫描工具

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);
    }
}
原文地址:https://www.cnblogs.com/xdzy/p/9584228.html