阶段二模块一

手写迷你Tomcat升级版(含解题思路及完整代码) 一. 题目要求 开发Minicat V4.0,在已有Minicat基础上进一步扩展,模拟出webapps部署效果 磁盘上放置一个webapps目录,webapps中可以有多个项目,例如demo1、demo2、demo3... 每个项目中含有servlet,可以根据请求url定位对应servlet进一步处理。具体的项⽬⽐如demo1中有serlvet(也即为:servlet是属于具体某⼀个项⽬的servlet),这样的话在Minicat初始化配置加载,以及根据请求url查找对应serlvet时都需要进⼀步. 阅读详情

作业要求

开发 Minicat V 4.0,在已有 Minicat 基础上进一步扩展,模拟出 webapps 部署效果。磁盘上放置一个 webapps 目录,webapps 中可以有多个项目,例如 demo1、demo2、demo3... 每个项目中含有 Servlet,可以根据请求 url 定位对应 Servlet 进一步处理。

作业具体要求参考以下链接文档:

https://gitee.com/lagouedu/alltestfile/raw/master/tomcat/Tomcat%E4%BD%9C%E4%B8%9A%E5%A4%A7%E9%A2%98.pdf

作业资料说明:

  1. 提供资料:工程代码和自己的 webapps 以及访问路径、功能演示和原理讲解视频。

  2. 讲解内容包含:题目分析、实现思路、代码讲解。

  3. 效果视频验证:实现模拟 Tomcat 多项目部署效果,访问多个不同项目可获得动态返回的内容。

分析

  1. 添加 server.xml,需要在开启端口监听之前开始解析该配置文件,因为存在端口配置信息。
  2. 封装 Mapper 组件体系,源码中采用的是数组的形式,但是这里我使用的是 Map 集合的形式进行存储,方便查找。
  3. 接收到请求的时候,需要通过 Mapper 体系逐级锁定。

代码

  1. server.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <Server>
        <Service>
            <Connector port="8080"/>
            <Engine>
                <Host name="localhost" base="C:/Users/Learner/webapps"/>
            </Engine>
        </Service>
    </Server>
    
  2. Mapper

    package cn.worstone.bean;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Mapper {
        private Map<String, Host> hostMap = new HashMap<>();
    
        public Map<String, Host> getHostMap() {
            return hostMap;
        }
    }
    
  3. Host

    package cn.worstone.bean;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Host {
        private String name;
        private String path;
        private Map<String, Context> contextMap = new HashMap<>();
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPath() {
            return path;
        }
    
        public void setPath(String path) {
            this.path = path;
        }
    
        public Map<String, Context> getContextMap() {
            return contextMap;
        }
    }
    
  4. Context

    package cn.worstone.bean;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Context {
        private String name;
        private Map<String, Wrapper> wrapperMap = new HashMap<>();
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Map<String, Wrapper> getWrapperMap() {
            return wrapperMap;
        }
    }
    
  5. Wrapper

    package cn.worstone.bean;
    
    import cn.worstone.servlet.HttpServlet;
    
    public class Wrapper {
        private HttpServlet servlet;
    
        public HttpServlet getServlet() {
            return servlet;
        }
    
        public void setServlet(HttpServlet servlet) {
            this.servlet = servlet;
        }
    }
    

    Mapper 组件基本上都是使用 Map 进行封装,为了方便查找。

  6. Request

    package cn.worstone.bean;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * 把请求信息封装为 Request 对象 (根据 InputStream 输入流进行封装)
     */
    public class Request {
        // 请求方式
        private String method;
        // 请求路径
        private String url;
        // 虚拟主机
        private String host;
    
        private InputStream inputStream;
    
        public String getMethod() {
            return method;
        }
    
        public void setMethod(String method) {
            this.method = method;
        }
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public String getHost() {
            return host;
        }
    
        public void setHost(String host) {
            this.host = host;
        }
    
        public InputStream getInputStream() {
            return inputStream;
        }
    
        public void setInputStream(InputStream inputStream) {
            this.inputStream = inputStream;
        }
    
        public Request() {
        }
    
        public Request(InputStream inputStream) throws IOException {
            this.inputStream = inputStream;
            // 从输入流中获取请求信息
            int count = 0;
            while (count == 0) {
                count = inputStream.available();
            }
            byte[] bytes = new byte[count];
            inputStream.read(bytes);
            String context = new String(bytes);
            // System.out.println("请求信息: ");
            // System.out.println(context);
            // 获取第一行请求信息
            String[] contextArr = context.split("\\n");
            String[] firstArr = contextArr[0].split(" ");
            this.method = firstArr[0];
            this.url = firstArr[1];
            System.out.println("Method: " + this.method);
            System.out.println("Url: " + this.url);
            // 获取第二行请求信息
            String[] secondArr = contextArr[1].split(" ");
            this.host = secondArr[1].replace("\r", "");
            System.out.println("Host: " + this.host);
        }
    }
    

    Request 中新增了一个虚拟主机 host,用来请求的虚拟主机信息,同时在处理请求的方法中,新增了虚拟主机信息的处理,注意这个地方别忘记处理 "\r"。

  7. Response

    package cn.worstone.bean;
    
    import cn.worstone.util.HttpProtocolUtil;
    import cn.worstone.util.StaticResourceUtil;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    
    /**
     * 封装 Response 对象, 需要 OutputStream
     * 该对象提供核心方法, 返回 HTML
     */
    public class Response {
        private OutputStream outputStream;
    
        public Response() {
        }
    
        public Response(OutputStream outputStream) {
            this.outputStream = outputStream;
        }
    
        /**
         * 输出指定字符内容
         *
         * @param context
         * @throws IOException
         */
        public void output(String context) throws IOException {
            this.outputStream.write(context.getBytes());
        }
    
        /**
         * 根据 url 获取静态资源绝对路径, 进一步根据绝对路径读取该静态资源文件, 最终通过输出流输出
         *
         * @param path
         */
        public void outputHtml(String path) throws IOException {
            // 获取静态资源绝对路径
            String absoluteResourcePath = StaticResourceUtil.getAbsolutePath(path);
            outputByAbsolutePath(absoluteResourcePath);
        }
    
        /**
         * 根据绝对路径获取静态资源文件, 并输出
         *
         * @param absolutePath
         * @throws IOException
         */
        public void outputByAbsolutePath(String absolutePath) throws IOException {
            // 处理文件路径包含中文的情况
            absolutePath = java.net.URLDecoder.decode(absolutePath, "utf-8");
    
            // 获取静态资源文件
            File file = new File(absolutePath);
            if (file.exists() && file.isFile()) {
                // 读取静态资源文件, 输出静态资源
                StaticResourceUtil.outputStaticResource(new FileInputStream(file), this.outputStream);
            } else {
                // 输出 404 信息
                output(HttpProtocolUtil.getHttpHeader404());
            }
        }
    }
    

    Response 中新增了一个方法 outputByAbsolutePath,用于通过绝对路径获取静态资源文件,并且添加了中文文件路径处理代码。由于方法中的内容与 outputHtml 方法十分相似,故此对 outputHtml 方法进行修改。

  8. RequestProcessor

    package cn.worstone.runable;
    
    import cn.worstone.bean.*;
    import cn.worstone.servlet.HttpServlet;
    import cn.worstone.util.HttpProtocolUtil;
    
    import java.io.InputStream;
    import java.net.Socket;
    import java.util.Map;
    
    public class RequestProcessor implements Runnable {
    
        private Socket socket;
    
        private Map<String, HttpServlet> servletMap;
    
        private Mapper mapper;
    
        public RequestProcessor(Socket socket, Map<String, HttpServlet> servletMap, Mapper mapper) {
            this.socket = socket;
            this.servletMap = servletMap;
            this.mapper = mapper;
        }
    
        @Override
        public void run() {
            try {
                InputStream inputStream = socket.getInputStream();
    
                // 封装 Request 对象以及 Response 对象
                Request request = new Request(inputStream);
                Response response = new Response(socket.getOutputStream());
    
                // 解析 URL
                Host host = this.mapper.getHostMap().get(request.getHost());
                if (host != null) {
                    String url = request.getUrl();
                    int index = url.indexOf("/", 1);
                    index = index == -1 ? url.length() : index;
                    String contextStr = url.substring(0, index);
                    Context context = host.getContextMap().get(contextStr);
                    if (context != null) {
                        String wrapperStr = url.substring(index);
                        Wrapper wrapper = context.getWrapperMap().get(wrapperStr);
                        if (wrapper != null) {
                            HttpServlet httpServlet = wrapper.getServlet();
                            httpServlet.service(request, response);
                        } else {
                            response.outputByAbsolutePath(host.getPath() + request.getUrl());
                        }
                    } else {
                        // 不是 webapps 里面的请求
                        if (servletMap.get(request.getUrl()) == null) {
                            response.outputHtml(request.getUrl());
                        } else {
                            HttpServlet httpServlet = servletMap.get(request.getUrl());
                            httpServlet.service(request, response);
                        }
                    }
                } else {
                    // 输出 404 信息
                    response.output(HttpProtocolUtil.getHttpHeader404());
                }
    
                // 必须在线程里面关闭
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    因为需要解析 webapps 文件夹下的项目,所以新增了一个 Mapper 参数,其中存储 webapps 下的映射信息。并且修改了请求处理部分代码。目前逻辑如下:

在这里插入图片描述

  1. BootStrap

    package cn.worstone.server;
    
    import cn.worstone.bean.Context;
    import cn.worstone.bean.Host;
    import cn.worstone.bean.Mapper;
    import cn.worstone.bean.Wrapper;
    import cn.worstone.runable.RequestProcessor;
    import cn.worstone.servlet.HttpServlet;
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import java.io.*;
    import java.lang.reflect.InvocationTargetException;
    import java.net.*;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.*;
    
    /**
     * Minicat 启动类
     */
    public class Bootstrap {
    
        // 监听端口号
        private int port = 8080;
    
        public int getPort() {
            return port;
        }
    
        public void setPort(int port) {
            this.port = port;
        }
    
        /**
         * Minicat 程序启动入口
         *
         * @param args
         */
        public static void main(String[] args) {
            Bootstrap bootstrap = new Bootstrap();
            try {
                // 启动 Minicat
                bootstrap.start();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Minicat 启动时需要初始化展开的操作
         */
        public void start() throws Exception {
            // Minicat 1.0 版本
            // 需求: 浏览器请求 http://localhost:8080, 返回一个固定字符串到页面 "Hello Minicat !"
            /*
            ServerSocket server = new ServerSocket(this.port);
            System.out.println("Minicat start on port: " + this.port);
            while (true) {
                Socket socket = server.accept();
                // 接收 socket 请求, 获取输出流
                OutputStream outputStream = socket.getOutputStream();
                String context = "Hello Minicat !";
                String responseStr = HttpProtocolUtil.getHttpHeader200(context.getBytes().length) + context;
                outputStream.write(responseStr.getBytes());
                outputStream.close();
                socket.close();
            }
            */
    
            // Minicat 2.0 版本
            // 需求: 封装 Request Response 对象, 返回 HTML 静态资源文件
            /*
            while (true) {
                Socket socket = server.accept();
                InputStream inputStream = socket.getInputStream();
    
                // 封装 Request 对象以及 Response 对象
                Request request = new Request(inputStream);
                Response response = new Response(socket.getOutputStream());
    
                response.outputHtml(request.getUrl());
                socket.close();
            }
            */
    
            // Minicat 3.0 版本
            // 需求: 可以请求动态资源 (Servlet)
            // 加载解析相关配置 server.xml
            /*
            loadServlet();
    
            while (true) {
                Socket socket = server.accept();
                InputStream inputStream = socket.getInputStream();
    
                // 封装 Request 对象以及 Response 对象
                Request request = new Request(inputStream);
                Response response = new Response(socket.getOutputStream());
    
                if (servletMap.get(request.getUrl()) == null) {
                    response.outputHtml(request.getUrl());
                } else {
                    HttpServlet httpServlet = servletMap.get(request.getUrl());
                    httpServlet.service(request, response);
                }
    
                socket.close();
            }
            */
    
            // 多线程改造 (不使用线程池)
            /*
            loadServlet();
    
            while (true) {
                Socket socket = server.accept();
                RequestProcessor processor = new RequestProcessor(socket, this.servletMap);
                processor.start();
            }
            */
    
            // 多线程改造 (使用线程池)
            /*
            loadServlet();
    
            // 创建线程池
            int corePoolSize = 10;
            int maximumPoolSize = 50;
            long keepAliveTime = 100;
            TimeUnit unit = TimeUnit.SECONDS;
            BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
            ThreadFactory threadFactory = Executors.defaultThreadFactory();
            RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
            ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    
            while (true) {
                Socket socket = server.accept();
                RequestProcessor processor = new RequestProcessor(socket, this.servletMap);
                executor.execute(processor);
            }
            */
    
            // Minicat 4.0 版本
            // 要求: 模拟 webapps 部署效果
            loadServer();
            loadServlet();
    
            ServerSocket server = new ServerSocket(this.port);
            System.out.println("Minicat start on port: " + this.port);
    
            // 创建线程池
            int corePoolSize = 10;
            int maximumPoolSize = 50;
            long keepAliveTime = 100;
            TimeUnit unit = TimeUnit.SECONDS;
            BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
            ThreadFactory threadFactory = Executors.defaultThreadFactory();
            RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
            ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    
            while (true) {
                Socket socket = server.accept();
                RequestProcessor processor = new RequestProcessor(socket, this.servletMap, this.mapper);
                executor.execute(processor);
            }
        }
    
        private Mapper mapper = new Mapper();
    
        private void loadServer() {
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("server.xml");
            SAXReader reader = new SAXReader();
    
            try {
                Document document = reader.read(inputStream);
                Element rootElement = document.getRootElement();
                // 解析 Connector
                loadConnector(rootElement);
                // 解析 Host
                loadHost(rootElement);
    
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 解析 Connector
         *
         * @param rootElement
         */
        private void loadConnector(Element rootElement) {
    
            Element connectorElement = (Element) rootElement.selectSingleNode("//Connector");
            if (connectorElement != null) {
                String connector = connectorElement.attributeValue("port");
                if (connector != null && !"".equals(connector)) {
                    this.port = Integer.parseInt(connector);
                }
            }
        }
    
        /**
         * 解析 Host
         *
         * @param rootElement
         */
        private void loadHost(Element rootElement) {
    
            List<Element> hostElements = rootElement.selectNodes("//Host");
            for (Element hostElement : hostElements) {
                Host host = new Host();
                String name = hostElement.attributeValue("name");
                String path = hostElement.attributeValue("base");
                host.setName(name + ":" + this.port);
                host.setPath(path);
    
                File base = new File(path);
                if (base.exists() && base.isDirectory()) {
                    File[] files = base.listFiles(new FileFilter() {
                        @Override
                        public boolean accept(File file) {
                            return file.isDirectory();
                        }
                    });
                    for (File file : files) {
                        loadContext(host, file);
                    }
                }
    
                // 添加 Host
                this.mapper.getHostMap().put(name + ":" + this.port, host);
            }
        }
    
        /**
         * 解析 Context
         *
         * @param host
         * @param directory
         */
        private void loadContext(Host host, File directory) {
            Context context = new Context();
            context.setName(directory.getName());
            File[] files = directory.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return "web.xml".equals(name);
                }
            });
            if (files != null && files.length > 0) {
                File file = files[0];
                if (file.exists() && file.isFile()) {
                    loadWrapper(context, file);
                }
            }
    
            host.getContextMap().put("/" + directory.getName(), context);
        }
    
        /**
         * 解析 Wrapper
         *
         * @param context
         * @param file
         */
        private void loadWrapper(Context context, File file) {
            SAXReader reader = new SAXReader();
    
            try {
                Document document = reader.read(file);
                List<Map<String, String>> properties = parse(document);
                for (Map<String, String> property : properties) {
                    String urlPattern = property.get("urlPattern");
                    String servletClass = property.get("servletClass");
                    HttpServlet httpServlet = loadClassByFilePath(file.getParentFile().getAbsolutePath(), servletClass);
                    Wrapper wrapper = new Wrapper();
                    wrapper.setServlet(httpServlet);
                    context.getWrapperMap().put(urlPattern, wrapper);
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
    
        }
    
        /**
         * 使用 URLClassLoader 加载 class 文件
         *
         * @param dir
         * @param servletClass
         * @return
         * @throws ClassNotFoundException
         * @throws NoSuchMethodException
         * @throws InvocationTargetException
         * @throws InstantiationException
         * @throws IllegalAccessException
         * @throws MalformedURLException
         */
        private HttpServlet loadClassByFilePath(String dir, String servletClass) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, MalformedURLException {
            URL[] urls = new URL[]{new URL("file:" + dir + "/")};
            URLClassLoader urlClassLoader = URLClassLoader.newInstance(urls);
            return (HttpServlet) urlClassLoader.loadClass(servletClass).getDeclaredConstructor().newInstance();
        }
    
        private Map<String, HttpServlet> servletMap = new HashMap<>();
    
        /**
         * 加载解析 server.xml, 初始化 Servlet
         */
        private void loadServlet() {
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
            SAXReader reader = new SAXReader();
    
            try {
                Document document = reader.read(inputStream);
                List<Map<String, String>> properties = parse(document);
                for (Map<String, String> property : properties) {
                    String urlPattern = property.get("urlPattern");
                    String servletClass = property.get("servletClass");
                    this.servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).getDeclaredConstructor().newInstance());
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    
        private List<Map<String, String>> parse(Document document) {
            List<Map<String, String>> properties = new ArrayList<>();
            Element rootElement = document.getRootElement();
            List<Element> nodes = rootElement.selectNodes("//servlet");
            for (Element element : nodes) {
                Map<String, String> property = new HashMap<>(8);
                Element servletNameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletNameElement.getStringValue();
                Element servletClassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletClassElement.getStringValue();
    
                // 根据 servlet-name 查找对应的 url-pattern
                Element servletMappingElement = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                String urlPattern = servletMappingElement.selectSingleNode("url-pattern").getStringValue();
    
                property.put("urlPattern", urlPattern);
                property.put("servletClass", servletClass);
                properties.add(property);
            }
            return properties;
        }
    
    }
    

    新增了解析 server.xml 相关方法,以及通过 URLClassLoader 类加载器加载非 classpath 下的类信息。因为解析 web.xml 文件代码相似,故此将其解析部分代码抽象为了 parse 方法。

问题

这次作业遇到做多的问题还是关于 URLClassLoader 的。

mmdetection各模块拆解(二)一阶段检测模型的构建(以FCOS为例) 一阶段检测模型的构建(以FCOS为例)引言一阶段检测模型的构成mmdet中的FCOS模型构建方法介绍mmdet模型一般构建过程FCOS 引言 对于笔者来说,学习mmdetection最重要的就是学会如何DIY自己的模型,那么弄懂经典的模型是如何一步步搭建出来的就显得非常重要。本章将从零开始,解构一阶段检测模型(以FCOS为例)在mmdetection中的构建过程。 一阶段检测模型的构成 一阶段检测模型(OneStageDetector)直接在提取到的特征图上进行目标位置和类别的密集预测。一阶段检测器的模型构 阅读详情

相关推荐

minicat.rar

《打工人也想有个属于自己的 Tomcat》博客附件。 博客地址:https://blog.youkuaiyun.com/Supreme_Sir/article/details/111050113

Tomcat在webapps下部署多个项目

1. tomcat部署多个项目的方式一 在进行一个tomcat下部署多个web项目的时候是可以直接在webapps文件夹下添加多个web项目,但是其实该不同的项目是占用一个相同服务器端口 此时打开项目是根据项目名称进行区分,然后只需要方访问tomcat默认的访问端口就行 2.tomcat部署多个项目的方式二 该方式是部署多个web项目,但是确占用不同的端口进行访问,测试你可以通过不同...

weixin_34025051的博客 2846

Python金融数据获取工具库之baostock使用详解

在金融数据分析和量化交易中,获取准确及时的市场数据是非常重要的。baostock是一个专门为中国股市数据提供支持的 Python 库,它提供了免费的股票数据接口,用户可以方便地获取股票、指数、基金等各种金融数据。本文将详细介绍baostock库,包括其安装方法、主要特性、基本和高级功能,以及实际应用场景,帮助全面了解并掌握该库的使用。

Rocky006的博客 5347

本地Tomcat如何部署多端口多模块项目

1.Maven集合下的项目,我的有得模块是jar包,有得是war包,所以不能单一的对某一个模块在右侧进行“package”,因为该模块是基于另一个模块的。比如我的很多模块都基于 commons mo

w524254582的博客 772

SFM(structure from motion 从运动恢复结构)和MVS(multi-view stereo 多视图立体视觉)

主要目的:SFM是重建稀疏点云的,MVS重建的是稠密点云。 输入的数据:SFM是没有标定的数据,而MVS输入的是标定的数据。 为什么SFM无法重建出稠密的点云,但是MVS可以? SFM中我们用来做重建的点是由特征匹配提供的!这些匹配点天生不密集!MVS则几乎对照片中的每个像素点都进行匹配,几乎重建每一个像素点的三维坐标,这样得到的点的密集程度可以较接近图像为我们展示出的清晰度。 SFM和MVS关系 SFM给MVS算好了输入视角的位姿,内参,稀疏点云以及它们的共视关系,MVS再利用这些信息以及彩色图

Vpn_zc的博客 1万+

企业级智能知识库问答AI助手(大模型+Python)

智能知识问答库AI助手

usa_washington的博客 1655

开发Minicat V4.0,在已有Minicat基础上进一步扩展,模拟出webapps部署效果 磁盘上放置一个webapps目录,webapps中可以有多个项目,例如demo1、demo2、demo

在minicat的resources目录下,增加server.xml配置文件 <?xml version="1.0" encoding="UTF-8" ?> <Server> <!--可以有多个service--> <Service> <Connector port="8080"/> <Engine> <Host name="localhost" appB

weixin_52717390的博客 940

Rclone替代RaiDrive?零广告免费挂载Alist WebDAV到Windows资源管理器(含自启脚本)

本文详细介绍了如何使用开源工具Rclone替代RaiDrive,实现零广告、全免费的Alist WebDAV挂载方案。通过深入解析配置参数、提供完整的自启动解决方案和解决常见问题,帮助用户在Windows资源管理器中高效管理云存储,提升使用体验。

weixin_33709364的博客 640

手写tomcat,实现简单功能

编程题 开发Minicat V4.0,在已有Minicat基础上进一步扩展,模拟出webapps部署效果 磁盘上放置一个webapps目录,webapps中可以有多个项目,例如demo1、demo2、demo3… 每个项目中含有servlet,可以根据请求url定位对应servlet进一步处理。 解答: 1)增加 server.xml配置文件,其中app元素指定appBase路径 <Server> <app appBase="G:/sources/Minicat/webapps"/

weixin_43960071的博客 470

DDR3性能优化实战:如何用Xilinx MIG控制器实现800MHz稳定读写(7系列FPGA版)

本文深入探讨了在Xilinx 7系列FPGA上使用MIG控制器实现DDR3存储器800MHz稳定高速读写的实战优化技巧。文章聚焦于高级时序调优、Bank Machine调度策略、用户接口设计优化以及利用ILA进行信号完整性调试,旨在帮助工程师突破性能瓶颈,实现接近理论峰值的稳定带宽,并为进一步冲刺更高频率提供进阶调参指南。

seed的博客 779

Skyworks SKY85331-11的Wi-Fi 6 (802.11ax)标准 2.4G 高功率WLAN前端模块解决方案

SKY85331-11是高度集成的2 GHz前端模块(FEM)包含2 GHz单刀双掷(SPDT)发送/接收(T / R)开关,2 GHz低噪声放大器(LNA)带旁路和一个2 GHz功率放大器(PA),用于大功率802.11ax应用程序和系统LNA和PA禁用功能可确保低漏电流 关闭模式。 包括一个集成的功率检测器以提供系统内的闭环功率控制。该设备提供Small (24-pin, 3 x 5 mm) (LGA)封装。 图1.引脚配置和封装如图所示 图2.信号引脚分配和功能引脚描述 图...

zhangbao19890622的博客 4508

阶段一模块二总结

阶段一模块二总结

qq_23187859的博客 311

Android 64位支持的坑:诡异的文件名问题

最近在尝试发布我的Android应用程序的更新时,遇到了一个令人困惑的64位错误。本文将详细讲解这个问题的产生原因及解决方法,供大家参考。

m0_74337424的博客 125

阶段一模块二

Java阶段一 模块二

wangxu123445678的博客 4693

基于STM32的太阳能充电宝设计_资料编号31

系统硬件包括主控 STM32F103C8T6、0.96 OLED 显示屏、蜂鸣器、电源自锁开关、温度传感器 DS18B20、继电器、5 V DC 升压模块 、TB4056、18650锂电池、9 V太阳能板、稳压降压 5 V三极管。电源供应:锂电池为系统供电,9 伏太阳能板经 5 伏降压稳压三极管降压为 5 伏后传送到 TP4056,TP4056 为锂电池供电,因锂电池电压 3.7 伏,通过 5 伏 DC 升压模块升压到 5 伏为整个系统提供 5 伏电压。

嵌入式阿齐Archie 1万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

阶段二模块一 MySQL基础和SQL入门

内容输出来源:拉钩教育Java就业训练营 1 数据库的基本概念 数据库(DataBase) 就是存储和管理数据的仓库 其本质是一个文件系统, 还是以文件的方式,将数据保存在电脑上 数据库存储方式比较: 存储方式 优点 缺点 内存 速度快 不能够永久保存,数据是临时状态的 文件 数据可以永久保存 使用IO流操作文件, 不方便 数据库 1.数据可以永久保存2.方便存储和管理数据3.使用统一的方式操作数据库(SQL) 占用资源,有些数据库需要付费(比如Oracle数据库) 2 SQ

wangxu123445678的博客 248

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【infra之路】阶段二 · 模块一:GPU 架构与显存层级

本文为AI基础设施学习路线第二阶段模块一的理论基础,重点解析GPU如何支持深度学习。核心内容包括:1) CPU与GPU的本质差异,GPU凭借数千简单核心和高吞吐特性,特别适合并行矩阵运算;2) 任务适合GPU的关键标准是可分解为独立并行计算;3) GPU采用SIMT模式,单指令驱动多线程同步执行;4) SM作为基础执行单元,影响任务调度效率;5) 显存分全局、共享和寄存器三层,速度与容量呈反比;6) nvidia-smi显示的显存占用主要指全局显存。这些理论为后续CUDA编程和显存优化奠定基础。

sweet_ran的博客 409

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

阶段一模块四任务二:IO流

第十七章 IO流 17.1 IO流的概念 IO就是Input和Output的简写,也就是输入和输出的含义。 IO流就是指读写数据时像流水一样从一端流到另外一端,因此得名为“流"。 17.2 基本分类 按照读写数据的基本单位不同,分为 字节流 和 字符流。 其中字节流主要指以字节为单位进行数据读写的流,可以读写任意类型的文件。 其中字符流主要指以字符(2个字节)为单位进行数据读写的流,只能读写文本文件。 按照读写数据的方向不同,分为 输入流 和 输出流(站在程序的角度)。 其中输入流主要指从文件中读取数据内容

weixin_41930667的博客 102

阶段二模块一任务一:MySQL基础和SQL入门

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习..

weixin_40351820的博客 174

阶段二模块一 MySql单表、约束和事务

内容输出来源:拉钩教育Java就业训练营 1 DQL操作单表 1.1 排序 通过 ORDER BY 子句,可以将查询出的结果进行排序(排序只是显示效果,不会影响真实数据) -- 排序 ASC 表示升序排序(默认) DESC 表示降序排序 SELECT 字段名 FROM 表名 [WHERE 字段 = 值] ORDER BY 字段名 [ASC / DESC] 1.1.1 排序方式 单列排序 只按照某一个字段进行排序, 就是单列排序 -- 默认升序排序 ASC SELECT * FROM emp ORDE

wangxu123445678的博客 149

阶段三模块一 直播二 手写VurRouter-hash模式

目标 观察vue-router源码-实现路由嵌套功能 Vue-Router 演示基本效果 Vue-Router 源码结构 Vue.use() 注册插件源码 src\core\global-api\use.js export function initUse (Vue: GlobalAPI) { // Vue.use(VueRouter, options) Vue.use = function (plugin: Function | Object) { const installedPl

weixin_45345105的博客 245

阶段二模块一 MySQL索引、视图和存储过程

内容输出来源:拉钩教育Java就业训练营 1 MySql索引 在数据库表中,对字段建立索引可以大大提高查询速度。通过善用这些索引,可以令MySQL的查询和运行更加高效。 1.1 常见索引分类 索引名称 说明 主键索引 (primary key) 主键是一种唯一性索引,每个表只能有一个主键, 用于标识数据表中的每一条记录 唯一索引 (unique) 唯一索引指的是 索引列的所有值都只能出现一次, 必须唯一. 普通索引 (index) 最常见的索引,作用就是 加快对数据的访问速度 1

wangxu123445678的博客 189

数据分析实训 阶段二 模块一 mysql基础与核心查询 by拉钩教育

一、mysql基础 1、数据库基本概念 2、mysql数据库 3、mysql安装与配置 暂略 4、sql语句操作 4.1 sql通用语法 SQL语句可以单行 或者 多行书写,以分号结尾 ; (Sqlyog中可以不用写分号) 可以使用空格和缩进来增加语句的可读性。 MySql中使用SQL不区分大小写 4.2 mysql注释 单行注释 # 或 – 多行注释 /* …*/ 4.3 DDL 数据库定义语言 操作数据库 创建数据库 # 创建指定名称的库 create database db1; # 指定数

qq_32795481的博客 229

阶段二模块一 MySql多表、外键和数据库设计

内容输出来源:拉钩教育Java就业训练营 1 多表 实际开发中,一个项目通常需要很多张表才能完成。 1.1 单表的缺点 冗余, 同一个字段中出现大量的重复数据 1.2 解决方案 1.2.1 设计为两张表 员工表中有一个字段dept_id 与部门表中的主键对应,员工表的这个字段就叫做外键 拥有外键的员工表 被称为从表, 与外键对应的主键所在的表叫做主表 1.2.2 多表设计上的问题 当我们在 员工表的 dept_id 里面输入不存在的部门id ,数据依然可以添加 显然这是不合理的. 1.3 外键约束 外键指的

wangxu123445678的博客 261

centerpoint网络结构

然后,检测头部分生成热力图来预测目标中心点,同时回归其他属性,比如尺寸、方向、速度等。损失函数方面,一阶段的热力图用高斯焦点损失,回归用L1,二阶段则用交叉熵和L1。CenterPoint网络结构分为两阶段,整体围绕点云数据的3D目标检测与跟踪设计,核心思路是将目标表示为几何中心点,并通过特征回归实现属性预测。需要把这些部分有条理地组织起来,可能分阶段描述,每个阶段的组件和功能,以及各部分的损失函数和实现细节。另外,速度估计和跟踪部分也是结构的一部分,通过回归速度来实现帧间匹配,简化跟踪流程。

luoganttcc的博客 1858
上一篇: 阶段一模块四
下一篇: 阶段二模块二
LiveForCode
博客等级 码龄5年 2粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值