SpringBootWeb登录认证
JWT令牌
JSON Web Token JSON Web Tokens - jwt.ioJSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).https://jwt.io/JSON Web Token(JWT)是一种基于JSON的开放标准(RFC 7519),用于在各方之间安全地传输信息。以下是对JWT进行详细介绍:
- JWT的工作原理:JWT的工作原理基于令牌(Token)的生成和验证两个主要过程。一旦用户通过身份验证,服务器会生成一个包含用户信息的JWT。这个令牌由三部分组成:标头(Header)、有效载荷(Payload)以及签名(Signature)。标头通常包含令牌的类型和所使用的签名算法;有效载荷则包含了实际的数据声明,如发行人、到期时间、主题、用户等信息;签名是为了确保令牌在传输过程中不被篡改。
- JWT的优点:JWT提供了无状态、可扩展且安全的认证解决方案,特别适用于分布式环境和移动应用。由于JWT自包含所有用户信息,服务端不需要存储session信息,从而减轻了服务器的压力。同时,JWT可以跨域使用,支持单点登录(SSO),并且不依赖于Cookie,因此也避免了CSRF攻击的风险。
- JWT的缺点:尽管JWT具有许多优点,但它也存在一些缺点。例如,一旦JWT被窃取,攻击者就可以访问所有的用户资源,直到令牌过期。此外,如果JWT未加密,通过某些手段可能会被解码并修改其内容。
在考虑使用JWT时,还需要注意以下几个方面:
- 安全性:虽然JWT可以加密并签名以保证数据的安全性和完整性,但默认情况下JWT是不加密的。因此,在使用JWT传输敏感信息时,应采取额外的安全措施,如使用HTTPS协议进行传输。
- 有效期:为了减少被盗用的风险,JWT的有效期不宜设置过长。对于一些重要操作,应要求用户频繁进行身份验证。
- 存储:虽然JWT通常存储在客户端,但也可以选择存储在服务器端,这取决于特定的应用场景和安全需求。
综上所述,JSON Web Token(JWT)是一个功能强大的工具,它提供了一种轻量级的解决方案,用于在现代Web应用程序中安全地处理身份验证和信息交换。通过了解JWT的工作原理、优缺点以及正确的使用方法,开发者可以有效地利用这一技术来提高应用的安全性和用户体验。
依赖配置
pom.xml引入JWT依赖
<!-- JWT依赖-->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
生成JWT令牌
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, "密钥") //签名算法 .setExpiration(new Date(System.currentTimeMillis() + 24*3600*1000)) //有效期 .compact();System.out.println(jwt);
}
输出的结果就是生成的JWT令牌,,通过英文的点分割对三个部分进行分割。可以打开JWT官网进行校验。
校验JWT令牌
public void parseJwt(){Claims claims = Jwts.parser().setSigningKey("密钥")//指定签名密钥.parseClaimsJws("JWT令牌内容").getBody();System.out.println(claims);
}
将JWT令牌封装成工具类
public class JwtUtils {private static String signKey = "wfit";private static Long expire = 43200000L;/*** 生成JWT令牌* @param claims JWT第二部分负载 payload 中存储的内容* @return*/public static String generateJwt(Map<String, Object> claims){String jwt = Jwts.builder()//添加内容荷载.addClaims(claims)//签名算法.signWith(SignatureAlgorithm.HS256, signKey)//令牌时间.setExpiration(new Date(System.currentTimeMillis() + expire))//转化字符串.compact();return jwt;}/*** 解析JWT令牌* @param jwt JWT令牌* @return JWT第二部分负载 payload 中存储的内容*/public static Claims parseJWT(String jwt){Claims claims = Jwts.parser()//签名密钥.setSigningKey(signKey)//JWT令牌.parseClaimsJws(jwt).getBody();return claims;}
}
过滤器 Filter
过滤器(Filter)是Java Web应用中的一个重要组件,它主要用于请求到达Servlet之前或响应返回客户端之前对请求和响应进行处理。具体分析如下:
- 基本介绍:过滤器可以对进入的应用请求进行预处理,也可以对出去的响应进行后处理。这种机制使得开发人员可以在请求到达目标之前,以及响应被发送给客户端之前,执行一些特定的操作。例如,可以用于实现权限验证、请求内容的转换、日志记录等。
- 过滤器原理:过滤器的工作原理基于一种链式结构,即过滤器链。当一个请求到达时,它会按照配置的顺序通过每个过滤器。每个过滤器都可以修改请求或响应,或者决定是否将请求/响应传递到链中的下一个过滤器或目标资源。
- 过滤器接口:在Java中,创建过滤器需要实现
javax.servlet.Filter
接口,该接口定义了init()
,doFilter()
, 和destroy()
三个方法。init()
方法在过滤器初始化时调用,doFilter()
方法用于实际的过滤操作,而destroy()
方法在过滤器销毁前调用。 - 使用过滤器:要使用过滤器,首先需要创建一个实现了Filter接口的Java类,然后通过注解
@WebFilter
指定过滤规则,或者在web.xml
文件中配置过滤器及其拦截路径。过滤器的具体逻辑实现在doFilter()
方法中完成。 - 配置过滤器:过滤器的配置可以通过两种方式完成:一是使用
@WebFilter
注解直接在过滤器类上指定拦截路径;二是在项目的web.xml
文件中配置过滤器及其拦截的URL模式。这两种方式都允许灵活地控制哪些请求应该被拦截和处理。 - 过滤器生命周期:过滤器的生命周期由Web容器管理。当Web应用启动时,过滤器被初始化;接收到请求时,执行
doFilter()
方法;在Web应用关闭时,执行destroy()
方法以释放资源。 - 多个Filter的执行顺序:当使用多个过滤器时,它们的执行顺序非常重要。这个顺序可以通过在
web.xml
中配置的顺序或使用@WebFilter
注解指定的顺序参数来确定。正确的执行顺序确保了过滤器能够按照预期的方式工作。
此外,在开发过程中,需要注意以下几点:
- 正确配置:确保过滤器及其拦截路径正确配置,避免拦截不应该被拦截的请求。
- 性能考虑:虽然过滤器提供了强大的功能,但不当使用可能会影响应用性能。应尽量减少过滤器的数量,并优化过滤逻辑。
- 线程安全问题:由于过滤器对象可能在多线程环境下被并发访问,因此需要确保过滤器的实现是线程安全的。
总的来说,过滤器是Java Web开发中一个非常强大且灵活的工具,能够帮助开发者实现许多高级功能,提高代码的模块化和重用性。通过合理使用过滤器,可以极大地提升Web应用的安全性、效率和可维护性。
启动类注解
@ServletComponentScan//识别service
@SpringBootApplication
public class WebManagementApplication {public static void main(String[] args) {SpringApplication.run(TliasWebManagementApplication.class, args);}}
只有添加了@ServletComponentScan,Spring才能正常使用Filter。
设计拦截器实现Filter接口,重新其中方法即可。
执行流程
@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter {@Override //初始化方法, 只调用一次public void init(FilterConfig filterConfig) throws ServletException {System.out.println("init 初始化方法执行了");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("DemoFilter 放行前逻辑.....");//放行请求filterChain.doFilter(servletRequest,servletResponse);System.out.println("DemoFilter 放行后逻辑.....");}@Override //销毁方法, 只调用一次public void destroy() {System.out.println("destroy 销毁方法执行了");}
}
拦截路径参数
拦截路径 | urlPatterns值 | 含义 |
---|---|---|
拦截具体路径 | /login | 只有访问 /login 路径时,才会被拦截 |
目录拦截 | /emps/* | 访问/emps下的所有资源,都会被拦截 |
拦截所有 | /* | 访问所有资源,都会被拦截 |
使用拦截器和JWT令牌实现登录认证案例
@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//类型请求对象HttpServletRequest ser= (HttpServletRequest) servletRequest;HttpServletResponse serp= (HttpServletResponse) servletResponse;//获取请求URLString url = ser.getRequestURL().toString();log.info("url:{}",url);//判断url是否包含login关键字,如果有就放行if (url.contains("login")){log.info("登录操作,放行...");filterChain.doFilter(servletRequest,servletResponse);return;}//获取请求头中的令牌String jwt = ser.getHeader("token");//判断令牌是否存在//否if (!StringUtils.hasLength(jwt)){log.info("token为空,未登录");Result error = Result.error("NOT_LOGIN");//手动将对象转换为JSON --->阿里巴巴fastJSONString jsonString = JSONObject.toJSONString(error);//将JSON返回给浏览器serp.getWriter().write(jsonString);return;}//是try {JwtUtils.parseJWT(jwt);} catch (Exception e) {e.printStackTrace();log.info("令牌解析失败");Result error = Result.error("NOT_LOGIN");//手动将对象转换为JSON --->阿里巴巴fastJSONString jsonString = JSONObject.toJSONString(error);//将JSON返回给浏览器serp.getWriter().write(jsonString);return;}//放行log.info("令牌合法,放行");filterChain.doFilter(servletRequest,servletResponse);}}
拦截器Interceptor
拦截器(Interceptor)是一种用于在控制器处理请求之前或之后执行某些操作的机制。以下将深入介绍拦截器的相关信息:
拦截器的基本概念:
- 拦截器(Interceptor)在Spring框架中,主要用于对Controller层的处理方法进行拦截,即可以在方法执行前后加入自定义的操作。拦截器与过滤器(Filter)相比,过滤器更广泛地用于请求和响应的预处理和后处理,而拦截器则更加关注于具体的处理器(Controller)方法。
拦截器的实现原理:
- 拦截器通常通过代理方式或反射机制实现。在Spring MVC应用中,拦截器通过动态代理来实现对Controller方法的增强。当一个HTTP请求到达时,如果配置了拦截器,那么这个请求在被目标Controller处理之前,会先经过一系列拦截器的处理。
拦截器的主要作用:
- 日志记录:记录请求信息,包括请求的URL、IP地址、时间等,便于监控和日志分析。
- 权限检查:例如检查用户是否已登录,是否有权访问某个特定的资源或服务。
- 性能监控:计算请求的处理时间,帮助开发者优化应用性能。
- 通用行为增强:如提取用户信息放入请求中,方便后续流程使用;或者根据不同的用户设置不同的主题和语言。
拦截器的自定义实现:
- 要创建自定义的拦截器,需要实现
HandlerInterceptor
接口或继承HandlerInterceptorAdapter
类,并重写preHandle()
,postHandle()
, 和afterCompletion()
三个方法。这些方法分别在请求处理前、视图渲染前、以及整个请求结束后被调用。
拦截器的使用场景举例:
- 在电商平台中,可以使用拦截器来检查用户是否登录,如果没有登录则重定向到登录页面。
- 对于需要计费的API,可以利用拦截器来计算调用次数和时长,从而实现计费功能。
- 在内容管理系统中,使用拦截器来限制只有特定角色的用户才能访问某些管理功能。
此外,考虑到拦截器的强大功能及其灵活性,开发者在使用时应注意以下几点:
- 正确配置:确保拦截器及其拦截规则正确配置,避免影响正常的业务流程。
- 性能考虑:虽然拦截器提供了强大的功能,但不当使用可能会影响应用性能。应尽量减少拦截器的数量,并优化其逻辑。
- 线程安全问题:由于拦截器对象可能在多线程环境下被并发访问,因此需要确保拦截器的实现是线程安全的。
综上所述,拦截器在Spring MVC应用中扮演着至关重要的角色,它不仅能够增强方法处理的能力,还能提高代码的模块化和重用性。通过合理使用拦截器,可以极大地提升Web应用的安全性、效率和可维护性。
自定义拦截器
需要实现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 .... ");}
}
注意:
preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行
postHandle方法:目标资源方法执行后执行
afterCompletion方法:视图渲染完毕后执行,最后执行
注册配置拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {//自定义的拦截器对象@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器对象registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表示拦截所有请求)}
}
拦截路径
拦截路径 | 含义 | 举例 |
---|---|---|
/* | 一级路径 | 能匹配/depts,/emps,/login,不能匹配 /depts/1 |
/** | 任意级路径 | 能匹配/depts,/depts/1,/depts/1/2 |
/depts/* | /depts下的一级路径 | 能匹配/depts/1,不能匹配/depts/1/2,/depts |
/depts/** | /depts下的任意级路径 | 能匹配/depts,/depts/1,/depts/1/2,不能匹配/emps/1 |
@Configuration
public class WebConfig implements WebMvcConfigurer {//拦截器对象@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器对象registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**")//设置拦截器拦截的请求路径( /** 表示拦截所有请求).excludePathPatterns("/login");//设置不拦截的请求路径}
}
使用过滤器和JWT令牌实现登录认证案例
注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**")//拦截什么样的路径.excludePathPatterns("/login");//不拦截什么路径}
}
定义拦截器
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override //目标资源方法运行前运行,true放行public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String url = request.getRequestURL().toString();log.info("拦截路径:{}",url);String token = request.getHeader("token");if (!StringUtils.hasLength(token)){log.info("token为空");Result error = Result.error("NOT_LOGIN");String s = JSONObject.toJSONString(error);response.getWriter().write(s);return false;}try {JwtUtils.parseJWT(token);} catch (Exception e) {log.info("令牌有误");response.getWriter().write(JSONObject.toJSONString(Result.success("NOT_LOGIN")));return false;}log.info("令牌正确,执行登录");return true;}@Override //目标资源方法运行后运行public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Override //视图渲染完毕后执行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}
扩展——执行流程
-
当我们打开浏览器来访问部署在web服务器当中的web应用时,此时我们所定义的过滤器会拦截到这次请求。拦截到这次请求之后,它会先执行放行前的逻辑,然后再执行放行操作。而由于我们当前是基于springboot开发的,所以放行之后是进入到了spring的环境当中,也就是要来访问我们所定义的controller当中的接口方法。
-
Tomcat并不识别所编写的Controller程序,但是它识别Servlet程序,所以在Spring的Web环境中提供了一个非常核心的Servlet:DispatcherServlet(前端控制器),所有请求都会先进行到DispatcherServlet,再将请求转给Controller。
-
当我们定义了拦截器后,会在执行Controller的方法之前,请求被拦截器拦截住。执行
preHandle()
方法,这个方法执行完成后需要返回一个布尔类型的值,如果返回true,就表示放行本次操作,才会继续访问controller中的方法;如果返回false,则不会放行(controller中的方法也不会执行)。 -
在controller当中的方法执行完毕之后,再回过来执行
postHandle()
这个方法以及afterCompletion()
方法,然后再返回给DispatcherServlet,最终再来执行过滤器当中放行后的这一部分逻辑的逻辑。执行完毕之后,最终给浏览器响应数据。
相关文章:

SpringBootWeb登录认证
JWT令牌 JSON Web Token JSON Web Tokens - jwt.ioJSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signatur…...
vim编辑器的使用
删除当前行及以后的行 使用vim编辑器打开文件 vim xxx.txt删除指定行及后面所有行,光标定位到要删除的第一行,比如:删除第10行以后的数据,光标定位到11行,然后在命令模式下按dG...
深入理解Linux网络总结
1、内核如何接收网络包 1.1 RingBuffer到底是什么,RingBuffer为什么会丢包? 问:RingBuffer到底存在那一块,是如何被使用到的,真的就只是一个环形队列吗?RingBuffer内存是预先分配好的,还是随着…...
Python冷知识
Python作为一种广泛使用的编程语言,有许多功能和特性可能不为初学者或普通用户所熟知。以下是一些相对冷门但有趣的Python知识: 魔术方法:Python中有一些特殊的方法,通常以双下划线__开头和结尾,被称为魔术方法(或特殊方法)。例如,__init__用于初始化对象,__str__返回…...

Redis之内存管理过期、淘汰机制
1.Redis内存管理 我们的redis是一个内存型数据库,我们的数据也都是放在内存中的,内存是有限的空间,当数据满了之后,我们要怎么样继续保证redis的可用性呢?我们就需要采取点管理措施和机制来保证我们redis的可用性。 在redis.co…...

金融科技赋能跨境支付:便捷与安全并驾齐驱
一、引言 在全球经济一体化的背景下,跨境支付作为国际贸易和金融活动的重要组成部分,正迎来金融科技浪潮的洗礼。金融科技以其独特的创新性和颠覆性,正在重塑跨境支付市场的格局,使其更加便捷、高效且安全。本文旨在探讨金融科技如何助力跨境支付,实现便捷与安全并存,并…...

【康耐视国产案例】智能AI相机:深度解析DataMan 380大视野高速AI读码硬实力
随着读码器技术的不断更新迭代,大视野高速应用成为当前工业读码领域的关键发展方向。客户对大视野高速读码器的需求源于其能显著减少生产成本并提升工作效率。然而,大视野应用场景往往伴随着对多个条码的读取需求,这无疑增加了算法的处理负担…...

SQL实验 带函数查询和综合查询
一、实验目的 1.掌握Management Studio的使用。 2.掌握带函数查询和综合查询的使用。 二、实验内容及要求 1.统计年龄大于30岁的学生的人数。 --统计年龄大于30岁的学生的人数。SELECT COUNT(*) AS 人数FROM StudentWHERE (datepart(yea…...
【前端每日基础】day34——HTTP和HTTPS
HTTP(Hypertext Transfer Protocol)和HTTPS(Hypertext Transfer Protocol Secure)是互联网通信协议,用于在Web浏览器和Web服务器之间传输数据。以下是对HTTP和HTTPS的详细介绍: HTTP(Hypertext…...
go mongo 唯一索引创建
1. 登录mongo,创建数据库 mongosh -u $username -p $password use test 2. 查看集合索引 db.$collection_name.getIndexes() 为不存在的集合创建字段唯一索引 package mainimport ("context""fmt""log""time""go…...
微信小程序如何进行页面跳转
微信小程序中的页面跳转可以通过多种方式实现,以下是几种主要的跳转方式及其详细解释: wx.navigateTo 功能:保留当前页面,跳转到应用内的某个页面。特点: 可以在新页面使用wx.navigateBack返回原页面。每跳转一个新页…...

信息标记形式 (XML, JSON, YAML)
文章目录 🖥️介绍🖥️三种形式🏷️XML (Extensible Markup Language)🔖规范🔖注释🔖举例🔖其他 🏷️JSON (JavaScript Object Notation)🔖规范🔖注释&#x…...

C语言:学生成绩管理系统(含源代码)
一.功能 二.源代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NUM 100 typedef struct {char no[30];char name[10];char sex[10];char phone[20];float cyuyan;float computer;float datastruct; } *student, student1;typ…...

MySQL 导出导入的101个坑
最近接到一个业务自行运维的MySQL库迁移至标准化环境的需求,库不大,迁移方式也很简单,由开发用myqldump导出数据、DBA导入,但迁移过程坎坷十足,记录一下遇到的各项报错及后续迁移注意事项。 一、 概要 空间问题源与目…...

OpenCv之简单的人脸识别项目(人脸提取页面)
人脸识别 准备五、人脸提取页面1.导入所需的包2.设置窗口2.1定义窗口外观和大小2.2设置窗口背景2.2.1设置背景图片2.2.2创建label控件 3.定义单人脸提取脚本4.定义多人脸提取脚本5.创建一个退出对话框6.按钮设计6.1单人脸提取按钮6.2多人脸提取按钮6.3返回按钮 7.定义关键函数8…...

linux 内核映像差异介绍:vmlinux、zImage、zbImage、image、uImage等
一、背景 Linux内核是整个Linux操作系统的核心部分,它是一个负责与硬件直接交互的软件层,并且提供多种服务和接口,让用户程序能够方便地使用硬件资源。 当我们编译自定义内核时,可以将其生成为以下内核映像之一:vmli…...

【Linux-INPUT输入的子系统】
Linux-INPUT输入的子系统 ■ input 子系统简介■ input 驱动编写流程■ 事件类型 ■ ■ input 子系统简介 input 子系统就是管理输入的子系统, input 子系统分为 input 驱动层、 input 核心层、 input 事件处理层,最终给用户空间提供可访问的设备节点 …...

密码加密及验证
目录 为什么需要加密? 密码算法分类 对称密码算法 非对称密码算法 摘要算法 DigestUtils MD5在线解密工具原理 实现用户密码加密 代码实现 为什么需要加密? 在MySQL数据库中,我们常常需要对用户密码、身份证号、手机号码等敏感信息进…...

找出字符串中出现最多次数的字符以及出现的次数
str.charAt(i) 是JavaScript中获取字符串中特定位置字符的方法,表示获取当前的字符。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wi…...

如何看待央行买卖长期国债?
央行远比大家想象中的要渴求货币宽松。 引子 今年以来,有不少关于“央行买卖长期国债”的讨论,前些时候关注点在“买”,最近关注点在“卖”。 然而,市场上的讨论采用了十分粗糙和松散的“自然语言”,所以࿰…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...