需要了解的过滤器
过滤器
1. 概念
过滤器: 从名字上理解就是对于事件的过滤操作,在web 中的过滤器,就是对于请求进行过滤操作,我们使用过滤器,就可以对于请求进行拦截操作,然后进行响应的处理操作,实现很多的特殊的功能,比如登录控制、权限控制操作、过滤敏感词汇.
2. 过滤器原理
流程:
浏览器 和web 资源之间存在一个过滤器,对于资源进行处理操作,浏览器进行Http请求操作,首先经过过滤器,然后携带放行的request 和 Reponse 进入到web 资源 ,然后将资源进行返回操作,http 进行响应。
注意拦截器的工作不仅仅对于请求进行拦截操作,而且也会对响应进行拦截操作。
3. 配置
过滤器的使用总共有两种方式: 一种是通过注解的形式进行实现操作。一种是通过web.xml进行实现。需要相关的配置文件Filter就在servlet-api.jar中,我们将该jar包放到WEB-INF下的lib目录下面,然后加入项目。如果是使用的maven 则需要进行如下的操作
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope> </dependency>
3.1 注解式配置
对于注解的源码进行分析
String[] value() default {}; String[] urlPatterns() default {}; // 其中两者的含义是相同的,urlPatterns和value只能配置一个,不能两个都配置,两个都配置就会报错。
进行条件的过滤操作的时候,设置过滤器的限制过滤的条件路径。
@WebFilter(urlPatterns = {"/Day45/user", "/Day45/admin"})@WebFilter("/Day45/user") ==> 注解中的value属性
3.2 web.xml式配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><filter><!-- 当前过滤器名字 --><filter-name>BFilter</filter-name><!-- 对应当前过滤器的.class文件 --><filter-class>com.java.a_filter.BFilter</filter-class></filter><filter-mapping><!-- 对应过滤器的名字 --><filter-name>BFilter</filter-name><!-- 限制过滤路径 --><url-pattern>/*</url-pattern></filter-mapping><filter-mapping><!-- 对应过滤器的名字 --><filter-name>BFilter</filter-name><!-- 限制过滤路径 --><url-pattern>/andmin/user</url-pattern></filter-mapping>
</web-app>
4. 过滤器链
FilterChain
过滤器链就是 在浏览器和 web 资源之间 有多个过滤器组成的一条过滤器链,返回的数据会经过每一个过滤器,中间多个过滤器形成一个过滤器链。
4.1 执行顺序
过滤器链的执行顺序,两种情况下需要进行考虑操作:
- 使用注解的方式进行配置过滤器,这个时候需要考虑的是类的名称在字典中的顺序,顺序在前的优先进行执行操作。在后的将靠后进行执行操作。
- 使用web.xml 文件进行配置filter 过滤器,根据在web.xml文件中的顺序来决定过滤器链的执行流程。靠前的优先进行执行操作。
- 如果两者进行混合使用,那么在web.xml 文件中的配置会优先进行操作执行。
4.2 FilterChain
通过查看源码能够得到的结论是: FilterChain 就只有一个方法。其实这个方法就是用来对于拦截进行放行操作的,如果有多个拦截器,那么就会继续调用下一个Filter 进行拦截。doFilter 方法需要传入个参数,一个是ServletRequest 参数 ,一个是ServletReponse 参数,这个直接进行传入就行。
Tomcat 在调用过滤器的时候,默认会传入Request 和 Reponse ,这个参数封装了请求和响应,我们直接使用就行。ServletResquest和ServletResponse可以直接强转成HttpServletRequest和HttpServletResponse,然后使用相应的方法。
//将ServletRequest 转换为 HttpServletRequest HttpServletRequest httpServletRequest =(HttpServletRequest) servletRequest;
@WebFilter("/*")
public class Filter01 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("调用过滤器01对请求进行过滤~~~~");//放行,如果还有过滤器,那么就执行下一个过滤器filterChain.doFilter(servletRequest,servletResponse);System.out.println("调用过滤器01对响应进行过滤~~~~");}@Overridepublic void destroy() {}
}
@WebFilter("/*")
public class Filter02 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("调用过滤器02对请求进行过滤~~~~");//放行,如果还有过滤器,那么就执行下一个过滤器filterChain.doFilter(servletRequest,servletResponse);System.out.println("调用过滤器02对响应进行过滤~~~~");}@Overridepublic void destroy() {}
}
运行结果:调用过滤器01对请求进行过滤调用过滤器02对请求进行过滤调用过滤器02对响应进行过滤调用过滤器01对响应进行过滤
5.过滤器初始化参数
指 加载一定的资源的时候,敏感词汇的过滤操作,跟当前的过滤器进行绑定操作,这里能够使用初始化参数,两种方式:
- 通过注解的方式来完成配置操作。
- 通过web.xml 实现配置操作
5.1 注解实现初始化
// 注解方式完成
@WebFilter(value = "/*",initParams = {@WebInitParam(name = "filename", value = "saolei.properties")})
5.2 xml 实现初始化
<!-- XML配置方式完成 -->
<filter><filter-name>EFilter</filter-name><filter-class>com.qfedu.a_filter.EFilter</filter-class><!-- 初始化参数 --><init-param><param-name>filename</param-name><param-value>saolei.xml</param-value></init-param></filter>
<filter-mapping><filter-name>EFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
6. 过滤器的声明周期
过滤器也有声明周期,Filter 的声明周期和Servlet 的声明周期十分相似。
过滤器总共有三个阶段: 初始化、拦截过滤、销毁
- 初始化阶段:当服务器启动的时候,我们的服务器就会读取配置文件,扫描注解,然后来创建我们的过滤器。
- 拦截和过滤阶段:只要请求资源的路径和拦截的路径相同,则过滤器就会对请求进行过滤操作,这个阶段在服务器运行的过程中会一直循环。
- 销毁阶段: 当服务器进行关闭的时候,服务器创建的过滤器也会随之销毁。
创建一个Filter类,实现其中所有的方法
import javax.servlet.*;
import java.io.IOException;public class LifeCycleFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 该方法是初始化方法、在Filter 创建的时候调用}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 该方法是过滤和拦截的方法,当请求和拦截匹配的时候进行调用}@Overridepublic void destroy() {// 这个方法是销毁方法,在Filter 销毁前进行调用}
}1.启动服务器时,调用初始化方法
2.进行拦截时调用doFilter方法
3.关闭服务器的时候调用销毁方法
7. FilterConfig
FilterConfig 和 FilterChain 这两个对象是通过服务器在创建和调用Filter 对象的时候所传入的,这两个对象十分有用,FilterConfig 对象能够读取我们的配置的初始化参数、FilterChain 可以实现多个Filter 之间的连接操作。
源码剖析:
- getFilterName():获取filter的名称
- getServletContext():获取ServletContext
- getInitparamter(String var1):获取配置的初始参数的值
- getInitParamterNames():获取配置的所有参数名称
分析:
我们在init方法中使用FilterConfig 来读取配置的数据库信息,然后进行输出操作。FilterConfig 的作用就是用来读取配置文件。
public class MyFilterConfig implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("-----------获取全部key:value------------");//得到所有配置参数的名字Enumeration<String> names = filterConfig.getInitParameterNames();while (names.hasMoreElements()) {//得到每一个名字String name = names.nextElement();System.out.println(name+" = "+filterConfig.getInitParameter(name));}System.out.println("-----------end.....------------");}// 输出的结果是配置信息的键值对数据@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}@Overridepublic void destroy() {}
}
<filter><filter-name>myFilterConfig</filter-name><filter-class>com.clucky.filter.MyFilterConfig</filter-class><init-param><param-name>driver</param-name><param-value>com.mysql.jdbc.Driver</param-value></init-param><init-param><param-name>url</param-name><param-value>jdbc:mysql://localhost:3306/equip_employ_manage?serverTimezone=GMT</param-value></init-param><init-param><param-name>username</param-name><param-value>root</param-value></init-param><init-param><param-name>password</param-name><param-value>root</param-value></init-param></filter><filter-mapping><filter-name>myFilterConfig</filter-name><url-pattern>/*</url-pattern></filter-mapping>
8. 实例实现
8.1 编码操作
@WebFilter("/*")
public class AEncodingFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 获取当前Tomcat服务器版本信息String serverInfo = request.getServletContext().getServerInfo();HttpServletRequest httpServletRequest = (HttpServletRequest) request;HttpServletResponse httpServletResponse = (HttpServletResponse) response;if (serverInfo.startsWith("Apache Tomcat/7") || serverInfo.startsWith("Apache Tomcat/6")) {// 存在ISO-8859-1// 留下一个小问题System.out.println("Tomcat 6 or 7");} else {// Tomcat 8以及以上处理POST请求中文乱码问题和对应Response响应乱码问题System.out.println("Tomcat 8 or 9");httpServletRequest.setCharacterEncoding("utf-8");httpServletResponse.setContentType("text/html;charset=utf-8");}// 过滤链进行放行操作chain.doFilter(httpServletRequest, httpServletResponse);}@Overridepublic void destroy() {}
}
8.2 登录过滤操作
先进行封装操作,使用抽象类能够保证该类不会被实例化,实例化的话只能够使用匿名内部类。
下面是相关的代码总结。
public abstract class BaseFilter implements Filter {/*** 过滤器的初始化操作** @param filterConfig 初始化参数 过滤器的配置* @throws ServletException Servlet异常*/@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}/*** 过滤的销毁方法*/@Overridepublic void destroy() {Filter.super.destroy();}
}
@WebFilter("/*")
public class MyFilter extends BaseFilter{/*** 【核心方法】用于制定针对于用户请求和响应的过滤规则,需要通过 FilterChain 进行请求放行操作** @param servletRequest ServletRequest 用户请求符合 Servlet 要求的 request 对象* @param servletResponse ServletResponse 根据用户请求绑定创建的符合 Servlet 要求的 Response 对象* @param filterChain FilterChain 过滤器链类型,用于【放行】请求* @throws IOException IO异常* @throws ServletException Servlet 异常*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//1.强制类型转换HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse)servletResponse;//3. 获取请求路径String uri = request.getRequestURI();StringBuffer requestURL = request.getRequestURL();System.out.println(requestURL);System.out.println(uri);//未进行登录时能够放行的操作if (uri.endsWith("/")||uri.endsWith("login.html")|| uri.endsWith("loginServlet")){// 放行操作filterChain.doFilter(request, response);} else {// 判断是否存在对象,如果存在过Object id1 = request.getSession().getAttribute("u_account");// 如果已经登录成功if (id1 != null){filterChain.doFilter(request,response);} else {response.setContentType("text/html;charset=utf-8");response.getWriter().write("<script>" +"alert('请先登录');"+"location.href='/login.html'</script>");}}}
}
8.3 实现敏感词汇过滤操作
// Filter 代码import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;@WebFilter(servletNames = {"comment"},initParams = {@WebInitParam(name = "sensitiveWord", value = "zz")})
public class CommentFilter implements Filter {private List<String> sensitiveWords = new ArrayList<>();@Overridepublic void init(FilterConfig filterConfig) throws ServletException {//得到敏感词汇String word = filterConfig.getInitParameter("sensitiveWord");//加入集合sensitiveWords.add(word);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//设置编码servletRequest.setCharacterEncoding("utf-8");servletResponse.setContentType("text/html;charset=utf-8");//得到评论String message = servletRequest.getParameter("message");for (String sensitiveWord : sensitiveWords) {//对所有敏感词汇进行过滤if (message.contains(sensitiveWord)){//替换敏感词汇message = message.replace(sensitiveWord, "**");}}//存入request域servletRequest.setAttribute("comment",message);//放行filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {}
}
// Servlet 代码import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.HashSet;@WebServlet(name = "comment",value = "/comment")
public class CommentServlet extends HttpServlet {//记录评论敏感词汇的ipprivate HashSet<String> hashSet = new HashSet<>();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String message = request.getParameter("message");String comment = (String) request.getAttribute("comment");if (message.equals(comment)){System.out.println("没有敏感词汇.....");//设置名字request.setAttribute("name","good boy:");}else {//有敏感词汇,记录IPString localAddr = request.getLocalAddr();System.out.println(localAddr);hashSet.add(localAddr);//设置名字request.setAttribute("name","bad boy:");}//转发到comment.jsp页面request.getRequestDispatcher("/comment.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
// JSP 页面<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>评论</title>
</head>
<body>
<h1>输入评论内容</h1>
<form action="${pageContext.request.contextPath}/comment" method="post"><textarea name="message" cols="30" rows="10"></textarea><input type="submit" value="提交">
</form>
<p >${requestScope.get("name")}<span style="color: red">${requestScope.get("comment")}</span></p>
</body>
</html>
相关文章:

需要了解的过滤器
过滤器 1. 概念 过滤器: 从名字上理解就是对于事件的过滤操作,在web 中的过滤器,就是对于请求进行过滤操作,我们使用过滤器,就可以对于请求进行拦截操作,然后进行响应的处理操作,实现很多的特殊…...

VUE3的setup函数
文章目录 目录 文章目录 前言 一、setup函数是什么? 二、使用步骤 三、vue3中文文档和面向vue3的组件库 总结 前言 Vue3是一个面向数据驱动的渐进式JavaScript框架,其的设计理念包括简洁、灵活和高效。相比Vue2,Vue3的架构设计有很大的不同&…...

停车场管理系统文件录入(C++版)
❤️作者主页:微凉秋意 ✅作者简介:后端领域优质创作者🏆,CSDN内容合伙人🏆,阿里云专家博主🏆 文章目录一、案例需求描述1.1、汽车信息模块1.2、普通用户模块1.3、管理员用户模块二、案例分析三…...

线程(Thread)的三种等待唤醒机制详解
1、为什么需要线程的等待和唤醒 线程的等待唤醒机制是一种经典的“生产者和消费者”模型。例如食品加工厂,食品加工人员和原料补给人员,在有充足原料时,补给人员是在等待,等到原料不够时,食品加工人员通知补给人员&am…...

从零学习python - 13模块的导入与使用(实现单例模式)
模块基础知识 # 项目 > 包 > 模块 > 变量\方法\类 # 在python中,模块是代码组织的一种方式,把功能相近的函数或类放到一个文件中,一个文件(.py)就是一个模块,模块名就是文件名去掉py后缀. # 好处:提高代码可复用性和可维护性,一个模块编写完成后,很方便在其他项目中导…...

国产SSD、内存卷哭国外大厂,三星宣布减产涨价在路上了
PC 圈有一句话是这么说的:论价格屠夫还得看国产品牌! 可不是嘛,国产长鑫、长江算是彻底将全球存储芯片市场搅局者这一「骂名」坐实了! 不说特别早期,前几年吧,普通单条 8G DDR4 内存都能卖到六七百元&…...

数据库管理-第六十六期 SQL Domain(20230413)
数据库管理 2023-04-13第六十六期 SQL Domain1 基本介绍2 Domain的表达式和条件3 语法4 语义5 示例总结第六十六期 SQL Domain 上一期一笔带过了部分Oracle 23c的新特性,这一期重点讲一下SQL Domain新特性。 【https://docs.oracle.com/en/database/oracle/oracle-…...

《Vue3实战》 第一章 nods/npm安装、配置
1、nods.js安装(Windows) 1.1、下载并安装node https://nodejs.org/en/ , 安装到d盘nodejs目录 1.2、配置环境变量 path配置 1.3、配置全局包存放目录和缓存目录 在根目录下创建node_global(全局包存放目录)和node_cache&…...

JAVA练习104-四数相加 II
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、题目-四数相加 II 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总结 前言 提示:这里可以添加本文要记录的大概内容: 4月10日练…...

【C++基础】引用(引用的概念;引用的特性;常引用;使用场景:做输出型参数、大对象传参、做输出型返回值、返回大对象的引用);引用和指针的区别)
六、引用 6.1 引用的概念 引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。(语法上) 格式:类型& 引用变量名(对象名) …...

Redis只用来做缓存?来认识一下它其他强大的能力吧。
当今互联网应用中,随着业务的发展,数据量越来越大,查询效率越来越高,对于时序数据的存储、查询和分析需求也越来越强烈,这时候 Redis 就成为了首选的方案之一。 Redis 提供了多种数据结构,如字符串、哈希表…...

【ES】数据同步集群
【ES】数据同步&集群3.数据同步3.1.思路分析3.1.1.同步调用3.1.2.异步通知3.1.3.监听binlog3.1.4.选择3.2.实现数据同步3.2.1.思路3.2.2.导入demo3.2.3.声明交换机、队列1)引入依赖2)声明队列交换机名称3)声明队列交换机3.2.4.发送MQ消息…...

37岁男子不愿熬夜,回乡养鸡每天准时下班,青山绿水中养鸡,直播间里卖鸡蛋...
37岁男子不愿熬夜,回乡养鸡每天准时下班,青山绿水中养鸡,直播间里卖鸡蛋。今天和大家分享一个创业案例,他叫胡铭浩,来自安徽省旌德县,今年37岁,曾做过车床操作工,开过婚纱摄影店&…...

深度学习和人工智能之间是什么样的关系?
深度学习与人工智能概念的潜在联系,我们依然借助维恩图来说明,如图4.1所示。 1、人工智能 “人工智能”这个概念新鲜时髦但又含混模糊,同时包罗万象。尽管如此,我们仍尝试对 人工智能进行定义:用一台机器处理来自其周围环境的信息,然后将这些…...

实战打靶集锦-016-lampiao
提示:本文记录了博主打靶过程中一次曲折的提权经历 文章1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 80端口探查4.2 1898端口探查4.3 EXP搜索4.3.1 exploit/unix/webapp/drupal_coder_exec4.3.2 exploit/unix/webapp/drupal_drupalgeddon25. 提权5.1 系统信息…...

《Web前端应用开发》考试试卷(模拟题)
一、产品搜索页面 打开“考试文件夹”中的input.html,完成以下步骤: 注意:本题仅能在input.html的(1)为产品名称所在的div添加样式属性,使得产品名称保持在文本框的左边; (2…...

【react全家桶学习】react简介
react是什么? react是用于构建用户界面的JS库,是一个将数据渲染为HTML视图的开源JS库 谁开发的? 由Facebook开发,且开源 为什么要学? 原生JavaScript操作DOM繁琐、效率低 ( DOM-API操作 UI)使用JavaScript直接操作…...

此战成硕,我成功上岸西南交通大学了~~~
友友们,好久不见,很长时间没有更一个正式点的文章了! 是因为我在去年年底忙着准备初试,今年年初在准备复试,直到3月底拟录取后,终于可以写下这篇上岸贴,和大家分享一下考研至上岸的一个过程 文章…...

光耦继电器工作原理及优点概述
光耦继电器是一种电子元器件,也是固态继电器的一种,其主要作用是隔离输入与输出电路,用于保护或者控制电路的正常工作。 光耦继电器工作原理是利用光电转换器将外界信号转化为光信号,通过光纤传输到另一端,再由另一端的…...

【Mysql】mysql8.0.26解压包部署方式
版本背景: 操作系统:centos7.3 mysql版本:mysql-8.0.26-linux-glibc2.12-x86_64.tar 一、前期准备 1、检测操作系统自带安装的mysql和mariadb服务,如存在,需卸载 rpm -qa | grep mysql rpm -qa | grep mariadb 卸载…...

进销存管理系统能为企业带来哪些实际效益?
随着互联网的不断发展,如今的商业世界已经越来越向数字化转型。拥有一套完整的数字化的进销存管理能够极大地提升公司货物进出库存情况的效率和准确性,避免过程中出现不必要的错误和漏洞,从而帮助企业更加稳健地自我发展。那么,一…...

图片怎么转换成pdf格式?这几个方法帮你一键转换
现今电子书籍越来越受到欢迎,其中PDF格式也成为了一种常用的电子书籍格式。无论是工作还是学习,我们都可能会遇到需要将图片转换成PDF格式的情况,例如保存一些资料证明、公文公告、学习资料等。在这篇文章中,我们将为大家介绍三种…...

数据结构exp1_2学生成绩排序
目录 数据结构exp1_2学生成绩排序 程序设计 程序分析 数据结构exp1_2学生成绩排序 【问题描述】 对某班学生成绩排序。从键盘依次输入某班学生的姓名和成绩(一个班级人数最多不超过50人)并保存,然后分别按学生成绩由高到低顺序输出学生姓名和成绩,成绩相同时,则按输…...

在DongshanPI-D1开箱使用分享与折腾记录实现MPU6050数据读取
前言 上一篇文章使用RT-Smart的IIC驱动OLED屏幕,进行基本的字符串显示,在使用过程中对RT-Smart有了一定熟悉,准备使用SPI驱动ST7789,但SPI接口没有引出,本次使用手上已有的传感器MPU6050进行使用。 过程 本次直接开始添加离线包…...

Nature子刊 定制饮食去除半胱氨酸和蛋氨酸可诱导细胞自毁进而治疗脑瘤?
恶性胶质瘤是成人最常见的脑部肿瘤。恶性胶质瘤的致死率为100%,无法治愈,是一种极度的恶性肿瘤。如此糟糕的预后促使研究者及神经外科医生不断学习研究肿瘤生物学,期望创造更好的疗法。神经外科助理教授Dominique Higgins博士从事肿瘤生物学的…...

抛弃 TCP 和 QUIC 的 HTTP
下班路上发了一则朋友圈: 周四听了斯坦福老教授 John Ousterhout 关于 Homa 的分享,基本重复了此前那篇 It’s Time To Rep… 的格调,花了一多半时间喷 TCP… Ousterhout 关于 Homa 和 TCP 之间的论争和论证,诸多反复回执&…...

未来公寓智能化设计平台项目(下)
创业场景通过在社区入口附近建设共享办公室,带动海慧园和众汽佳苑创业氛围,也让社区出了居住以外有其它功能,并且结合教育、邻里模块让社区更有活力。住户可通过app查看共享空间的使用情况,以及可以远程控制各种设备。 顺应未来生活与就业、创业融合新趋势,构建“大众创新…...

常见分布式消息队列综合对比
本文将从,Kafka、RabbitMQ、ZeroMQ、RocketMQ、ActiveMQ 17 个方面综合对比作为消息队列使用时的差异。 1. 资料文档 Kafka:中,有 kafka 作者自己写的书,网上资料也有一些。 rabbitmq:多,有一些不错的书…...

怎么邀请主流媒体到现场报道
传媒如春雨,润物细无声,大家好 主流媒体通常是指央媒,报纸杂志,电视台,地方重点媒体等,采访形式包括现场取材报道,媒体专访,群访等。通常主流媒体对选题要求较严格,因此在…...

2023年最强手机远程控制横测:ToDesk、向日葵、Airdroid三款APP免Root版本
前言 随着远程办公和远程协作的日益普及,跨设备、系统互通的远程控制软件已经成为职场人士不可或缺的工具之一。在国内,向日葵和ToDesk是最著名的远程控制软件;而在国外,则有微软远程桌面、AirDroid、TeamViewer、AnyDesk、Parse…...