当前位置: 首页 > news >正文

Web day09 会话技术 JWT令牌 Filter Interceptor

目录

会话技术:

1.Cookie:

2.Session:

3.令牌技术:

JWT令牌:

生成JWT令牌:

校验JWT令牌(解析生成的令牌)

登陆时下发令牌:

过滤器Filter:

拦截器Interceptor:

1). 自定义拦截器

2).注册配置拦截器

当Filter和Intercepter都存在时的执行逻辑:


会话技术:

会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。

由于HTTP是无状态协议,在后面请求中怎么拿到前一次请求生成的数据 就需要在一次会话的多次请求之间进行数据共享

1.Cookie:

Cookie(客户端会话跟踪技术):数据存储在客户端浏览器当中

比如第一次请求了登录接口,登录接口执行完成之后,我们就可以设置一个cookie,在 cookie 当中我们就可以来存储用户相关的一些数据信息。比如我可以在 cookie 当中来存储当前登录用户的用户名,用户的ID。

服务器端在给客户端在响应数据的时候,会自动的将 cookie 响应给浏览器,浏览器接收到响应回来的 cookie 之后,会自动的将 cookie 的值存储在浏览器本地。接下来在后续的每一次请求当中,都会将浏览器本地所存储的 cookie 自动地携带到服务端。

  • 在一次开启会话时 浏览器接收到响应回来的数据之后,会 自动 的将 cookie 存储在浏览器本地。

  • 在后续的请求当中,浏览器会 自动 的将 cookie 携带到服务器端。

@Slf4j
@RestController
public class SessionController {//设置Cookie@GetMapping("/c1")public Result cookie1(HttpServletResponse response){response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookiereturn Result.success();}//获取Cookie@GetMapping("/c2")public Result cookie2(HttpServletRequest request){Cookie[] cookies = request.getCookies();for (Cookie cookie : cookies) {if(cookie.getName().equals("login_username")){System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie}}return Result.success();}
}    

用cookie 配合拦截器 可以判断 用户是否已经登录  从而判断是否可以放行 

cookie的缺点:

  • 缺点:

    • 移动端APP(Android、IOS)中无法使用Cookie

    • 不安全,用户可以自己禁用Cookie

    • Cookie不能跨域  现在大多为集群开发 前后端系统不在一个服务器则无法使用Cookie

     区分跨域的维度(三个维度有任何一个维度不同,那就是跨域操作):

  • 协议

  • IP/协议

  • 端口

2.Session:

前面介绍的时候,我们提到Session,它是服务器端会话跟踪技术,所以它是存储在服务器端的。而 Session 的底层其实就是基于我们刚才所介绍的 Cookie 来实现的。

如果我们现在要基于 Session 来进行会话跟踪,浏览器在第一次请求服务器的时候,我们就可以直接在服务器当中来获取到会话对象Session。如果是第一次请求Session ,会话对象是不存在的,这个时候服务器会自动的创建一个会话对象Session 。而每一个会话对象Session ,它ID我们称之为 Session 的ID。

接下来,服务器端在给浏览器响应数据的时候,它会将 Session 的 ID 通过 Cookie 响应给浏览器。其实在响应头当中增加了一个 Set-Cookie 响应头。这个 Set-Cookie 响应头对应的值是不是cookie? cookie 的名字是固定的 JSESSIONID 代表的服务器端会话对象 Session 的 ID。浏览器会自动识别这个响应头,然后自动将Cookie存储在浏览器本地。

接下来,在后续的每次请求时,都会将Cookie的值在Cookie请求头中,携带到服务端,那服务端呢,接收到Cookie之后,会自动的根据JSESSIONID的值,找到对应的会话对象Session

  • 优点:Session是存储在服务端的,安全

  • Cookie存储在服务器中

  • 缺点:

    • 服务器集群环境下无法直接使用Session

    • 移动端APP(Android、IOS)中无法使用Cookie

    • 用户可以自己禁用Cookie

    • Cookie不能跨域

 @GetMapping("/s1")public Result session1(HttpSession session){session.setAttribute("loginUser", "tom"); //往session中存储数据return Result.Success("设置session成功");}@GetMapping("/s2")public Result session2(HttpServletRequest request){HttpSession session = request.getSession();Object loginUser = session.getAttribute("loginUser"); //从session中获取数据return Result.Success(loginUser);}

3.令牌技术:

令牌就是一个 字符串

如果通过令牌技术来跟踪会话,我们就可以在浏览器发起请求。在请求登录接口的时候,如果登录成功,我就可以生成一个令牌,令牌就是用户的合法身份凭证。接下来我在响应数据的时候,我就可以直接将令牌响应给前端。

接下来我们在前端程序当中接收到令牌之后,就需要将这个令牌存储起来。这个存储可以存储在 cookie 当中,也可以存储在其他的存储空间(比如:localStorage)当中。

接下来,在后续的每一次请求当中,都需要将令牌携带到服务端。携带到服务端之后,接下来我们就需要来校验令牌的有效性。如果令牌是有效的,就说明用户已经执行了登录操作,如果令牌是无效的,就说明用户之前并未执行登录操作。

此时,如果是在同一次会话的多次请求之间,我们想共享数据,我们就可以将共享的数据存储在令牌当中就可以了。

优点:

  • 支持PC端、移动端

  • 解决集群环境下的认证问题

  • 减轻服务器的存储压力(无需在服务器端存储)

注意: token会存储在浏览器本地数据库中 再下一次请求的请求头中 会有 Token:存储 令牌字符串   所以接受到请求头 以后 可以使用 getHeader("token") 获取token值 

JWT令牌最典型的应用场景就是登录认证:

  1. 在浏览器发起请求来执行登录操作,此时会访问登录的接口,如果登录成功之后,我们需要生成一个jwt令牌,将生成的 jwt令牌返回给前端。

  2. 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服务端。

  3. 服务端统一拦截请求之后,先来判断一下这次请求有没有把令牌带过来,如果没有带过来,直接拒绝访问,如果带过来了,还要校验一下令牌是否是有效。如果有效,就直接放行进行请求的处理。

JWT令牌:

  • JWT全称 JSON Web Token (官网:https://jwt.io/),定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。

    • 简洁:是指jwt就是一个简单的字符串。可以在请求参数或者是请求头当中直接传递。

    • 自包含:指的是jwt令牌,看似是一个随机的字符串,但是我们是可以根据自身的需求在jwt令牌中存储自定义的数据内容。如:可以直接在jwt令牌中存储用户的相关信息。

    • 简单来讲,jwt就是将原始的json数据格式进行了安全的封装,这样就可以直接基于jwt在通信双方安全的进行信息传输了。

JWT的组成: (JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)

  • 第一部分:Header(头), 记录令牌类型、签名算法等。 例如:{"alg":"HS256","type":"JWT"}

  • 第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:{"id":"1","username":"Tom"}

注意: 有效载荷中的数据 要以 键值 json的格式存储

  • 第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来。

签名的目的就是为了防jwt令牌被篡改,而正是因为

jwt令牌最后一个部分数字签名的存在,所以整个jwt 令牌是非常安全可靠的。一旦jwt令牌当中任何一个部分、任何一个字符被篡改了,整个令牌在校验的时候都会失败,所以它是非常安全可靠的

生成JWT令牌:

1) 导入JWT依赖:

<!-- JWT依赖-->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>

2). 生成JWT代码实现:

@Test
public void testGenJwt() {Map<String, Object> claims = new HashMap<>();claims.put("id", 10);claims.put("username", "itheima");String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256, "aXRjYXN0").addClaims(claims).setExpiration(new Date(System.currentTimeMillis() + 12 * 3600 * 1000)).compact();System.out.println(jwt);
}

aXRjYXN0 为 自己定义的 密码 

claims 为Payload(有效载荷),携带一些自定义信息、默认信息 claims要以json(map集合)方式传递

SignatureAlgorithm.HS256 为指定的签名算法

校验JWT令牌(解析生成的令牌)

3). 实现了JWT令牌的生成,下面我们接着使用Java代码来校验JWT令牌(解析生成的令牌):

@Test
public void testParseJwt() {Claims claims = Jwts.parser().setSigningKey("aXRjYXN0").parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MTAsInVzZXJuYW1lIjoiaXRoZWltYSIsImV4cCI6MTcwMTkwOTAxNX0.N-MD6DmoeIIY5lB5z73UFLN9u7veppx1K5_N_jS9Yko").getBody();System.out.println(claims);
}

aXRjYXN0 为自己定义的密码

登陆时下发令牌:

首先现在util 包下创建 TokenUtil 工具类 此类为 根据 传入的 有效载荷数据信息  生成 token 令牌 或者 根据令牌 解析 令牌中携带的数据

@Component
public class TokenUtil {@Value("${jwt.secret}")private String jwtSecret;@Value("${jwt.timeout}")private long jwtTimeout;public String generateToken(Map<String, Object> claims) {String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, jwtSecret).setExpiration(new Date(System.currentTimeMillis() + jwtTimeout * 1000 * 60)).compact();return token;}public Map<String, Object> parseJwtToken(String jwt) {Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(jwt).getBody();return claims;}
}

 把工具类加入 @Component 加入IOC容器管理是为了@Value 可以从yml文件中动态注入 密码值和时间

完善 EmpServiceImpl中的 login 方法逻辑, 登录成功,生成JWT令牌并返回

查到用户时返回令牌 在响应体中 前端会操作浏览器 数据库 保存令牌 

public LoginInfo login(Emp emp) {Emp loginEmp = empMapper.getUsernameAndPassword(emp);if (loginEmp != null) {Map<String, Object> stringObjectHashMap = new HashMap<>();stringObjectHashMap.put("id", loginEmp.getId());stringObjectHashMap.put("username", loginEmp.getUsername());String s = tokenUtil.generateToken(stringObjectHashMap);return new LoginInfo(loginEmp.getId(), loginEmp.getUsername(), loginEmp.getName(), s);} elsereturn null;}

LoginController层中:

@RestController
@RequestMapping("/login")
public class LoinController {@Autowiredprivate EmpService empService;@PostMappingpublic Result login(@RequestBody Emp emp) {LoginInfo loginInfo = empService.login(emp);if (loginInfo !=null){return Result.Success(loginInfo);}elsereturn new Result(0, "用户名或密码错误", null);}
}

过滤器Filter:

  • Filter表示过滤器,是 JavaWeb三大组件(Servlet、Filter、Listener)之一。

注意Filter 并不属于 spring框架 所以 过滤器的执行优先级 会大于拦截器

过滤器的使用步骤:

  • 第1步,定义过滤器 :1.定义一个类,实现 Filter 接口,并重写其所有方法。

  • 第2步,配置过滤器:Filter类上加 @WebFilter 注解,配置拦截资源的路径。引导类上加 @ServletComponentScan 开启Servlet组件支持。

1.定义过滤器:

public class DemoFilter implements Filter {//初始化方法, web服务器启动, 创建Filter实例时调用, 只调用一次public void init(FilterConfig filterConfig) throws ServletException {System.out.println("init ...");}//拦截到请求时,调用该方法,可以调用多次public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {System.out.println("拦截到了请求...");}//销毁方法, web服务器关闭时调用, 只调用一次public void destroy() {System.out.println("destroy ... ");}
}

在放行后访问完 web 资源之后还会回到过滤器当中,回到过滤器之后如有需求还可以执行放行之后的逻辑,放行之后的逻辑我们写在doFilter()这行代码之后。


@Component
@WebFilter("/*")
public class TokenFilter implements Filter {@Autowiredprivate TokenUtil tokenUtil;public static int a = 1;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {a++;System.out.println(a);System.out.println("过滤器初始化");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;String requestURI = request.getRequestURI();if (requestURI.equals("/login")) {filterChain.doFilter(servletRequest, servletResponse);return;}String token = request.getHeader("token");if (token == null) {System.out.println("token为空asdfsadfs");response.setStatus(401);return;}try {Map<String, Object> map = tokenUtil.parseJwtToken(token);System.out.println(map.get("username") + "登录成功!!!!!!!!!");filterChain.doFilter(servletRequest, servletResponse);} catch (Exception e) {System.out.println("token错误     " + e);response.setStatus(401);return;}}
}

filterChain.doFilter(servletRequest, servletResponse); 为放行方法

  • init方法:过滤器的初始化方法。在web服务器启动的时候会自动的创建Filter过滤器对象,在创建过滤器对象的时候会自动调用init初始化方法,这个方法只会被调用一次。

  • doFilter方法:这个方法是在每一次拦截到请求之后都会被调用,所以这个方法是会被调用多次的,每拦截到一次请求就会调用一次doFilter()方法。

  • destroy方法: 是销毁的方法。当我们关闭服务器的时候,它会自动的调用销毁方法destroy,而这个销毁方法也只会被调用一次。

拦截器Interceptor:

  • 是一种动态拦截方法调用的机制,类似于过滤器。

  • 拦截器是Spring框架中提供的,用来动态拦截控制器方法的执行。

  • 拦截器的作用:拦截请求,在指定方法调用前后,根据业务需要执行预先设定的代码。

拦截器的使用步骤和过滤器类似,也分为两步:

  1. 定义拦截器 实现 HandlerInterceptor 接口 重写  preHandle方法 

  2. 注册配置拦截器

1). 自定义拦截器

需要单独开一个LoginInterceptor 包来 存储 拦截器

因为配置类需要 拦截器对象 所以需要加上Component交给IOC容器管理

@Component
public class LoginInterceptor implements HandlerInterceptor {@AutowiredTokenUtil tokenUtil;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String requestURI = request.getRequestURI();String token = request.getHeader("token");if (token == null){System.out.println("token为空====> Intercepter拦截"+requestURI);response.setStatus(401);return false;}try {Map<String, Object> stringObjectMap = tokenUtil.parseJwtToken(token);System.out.println(stringObjectMap.get("username") + "登录成功!!!!!!!!!");return true;} catch (Exception e) {response.setStatus(401);return false;}}
}
  • preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行

  • postHandle方法:目标资源方法执行后执行

  • afterCompletion方法:视图渲染完毕后执行,最后执行

2).注册配置拦截器

先单独创建conf包 防止 配置类对象 

需要实现WebMvcConfigurer接口 并 加@Configuration注解

@Configuration
public class WebConfig implements WebMvcConfigurer {//拦截器对象@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册拦截器对象registry.addInterceptor(loginInterceptor)//拦截所有请求.addPathPatterns("/**")//放行请求.excludePathPatterns("/login").excludePathPatterns("/*.html");}
}

.addPathPatterns("/**") 为设置拦截路径

注意和filter规则不同

.excludePathPatterns("/login")为不拦截哪一uri路径

Filter/Intercepter 区别:

  • 接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口。

当Filter和Intercepter都存在时的执行逻辑:

  • 当我们打开浏览器来访问部署在web服务器当中的web应用时,此时我们所定义的过滤器会拦截到这次请求。拦截到这次请求之后,它会先执行放行前的逻辑,然后再执行放行操作。而由于我们当前是基于springboot开发的,所以放行之后是进入到了spring的环境当中,也就是要来访问我们所定义的controller当中的接口方法。

  • Tomcat并不识别所编写的Controller程序,但是它识别Servlet程序,所以在Spring的Web环境中提供了一个非常核心的Servlet:DispatcherServlet(前端控制器),所有请求都会先进行到DispatcherServlet,再将请求转给Controller。

  • 当我们定义了拦截器后,会在执行Controller的方法之前,请求被拦截器拦截住。执行preHandle()方法,这个方法执行完成后需要返回一个布尔类型的值,如果返回true,就表示放行本次操作,才会继续访问controller中的方法;如果返回false,则不会放行(controller中的方法也不会执行)。

  • 在controller当中的方法执行完毕之后,再回过来执行postHandle()这个方法以及afterCompletion() 方法,然后再返回给DispatcherServlet,最终再来执行过滤器当中放行后的这一部分逻辑的逻辑。执行完毕之后,最终给浏览器响应数据。

相关文章:

Web day09 会话技术 JWT令牌 Filter Interceptor

目录 会话技术&#xff1a; 1.Cookie&#xff1a; 2.Session&#xff1a; 3.令牌技术&#xff1a; JWT令牌&#xff1a; 生成JWT令牌&#xff1a; 校验JWT令牌&#xff08;解析生成的令牌&#xff09; 登陆时下发令牌&#xff1a; 过滤器Filter&#xff1a; 拦截器Inte…...

OpenCV相机标定与3D重建(14)用于组合两个旋转和平移(R|T)变换函数composeRT()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::composeRT 是 OpenCV 库中的一个函数&#xff0c;用于组合两个旋转和平移&#xff08;R|T&#xff09;变换。这个函数可以将两个连续的刚体变…...

leetcode33.搜索旋转排序数组

整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], ..., nums[n-1], nums[0], nums[1], ..…...

TMS Software:TMS BIZ产品——TMS XData

TMS XData 用于多层REST/JSON HTTP/HTTPS应用服务器开发和ORM远程处理的Delphi框架。 TMS扩展数据可同时用于以下框架&#xff1a; VCLWEBFMX TMS XData可同时用于以下操作系统/浏览器&#xff1a; TMS XData可同时用于以下IDE&#xff1a; 功能概述 基于REST/JSON架构风格的…...

leecode中的面试100题

isalnum函数用于检查一个字符是否为字母或数字。它的参数是一个int类型 isupper() 是大写 islower() 是小写 toupper() 变成大写 tolower() 变成小写 do while 首先不管怎么 先执行do一次 然后执行完了之后 在判断while如果符合while里面就继续执行do vector容器中insert…...

不同类型的集成技术——Bagging、Boosting、Stacking、Voting、Blending简述

目录 一、说明 二、堆叠 2.1 堆叠的工作原理&#xff1a; 2.2 例子&#xff1a; 2.3 堆叠的优点&#xff1a; 三、投票&#xff08;简单投票&#xff09; 3.1 例子&#xff1a; 3.2 投票的优点&#xff1a; 四、装袋和投票之间的区别 五、混合 6.1 混合的主要特征&#xff1a; …...

【从零开始入门unity游戏开发之——C#篇01】理论开篇

文章目录 前言前置条件什么是编程&#xff1f;什么是代码&#xff1f;什么是编程语言&#xff1f;常见的编程语言什么是C#&#xff1f;学习Unity为什么要先学习C#&#xff1f;选择适合自己的IDE集成开发环境VSCode安装和环境配置VSCode调试模式专栏推荐完结 前言 这个系列我想…...

TCP的“可靠性”(上)

目录 TCP的“可靠性”&#xff08;上&#xff09;确认应答&#xff08;可靠性传输的基础&#xff09;超时重传连接管理&#xff08;三次握手&#xff0c;四次挥手&#xff09; TCP的“可靠性”&#xff08;上&#xff09; 想必大家都或多或少的听说过TCP的特性&#xff1a;有连…...

Windows平台Unity3D下如何低延迟低资源占用播放RTMP或RTSP流?

技术探讨 自2017年我们发布跨平台的低延迟Unity下的RTSP|RTMP直播播放器后&#xff0c;Unity下的直播体验有了质的提升&#xff0c;特别是RTMP&#xff0c;从大家认知里面的几秒钟&#xff0c;直接缩减到100-300ms&#xff0c;满足了绝大多数场景下低延迟的技术诉求。今天就Un…...

burp的编解码,日志,比较器

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…...

Vercel部署前端部署

Vercel 部署 今天要讲的是如何对别人向自己的开源仓库提的PR进行自动代码审核 1. 注册并登录Vercel 访问 Vercel官网点击右上角的"Sign Up"选择使用GitHub、GitLab、Bitbucket或邮箱注册完成注册流程并登录 2. 连接代码仓库 在Vercel仪表板,点击"New Proje…...

Jenkins相关的Api接口调用详解

Jenkins API是Jenkins持续集成和持续部署(CI/CD)平台提供的一组接口,允许外部程序通过HTTP请求与Jenkins进行交互。以下是对Jenkins API使用的简介: 一、Jenkins API的主要功能 作业管理:通过API,可以创建、配置、删除以及查询作业(Job)。构建触发:可以远程触发新的构…...

HBU深度学习实验15-循环神经网络(2)

LSTM的记忆能力实验 飞桨AI Studio星河社区-人工智能学习与实训社区 (baidu.com) 长短期记忆网络&#xff08;Long Short-Term Memory Network&#xff0c;LSTM&#xff09;是一种可以有效缓解长程依赖问题的循环神经网络&#xff0e;LSTM 的特点是引入了一个新的内部状态&am…...

洛谷P1364 医院设置(c嘎嘎)

题目链接&#xff1a;P1364 医院设置 - 洛谷 | 计算机科学教育新生态 题目难度&#xff1a;普及/提高 数据规模与约定&#xff1a; 对于 100%100% 的数据&#xff0c;保证 1≤n≤1001≤n≤100&#xff0c;0≤u,v≤n0≤u,v≤n&#xff0c;1≤w≤1051≤w≤105。 解题思路&…...

Java死锁问题如何解决?

大家好&#xff0c;我是锋哥。今天分享关于【Java死锁问题如何解决&#xff1f;】面试题。希望对大家有帮助&#xff1b; Java死锁问题如何解决&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Java中的死锁&#xff08;Deadlock&#xff09;是一种并发…...

go锁与chan的性能对比

锁的作用chan 的作用golang的数据并不是并发安全的为什么锁的性能更加优秀?如何选择? 锁的作用 解决并发安全问题,流程控制等 chan 的作用 线程通信(数据传输), 并发安全,流程控制 golang的数据并不是并发安全的 golang的变量并不是并发安全的锁与chan都可以解决并发安全…...

最小二乘法拟合出二阶响应面近似模型

背景&#xff1a;根据样本试验数据拟合出二阶响应面近似模型&#xff08;正交二次型&#xff09;&#xff0c;并使用决定系数R和调整的决定系数R_adj来判断二阶响应面模型的拟合精度。 1、样本数据&#xff08;来源&#xff1a;硕士论文《航空发动机用W形金属密封环密封性能分析…...

Scala的隐式转换

package hfdobject Test37 { //复习隐式转换//隐式转换&#xff1a;编译器 偷偷地&#xff0c;自动的帮我们把一种数据类型转换为另外一种类型//列如&#xff1a;int -->double//它有失败的时候&#xff08;double -->int),有成功的时候//当它转换失败的时候&#xff0c;…...

vue中父组件接收子组件的多个参数的方法:$emit或事件总线

方法一&#xff1a;使用 $emit 方法 原理 子组件通过 $emit 方法向父组件发送事件&#xff0c;同时可以传递多个参数&#xff0c;父组件通过事件监听来接收这些参数。 示例 子组件代码 <template><div><button click"sendData">发送数据</…...

网络安全法-网络安全支持与促进

第二章 网络安全支持与促进 第十五条 国家建立和完善网络安全标准体系。国务院标准化行政主管部门和国务院其他有关部门根据各自的职责&#xff0c;组织制定并适时修订有关网络安全管理以及网络产品、服务和运行安全的国家标准、行业标准。 国家支持企业、研究机构、高等学…...

prometheusgrafana实现监控告警

Prometheus负责集群数据的监控和采集&#xff0c;然后传递给grafana进行可视化&#xff0c;集成睿象云可实现监控报警&#xff0c;为了方便操作&#xff0c;可以通过iframe嵌套grafana到指定的页面。 文章目录 1.Grafana集成Prometheus2.iframe内嵌grafana3.监控告警 1.Grafana…...

php:完整部署Grid++Report到php项目,并实现模板打印

一、下载Grid++Report软件 路径:开发者安装包下载 - 锐浪报表工具 二、 安装软件 1、对下载的压缩包运行内部的exe文件 2、选择语言 3、 完成安装引导 下一步即可 4、接收许可协议 点击“我接受” 5、选择安装路径 “浏览”选择安装路径,点击"安装" 6、完成…...

【数据结构】基数排序的原理及实现

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在准备26考研 ✈️专栏&#xff1a;数据结构 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章…...

Unix/Linux 命令行重定向操作

2>/dev/null 是一个常见的 Unix/Linux 命令行重定向操作&#xff0c;用于将标准错误&#xff08;stderr&#xff09;输出重定向到 /dev/null&#xff0c;即丢弃错误信息而不显示。理解这个表达式需要了解几个概念&#xff1a;文件描述符、重定向和特殊文件 /dev/null。 ###…...

leetcode周赛-3379. 转换数组

给你一个整数数组 nums&#xff0c;它表示一个循环数组。请你遵循以下规则创建一个大小 相同 的新数组 result &#xff1a; 对于每个下标 i&#xff08;其中 0 < i < nums.length&#xff09;&#xff0c;独立执行以下操作&#xff1a; 如果 nums[i] > 0&#xff1…...

D89【python 接口自动化学习】- pytest基础用法

day89 pytest的setup&#xff0c;setdown详解 学习日期&#xff1a;20241205 学习目标&#xff1a;pytest基础用法 -- pytest的setup&#xff0c;setdown详解 学习笔记&#xff1a; setup、teardown详解 模块级 setup_module/teardown_module 开始于模块始末&#xff0c;生…...

【Appium】AttributeError: ‘NoneType‘ object has no attribute ‘to_capabilities‘

目录 1、报错内容 2、解决方案 &#xff08;1&#xff09;检查 &#xff08;2&#xff09;报错原因 &#xff08;3&#xff09;解决步骤 3、解决结果 1、报错内容 在PyCharm编写好脚本后&#xff0c;模拟器和appium也是连接成功的&#xff0c;但是运行脚本时报错&…...

【机器人】轨迹规划 之 spline 规划

在轨迹规划中&#xff0c;使用 spline &#xff08;通常是指通过样条曲线进行轨迹规划&#xff09;可以实现平滑、连续的路径。以下是使用样条&#xff08;如B样条、三次样条插值&#xff09;的具体方法和步骤&#xff0c;结合一个简单的例子说明&#xff1a; 示例场景&#xf…...

健康管理系统(Koa+Vue3)

系统界面(源码末尾获取) 系统技术 Vue3 Koa Nodejs Html Css Js ....... 系统介绍 系统比较简单,轻轻松松面对结业课堂作业.采用的是基于nodejs开发的Koa框架作为后端,采用Vue框架作为前端,完成快速开发和界面展示. 系统获取 啊啊啊宝/KoaVue3https://gitee.com/ah-ah-b…...

【MySQL 进阶之路】基础语法及优化技巧

MySQL DML 基础语法及优化技巧 一、DML&#xff08;数据操作语言&#xff09;概述 DML 是数据库操作语言的子集&#xff0c;用于数据的增、删、改、查四个基本操作。MySQL 中的 DML 操作通常是指以下四种基本操作&#xff1a; INSERT&#xff1a;插入数据SELECT&#xff1a;…...

2021 年“泰迪杯”数据分析技能赛B 题肥料登记数据分析

2021 年“泰迪杯”数据分析技能赛B 题肥料登记数据分析 完整代码请私聊 博主 一、背景 肥料是农业生产中一种重要的生产资料&#xff0c;其生产销售必须遵循《肥料登记管理办法》&#xff0c;依法在农业行政管理部门进行登记。各省、自治区、直辖市人民政府农业行政主管部门主…...

体验AI直播:感受科技的魅力

​ 在当今这个科技飞速发展的时代&#xff0c;各种创新技术层出不穷&#xff0c;不断刷新着我们的认知和体验。其中&#xff0c;无人直播作为一种新兴的直播形式&#xff0c;正以其独特的魅力吸引着人们的目光。当我们真正去体验无人直播时&#xff0c;才能更深刻地感受到科技…...

NLP-中文分词

中文分词 1、中文分词研究背景及意义 和大部分西方语言不同&#xff0c;书面汉语的词语之间没有明显的空格标记&#xff0c;句子是以字串的形式出现。因此对中文进行处理的第一步就是进行自动分词&#xff0c;即将字串转变成词串。 比如“中国建筑业呈现新格局”分词后的词串…...

oracle 架构详解

Oracle 数据库是一个复杂且强大的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;广泛应用于企业级应用中。了解 Oracle 的架构对于数据库管理员&#xff08;DBA&#xff09;、开发人员和架构师来说至关重要。以下是 Oracle 数据库架构的详细解析&#xff0c;涵…...

东方资产管理校招笔试测评题型题目深入解读

东方资管作为四大资产AMC公司之一&#xff0c;其薪资待遇还是不错的&#xff0c;现在为数不多还可以投递简历的金融央企。东方资产管理校招笔试一般在简历投递截止后的周末&#xff0c;总部和子公司、分公司需要分别做笔试。 东方资管笔试大概2h&#xff0c;线上双机位&#x…...

PDF处理的创新工具:福昕低代码平台尝鲜实现PDF2word功能

在当今数字化时代&#xff0c;PDF文件的处理和管理变得越来越重要。福昕低代码平台是新发布的一款创新的工具&#xff0c;旨在简化PDF处理和管理的流程。通过这个平台&#xff0c;用户可以通过简单的拖拽界面上的按钮&#xff0c;轻松完成对Cloud API的调用工作流&#xff0c;而…...

springboot系列--拦截器加载原理

一、拦截器加载原理 拦截器是在容器启动时&#xff0c;就创建并加载好&#xff0c;此时并未放入拦截器链中&#xff0c;只是放在一个拦截器集合当中&#xff0c;当一个请求进来之后&#xff0c;会通过匹配路径&#xff0c;查看是否有命中集合中的拦截器的拦截路径&#xff0c;如…...

当Nginx所在服务器的磁盘空间满了,会有什么影响及如何避免这种问题

大家好&#xff0c;我是G探险者&#xff01; 最近遇到一个问题是&#xff0c;nginx所在服务器磁盘满了&#xff0c;导致前端页面上的一个文件上传功能不好使了&#xff0c;搞得我排查半天&#xff0c;找不见原因&#xff0c;最后发现是nginx的磁盘满了导致&#xff0c;清理了里…...

光猫开DMZ教程

本教程以移动光猫未例&#xff0c;具体操作以实际光猫为准 1、登录移动光猫管理后台 打开浏览器&#xff0c;在浏览器地址栏输入移动光猫登录管理地址192.168.1.1或者tplogin.cn 按“回车键”打开登录页面&#xff0c;然后输入路由器管理密码登录。 移动光猫登录页面 超级密…...

WireShark速成

1.WireShark安装 官网&#xff1a; Wireshark Go Deep Kali Linux系统自带WireShark工具。 2.WireShark介绍 WireShark是一个网络包分析工具&#xff0c;该工具主要用于捕获网络数据包&#xff0c;并自动解析数据包&#xff0c;为用户显示数据包的详情信息&#xff0c;供…...

BFS入门

目录 定义二叉树层次遍历电梯问题倒可乐BFS基本思想算法 四方访问 定义 BFS 通常是指广度优先搜索&#xff08;Breadth - First Search&#xff09;&#xff0c;它是一种图形数据结构的遍历算法。从给定的起始顶点开始&#xff0c;首先访问起始顶点的所有邻接顶点&#xff0c;然…...

ElementUI:el-tabs 切换之前判断是否满足条件

<div class"table-card"><div class"card-steps-class"><el-tabsv-model"activeTabsIndex":before-leave"beforeHandleTabsClick"><el-tab-pane name"1" label"基础设置"><span slot&…...

mid360使用cartorapher进行3d建图导航

1. 添加urdf配置文件&#xff1a; 添加IMU配置关节点和laser关节点 <!-- imu livox --> <joint name"livox_frame_joint" type"fixed"> <parent link"base_link" /> <child link"livox_frame" /> <o…...

【CSS in Depth 2 精译_073】第 12 章 CSS 排版与间距概述 + 12.1 间距设置(中):对 CSS 行高的深入思考

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 12.1.1 使用 em 还是 px12.1.2 对行高的深入思考 ✔️12.1.3 行内元素的间距设置 文章目录 12.1.2 对行高的深入思考…...

JAVA设计模式-观察者模式

概述&#xff1a; 观察者模式通常由两个对象组成&#xff1a;观察者和被观察者。当被观察者状态发生改变时&#xff0c;它会通知所有的观察者对象&#xff0c;使他们能够及时做出响应&#xff0c;所以也被称作“发布-订阅模式”。 特点&#xff1a; 优点&#xff1a; 解耦且可…...

Java调用SSE流式接口,并流式返回给前端实现打字输出效果

目录 1.SSE概述 1.1 什么是是SSE2.2 与长链接(Long Polling)的区别 长链接(Long Polling)Server-Sent Events (SSE) 比较总结 2.通过okhttp调用SSE流式接口并流式返回给前端 环境要求使用okhttp相关依赖示例 3. 如果Spring Framework 低于5.0&#xff0c;可使用Servlet 3.0进行…...

倚光科技助力自由曲面设计与加工

近年来&#xff0c;自由曲面因其在光学、汽车、航空航天等领域的广泛应用&#xff0c;受到设计师和工程师的高度关注。自由曲面作为一种具有更高自由度的非球面透镜&#xff0c;能够在光学系统中实现更加精确的光线控制&#xff0c;优化像差校正&#xff0c;并且在满足功能需求…...

【推荐算法】推荐系统中的单目标精排模型

前言&#xff1a;推荐系统中模型发展较快&#xff0c;初学者【也就是笔者】很难对模型进行一个系统的学习。因此&#xff0c;这篇文章总结了王树森中的视频以及《深度学习推荐系统》中的单目标精排模型&#xff0c;绘制了一个单目标精排模型的思维导图来帮助初学者【笔者】更好…...

Android UI:ViewTree:源码分析:事件处理:显示事件

文章目录 概述测量:measure和onMeasure​​​​​​​ View.MeasureSpecViewViewGroupLinearLayoutRelativeLayout布局:layout和onLayout ViewViewGroupLinearLayoutRelativeLayout绘制:dispatchDraw、draw和onDraw ViewViewGroupLinearLayoutRelativeLayout总结概述 显示事…...

esp32 OTA学习笔记

csv分区表中ota-0和ota-1存放程序 不超过1600kb的程序可以ota&#xff08;可手动划分&#xff09; 分区表中有 ota0和ota1两个数据分区。 ota是指先下载固件到ota1然后下次从ota1启动&#xff0c;回滚就是回到ota0 启动。 关于固件&#xff1a; bin文件可以用arduino生成也可以…...