Java阶段二Day07

news2024/11/14 20:02:21

Java阶段二Day07

文章目录

  • Java阶段二Day07
    • V17
      • UserController
      • DispatcherServlet
      • Controller
      • RequestMapping
    • V18
      • DispatcherServlet
      • HandleMapping
    • V19
      • BirdBootApplication
    • 线程池
      • 线程的执行过程
      • 线程池API
    • 数据库
      • 数据库的基本概念
      • 数据库管理系统中常见的概念
    • SQL分类
    • DDL语言-数据定义语言
      • 对数据库的操作
      • 对数据表的操作

V17

利用反射机制重构DispatcherServlet,使得将来添加新的业务时DispatcherServlet不必再添加分支判断(不进行修改)

实现:

  1. 新建包com.webserver.annotation
  2. annotation包下添加两个注解
    • @Controller:用于标注哪些类是处理业务的Controller
    • @RequestMapping:用于标注处理某个业务请求的业务方法
  3. com.webserver.controller包下的所有Controller类添加注解@Controller并将里面用于处理某个业务的方法标注@RequestMapping并指定该方法处理的请求
  4. DispatcherServlet在处理请求时,先扫描controller包下的所有Controller类,并找到处理该请求的业务方法,使用反射调用

UserController

package com.birdboot.controller;

import com.birdboot.annotations.Controller;
import com.birdboot.annotations.RequestMapping;
import com.birdboot.entity.User;
import com.birdboot.http.HttpServletRequest;
import com.birdboot.http.HttpServletResponse;

import java.io.*;

/**
 * 处理与用户相关的业务
 */
@Controller
public class UserController {
    private static File userDir;//表示存放所有用户信息的目录:users
    static {
        userDir = new File("./users");
        if(!userDir.exists()){
            userDir.mkdirs();
        }
    }

    @RequestMapping("/regUser")
    public void reg(HttpServletRequest request, HttpServletResponse response){
        System.out.println("开始处理用户注册");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String nickname = request.getParameter("nickname");
        String ageStr = request.getParameter("age");
        System.out.println(username+","+password+","+nickname+","+ageStr);
        //必要的验证
        if(username==null||username.isEmpty()||
                password==null||password.isEmpty()||
                nickname==null||nickname.isEmpty()||
                ageStr==null||ageStr.isEmpty()||
                !ageStr.matches("[0-9]+")
        ){
            response.sendRedirect("/reg_info_error.html");
            return;
        }

        int age = Integer.parseInt(ageStr);//将年龄转换为int值
        //2
        User user = new User(username,password,nickname,age);
        /*
            File的构造器
            File(File parent,String child)
            创建一个File对象表示child这个子项,而它是在parent这个File对象所表
            示的目录中
         */
        File file = new File(userDir,username+".obj");
        if(file.exists()){//注册前发现以该用户名命名的obj文件已经存在,说明是重复用户
            response.sendRedirect("/have_user.html");
            return;
        }

        try (
                FileOutputStream fos = new FileOutputStream(file);
                ObjectOutputStream oos = new ObjectOutputStream(fos);
        ){
            oos.writeObject(user);//保存用户信息完毕

            //3给用户回馈注册成功页面
            //要求浏览器重新访问下述地址对应的页面
            response.sendRedirect("/reg_success.html");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping("/loginUser")
    public void login(HttpServletRequest request,HttpServletResponse response){
        System.out.println("开始处理登录!!!!");
        //1获取登录信息
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //必要验证
        if(username==null||username.isEmpty()||password==null||password.isEmpty()){
            response.sendRedirect("/login_info_error.html");
            return;
        }

        //根据该登录用户的名字去定位users下该用户的注册信息
        File file = new File(userDir,username+".obj");
        //判断该文件是否存在,不存在则说明该用户没有注册过
        if(file.exists()){
            //将该用户曾经的注册信息读取出来用于比较密码
            try (
                    FileInputStream fis = new FileInputStream(file);
                    ObjectInputStream ois = new ObjectInputStream(fis);
            ){
                User user = (User)ois.readObject();//读取注册信息
                //比较本次登录的密码是否与注册时该用户输入的密码一致
                if(user.getPassword().equals(password)){
                    //密码一致则登录成功
                    response.sendRedirect("/login_success.html");
                    return;
                }
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        //如果程序可以执行到这里,则说明要么是用户名没输入对,要么是密码没有输入对.都属于登录失败
        response.sendRedirect("/login_fail.html");
    }
}

DispatcherServlet

package com.birdboot.core;

import com.birdboot.annotations.Controller;
import com.birdboot.annotations.RequestMapping;
import com.birdboot.controller.UserController;
import com.birdboot.http.HttpServletRequest;
import com.birdboot.http.HttpServletResponse;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;

/**
 * V8新增内容:
 * 该类是SpringMVC框架与Tomcat整合时的一个关键类
 * Tomcat处理业务原生的都是调用继承了HttpServlet的类来完成,此时需要进行很多配置
 * 以及使用时要作很多重复性劳动。
 * SpringMVC框架提供的该类也是继承了HttpServlet的,使用它来接收处理请求的工作。
 */
public class DispatcherServlet {
    private static File baseDir;//类加载路径
    private static File staticDir;//类加载路径下的static目录

    static {
        try {
            //定位当前项目的类加载路径
            baseDir = new File( DispatcherServlet.class.getClassLoader().getResource(".").toURI());
            //定位类加载路径下的static目录
            staticDir = new File(baseDir, "static");
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    /**
     * service方法实际上是当我们继承了HttpServlet后必须重写的方法
     * 该方法要求接收两个参数:请求对象与响应对象。
     * Tomcat在处理请求时就是调用某个Servlet的service方法并将请求与响应对象传入
     * 来让其完成处理工作的。
     */
    public void service(HttpServletRequest request, HttpServletResponse response) {
        //获取请求的抽象路径
        //不能在使用uri判断请求了,因为uri可能含参数,内容不固定。
        String path = request.getRequestURI();//path:"/regUser"
        System.out.println(path);

        //判断该请求是否为请求一个业务
        /*
            V17新增内容:
            当我们得到本次请求路径path的值后,我们首先要查看是否为请求业务:
            1:扫描controller包下的所有类
            2:查看哪些被注解@Controller标注的过的类(只有被该注解标注的类才认可为业务处理类)
            3:遍历这些类,并获取他们的所有方法,并查看哪些时业务方法
              只有被注解@RequestMapping标注的方法才是业务方法
            4:遍历业务方法时比对该方法上@RequestMapping中传递的参数值是否与本次请求
              路径path值一致?如果一致则说明本次请求就应当由该方法进行处理
              因此利用反射机制调用该方法进行处理。
              提示:反射调用后要记得return,避免执行后续处理静态资源的操作
            5:如果扫描了所有的Controller中所有的业务方法,均未找到与本次请求匹配的路径
              则说明本次请求并非处理业务,那么执行下面请求静态资源的操作
         */
        //定位controller目录   使用File访问文件系统时,路径中目录的层级分割是用"/"
        try {
            File dir = new File(baseDir,"com/birdboot/controller");
            //获取该目录下的所有.class文件
            File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
            for(File sub : subs){//遍历每一个.class文件
                String fileName = sub.getName();//获取文件名
                String className = fileName.substring(0,fileName.indexOf("."));//根据文件名获取类名
                //包名的层级分割使用"."
                Class cls = Class.forName("com.birdboot.controller."+className);
                //判断该类有没有注解@Controller
                if(cls.isAnnotationPresent(Controller.class)){
                    //扫描该类的所有方法
                    Method[] methods = cls.getDeclaredMethods();
                    //遍历每一个方法
                    for(Method method : methods){
                        //判断该方法是否有注解@RequestMapping
                        if(method.isAnnotationPresent(RequestMapping.class)){
                            //获取注解
                            RequestMapping rm = method.getAnnotation(RequestMapping.class);
                            //通过注解对象获取参数
                            String value = rm.value();
                            //对比本次请求是否与该方法注解参数一致?
                            if(path.equals(value)){
                                //一致则说明本次请求应当交由该方法处理
                                //实例化该Controller
                                Object c = cls.newInstance();
                                //调用该方法处理本次请求
                                method.invoke(c,request,response);
                                return;//处理后解除本次处理请求(避免执行下面处理静态资源的部分)
                            }
                        }
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        File file = new File(staticDir, path);
        if (file.isFile()) {
            //由于响应对象中状态代码和描述默认值为200,OK因此正确情况下不用再设置
            response.setContentFile(file);
            //设置响应头
            response.addHeader("Server", "BirdServer");
        } else {
            response.setStatusCode(404);
            response.setStatusReason("NotFound");
            file = new File(staticDir, "404.html");
            response.setContentFile(file);
            response.addHeader("Server", "BirdServer");
        }
    }
}

Controller

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
}

RequestMapping

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
    String value();
}

V18

重构代码
上一个版本那种DispatcherServlet每次处理请求时都要扫描controller包,这样性能低下,因此改为仅扫描一次

实现:

  1. com.webserver.core包下新建类HandlerMapping
  2. 定义静态属性Map mapping key:请求路径;value:Method记录处理该请求的方法对象
  3. 在静态块中初始化,完成原DispatcherServlet扫描controller包的工作并初始化mapping
  4. 提供静态方法:getMethod()可根据请求路径获取处理该请求的方法
  5. DispatcherServlet中处理业务时只需要根据请求获取对应的处理方法利用反射机制调用即可

DispatcherServlet

package com.birdboot.core;

import com.birdboot.annotations.Controller;
import com.birdboot.annotations.RequestMapping;
import com.birdboot.controller.UserController;
import com.birdboot.http.HttpServletRequest;
import com.birdboot.http.HttpServletResponse;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;

/**
 * V8新增内容:
 * 该类是SpringMVC框架与Tomcat整合时的一个关键类
 * Tomcat处理业务原生的都是调用继承了HttpServlet的类来完成,此时需要进行很多配置
 * 以及使用时要作很多重复性劳动。
 * SpringMVC框架提供的该类也是继承了HttpServlet的,使用它来接收处理请求的工作。
 */
public class DispatcherServlet {
    private static File baseDir;//类加载路径
    private static File staticDir;//类加载路径下的static目录

    static {
        try {
            //定位当前项目的类加载路径
            baseDir = new File(
                    DispatcherServlet.class.getClassLoader().getResource(".").toURI()
            );
            //定位类加载路径下的static目录
            staticDir = new File(baseDir, "static");
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    /**
     * service方法实际上是当我们继承了HttpServlet后必须重写的方法
     * 该方法要求接收两个参数:请求对象与响应对象。
     * Tomcat在处理请求时就是调用某个Servlet的service方法并将请求与响应对象传入
     * 来让其完成处理工作的。
     */
    public void service(HttpServletRequest request, HttpServletResponse response) {
        //获取请求的抽象路径
        //不能在使用uri判断请求了,因为uri可能含参数,内容不固定。
        String path = request.getRequestURI();//path:"/regUser"
        System.out.println(path);

        //判断该请求是否为请求一个业务
        Method method = HandlerMapping.getMethod(path);
        if(method!=null){//本次为请求业务
            //通过方法获取其所属类的类对象(某个Controller)
            try {
                Class cls = method.getDeclaringClass();
                Object obj =cls.newInstance();
                method.invoke(obj,request,response);
            } catch (Exception e) {
               //如果处理业务过程中报错,这是典型的因为服务端处理请求出现错误导致处理失败(500错误)
               response.setStatusCode(500);
               response.setStatusReason("Internal Server Error");
            }
        }else {
            File file = new File(staticDir, path);
            if (file.isFile()) {
                //由于响应对象中状态代码和描述默认值为200,OK因此正确情况下不用再设置
                response.setContentFile(file);
                //设置响应头
                response.addHeader("Server", "BirdServer");
            } else {
                response.setStatusCode(404);
                response.setStatusReason("NotFound");
                file = new File(staticDir, "404.html");
                response.setContentFile(file);
                response.addHeader("Server", "BirdServer");
            }
        }
    }
}

HandleMapping

package com.birdboot.core;

import com.birdboot.annotations.Controller;
import com.birdboot.annotations.RequestMapping;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

/**
 * SpringMVC框架使用这个类来维护所有Controller
 */
public class HandlerMapping {
    private static File baseDir;//类加载路径
    /*
        请求与对应的处理方法的映射关系
        key:请求路径(与对应方法上@RequestMapping注解参数一致)
        value:处理该请求的方法
     */
    private static Map<String, Method> mapping = new HashMap<>();

    static{
        try {
            //定位当前项目的类加载路径
            baseDir = new File(
                    HandlerMapping.class.getClassLoader().getResource(".").toURI()
            );
            initMapping();
        } catch (URISyntaxException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化mapping
     */
    private static void initMapping() throws ClassNotFoundException {
        File dir = new File(baseDir,"com/birdboot/controller");
        //获取该目录下的所有.class文件
        File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
        for(File sub : subs){//遍历每一个.class文件
            String fileName = sub.getName();//获取文件名
            String className = fileName.substring(0,fileName.indexOf("."));//根据文件名获取类名
            //包名的层级分割使用"."
            Class cls = Class.forName("com.birdboot.controller."+className);
            //判断该类有没有注解@Controller
            if(cls.isAnnotationPresent(Controller.class)){
                //扫描该类的所有方法
                Method[] methods = cls.getDeclaredMethods();
                //遍历每一个方法
                for(Method method : methods){
                    //判断该方法是否有注解@RequestMapping
                    if(method.isAnnotationPresent(RequestMapping.class)){
                        //获取注解
                        RequestMapping rm = method.getAnnotation(RequestMapping.class);
                        //通过注解对象获取参数
                        String value = rm.value();
                        //将该方法与其处理的请求路径以key,value形式存入mapping
                        mapping.put(value,method);
                    }
                }
            }
        }
    }

    /**
     * 根据请求路径获取某个Controller下的对应处理方法
     * @param path
     * @return
     */
    public static Method getMethod(String path){
        return mapping.get(path);
    }

    public static void main(String[] args) {
        Method method = getMethod("/regUser");
        System.out.println(method);
    }
}

V19

使用线程池管理线程
在主启动类BirdBootApplication中定义线程池,
并在接收客户端链接后将ClientHandler交给线程池处理

BirdBootApplication

package com.birdboot.core;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 主启动类
 */
public class BirdBootApplication {
    private ServerSocket serverSocket;
    private ExecutorService threadPool;

    public BirdBootApplication(){
        try {
            System.out.println("正在启动服务端...");
            serverSocket = new ServerSocket(8088);
            threadPool = Executors.newFixedThreadPool(50);
            System.out.println("服务端启动完毕!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start(){
        try {
            while(true) {
                System.out.println("等待客户端链接...");
                Socket socket = serverSocket.accept();
                System.out.println("一个客户端链接了!");
                //启动一个线程处理该客户端交互
                ClientHandler handler = new ClientHandler(socket);
                threadPool.execute(handler);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        BirdBootApplication application = new BirdBootApplication();
        application.start();
    }
}

线程池

  • 复用线程
  • 线程的数量控制

线程的执行过程

  1. 线程任务:Runnable
  2. 创建线程:new Thread()
  3. 启动:start()
  4. 并发执行中:Running
  5. 任务执行完毕:Dead
  6. 线程销毁:gc

线程池API

  • Executors:创建线程池的工厂类,用于创建线程池对象
  • ExecutorService:线程池接口,规定线程池相关功能方法

创建线程池ExecutorService pool = Executors.newFixedThreadPool(容量)

创建并指派任务

  1. 创建任务:实现Runnable接口重写run()方法
  2. 指派任务:调用线程池方法 pool.execute(任务)

线程池的关闭

  1. shutdown():不再接收新的任务,将现有任务执行完毕结束线程池中所以线程
  2. shutdownNow():不再接收新任务,中断线程池所有线程

数据库

数据库的基本概念

  • 数据库DataBase:保存一组数据的仓库就是数据库

  • 数据库管理系统(DBMS):一套可以独立运行的软件,用于维护磁盘上的数据,维护性好,性能好,可扩展性强

    常见的DBMS:

    • MySQL
    • MariaDB
    • Oracle
    • DB2
    • SQLServer

数据库管理系统中常见的概念

  • 库:是表的集合,一个库中可以存放若干张表。通常库是服务于项目的。

  • 表:是数据的集合,具有一组相同属性的数据存放在同一张表中。

    • 行:存放数据
    • 列:存放字段
  • 数据库的角色:数据库是一个独立运行的软件,并且是以服务端的形式体现的,我们要操作数据库则需要以客户端的角度与服务端建立连接并进行相关的操作

  • 数据库的交互:连接数据库后,向其发送SQL语句(Structured Query Language 结构化查询语言),数据库会理解该SQL语句的含义并进行对应操作

    SQL语句的标准:SQL92标准,所有DBMS都支持SQL92标准,该标准就是操作数据库的“普通话”,但不是所有的数据库操作都在SQL92标准中,不在该标准中的操作,不同的数据库提供的语法可能完全不同,此时这类SQL称为“方言”

  • 常用的客户端

    • 命令行
    • 图形化界面
    • JDBC
    • 集成开发环境(IDE)

在这里插入图片描述

SQL分类

  • DDL:数据定义语言,是操作数据库对象的语言。数据库对象(库,表,视图,索引,序列)
  • DML:数据操作语言,是操作表中数据的语言。对表中数据操作的语言(增INSERT,删DELETE,改UPDATE)
  • DQL:数据查询语言,是查询表中数据的语言。SELECT语句(学习的重点和难点)
  • DCL:数据控制语言,管理数据库的语言(权限分配等,DBA关心的)
  • TCL:事务控制语言,控制事务操作

DDL语言-数据定义语言

对数据库的操作

  • 新建一个数据库:

    CREATE DATABASE 数据库名 [charset = 字符集]
    # 指定字符集
    CREATE DATABASE mydb1 CHARSET = UTF8;
    CREATE DATABASE mydb2 CHARSET = GBK;
    
  • 查看已创建数据库:

    SHOW DATABASES;
    
  • 查看创建数据库时的信息:

    SHOW CREATE DATABASE 数据库名
    
  • 删除数据库:

    DROP DATABASE 数据库名
    
  • 切换数据库:

    USE 数据库名
    

对数据表的操作

  • 创建数据库表

    CREATE TABLE 表名(
    	字段名1 类型[(长度)][DEFALUT 默认值][约束],
        字段名2 类型[(长度)][DEFALUT 默认值][约束],
    ) [charset = 字符集]
    
  • 查看表结构:

    DESC 表名
    
  • 查看表创建时的信息:

    SHOW CREATE TABLE 表名
    
  • 查看当前数据库中创建的所有表:

    SHOW TABLES
    
  • 修改表名:

    RENAME TABLE 原表名 TO 新表名
    
  • 删除表:

    DROP TABLE 表名
    
  • 修改表结构,在表末尾追加新字段:

    ALTER TABLE 表名 ADD 字段名 类型[(长度) 默认值 约束]
    
  • 修改表结构,在表最开始添加新字段:

    ALTER TABLE 表名 ADD 字段名 类型 [(长度) 默认值 约束] FIRST
    
  • 修改表结构,在表中间插入新字段:

    ALTER TABLE 表名 ADD 字段名 类型[(长度) 默认值 约束] AFTER 表中现有字段名
    
  • 修改表结构,在表中删除字段:

    ALTER TABLE 表名 DROP 字段名
    
  • 修改表结构,在表中修改现有字段:

    ALTER TABLE 表名 CHANGE 原字段名 新字段名 类型 [(长度) 默认值 约束]
    

修改表结构的注意事项

  • 修改表结构最好在表中没有数据的情况下进行
  • 当表中含有数据时,
    • 尽量不修改表中某字段类型,否则可能因为现有数据不满足新修改的类型导致修改失败
    • 尽量不缩短字段长度
    • 若为字段新添加约束,该字段现有的数据不能违反该约束

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

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

相关文章

浅析流媒体技术的发展趋势及EasyCVR视频技术的应用

随着科技的不断发展&#xff0c;流媒体已经成为人们日常生活中必不可少的一部分。为了进一步提高流媒体的质量&#xff0c;未来的技术革新方向将集中在以下几个方面&#xff1a; 1&#xff09;提高视频编解码技术的质量和效率 随着高清视频的普及&#xff0c;人们对流媒体的质…

GD32F470 移植STM32F429工程 Keil调试笔记

keil版本&#xff1a;5.25 安装 GigaDevice.GD32F4xx_DFP.3.0.4.pack Keil.STM32F4xx_DFP.2.15.0.pack 一、GD32F470 与 STM32F429 切换编译 1、原项目为STM32F429 工程&#xff0c;切换到GD32F470 只需在 Options for Target"“对话框的Device菜单中选中“GD32F470II”…

Http协议—请求的构造

目录 一、通过 form表单 构造HTTP请求 1、form 发送 Get 请求 &#xff08;1&#xff09;form 的重要参数 &#xff08;2&#xff09;input 的重要参数 2、通过 form 构造 Post 请求 二、通过 ajax 构造 HTTP 请求 1、基于 jQuery 中的 ajax 构造 &#xff08;1&#x…

动态网站开发讲课笔记07:EL和JSTL

文章目录 零、本节学习目标一、EL&#xff08;一&#xff09;EL基本语法1、EL的概念2、EL的语法3、案例演示&#xff08;1&#xff09;用EL读取保存的信息&#xff08;2&#xff09;使用Java代码与EL获取信息的对比 4、EL基本语法的特点 &#xff08;二&#xff09;EL中的标识符…

从语言模型到ChatGPT,大模型训练全攻略

文&#xff5c;python 前言 你是否想过&#xff0c;为什么ChatGPT能够如此火爆呢&#xff1f;我认为这主要是因为ChatGPT提供了好玩、有用的对话式交互功能&#xff0c;能够为用户提供帮助&#xff0c;而不仅仅是依靠“大”模型的魅力。毕竟&#xff0c;GPT-3在2020年就已经推出…

RedHat yum没有已启用源的解决方法

一般安装的红帽系统&#xff0c;自带的yum在没有付费的情况下是无使用的&#xff0c;所以我们要进行换源。 1、环境准备 先检查以下我们的linux系统环境&#xff0c;看看是不是Redhat7的版本 &#xff0c;出现如下图所示的界面 cat /etc/redhat-release 检查系统中是否安…

科技云报道:重塑增长新动能,“数智融合”捷径该如何走?

科技云报道原创。 如果说&#xff0c;过去是数字化转型的试验阶段&#xff0c;实施的是开荒动土、选种育苗&#xff0c;那么当前要进行的是精耕细作、植树造林。 数字化转型已进入了由个别行业、个别场景的“点状应用”向各行各业全流程、全环节“整体渗透”的关键期。 云计算…

yolov5-7.0 训练自己的数据集之检测数据集

YOLOv5是一种单阶段目标检测算法&#xff0c;有很高的精度和速度&#xff0c;因为项目需求&#xff0c;需要利用yolov5-7.0训练自己的目标检测数据集。 假设&#xff0c;环境已经配置完成&#xff01; 1&#xff09;准备数据集 在D:\Graduation_Project_Coding\network_class…

QGIS中导入dwg文件并使用GetWKT插件获取绘制元素WKT字符串以及QuickWKT插件实现WKT显示在图层

场景 QGIS在Windows上下载安装与建立空间数据库连接&#xff1a; https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/124108040 在上面实现QGIS的安装之后&#xff0c;版本是3.26.3。 业务需求: 1、在dwg文件上绘制多边形区域&#xff0c;并获取绘制区域的wkt字…

如何在美国虚拟主机上安装WordPress?

如果你想在美国虚拟主机上搭建一个博客网站&#xff0c;那么WordPress是一个非常好的选择。本文将介绍如何在美国虚拟主机上安装WordPress&#xff0c;帮助你快速建立一个美观、高效的博客网站。 一、选择合适的虚拟主机服务商 在安装WordPress之前&#xff0c;你需要选择一个可…

[Netty] Netty自带的心跳机制 (十五)

文章目录 1.IdleStateHandler介绍2.IdleStateHandler源码解析3.IdleStateHandler总结 1.IdleStateHandler介绍 Netty服务端心跳机制: IdleStateHandler, 这个类可以对三种类型的心跳检测。 ChannelHandler.Sharable public class IdleHandler extends ChannelInboundHandlerA…

redis7详解

Redis基础 文章目录 一、Redis入门概述是什么&#xff1f;能干嘛&#xff1f;主流功能与应用优势 Redis7新特性 二、Redis安装配置Redis7安装步骤Redis7卸载步骤 三、Redis10大数据类型Redis 键(key)1、Redis 字符串&#xff08;String&#xff09;2、Reids列表&#xff08;Lis…

java版本电子招标采购系统源码—企业战略布局下的采购

​ 智慧寻源 多策略、多场景寻源&#xff0c;多种看板让寻源过程全程可监控&#xff0c;根据不同采购场景&#xff0c;采取不同寻源策略&#xff0c; 实现采购寻源线上化管控&#xff1b;同时支持公域和私域寻源。 询价比价 全程线上询比价&#xff0c;信息公开透明&#xff0…

谷歌云 | 内部 HTTP(S) 负载均衡器现在可以在全球范围内访问

【本文由Cloud Ace整理发布&#xff0c;Cloud Ace 是谷歌云全球战略合作伙伴&#xff0c;拥有 300 多名工程师&#xff0c;也是谷歌最高级别合作伙伴&#xff0c;多次获得 Google Cloud 合作伙伴奖。 作为谷歌托管服务商&#xff0c;我们提供谷歌云、谷歌地图、谷歌办公套件、谷…

店铺销售管理系统有哪些用?该如何选?

现在市场竞争越来越激烈&#xff0c;实体店想要吸引更多意向客户&#xff0c;快速提高销量&#xff0c;使用店铺管理系统来智能化管理店铺&#xff0c;已经成为不可或缺的手段。 店铺管理系统能够帮助实体店老板实现店铺销售和库存管理的自动化和集中化&#xff0c;提高门店的销…

Ceph入门到精通-podman 入门实战

目录 podman安装podman制作本地镜像podman(docker)命令回顾podman快速入门 一入编程深似海&#xff0c;从此节操是路人。 最近使用podman&#xff0c;就想着写一篇总结性的笔记&#xff0c;以备后续参考。就如同写代码&#xff0c;不写注释&#xff0c;过了一段时间可能会想这…

【Leetcode】572.另一棵树的子树

另一棵树的子树 题目思路代码 题目 思路 这道题目主要用到判断两个二叉树是否相同 对root为根节点的树进行递归遍历判断 是否存在一颗子树和以subRoot为根节点的树 代码 class Solution {public boolean isSubtree(TreeNode root, TreeNode subRoot) {if(root null){return…

HJL-93/A数字式交流三相电流继电器 导轨安装 约瑟JOSEF

品牌&#xff1a;JOSEF约瑟名称&#xff1a;数字式交流三相电流继电器型号&#xff1a;HJL系列功率消耗&#xff1a;≤5W触点容量&#xff1a;250V/5A额定电压&#xff1a;58、100、110、220V HJL系列 数字式交流三相电流继电器型号&#xff1a; HJL-93/AY数字式交流三相电流继…

收藏~六大网站访客类型及应对方式

收藏&#xff01;六大网站访客类型及应对方式&#xff01; 当涉及到与潜在客户接触时&#xff0c;速度是关键。毕竟&#xff0c;当一个潜在客户来到你的网站时&#xff0c;你只有10秒钟的时间来捕捉他们的兴趣。我们把这种主动的方法称为 "扑捉"。它确保你的销售团队…

《百年孤独》

《创世记》之后&#xff0c;首部值得全人类阅读的文学巨著。 — 纽约时报 加西亚 马尔克斯以小说作品创建了一个自己的世界&#xff0c;一个浓缩的宇宙&#xff0c;其中喧嚣纷乱却又生动可信的现实&#xff0c;映射了一篇大陆及其人民的富足与贫困。 — 诺贝尔文学奖颁奖辞 马…