springboot listener、filter登录实战

转载自: www.javaman.cn
博客系统访问: http://175.24.198.63:9090/front/index
在这里插入图片描述

登录功能

1、前端页面

采用的是layui-admin框架,文中的验证码内容,请参考作者之前的验证码功能

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head><title>ds博客</title><div th:replace="common/link::header"></div><link rel="stylesheet" th:href="@{/static/layuiadmin/style/login.css}" media="all">
</head>
<body>
<div class="layadmin-user-login layadmin-user-display-show" id="LAY-user-login" style="display: none;"><div class="layadmin-user-login-main"><div class="layadmin-user-login-box layadmin-user-login-header"><h2>ds博客</h2><p>后台登录</p></div><div class="layadmin-user-login-box layadmin-user-login-body layui-form"><div class="layui-form-item"><label class="layadmin-user-login-icon layui-icon layui-icon-username" for="LAY-user-login-username"></label><input type="text" name="userName" value="test" id="LAY-user-login-username" lay-verify="required" placeholder="用户名" class="layui-input"></div><div class="layui-form-item"><label class="layadmin-user-login-icon layui-icon layui-icon-password" for="LAY-user-login-password"></label><input type="password" name="passWord" value="test" id="LAY-user-login-password" lay-verify="required" placeholder="密码" class="layui-input"></div><div class="layui-form-item"><div class="layui-row"><div class="layui-col-xs7"><label class="layadmin-user-login-icon layui-icon layui-icon-vercode"></label><input type="text" name="code"  lay-verify="required" placeholder="图形验证码" class="layui-input"></div><div class="layui-col-xs5"><div style="margin-left: 10px;"><img id="codeImg" class="layadmin-user-login-codeimg"></div></div></div></div><div class="layui-form-item" style="margin-bottom: 20px;"><input type="checkbox" name="remember-me" lay-skin="primary" title="记住密码"></div><div class="layui-form-item"><button class="layui-btn layui-btn-fluid layui-bg-blue"  lay-submit lay-filter="login">登 录</button></div></div></div><!--    <div class="layui-trans layadmin-user-login-footer">-->
<!--        <p>版权所有 © 2022 <a href="#" target="_blank">济南高新开发区微本地软件开发工作室</a> 鲁ICP备20002306号-1</p>-->
<!--    </div>-->
</div>
<div th:replace="common/script::footer"></div>
<script th:inline="javascript">layui.config({base: '/static/layuiadmin/' //静态资源所在路径}).extend({index: 'lib/index' //主入口模块}).use(['index', 'user'], function(){let $ = layui.$,form = layui.form;// 初始化getImgCode();form.render();//提交form.on('submit(login)', function(obj) {// 打开loadinglet loading = layer.load(0, {shade: false,time: 2 * 1000});// 禁止重复点击按钮$('.layui-btn').attr("disabled",true);//请求登入接口$.ajax({type: 'POST',url:  ctx + '/login',data: obj.field,dataType: 'json',success: function(result) {if (result.code === 200) {layer.msg('登入成功', {icon: 1,time: 1000}, function(){window.location.href = '/';});} else {layer.msg(result.message);// 刷新验证码getImgCode();// 关闭loadinglayer.close(loading);// 开启点击事件$('.layui-btn').attr("disabled", false);}}});});$("#codeImg").on('click', function() {// 添加验证码getImgCode();});$(document).keydown(function (e) {if (e.keyCode === 13) {$('.layui-btn').click();}});// 解决session过期跳转到登录页并跳出iframe框架$(document).ready(function () {if (window != top) {top.location.href = location.href;}});});/*** 获取验证码*/function getImgCode() {let url = ctx + '/getImgCode';let xhr = new XMLHttpRequest();xhr.open('GET', url, true);xhr.responseType = "blob";xhr.onload = function() {if (this.status === 200) {let blob = this.response;document.getElementById("codeImg").src = window.URL.createObjectURL(blob);}}xhr.send();}
</script>
</body>
</html>
2、后端处理/login请求

在这里插入图片描述

通过springsecurity的.loginProcessingUrl(“/login”)处理,处理逻辑如下:

.loginProcessingUrl("/login") 用于指定处理登录操作的URL地址,而具体的验证逻辑是由 Spring Security 提供的认证过滤器链负责的。在Spring Security中,主要的认证过程是由UsernamePasswordAuthenticationFilter来完成的。

当用户提交登录表单,请求到达.loginProcessingUrl("/login")配置的URL时,UsernamePasswordAuthenticationFilter会拦截这个请求,然后进行以下主要步骤:

  1. 获取用户名和密码:从请求中获取用户输入的用户名和密码。

  2. 创建认证令牌:使用获取到的用户名和密码创建一个认证令牌(UsernamePasswordAuthenticationToken)。

  3. 将认证令牌传递给认证管理器:将认证令牌传递给配置的认证管理器(AuthenticationManager)进行认证。

  4. 执行认证逻辑:认证管理器会调用已配置的身份验证提供者(AuthenticationProvider)来执行实际的身份验证逻辑。通常,会使用用户提供的用户名和密码与系统中存储的用户信息进行比对。

  5. 处理认证结果:认证提供者返回认证结果,如果认证成功,则将认证令牌标记为已认证,并设置用户权限等信息。如果认证失败,会抛出相应的异常。

  6. 处理认证成功或失败:根据认证的结果,UsernamePasswordAuthenticationFilter将请求重定向到成功或失败的处理器,执行相应的操作,比如跳转页面或返回错误信息。

这个整个过程是由 Spring Security 提供的默认配置完成的,通常情况下,开发者只需要配置好认证管理器、用户信息服务(UserDetailsService),以及成功和失败的处理器,Spring Security 就会负责处理登录验证的整个流程。

package com.ds.core.config;import com.ds.blog.system.service.SysUserService;
import com.ds.core.security.CustomAccessDeniedHandler;
import com.ds.core.security.DefaultAuthenticationFailureHandler;
import com.ds.core.security.DefaultAuthenticationSuccessHandler;
import com.ds.core.security.filter.ValidateCodeFilter;
import net.bytebuddy.asm.Advice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()// 放过.antMatchers("/loginPage", "/getImgCode").permitAll().antMatchers("/**/*.jpg", "/**/*.png", "/**/*.gif", "/**/*.jpeg").permitAll()// 剩下的所有的地址都是需要在认证状态下才可以访问.anyRequest().authenticated().and()// 过滤登录验证码.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)// 配置登录功能.formLogin().usernameParameter("userName").passwordParameter("passWord")// 指定指定要的登录页面.loginPage("/loginPage")// 处理认证路径的请求.loginProcessingUrl("/login").successHandler(defaultAuthenticationSuccessHandler).failureHandler(defaultAuthenticationFailureHandler).and().exceptionHandling().accessDeniedHandler(accessDeniedHandler).and()// 登出.logout().invalidateHttpSession(true).deleteCookies("remember-me").logoutUrl("/logout").logoutSuccessUrl("/loginPage").and().rememberMe()// 有效期7天.tokenValiditySeconds(3600 * 24 * 7)// 开启记住我功能.rememberMeParameter("remember-me").and()//禁用csrf.csrf().disable()// header response的X-Frame-Options属性设置为SAMEORIGIN.headers().frameOptions().sameOrigin().and()// 配置session管理.sessionManagement()//session失效默认的跳转地址.invalidSessionUrl("/loginPage");}
}
3、登录成功监听器(记录登录日志)

创建监听器,在登录成功的时候记录登录日志。

  1. @Slf4j

    • @Slf4j 是 Lombok 提供的注解,用于自动生成日志对象,这里是为了方便使用日志。
  2. @Component

    • @Component 注解将类标识为一个 Spring 组件,使得 Spring 能够自动扫描并将其纳入容器管理。
  3. AuthenticationSuccessListener 实现 ApplicationListener 接口

    • AuthenticationSuccessListener 类实现了 ApplicationListener<AuthenticationSuccessEvent> 接口,表明它是一个事件监听器,监听的是用户认证成功的事件。
  4. SysLoginLogService 注入

    • SysLoginLogService 是一个服务类,通过 @Autowired 注解注入到当前类中。该服务类用于对登录日志的持久化操作。
  5. onApplicationEvent 方法

    • onApplicationEvent 方法是实现 ApplicationListener 接口的回调方法,在用户认证成功的时候会被触发。
    • 通过 authenticationSuccessEvent.getAuthentication().getPrincipal() 获取登录的用户信息,这里假设用户信息是 User 类型。
    • 通过 ServletUtil.getClientIP 获取客户端的IP地址,这里使用了 ServletUtil 工具类,可以通过请求上下文获取IP地址。
    • 创建一个 SysLoginLog 对象,将登录成功的相关信息设置进去,包括账号、登录IP、备注等。
    • 调用 sysLoginLogService.save(sysLoginLog) 将登录日志持久化存储。

总的来说,这段代码的作用是在用户成功登录后,通过监听 Spring Security 的认证成功事件,记录用户的登录日志信息,包括登录账号、登录IP和登录成功的备注。这样可以实现登录成功后的自定义操作,例如记录登录日志等。

@Slf4j
@Component
public class AuthenticationSuccessListener implements ApplicationListener<AuthenticationSuccessEvent> {@Autowiredprivate SysLoginLogService sysLoginLogService;@Overridepublic void onApplicationEvent(AuthenticationSuccessEvent authenticationSuccessEvent) {// 登录账号User user = (User) authenticationSuccessEvent.getAuthentication().getPrincipal();// 请求IPString ip = ServletUtil.getClientIP(((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(), "");SysLoginLog sysLoginLog = new SysLoginLog();sysLoginLog.setAccount(user.getUsername());sysLoginLog.setLoginIp(ip);sysLoginLog.setRemark("登录成功");sysLoginLogService.save(sysLoginLog);}
}
4、登录失败监听器(记录登录日志)

创建监听器,在登录失败的时候记录异常登录日志。

@Slf4j
@Component
public class AuthenticationFailureListener implements ApplicationListener<AbstractAuthenticationFailureEvent>  {@Autowiredprivate SysLoginLogService sysLoginLogService;@Overridepublic void onApplicationEvent(AbstractAuthenticationFailureEvent abstractAuthenticationFailureEvent) {// 登录账号String username = abstractAuthenticationFailureEvent.getAuthentication().getPrincipal().toString();// 登录失败原因String message ;if (abstractAuthenticationFailureEvent instanceof AuthenticationFailureBadCredentialsEvent) {//提供的凭据是错误的,用户名或者密码错误message = "提供的凭据是错误的,用户名或者密码错误";} else if (abstractAuthenticationFailureEvent instanceof AuthenticationFailureCredentialsExpiredEvent) {//验证通过,但是密码过期message = "验证通过,但是密码过期";} else if (abstractAuthenticationFailureEvent instanceof AuthenticationFailureDisabledEvent) {//验证过了但是账户被禁用message = "验证过了但是账户被禁用";} else if (abstractAuthenticationFailureEvent instanceof AuthenticationFailureExpiredEvent) {//验证通过了,但是账号已经过期message = "验证通过了,但是账号已经过期";} else if (abstractAuthenticationFailureEvent instanceof AuthenticationFailureLockedEvent) {//账户被锁定message = "账户被锁定";} else if (abstractAuthenticationFailureEvent instanceof AuthenticationFailureProviderNotFoundEvent) {//配置错误,没有合适的AuthenticationProvider来处理登录验证message = "配置错误";} else if (abstractAuthenticationFailureEvent instanceof AuthenticationFailureProxyUntrustedEvent) {// 代理不受信任,用于Oauth、CAS这类三方验证的情形,多属于配置错误message = "代理不受信任";} else if (abstractAuthenticationFailureEvent instanceof AuthenticationFailureServiceExceptionEvent) {// 其他任何在AuthenticationManager中内部发生的异常都会被封装成此类message = "内部发生的异常";} else {message = "其他未知错误";}// 请求IPString ip = ServletUtil.getClientIP(((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(), "");SysLoginLog sysLoginLog = new SysLoginLog();sysLoginLog.setAccount(username);sysLoginLog.setLoginIp(ip);sysLoginLog.setRemark(message);sysLoginLogService.save(sysLoginLog);}
}
5、认证成功处理器

下面是一个认证成功处理器,登录成功后,会返回响应的信息给前端

@Component
@Slf4j
public class DefaultAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {log.info("-----login in success----");response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");PrintWriter writer = response.getWriter();writer.write(JSON.toJSONString(Result.success()));writer.flush();}
}
.successHandler(defaultAuthenticationSuccessHandler)
.failureHandler(defaultAuthenticationFailureHandler)
6、认证失败处理器

下面是一个认证成功处理器,登录成功后,会返回响应的信息给前端

@Component
@Slf4j
public class DefaultAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {log.info("login in failure : " +  exception.getMessage());response.setContentType("application/json;charset=utf-8");response.setCharacterEncoding("utf-8");PrintWriter writer = response.getWriter();String message;if (exception instanceof BadCredentialsException) {message =  "用户名或密码错误,请重试。";writer.write(JSON.toJSONString(Result.failure(message)));}else{writer.write(JSON.toJSONString(Result.failure(exception.getMessage())));}writer.flush();}
.successHandler(defaultAuthenticationSuccessHandler)
.failureHandler(defaultAuthenticationFailureHandler)
7、前端页面

返回200,就代表成功,跳转到/请求,进去index或者main页面

if (result.code === 200) {layer.msg('登入成功', {icon: 1,time: 1000}, function(){window.location.href = '/';});
} else {

在这里插入图片描述

总结

AuthenticationSuccessEvent 是 Spring Security 中用于表示用户认证成功的事件。判断登录成功的主要依据是在认证过程中,用户提供的凭据(通常是用户名和密码)与系统中存储的凭据匹配。以下是判断登录成功的基本流程:

  1. 用户提交登录表单
    • 用户在浏览器中输入用户名和密码,然后点击登录按钮,提交登录表单。
  2. Spring Security 拦截登录请求
    • 配置的 .loginProcessingUrl("/login") 指定了登录请求的URL,Spring Security会拦截这个URL的请求。
  3. UsernamePasswordAuthenticationFilter处理登录请求
    • UsernamePasswordAuthenticationFilter 是 Spring Security 内置的过滤器之一,用于处理用户名密码登录认证。
    • 当用户提交登录表单时,UsernamePasswordAuthenticationFilter会拦截该请求,尝试进行身份验证。
  4. AuthenticationManager执行身份验证
    • UsernamePasswordAuthenticationFilter将用户名密码等信息封装成一个 UsernamePasswordAuthenticationToken
    • 通过 AuthenticationManager 进行身份验证,AuthenticationManager 是一个接口,实际的实现为 ProviderManager
    • ProviderManager通过配置的 AuthenticationProvider 来执行实际的身份验证逻辑。
  5. AuthenticationProvider处理身份验证
    • DaoAuthenticationProviderAuthenticationProvider 的默认实现之一,用于处理基于数据库的身份验证。
    • DaoAuthenticationProvider会从配置的 UserDetailsService 中获取用户信息,然后与用户提交的信息进行比对。
  6. 认证成功
    • 如果认证成功,AuthenticationProvider 会返回一个已认证的 Authentication 对象。
    • 这个已认证的 Authentication 对象包含了用户的信息,通常是 UserDetails 的实现。
  7. AuthenticationSuccessHandler处理认证成功
    • 在配置中,通过 .successHandler() 方法指定了处理认证成功的 AuthenticationSuccessHandler
    • 在这个处理器中,可以执行一些额外的逻辑,例如记录登录日志等。
  8. AuthenticationSuccessEvent被发布
    • 在处理成功的阶段,Spring Security 发布了 AuthenticationSuccessEvent 事件,表示认证成功。

在上述流程中,认证成功的判断主要是在 AuthenticationProvider 中完成的。DaoAuthenticationProvider 会检查用户提供的密码与数据库中存储的密码是否匹配。如果匹配,就认为认证成功。当认证成功后,后续的处理流程包括 AuthenticationSuccessHandler 的执行和 AuthenticationSuccessEvent 的发布。你可以通过监听 AuthenticationSuccessEvent 事件来执行一些额外的自定义逻辑,例如记录登录日志。

在这里插入图片描述

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

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

相关文章

Java连接数据库的各种细节错误(细节篇)

目录 前后端联调&#xff08;传输文件&#xff09; ClassNotFoundException: SQLException: SQL语法错误: 数据库连接问题: 驱动问题: 资源泄露: 并发问题: 超时问题: 其他库冲突: 配置问题: 网络问题: SSL/TLS问题: 数据库权限问题: 驱动不兼容: 其他未知错误…

Docker-compose单机容器编排

YML文件是什么&#xff1f; YAML文件是一种标记语言&#xff0c;以竖列的形式展示序列化的数据格式。可读性很高类似于json格式。语法简单。 YAML通过缩进来表示数据结构&#xff0c;连续的项目用-符号来表示。 YML文件使用的注意事项 1、 大小写敏感 2、 通过缩进表示层级…

JavaScript实现飘窗功能

实现飘窗功能很简单 html代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title…

Ubuntu22.04添加用户

一、查看已存在的用户 cat /etc/passwd 二、添加用户 sudo adduser xxx 除了密码是必须的&#xff0c;其他的都可以不填&#xff0c;直接回车即可 三、查看添加的用户 cat /etc/passwd 四、将新用户添加到sudo组 sudo adduser xxx sudo 五、删除用户 sudo delus…

钉钉 × E签宝,打通系统屏障,实现钉钉审批通过后自动同步到E签宝发起签署并返回拖章链接全流程自动化

1 场景描述 成熟的业务体系需要用户的优质体验和高效的交易效率来支撑。而合同作为双方业务往来的法律保证&#xff0c;签合同已成为目前企业必不可少的重要一环。但传统的签署场景中&#xff0c;传统纸质合同的签署往往采用线下见面或邮寄的方式进行&#xff0c;不仅流程复杂&…

5 转向事件驱动的架构

文章目录 核心概念消息代理事件和消息了解事件异步消息通信响应式系统 事件驱动的利弊消息传递模式发布—订阅工作队列过滤器数据持久性 消息传递代理协议、标准和工具AMQP和RabbitMQ基本概念交换类型和路由消息确认和拒绝 设置RabbitMQ安装RabbitMQRabbitMQ管理界面 Spring AM…

pyqt5+QWebEngineView+pdfjs+win32print实现pdf文件的预览、打印

一、pdf显示逻辑 import sys from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgetsPDFJS file:///pdfjs-1.9.426-dist/web/viewer.html # PDFJS file:///usr/share/pdf.js/web/viewer.html PDF file:///D:/Code/report.pdfclass Window(QtWebEngineWidgets.QWebEngine…

数据结构:使用Stack完成表达式计算逻辑

题目&#xff1a; 给出如下串&#xff1a;sum(sum(sum(1,2),avg(3,5)),avg(avg(6,8),7))&#xff0c; 计算结果&#xff08;保证输入任意上述接口均能输出正确结果&#xff09; 思路&#xff1a; ​编辑 代码&#xff1a; import java.util.Stack;public class Test {public …

paddleocr文字识别变迁

数据挖掘 v3 UIM&#xff1a;无标注数据挖掘方案 UIM&#xff08;Unlabeled Images Mining&#xff09;是一种非常简单的无标注数据挖掘方案。核心思想是利用高精度的文本识别大模型对无标注数据进行预测&#xff0c;获取伪标签&#xff0c;并且选择预测置信度高的样本作为训…

LeetCode(57)合并两个有序链表【链表】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 合并两个有序链表 1.题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4…

修改naive ui默认样式,css变量值修改

新项目开发使用了naive ui组件库&#xff0c;使用组件时涉及到css样式修改&#xff0c;可以直接在组件父容器上使用组件内自带的css变量&#xff0c;组件会自动继承父容器的css变量值&#xff0c;不会影响其他页面使用&#xff1b; 示例&#xff1a;一个注册表单&#xff0c;两…

Centos7 配置Git

随笔记录 目录 1&#xff0c; 新建用户 2. 给用户设置密码相关操作 3. 为新用户添加sudo 权限 4. 配置Git 4.1 配置Git 4.2 查看id_ras.pub 5, 登录Git 配置SSH 秘钥 6. Centos7 登录Git 7. clone 指定branch到本地 8. 将新代码复制到指定路径 9. 上传指定代码 …

生态系统NPP及碳源、碳汇模拟、土地利用变化、未来气候变化、空间动态模拟实践技术应用

碳中和可以从碳排放&#xff08;碳源&#xff09;和碳固定&#xff08;碳汇&#xff09;这两个侧面来理解。陆地生态系统在全球碳循环过程中有着重要作用&#xff0c;准确地评估陆地生态系统碳汇及碳源变化对于研究碳循环过程、预测气候变化及制定合理政策具有重要意义。 CASA(…

生产实践:基于K8S私有化交付要注意这几点问题

公众号「架构成长指南」&#xff0c;专注于生产实践、云原生、分布式系统、大数据技术分享 在使用 k8s 进行项目私有化部署时&#xff0c;会遇到很多问题&#xff0c;以下把作者经常遇到的一些问题以及需要注意的点分享给各位。 资源依赖问题 在进行私有化部署时&#xff0c;…

字符设备驱动开发基础

一. 简介 本文简单了解一下&#xff0c;在字符设备驱动开发开始前对其一些基本认识。简单了解一下&#xff0c;应用程序与驱动的交互原理&#xff0c;以及字符设备驱动开发流程。 二. 字符设备驱动开发流程 1. 在 Linux 中一切皆为文件&#xff0c;驱动加载成功以后会在“…

数据爬虫:获取申万一级行业数据

目录 1. 获取访问接口 2. 链接网址 3. 链接名单 免责声明&#xff1a;本文由作者参考相关资料&#xff0c;并结合自身实践和思考独立完成&#xff0c;对全文内容的准确性、完整性或可靠性不作任何保证。同时&#xff0c;文中提及的数据仅作为举例使用&#xff0c;不构成推荐…

网站高性能架构设计——高性能数据库集群

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、高性能数据库简介 1.高性能数据库方式 读写分离&#xff1a;将访问压力分散到集群中的多个节点&#xff0c;没有分散存储压力 分库分表&…

Unity_使用FairyGUI搭建登录页面

Unity_使用FairyGUI搭建登录页面 1. 使用FairyGUI准备一个UI界面&#xff0c;例如&#xff1a;以下登录 2. 发布导出&#xff08;发布路径设置为Unity的Asset下任何路径&#xff09; 3. Unity编辑器安装FairyGUI包资源&#xff08;在资源商店找见并存储为我的资源&#xff0c;…

百度智能云战略与咨询高级总监詹颖:每个人都能在大模型驱动的数字化生态中找到立足之地

“ 大模型是皇冠上的明珠。 ” 整理 | 王娴 编辑 | 云舒 出品&#xff5c;极新 2023年11月28日&#xff0c;极新AIGC行业峰会在北京东升国际科学园顺利召开&#xff0c;百度智能云战略与咨询高级总监詹颖女士在会上做了题为《生成式 AI 驱动企业应用创新》的演讲。 重点…

了解宝宝健康第一步:做好华大基因无创产前筛查检测

近年来&#xff0c;高龄产妇明显增加&#xff0c;多因素的影响导致出生缺陷发生率呈总体上升趋势&#xff0c;出生缺陷已经成为重大公共卫生问题之一&#xff0c;更是影响人口质量的重要风险因素。孕前、孕期到产后的出生缺陷综合防控三级体系中&#xff0c;做好产前筛查是阻断…