spring mvc源码学习笔记之十一

  • pom.xml 内容如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.qs.demo</groupId><artifactId>test-011</artifactId><version>1.0.0</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.3.30.RELEASE</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring4</artifactId><version>3.0.11.RELEASE</version></dependency></dependencies></project>
  • src/main/webapp/WEB-INF/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_4_0.xsd"version="4.0"><servlet><servlet-name>app</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping><servlet-name>app</servlet-name><!-- / 表示除了 xxx.jsp 之外的所有请求 --><!-- /* 表示所有请求 --><url-pattern>/</url-pattern></servlet-mapping>
</web-app>
  • src/main/webapp/WEB-INF/app-servlet.xml 内容如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 这个文件的名字是有讲究的 --><!-- springmvc 的配置 --><mvc:annotation-driven/><!-- 开启组件扫描 --><context:component-scan base-package="com.qs.demo"/><!-- 配置视图解析器 --><bean id="thymeleafViewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver"><property name="characterEncoding" value="UTF-8"/><property name="order" value="1"/><property name="templateEngine"><bean class="org.thymeleaf.spring4.SpringTemplateEngine"><property name="templateResolver"><bean class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver"><property name="prefix" value="/WEB-INF/templates/"/><property name="suffix" value=".html"/><property name="templateMode" value="HTML"/><property name="characterEncoding" value="UTF-8"/></bean></property></bean></property></bean></beans>
  • src/main/webapp/WEB-INF/templates/t01.html 内容如下
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>t01</title>
</head>
<body>
<a th:href="@{/t02}">hello</a>
</body>
</html>
  • src/main/webapp/WEB-INF/templates/t02.html 内容如下
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>t01</title>
</head>
<body><h1>Peter</h1>
</body>
</html>
  • com.qs.demo.A_ControllerAdvice 内容如下
package com.qs.demo;import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;import java.beans.PropertyEditorSupport;
import java.util.Date;/*** @author qs* @date 2025/01/10*/
@ControllerAdvice(basePackages = "com.qs.demo.controller")
public class A_ControllerAdvice {@InitBinder({"time"})public void a(WebDataBinder webDataBinder) {webDataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() {@Overridepublic void setAsText(String text) throws IllegalArgumentException {setValue(new Date(Long.parseLong(text) / 1000));}});}}
  • com.qs.demo.controller.FirstController 内容如下
package com.qs.demo.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @author qs* @date 2024/12/20*/
@Controller
public class FirstController {@InitBinder({"date"})public void a(WebDataBinder webDataBinder) {webDataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() {@Overridepublic void setAsText(String text) throws IllegalArgumentException {setValue(new Date(Long.parseLong(text)));}});}@RequestMapping("/t01")public String t01() {return "t01";}@RequestMapping("/t02")public String t02() {return "t02";}@RequestMapping("/t03")@ResponseBodypublic String t03(@RequestParam Date date) {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);}@RequestMapping("/t04")@ResponseBodypublic String t04(@RequestParam Date time) {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);}}

以上就是全部代码。需要注意的是代码里边有跟本文无关的内容。本文只需要关注 /t03 和 /t04 这2个接口即可。

写这个例子,主要是为了讲解 @InitBinder 注解。
在例子中,我们展示了 @InitBinder 的两种用法:一种局部的(或者说本地的,此处的本地指的是controller内部)和一种全局的。
不管是本地的还是全局的,代码所做的事情都是我们编码中常见的将前端传过来的 long 格式的日期转换为 Java 中的Date。无非是这里为了区分,全局的 @InitBinder 对前端传过来的 long 格式的时间先除以1000然后转为 Date,而本地的 @InitBinder 则直接将前端传来的 long 格式的时间转换为 Date
当然,还有一个点需要注意,在全局的 @InitBinder 上,我们将它的 value 值设置为 {"time"} 意思是只转换名字为 time 的参数,对应的就是接口 /t04,同样的,本地的 @InitBindervalue 值是 {"date"} 意思是只转换名字为 date 的参数,对应的就是接口 /t03。

测试 /t03 接口

http://localhost:8080/test_011/t03?date=1736501024000

结果是

2025-01-10 17:23:44

测试 /t04 接口

http://localhost:8080/test_011/t04?time=1736501024000

结果是

1970-01-21 10:21:41

以上是对代码的解释,下面开始分析 @InitBinder 的源码

  • 第一点就是看 @InitBinder 这个注解是在哪里被解析的
@Overridepublic void afterPropertiesSet() {// Do this first, it may add ResponseBody advice beansSystem.out.println("这个方法仔细看");System.out.println("这个方法仔细看");System.out.println("这个方法仔细看");initControllerAdviceCache();if (this.argumentResolvers == null) {System.out.println("初始化默认的参数解析器");System.out.println("初始化默认的参数解析器");System.out.println("初始化默认的参数解析器");List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.initBinderArgumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.returnValueHandlers == null) {System.out.println("初始化默认的返回值处理器");System.out.println("初始化默认的返回值处理器");System.out.println("初始化默认的返回值处理器");List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);}}

上面的代码是 RequestMappingHandlerAdapter 中的 afterPropertiesSet 方法。我们只需要关注第一行的 initControllerAdviceCache();

private void initControllerAdviceCache() {if (getApplicationContext() == null) {return;}System.out.println("寻找 @ControllerAdvice 注解。");if (logger.isInfoEnabled()) {logger.info("Looking for @ControllerAdvice: " + getApplicationContext());}List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());AnnotationAwareOrderComparator.sort(adviceBeans);List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();for (ControllerAdviceBean adviceBean : adviceBeans) {Class<?> beanType = adviceBean.getBeanType();if (beanType == null) {throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);}Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);if (!attrMethods.isEmpty()) {this.modelAttributeAdviceCache.put(adviceBean, attrMethods);if (logger.isInfoEnabled()) {logger.info("Detected @ModelAttribute methods in " + adviceBean);}}Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);System.out.println("@InitBinder 方法有 " + binderMethods.size() + " 个");if (!binderMethods.isEmpty()) {this.initBinderAdviceCache.put(adviceBean, binderMethods);if (logger.isInfoEnabled()) {logger.info("在 ControllerAdviceBean ---> " + adviceBean+ " 中检测到了 @InitBinder 方法。 Detected @InitBinder methods in " + adviceBean);}}if (RequestBodyAdvice.class.isAssignableFrom(beanType)) {requestResponseBodyAdviceBeans.add(adviceBean);if (logger.isInfoEnabled()) {logger.info("Detected RequestBodyAdvice bean in " + adviceBean);}}if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {requestResponseBodyAdviceBeans.add(adviceBean);if (logger.isInfoEnabled()) {logger.info("Detected ResponseBodyAdvice bean in " + adviceBean);}}}if (!requestResponseBodyAdviceBeans.isEmpty()) {this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);}}

这里边我们只需要关注跟 @InitBinder 相关的部分。它所做的事情就是先找到被 @ControllerAdvice 注解标记的 bean,然后遍历这些 bean,找到被 @InitBinder 注解标记的方法,把这些方法缓存到成员变量 initBinderAdviceCache 里边。这其实就是全局的 @InitBinder 被解析的过程。

  • 接下来看本地的 InitBinder 是在哪里被解析的
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {System.out.println("获取数据绑定工厂 WebDataBinderFactory ");Class<?> handlerType = handlerMethod.getBeanType();Set<Method> methods = this.initBinderCache.get(handlerType);if (methods == null) {System.out.println("找标记了 InitBinder 注解的方法");System.out.println("找标记了 InitBinder 注解的方法");System.out.println("找标记了 InitBinder 注解的方法");methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);this.initBinderCache.put(handlerType, methods);}List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();// Global methods firstSystem.out.println("全局的 @InitBinder 方法优先");System.out.println("全局的 @InitBinder 方法优先");System.out.println("全局的 @InitBinder 方法优先");this.initBinderAdviceCache.forEach((clazz, methodSet) -> {if (clazz.isApplicableToBeanType(handlerType)) {Object bean = clazz.resolveBean();for (Method method : methodSet) {initBinderMethods.add(createInitBinderMethod(bean, method));}}});for (Method method : methods) {Object bean = handlerMethod.getBean();initBinderMethods.add(createInitBinderMethod(bean, method));}return createDataBinderFactory(initBinderMethods);}

上面的代码是 RequestMappingHandlerAdaptergetDataBinderFactory 方法。可以注意下这个方法的入参 HandlerMethod,也就是我们写的 controller 里边处理请求的方法。这段代码的逻辑就是先获取 HandlerMethod 所在的类,也就是我们的 controller 类,然后找 controller 类中的 @InitBinder 方法,把这些方法解析完了以后放到成员变量 initBinderCache 里边。

到这里,我们就知道不管是全局的 @InitBinder 还是本地的 @InitBinder ,最终都是在被解析后放到了 RequestMappingHandlerAdapter 的成员变量里边。

  • 第二点就是看 InitBinder 方法是在哪里被调用的
	/*** Initialize a WebDataBinder with {@code @InitBinder} methods.* If the {@code @InitBinder} annotation specifies attributes names, it is* invoked only if the names include the target object name.* @throws Exception if one of the invoked @{@link InitBinder} methods fail.*/@Overridepublic void initBinder(WebDataBinder binder, NativeWebRequest request) throws Exception {System.out.println("循环调用所有 @InitBinder 方法");System.out.println("循环调用所有 @InitBinder 方法");for (InvocableHandlerMethod binderMethod : this.binderMethods) {if (isBinderMethodApplicable(binderMethod, binder)) {Object returnValue = binderMethod.invokeForRequest(request, null, binder);System.out.println("@InitBinder methods should return void ----> @InitBinder 方法应该返回 void");System.out.println("@InitBinder methods should return void ----> @InitBinder 方法应该返回 void");if (returnValue != null) {throw new IllegalStateException("@InitBinder methods should return void: " + binderMethod);}}}}

上面这段代码是 InitBinderDataBinderFactory 中的。它的逻辑就是遍历成员变量 binderMethods 并依次调用。关于这个成员变量是在哪里被赋值的,其实是在构造方法中

	public InitBinderDataBinderFactory(@Nullable List<InvocableHandlerMethod> binderMethods,@Nullable WebBindingInitializer initializer) {super(initializer);this.binderMethods = (binderMethods != null ? binderMethods : Collections.emptyList());}

而这个构造方法又被子类 ServletRequestDataBinderFactory 的构造方法调用了

	public ServletRequestDataBinderFactory(@Nullable List<InvocableHandlerMethod> binderMethods,@Nullable WebBindingInitializer initializer) {super(binderMethods, initializer);}

子类 ServletRequestDataBinderFactory 的构造方法又被 RequestMappingHandlerAdapter 调用了

	protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods)throws Exception {return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());}

调用的地方恰恰就是上面讲的 getDataBinderFactory 方法。

到这里,不要迷糊,只是追踪了 InitBinderDataBinderFactory 的成员变量 binderMethods 的赋值链路,并没有追踪 binderMethods 的调用链路。
直接说结论,binderMethods的是在参数解析的阶段被调用的,可以以 RequestResponseBodyMethodProcessorresolveArgument 为例看下

@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {parameter = parameter.nestedIfOptional();System.out.println("HttpMessageConverter 是在这里用的 ------");System.out.println("HttpMessageConverter 是在这里用的 ------");System.out.println("HttpMessageConverter 是在这里用的 ------");Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());System.out.println("获取参数对应的变量名");System.out.println("获取参数对应的变量名");String name = Conventions.getVariableNameForParameter(parameter);System.out.println("获取参数对应的变量名,得到的值是 " + name);if (binderFactory != null) {System.out.println("创建 WebDataBinder -----> 开始");WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);System.out.println("创建 WebDataBinder -----> 结束");if (arg != null) {// 参数校验是在这里做的// 参数校验是在这里做的// 参数校验是在这里做的System.out.println("----- 参数校验是在这里做的 ---- 开始");System.out.println("----- 参数校验是在这里做的 ---- 开始");System.out.println("----- 参数校验是在这里做的 ---- 开始");validateIfApplicable(binder, parameter);System.out.println("----- 参数校验是在这里做的 ---- 结束");if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {System.out.println("参数校验失败的话就抛出 MethodArgumentNotValidException 。");throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());}}if (mavContainer != null) {mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());}}return adaptArgumentIfNecessary(arg, parameter);
}

@InitBinder 方法就是在如下这段代码中被调用的

WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);

多说一嘴,方法的调用链很长,可以根据本文的线索自己追踪。还有一点,RequestMappingHandlerAdapter 是一个很重要的处理器适配器,需要深入仔细研究。

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

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

相关文章

泛目录和泛站有什么差别

啥是 SEO 泛目录&#xff1f; 咱先来说说 SEO 泛目录是啥。想象一下&#xff0c;你有一个巨大的图书馆&#xff0c;里面的书架上摆满了各种各样的书&#xff0c;每一本书都代表着一个网页。而 SEO 泛目录呢&#xff0c;就像是一个超级图书管理员&#xff0c;它的任务就是把这些…

WebScoket-服务器客户端双向通信

文章目录 1. 消息推送常用方式介绍2. WebSocket2.1 介绍2.2 客户端API2.3 服务端API 3. 总结 1. 消息推送常用方式介绍 轮询 浏览器以指定的时间间隔向服务器发出HTTP请求&#xff0c;服务器实时返回数据给浏览器。 长轮询 浏览器发出ajax请求&#xff0c;服务器端接收到请求…

uniapp 之 uni-forms校验提示【提交的字段[‘xxx‘]在数据库中并不存在】解决方案

目录 场景问题代码结果问题剖析解决方案 场景 uni-forms官方组件地址 使用uniapp官方提供的组件&#xff0c;某个表单需求&#xff0c;单位性质字段如果是高校&#xff0c;那么工作单位则是高校的下拉选择格式&#xff0c;单位性质如果是其他的类型&#xff0c;工作单位则是手动…

SOME/IP 协议详解——服务发现

文章目录 1. Introduction &#xff08;引言&#xff09;2. SOME/IP Service Discovery (SOME/IP-SD)2.1 General&#xff08;概述)2.2 SOME/IP-SD Message Format2.2.1 通用要求2.2.2 SOME/IP-SD Header2.2.3 Entry Format2.2.4 Options Format2.2.4.1 配置选项&#xff08;Co…

探秘 JMeter (Interleave Controller)交错控制器:解锁性能测试的隐藏密码

嘿&#xff0c;小伙伴们&#xff01;今天咱们要把 JMeter 里超厉害的 Interleave Controller&#xff08;交错控制器&#xff09;研究个透&#xff0c;让你从新手直接进阶成高手&#xff0c;轻松拿捏各种性能测试难题&#xff01; 一、Interleave Controller 深度剖析 所属家族…

C++内存泄露排查

内存泄漏是指程序动态分配的内存未能及时释放&#xff0c;导致系统内存逐渐耗尽&#xff0c;最终可能造成程序崩溃或性能下降。在C中&#xff0c;内存泄漏通常发生在使用new或malloc等分配内存的操作时&#xff0c;但没有正确地使用delete或free来释放这块内存。 在日常开发过程…

rk3568 , buildroot , qt ,使用sqlite, 动态库, 静态库

问题说明&#xff1a; 客户反馈 &#xff0c;buildroot 系统 &#xff0c;使用qt 使用sqlite &#xff0c;有报错&#xff0c;无法使用sqlite. 测试情况说明&#xff1a; 我自己测试&#xff0c;发现&#xff0c; buildroot 自己默认就是 使能了 sqlite 的。 是否解决说明&…

5、波分复用 WDM

这是一张波分复用&#xff08;WDM&#xff09;系统原理示意图&#xff0c;以下是对各部分的详细解析&#xff1a; 业务站&#xff08;OTM&#xff09;部分 光波长转换单元&#xff08;OTU&#xff09;&#xff1a; 图中标注为①&#xff0c;多个 OTU 是波分复用系统的信号源。它…

Spring bean的生命周期和扩展

接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客&#xff0c;以具体实例看bean生命周期的一些执行阶段 bean生命周期流程 生命周期扩展处理说明实例化:createBeanInstance 构造方法&#xff0c; 如Autowired的构造方法注入依赖bean 如UserSer…

【Rust】引用与借用

目录 思维导图 1. 引用与借用的基本概念 1.1. 引用示例 2. 借用的规则 2.1. 可变借用示例 2.2. 借用的限制 3. 引用的生命周期 思维导图 1. 引用与借用的基本概念 引用的定义&#xff1a;引用是一种指向数据的指针&#xff0c;但与裸指针不同&#xff0c;Rust的引用在编…

Java内存与缓存

Java内存管理和缓存机制是构建高性能应用程序的关键要素。它们之间既有联系又有区别&#xff0c;理解这两者对于优化Java应用至关重要。 Java 内存模型 Java内存模型&#xff08;JMM&#xff09;定义了线程如何以及何时可以看到其他线程修改过的共享变量的值&#xff0c;并且规…

java项目之智慧农贸信息化管理平台(ssm+mybatis+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的码农一枚。今天要和大家聊的是一款基于ssm的智慧农贸信息化管理平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 智慧农贸信息化管理平台…

java人脸识别

文章目录 前言 为什么选择虹软呢&#xff1f; 注册虹软账号&#xff0c;下载SDK 将jar包安装到maven本地仓库 项目实战 导入jar包 编写配置文件 Service 编写测试类 人脸识别更多应用 前言 ‌虹软人脸识别技术‌是由虹软公司开发的一系列人脸识别技术&#xff0c;包括…

【学习路线】Python自动化运维 详细知识点学习路径(附学习资源)

学习本路线内容之前&#xff0c;请先学习Python的基础知识 其他路线&#xff1a; Python基础 >> Python进阶 >> Python爬虫 >> Python数据分析&#xff08;数据科学&#xff09; >> Python 算法&#xff08;人工智能&#xff09; >> Pyth…

Nginx代理同域名前后端分离项目的完整步骤

前后端分离项目&#xff0c;前后端共用一个域名。通过域名后的 url 前缀来区别前后端项目。 以 vue php 项目为例。直接上 server 模块的 nginx 配置。 server{ listen 80; #listen [::]:80 default_server ipv6onlyon; server_name demo.com;#二配置项目域名 index index.ht…

73.矩阵置零 python

矩阵置零 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解思路分析Python 实现代码代码解释提交结果 题目 题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例…

【深度学习】通俗理解偏差(Bias)与方差(Variance)

在统计学习中&#xff0c;我们通常使用方差与偏差来衡量一个模型 1. 方差与偏差的概念 偏差(Bais)&#xff1a; 预测值和真实值之间的误差 方差(Variance)&#xff1a; 预测值之间的离散程度 低偏差低方差、高偏差低方差&#xff1a; 图中每个点表示同一个模型每次采样出不同…

Git学习记录

针对各个项目的gitignore文件示例 github/gitignore: A collection of useful .gitignore templates 忽略文件 文件 .gitignore 的格式规范如下&#xff1a; • 所有空行或者以 &#xff03; 开头的行都会被 Git 忽略。 • 可以使用标准的 glob 模式匹配。 • 匹配模式…

自然语言转 SQL:通过 One API 将 llama3 模型部署在 Bytebase SQL 编辑器

使用 Open AI 兼容的 API&#xff0c;可以在 Bytebase SQL 编辑器中使用自然语言查询数据库。 出于数据安全的考虑&#xff0c;私有部署大语言模型是一个较好的选择 – 本文选择功能强大的开源模型 llama3。 由于 OpenAI 默认阻止出站流量&#xff0c;为了简化网络配置&#…

Cookie和Session

会话&#xff1a; 有状态会话&#xff1a; 客户端知道发起请求的是谁 无状态会话&#xff1a; 不知道发起请求的是谁 只知道有请求 http是无状态请求 保存会话信息的两种技术&#xff1a; 可以通过Cookie和Session储存会话信息 cookie&#xff1a;客户端技术 信心存…