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

    技术2022-07-11  157

    前言:这段时间做了一个课程设计,内容是将温湿度传感器采集到的温湿度数据上传到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="zh" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Thymleaf</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous"> <link rel="stylesheet" th:href="@{/layui.css}"> <script th:src="@{/layui.js}"></script> <script></script> </head> <body background="2.jpg"> <!--2.jpg--> <!--<div style="text-align: center;margin-top: 20px">--> <!-- <button type="button" class="btn btn-success ">温湿度采集表格数据展示</button>--> <!--</div>--> <h1 style="text-align: center;margin-top: 20px">温湿度超声波采集表格数据展示</h1> <h2 style="text-align: center;margin-top: 20px;color: mediumvioletred">author : cx</h2> <!--<div style="text-align: center;margin-top: 20px">--> <!-- <button type="button" class="btn btn-danger ">author:陈霞</button>--> <!--</div>--> <table class="table table-hover table-dark" th:align="center" th:valign="middle" style="margin-top: 40px"> <thead> <tr> <th scope="col">组号</th> <th scope="col">温度</th> <th scope="col">湿度</th> <th scope="col">ip地址</th> <th scope="col">距离</th> <th scope="col">采集时间</th> </tr> </thead> <tbody> <tr th:each="c,State:${message}"> <th scope="row" th:text="${c.id}"></th> <td th:text="${c.temp}"></td> <td th:text="${c.humidity}"></td> <td th:text="${c.ip}"></td> <td th:text="${c.distance}"></td> <td th:text="${c.time}"></td> </tr> </tbody> </table> <div style="text-align: center"> <a href="/humiture" rel="external nofollow" > <button type="button" class="btn btn-primary ">点击查看动态折现图</button> </a> </div> </body> </html>

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

    客户端发送温湿度格式为 字符串,中间以逗号隔开例如“29,88”(温度,湿度)服务器就会接收到对应的温湿度信息并且存入数据库!

    都看到这里了,不妨点个赞再走呗,创作不易,不想被白嫖,求点赞,奥利给!!!

    Processed: 0.011, SQL: 9