手写SpringMVC之ApplicationContextListener

news2024/11/24 20:01:36

什么是Spring MVC?

Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就包含在Spring Framework中。正式名称“Spring Web MVC”来自其源模块的名称( spring-webmvc ),但它通常被称为“Spring MVC”。

手写Spring MVC(一)

创建项目

创建父工程 [ 选择9号模板 :site-simple],命名为shop(以商城为例子)

创建子工程 [ 选择10号模板:webapp],命名为shop-web

创建子工程 [ 选择7号模板:quickstart],命名为shop-mvc

依赖准备

servlet-api
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>
lombok
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>
编译插件
<build>
    <finalName>shop_web</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (maybe moved to parent pom) -->
        <plugins>
            <!--这个插件就是java类生成class的编译插件-->
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!--编译参数-->
                    <compilerArgument>-parameters</compilerArgument>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

创建文件

  1. 在shop-web工程下创建以下目录

    image-20240626170051128

  2. 在mvc工程下创建以下目录

    image-20240626170120536

文件详解

mvc工程
  1. cn.cnmd.shop.mvc.annotation:主要是注解,包括控制器、路由映射、配置

    1. cn.cnmd.shop.mvc.annotation.Controller
    package cn.cnmd.shop.mvc.annotation;
    
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Controller {
    }
    
    1. cn.cnmd.shop.mvc.annotation.RequestMapping
    package cn.cnmd.shop.mvc.annotation;
    
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface RequestMapping {
        String value();
    }
    
    1. cn.cnmd.shop.mvc.annotation.Configuration
    package cn.cnmd.shop.mvc.annotation;
    
    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)
    public @interface Configuration {
        String value();
    }
    
  2. cn.cnmd.shop.mvc.canstant:包含了常见的错误码和错误信息

    1. cn.cnmd.shop.mvc.canstant.ResponseCodeInterface

      package cn.cnmd.shop.mvc.constant;
      
      public interface ResponseCodeInterface {
      
          int getCode();
          String getMessage();
      
          void setCode(int code);
          void setMessage(String message);
      }
      
    2. cn.cnmd.shop.mvc.canstant.ResponseCode

      package cn.cnmd.shop.mvc.constant;
      
      public enum ResponseCode implements ResponseCodeInterface {
      
          CONFIG_EXCEPTION(100, "config的配置信息出错"),
          CONFIGURATION_EXCEPTION(101, "需要配置Configuration这个注解"),
          CLASS_FILE_EXCEPTION(102, "class文件转换异常"),
          REQUEST_MAPPING_PATH_EXCEPTION(103, "RequestMapping地址设置有误"),
          REQUEST_PATH_EXCEPTION(104, "uri映射错误"),
          EXCEPTION_CONFIG_EXCEPTION(105, "未配置全局异常的路径"),
          ADVISER_CONFIG_EXCEPTION(106, "未配置处理器的路径");
      
          private int code;
          private String message;
      
          ResponseCode(int code, String message) {
              this.code = code;
              this.message = message;
          }
      
          @Override
          public int getCode() {
              return code;
          }
      
          @Override
          public String getMessage() {
              return message;
          }
      
          @Override
          public void setCode(int code) {
              this.code = code;
          }
      
          @Override
          public void setMessage(String message) {
              this.message = message;
          }
      }
      
      
  3. cn.cnmd.shop.mvc.container:容器,用于存储项目启动之后创建的BeanDefinition对象

    1. cn.cnmd.shop.mvc.container.BeanContainer

      package cn.cnmd.shop.mvc.container;
      
      import cn.cnmd.shop.mvc.model.BeanDefinition;
      import lombok.Getter;
      
      import java.util.Map;
      import java.util.concurrent.ConcurrentHashMap;
      
      public class BeanContainer {
      
          @Getter
          private static Map<String, BeanDefinition<?>> maps = null;
      
          static {
              maps = new ConcurrentHashMap<>();
          }
      }
      
      
  4. cn.cnmd.shop.mvc.exception:异常类,用于处理异常

    1. cn.cnmd.shop.mvc.exception.FrameWorkException

      package cn.cnmd.shop.mvc.exception;
      
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      
      @AllArgsConstructor
      @Data
      
      public class FrameWorkException extends RuntimeException {
      
          private int code;
          private String message;
      }
      
  5. cn.cnmd.shop.mvc.listener:监听器,主要作用是在项目启动时扫描controller下的文件生成BeanDefinition对象

    1. cn.cnmd.shop.mvc.listener.ApplicationListener

      package cn.cnmd.shop.mvc.listener;
      
      import cn.cnmd.shop.mvc.annotation.Configuration;
      import cn.cnmd.shop.mvc.annotation.RequestMapping;
      import cn.cnmd.shop.mvc.constant.ResponseCode;
      import cn.cnmd.shop.mvc.container.BeanContainer;
      import cn.cnmd.shop.mvc.exception.FrameWorkException;
      import cn.cnmd.shop.mvc.model.BeanDefinition;
      import cn.cnmd.shop.mvc.model.MethodDefinition;
      import cn.cnmd.shop.mvc.model.ParameterDefinition;
      
      import javax.servlet.ServletContext;
      import javax.servlet.ServletContextEvent;
      import javax.servlet.ServletContextListener;
      import java.io.File;
      import java.lang.reflect.Method;
      import java.lang.reflect.Parameter;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Map;
      
      public class ApplicationListener implements ServletContextListener {
      
          @Override
          public void contextInitialized(ServletContextEvent sce) {
              /*
               * 扫描web项目的Controller层
               * 封装成类描述类的对象
               * 添加到容器中 -- Key(父级uri+子级uri) Value(类描述类的对象)
               */
      
              ServletContext servletContext = sce.getServletContext();
              String config = servletContext.getInitParameter("config");//cn.cnmd.config.AppConfig
              if (config == null) {
                  throw new FrameWorkException(ResponseCode.CONFIG_EXCEPTION.getCode(), ResponseCode.CONFIG_EXCEPTION.getMessage());
              }
      
              //获取配置类的class对象
              Class<?> configurationClass = getConfiguration(config);
      
              //通过配置类的class对象拿到 AppConfig注解 中的cn.cnmd.controller
              String controllerPosition = getControllerPosition(configurationClass);
      
              //D:\Desktop\code\apache-tomcat-8.0.49\webapps\ROOT\WEB-INF\classes\cn\cnmd\controller
              String controllerAbsolutePath = getControllerAbsolutePath(servletContext, controllerPosition);
      
              //获取controller文件夹下所有的文件
              List<File> fileList = new ArrayList<>();
              findFileByPath(fileList, controllerAbsolutePath);
      
              //文件对象集合 --> class对象集合
              List<Class<?>> classes = transformTo(servletContext, fileList);
      
              //封装成类描述类的对象: BeanDefinition -> MethodDefinition -> ParameterDefinition
              handleController(classes);
      
          }
      
          /**
           * 通过web.xml的配置
           * <context-param>
           * <param-name>config</param-name>
           * <param-value>cn.cnmd.config.AppConfig</param-value>
           * </context-param>
           * 参数 [config] 获取的 [cn.cnmd.config.AppConfig] 获取配置文件类的class对象
           *
           * @param config [cn.cnmd.config.AppConfig]
           * @return class对象
           */
          public Class<?> getConfiguration(String config) {
              try {
                  return Class.forName(config);
              } catch (ClassNotFoundException e) {
                  throw new RuntimeException(e);
              }
          }
      
          /**
           * 通过配置文件类的class对象获取注解中的controller的类的全限定名 [cn.cnmd.controller]
           *
           * @param configurationClass 配置文件类的class对象
           * @return controller的类的全限定名
           */
          public String getControllerPosition(Class<?> configurationClass) {
              Configuration annotation = configurationClass.getAnnotation(Configuration.class);
              if (annotation == null) {
                  throw new FrameWorkException(ResponseCode.CONFIGURATION_EXCEPTION.getCode(), ResponseCode.CONFIGURATION_EXCEPTION.getMessage());
              }
              return annotation.value();
          }
      
          /**
           * 通过配置文件类 [AppConfig] 的注解信息 [cn.cnmd.controller] 获取controller包的发布路径
           *
           * @param servletContext     servlet上下文对象
           * @param controllerPosition 配置文件类 [AppConfig] 的注解信息 [cn.cnmd.controller]
           * @return controller包的发布路径
           */
          public String getControllerAbsolutePath(ServletContext servletContext, String controllerPosition) {
              //D:\Desktop\code\apache-tomcat-8.0.49\webapps\ROOT\WEB-INF\classes
              String absolutePath = servletContext.getRealPath("WEB-INF" + File.separator + "classes");
              controllerPosition = controllerPosition.replace(".", File.separator);
              return absolutePath + File.separator + controllerPosition;
          }
      
          /**
           * 通过controller包路径找到路径下所有文件对象
           *
           * @param fileList               文件对象集合
           * @param controllerAbsolutePath controller包的发布路径
           */
          public void findFileByPath(List<File> fileList, String controllerAbsolutePath) {
              File file = new File(controllerAbsolutePath);
              File[] files = file.listFiles();
              if (files != null) {
                  for (File f : files) {
                      if (f.isDirectory()) {
                          findFileByPath(fileList, f.getAbsolutePath());
                      } else if (f.isFile()) {
                          fileList.add(f);
                      }
                  }
              }
      
          }
      
          public List<Class<?>> transformTo(ServletContext servletContext, List<File> fileList) {
              List<Class<?>> classes = new ArrayList<>();
              for (File file : fileList) {
                  //D:\Desktop\code\apache-tomcat-8.0.49\webapps\ROOT\WEB-INF\classes\cn\cnmd\controller\UserController.class
                  String classPath = file.getAbsolutePath();
                  String absolutePath = servletContext.getRealPath("WEB-INF" + File.separator + "classes");
      
                  //cn\cnmd\controller\UserController.class --> cn.cnmd.controller.UserController
                  classPath = classPath.substring(absolutePath.length() + 1).split("\\.")[0].replace("\\", ".");
      
                  System.out.println(classPath);
                  Class<?> clazz = null;
                  try {
                      clazz = Class.forName(classPath);
                  } catch (ClassNotFoundException e) {
                      throw new RuntimeException(e);
                  }
                  classes.add(clazz);
              }
              return classes;
          }
      
          public void handleController(List<Class<?>> classes) {
              Map<String, BeanDefinition<?>> maps = BeanContainer.getMaps();
      
              for (Class<?> clazz : classes) {
                  try {
                      //父级url requestMappingPath --> requestMapping.value()
                      RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class);
                      String requestMappingPath1 = requestMapping.value();
      
                      //类名 beanName --> clazz.getName()
                      String beanName = clazz.getName();
      
                      //controller的类对象 t --> clazz.newInstance()
                      Object t = clazz.newInstance();
      
                      //方法描述对象
                      Method[] methods = clazz.getMethods();
      
                      for (Method method : methods) {
                          method.setAccessible(true);
                          if (!method.isAnnotationPresent(RequestMapping.class)) {
                              continue;
                          }
      
                          RequestMapping requestMapping1 = method.getAnnotation(RequestMapping.class);
      
                          //子级url requestMappingPath --> requestMapping1.value()
                          String requestMappingPath2 = requestMapping1.value();
      
                          //方法名 methodName --> method.getName()
                          String methodName = method.getName();
      
                          //方法对象 method --> method
      
                          //返回值类型 returnType -->  method.getReturnType()
                          Class<?> returnType = method.getReturnType();
      
                          //参数描述对象
                          Parameter[] parameters = method.getParameters();
                          List<ParameterDefinition> parameterDefinitions = new ArrayList<>();
      
                          for (int i = 0; i < parameters.length; i++) {
                              Class<? extends Parameter> paramClass = parameters[i].getClass();
      
                              //参数名 parameterName --> paramClass.getName()
                              String parameterName = paramClass.getName();
      
                              //参数类型 type --> paramClass
      
                              //参数下标 index --> i
      
                              ParameterDefinition parameterDefinition = new ParameterDefinition(parameterName, paramClass, i);
                              parameterDefinitions.add(parameterDefinition);
                          }
      
                          MethodDefinition methodDefinition = new MethodDefinition(requestMappingPath2, methodName, method, returnType, parameterDefinitions);
                          BeanDefinition<?> beanDefinition = new BeanDefinition<>(requestMappingPath1, beanName, clazz, t, methodDefinition);
                          String route = requestMappingPath1 + File.separator + requestMappingPath2;
                          maps.put(route, beanDefinition);
                      }
                  } catch (InstantiationException | IllegalAccessException e) {
                      throw new RuntimeException(e);
                  }
              }
          }
      }
      
      
  6. cn.cnmd.shop.mvc.model:类描述类,包括参数描述类、方法描述类、类描述类

    1. cn.cnmd.shop.mvc.model.ParameterDefinition

      package cn.cnmd.shop.mvc.model;
      
      import com.sun.istack.internal.NotNull;
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      /**
       * 参数描述类
       */
      
      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      public class ParameterDefinition {
          private String name;//参数名
          private Class<?> type;//参数类型
          private int index;//参数下标
      }
      
      
    2. cn.cnmd.shop.mvc.model.MethodDefinition

      package cn.cnmd.shop.mvc.model;
      
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      import java.lang.reflect.Method;
      import java.util.List;
      
      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      public class MethodDefinition {
      
          private String requestMappingPath;//子级url
          private String methodName;//方法名
          private Method method;//方法对象
          private Class<?> returnType;//返回值类型
          private List<ParameterDefinition> parameters;//参数描述列表
      }
      
      
    3. cn.cnmd.shop.mvc.model.BeanDefinition

      package cn.cnmd.shop.mvc.model;
      
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      public class BeanDefinition<T> {
          private String requestMappingPath;//父级url
          private String name;//类名
          private Class<?> beanClass;//controller类的class对象
          private T t;//controller类对象
          private MethodDefinition methodDefinition;//方法描述对象
      }
      
web工程
  1. cn.cnmd.config

    1. cn.cnmd.config.AppConfig

      package cn.cnmd.config;
      
      import cn.cnmd.shop.mvc.annotation.Configuration;
      
      @Configuration("cn.cnmd.controller")
      public class AppConfig {
      
      }
      
  2. cn.cnmd.controller:存放各种controller

    1. cn.cnmd.controller.UserController

      package cn.cnmd.controller;
      
      
      import cn.cnmd.pojo.User;
      import cn.cnmd.shop.mvc.annotation.Controller;
      import cn.cnmd.shop.mvc.annotation.RequestMapping;
      
      @Controller
      @RequestMapping("user")
      public class UserController {
      
          @RequestMapping("login1")
          public void login(String username, String password) {
          }
      
          @RequestMapping("login2")
          public void login(User user) {
          }
      
          public void method(String name){}
      }
      
    2. cn.cnmd.controller.back.AdminController

      package cn.cnmd.controller.back;
      
      
      import cn.cnmd.shop.mvc.annotation.Controller;
      import cn.cnmd.shop.mvc.annotation.RequestMapping;
      
      @Controller
      @RequestMapping("admin")
      public class AdminController {
      
          @RequestMapping("login")
          public void login(String name, String password){
      
          }
      }
      
      
  3. cn.cnmd.pojo:用于存放web项目中的JavaBean对象

    1. cn.cnmd.pojo.User

      package cn.cnmd.pojo;
      
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      public class User {
          String name;
          int age;
          String sex;
      }
      

ApplicationContextListener扫描过程(个人理解)

applicationContextListener扫描

roller
@RequestMapping(“admin”)
public class AdminController {

	    @RequestMapping("login")
	    public void login(String name, String password){
	
	    }
	}
	
	```
  1. cn.cnmd.pojo:用于存放web项目中的JavaBean对象

    1. cn.cnmd.pojo.User

      package cn.cnmd.pojo;
      
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      public class User {
          String name;
          int age;
          String sex;
      }
      

ApplicationContextListener扫描过程(个人理解)

[外链图片转存中…(img-wN91i1Ja-1719492618962)]

image-20240626191314663

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

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

相关文章

2024最新特种设备(锅炉作业)题库分享。

1.锅炉蒸发量大小是由(  )决定的。 A.压力的高低 B.受压元件多少 C.受热面积大小 答案:C 2.哪项不是自然循环的故障?&#xff08; &#xff09; A.停滞 B.倒流 C.下降管带汽 D.上升管带汽 答案:D 3.水冷壁被现代大型锅炉广泛采用的是(  )。 A.光管水冷壁 B.膜…

锐捷AP从其它项目拆下,怎么也加入不了到现在这个网络里来

环境: AP 产品型号:RG-RAP2260G 问题描述: 锐捷AP从其它项目拆下,怎么也加入不了到现在这个网络里来,现网是WIFI5的,想把2260G用来升级,恢复出厂设置后,插上网线,现网找不到这个AP 解决方案: 1.通电重置AP后,连接AP WiFi进入管理页面,要求先快速配置 2.开始配置…

【电路笔记】-MOSFET放大器

MOSFET放大器 文章目录 MOSFET放大器1、概述2、电路图3、电气特性3.1 ** I D = F ( V G S ) I_D=F(V_{GS}) ID​=F(VGS​)**特性3.2 I D = F ( V D S ) I_D=F(V_{DS}) ID​=F(VDS​)特性4、MOSFET放大器5、输入和输出电压6、电压增益7、总结1、概述 在前面的文章中,我们已经…

01.Ambari自定义服务开发-项目初始化

文章目录 基础环境在PyCharm中初始化项目配置项目相关依赖在PyCharm中导入依赖 基础环境 PyCharmPython 2.7已经安装完成的Ambari服务端 在PyCharm中初始化项目 项目名称就是我们要安装服务的名称&#xff0c;要求名称为全大写&#xff0c;如&#xff1a;DORIS创建Python2.7…

网格处理库 pmp-library 编译及应用笔记 -- 已全部解决√

多边形网格处理库Polygon Mesh Processing Library&#xff0c;简称pmp-library的 编译及应用笔记 – 已全部解决√ 官网&#xff1a;https://www.pmp-library.org/index.html 代码&#xff1a;https://github.com/pmp-library/pmp-library 平台&#xff1a;Ubuntu1 20.04&…

知识图谱——Neo4j数据库实战

数据与代码链接见文末 1.Neo4j数据库安装 JDK 安装:https://www.oracle.com/java/technologies/javase-downloads.html Neo4j 安装:https://neo4j.com/download-center/ 配置好 JDK 和 Neo4j 的环境变量

多电商账户为什么要用指纹浏览器?

随着电子商务的蓬勃发展&#xff0c;越来越多的商家选择开设多店来扩大经营规模。然而多店运营也带来了一系列的挑战&#xff0c;其中之一就是账号安全。 1. 了解反检测浏览器和代理服务器 在我们开始讨论如何有效地使用反检测浏览器之前&#xff0c;我们首先需要了解这两个工…

Excel 宏录制与VBA编程 —— 12、文本字符串类型相关(转换、拆分、分割、连接、替换、查找、“Like“)

字符串分割&#xff0c;文末示例&#xff08;文末代码3附有源码&#xff09; 代码1 - 基础字符串 代码2 - 字符串拆分 代码3 - 字符串分割 Option ExplicitSub WorkbooksClear()Dim DataRange As RangeSet DataRange Range("C2:E12")DataRange.Clear End SubSub Wo…

爆火网络的 AI 粘土风照片,如何用免费的AI绘画工具Stable Diffusion实现?只需一个Lora即可轻松解决!

大家好&#xff0c;我是画画的小强 最近粘土滤镜照片在小某书上爆火&#xff0c;随便一翻就出现好多 这些丑可爱丑可爱的粘土滤镜是这样紫。 这些照片都是通过手机APP Remini 来转绘的。Remini原来是由国人开发&#xff0c;据说卖给了国外公司&#xff0c;现在排在了谷歌商店下…

最年轻获奖者诞生!一文带你了解历届国家最高科学技术奖获奖人

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛贤 深度好文&#xff1a;4000字丨15分钟阅读 作为国家层面面向科学、技术领域的最高级别奖励&#xff0c;国家最高科学技术奖于 2000 年由国务院设立&#xff0c;每年评选…

8. Revit API UI: DockablePane(可停靠窗口)

8. Revit API UI: DockablePane&#xff08;可停靠窗口&#xff09; 接着前面的预览控件和外部事件&#xff0c;这一篇&#xff0c;我们来看看可停靠窗口DockablePane的实现。 实现流程 可停靠窗口相关的类与接口主要有DockablePane和IDockablePageProvider&#xff0c;都是…

探索Facebook的未来世界:数字社交的演进之路

在数字化和全球化的浪潮中&#xff0c;社交网络如Facebook已经成为了人们日常生活不可或缺的一部分。然而&#xff0c;随着技术的迅猛发展和用户需求的不断变化&#xff0c;Facebook正在经历着社交平台的演进之路。本文将探索Facebook的未来世界&#xff0c;分析数字社交的发展…

Android 13 为应用创建快捷方式

参考 developer.android.google.cn 创建快捷方式 来自官网的说明&#xff1a; 静态快捷方式 &#xff1a;最适合在用户与应用互动的整个生命周期内使用一致结构链接到内容的应用。由于大多数启动器一次仅显示四个快捷方式&#xff0c;因此静态快捷方式有助于以一致的方式执行…

ADC位数、增益调制与参考电压

位数&#xff1a;12bit、10bit、8bit 一般就是对应的ADC值分别为&#xff1a;4095、1023、255&#xff0c;也就选用对应位数时ADC的最大值。 增益的作用 增益设置用于放大或缩小输入信号&#xff0c;使其适配到ADC的输入范围。增益设置可以通过配置SAADC的通道配置寄存器来实…

第一后裔The First Descendant开服时间、配置要求一览

第一后裔是一款采用虚幻5引擎打造的第三人称合作射击动作RPG&#xff0c;玩家将化身为一名继承者&#xff0c;通过各种任务和故事不断成长&#xff0c;为守护人类与对抗侵略者战斗。该作即将上线&#xff0c;为了不让玩家们错过这款精彩的游戏&#xff0c;本文整理了第一后裔上…

[行业原型] Web端原型案例:康欣医疗后台管理系统

​医疗管理系统是一个业务复杂&#xff0c;功能庞大的系统&#xff0c;以下为HIS医院管理系统的常见模块&#xff0c;供大家参考。 本周为大家带来Web端原型案例&#xff1a;康欣医疗后台管理系统&#xff0c;先上原型&#xff1a; 完整文档加班主任微信号 添加班主任回复 “1…

推荐两款电脑文件处理工具,强大到你不舍得卸载

EasyFileCount EasyFileCount是一款基于Java开发的多功能文件管理工具&#xff0c;旨在帮助用户更轻松地管理和优化他们的文件存储。以下是EasyFileCount的主要功能和特点&#xff1a; 查看文件夹大小&#xff1a;用户可以快速统计和查看文件夹的总大小&#xff0c;实时显示各…

基于C++实现的EventLoop与事件驱动编程

一&#xff0c;概念介绍 事件驱动编程&#xff08;Event-Driven&#xff09;是一种编码范式&#xff0c;常被应用在图形用户界面&#xff0c;应用程序&#xff0c;服务器开发等场景。 采用事件驱动编程的代码中&#xff0c;通常要有事件循环&#xff0c;侦听事件&#xff0c;…

Qt样式表及相关案例

一.Qt样式表介绍 Qt样式表是一个可以自定义部件外观的强大机制&#xff0c;样式表的概念、术语、语法均受到HTML的层叠样式表(Cascading Style Sheets,CSS)的启发。 样式表可通过QApplication::setStyleSheet()函数将其设置到整个应用程序上&#xff0c;也可以使用QWidget::se…

突然!某大客户核心凌晨突然崩溃....

这几天实在太忙&#xff0c;刚弄完文档。业务线的同事就找到我&#xff0c;说一个银行客户的核心系统昨晚出了故障&#xff0c;还没找到原因&#xff0c;希望能帮忙分析下。 从提供的信息来看是业务跑任务报错&#xff0c;遇到了Oracle-00600和ora-07445 错误。 Doing block re…