httpclient工具类(支持泛型转换)

1、网上搜到的httpclient工具类的问题:

1.1、如下图我们都能够发现这种封装的问题:

  • 代码繁杂、充斥了很多重复性代码
  • 返回值单一,无法拿到对应的Java Bean对象及List对象集合
  • 实际场景中会对接大量第三方的OPEN API,下述方法的扩展性差

在这里插入图片描述

1.2、简洁调用方式演示

本文基于上述问题,通过设计模式、泛型、JSON工具类的方式进行了封装,得到了下述更方便、更简洁的http请求调用方式

Entity params = new Entity();
params.setUrl("/common/postJson");
 Map<String, Object> map = new HashMap<>();
map.put("userId", "13277887788");
map.put("companyId", "87037827534cf");
params.setParams(map);

// 返回对象集合
List<AppEntity> appEntity = thirdHttpProcessorFactory
	.doGetReturnList(ThirdSystemEnum.ION, params, AppEntity.class);
// 返回String类型
String result = thirdHttpProcessorFactory
	.doGetReturnBean(ThirdSystemEnum.ION, params, String.class);
// 返回指定的对象
AppEntity appEntity = thirdHttpProcessorFactory
	.doGetReturnBean(ThirdSystemEnum.ION, params, AppEntity.class);
        

1.3、 目录结构

在这里插入图片描述

2、引入的maven仓库

 <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
     <artifactId>jackson-databind</artifactId>
	 <version>2.14.2</version>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.16</version>
</dependency>
  • ThirdHttpProcessorFactory:存储不同三方平台的处理期
  • ThirdHttpProcessor:定义通用的接口
  • AbstractThirdHttpProcessor:定义公共的处理逻辑
  • IonHttpProcessor:定义各对接平台的差异性逻辑
  • AppEntity:返回值
  • Entity:入参
  • ThirdSystemEnum:定义三方平台的枚举

3、代码实现

3.1、获取不同第三方处理器的工厂ThirdHttpProcessorFactory

package com.ionrocking.platform.tripartite;


import com.ionrocking.common.core.exception.ServiceException;
import com.ionrocking.platform.tripartite.entity.Entity;
import com.ionrocking.platform.tripartite.enums.ThirdSystemEnum;
import lombok.experimental.Accessors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ke
 * Created by on  2023-10-27 15:23
 */
@Component
@Accessors(chain = true)
public class ThirdHttpProcessorFactory {

    @Autowired
    private List<ThirdHttpProcessor> thirdHttpProcessors;

    private Map<String, ThirdHttpProcessor> thirdHttpProcessorMap;

    @PostConstruct
    public void init() {
        if (CollectionUtils.isEmpty(thirdHttpProcessors)) {
            return;
        }
        thirdHttpProcessorMap = new HashMap<>(8);
        for (ThirdHttpProcessor processor : thirdHttpProcessors) {
            thirdHttpProcessorMap.put(processor.getType().getCode(), processor);
        }
    }

    private ThirdHttpProcessor getThirdHttpProcessor(String type) {
        ThirdSystemEnum thirdSystemEnum = ThirdSystemEnum.getByCode(type);
        if (null == thirdSystemEnum) {
            throw new ServiceException("三方OpenApi尚未配置,无法进行请求");
        }
        return thirdHttpProcessorMap.get(type);
    }


    /**
     * http get请求
     *
     * @param thirdSystemEnum 三方系统类型枚举
     * @param entity          参数
     * @param tClass          返回参数类型
     * @return T              返回数据对象
     * @throws Exception 业务执行异常
     */
    public <T> T doGetReturnBean(ThirdSystemEnum thirdSystemEnum, Entity entity, Class<T> tClass) throws Exception {
        return getThirdHttpProcessor(thirdSystemEnum.getCode()).doGetReturnBean(entity, tClass);
    }

    /**
     * http post请求,入参支持application/x-www-form-urlencoded 请求
     *
     * @param thirdSystemEnum 三方系统类型枚举
     * @param entity          参数
     * @param tClass          返回参数类型
     * @return T              返回数据对象
     * @throws Exception 业务执行异常
     */
    public <T> T doPostReturnBean(ThirdSystemEnum thirdSystemEnum, Entity entity, Class<T> tClass) throws Exception {
        return getThirdHttpProcessor(thirdSystemEnum.getCode()).doPostReturnBean(entity, tClass);
    }

    /**
     * http post请求,入参支持application/json请求
     *
     * @param thirdSystemEnum 三方系统类型枚举
     * @param entity          参数
     * @param tClass          返回参数类型
     * @return T              返回数据对象
     * @throws Exception 业务执行异常
     */
    public <T> T doPostJsonReturnBean(ThirdSystemEnum thirdSystemEnum, Entity entity, Class<T> tClass) throws Exception {
        return getThirdHttpProcessor(thirdSystemEnum.getCode()).doPostJsonReturnBean(entity, tClass);
    }

    /**
     * http get请求
     *
     * @param thirdSystemEnum 三方系统类型枚举
     * @param entity          参数
     * @param tClass          返回参数类型
     * @return List<T>        返回数据集合
     * @throws Exception 业务执行异常
     */
    public <T> List<T> doGetReturnList(ThirdSystemEnum thirdSystemEnum, Entity entity, Class<T> tClass) throws Exception {
        return getThirdHttpProcessor(thirdSystemEnum.getCode()).doGetReturnList(entity, tClass);
    }

    /**
     * http post请求,入参支持application/x-www-form-urlencoded 请求
     *
     * @param thirdSystemEnum 三方系统类型枚举
     * @param entity          参数
     * @param tClass          返回参数类型
     * @return List<T>        返回数据集合
     * @throws Exception 业务执行异常
     */
    public <T> List<T> doPostReturnList(ThirdSystemEnum thirdSystemEnum, Entity entity, Class<T> tClass) throws Exception {
        return getThirdHttpProcessor(thirdSystemEnum.getCode()).doPostReturnList(entity, tClass);
    }

    /**
     * http post请求,入参支持application/json请求
     *
     * @param thirdSystemEnum 三方系统类型枚举
     * @param entity          参数
     * @param tClass          返回参数类型
     * @return List<T>        返回数据集合
     * @throws Exception 业务执行异常
     */
    public <T> List<T> doPostJsonReturnList(ThirdSystemEnum thirdSystemEnum, Entity entity, Class<T> tClass) throws Exception {
        return getThirdHttpProcessor(thirdSystemEnum.getCode()).doPostJsonReturnList(entity, tClass);
    }

}

3.2、http请求处理的接口ThirdHttpProcessor

/**
 * Dans.com Inc.
 * Copyright (c) 2011-2020 All Rights Reserved
 */
package com.ionrocking.platform.tripartite;


import com.ionrocking.platform.tripartite.entity.Entity;
import com.ionrocking.platform.tripartite.enums.ThirdSystemEnum;

import java.util.List;

/**
 * 追踪事件处理器
 *
 * @author ke
 * Created by on  2023-06-20 15:23
 */
public interface ThirdHttpProcessor {

    /**
     * 业务执行
     *
     * @param entity
     * @param tClass
     * @return T
     * @throws Exception 业务执行异常
     */
    <T> T doGetReturnBean(Entity entity, Class<T> tClass) throws Exception;

    /**
     * 业务执行
     *
     * @param entity
     * @param tClass
     * @return
     * @throws Exception 业务执行异常
     */
    <T> T doPostReturnBean(Entity entity, Class<T> tClass) throws Exception;

    /**
     * 业务执行
     *
     * @param entity
     * @param tClass
     * @return
     * @throws Exception 业务执行异常
     */
    <T> T doPostJsonReturnBean(Entity entity, Class<T> tClass) throws Exception;
    /**
     * 业务执行
     *
     * @param entity
     * @param tClass
     * @return T
     * @throws Exception 业务执行异常
     */
    <T> List<T> doGetReturnList(Entity entity, Class<T> tClass) throws Exception;

    /**
     * 业务执行
     *
     * @param entity
     * @param tClass
     * @return
     * @throws Exception 业务执行异常
     */
    <T> List<T> doPostReturnList(Entity entity, Class<T> tClass) throws Exception;

    /**
     * 业务执行
     *
     * @param entity
     * @param tClass
     * @return
     * @throws Exception 业务执行异常
     */
    <T> List<T> doPostJsonReturnList(Entity entity, Class<T> tClass) throws Exception;

    /**
     * 获取事件类型
     *
     * @return
     */
    ThirdSystemEnum getType();
}

3.3、通用逻辑处理的抽象类AbstractThirdHttpProcessor

  • 如在通过http client发起HTTP请求时,除了请求头requestHeader、请求入参requestBody不同,其他逻辑都是一样的,则可以进行公共代码的抽取
  • 如果存在特殊的逻辑处理,则可以在子类中重写父类的方法
package com.ionrocking.platform.tripartite;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ionrocking.common.core.exception.ServiceException;
import com.ionrocking.platform.config.SysNacosConfig;
import com.ionrocking.platform.tripartite.entity.Entity;
import com.ionrocking.platform.tripartite.entity.IonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author ke
 * @Date 2023/10/27
 */
@Slf4j
@Component
public abstract class AbstractThirdHttpProcessor implements ThirdHttpProcessor {
    @Override
    public <T> List<T> doGetReturnList(Entity entity, Class<T> tClass) throws Exception {
        // 构造请求头
        Map<String, String> requestHead = constructRequestHead(entity);
        // 构造请求数据
        Map<String, Object> requestBody = constructRequestBody(entity);
        String result = HttpUtil.createGet(sysNacosConfig.getIonRequestUrl() + entity.getUrl())
                .addHeaders(requestHead)
                .form(requestBody)
                .execute()
                .body();
        return toList(result, tClass);
    }

    @Override
    public <T> List<T> doPostReturnList(Entity entity, Class<T> tClass) throws Exception {
        // 构造请求头
        Map<String, String> requestHead = constructRequestHead(entity);
        // 构造请求数据
        Map<String, Object> requestBody = constructRequestBody(entity);
        String result = HttpUtil.createPost(sysNacosConfig.getIonRequestUrl() + entity.getUrl())
                .addHeaders(requestHead)
                .form(requestBody)
                .execute()
                .body();
        return toList(result, tClass);
    }

    @Override
    public <T> List<T> doPostJsonReturnList(Entity entity, Class<T> tClass) throws Exception {
        // 构造请求头
        Map<String, String> requestHead = constructRequestHead(entity);
        // 构造请求数据
        Map<String, Object> requestBody = constructRequestBody(entity);
        String result = HttpUtil.createPost(sysNacosConfig.getIonRequestUrl() + entity.getUrl())
                .addHeaders(requestHead)
                .body(JSONUtil.toJsonStr(requestBody))
                .execute()
                .body();
        return toList(result, tClass);
    }

    public <T> T toBean(String result, Class<T> tClass) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        IonResponse<Object> response = JSONUtil.toBean(result, IonResponse.class);
        if (CODE != response.getCode()) {
            throw new ServiceException(response.getMsg());
        }
        if (null == response.getData()) {
            return null;
        }
        return objectMapper.readValue(response.getData().toString(), tClass);
    }

    public <T> List<T> toList(String result, Class<T> tClass) throws JsonProcessingException {
        List<T> data = new ArrayList<>();
        IonResponse<List<Object>> response = JSONUtil.toBean(result, IonResponse.class);
        if (CODE != response.getCode()) {
            throw new ServiceException(response.getMsg());
        }
        if (CollUtil.isEmpty(response.getData())) {
            return null;
        }
        for (Object o : response.getData()) {
            ObjectMapper objectMapper = new ObjectMapper();
            data.add(objectMapper.readValue(o.toString(), tClass));
        }
        return data;
    }

    @Resource
    protected SysNacosConfig sysNacosConfig;

    protected static final int CODE = 200;

    @Override
    public <T> T doGetReturnBean(Entity entity, Class<T> tClass) throws Exception {
        // 构造请求头
        Map<String, String> requestHead = constructRequestHead(entity);
        // 构造请求数据
        Map<String, Object> requestBody = constructRequestBody(entity);
        String result = HttpUtil.createGet(sysNacosConfig.getIonRequestUrl() + entity.getUrl())
                .addHeaders(requestHead)
                .form(requestBody)
                .execute()
                .body();
        return toBean(result, tClass);
    }

    /**
     * 执行
     *
     * @return
     */
    @Override
    public <T> T doPostReturnBean(Entity entity, Class<T> tClass) throws Exception {
        // 构造请求头
        Map<String, String> requestHead = constructRequestHead(entity);
        // 构造请求数据
        Map<String, Object> requestBody = constructRequestBody(entity);
        String result = HttpUtil.createPost(sysNacosConfig.getIonRequestUrl() + entity.getUrl())
                .addHeaders(requestHead)
                .form(requestBody)
                .execute()
                .body();
        return toBean(result, tClass);
    }

    @Override
    public <T> T doPostJsonReturnBean(Entity entity, Class<T> tClass) throws Exception {
        // 构造请求头
        Map<String, String> requestHead = constructRequestHead(entity);
        // 构造请求数据
        Map<String, Object> requestBody = constructRequestBody(entity);
        String result = HttpUtil.createPost(sysNacosConfig.getIonRequestUrl() + entity.getUrl())
                .addHeaders(requestHead)
                .body(JSONUtil.toJsonStr(requestBody))
                .execute()
                .body();
        return toBean(result, tClass);
    }


    /**
     * 构造请求头
     *
     * @param entity
     * @return
     */
    public abstract Map<String, String> constructRequestHead(Entity entity);

    /**
     * 构造请求体
     *
     * @param entity
     * @return
     */
    public Map<String, Object> constructRequestBody(Entity entity) {
        if (CharSequenceUtil.isBlank(entity.getUrl())) {
            throw new ServiceException("请求路径不能为空");
        }
        if (null == entity) {
            return null;
        }
        return entity.getParams();
    }

}

3.4、第三方非通用逻辑处理类IonHttpProcessor

  • 比如此处对接的xx公司需要进行access_token获取及验证,然后将access_token放在请求头中
package com.ionrocking.platform.tripartite.impl;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.ionrocking.platform.tripartite.AbstractThirdHttpProcessor;
import com.ionrocking.platform.tripartite.entity.Entity;
import com.ionrocking.platform.tripartite.entity.IonResponse;
import com.ionrocking.platform.tripartite.enums.ThirdSystemEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @author ke
 * @Date 2023/10/27
 */
@Slf4j
@Component
public class IonHttpProcessor extends AbstractThirdHttpProcessor {

    private String accessTokenUrl = "/token/getAccessToken";


    private static final String ACCESS_TOKEN_KEY = "access_token";

    @Override
    public Map<String, String> constructRequestHead(Entity entity) {
        Map<String, String> header = new HashMap<>(2);
        Map<String, Object> params = new HashMap<>(4);
        params.put("appId", sysNacosConfig.getIonRequestAppId());
        params.put("appSecret", sysNacosConfig.getIonRequestAppSecret());

        String result = HttpUtil.get(sysNacosConfig.getIonRequestUrl() + accessTokenUrl, params);
        if (CharSequenceUtil.isEmpty(result)) {
            return null;
        }
        TypeReference<IonResponse<Map<String, Object>>> typeRef = new TypeReference<IonResponse<Map<String, Object>>>() {
        };
        IonResponse<Map<String, Object>> response = JSONUtil.toBean(result, typeRef, false);
        if (CODE == response.getCode() && null != response.getData()) {
            if (response.getData().containsKey(ACCESS_TOKEN_KEY)) {
                header.put(ACCESS_TOKEN_KEY, response.getData().get(ACCESS_TOKEN_KEY).toString());
            }
        }
        return header;
    }

    @Override
    public ThirdSystemEnum getType() {
        return ThirdSystemEnum.ION;
    }
}

3.5、枚举类ThirdSystemEnum

  • 区分不同的平台,根据枚举获取不同的实现类
package com.ionrocking.platform.tripartite.enums;

import org.apache.commons.lang3.StringUtils;

/**
 * @author ke
 * @Date 2023/10/27
 */
public enum ThirdSystemEnum {
    /**
     * XX科技公司
     */
    ION("ion", "xx科技");

    private final String code;

    private final String name;

    public String getName() {
        return this.name;
    }


    public String getCode() {
        return this.code;
    }

    ThirdSystemEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public static ThirdSystemEnum getByCode(String code) {
        if (StringUtils.isEmpty(code)) {
            return null;
        }
        for (ThirdSystemEnum codeEnum : values()) {
            if (code.equals(codeEnum.getCode())) {
                return codeEnum;
            }
        }
        return null;
    }
}

3.6、第三方返回格式对象IonResponse

package com.ionrocking.platform.tripartite.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @author ke
 * @Date 2023/10/27
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class IonResponse<T> implements Serializable {

    private static final long serialVersionUID = -8741972144218822267L;
    private int code;
    /**
     * 消息
     */
    private String msg;
    /**
     * 数据
     */
    private T data;
    /**
     * 总记录数
     */
    private long total;
}

3.7、处理器入参对象Entity

  • 此处定义请求的URL和请求的参数
package com.ionrocking.platform.tripartite.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Map;

/**
 * @author ke
 * @Date 2023/10/27
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Entity implements Serializable {

    private static final long serialVersionUID = -6083780287057302816L;

    private String url;

    /**
     * 参数
     */
    private Map<String, Object> params;
}

3.8、第三方接口返回值对象AppEntity

package com.ionrocking.platform.tripartite.entity;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotBlank;

/**
 * @author ke
 * @Date 2023/10/26
 */

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class AppEntity {
    private long id;

    private String appId;

    @NotBlank(message = "应用名称不能为空")
    private String appName;

    private String appSecret;

    private String accessToken;

    private Integer isFlag;
}

3.9、Nacos配置

  • Nacos中一般存放一些第三方的请求域名、鉴权的appId、appSecret等
tripartite-platform:
  ion:
    request:
      url: http://localhost:8080/api/
      appId: YodeqWwp
      appSecret: 87037827534cf848a570fae3c93a2469fa0262935af531dddfe7a52ae7f98f41
package com.ionrocking.platform.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * nacos配置信息
 * @author ke
 * @Date 2023/9/20
 */
@Component
public class SysNacosConfig {


    @Value("${upload.path}")
    private String uploadPath;

    @Value("${tripartite-platform.ion.request.url}")
    private String ionRequestUrl;

    @Value("${tripartite-platform.ion.request.appId}")
    private String ionRequestAppId;

    @Value("${tripartite-platform.ion.request.appSecret}")
    private String ionRequestAppSecret;

    public String getUploadPath() {
        return uploadPath;
    }

    public String getIonRequestUrl() {
        return ionRequestUrl;
    }

    public String getIonRequestAppId() {
        return ionRequestAppId;
    }

    public String getIonRequestAppSecret() {
        return ionRequestAppSecret;
    }
}

测试

@RestController
@RequestMapping("/test")
public class Test {
    
    @Resource
    private SysNacosConfig sysNacosConfig;
    
    @Resource
    private ThirdHttpProcessorFactory thirdHttpProcessorFactory;
    
    @ResponseBody
    @RequestMapping(value = "/get")
    public AjaxResult get() throws Exception extends BaseController  {
        Entity params = new Entity();
        params.setUrl("/common/get");
        String result = thirdHttpProcessorFactory.doGetReturnBean(ThirdSystemEnum.ION, params, String.class);
        return AjaxResult.success(result);
    }


    @ResponseBody
    @RequestMapping(value = "/list")
    public AjaxResult list() throws Exception {
        Entity params = new Entity();
        params.setUrl("/common/list");
        List<AppEntity> appEntity = thirdHttpProcessorFactory.doGetReturnList(ThirdSystemEnum.ION, params, AppEntity.class);
        return AjaxResult.success(appEntity);
    }

    @ResponseBody
    @RequestMapping(value = "/postJson")
    public AjaxResult postJson() throws Exception {
        Entity params = new Entity();
        params.setUrl("/common/postJson");
        Map<String, Object> map = new HashMap<>();
        map.put("appId", "YodeqWwp");
        map.put("appSecret", "87037827534cf848a570fae3c93a2469fa0262935af531dddfe7a52ae7f98f41");
        params.setParams(map);
        List<AppEntity> list = thirdHttpProcessorFactory.doPostJsonReturnList(ThirdSystemEnum.ION, params, AppEntity.class);
		return AjaxResult.success(list);
    }
}

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

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

相关文章

二叉树OJ题汇总

本专栏内容为&#xff1a;leetcode刷题专栏&#xff0c;记录了leetcode热门题目以及重难点题目的详细记录 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;Leetcode &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &…

奇偶校验码和循环冗余码

在数据链路层的传输中&#xff0c;1可能变成0&#xff0c;0可能变成1&#xff0c;这是比特差错。 为了应对比特差错&#xff0c;有两种方式&#xff0c;即自动重传请求ARQ&#xff08;Automatic Repeat-reQuest&#xff09;和前向纠错FEC&#xff08;Forward Error Correction&…

c++获取和设置环境变量

这个功能非常常用&#xff0c;但是容易忘记&#xff0c;这里做个记录。 注意&#xff0c;设置的环境变量只在当前进程中生效&#xff0c;所以在电脑中的环境变量设置区域看不到。 std::string env getenv("PATH");env "X:\\envtest";std::string newEnv…

亚马逊、美客多卖家测评:如何建立养号团队实现运营化式测评?

大家好&#xff0c;我是跨境电商测评养号7年从事经验的珑哥。养号环境软件开发&#xff0c;深度解决各跨境平台矩阵养号防关联、砍单、F号问题。关注珑哥解决更多跨境养号测评问题。 测评&#xff0c;相信这个词对于大部分跨境卖家来说&#xff0c;想必都不陌生&#xff0c;因…

LCR 166.珠宝的最高价值 + 动态规划 + 记忆化搜索 + 递推 + 空间优化

LCR 166. 珠宝的最高价值 - 力扣&#xff08;LeetCode&#xff09; 现有一个记作二维矩阵 frame 的珠宝架&#xff0c;其中 frame[i][j] 为该位置珠宝的价值。拿取珠宝的规则为&#xff1a; 只能从架子的左上角开始拿珠宝每次可以移动到右侧或下侧的相邻位置到达珠宝架子的右下…

什么是OTP认证?OTP认证服务器有哪些应用场景?

OTP是一次性密码&#xff0c;即只能使用一次的密码。它基于专门的算法&#xff0c;每隔60秒生成一个不可预测的随机数字组合。这种密码的有效期仅在一次会话或交易过程中&#xff0c;因此不容易受到重放攻击。在计算器系统或其他数字设备上&#xff0c;OTP是一种只能使用一次的…

Spring Boot 3 整合 xxl-job 实现分布式定时任务调度,结合 Docker 容器化部署(图文指南)

目录 前言初始化数据库Docker 部署 xxl-job下载镜像创建容器并运行访问调度中心 SpringBoot 整合 xxl-jobpom.xmlapplication.ymlXxlJobConfig.java执行器注册查看 定时任务测试添加测试任务配置定时任务测试结果 结语附录xxl-job 官方文档xxl-job 源码测试项目源码 前言 xxl-…

【VR开发】【Unity】【VRTK】3-VR项目设置

任何VR避不开的步骤 如何设置VR项目,无论是PC VR还是安卓VR,我在不同的系列教程中都说过了,不过作为任何一个VR开发教程都难以避免的一环,本篇作为VRTK的开发教程还是对VR项目设置交代一下。 准备好你的硬件 头盔必须是6DoF的,推荐Oculus Quest系列,Rift系列,HTC和Pi…

3.字符集和比较规则简介

3.字符集和比较规则简介 1.字符集和比较规则简介1.1 字符集简介1.2 比较规则简介1.3 一些重要的比较规则 2. MySQL 中支持的字符集和比较规则2.1 MySQL 的 utf8 和 utf8mb42.2 字符集查看2.3 比较规则查看 3. 字符集和比较规则的应用3.1 各级别的字符集和比较规则1. 服务器级别…

基于深度学习的植物识别算法 - cnn opencv python 计算机竞赛

文章目录 0 前言1 课题背景2 具体实现3 数据收集和处理3 MobileNetV2网络4 损失函数softmax 交叉熵4.1 softmax函数4.2 交叉熵损失函数 5 优化器SGD6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的植物识别算法 ** …

【设计模式】第6节:创建型模式之“原型模式”

由于本人现在所使用的语言主要是golang&#xff0c;所以后面的代码主要使用golang编写。语言实现应该不是障碍&#xff0c;主要是理解每种设计模式它的思想。 如果对象的创建成本比较大&#xff0c;而同一个类的不同对象之间差别不大&#xff08;大部分字段都相同&#xff09;…

Google play开发者账号注册的实用技巧与建议——身份验证、付款资料、支付成功注册失败?

总所周知&#xff0c;如果要在Google paly应用商店上发布应用&#xff0c;需要先注册谷歌开发者账号。但随着发展&#xff0c;谷歌对开发者账号的审核越来越严格&#xff0c;要求越来越多&#xff0c;账号注册通过率越来越低&#xff0c;频繁被封&#xff0c;令开发者们苦恼不已…

AD9371 官方例程HDL JESD204B相关IP端口信号

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 AD9371 官方例程 时钟间的关系与生成 &#xff1a; AD9371 官方…

项目实战:修改水果库存系统特定库存记录

1、在edit.html修改库存页面添加点击事件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href"style/index.css"><script s…

基于B样条的FFD自由变换原理与C++实现

原理&#xff1a; https://blog.csdn.net/shandianfengfan/article/details/113706496 https://blog.csdn.net/qq_38517015/article/details/99724916 https://blog.csdn.net/qq_38517015/article/details/99724916 三次B样条 cubicBSplineFFD .h #pragma once #include &quo…

Unity在Project右键点击物体之后获取到点击物体的名称

Unity在Project右键点击物体之后获取到点击物体的名称 描述&#xff1a; 在Unity的Project右键点击物体之后选择对应的菜单选项点击之后打印出物体的名称 注意事项 如果获取到文件或者预制体需要传递objcet类型&#xff0c;然后使用 GameObject.Instantiate((GameObject)se…

vue-advanced-chat使用指南

demo地址:— vue-advanced-chat的git地址:https://github.com/advanced-chat/vue-advanced-chat 1.搭建demo demo地址克隆后在demo目录安装依赖并启动 启动之后的页面如下: 2.前端代码分析 2.1 重点api分析 current-user-id:当前用户id room-id:可随时加载特定房间?…

Rhino 8 for Mac(犀牛8)中文激活版

Rhino 8是一款功能强大的三维构建软件&#xff0c;它可以帮助用户创建各种类型的3D模型&#xff0c;包括产品设计、建筑设计、工业设计计划等。Rhino 7具有直观的界面和丰富的工具库&#xff0c;让用户可以快速轻松地进行建模、编辑、分析和漂染。 Rhino 8支持多种文件格式的导…

回归预测 | Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测

Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测 目录 Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机的多变量回归…