[实战]Springboot与GB28181摄像头对接。摄像头注册上线(一)

news2024/11/18 21:38:07

与支持国标摄像头对接

  • 前言:不想看教程?
  • 1、准备阶段
    • 1.1、我们会学到什么?
    • 1.2、创建项目
    • 1.3、pom中用到的依赖
    • 1.4 打开摄像头的网址(了解配置方式)
  • 2、代码编写
    • 2.1、增加项目配置
    • 2.2、在config目录下创建SipConfig
    • 2.3、在service目录下创建SipService
    • 2.4、在adapter目录下创建如下类
    • 2.5、在listener准备如下类
    • 2.7、准备基础的枚举类(enums目录下)
  • 3、按照项目配置摄像头的SIP
  • 4、启动项目

前言:不想看教程?

   想直接拿源码?Qq:1101165230

1、准备阶段

  电脑和idea这个肯定是要准备的,然后准备几台(或一台)支持国标对接的摄像头。要知道摄像头的访问地址账号和密码。

1.1、我们会学到什么?

   在这个项目中我们会用到一些设计模式以及一些注解平时可能不太常用的注解。我们还额外的知道了与物联网相关的一些对接知识。(文章中可能更多的是代码上的,为了便于大家直接CV。对于理论知识的大家可以私我,我可以出一期视频讲解这个项目)

1.2、创建项目

  我们在这里创建的是一个WebFlux的项目,便须后期处理设备的命令。
结构如下:(ps: 在idea的Terminal中输入tree或者tree -f,-f会包含目录下文件名)

<!--打印目录-->
tree
<!--打印目录带文件-->
tree -f
<!--将目录输出到文件并保存-->
tree /f >> D:/tree.txt
gb28181-sg
│
├─src
│  ├─main
│  │  ├─java
│  │  │  └─org
│  │  │      └─ougnuhs
│  │  │          └─gb
│  │  │              │  GbApplication.java 
│  │  │              ├─adapter
│  │  │              ├─config 
│  │  │              ├─controller     
│  │  │              ├─enums
│  │  │              │  └─base        
│  │  │              ├─listener    
│  │  │              ├─service     
│  │  │              └─utils                   
│  │  └─resources         
│  └─test
│      └─java
└─target

1.3、pom中用到的依赖

 &emsp(这里只放了dependencies)SIP依赖特别需要。

 <dependencies>

        <!-- SpringBoot 核心包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--SIP-->
        <!-- sip协议栈 -->
        <dependency>
            <groupId>javax.sip</groupId>
            <artifactId>jain-sip-ri</artifactId>
            <version>1.3.0-91</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!-- 引入log4j2依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

    </dependencies>

1.4 打开摄像头的网址(了解配置方式)

这里大家先看一下,熟悉摄像头配置位置,不用填写。
找到如图位置
我这里用的是海康摄像头,摄像头的网页配置地址就是摄像头的ip地址。我们可以看到在平台接入的地方需要填写SIP的一些信息,以及提供服务的ip。
红框里的就是我们在项目中的
这个是我之前配置过的,对于新摄像头可能没有,不过没关系,我们在项目中配置成什么这里就填写成什么即可。

2、代码编写

2.1、增加项目配置

  在前面我们创建好了项目,并知道了摄像头SIP的配置位置。接着我们在application.yml文件中增加我们的sip配置。
application.yml

server:
  port: 8087

sip:
  ip: 192.168.20.78
  port: 5060
  id: 34020000002000000001
  domain: 3402000000
  password: sg@123456

2.2、在config目录下创建SipConfig

  需要在config目录下创建。


import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description SipConfig
 * @date 2024/3/22 10:44
 */
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = SipConfig.SIP)
public class SipConfig {

    public static final String SIP = "sip";

    /**
     * 默认使用 0.0.0.0
     */
    private String monitorIp = "0.0.0.0";

    private String ip;

    private Integer port;

    private String id;

    private String password;

    private String domain;

}

2.3、在service目录下创建SipService


import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import lombok.extern.slf4j.Slf4j;
import org.ougnuhs.gb.config.SipConfig;
import org.ougnuhs.gb.listener.MySipListener;
import org.ougnuhs.gb.utils.SIPDefaultProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.sip.*;
import java.util.Properties;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description SipService need SipConfig
 * @date 2024/3/22 11:02
 */
@Slf4j
@Configuration
public class SipService {

    @Autowired
    private SipConfig sipConfig;

    @Autowired
    private MySipListener mySipListener;

    private SipFactory sipFactory;

    private SipStackImpl sipStack;


    @Bean("sipFactory")
    SipFactory createSipFactory(){
        sipFactory = SipFactory.getInstance();
        sipFactory.setPathName("gov.nist");
        return sipFactory;
    }

    @Bean("sipStack")
    @DependsOn("sipFactory")
    SipStackImpl createSipStackImpl() throws PeerUnavailableException {
        Properties sipProperties = SIPDefaultProperties.getSipProperties(sipConfig.getMonitorIp(), false);
        sipStack =(SipStackImpl) sipFactory.createSipStack(sipProperties);
        return sipStack;
    }

    /**
     * 监听TCP 对于产生的异常需要在这个地方处理
     * @return
     * @throws Exception
     */
    @Bean("tcpSipProvider")
    @DependsOn("sipStack")
    public SipProviderImpl startTcpListener() throws Exception {
        // 创建SIP Provider并绑定到SIP Stack
        ListeningPoint lp = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "TCP");
        SipProviderImpl sipProvider = (SipProviderImpl)sipStack.createSipProvider(lp);
        // 注册SIP Servlet
        sipProvider.addSipListener(mySipListener);
        log.info("TCP Start SUCCESS");
        return sipProvider;
    }

    /**
     * 监听TCP 对于产生的异常需要在这个地方处理
     * @return
     * @throws Exception
     */
    @Bean("udpSipProvider")
    @DependsOn("sipStack")
    public SipProviderImpl startUdpListener() throws Exception {
        // 创建SIP Provider并绑定到SIP Stack
        ListeningPoint lp = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
        SipProviderImpl sipProvider =  (SipProviderImpl)sipStack.createSipProvider(lp);
        // 注册SIP Servlet
        sipProvider.addSipListener(mySipListener);
        log.info("UDP Start SUCCESS");
        return sipProvider;
    }


}

2.4、在adapter目录下创建如下类

import org.springframework.beans.factory.InitializingBean;

import javax.sip.RequestEvent;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description SIP事件处理接口
 * @date 2024/3/22 13:59
 */
public interface ISIPEventHandler extends InitializingBean {

    /**
     * 事件处理方法
     * @param requestEvent
     */
    void process(RequestEvent requestEvent);

}

@Slf4j
public class SIPFactory {

    public static Map<String, ISIPEventHandler> requestHandlerMap = new ConcurrentHashMap<>();

    public static void register(String key, ISIPEventHandler handler){
        if(!StringUtils.hasText(key) || ObjectUtils.isEmpty(handler)){
            log.info("error: key or handler is null");
            return;
        }
        requestHandlerMap.put(key, handler);
        log.info("id:{}, handler:{}, register success", key, handler );
    }

    public static ISIPEventHandler getInvokeStrategy(String key) throws NoSuchMethodException {
        if(!requestHandlerMap.containsKey(key)){
            throw new NoSuchMethodException("未找到执行该方法的策略 key: " + key);
        }
        return requestHandlerMap.get(key);
    }
}
package org.ougnuhs.gb.adapter;

import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
import lombok.extern.slf4j.Slf4j;
import org.ougnuhs.gb.enums.TransportTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.sip.*;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 模板方法
 * @date 2024/3/22 16:43
 */
@Slf4j
public abstract class SIPRequestProcessorParent {

    @Autowired
    @Qualifier(value="tcpSipProvider")
    private SipProviderImpl tcpSipProvider;

    @Autowired
    @Qualifier(value="udpSipProvider")
    private SipProviderImpl udpSipProvider;


    /**
     * 根据 RequestEvent 获取 ServerTransaction
     * @param evt
     * @return
     */
    public ServerTransaction getServerTransaction(RequestEvent evt) {
        Request request = evt.getRequest();
        SIPServerTransactionImpl serverTransaction = (SIPServerTransactionImpl)evt.getServerTransaction();
        // 判断TCP还是UDP
        boolean isTcp = transportTypeIsTcp(request);
        if (serverTransaction != null && serverTransaction.getOriginalRequest() == null) {
            serverTransaction.setOriginalRequest((SIPRequest) evt.getRequest());
        }
        if (serverTransaction == null) {
            try {
                if (isTcp) {
                    SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
                    serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
                    if (serverTransaction == null) {
                        serverTransaction = (SIPServerTransactionImpl)tcpSipProvider.getNewServerTransaction(request);
                    }
                } else {
                    SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
                    serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
                    if (serverTransaction == null) {
                        serverTransaction = (SIPServerTransactionImpl)udpSipProvider.getNewServerTransaction(request);
                    }
                }
            } catch (TransactionAlreadyExistsException e) {
                log.error(e.getMessage());
            } catch (TransactionUnavailableException e) {
                log.error(e.getMessage());
            }
        }
        return serverTransaction;
    }

    /**
     * 判断通讯的方式是TCP吗
     * @param request
     * @return
     */
    private boolean transportTypeIsTcp(Request request){
        ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
        String transport = reqViaHeader.getTransport();
        log.info("通讯方式是:{}", transport);
        return transport.equalsIgnoreCase(TransportTypeEnum.TCP.getValue());
    }


    //FIXME 在SipService中不是有一个这个对象吗?
    public MessageFactory getMessageFactory() {
        try {
            return SipFactory.getInstance().createMessageFactory();
        } catch (PeerUnavailableException e) {
            e.printStackTrace();
        }
        return null;
    }



}
package org.ougnuhs.gb.adapter;

import gov.nist.javax.sip.RequestEventExt;
import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.clientauthutils.DigestServerAuthenticationHelper;
import lombok.extern.slf4j.Slf4j;
import org.ougnuhs.gb.config.SipConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.header.AuthorizationHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 提供注册事件的处理器
 * TODO 返回Response; 以及错误信息返回需要统一,不能随便写返回的错误!
 * @date 2024/3/22 14:17
 */
@Slf4j
@Component
public class SIPRegisterEventHandler extends SIPRequestProcessorParent implements ISIPEventHandler {

    @Autowired
    private SipConfig sipConfig;

    private static final String KEY = "REGISTER";

    private Response response;

    @Override
    public void afterPropertiesSet() throws Exception {
        SIPFactory.register(KEY, this);
    }

    @Override
    public void process(RequestEvent requestEvent) {
        RequestEventExt requestEventExt = (RequestEventExt) requestEvent;
        String ipAddress = requestEventExt.getRemoteIpAddress() + ":" + requestEventExt.getRemotePort();
        log.info("ipAddress:{}", ipAddress);
        //取出request对象
        Request request = requestEventExt.getRequest();
        //FromHeader
        fromHeader(request);
        //AuthorizationHeader
        authorizationHeader(request);
        //ExpiresHeader
        expiresHeader(request);
        //ViaHeader
        viaHeader(request);
        //TODO 假设一切都ok。我们直接进行回复成功
        try {
            response = getMessageFactory().createResponse(Response.OK, request);
            sendResponse(requestEvent, response);
        }catch (ParseException parseException){
            parseException.printStackTrace();
            log.error("SIPRegisterEventHandler createResponse fail");
        }
    }

    /**
     * 注册参数-主要是为了拿到SIP用户名,这个用户不能重复,如果平台需要级联多个摄像头,该SIP必须唯一
     * deviceId 对应的就是SIP用户名
     * @param request
     */
    private void fromHeader(Request request){
        FromHeader fromHeader =(FromHeader) request.getHeader(FromHeader.NAME);
        AddressImpl addressImpl = (AddressImpl) fromHeader.getAddress();
        SipUri sipUri = (SipUri)addressImpl.getURI();
        String deviceId = sipUri.getUser();
        log.info("fromHeader:{} \t addressImpl:{} \t sipUrl:{} \t deviceId:{}",
                fromHeader, addressImpl, sipUri, deviceId);
    }

    /**
     * 携带参数
     * @param request
     */
    private void expiresHeader(Request request){
        ExpiresHeader expiresHeader =(ExpiresHeader) request.getHeader(ExpiresHeader.NAME);
        if(ObjectUtils.isEmpty(expiresHeader)){
            log.error("[注册请求] {}", Response.BAD_REQUEST);
            return;
        }
        if(expiresHeader.getExpires() == 0){
            log.error("[注册请求] 用户申请注销!");
            return;
        }else{
            log.info("[注册请求] 用户申请注册!");
            //TODO 放入数据库
        }
        log.info("expiresHeader:{}", expiresHeader);
    }

    /**
     * 口令密码等信息
     * @param request
     */
    private void authorizationHeader(Request request) {
        AuthorizationHeader authorizationHeader =(AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
        if (ObjectUtils.isEmpty(authorizationHeader) && ObjectUtils.isEmpty(sipConfig.getPassword())){
            log.error("[注册请求] 未携带授权");
            return;
        }
        try{
            boolean passwordCorrect = ObjectUtils.isEmpty(sipConfig.getPassword()) ||
                    new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, sipConfig.getPassword());
            if(!passwordCorrect){
                log.error("[注册请求] 密码/SIP服务器ID错误, 回复403");
                return;
            }
        }catch (NoSuchAlgorithmException e){
            log.error("[注册请求] 验证授权发生错误!");
            return;
        }
        log.info("authorizationHeader:{}", authorizationHeader.toString());
    }

    /**
     * 主要用来查看是UDP还是TCP传输
     * @param request
     */
    private void viaHeader(Request request){
        ViaHeader viaHeader =(ViaHeader) request.getHeader(ViaHeader.NAME);
        String transport = viaHeader.getTransport();
        log.info("viaHeader:{} \t transport:{}", viaHeader, transport);
    }

    /**
     * 响应回复
     * @param requestEvent
     * @param response
     * @throws InvalidArgumentException
     * @throws SipException
     */
    private void sendResponse(RequestEvent requestEvent, Response response){
        ServerTransaction serverTransaction = getServerTransaction(requestEvent);
        if (serverTransaction == null) {
            log.warn("[回复失败]:{}", response);
            return;
        }
        try {
            serverTransaction.sendResponse(response);
            log.info("SIPRegisterEventHandler sendResponse success");
        }catch (InvalidArgumentException | SipException exception){
            exception.printStackTrace();
            log.error("[回复发生异常]:{}", response);
        }finally {
            if (serverTransaction.getDialog() != null) {
                serverTransaction.getDialog().delete();
            }
        }
    }

}

2.5、在listener准备如下类

import javax.sip.SipListener;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description MySipService 继承 SipListener
 * @date 2024/3/22 11:14
 */
public interface MySipListener extends SipListener {
}

import lombok.extern.slf4j.Slf4j;
import org.ougnuhs.gb.adapter.SIPFactory;
import org.springframework.stereotype.Service;

import javax.sip.*;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description IMySipService 实现 MySipService
 * @date 2024/3/22 11:16
 */
@Slf4j
@Service
public class MySipListenerImpl implements MySipListener{

    /**
     * 摄像头上报事件
     * @param requestEvent
     */
    @Override
    public void processRequest(RequestEvent requestEvent) {
        String method = requestEvent.getRequest().getMethod();
        try {
            SIPFactory.getInvokeStrategy(method).process(requestEvent);
        }catch (Exception e){
            log.error("processRequest error", e);
        }
    }

    @Override
    public void processResponse(ResponseEvent responseEvent) {
        log.info("processResponse");
    }

    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
        log.info("processTimeout");
    }

    @Override
    public void processIOException(IOExceptionEvent exceptionEvent) {
        log.info("processIOException");
    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
        log.info("processTransactionTerminated");
    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
        log.info("processDialogTerminated");
    }
}

2.7、准备基础的枚举类(enums目录下)

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 传输方式类型
 * @date 2024/3/27 9:52
 */
public enum TransportTypeEnum implements BaseEnum {

    TCP("TCP"),
    UDP("UDP");

    private String value;

    TransportTypeEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String getName() {
        return null;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 枚举基类 TODO 没有增加反序列化
 * @date 2024/3/27 9:54
 */
public interface BaseEnum {

    Object getValue();

    default String getText() {
        return null;
    }

    String getName();

    /**
     * 根据枚举value生成枚举
     * @author liyuanxi
     * @date 2019/4/17 11:47
     */
    static <E extends Enum<E> & BaseEnum> E valueOf(Object value, Class<E> clazz) {
        E em;
        E[] enums = clazz.getEnumConstants();
        String enumName = null;
        for (BaseEnum e : enums) {
            if (e.getValue().equals(value)) {
                enumName = e.getName();
            }
        }
        if (null != enumName) {
            em = Enum.valueOf(clazz, enumName);
        } else {
            throw new RuntimeException(value + "未匹配上对应的枚举");
        }
        return em;
    }

    /**
     * 根据枚举name生成枚举类型
     * @author liyuanxi
     * @date 2019/4/17 11:47
     */
    static <E extends Enum<E> & BaseEnum> E nameOf(String name, Class<E> clazz) {
        return Enum.valueOf(clazz, name);
    }
}

以上全部cv走。

3、按照项目配置摄像头的SIP

请按照这个配置
需要说明的是多个摄像头的话,SIP用户名请保证唯一

4、启动项目

  启动项目后,设备会自动注册上来,我方会告知他注册成功。

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

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

相关文章

手机录屏在哪里找?手把手教你找到录屏功能

随着智能手机的普及和移动应用的快速发展&#xff0c;手机录屏功能变得越来越受欢迎。无论是记录游戏精彩瞬间、制作教程视频&#xff0c;还是为了保存重要的视频通话内容&#xff0c;手机录屏都能帮上大忙&#xff0c;可是很多人不知道手机录屏在哪里找&#xff0c;本文将介绍…

防静电检测设备如何完善PCBA车间的防静电管控?

在PCBA&#xff08;Printed Circuit Board Assembly&#xff09;车间中&#xff0c;静电是一个极其重要的问题&#xff0c;因为静电可能对电子元器件和PCB板造成损坏&#xff0c;进而影响整个生产流程和产品质量。为了有效防止静电问题&#xff0c;企业通常会引入防静电检测设备…

US-T65 DM蓝牙5.2双模热插拔PCB

键盘使用说明索引&#xff08;均为出厂默认值&#xff09; 一些常见问题解答&#xff08;FAQ&#xff09;注意首次使用步骤蓝牙配对&#xff08;重要&#xff09;蓝牙和USB切换键盘默认层默认触发层0的FN键配置的功能默认功能层1配置的功能默认的快捷键 蓝牙参数蓝牙MAC地址管理…

Win11电脑cpu温度过高怎么办呢

Win11电脑cpu温度过高怎么办呢?有时候我们感觉电脑发烫,担心电脑过烫会不会损坏。正常情况下,cpu的温度在45~65度之间,但不排除电脑同时开了太多软件,或者在玩吃鸡、英雄联盟等的大型游戏而导致温度超过85度。只要最高温不超过85度都仍在正常的波动范围。但是超过了,电脑…

C# winform校验文件版本差异及版本号

界面 代码 using System.Diagnostics;namespace VersionTool {public partial class Form1 : Form{List<string> fileNmaes new List<string>() { "PhotoMes.Base.dll", "PhotoMes.App.exe", "PhotoMes.Cameras.dll" };public F…

零基础学习挖掘PHP网站漏洞

教程介绍 本套课程&#xff0c;分为三个阶段&#xff1a;第一阶段&#xff1a;基础篇 学习PHP开发的基础知识&#xff0c;对PHP常见的漏洞进行分析&#xff0c;第二阶段&#xff1a;进阶篇 实战PHP漏洞靶场&#xff0c;了解市面上的PHP主流网站开发技术&#xff0c;并对市面上…

【Java程序设计】【C00377】基于(JavaWeb)Springboot的社区医疗服务系统(有论文)

【C00377】基于&#xff08;JavaWeb&#xff09;Springboot的社区医疗服务系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#x…

HDFSRPC通信框架详解

本文主要对HDFSRPC通信框架解析。包括listener&#xff0c;reader&#xff0c;handler&#xff0c;responser等实现类的源码分析。注意hadoop版本为3.1.1。 写在前面 rpc肯定依赖于socket通信&#xff0c;并且使用的是java NIO。读者最好对nio有一定的了解&#xff0c;文章中…

MySQL索引优化二

分页查询优化 很多时候我们的业务系统实现分页功能可能会用如下sql实现 select * from employees limit 10000,10;表示从表employees中取出从10001行开始的10条记录.看似只查询了10条记录,实际这条sql是先读取10010条记录,然后抛弃前10000条记录,然后读到后面10条想要的数据,…

创建云知识库,你需要了解这些

云知识库对于提升企业的知识管理水平和整体效能具有重要作用。越来越多的企业使用云知识库。但是&#xff0c;对于刚开始创建云知识库的企业来说&#xff0c;什么是云知识库&#xff1f;云知识库的作用是什么&#xff1f;如何创建云知识库&#xff1f;这就是这篇文章要解决的问…

浏览器导出excel

做java web项目时&#xff0c;经常遇到需要在页面上点击导出按钮&#xff0c;然后直浏览器接下载下来一个excel文档。 比如一个List<Person>的集合&#xff0c;需要将每个Person当做一行&#xff0c;输出到excel中去。其中Person实体类如下&#xff1a; import lombok.…

ChatGPT助力论文写作:详细步骤解析

前言 在论文写作过程中&#xff0c;尽管人工智能工具如ChatGPT能为我们提供有效的辅助&#xff0c;但我们必须铭记&#xff0c;这些工具并不能完全取代我们的思考与判断能力。本指南将详尽地展示如何利用ChatGPT辅助论文写作的全过程&#xff0c;旨在帮助您更高效地完成学术任…

hadoop安装及基本使用

环境准备 三台centos7虚拟机&#xff0c;设置固定ip&#xff08;自己设置&#xff09;&#xff0c;设置ssh秘密登录&#xff08;自己设置&#xff09;&#xff0c;安装jdk8&#xff08;自己安装&#xff09; 准备安装包hadoop-3.3.6.tar.gz 位置在/home/hadoop 准备服务器之间…

Ubuntu 下统计文件数量的命令

参考:https://blog.csdn.net/kxh123456/article/details/123811580 查看当前目录下的文件数量&#xff08;不包含子目录中的文件&#xff09; ls -l|grep "^-"| wc -l实例展示&#xff1a;如下图所示&#xff0c;当前路径下&#xff0c;有2个json文件和2个文件夹&a…

JavaWeb学习笔记01

一、教程简介 全新JAVAWEB&#xff08;里程碑版&#xff09; 一套更适合后端工程师学习的WEB教程 All in Java 1、后端 ① Spring全家桶及微服务框架 ② 高性能数据库和消息组件 ③ Web攻击防护安全控制手段 ④ 其他第三方SDK生态环境 ...... 2、前端 ① 视图三大件&…

第十一届蓝桥杯大赛第二场省赛试题 CC++ 研究生组-寻找2020

数据很恶心&#xff0c;但是考点挺友好~ 把测试数据黏贴到记事本中&#xff0c;知测试数据的行列数 然后根据规则判断2020是否出现&#xff0c;并累计其次数即可。 判断可能需要注意超出下标&#xff0c;可以索性把数组定大些。 #include<stdio.h> const int N 310; ch…

管理能力学习笔记三:管理者的时间管理法

时间管理三步法 1、对任务进行分类 2、估算任务时间 3、持续反思评估 对任务进行分类 分类方法&#xff1a;时间管理四象限 A类 B类 C类 D类 估算时间 需要预留休息时间和机动时间 持续反思评估 核对检查任务 自我提问 处理日常干扰的办法 对事情发出提问 对话内容进行…

爬虫基础训练题

1.抓取imooc网站实战课程部分的课程名称&#xff08;所有课程大概7页&#xff0c;抓取1到5页&#xff09;&#xff0c;并把所有课程名称存储为txt文件第一页地址 2.设置一个请求头&#xff08;headers&#xff09;&#xff0c;这是一个字典&#xff0c;用于在HTTP请求中设置请…

win10硬盘格式化后数据还能恢复吗?提供恢复步骤

在使用电脑的过程中&#xff0c;可能会出现需要格式化硬盘的情况。但是在进行格式化后&#xff0c;是否还有可能恢复已经删除的数据呢&#xff1f;本文将探讨Win10系统下硬盘格式化后数据恢复的可能性&#xff0c;为您提供一些实用的恢复步骤。 图片来源于网络&#xff0c;如有…

电脑windows 蓝屏【恢复—无法加载操作系统,原因是关键系统驱动程序丢失或包含错误。.......】

当你碰到下图这种情况的电脑蓝屏&#xff0c;先别急着重装系统&#xff0c;小编本来也是想重装系统的&#xff0c;但是太麻烦&#xff0c;重装系统后你还得重装各种软件&#xff0c;太麻烦了&#xff01;&#xff01; 这种情况下&#xff0c;你就拿出你的启动U盘&#xff0c;进…