servlet抽取二:基于注解的方式
2021/4/12 18:32:27
本文主要是介绍servlet抽取二:基于注解的方式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
回顾
之前写过一篇博客是servlet的抽取
但是在使用的时候,每次都要加上method=xxx
现在就想基于之前的方法进行改进,实现类似于springmvc那样的效果
直接根据请求,找到对应的方法,来执行,
所以现在就是用注解的方式对之前的serlvet抽取进行改进
思想
- 创建一个servlet,让所有的请求走这个servlet
- 再在这个servlet中,通过注解找到编写了映射地址的方法的类(这个类是标注有注解)
- 再找到这个类中定义的方法,对标注了映射地址的方法,通过反射调用
代码与解释
- 工具类ClassScaner:用于找到某个包下的所有类
public class ClassScanner { /** * 获得包下面的所有的class * @param * @return List包含所有class的实例 */ public static List<Class<?>> getClasssFromPackage(String packageName) { List<Class<?>> clazzs = new ArrayList<>(); // 是否循环搜索子包 boolean recursive = true; // 包名对应的路径名称 String packageDirName = packageName.replace('.', '/'); 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"); findClassInPackageByFile(packageName, filePath, recursive, clazzs); } } } catch (Exception e) { e.printStackTrace(); } return clazzs; } /** * 在package对应的路径下找到所有的class */ public static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive, List<Class<?>> clazzs) { File dir = new File(filePath); if (!dir.exists() || !dir.isDirectory()) { return; } // 在给定的目录下找到所有的文件,并且进行条件过滤 File[] dirFiles = dir.listFiles(new FileFilter() { public boolean accept(File file) { boolean acceptDir = recursive && file.isDirectory();// 接受dir目录 boolean acceptClass = file.getName().endsWith("class");// 接受class文件 return acceptDir || acceptClass; } }); for (File file : dirFiles) { if (file.isDirectory()) { findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs); } else { String className = file.getName().substring(0, file.getName().length() - 6); try { clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className)); } catch (Exception e) { e.printStackTrace(); } } } } }
- DispatherServlet :用于获取所有的*.do的请求,分发到相应的方法
@WebServlet("*.do") public class DispatherServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String requestURI = req.getRequestURI(); String contextPath = req.getContextPath(); //为了获取请求地址中,我们需要的部分,主要是为了取出ip端口项目名等无关信息 String mappingPath = requestURI.substring(contextPath.length(),requestURI.length()); //找到controller包下所有的类 List<Class<?>> classsFromPackage = ClassScanner.getClasssFromPackage("com.kehao.controller"); //对每一个类去看他是否有MyCompoent注解 classsFromPackage.stream().filter(clz-> clz.isAnnotationPresent(MyCompoent.class)).forEach( //对于符合要求的类,获取他们的被MyRequestMapping注解标注的方法,如果注解的值和请求地址相同就调用该方法 (clz)->{ Arrays.stream(clz.getDeclaredMethods()). filter(method -> method.isAnnotationPresent(MyRequestMapping.class)). filter(method->mappingPath.equals(method.getAnnotation(MyRequestMapping.class).value())). forEach(method -> { try { method.invoke(clz.newInstance(),req,resp); } catch (Exception e) { e.printStackTrace(); } }); } ); } }
- HelloController 实际的控制层
@MyCompoent public class HelloController { @MyRequestMapping("/hello.do") public void hello(HttpServletRequest req, HttpServletResponse resp) throws Exception { resp.getWriter().println("hello,i'm in HelloController"); } }
- 注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyRequestMapping { String value(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MyCompoent { }
依然存在的不足
很明显,这个代码还存在着明显的不足,需要改进,首先每次调用都需要扫描类和方法,需要新建了一个对象,而这些过程是重复的,还可以继续优化
这篇关于servlet抽取二:基于注解的方式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-04-26敏捷开发:想要快速交付就必须舍弃产品质量?
- 2024-04-26静态代码分析的这些好处,我竟然都不知道?
- 2024-04-26你在测试金字塔的哪一层?(下)
- 2024-04-26快刀斩乱麻,DevOps让代码评审也自动起来
- 2024-04-262024年最好用的10款ER图神器!
- 2024-04-2203-为啥大模型LLM还没能完全替代你?
- 2024-04-2101-大语言模型发展
- 2024-04-17基于SpringWeb MultipartFile文件上传、下载功能
- 2024-04-14个人开发者,Spring Boot 项目如何部署
- 2024-04-14RAG应用开发实战02-相似性检索的关键 - Embedding