【玩转SpringBoot】优雅的整合Body和Header参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【玩转SpringBoot】优雅的整合Body和Header参数相关的知识,希望对你有一定的参考价值。

参考技术A         【优雅的解决问题】

        一、 问题场景

        我们在研发过程中普遍会遇到一种情况,一个请求过来,会同时用到body和header里面的参数,如果分别从body和header中获取参数的话,简直Low到爆!!!在这儿给各位支个招。

        二、 解决方案

        构建思路:自定义注解 + 自定义参数解析器 + 注册解析器

        1  自定义注解 RequestBodyAndHeader

        2  自定义参数解析器 RequestBodyAndHeaderResolver

        红色框标出了两部分重点:

        重点1: 合并Body和Header中的参数,其中使用BeanUtils.populate的特性来处理此场景;

        重点2:判断是否支持我们自定义的RequestBodyAndHeader。

        3  在配置文件中 注册自定义的参数解析器

        4  定义测试用的参数对象

        5  定义测试接口

        6  通过Postman测试可用性

        6.1  设置header参数和content-type

        6.2  设置对象参数

        6.3  提交请求

        查看程序打印结果,Bingo!header携带的参数自动赋值到了对象中。 

         三、简单总结

        这里主要是运用RequestResponseBodyMethodProcessor的特性来解决问题,关于其细节可参考官方的API文档。

使用sprintboot 优雅的整合 mqtt

mqtt 有许多实现的产品,这里使用国内使用比较多的emqx,可以参考 emqx安装 来安装环境

emqx 官方有提供java示例来连接mqtt:传送门

下面我使用springboot 来优雅的整合下

创建springboot 工程

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>top.wushanghui</groupId>
    <artifactId>mqtt-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mqtt-client</name>
    <description>mqtt-client</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.5</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

主要是引入mqtt依赖:

<dependency>
    <groupId>org.eclipse.paho</groupId>
    <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
    <version>1.2.5</version>
</dependency>

配置文件(yml)

application.yml

spring:
  profiles:
    active: dev

application-dev.yml

server:
  port: 8080
emqx:
  host: tcp://192.168.33.10:1883
  clientId: MQTT_IOT_DEFAULT_CLIENT
  username:
  password:
  timeout: 1000
  keepAlive: 60

配置类

EmqxProperties

package top.wushanghui.mqttclient.config;

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

/**
 * @author 吴尚慧
 * @since 2021/11/11 19:26
 */
@Getter
@Setter
@ToString
@ConfigurationProperties(prefix = "emqx")
public class EmqxProperties 

    private String host;
    private String clientId;
    private String username;
    private String password;
    private Integer timeout;
    private Integer keepAlive;



EmqxConfiguration

package top.wushanghui.mqttclient.config;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.wushanghui.mqttclient.callback.MyPushCallback;
import top.wushanghui.mqttclient.enums.MqttTopicEnum;

@Slf4j
@Configuration
@EnableConfigurationProperties(EmqxProperties.class)
public class EmqxConfiguration 

    @Bean
    public MqttClient mqttClient(EmqxProperties properties, MqttConnectOptions mqttConnectOptions, MyPushCallback myPushCallback) throws MqttException 
        log.info("", properties);
        String cid = properties.getClientId() + System.currentTimeMillis();
        MqttClient mqttClient = new MqttClient(properties.getHost(), cid, new MemoryPersistence());
        mqttClient.setCallback(myPushCallback);
        myPushCallback.setMqttClient(mqttClient);

        mqttClient.connect(mqttConnectOptions);
        log.info("连接 emqx 成功 当前客户端id=", mqttClient.getClientId());
        mqttClient.subscribe(MqttTopicEnum.DEFAULT_TOPIC.getTopic(), MqttTopicEnum.DEFAULT_TOPIC.getQos());
        log.info("mqttClient=", mqttClient);
        log.info("myPushCallback=", myPushCallback);
        return mqttClient;
    

    @Bean
    public MqttConnectOptions mqttConnectOptions(EmqxProperties properties) 
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(true);
        options.setUserName(properties.getUsername());
        options.setPassword(properties.getPassword().toCharArray());
        options.setConnectionTimeout(properties.getTimeout());
        options.setKeepAliveInterval(properties.getKeepAlive());
        options.setAutomaticReconnect(true);
        return options;
    



上述代码中,往spring容器中注入了MqttClient 对象,如果需要发布消息的话,可以直接在类中注入 MqttClient 直接使用:

mqttClient.publish(String topic, MqttMessage message)

枚举

MqttTopicEnum

package top.wushanghui.mqttclient.enums;

public enum MqttTopicEnum 

    /**
     * 默认topic
     * 使用了通配符
     */
    DEFAULT_TOPIC("sensor/+/#", 0);

    /**
     * 主题
     */
    private String topic;
    /**
     * 服务质量
     */
    private Integer qos;

    MqttTopicEnum(String topic, Integer qos) 
        this.topic = topic;
        this.qos = qos;
    

    public String getTopic() 
        return topic;
    

    public void setTopic(String topic) 
        this.topic = topic;
    

    public Integer getQos() 
        return qos;
    

    public void setQos(Integer qos) 
        this.qos = qos;
    


回调(消费消息)

package top.wushanghui.mqttclient.callback;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.stereotype.Component;
import top.wushanghui.mqttclient.enums.MqttTopicEnum;

/**
 * @author 吴尚慧
 * @since 2021/11/11 20:36
 */
@Slf4j
@Component
public class MyPushCallback implements MqttCallbackExtended 

    private MqttClient mqttClient;

    @Override
    public void connectComplete(boolean reconnect, String serverURI) 
        log.info("MyPushCallback connectComplete reconnect=, serverURI=", reconnect, serverURI);
        if (reconnect) 
            // 重新连接后,需重新订阅主题
            try 
                log.info("mqttClient=", mqttClient);
                mqttClient.subscribe(MqttTopicEnum.DEFAULT_TOPIC.getTopic(), MqttTopicEnum.DEFAULT_TOPIC.getQos());
             catch (MqttException e) 
                log.error("订阅主题失败", e);
            
        
    

    @Override
    public void connectionLost(Throwable cause) 
        log.error("MyPushCallback connectionLost cause=", cause.toString());
    

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception 
        log.info("MyPushCallback messageArrived topic=, message=", topic, message);
    

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) 
        log.info("MyPushCallback deliveryComplete token=", token);
    

    public void setMqttClient(MqttClient mqttClient) 
        this.mqttClient = mqttClient;
    


在messageArrived方法中可以消费消息。

启动服务,用工具发个消息试一下:

在控制台就可以收到消息:

需要源码的小伙伴点击:传送门

以上是关于【玩转SpringBoot】优雅的整合Body和Header参数的主要内容,如果未能解决你的问题,请参考以下文章

玩转 SpringBoot 2 之整合 JWT 上篇

SpringBoot 优雅的整合 Shiro

玩转 SpringBoot 2 快速整合拦截器

SpringBoot2.0之五 优雅整合SpringBoot2.0+MyBatis+druid+PageHelper

netty玩转irving聊天室(android整合netty客户端+springboot整合netty服务端),附源码

玩转SpringBoot之整合Mybatis拦截器对数据库水平分表