zoukankan      html  css  js  c++  java
  • 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
            }
        }
    
    }
  • 相关阅读:
    [DB] 数据库的连接
    JS leetcode 翻转字符串里的单词 题解分析
    JS leetcode 拥有最多糖果的孩子 题解分析,六一快乐。
    JS leetcode 搜索插入位置 题解分析
    JS leetcode 杨辉三角Ⅱ 题解分析
    JS leetcode 寻找数组的中心索引 题解分析
    JS leetcode 移除元素 题解分析
    JS leetcode 最大连续1的个数 题解分析
    JS leetcode 两数之和 II
    JS leetcode 反转字符串 题解分析
  • 原文地址:https://www.cnblogs.com/wu-1393180819/p/9695607.html
Copyright © 2011-2022 走看看