java注解的使用

资料:

(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
        }
    }

}
原文地址:https://www.cnblogs.com/wu-1393180819/p/9695607.html