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
            }
        }
    
    }
  • 相关阅读:
    laravel使用redis报错
    PHP新特性W3Cschool
    【python】跳过验证直接登陆-cookie已经知道需要部分直接注入
    【python】显示等待
    【python】pymysql库的简单使用
    【python】UI自动化优化浏览器重复打开和跑脚本时电脑无法做其他工作的问题
    【python】seleniumwire和selenium的区别
    【python】UI自动化-新版
    【python】UI自动化获取输入框的值
    【python】UI自动化多窗口处理
  • 原文地址:https://www.cnblogs.com/wu-1393180819/p/9695607.html
Copyright © 2011-2022 走看看