springboot+Netty搭建web服务器实现物联网温湿度采集

前言:这段时间做了一个课程设计,内容是将温湿度传感器采集到的温湿度数据上传到web服务器并以表格或者折线图的方式可视化展示出来。

话不多说:上代码
①Netty服务器搭建

NettyServer.java

/**
 * @author cx
 * @Time 2020/6/29 22:00
 * @Description netty 服务器配置
 */
public class NettyServer {
    public void start(InetSocketAddress socketAddress){
        /**new 一个主线程组*/
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        /**new 一个工作线程组*/
        EventLoopGroup workGroup = new NioEventLoopGroup(200);
        ServerBootstrap bootstrap = new ServerBootstrap()
                .group(bossGroup,workGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ServerChannelInitializer())
                .localAddress(socketAddress)
                /**设置队列的大小*/
                .option(ChannelOption.SO_BACKLOG,1024)
                /**两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文*/
                .childOption(ChannelOption.SO_KEEPALIVE,true);
                /**绑定端口,开始接收进来的连接*/
                try{
                    ChannelFuture future = bootstrap.bind(socketAddress).sync();
                    System.out.println("服务器ip为:"+socketAddress.getHostName());
                    System.out.println("服务器端口号为:"+socketAddress.getPort());
                    future.channel().closeFuture().sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    /**关闭主线程组*/
                    bossGroup.shutdownGracefully();
                    /**关闭工作线程组*/
                    workGroup.shutdownGracefully();
                }
    }
}

NettyServerHandler.java

/**
 * @author cx
 * @Time 2020/6/29 22:23
 * @Description 服务端业务处理
 */
@Component
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    /**获取实例化对象*/
    @Autowired
    protected IHumitureService humitureService;

    private static NettyServerHandler serverHandler;

    /**配合@Component注解获取service层的bean*/
    @PostConstruct
    public void init(){
        serverHandler = this;
        serverHandler.humitureService = this.humitureService;
    }

    /**
     * 客户端连接会触发
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端发起连接!!!!");
    }

    /**
     * 客户端发消息会触发
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        /**获取客户端的IP*/
        InetSocketAddress insocket = (InetSocketAddress)ctx.channel().remoteAddress();
        String ip = insocket.getAddress().getHostAddress();
        /**将温湿度数据处理*/
        String tem = msg.toString();
        String[] arr = tem.split(",");
        Humiture  humiture = new Humiture();
        humiture.setTemp(arr[0]);
        humiture.setHumidity(arr[1]);
        humiture.setIp(ip);
        /**调用业务层方法将数据写入数据库*/
        serverHandler.humitureService.insertData(humiture);
        System.out.println("服务器接收到客户端的温度,湿度---"+msg.toString());
        System.out.println("温湿度写入数据库成功!!!!");
        ctx.write("receive OK!");
        ctx.flush();
    }

    /**
     * 发生异常触发
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

注意:上面代码解决了一个问题,就是如何在controller层外获得bean,然后调用业务层方法将获得的数据写入数据库。方法是在handler类上加一个@Component注解,然后写一个init()方法,init()方法上面加一个@PostConstruct注解将bean实例化

ServerChannelInitializer .java

/**
 * @author cx
 * @Time 2020/6/29 22:06
 * @Description 初始化编码器
 */
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        /**添加编解码*/
        socketChannel.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
        socketChannel.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
        socketChannel.pipeline().addLast(new NettyServerHandler());
    }
}

②controller层代码

HumitureController .java

/**
 * @author cx
 * @Time 2020/6/28 15:32
 * @Description 温湿度采集 控制层
 */
@Controller
public class HumitureController {
    @Autowired
    private IHumitureService iHumitureService;

    @GetMapping("/test")
    @ResponseBody
    public List<Humiture> list()
    {
        return iHumitureService.listHumiture();
    }

    @GetMapping("/list")
    @ResponseBody
    public Map<String,Object> selectAll()
    {
        Map<String,Object> map = new HashMap<>();
        List<Humiture> data = iHumitureService.listHumiture();
        map.put("code",0);
        map.put("msg","随便写点东西");
        map.put("count",10);
        map.put("data",data);
        return map;
    }
}

IndexController .java

/**
 * @author cx
 * @Time 2020/6/28 10:22
 * @Description 页面信息展示 控制层
 */
@Controller
public class IndexController {

    @Autowired
    private IHumitureService iHumitureService;

    @GetMapping("/")
    public String hello(ModelMap modelMap)
    {
        List<Humiture> list = iHumitureService.listHumiture();
        modelMap.addAttribute("message",list);
        return "index";
    }

    @GetMapping("/humiture")
    public String humiture(ModelMap modelMap)
    {
        List<Humiture> list = iHumitureService.listHumiture();
        modelMap.addAttribute("value",list);
        return "humiture";
    }
}

③实体层

/**
 * @author cx
 * @Time 2020/6/28 15:11
 * @Description 温湿度检测 实体
 */
public class Humiture {

    /**数据编号*/
    private int id;
    /**温度*/
    private String temp;
    /**湿度*/
    private String humidity;
    /**ip地址*/
    private String ip;
    /**采集时间*/
    private String time;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTemp() {
        return temp;
    }

    public void setTemp(String temp) {
        this.temp = temp;
    }

    public String getHumidity() {
        return humidity;
    }

    public void setHumidity(String humidity) {
        this.humidity = humidity;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }
}

④mapper层

HumitureMapper .java

/**
 * @author cx
 * @Time 2020/6/28 15:18
 * @Description 温湿度采集 数据层
 */
@Repository
public interface HumitureMapper {
    /**
     * @description 温湿度采集 查询
     *
     * @param
     * @return 温湿度采集 列表
     */
    public List<Humiture> listHumiture();
    /**
     * @description 温湿度采集 存库
     *
     * @param
     * @return 温湿度采集 存库
     */
    public int insertData(Humiture humiture);
}

⑤service层代码

IHumitureService .java

/**
 * @author cx
 * @Time 2020/6/28 15:22
 * @Description 温湿度采集 业务层接口
 */
public interface IHumitureService {
    /**
     * @description 温湿度采集 查询
     *
     * @param
     * @return 温湿度采集 列表
     */
    public List<Humiture> listHumiture();
    /**
     * @description 温湿度采集 存库
     *
     * @param
     * @return 温湿度采集 存库
     */
    public int insertData(Humiture humiture);
}

HumitureServiceImpl .java

/**
 * @author cx
 * @Time 2020/6/28 15:23
 * @Description 温湿度采集 业务层实现
 */
@Service
public class HumitureServiceImpl implements IHumitureService {

    @Autowired
    private HumitureMapper humitureMapper;

    /**
     * @description 温湿度采集 查询
     *
     * @param
     * @return 温湿度采集 列表
     */
    @Override
    public List<Humiture> listHumiture()
    {
        return humitureMapper.listHumiture();
    }
    /**
     * @description 温湿度采集 存库
     *
     * @param
     * @return 温湿度采集 存库
     */
    @Override
    public int insertData(Humiture humiture){
        return humitureMapper.insertData(humiture);
    }
}

⑥resource下的mapper

HumitureMapper .xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hunau.springboot.mapper.HumitureMapper">
    <resultMap id="HumitureResult" type="Humiture">
        <result property="id" column="id"/>
        <result property="temp" column="temp"/>
        <result property="humidity" column="humidity"/>
        <result property="ip" column="ip"/>
        <result property="time" column="time"/>
    </resultMap>

    <select id="listHumiture" resultMap="HumitureResult">
        select * from tb_humiture
    </select>

    <insert id="insertData" parameterType="Humiture">
        insert into tb_humiture
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="temp != null  and temp != ''  ">temp,</if>
            <if test="humidity != null  and humidity != ''  ">humidity,</if>
            <if test="ip != null  and ip != ''  ">ip,</if>
            <if test="time != null  and time != ''  ">time,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="temp != null  and temp != ''  ">#{temp},</if>
            <if test="humidity != null  and humidity != ''  ">#{humidity},</if>
            <if test="ip != null  and ip != ''  ">#{ip},</if>
            <if test="time != null  and time != ''  ">#{time},</if>
        </trim>
    </insert>
</mapper>

⑦前端代码

humiture.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>test</title>
    <script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts/echarts-all-3.js"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body> <!--5.jpg-->

<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="width: 600px;height:400px;position: absolute; top:50%; left: 50%; margin-top: -200px;margin-left: -300px"></div>
<!--<div style="left:945px;top:819px ">-->
<!--    <a href="/" rel="external nofollow" >-->
<!--        <button type="button" class="btn btn-primary ">返回首页</button>-->
<!--    </a>-->
<!--</div>-->
<!--<script th:inline="javascript">-->
<!--    var data = [[${value}]];-->
<!--    console.log(data);-->
<!--</script>-->
<script th:inline="javascript">
    /**基于准备好的dom,初始化echarts实例*/
    var myChart = echarts.init(document.getElementById('main'));
    var data = [[${value}]];
    console.log(data);
    /**温度*/
    var temperature = [];
    /**湿度*/
    var humidity = [];
    /**采集时间*/
    var coltime = [];
    /**获取温度打包为数组*/
    for (i in data)
        temperature.push(data[i].temp);
    console.log(temperature);
    /**获取湿度打包为数组*/
    for (i in data)
        humidity.push(data[i].humidity);
    console.log(humidity);
    for (i in data)
        coltime.push(data[i].time);
    console.log(coltime);
    /**指定图表的配置项和数据*/
    option = {
        title: {
            text: '温湿度动态图'
        },
        tooltip: {
            trigger: 'axis'
        },
        legend: {
            data: ['温度', '湿度']
        },
        grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true
        },
        toolbox: {
            feature: {
                saveAsImage: {}
            }
        },
        xAxis: {
            type: 'category',
            boundaryGap: false,
            data: coltime
        },
        yAxis: {
            type: 'value'
        },
        series: [
            {
                name: '温度',
                type: 'line',
                stack: '总量',
                data: temperature
            },
            {
                name: '湿度',
                type: 'line',
                stack: '总量',
                data: humidity
            }
        ]
    };

    /**使用刚指定的配置项和数据显示图表*/
    myChart.setOption(option);
</script>
</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>test</title>
    <script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts/echarts-all-3.js"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body> <!--5.jpg-->

<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="width: 600px;height:400px;position: absolute; top:50%; left: 50%; margin-top: -200px;margin-left: -300px"></div>
<!--<div style="left:945px;top:819px ">-->
<!--    <a href="/" rel="external nofollow" >-->
<!--        <button type="button" class="btn btn-primary ">返回首页</button>-->
<!--    </a>-->
<!--</div>-->
<!--<script th:inline="javascript">-->
<!--    var data = [[${value}]];-->
<!--    console.log(data);-->
<!--</script>-->
<script th:inline="javascript">
    /**基于准备好的dom,初始化echarts实例*/
    var myChart = echarts.init(document.getElementById('main'));
    var data = [[${value}]];
    console.log(data);
    /**温度*/
    var temperature = [];
    /**湿度*/
    var humidity = [];
    /**采集时间*/
    var coltime = [];
    /**获取温度打包为数组*/
    for (i in data)
        temperature.push(data[i].temp);
    console.log(temperature);
    /**获取湿度打包为数组*/
    for (i in data)
        humidity.push(data[i].humidity);
    console.log(humidity);
    for (i in data)
        coltime.push(data[i].time);
    console.log(coltime);
    /**指定图表的配置项和数据*/
    option = {
        title: {
            text: '温湿度动态图'
        },
        tooltip: {
            trigger: 'axis'
        },
        legend: {
            data: ['温度', '湿度']
        },
        grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true
        },
        toolbox: {
            feature: {
                saveAsImage: {}
            }
        },
        xAxis: {
            type: 'category',
            boundaryGap: false,
            data: coltime
        },
        yAxis: {
            type: 'value'
        },
        series: [
            {
                name: '温度',
                type: 'line',
                stack: '总量',
                data: temperature
            },
            {
                name: '湿度',
                type: 'line',
                stack: '总量',
                data: humidity
            }
        ]
    };

    /**使用刚指定的配置项和数据显示图表*/
    myChart.setOption(option);
</script>
</body>
</html>

代码到此结束
下面上效果图
效果图1
效果图2

热门文章

暂无图片
编程学习 ·

大数据-java基础-第01章 java概述

1.java简介 答:java是1995年推出的一门高级编程语言,它即安全、可移植、又可跨平台,并且可以解决Internet上的大型应用问题。 2.java的特点 答: ①简单易用、完全面向对象; ②与平台无关型、可扩展性强; ③可移植高、支持分布式编程; ④半编译半解释型; ⑤健壮、安全可…
暂无图片
编程学习 ·

最新99道前端面试题

前言:7月份的第一天,毕业马上两年了,居安思危,为后边儿做个准备吧“即便不跳,也始终保持跳的能力”1.vue优点?答:轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;双向数据绑定:…
暂无图片
编程学习 ·

【考试记录】Apsara Clouder基础技能认证:实现调用API接口

从今天开始,准备把阿里的认证尽可能多的考出来。原因有这么几个:研究生要毕业了,除了把论文写好,还有找工作的压力,所以想尽可能多的考出几个证来证明自己的学习能力;研究生毕业后想找个教师的工作,所以得以身作则,多学习知识,这样教学生才能有底气。知道自己现在能力…
暂无图片
编程学习 ·

SQL Server将查询结果输出到文件中保存

1. 手动方法在SSMS中,查询出结果后,右键点击"copy/copy with headers"可以复制结果,打开空白csv/Excel后粘贴即可在SSMS中,查询出结果后,右键点击"save result as"(结果另存为)并保存即可 注意按照这种方法保存的结果是没有字段名称的,相当于上一种…
暂无图片
编程学习 ·

一文详解 Ansible 的自动化运维

一、Ansible 概述 Ansible 是近年来越来越火的一款开源运维自动化工具,通过Ansible可以实现运维自动化,提高运维工程师的工作效率,减少人为失误。 Ansible 通过本身集成的非常丰富的模块可以实现各种管理任务,其自带模块超过上千个。更为重要的是,它操作非常简单,即使小白…
暂无图片
编程学习 ·

EasyNTS上云网关内配置EasyNVR云终端成功后显示设备离线问题解决

之前为大家简单介绍过EasyNTS上云网关,一部分是为了进行网络穿透而产生的设备,目前有部分用户已经在进行了内测,我们也会收集一些内测用户的问题,集中排查解决,以达到更好的使用效果。有的用户在EasyNTS上云网关内进行流媒体终端EasyNVR硬件配置测试时,设备已经配置完成,…
暂无图片
编程学习 ·

ITEST考试助手 --- 记一次我与ITEST的拉锯战

文章目录0x0 前言0x1 1.0版本 -- 解除限制我方进攻0x2 2.0版本 - 自动翻译与解析听力我方进攻ITEST方防御0x3 3.0版本 -- 解除切屏限制与添加翻译助手反制防御我方进攻ITEST防御0x4 4.0版本 - 全随机与ajax拦截反制防御我方进攻ITEST防御0x5 5.0版本 - 只读属性的胜利反制防御我…
暂无图片
编程学习 ·

如何重命名data.frame中的单个列?

本文翻译自:How to rename a single column in a data.frame? I know if I have a data frame with more than 1 column, I can use 我知道如果我有一个多于一列的数据框,我可以使用 colnames(x) <- c("col1","col2")to rename the columns. 重命名…
暂无图片
编程学习 ·

springboot整合poi导入excel案例

1.在pom.xml中添加poi依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.13</version></dependency><dependency><groupId>org.apache.poi</groupId><artifac…
暂无图片
编程学习 ·

ubuntu python 升级 和pip匹配问题

ubuntu16.04,卸载系统自带的python3.5引发了一宗惨案,好在最终完美解决https://blog.csdn.net/qq_29935433/article/details/105568942?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribut…
暂无图片
编程学习 ·

设计模式学习——单例模式

一、单例模式的概念1.1 概念单例模式是指 确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式的特点是隐藏其所有的构造方法。属于创建型模式。1.2 单例模式的适用场景确保任何情况下都绝对只有一个实例。例如ServletContext、ServletConfig、Applicat…
暂无图片
编程学习 ·

画图-身份证

画图函数:base_dir = f{main.BASE_DIR}/quality_management_logic/dataCenter/self.draw.text((55, self.height * 0.31), self.personName, (0, 0, 0),font=ImageFont.truetype(os.path.join(base_dir, msyh.ttc),24)) #personname应用: # -*- coding: utf-8 -*- # import …
暂无图片
编程学习 ·

咸鱼软件应用—VMware下安装ubantu

咸鱼软件应用—VMware下安装ubantuubantu简介开源下载地址在VMware虚拟机安装ubantu系统 为了测试固件需要安装Linux系统,后面有测试说明。现在先把ubantu系统装上再说~ubantu简介 ubuntu基于linux的免费开源桌面PC操作系统,十分契合英特尔的超极本定位,支持x86、64位和ppc架…
暂无图片
编程学习 ·

echarts关系图多条连线

最近用echarts做图的关系实现图数据结构连接线会重合,解决办法 import Graph from echarts/lib/data/Graph import echarts from echartsconst Edge = Graph.Edge const Node = Graph.Nodefunction generateNodeKey(id) {return _EC_ + id; }Graph.prototype.addEdge = functi…
暂无图片
编程学习 ·

Strategies For Pre-Training Graph Neural Networks

Paper : STRATEGIES FOR PRE-TRAINING GRAPH NEURAL NETWORKS Code : official摘要 作者解决的问题是如何预训练一个GNN网络,保证预训练的结果在具体数据集中finetune不会negative transfer 的现象。作者在文中并没有细致的解释为什么GNN上进行transfer learning 会更难,这个…
暂无图片
编程学习 ·

CQF笔记M1L3泰勒级数和转移概率密度函数

CQF笔记M1L3泰勒级数和转移密度函数Module 1 Building Blocks of Quant FinanceLecture 2 Taylor Series and Transition Density Functions泰勒级数期权价格的泰勒级数trinomial random walk和转移密度函数Similarity solutions 求解过程 Module 1 Building Blocks of Quant F…
暂无图片
编程学习 ·

Chen08

[Calendar] 实例化Calendar Calendar c = Calendar.getInstance(); 月份是从0开始计数的(0-11) c.set();//日历设置到某一天 c.get();//日历翻到的那一天BigInteger 表示整数、 BigDecimal表示浮点数 对于输出浮点数保留几位小数的问题,可以使用DecimalFormat类, DecimalForm…