Web后端开发:登录认证案例

登录功能

需求分析

在这里插入图片描述
  在登录界面中,输入用户的用户名以及密码,然后点击 “登录” ,服务端判断用户输入的用户名和密码是否都正确。如果正确,则返回成功结果,前端跳转至系统首页面;否则报错,停留在登录界面。

接口文档

请求路径:/login
请求方式:POST
接口描述:该接口用于员工登录Tlias智能学习辅助系统,登录完毕后,系统下发JWT令牌。请求参数参数格式:application/json
请求数据样例:{"username": "jinyong","password": "123456"}响应数据参数格式:application/json
响应数据样例:{"code": 1,"msg": "success","data":"eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi6YeR5bq4IiwiaWQiOjEsInVzZXJuYW1lIjoiamlueW9uZyIsImV4cCI6MTY2MjIwNzA0OH0.KkUc_CXJZJ8Dd063eImx4H9Ojfrr6XMJ-yVzaWCVZCo"}

请求参数参数说明:
在这里插入图片描述
.
请求参数参数说明:
在这里插入图片描述

思路分析

在这里插入图片描述

  登录服务端的核心逻辑就是:接收前端请求传递的用户名和密码 ,然后再根据用户名和密码查询用户信息,如果用户信息存在,则说明用户输入的用户名和密码正确。如果查询到的用户不存在,则说明用户输入的用户名和密码错误。

功能开发

LoginController

@Slf4j
@RestController
public class LoginController {@Autowiredprivate EmpService empService;@PostMapping("/login")public Result login(@RequestBody Emp emp){log.info("员工登录:{}",emp);Emp e = empService.login(emp);return e != null ? Result.success():Result.error("用户名或密码错误");}
}

EmpService

// 用户登录
Emp login(Emp emp);

EmpServiceImpl

@Override
public Emp login(Emp emp) {//调用dao层功能:登录Emp loginEmp = empMapper.getByUsernameAndPassword(emp);//返回查询结果给Controllerreturn loginEmp;
}

EmpMapper

@Select("select id, username, password, name, gender, image,job, entrydate, dept_id, create_time, update_time " +"from empf  where username=#{username} and password =#{password}")
Emp getByUsernameAndPassword(Emp emp);

功能测试

在这里插入图片描述

登录校验

会话技术

  在web开发当中,会话指的是浏览器与服务器之间的一次连接。
  需要注意的是:会话和浏览器是关联的。
  会话跟踪:是一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。

会话跟踪技术有两种:Cookie(客户端会话跟踪技术),即数据存储在客户端浏览器当中Session(服务端会话跟踪技术),即数据存储在储在服务端

传统的会话跟踪技术,在现在的开发当中存在很多的问题。 为了解决这些问题,在现在开发中基本上都会采用第三种方案,通过令牌技术来进行会话跟踪。

JWT令牌

JWT介绍

  JWT全称:JSON Web Token,定义了一种简洁的、自包含的格式,用于在通信双方以 json 数据格式安全的传输信息。

JWT的组成: (JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)第一部分:Header(头), 记录令牌类型、签名算法等。 例如:{"alg":"HS256","type":"JWT"}第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:{"id":"1","username":"Tom"}第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来。

JWT令牌最典型的应用场景就是登录认证:
  1. 在浏览器发起登录请求,此时会访问登录接口,如果登录成功,则会生成一个jwt令牌,并将生成的 jwt令牌返回给前端。
  2. 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服务端。
  3. 服务端统一拦截请求之后,先判断请求有没有携带令牌,如果没有则直接拒绝访问;如果有,还需要校验一下令牌是否是有效,有效则直接放行进行请求的处理。

在JWT登录认证整个流程当中涉及到两步操作:1. 在登录成功之后,生成令牌。2. 每一次请求当中,要接收令牌并对令牌进行校验。

生成jwt令牌

  JWT的依赖

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

  生成JWT代码

@Test
public void genJwt(){Map<String,Object> claims = new HashMap<>();claims.put("id",1);claims.put("username","Tom");String jwt = Jwts.builder().setClaims(claims) //自定义内容(载荷).signWith(SignatureAlgorithm.HS256, "itheima") //签名算法.setExpiration(new Date(System.currentTimeMillis() + 24*3600*1000)) //有效期.compact();System.out.println(jwt);
}

校验jwt令牌

  解析生成的令牌

@Test
public void parseJwt(){Claims claims = Jwts.parser()//指定签名密钥(必须保证和生成令牌时使用相同的签名密钥).setSigningKey("itheima").parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjcyNzI5NzMwfQ.fHi0Ub8npbyt71UqLXDdLyipptLgxBUg_mSuGJtXtBk").getBody();System.out.println(claims);
}
在使用JWT令牌时需要注意:JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的。如果JWT令牌解析校验时报错,则说明JWT令牌被篡改或失效了,令牌非法。

登录下发令牌

通过JWT令牌技术来跟踪会话,主要是两步操作:1. 生成令牌2. 校验令牌	JWT令牌怎么返回给前端呢?主要看接口文档中关于登录接口的描述的响应数据:
响应数据参数格式:application/json
响应数据样例:{"code": 1,"msg": "success","data":"eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi6YeR5bq4IiwiaWQiOjEsInVzZXJuYW1lIjoiamlueW9uZyIsImV4cCI6MTY2MjIwNzA0OH0.KkUc_CXJZJ8Dd063eImx4H9Ojfrr6XMJ-yVzaWCVZCo"}

响应数据参数说明:
在这里插入图片描述

过滤器Filter

  怎么判断统一拦截到所有的请求校验令牌的有效性呢?有两种解决方案:1. Filter过滤器、2. Interceptor拦截器

  Filter过滤器,是 JavaWeb三大组件(Servlet、Filter、Listener)之一。过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。使用了过滤器之后,要想访问web服务器上的资源,必须先经过滤器,过滤器处理完毕之后,才可以访问对应的资源。过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。

Filter快速入门

过滤器的基本使用操作:第1步,定义过滤器 :1.定义一个类,实现 Filter 接口,并重写其所有方法。第2步,配置过滤器:Filter类上加 @WebFilter 注解,配置拦截资源的路径。引导类上加@ServletComponentScan 开启Servlet组件支持。

定义过滤器

//定义一个类,实现一个标准的Filter过滤器的接口
public class DemoFilter implements Filter {@Override //初始化方法, 只调用一次public void init(FilterConfig filterConfig) throwsServletException {System.out.println("init 初始化方法执行了");}@Override //拦截到请求之后调用, 调用多次public void doFilter(ServletRequest request, ServletResponseresponse, FilterChain chain) throws IOException, ServletException {System.out.println("Demo 拦截到了请求...放行前逻辑");//放行chain.doFilter(request,response);}@Override //销毁方法, 只调用一次public void destroy() {System.out.println("destroy 销毁方法执行了");}
}

Filter的配置

@WebFilter(urlPatterns = "/*") //配置过滤器要拦截的请求路径( /* 表示拦截浏览器的所有请求 )
public class DemoFilter implements Filter {@Override //初始化方法, 只调用一次public void init(FilterConfig filterConfig) throwsServletException {System.out.println("init 初始化方法执行了");}@Override //拦截到请求之后调用, 调用多次public void doFilter(ServletRequest request, ServletResponseresponse, FilterChain chain) throws IOException, ServletException {System.out.println("Demo 拦截到了请求...放行前逻辑");//放行chain.doFilter(request,response);}@Override //销毁方法, 只调用一次public void destroy() {System.out.println("destroy 销毁方法执行了");}
}

  在Filter类上面加了@WebFilter注解之后,还需要在启动类上面加上一个注解@ServletComponentScan,通过这个@ServletComponentScan注解来开启SpringBoot项目对于Servlet组件的支持。

@ServletComponentScan
@SpringBootApplication
public class SpringbootWebExampleApplication {public static void main(String[] args) {SpringApplication.run(SpringbootWebExampleApplication.class, args);}}

Filter详解

过滤器的执行流程

在这里插入图片描述
  过滤器拦截到请求后,如果要继续访问后面的web资源,则需要执行放行操作,即调用 FilterChain对象当中的doFilter()方法。在放行后访问完 web 资源之后还会回到过滤器当中,回到过滤器之后如有需求还可以执行放行之后的逻辑,放行之后的逻辑我们写在doFilter()这行代码之后。

@WebFilter(urlPatterns = "/*") //配置过滤器要拦截的请求路径( /* 表示拦截浏览器的所有请求 )
public class DemoFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);System.out.println("init 初始化方法执行了");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("Demo 拦截到了请求...放行前逻辑");//放行filterChain.doFilter(servletRequest, servletResponse);System.out.println("DemoFilter放行后逻辑.....");}@Overridepublic void destroy() {Filter.super.destroy();}
}

在这里插入图片描述

过滤器的拦截路径配置

  Filter可以根据需求,配置不同的拦截资源路径:

拦截路径urlPatterns值含义
拦截具体路径/login只有访问 /login 路径时,才会被拦截
目录拦截/emps/*访问/emps下的所有资源,都会被拦截
拦截所有/*访问所有资源,都会被拦截
过滤器链

  过滤器链指的是在一个web应用程序当中,可以配置多个过滤器,多个过滤器就形成了一个过滤器链。
在这里插入图片描述
  如上图,定义了两个过滤器,这两个过滤器就形成了一个过滤器链。而这个链上的过滤器在执行的时候会一个一个的执行,会先执行第一个Filter,放行之后再来执行第二个Filter。要执行到最后一个过滤器放行之后,才会访问对应的web资源。如上图,先要执行过滤器2放行之后的逻辑,再来执行过滤器1放行之后的逻辑,最后再给浏览器响应数据。

Filter-登录校验

需求分析

要完成登录校验,主要是利用Filter过滤器实现,而Filter过滤器的流程步骤:
在这里插入图片描述

接口文档
请求路径:/login
请求方式:POST
接口描述:该接口用于员工登录Tlias智能学习辅助系统,登录完毕后,系统下发JWT令牌。请求参数参数格式:application/json
请求数据样例:{"username": "jinyong","password": "123456"}响应数据参数格式:application/json
响应数据样例:{"code": 1,"msg": "success","data":"eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi6YeR5bq4IiwiaWQiOjEsInVzZXJuYW1lIjoiamlueW9uZyIsImV4cCI6MTY2MjIwNzA0OH0.KkUc_CXJZJ8Dd063eImx4H9Ojfrr6XMJ-yVzaWCVZCo"}

请求参数参数说明:
在这里插入图片描述

响应数据参数说明:
在这里插入图片描述

思路分析
基于上面业务流程,可以分析出具体的操作步骤:1. 获取请求url2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行3. 获取请求头中的令牌(token)4. 判断令牌是否存在,如果不存在,返回错误结果(未登录)5. 解析token,如果解析失败,返回错误结果(未登录)6. 放行
功能开发

登录校验过滤器:LoginCheckFilter

@Slf4j
@WebFilter(urlPatterns = "/*") //拦截所有请求
public class LoginCheckFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest,ServletResponse servletResponse, FilterChain chain) throwsIOException, ServletException {//前置:强制转换为http协议的请求对象、响应对象 (转换原因:要使用子类中特有方法)HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse)servletResponse;//1.获取请求urlString url = request.getRequestURL().toString();log.info("请求路径:{}", url); //请求路径:http://localhost:8080/login//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行if(url.contains("/login")){chain.doFilter(request, response);//放行请求return;//结束当前方法的执行}//3.获取请求头中的令牌(token)String token = request.getHeader("token");log.info("从请求头中获取的令牌:{}",token);//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)if(!StringUtils.hasLength(token)){log.info("Token不存在");Result responseResult = Result.error("NOT_LOGIN");//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)String json = JSONObject.toJSONString(responseResult);response.setContentType("application/json;charset=utf-8");//响应response.getWriter().write(json);return;}//5.解析token,如果解析失败,返回错误结果(未登录)try {JwtUtils.parseJWT(token);}catch (Exception e){log.info("令牌解析失败!");Result responseResult = Result.error("NOT_LOGIN");//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)String json = JSONObject.toJSONString(responseResult);response.setContentType("application/json;charset=utf-8");//响应response.getWriter().write(json);return;}//6.放行chain.doFilter(request, response);}
}

在上述过滤器的功能实现中使用到了一个第三方json处理的工具包fastjson。我们要想使用,需要引入如下依赖:

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version>
</dependency>

拦截器Interceptor

  拦截器是一种动态拦截方法调用的机制,类似于过滤器。拦截器是Spring框架中提供的,用来动态拦截控制器方法的执行。
  拦截器的作用:拦截请求,在指定方法调用前后,根据业务需要执行预先设定的代码。

Interceptor快速入门

拦截器的使用步骤和过滤器类似,也分为两步:1. 定义拦截器2. 注册配置拦截器

自定义拦截器: 实现HandlerInterceptor接口,并重写其所有方法

//自定义拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {//目标资源方法执行前执行。 返回true:放行 ;返回false:不放行@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle .... ");return true; //true表示放行}//目标资源方法执行后执行@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle ... ");}//视图渲染完毕后执行,最后执行@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion .... ");}
}

注册配置拦截器: 实现WebMvcConfigurer接口,并重写addInterceptors方法

@Configuration
public class WebConfig implements WebMvcConfigurer {//自定义的拦截器对象@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器对象registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**		");//设置拦截器拦截的请求路径( /** 表示拦截所有请求)}
}

Interceptor详解

拦截路径

  通过 addPathPatterns(“要拦截路径”) 方法,可以指定要拦截的资源,还可以调用 excludePathPatterns(“不拦截路径”) 方法,指定不拦截的资源。

@Configuration
public class WebConfig implements WebMvcConfigurer {//拦截器对象@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器对象registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**")//设置拦截器拦截的请求路径( /**表示拦截所有请求).excludePathPatterns("/login");//设置不拦截的请求路径}
}

  常见拦截路径设置:

在这里插入图片描述

执行流程

在这里插入图片描述

  当浏览器发起访问web应用时,此时定义的过滤器会拦截到请求。拦截到这次请求之后,先执行放行前的逻辑,然后再执行放行操作。而由于当前是基于springboot开发的,所以放行之后是进入到了spring的环境当中,也就是要来访问定义的controller当中的接口方法。
  Tomcat并不识别所编写的Controller程序,但是它识别Servlet程序,所以在Spring的Web环境中提供了一个非常核心的Servlet:DispatcherServlet(前端控制器),所有请求都会先进行到DispatcherServlet,再将请求转给Controller。
  当我们定义了拦截器后,会在执行Controller的方法之前,请求被拦截器拦截住。执行preHandle() 方法,这个方法执行完成后需要返回一个布尔类型的值,如果返回true,就表示放行本次操作,才会继续访问controller中的方法;如果返回false,则不会放行(controller中的方法也不会执行)。
  在controller当中的方法执行完毕之后,再回过来执行 postHandle() 这个方法以及afterCompletion() 方法,然后再返回给DispatcherServlet,最终再来执行过滤器当中放行后的这一部分逻辑的逻辑。执行完毕之后,最终给浏览器响应数据。

过滤器和拦截器的区别
过滤器和拦截器之间的区别主要是两点:接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口。拦截范围不同:过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源。

Interceptor-登录校验

  和登录校验Filter过滤器当中的逻辑是完全一致的,只需要把原来的过滤器换成拦截器interceptor就可以了。

登录校验拦截器

@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {//前置方式@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle .... ");//1.获取请求urlString url = request.getRequestURL().toString();log.info("请求的ur1:{}",url);//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行if (url.contains("login")){log.info("登录操作,放行……");return true;}//3.获取请求头中的令牌(token)String token = request.getHeader("token");log.info("从请求头中获取的令牌:{}",token);//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)if(!StringUtils.hasLength(token)){log.info("Token不存在");//创建响应结果对象Result responseResult = Result.error("NOT_LOGIN");//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)String json = JSONObject.toJSONString(responseResult);//设置响应头(告知浏览器:响应的数据类型为json、响应的数据编码表为utf-8)response.setContentType("application/json;charset=utf-8");//响应response.getWriter().write(json);return false;//不放行}//5.解析token,如果解析失败,返回错误结果(未登录)try {JwtUtils.parseJWT(token);}catch (Exception e){log.info("令牌解析失败!");//创建响应结果对象Result responseResult = Result.error("NOT_LOGIN");//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)String json = JSONObject.toJSONString(responseResult);//设置响应头response.setContentType("application/json;charset=utf-8");//响应response.getWriter().write(json);return false;}//6.放行return true;}
}

注册配置拦截器


@Configuration
public class WebConfig implements WebMvcConfigurer {//自定义的拦截器对象@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器对象registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");}
}

异常处理

  出现异常之后,最终服务端给前端响应回来的数据是一个JSON格式的数据,但这种JSON格式的数据不是开发规范中所提到的统一响应结果Result,由于返回的数据不符合开发规范,所以前端并不能解析出响应的JSON数据。

在三层构架项目中,出现了异常,该如何处理?方案一:在所有Controller的所有方法中进行try…catch处理缺点:代码臃肿(不推荐)方案二:全局异常处理器好处:简单、优雅(推荐)

在这里插入图片描述

全局异常处理器

  我们该怎么样定义全局异常处理器?定义全局异常处理器非常简单,就是定义一个类,在类上加上一个注解@RestControllerAdvice,加上这个注解就代表我们定义了一个全局异常处理器。在全局异常处理器当中,需要定义一个方法来捕获异常,在这个方法上需要加上注解@ExceptionHandler。通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常。


/*全局异常处理*/
@RestControllerAdvice
public class GlobalExceptionHandler {//处理异常@ExceptionHandler(Exception.class) //捕获所有异常public Result ex(Exception e){e.printStackTrace();//打印堆栈中的异常信息//捕获到异常之后,响应一个标准的Resultreturn Result.error("对不起,操作失败,请联系管理员");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/254475.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Web】vulhub Shiro-550反序列化漏洞复现学习笔记

目录 Shiro简介 复现流程 工具一把梭 半脚本半手动 原理分析 反序列化入口 常见的key 登录过程 验证过程 利用原理 Shiro简介 Apache Shiro 是一个强大且易于使用的 Java 安全框架&#xff0c;用于身份验证、授权、加密和会话管理等安全功能。Shiro 的设计目标是简单…

2.0 Zookeeper 安装配置

Linux 安装 zookeeper 下载地址为: Apache ZooKeeper。 选择一稳定版本&#xff0c;本教程使用的 release 版本为3.4.14&#xff0c;下载并安装。 打开网址 https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz&#xff0c;看到如下界…

通过平扫CT实现胰腺癌早筛(平扫CT+AI)

Large-scale pancreatic cancer detection via non-contrast CT and deep learning - PubMed (nih.gov) 实验团队&#xff1a;海军军医大学第一附属医院&#xff08;上海长海医院&#xff09;&#xff0c;放射诊断科曹凯主治医生为共同第一作者&#xff0c;邵成伟、陆建平等教…

自然语言学习nlp 六

https://www.bilibili.com/video/BV1UG411p7zv?p118 Delta Tuning&#xff0c;尤其是在自然语言处理&#xff08;NLP&#xff09;和机器学习领域中&#xff0c;通常指的是对预训练模型进行微调的一种策略。这种策略不是直接更新整个预训练模型的权重&#xff0c;而是仅针对模型…

第七届西湖论剑·中国杭州网络安全技能大赛 AI 回声海螺 WP

第七届西湖论剑中国杭州网络安全技能大赛-AI-回声海螺 开题&#xff0c;提示输入密码给FLAG。 这个回声海螺应该是个AI&#xff0c;就是复读机&#xff0c;应该是想办法从中骗出密码。 感觉这题不像是AI&#xff0c;也没用啥模型&#xff0c;应该是WEB。或者是说类似于AI的提示…

150基于matlab的凸轮轮廓的设计计算与绘图计算此结构的最优化参数

基于matlab的凸轮轮廓的设计计算与绘图计算此结构的最优化参数&#xff0c;根据其原理输出推程和回程的最大压力角、最小曲率半径等相关结果。程序已调通&#xff0c;可直接运行。 150 凸轮轮廓的设计 结构的最优化参数 (xiaohongshu.com)

uniapp vue3怎么调用uni-popup组件的this.$refs.message.open() ?

vue2代码 <!-- 提示信息弹窗 --><uni-popup ref"message" type"message"><uni-popup-message :type"msgType" :message"messageText" :duration"2000"></uni-popup-message></uni-popup>typ…

OpenEuler20.03LTS SP2 上安装 OpenGauss3.0.0 单机部署过程(二)

开始安装 OpenGauss 数据库 3.1.7 安装依赖包 (说明:如果可以联网,可以通过网络 yum 安装所需依赖包,既可以跳过本步骤。如果网络无法连通,请把本文档所在目录下的依赖包上传到服务器上,手工安装后,即无需通过网络进行 Yum 安装了): 上传:libaio-0.3.111-5.oe1.x8…

C语言的循环结构

目录 前言 1.三种循环语句 1.while循环 2.for循环 2.1缺少表达式的情况 3.do while循环 2.break语句和continue语句 2.1在while循环中 2.2在for循环中 2.3在do while 循环中 3.循环的嵌套 4.go to语句 前言 C语⾔是结构化的程序设计语⾔&#xff0c;这⾥的结构指的是…

《MySQL 简易速速上手小册》第4章:数据安全性管理(2024 最新版)

文章目录 4.1 用户认证和权限控制4.1.1 基础知识4.1.2 重点案例&#xff1a;使用 Python 管理 MySQL 用户权限4.1.3 拓展案例 4.2 防止 SQL 注入和其他安全威胁4.2.1 基础知识4.2.2 重点案例&#xff1a;使用 Python 和 MySQL 进行安全的数据查询4.2.3 拓展案例 4.3 数据加密和…

【Java八股面试系列】JVM-内存区域

目录 Java内存区域 运行时数据区域 线程独享区域 程序计数器 Java 虚拟机栈 StackFlowError&OOM 本地方法栈 线程共享区域 堆 GCR-分代回收算法 字符串常量池 方法区 运行时常量池 HotSpot 虚拟机对象探秘 对象的创建 对象的内存布局 句柄 Java内存区域 运…

Golang与Erlang有什么差异

Golang和Erlang是两种备受关注的编程语言&#xff0c;它们各自具有独特的特点和优势。下面我将简单的探讨一下Golang和Erlang之间的差异&#xff0c;并且分析它们在并发模型、运行环境、函数式编程和领域特性等多个方面的不同之处。 并发模型 Golang使用goroutines和channels…

UE4运用C++和框架开发坦克大战教程笔记(十九)(第58~60集)完结

UE4运用C和框架开发坦克大战教程笔记&#xff08;十九&#xff09;&#xff08;第58~60集&#xff09;完结 58. 弹窗显示与隐藏59. UI 面板销毁60. 框架完成与总结 58. 弹窗显示与隐藏 这节课我们先来补全 TransferMask() 里对于 Overlay 布局类型面板的遮罩转移逻辑&#xff…

获取视频帧图片

在实现了minio文件上传的基础上进行操作 一、编写pom <dependency><groupId>org.jcodec</groupId><artifactId>jcodec</artifactId><version>0.2.5</version> </dependency> <dependency><groupId>org.jcodec<…

【RPA】智能自动化的未来:AI + RPA

伴随着人工智能&#xff08;AI&#xff09;技术的迅猛进步&#xff0c;机器人流程自动化&#xff08;RPA&#xff09;正在经历一场翻天覆地的变革。AI为RPA注入了新的活力&#xff0c;尤其在处理复杂任务和制定决策方面。通过融合自然语言处理&#xff08;NLP&#xff09;、机器…

Flink面试准备

零. 主要内容 一. Flink 提交 1. Flink怎么提交? Local模式 JobManager 和 TaskManager 共用一个 JVM,只需要jdk支持&#xff0c;单节点运行&#xff0c;主要用来调试。 Standlone模式 Standlone 是Flink自带的一个分布式集群&#xff0c;它不依赖其他的资源调度框架、不依赖y…

leetcode——滑动窗口题目汇总

本章总结一下滑动窗口的解题思路&#xff1a; 在字符串中使用双指针 left 和 right 围成的一个左闭右开的区域作为一个窗口。不断将 right 向右滑动&#xff0c;直到窗口中的字符串符合条件。此时将 left 向右滑动&#xff0c;直到窗口中的字符串不符合条件&#xff0c;期间需…

离线场景下任意文档的在线预览及原样格式翻译,不依赖其他厂商接口非侵入式一行js代码实现网站的翻译及国际化,可配置使用多种翻译语言

离线场景下任意文档的在线预览及原样格式翻译&#xff0c;不依赖其他厂商接口非侵入式一行js代码实现网站的翻译及国际化&#xff0c;可配置使用多种翻译语言。 要实现翻译需要解决以下3个主要问题&#xff1a; 1&#xff09;from&#xff1a;内容本身的语言类型是什么&#xf…

PCIE 参考时钟架构

一、PCIe架构组件 首先先看下PCIE架构组件&#xff0c;下图中主要包括&#xff1a; ROOT COMPLEX (RC) (CPU); PCIE PCI/PCI-X Bridge; PCIE SWITCH; PCIE ENDPOINT (EP) (pcie设备); BUFFER; 各个器件的时钟来源都是由100MHz经过Buffer后提供。一个PCIE树上最多可以有256…

【Docker】了解Docker Desktop桌面应用程序,TA是如何管理和运行Docker容器(2)

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Docker容器》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…