springboot够用就好系列-2.基于commandfast框架的应用开发

news2024/11/24 9:29:56

参考web的jsoncat框架,实现一个控制台IO的commandfast简易框架,并进行使用。

 目录

程序效果

实现过程

样例代码

工程文件

参考资料


程序效果

截图1.查询当前时间和用户,查询磁盘空间

        利用commandfast框架,实现的2个简单功能,界面显示出功能名称列表,输入对应名称即可使用相关功能。比如这里显示的“CurrentBaseInfo”、“CurrentDiskInfo”。

截图2-3.工程目录结构

        开发只用关注在main所在类中调用框架入口方法run、基于框架“CommandFastPro”接口定义Controller类,Controller还需要调用其他类的,利用@Service定义类并使用@Autowired注入到Controller中。

实现过程

1.开发应用视角

截图2.使用commandfast的开发过程

        不需要在开发过程中new自定义的类,交给框架来管理。

只需要:

        步骤一、使用@Component注解修饰main所在类,告诉commandfast应用所在的jar包名称。

        步骤二、使用@Controller注解修饰功能入口所在类,Controller类需要继承commandfast中定义的“CommandFastPro”接口(需要实现一个work方法作为入口)。

        步骤三、使用@Service注解修饰@Controller的类调用的类,并使用@Autowired注解在Controller类中注入。

        步骤四、编译、运行应用即可。

2.框架启动流程视角

截图3.启动流程

        开发过程只用关注业务实现的代价是,commandfast框架部分需要操心很多。

其中包括

(1)与用户的交互:规定参数格式,本次示例没有使用args入参,只使用了Controller实例名用于调用对应的bean。

(2)类扫描:要扫描用户定义类的包里面所有@Controller、@Service描述的类。

(3)类的实例化及注入:将扫描出的每个类生成实例,涉及@Autowired注入的属性,需要将Service的实例设置进去,否则会报空指针异常。

样例代码

1.应用开发视角

(1)main方法

package maplegam.com.application;
@ComponentScan(name = "maplegam.com.application")
public class CommandApp {

  public static void main(String[] args) throws IOException {
    CommandFastApplication.run(CommandApp.class, args);
  }

}

(2)定义Controller类

@Controller(name = "CurrentDiskInfo")
public class CurrentDiskInfo implements CommandFastPro {
  
  @Autowired
  MemDisk memDisk;
  
  public void work() {
    memDisk.getDiskInfo();
    memDisk.getMemInfo();
  }
}

        @Controller注解中的name会存放于BeanFactory中,用户输入名称,也是通过这个找到对应的bean。

        @Autowired修饰的类不需要实例化,由框架注入。

(3)定义Service类

@Service
public class MemDisk {

  public static void getDiskInfo() {
    File[] disks = File.listRoots();

    System.out.println("[DiskInfo]");
    
    for(File file : disks) {
      System.out.print(file.getPath() + " ");
      System.out.print("total = " + file.getTotalSpace() / 1024 / 1024 + "M," + " ");// 总空间
      System.out.print("unuse = " + file.getFreeSpace() / 1024 / 1024 + "M," + " ");// 空闲空间
      System.out.print("already used = " + file.getUsableSpace() / 1024 / 1024 + "M");// 可用空间
      System.out.println();
    }
  }

  public static void getMemInfo() {
    System.out.println("[MemInfo]");
    OperatingSystemMXBean mem = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    System.out.println("Total RAM:" + mem.getTotalPhysicalMemorySize() / 1024 / 1024 + "MB");
    System.out.println("Available RAM:" + mem.getFreePhysicalMemorySize() / 1024 / 1024 + "MB");
  }
}

        该Service类的实例会被注入到(2)中的Controller中。

        一个功能的开发只用涉及(1)、(2)、(3),如果Controller功能简单不用调用其他类,那么(3)都不用开发。

2.框架视角

(1)run方法

public class CommandFastApplication {
  public static void run(Class<?> mainClass, String[] args) throws IOException {
    System.out.println("CommandFastApplication is starting!");
    
    //获取注解里面的信息
        ComponentScan componentScan = mainClass.getAnnotation(ComponentScan.class);
        String packageName = componentScan.name();
        System.out.println("package name:"+packageName);
    
    //根据@ComponentScan里的包名进行扫描
    String[] packageNames = new String[]{packageName};

    ClassFactory.loadClass(packageNames); //加载用户开发的类
    BeanFactory.loadBeans(); //将类生成实例
    DependencyInjection.inject(); //实例中@Autowire的属性进行注入
    
    System.out.println("CommandFastApplication is running!");
    
    //控制台输入输出界面
    ProvideService.start();
  }
}

(2)控制台IO相关类

public class ProvideService {
    public static void start() throws IOException {
      BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
      String s = null;
      
      while (true) {
        System.out.println("Please input a service name to work:");
          
          ClassFactory.CLASSES.get(Controller.class).forEach(aClass -> {
                String beanName = BeanHelper.getBeanName(aClass);
                System.out.println(beanName);
            });
          
        s=br.readLine();
        s.trim();

                //从BEAN中获取同名实例,强制类型转换成接口“CommandFastPro”类型,调用work入口方法
        if (BeanFactory.BEANS.get(s) != null) {
          CommandFastPro commandFastPro = (CommandFastPro) BeanFactory.BEANS.get(s);
          commandFastPro.work();
        }
        System.out.println();
      }
    }
}

(3)被应用使用的注释和接口

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ComponentScan {
  String name() default "";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {
  String name() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

}
public interface CommandFastPro {
  public void work();
}

        run方法中的几个方法涉及的代码不详细贴,主要涉及:

        Reflection工具类(导入reflections-0.9.12.jar),可使用其中的包扫描功能,及其他反射相关方法。

工程文件

1.下载地址:

        https://pan.baidu.com/s/1sAUSHeL5zjlUh7Lp5y9EKw

2.提取码:x7p8

参考资料

1.jsoncat源码及相关教程

微信公众号“JavaGuide”作者写的jsoncat框架,框架教程在公众号里有。

源代码:https://github.com/Snailclimb/jsoncat

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/116675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

95后阿里P7晒出工资单:狠补了两眼泪汪汪,真香...

最近一哥们跟我聊天装逼&#xff0c;说他最近从阿里跳槽了&#xff0c;我问他跳出来拿了多少&#xff1f;哥们表示很得意&#xff0c;说跳槽到新公司一个月后发了工资&#xff0c;月入5万多&#xff0c;表示很满足&#xff01;这样的高薪资着实让人羡慕&#xff0c;我猜这是税后…

Redis 核心原理串讲(上),从一条请求透视高性能的本质

文章目录Redis 核心原理总览&#xff08;全局篇&#xff09;前言一、请求二、数据结构1. 有哪些&#xff1f;2. 为什么节省内存又高效&#xff1f;三、网络模型1、四种常见IO模型1.1 同步阻塞1.2 同步非阻塞1.3 IO多路复用1.4 异步IO2、事件驱动2.1 引子2.2 事件驱动模型3、Rea…

【Windows】win10家庭版无法被远程桌面(mstsc)连接的解决方案

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;善假于物&#…

前端知识学习

一、html的学习 1.1 html的基本结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body></body> </html>1. <!DOCTYPE html> 告诉浏…

网页版chatGPT,国内直接打开就用的chatgpt

先看效果&#xff1a; 文件就是一个网页文件&#xff0c;直接打开就可以网页使用了。 使用的前提是需要有chatGPT的账号去获取apikey,然后把拿到的apikey放在下面代码中 然后网页的代码如下&#xff1a; <script src"https://unpkg.com/vue3/dist/vue.global.js&qu…

MySQL事务日志 (redo log)

MySQL事务日志 &#xff08;redo log) 事务的隔离性由 锁机制 实现。 而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。 REDO LOG 称为 重做日志 &#xff0c;提供再写入操作&#xff0c;恢复提交事务修改的页操作&#xff0c;用来保证事务的持久性。 …

如何使用YonBuilder进行报表分析?

报表是基于业务元数据、业务模型、数据模型等数据来源展示与分析业务的重要工具&#xff0c;在YonBuilder中可以通过简单拖拽、选择&#xff0c;快速生成报表分析&#xff0c;提升报表开发效率。本期通过员工信息数据对YonBuilder中报表的基本配置进行介绍。 01、创建报表 首…

深入理解kafka-1

kafka快速入门1、kafka简介1.1 kafka是什么1.2 kafka基础架构1.3 kafka模块概述2、kafkka结构剖析2.1 kafka工作流程2.2 kafka文件存储2.2.1 顺序写2.2.2 分片&#xff0c;索引2.2.3 页缓存2.2.4 零拷贝2.3 broker集群2.3.1 Controller控制器及选举机制2.4 生产者2.4.1 生产者分…

MCU-51:定时器

目录一、定时器介绍1.1 定时器的功能1.2 定时器的结构1.3 定时器框图二、定时器控制2.1 工作模式寄存器TMOD2.2 控制寄存器TCON三、中断系统3.1 中断系统介绍3.2 中断程序流程3.3 STC89C52中断资源四、应用4.1 定时器控制LED闪烁4.2 基于定时器按键控制LED流水灯4.3 定时器时钟…

C进阶 :征服指针之指针与数组强化笔试题练习(1)

目录 &#x1f63c;&#x1f638;一.彻底明白 sizeof 操作符 &#xff0c;数组名&#xff0c;strlen 函数 &#x1f405;1.数组名的意义 &#x1f406;2. sizeof 详解 &#x1f40b;3.strlen详解 &#x1f996;3.数组名意义详细图解演示 &#x1f431;&#x1f640;二.关于…

使用JDBC+javafx写一个简单功能齐全的图书管理系统

目录 1、JDBC的使用 2、对应包和Java文件的层级关系及对应的含义 3、数据库 4、相关代码 1&#xff09;、bookmanager包 Ⅰ、main函数 Ⅱ、utils包 Ⅲ、bean包 Ⅳ、controller包 2)resources(为资源文件包&#xff0c;可以看链接文章了解) Ⅰ、book包 Ⅱ、 login包…

嘘!P站数据分析年报;各省市疫情感染进度条;爱奇艺推出元宇宙App;You推出AI聊天机器人;GitHub今日热榜 | ShowMeAI资讯日报

&#x1f440;日报合辑 | &#x1f3a1;AI应用与工具大全 | &#x1f514;公众号资料下载 | &#x1f369;韩信子 &#x1f4e2; 『The 2022 Year in Review』P站2022年度报告 Pornhub 发布了第 9 次年度报告&#xff0c;数据科学家们绘制了多张彩色可视化图表&#xff0c;回顾…

Spring注册Bean系列--方法3:@Import+@Bean

原文网址&#xff1a;Spring注册Bean系列--方法3&#xff1a;ImportBean_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Spring注册Bean的方法&#xff1a;ImportBean。 注册Bean的方法我写了一个系列&#xff0c;见&#xff1a;Spring注册Bean(提供Bean)系列--方法大全_IT利刃出鞘…

Redis-SDS

本文你能得到&#xff1a; 1 SDS基本介绍 。 2 SDS与 C语言传统字符串的区别&#xff0c;为什么使用SDS。 3 SDS的结构和策略详解。 1 SDS 是什么&#xff1f;用来做什么&#xff1f; 1.1 ​ Redis没有直接使用C语言传统的字符串表示&#xff08;以空字符结尾的字符数组&a…

[网络工程师]-STP

生成树协议&#xff08;Spanning Tree Protocol&#xff0c;STP&#xff09;是一种链路管理协议&#xff0c;为网络提供路径冗余&#xff0c;同时防止产生环路。交换机之间使用网桥协议数据单元&#xff08;Bridge Protocol Data Unit&#xff0c;BPDU&#xff09;来交换STP信息…

C语言中单井号(#)和双井号(##)在宏语句中的应用

在阅读Linux内核代码过程中&#xff0c;特别是一些预处理指令宏的时候&#xff0c;会看到宏语句里会包含一些# 或者是连着的## 符号&#xff0c;刚接触的时候觉得很一头雾水&#xff0c;但这些宏语句有时候绕不开&#xff0c;所以为了更好地读懂这些代码&#xff0c;很有必要仔…

头豹研究院发布《2022年腾讯安全威胁情报能力中心分析报告》:助力企业掌握安全防御主动权

12月23日&#xff0c;头豹研究院发布了《2022年腾讯安全威胁情报能力中心分析报告》&#xff08;以下简称《报告》&#xff09;&#xff0c;深度研究了腾讯安全威胁情报能力建设、威胁情报能力应用、威胁情报价值实践方面的现状及成果&#xff0c;从专业视角分析腾讯安全威胁情…

全网首发!华为云UCS正式商用

日前&#xff0c;华为云UCS正式商用。华为云UCS是业界首个分布式云原生服务&#xff0c;支持对华为云集群、伙伴云集群、多云集群、本地集群和附着集群的统一管理&#xff0c;覆盖中心Region、专有Region、边缘云、客户数据中心和第三方云场景&#xff0c;提供无处不在的云原生…

深度学习02:损失函数总结

目录 nn.L1Loss: nn.NLLLoss: nn.MSELoss: nn.CrossEntropyLoss: 损失函数是用来估量模型的预测值与真实值的不一致程度&#xff0c;它是一个非负实值函数。我们训练模型的过程&#xff0c;就是通过不断的迭代计算&#xff0c;使用梯度下降的优化算法&#xff0c;使得损失函…

Day 05- Vue3 Vue2响应式原理

Vue2的响应式 核心&#xff1a;通过 Object.defineProtytype() 对对象的已有属性值的读取和修改进行劫持&#xff1b; 数据劫持 --> 给对象扩展属性 --> 属性设置 实现原理&#xff1a; 对象类型&#xff1a;通过Object.defineProperty()对属性的读取、修改进行拦截…