jbase仪器接口设计

jbase的计划有借助虚拟M来实现连仪器,之前陆续写了些TCP逻辑,今天终于整理完成了仪器设计。首先用java的cs程序测试TCP的服务和客户端。

javafx的示例加强

package sample;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.ScrollPane;

import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

public class Main extends Application {

    //数字
    static int num = 0;

    //场景
    Scene scene;

    //场景1
    Scene scene1;

    //定时发送
    Socket sendSocket = null;

    //自动发送次数
    int sendNum = 0;

    //通讯日志
    StringBuilder sbLog=new StringBuilder();

    //换行符
    String lineStr=System.getProperty("line.separator");


    @Override
    public void start(Stage stage) throws Exception {
        //舞台标题
        stage.setTitle("第一个java程序");
        // 流式布局:按照控件的添加次序按个摆放,按照从上到下、从左到右的次序摆放。
        FlowPane pane = new FlowPane(5, 5);
        // 居中显示
        pane.setAlignment(Pos.CENTER);
        // 场景
        scene = new Scene(pane, 800, 600);


        // 标签
        Label label = new Label("初始值:" + num);


        // 加1按钮
        Button addButton = new Button("加1");
        addButton.setOnMouseClicked(e -> {
            num++;
            label.setText("当前值:" + num);
        });

        //减1按钮
        Button subButton = new Button("减1");
        subButton.setOnMouseClicked(e -> {
            num--;
            label.setText("当前值:" + num);
        });

        //切换到场景1
        Button btnScene1 = new Button("场景1");
        btnScene1.setOnMouseClicked(e -> {
            stage.setScene(scene1);
        });

        //弹出一个子窗口
        Button btnShowChildForm = new Button("子窗口");
        btnShowChildForm.setOnMouseClicked(e -> {
            Child.ShowChild("子窗口", "传给子窗口的参数");
        });

        // 创建一个TextArea控件
        TextArea textArea = new TextArea();
        textArea.setWrapText(true); // 设置文本自动换行

        //定时器,主动上传时候用
        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                if (sendSocket != null) {
                    try {
                        sendNum++;
                        // 发送请求消息到服务端
                        OutputStream outputStream = sendSocket.getOutputStream();
                        PrintWriter out = new PrintWriter(new OutputStreamWriter(outputStream, "GBK"), true);
                        out.println("这是定时发送的第" + sendNum + "次数据");
                        out.flush();
                    } catch (Exception ex) {

                    }
                }
            }
        };
        // 设置定时器的执行策略,延迟0秒后开始执行,每隔1秒执行一次
        timer.schedule(task, 0, 5000);


        //启动tcp服务
        Button btnTcpServer = new Button("TCP服务");
        btnTcpServer.setOnMouseClicked(e -> {
            Thread clientThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        ServerSocket serverSocket = new ServerSocket(8888);
                        //增加一个无限循环
                        while (true) {
                            sbLog.append("服务启动"+lineStr);
                            System.out.println("服务启动");
                            //通知界面
                            javafx.application.Platform.runLater(()->{
                                textArea.setText(sbLog.toString());
                            });
                            //等待客户端连接,阻塞
                            Socket clientSocket = serverSocket.accept();
                            sendSocket = clientSocket;
                            //得到输出流
                            PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
                            System.out.println("客户端连接");
                            sbLog.append("客户端连接"+lineStr);
                            //通知界面
                            javafx.application.Platform.runLater(()->{
                                textArea.setText(sbLog.toString());
                            });
                            //得到输入流
                            InputStream inputStream = clientSocket.getInputStream();
                            //IO读取
                            byte[] buf = new byte[10240];
                            int readlen = 0;
                            //阻塞读取数据
                            while ((readlen = inputStream.read(buf)) != -1) {
                                System.out.println(new String(buf, 0, readlen, "GBK"));
                                sbLog.append(new String(buf, 0, readlen, "GBK")+lineStr);
                                //通知界面
                                javafx.application.Platform.runLater(()->{
                                    textArea.setText(sbLog.toString());
                                });
                            }
                            //关闭输入
                            inputStream.close();
                            //关闭输出
                            out.close();
                            clientSocket.close();
                        }
                    } catch (Exception e) {

                    }
                }
            });
            clientThread.start();
        });

        //启动tcp客户端
        Button btnTcpClient = new Button("TCP客户端");
        btnTcpClient.setOnMouseClicked(e -> {
            Thread clientThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        try {
                            // 创建 Socket 对象并连接到服务端
                            Socket socket = new Socket("172.16.1.232", 1991);
                            sendSocket = socket;
                            // 发送请求消息到服务端
                            OutputStream outputStream = socket.getOutputStream();
                            PrintWriter out = new PrintWriter(new OutputStreamWriter(outputStream, "GBK"), true);
                            out.println("你好,我是客户端");
                            out.flush();
                            //得到输入流
                            InputStream inputStream = socket.getInputStream();
                            //IO读取
                            byte[] buf = new byte[10240];
                            int readlen = 0;
                            //阻塞读取数据
                            while ((readlen = inputStream.read(buf)) != -1) {
                                System.out.println(new String(buf, 0, readlen, "GBK"));
                                sbLog.append(new String(buf, 0, readlen, "GBK")+lineStr);
                                out.println("我已经收到数据");
                                //通知界面
                                javafx.application.Platform.runLater(()->{
                                    textArea.setText(sbLog.toString());
                                });
                            }
                            //关闭输入
                            inputStream.close();
                            //关闭输出
                            out.close();
                            // 关闭连接
                            socket.close();
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    } catch (Exception e) {

                    }
                }
            });
            clientThread.start();
        });

        pane.getChildren().addAll(addButton, subButton, btnScene1, btnShowChildForm, label, textArea, btnTcpServer, btnTcpClient);


        // 场景1
        // 流式布局:按照控件的添加次序按个摆放,按照从上到下、从左到右的次序摆放。
        FlowPane pane1 = new FlowPane(10, 10);
        // 居中显示
        pane1.setAlignment(Pos.CENTER);
        scene1 = new Scene(pane1, 200, 150);

        //返回开始的场景
        Button btnReturn = new Button("返回");
        btnReturn.setOnMouseClicked(e -> {
            stage.setScene(scene);
        });
        pane1.getChildren().addAll(btnReturn);

        //默认场景和显示
        stage.setScene(scene);
        stage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

在这里插入图片描述

客户端测试成功后设计jbase仪器基础,这里首先要理解连设备的本质,连TCP设备的话,其实真正的业务只关心我当做客户端还是服务端、以什么编码、然后解析和发送数据,我并不想关系TCP的实现细节。所以可以把初始化TCP和处理数据及定时上传以接口形式抽取出来。

先抽取处理仪器数据接口IMachDealData,具体仪器只需要实现该接口即可,抽取变性很重要

package LIS.Core.Socket;

import java.io.PrintWriter;
import java.net.Socket;

/**
 * 仪器处理数据接口,具体的仪器接口实现此接口后初始化MachSocketBase对象
 */
public interface IMachDealData {
    /**
     * 处理上传定时器接口
     * @param sender Socket对象,用来发送比特用
     * @param writer 用来发布初始化指定的字符用
     */
    public void DealUpTimer(Socket sender, PrintWriter writer);

    /**
     * 处理数据接收
     * @param data 公共层处理成字符串的数据
     * @param buf 没处理的比特数组
     * @param sender Socket对象,用来发送比特用
     * @param writer 用来发布初始化指定的字符用
     */
    public void DealReceive(String data, byte[] buf, Socket sender, PrintWriter writer);

}

然后实现MachSocketBase类作为连接TCP仪器的基础类,里面实现了tcp的客户端和服务端和定时器,里面对数据处理都是调用接口操作

package LIS.Core.Socket;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import LIS.Core.Socket.IMachDealData;
import LIS.Core.Util.LogUtils;

/**
 * 通过Socket连接的仪器操作基类,由该类提供TCP客户端和服务端的公共逻辑,并且调用处理数据接口处理数据,从而分离TCP主体和业务处理逻辑,达到简化连设备目的
 */
public class MachSocketBase {
    /**
     * 发送数据的操作对象
     */
    public Socket Sender = null;

    /**
     * 写操作对象
     */
    public PrintWriter Writer = null;

    /**
     * 主动上传定时器
     */
    public Timer UpTimer = null;

    /**
     * 处理接口对象
     */
    public IMachDealData DealObj;

    /**
     * 编码
     */
    public String Encode;

    /**
     * 要关闭的客户端端口
     */
    private Socket closeSocket = null;

    /**
     * 要关闭的服务端口
     */
    private ServerSocket closeServerSocket = null;

    /**
     * 存IP和端口的唯一标识串
     */
    public String ID;

    /**
     * 处理类的全面
     */
    public String DealClassName;

    /**
     * 主处理进程
     */
    Thread MainThread = null;

    /**
     * 定时器任务
     */
    TimerTask timerTask = null;

    /**
     * 上传间隔
     */
    Long UpPeriod = null;

    /**
     * 存启动和停止的错误串
     */
    public String Err="";

    /**
     * 停止负载
     *
     * @return 有错误就返回错误
     */
    public String Stop() {
        try {
            if (MainThread != null) {
                MainThread.interrupt();
            }
            if (UpTimer != null) {
                UpTimer.cancel();
            }
            if (closeSocket != null) {
                closeSocket.close();
                ;
            }
            if (closeServerSocket != null) {
                closeServerSocket.close();
                ;
            }
        } catch (Exception ex) {
            Err=ex.getCause().getMessage();
            LogUtils.WriteExceptionLog("停止仪器TCP异常", ex);
            return ex.getCause().getMessage();
        }
        return "";
    }


    /**
     * 启动连接和定时器
     * @return 有错误就返回错误
     */
    public String Start() {
        try {
            if (UpTimer != null) {
                // 设置定时器的执行策略,延迟0秒后开始执行,每隔1秒执行一次
                UpTimer.schedule(timerTask, 0, UpPeriod);
            }
            if (MainThread != null) {
                MainThread.start();
            }
        } catch (Exception ex) {
            Err=ex.getCause().getMessage();
            LogUtils.WriteExceptionLog("启动仪器TCP异常", ex);
            return ex.getCause().getMessage();
        }
        return "";

    }


    /**
     * 构造一个Socket基础并且启动Socket
     *
     * @param ip       IP地址,当服务端传空串
     * @param port     端口
     * @param upPeriod 上传毫秒间隔,不是主动上传的传null
     * @param dealObj  处理接口实现类
     * @param encode   编码格式,传null或空串默认为GBK
     */
    public MachSocketBase(String ip, int port, Long upPeriod, IMachDealData dealObj, String encode) {
        //处理对象
        DealObj = dealObj;
        //编码
        if (encode == null || encode.isEmpty()) {
            encode = "GBK";
        }
        Encode = encode;
        UpPeriod = upPeriod;
        ID = ip + ":" + port;
        if(dealObj!=null)
        {
            DealClassName=dealObj.getClass().getName();
        }
        //上传定时器
        if (upPeriod != null) {
            UpTimer = new Timer();
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    try {
                        //初始化写对象
                        if (Sender != null && Writer == null) {
                            Writer = new PrintWriter(new OutputStreamWriter(Sender.getOutputStream(), Encode), false);
                        }
                        DealObj.DealUpTimer(Sender, Writer);
                    } catch (Exception ex) {
                        LogUtils.WriteExceptionLog("仪器上传定时器异常", ex);
                    }
                }
            };

        }
        //当客户端
        if (!ip.isEmpty()) {
            MainThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    //得到输入流
                    InputStream inputStream = null;
                    //创建Socket对象并连接到服务端
                    Socket socket = null;
                    try {
                        //创建Socket对象并连接到服务端
                        socket = new Socket(ip, port);
                        Sender = socket;
                        closeSocket = socket;
                        Writer = new PrintWriter(new OutputStreamWriter(Sender.getOutputStream(), Encode), false);
                        //得到输入流
                        inputStream = socket.getInputStream();
                        //IO读取
                        byte[] buf = new byte[102400];
                        int readlen = 0;
                        //阻塞读取数据
                        while ((readlen = inputStream.read(buf)) != -1) {
                            String res = new String(buf, 0, readlen, Encode);
                            byte[] targetArray = new byte[readlen];
                            System.arraycopy(buf, 0, targetArray, 0, readlen);
                            //处理接收数据
                            DealObj.DealReceive(res, targetArray, Sender, Writer);
                        }
                    } catch (IOException ex) {
                        LogUtils.WriteExceptionLog("侦听仪器TCP异常", ex);
                    } finally {
                        try {
                            if (inputStream != null) {
                                //关闭输入
                                inputStream.close();
                            }
                            if (Writer != null) {
                                Writer.flush();
                                //关闭输出
                                Writer.close();
                            }
                            if (socket != null) {
                                // 关闭连接
                                socket.close();
                            }
                        } catch (Exception ex) {
                            LogUtils.WriteExceptionLog("释放TCP资源异常", ex);
                        }

                    }
                }
            });

        }
        //当服务端
        else {
            MainThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    //得到输入流
                    InputStream inputStream = null;
                    //创建Socket对象并连接到服务端
                    Socket socket = null;
                    try {
                        ServerSocket serverSocket = new ServerSocket(port);
                        closeServerSocket = serverSocket;
                        //增加一个无限循环
                        while (true) {
                            //等待客户端连接,阻塞
                            socket = serverSocket.accept();
                            Sender = socket;
                            //得到输出流
                            Writer = new PrintWriter(new OutputStreamWriter(Sender.getOutputStream(), Encode), false);
                            //得到输入流
                            inputStream = socket.getInputStream();
                            //IO读取
                            byte[] buf = new byte[102400];
                            int readlen = 0;
                            //阻塞读取数据
                            while ((readlen = inputStream.read(buf)) != -1) {
                                String res = new String(buf, 0, readlen, Encode);
                                byte[] targetArray = new byte[readlen];
                                System.arraycopy(buf, 0, targetArray, 0, readlen);
                                //处理接收数据
                                DealObj.DealReceive(res, targetArray, Sender, Writer);
                            }
                        }
                    } catch (IOException ex) {
                        LogUtils.WriteExceptionLog("侦听仪器TCP异常", ex);
                    } finally {
                        try {
                            if (inputStream != null) {
                                //关闭输入
                                inputStream.close();
                            }
                            if (Writer != null) {
                                Writer.flush();
                                //关闭输出
                                Writer.close();
                            }
                            if (socket != null) {
                                // 关闭连接
                                socket.close();
                            }
                        } catch (Exception ex) {
                            LogUtils.WriteExceptionLog("释放TCP资源异常", ex);
                        }

                    }
                }
            });
        }

    }
}

然后为了统一管理所有TCP仪器提供MachManager,接口开发者之需要关心GetMachSocketBase方法

package LIS.Core.Socket;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import LIS.Core.Socket.MachSocketBase;
import LIS.Core.Socket.IMachDealData;

/**
 * 统一管理所有仪器的MachSocketBase对象
 */
public class MachManager {
    /**
     * 存所有仪器连接
     */
    public static ConcurrentHashMap<String, MachSocketBase> AllMach = new ConcurrentHashMap<>();

    /**
     * 更新处理接口对象
     * @param dealClass
     * @throws Exception
     */
    public static void UpdateDeal(Class dealClass) throws Exception
    {
        String dealClsName=dealClass.getName();
        for (Map.Entry<String, MachSocketBase> entry : AllMach.entrySet()) {
            String key = entry.getKey();
            MachSocketBase value = entry.getValue();
            if(value.DealClassName.equals(dealClsName))
            {
                //创建对象
                Object o = dealClass.getConstructor().newInstance();
                value.DealObj=(IMachDealData)o;
                System.out.println("更新:"+value.ID+"的数据处理类");
            }
        }
    }

    /**
     * 得到仪器连接的Socket管理类,直接就启动了控制了
     * @param ip IP地址,当服务端传空串
     * @param port 端口
     * @param upPeriod 上传毫秒间隔,不是主动上传的传null
     * @param dealObj 处理接口实现类
     * @param encode 编码格式,传null或空串默认为GBK
     * @return
     */
    public static MachSocketBase GetMachSocketBase(String ip, int port, Long upPeriod, IMachDealData dealObj, String encode)
    {
        MachSocketBase base=new MachSocketBase(ip,port,upPeriod,dealObj,encode);
        //注册到管理
        RegisterMachSocketBase(base);
        return base;
    }

    /**
     * 注册到管理
     * @param base
     */
    public static void RegisterMachSocketBase(MachSocketBase base)
    {
        //先停止老的接口
        if(AllMach.containsKey(base.ID))
        {
            AllMach.get(base.ID).Stop();
            AllMach.remove(base.ID);
        }
        //加入管理
        AllMach.put(base.ID,base);
        base.Start();
    }
}

然后为了解决修改仪器接口脚本后实时生效实现仪器注解,接口修改后会自动调用MachManager.UpdateDeal更新处理类,这样不用频繁重启仪器控制

//特性,申明此特性的仪器接口在修改后自动调用启动
package LIS.Core.CustomAttributes;

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  Mach {

}

在这里插入图片描述

然后实现一个实例仪器接口
在这里插入图片描述

import LIS.Core.CustomAttributes.Mach;
import LIS.Core.Socket.IMachDealData;
import LIS.Core.Socket.MachSocketBase;
import appcode.BaseHttpHandlerNoSession;
import appcode.Helper;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

/**
 *连仪器示例代码
 */
@Mach
public class MachDemo extends BaseHttpHandlerNoSession implements IMachDealData {
    /**
     * 缓存数据
     */
    private static StringBuilder dataCache=new StringBuilder();

    //换行符
    private static String lineStr=System.getProperty("line.separator");

    /**
     * 显示日志
     * http://localhost:8080/ankilis/mi/MachDemo.ashx?Method=ShowLog
     * @return
     */
    public String ShowLog()
    {
        return dataCache.toString();
    }

    /**
     * 启动控制
     * http://localhost:8080/ankilis/mi/MachDemo.ashx?Method=Start
     * @return
     * @throws Exception
     */
    public String Start() throws Exception
    {
        //ip地址
        String ip=Helper.ValidParam(LIS.Core.MultiPlatform.LISContext.GetRequest(Request, "ip"), "");
        //端口
        int port=Helper.ValidParam(LIS.Core.MultiPlatform.LISContext.GetRequest(Request, "port"), 8888);
        MachSocketBase base=LIS.Core.Socket.MachManager.GetMachSocketBase(ip,port,Long.valueOf(5000),this,"GBK");
        if(base.Err.isEmpty())
        {
            return Helper.Success();
        }
        else
        {
            return Helper.Error(base.Err);
        }
    }

    /**
     * 处理上传定时器接口
     * @param sender Socket对象,用来发送比特用
     * @param writer 用来发布初始化指定的字符用
     */
    public void DealUpTimer(Socket sender, PrintWriter writer)
    {
        String sendStr="H->M:我主动定时给你推送的数据</br>";
        //返回数据
        writer.print(sendStr);
        writer.flush();
        dataCache.append(sendStr+lineStr);
    }

    /**
     * 处理数据接收
     * @param data 公共层处理成字符串的数据
     * @param buf 没处理的比特数组
     * @param sender Socket对象,用来发送比特用
     * @param writer 用来发布初始化指定的字符用
     */
    public void DealReceive(String data, byte[] buf, Socket sender, PrintWriter writer)
    {
        //缓存数据
        dataCache.append("M->H:"+data+lineStr);
        String sendStr="H->M:我收到你发给我的:"+data+"</br>";
        //返回数据
        writer.print(sendStr);
        writer.flush();
        dataCache.append(sendStr+lineStr);
    }
}

启动控制
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这样就可以在这个基础上轻松连接TCP的仪器了,还是脚本化、还不用来回重启控制

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

接入keycloak实现单点登录

问题 1.如果跨域在keycloak管理中心Clients-Client details-Settings-Web origins添加浏览器访问地址就行 一、html引入cdn实现 页面引入 <!-- keycloak --> <script src"https://unpkg.com/keycloak-js22.0.5/dist/keycloak.js"></script> &l…

UE4基础篇十六:自定义 EQS 生成器

UE4 中的 EQS 带有一组很好的查询项生成器,但在某些情况下,您可能更喜欢根据需要创建生成器。我决定编写自己的生成器,因为我必须编写一个查询来找到查询器周围的最佳位置,但又不能太靠近它。我知道我可以添加一个距离测试来随着距离增加分数,但我什至不想考虑距查询器一定…

成长在于积累——https 认证失败的学习与思考

1. 引言 本周二长城项目在收尾过程中&#xff0c;出现了一个车端无法进行注册的问题&#xff1a;curl提示证书认证失败&#xff08;其实已经能确认问题方向了&#xff0c;运维人员去确认证书问题即可&#xff09;。虽然最终的原因是由于长城运维人员导致的。但是这个过程让我颇…

DeepMind 推出 OPRO 技术,可用于优化 ChatGPT 提示

本心、输入输出、结果 文章目录 DeepMind 推出 OPRO 技术&#xff0c;可用于优化 ChatGPT 提示前言消息摘要OPRO的工作原理DeepMind的研究相关链接花有重开日&#xff0c;人无再少年实践是检验真理的唯一标准 DeepMind 推出 OPRO 技术&#xff0c;可用于优化 ChatGPT 提示 编辑…

NSSCTF web刷题记录6

文章目录 [HZNUCTF 2023 final]eznode[MoeCTF 2021]地狱通讯-改[红明谷CTF 2022] Smarty Calculator方法一 CVE-2021-26120方法二 CVE-2021-29454方法三 写马蚁剑连接 [HZNUCTF 2023 final]eznode 考点&#xff1a;vm2沙箱逃逸、原型链污染 打开题目&#xff0c;提示找找源码 …

【数据结构(四)】栈(1)

文章目录 1. 关于栈的一个实际应用2. 栈的介绍3. 栈的应用场景4. 栈的简单应用4.1. 思路分析4.2. 代码实现 5. 栈的进阶应用(实现综合计算器)5.1. 栈实现一位数计算(中缀表达式)5.1.1. 思路分析5.1.2. 代码实现 5.2. 栈实现多位数计算(中缀表达式)5.2.1. 解决思路5.2.2. 代码实…

私域运营如何提高收益?

一旦建立了私域之后&#xff0c;企业需要不断地进行数据统计与分析&#xff0c;以寻找提高收益的方法。通过收集和分析用户的信息&#xff0c;了解他们的购物行为、心理需求等&#xff0c;从而制定更符合顾客口味的促销计划和产品服务。只有持续对数据进行监控&#xff0c;才能…

Markdown Nice:表格

第二行用来对齐&#xff1a; -表示左对齐 :-:表示居中 -:表示右对齐

安防监控视频云存储平台EasyCVR页面播放卡顿的优化方法

视频监控平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多路视频流&#xff0c;也能支持视…

股票池(三)

3-股票池 文章目录 3-股票池一. 查询股票池支持的类型二. 查询目前股票池对应的股票信息三 查询股票池内距离今天类型最少/最多的股票数据四. 查询股票的池统计信息 一. 查询股票池支持的类型 接口描述: 接口地址:/StockApi/stockPool/listPoolType 请求方式&#xff1a;GET…

Jmeter监听器

Jmeter监听器 一、监听器介绍二、监听器的类型三、监听器详解3.1 察看结果树3.2 Summary Report3.3 聚合报告3.4 后端监听器3.5 Aggregate Graph3.6 Comparison Assertion Visualizer&#xff08;比较断言可视化器&#xff09;3.7 JSR223 Listener3.8 Response Time Graph3.9 S…

第三届VECCTF-2023 Web方向部分wp

拳拳组合 题目描述&#xff1a;明喜欢保存密钥在某个文件上。请找到秘钥并读取flag文件。 开题&#xff0c;点不完的。源码提示&#xff1a; <!--据说小明很喜欢10的幂次方--> 扫一下看看&#xff0c;应该是有git泄露。 其它一些路由没什么用 git泄露拿下一堆码 pytho…

API网关那些事【架构新知系列】

目前随着云原生ServiceMesh和微服务架构的不断演进&#xff0c;网关领域新产品不断出现&#xff0c;各种网关使用的技术&#xff0c;功能和应用领域也不断扩展&#xff0c;在各有所长的前提下也有很多功能重合&#xff0c;网上各种技术PR文章&#xff0c;评测资料和网关落地实践…

从零开始的C++(十八)

avl树中insert的模拟实现 avl树特点&#xff1a; 1.是搜索二叉树 2.每个结点的左右子树高度差的绝对值不超过2 inser模拟实现&#xff1a; // 右单旋void RotateR(Node* pParent){Node* parent pParent;Node* pr parent->_pRight;Node* prl pr->_pLeft;//记录父节点…

spring boot项目未将resource目录标志为资源目录导致配置文件无效因而运行报错问题

能编译&#xff0c;但不能运行。感觉配置文件没有生效。 将程序代码发给同事&#xff0c;我自己能跑&#xff0c;他不能跑&#xff0c;提示无法构造redis对象。redis的链接写在配置文件里&#xff0c;其实是可以连接的。然后从GIT库下载代码&#xff0c;也同样不能跑。同事的操…

CV计算机视觉每日开源代码Paper with code速览-2023.11.16

点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【基础网络架构】ConvNet vs Transformer, Supervised vs CLIP: Beyond ImageNet Accuracy 论文地址&#xff1a;https://arxiv.org//pdf/23…

VBA技术资料MF85:将工作簿批量另存为PDF文件

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…

基于SSM的社区生鲜商城的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

【探索嵌入式虚拟化技术与应用】— 虚拟化技术深入浅出自学系列

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏:【探索嵌入式虚拟化技术与应用】&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 一、虚拟技术的发展历史 1.1传统技术的局限性&#xff1a; ​编辑 1.2云计算和万物互联技术的发展机遇&#x…

Altium Designer学习笔记6

原理图库的制作&#xff0c;SMA元件的制作&#xff1a; 图形不是很重要&#xff0c;重要的是管脚的功能。 Design Item ID和Designator两个值是要注意的。 进行Place放置&#xff0c;切换到原理图工作区&#xff0c;测试下功能。 AD9851元件库制作&#xff1a; 不需要再新建原…
最新文章