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

SpringBoot3-web开发笔记(下)

内容协商

实现:一套系统适配多端数据返回

多端内容适配:

1. 默认规则

 SpringBoot 多端内容适配。

      基于请求头内容协商:(默认开启)

             客户端向服务端发送请求,携带HTTP标准的Accept请求头。

             Accept: application/json(要求返回json形式的数据)、text/xml、text/yaml

             服务端根据客户端请求头期望的数据类型进行动态返回

 基于请求参数内容协商:(需要开启)

      客户端发送参数时,携带一个format参数,其值就是我们要求的参数的形式

             发送请求 GET /projects/spring-boot?format=json

             匹配到 @GetMapping("/projects/spring-boot")

             根据参数协商,优先返回 json 类型数据【需要开启参数匹配设置】

             发送请求 GET /projects/spring-boot?format=xml,优先返回 xml 类型数据

代码举例:

Application.properties配置文件:

#使用参数进行内容协商

spring.mvc.contentnegotiation.favor-parameter=true

#自定义参数名,默认为format

spring.mvc.contentnegotiation.parameter-name=format

实体类

@Data

@JacksonXmlRootElement//可以写出xml文档

public class Person {

    private Integer id;

    private String username;

    private String email;

    private int age;

}

controller

@RestController

@Slf4j

public class HelloController {

    /**

     * @RequestBody默认对象以json形式返回

     * 想要返回xml形式的数据步骤:

     *      ①引入支持写出xml内容依赖:jackson-dataformat-xml

     *      ②在实体类加上注解  @JacksonXmlRootElement//可以写出xml文档

     *      ③可以 基于请求头内容协商或  基于请求参数内容协商 两种方式:要求返回xml/json形式的数据

     * @return

     */

    @GetMapping("/person")

    public Person person(){

        Person person = new Person();

        person.setId(1);

        person.setUsername("张三");

        person.setEmail("aaa@qq.com");

        person.setAge(19);

        return person;

    }

}

测试;

HttpMessageConverter原理(内容协商的底层原理)

希望返回yaml形式的数据

● HttpMessageConverter 怎么工作?合适工作?

通过定制 HttpMessageConverter  来实现多端内容协商

● 编写WebMvcConfigurer提供的configureMessageConverters底层,修改底层的MessageConverter

1. @ResponseBody由HttpMessageConverter处理

标注了@ResponseBody的返回值 将会由支持它的 HttpMessageConverter写给浏览器

   如果controller方法的返回值标注了 @ResponseBody 注解

    过程

            ①请求进来先来到DispatcherServlet的doDispatch()进行处理

            ② 找到一个 HandlerAdapter 适配器。利用适配器执行目标方法

            ③到RequestMappingHandlerAdapter来执行,调用invokeHandlerMethod()来执行目标方法

            ④目标方法执行之前,准备好两个东西

                  HandlerMethodArgumentResolver:参数解析器,确定目标方法每个参数值

                  HandlerMethodReturnValueHandler:返回值处理器,确定目标方法的返回值该怎么处理

          ⑤RequestMappingHandlerAdapter 里面的invokeAndHandle()(在invokeHandlerMethod()中调用此方法)真正执行目标方法

          目标方法执行完成,会返回返回值对象

          找到一个合适的返回值处理器 HandlerMethodReturnValueHandler(然后寻找合适的MessageConverter)

          最终找到 RequestResponseBodyMethodProcessor能处理 标注了 @ResponseBody注解的方法

           RequestResponseBodyMethodProcessor 调用writeWithMessageConverters ,利用MessageConverter把返回值写出去

上面解释:@ResponseBody由HttpMessageConverter处理

            HttpMessageConverter 会先进行内容协商

                 遍历所有的MessageConverter看谁支持这种内容类型的数据

 总结;@ResponseBody标注的方法最终会由MessaConverter进行内容协商写出去,系统中有什么MessageConverter(导那个依赖就有那个的MessageConverter)能处理,就用那个。

WebMvcAutoConfiguration提供几种默认HttpMessageConverters

● EnableWebMvcConfiguration通过 addDefaultHttpMessageConverters添加了默认的MessageConverter;如下:

  ○ ByteArrayHttpMessageConverter: 支持字节数据读写(将对象写成字节数组)

  ○ StringHttpMessageConverter: 支持字符串读写(写成字符串)

  ○ ResourceHttpMessageConverter:支持资源读写

  ○ ResourceRegionHttpMessageConverter: 支持分区资源写出

  ○ AllEncompassingFormHttpMessageConverter:支持表单xml/json读写

  ○ MappingJackson2HttpMessageConverter: 支持请求响应体Json读写

系统提供默认的MessageConverter 功能有限,仅用于json或者普通返回数据。额外增加新的内容协商功能,必须增加新的HttpMessageConverter

WebMvcAutoConfiguration

提供了很多默认设置。

判断系统中是否有响应的类,如果有就加入响应的HttpMessageConverter

增加yaml格式内容协商

    /**

     * 想要返回yaml格式的数据

     * 步骤:

     *  ①导入相应的包

     *      支持返回yaml格式的数据

     *         <dependency>

     *             <groupId>com.fasterxml.jackson.dataformat</groupId>

     *             <artifactId>jackson-dataformat-yaml</artifactId>

     *         </dependency>

     *  ② 在handler方法中通过mapper干涉(在底层,将返回值对象转成json形式,xml形式,yaml形式,... 都是由mapper来干涉的)

     *      创建mapper对象,并传入yaml工厂的对象new YAMLFactory()

     *           new ObjectMapper(new YAMLFactory());

     *      通过mapper调用writeValueAsString(person) ,传入要返回的对象,

     *      此字符串就是yaml格式的

     *  ③内容协商(告知系统,存在一种yaml格式)

     *    在application.properties中编写;

     *    #增加一种新的类型(返回对象的格式)

     *    #新格式的key--》yaml 新格式的value--》application/yaml(客户端发送请求指明返回对象格式的请求头Accept的值)

     *       spring.mvc.contentnegotiation.media-types.yaml=application/yaml

     *  ④在配置类中重写configureMessageConverters方法新增一个MessageConverter组件

             增加HttpMessageConverter组件,专门负责把对象写出为yaml格式      

         ⑤创建一个自定义的MessageConverter类

     *

     */

controller类

@RestController

@Slf4j

public class HelloController {

    @GetMapping("/person2")

    public String person2() throws JsonProcessingException {

        Person person = new Person();

        person.setId(1);

        person.setUsername("张三");

        person.setEmail("aaa@qq.com");

        person.setAge(19);

        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());//传入yaml工厂的对象new YAMLFactory()

        //在底层,将返回值对象转成json形式,xml形式,yaml形式,... 都是由mapper来干涉的

        String s = mapper.writeValueAsString(person);

        System.out.println(s);//------------------------②在handler方法中通过mapper干涉

        return s;

    }

}

Application.properties文件-----------------③内容协商(告知系统,存在一种yaml格式)

#增加一种新的类型(返回对象的格式)

#新格式的key--》yaml 新格式的value--》application/yaml(客户端发送请求指明返回对象格式的请求头Accept的值)

spring.mvc.contentnegotiation.media-types.yaml=application/yaml

配置类(手自一体模式)-----------------------④在配置类中重写configureMessageConverters方法新增一个MessageConverter组件

@Configuration//这是一个配置类

public class MyConfig implements WebMvcConfigurer {

    //配置能把对象转为yaml的messageConverter

    /**

     *通过converters.add()方法传入自定义的MessageConverter

     * @param converters

     */

    @Override

    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        converters.add(new MyYamlHttpMessageConverter());

    }

}

⑤自定义的MessageConverter

/**

 * 创建一个yaml的MessageConverter

 * 步骤:

 * ①继承AbstractHttpMessageConverter<泛型> 该泛型代表,可以将什么样的类型转化为我们自定义的格式

 * ②创建一个空参构造器在其中:

 *   1创建mapper对象,并传入yaml工厂的对象new YAMLFactory(),通过mapper干涉对象的格式转换

 *   2告诉SpringBoot这个MessageConverter支持那种媒体类型

 *      创建一个媒体类(MediaType)对象,传入type("application/text")与subtype(yaml),字符编码----------与配置类中定义的媒体类型名一致

 *      在构造器的首行传入调用super()传入MediaType对象

 * ③实现三个方法

 */

public class MyYamlHttpMessageConverter extends AbstractHttpMessageConverter<Object> {

    private ObjectMapper objectMapper= null;//把对象转成yaml

    public MyYamlHttpMessageConverter(){

        //告诉SpringBoot这个MessageConverter支持那种媒体类型

        super(new MediaType("application", "yaml",Charset.forName("UTF-8")));

        YAMLFactory factory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);

        this.objectMapper=new ObjectMapper(factory);

    }

    @Override

    protected boolean supports(Class<?> clazz) {

        //只要是对象类型,不是基本类型都支持转换

        return true;

    }

    /**

     *readInternal方法配合注解;@RequestBody

     * 把对象怎么读进来

     */

    @Override

    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {

        return null;

    }//读数据

    /**

     *writeInternal方法配合注解@ResponseBody

     * 把对象怎么写出去

     * methodReturnValue--------------方法的返回值

     * outputMessage---------------对应响应的输出流

     * 步骤:

     * ①通过outputMessage调用getBody()得到一个输出流------------body

     * ②通过mapper对象调用writeValue(body,methodReturnValue)方法,传入输出流body与methodReturnValue返回值对象

     * ③关闭输出流

     */

    @Override

    protected void writeInternal(Object methodReturnValue, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

        OutputStream body = outputMessage.getBody();//得到输出流

        try {

            this.objectMapper.writeValue(body,methodReturnValue);

        } finally {

          body.close();

        }

//        try(OutputStream os = outputMessage.getBody()){

//            this.objectMapper.writeValue(os,methodReturnValue);

//        }//------------------------try-with写法自动关流

    }

}

总结:

如何增加其他

● 配置媒体类型支持:

  ○ spring.mvc.contentnegotiation.media-types.yaml=text/yaml

● 编写对应的HttpMessageConverter,要告诉Boot这个支持的媒体类型

● 把MessageConverter组件加入到底层

  ○ 容器中放一个`WebMvcConfigurer` 组件,并配置底层的MessageConverter

web开发-Thymeleaf

模板引擎

● 由于 SpringBoot 使用了嵌入式 Servlet 容器。所以 JSP 默认是不能使用的。

● 如果需要服务端页面渲染,优先考虑使用 模板引擎。

模板引擎页面默认放在 src/main/resources/templates

SpringBoot 包含以下模板引擎的自动配置

● FreeMarker

● Groovy

● Thymeleaf

● Mustache

Thymelea整合

自动配置原理

1. 开启了 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration 自动配置

2. 属性绑定在 ThymeleafProperties 中,对应配置文件 spring.thymeleaf 内容

3. 所有的模板页面默认在 classpath:/templates文件夹下

4. 默认效果

  a. 所有的模板页面在 classpath:/templates/下面找--------前缀

  b. 找后缀名为.html的页面

可以修改

spring.thymeleaf.prefix=前缀

spring.thymeleaf.suffix=后缀

#缓存的开启与关闭(默认时true开启的)

#推荐开发期间关闭,上线以后开启

spring.thymeleaf.cache=false

步骤:

①导入依赖

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

②handler方法中利用模板引擎跳转到指定页面

     * 1,由共享数据,将需要给页面共享的数据放到model中

     *       model调用addAttribute("msg",name)传入接收参数的变量名与参数

     *       页面:<span th:text="${msg}"></span>     ${}利用模板字符串

     * 2,直接返回页面的地址(去掉前缀与后缀),实现跳转

     * @return

     *          * 模板的逻辑视图名

     *          * 物理视图=前缀+逻辑视图名+后缀

     *          * 真实地址=classpath:/templates/welcome.html

测试代码

controller类

@Controller//适配服务端渲染 前后端不分离模式

public class WelcomeController {

    /**

     * 利用模板引擎跳转到指定页面

     * ①由共享数据,将需要给页面共享的数据放到model中

     *       model调用addAttribute("msg",name)传入接收参数的变量名与参数

     *       页面:<span th:text="${msg}"></span>     ${}利用模板字符串

     * ②直接返回页面的地址(去掉前缀与后缀),实现跳转

     * @return

     *          * 模板的逻辑视图名

     *          * 物理视图=前缀+逻辑视图名+后缀

     *          * 真实地址=classpath:/templates/welcome.html

     */

    @GetMapping("/well")

    public String hello(@RequestParam("name") String name, Model model){

        model.addAttribute("msg",name);

        return "welcome";

    }

}

核心用法

th:xxx:动态渲染指定的 html 标签属性值、或者th指令(遍历、判断等)

● th:text:标签体内文本值渲染

  ○ th:utext:不会转义,显示为html原本的样子。

● th:属性:标签指定属性渲染

● th:attr:标签任意属性渲染

● th:ifth:each...:其他th指令

代码举例:html文件

<body>

<h1>你好: <span th:text="${msg}"></span></h1>

<hr>

th:任意html属性;实现动态替换任意属性的值

th:text   替换标签体的内容 (哈哈被替换为msg的内容)---------------不会识别html的标签,会将html标签转义

th:utext   替换标签体的内容----------------会识别html的标签

<h1 th:text="${msg}">哈哈</h1>

<h1 th:utext="${msg}">呵呵</h1>

th:src    动态的路径

<img th:src="${imgUrl}" style="width:300px"/>

th:attr      任意属性指定(所有的属性都可以从attr中动态取出)

<img th:attr="src=${imgUrl},style=${style}"/>

th:其他指令

<img th:src="${imgUrl}" th:if="${show}"/>

</body>

表达式:用来动态取值

● ${}:变量取值;使用model共享给页面的值都直接用${}

● @{}:url路径;(自动处理应用上下文路径,支持绝对相对路径,动态拼接参数)

举例:

@{} 专门用来去各种路径

<img th:src="@{${imgUrl}}" th:if="${show}"/>

● #{}:国际化消息

● ~{}:片段引用

● *{}:变量选择:需要配合th:object绑定对象

系统工具&内置对象

● param:请求参数对象

● session:session对象

● application:application对象

● #execInfo:模板执行信息

● #messages:国际化消息

● #uris:uri/url工具

● #conversions:类型转换工具

● #dates:日期工具,是java.util.Date对象的工具类

● #calendars:类似#dates,只不过是java.util.Calendar对象的工具类

● #temporals: JDK8+ java.time API 工具类

● #numbers:数字操作工具

● #strings:字符串操作

● #objects:对象操作

● #bools:bool操作

● #arrays:array工具

● #lists:list工具

● #sets:set工具

● #maps:map工具

● #aggregates:集合聚合工具(sum、avg)

● #ids:id生成工具

代码举例:

转大写:<h1 th:text="${#strings.toUpperCase(msg)}">哈哈</h1>

语法示例

表达式:

● 变量取值:${...}

● url 取值:@{...}

● 国际化消息:#{...}

● 变量选择:*{...}

● 片段引用: ~{...}

常见:

● 文本: 'one text','another one!',...

● 数字: 0,34,3.0,12.3,...

● 布尔:true、false

● null: null

● 变量名: one,sometext,main...

文本操作:

● 拼串: +

● 文本替换:| The name is ${name} |

举例:

拼接操作 | |代表要进行拼接操作

<h1 th:text="${'前缀'+msg+'后缀'}">哈哈</h1>

<h1 th:text="|前缀:${msg} 后缀|">哈哈</h1>

布尔操作:

● 二进制运算: and,or

● 取反:!,not

比较运算:

● 比较:>,<,<=,>=(gt,lt,ge,le)

● 等值运算:==,!=(eq,ne)

条件运算:

● if-then: (if)?(then)

● if-then-else: (if)?(then):(else)

● default: (value)?:(defaultValue)

Thymeleaf遍历

遍历语法:  th:each="元素名,迭代状态 : ${集合}"

迭代状态 有以下属性:

● index:当前遍历元素的索引,从0开始

● count:当前遍历元素的索引,从1开始

● size:需要遍历元素的总数量

● current:当前正在遍历的元素对象

● even/odd:是否偶数/奇数行

● first:是否第一个元素

● last:是否最后一个元素

Thymeleaf判断

th:if

如果if中的语句为true,渲染该元素,否完全移除(不会生成空标签)

th:switch

行内写法:[[...]] or [(...)]

代码举例:

controller类

@Controller//适配服务端渲染 前后端不分离模式

public class WelcomeController {

    @GetMapping("/list")

    public String list(Model model){

        List<Person> list = Arrays.asList(

                new Person(1, "张三1", "zsl@qq.com", 15),

                new Person(1, "张三2", "zsl@qq.com", 15),

                new Person(1, "张三3", "zsl@qq.com", 15),

                new Person(1, "张三4", "zsl@qq.com", 15),

                new Person(1, "张三5", "zsl@qq.com", 15)

                );

        model.addAttribute("persons",list);//与页面共享数据

        return "list";

    }

}

List.html文件

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="UTF-8">

    <title>Title</title>

</head>

<body>

<table>

<thead>

  <tr>

     <th>id</th>

     <th>username</th>

     <th>email</th>

     <th>age</th>

     <th>状态索引</th>

  </tr>

</thead>

  <tbody>

  <tr th:each="person,stats : ${persons}">

    <!--    行内写法:[[...]] or [(...)]-->

    <th>[[${person.id}]]</th>

    <th th:text="${person.username}"></th>

<!--    判断语法-->

    <!--th:if-->

    <th th:if="${#strings.isEmpty(person.email)}" th:text="联系不上"></th>

    <th th:if="not ${#strings.isEmpty(person.email)}" th:text="${person.email}"></th>

    <!-- 三目运算符   <th th:text="|${person.age}-${person.age>=18? '成年':'未成年'}|"></th>-->

    <!--    th:switch-->

    <th th:switch="${person.age}">

      <button th:case="15">未成年</button>

      <button th:case="16">未成年</button>

      <button th:case="17">未成年</button>

      <button th:case="18">成年</button>

      <button th:case="19">成年</button>

    </th>

    <th th:text="${stats.index}"></th>

  </tr>

  </tbody>

</table>

</body>

</html>

属性优先级

Order

        Feature        

Attributes

1        

片段包含        

th:insert th:replace

2        

遍历        

th:each

3        

判断        

th:if th:unless th:switch th:case

4        

定义本地变量

th:object th:with

5        

通用方式属性修改        

th:attr th:attrprepend th:attrappend

6        

指定属性修改        

th:value th:href th:src ...

7        

文本值

th:text th:utext

8        

片段指定        

th:fragment

9        

片段移除        

th:remove

片段包含>遍历>判断

变量选择

<div th:object="${session.user}">

  <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>

  <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>

  <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>

</div>

等同于

<div>

  <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>

  <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>

  <p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>

</div

 模板布局

(把公共的部分抽取出来,在别的页面可以引用)

● 定义模板: th:fragment="片段名"

● 引用模板:~{templatename::selector}即 ~{模板名:: 片段名}

● 插入模板:th:insert、th:replace="~{模板名:: 片段名}"

代码举例

写在footer.html文件中的公共部分

<footer th:fragment="copy">&copy; 2011 The Good Thymes Virtual Grocery</footer>

其他文件引用公共部分

引用格式: ~{模板名:: 片段名}

<body>

  <div th:insert="~{footer :: copy}"></div>

  <div th:replace="~{footer :: copy}"></div>

</body>

<body>

  结果:

  <body>

    <div>

      <footer>&copy; 2011 The Good Thymes Virtual Grocery</footer>

    </div>

    <footer>&copy; 2011 The Good Thymes Virtual Grocery</footer>

  </body>

</body>

 Devtools使用

(修改.xml文件,浏览器显示的内容立即同步更新)

当修改Thymeleaf模板文件(.html)时:

自动更新加载

即时生效,刷新浏览器即可看到更改

java代码的修改,如果devtools热启动了,可能会引起一些bug,难以排查

使用:

①导入依赖

      <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-devtools</artifactId>

      </dependency>

②修改完.xml文件后要ctrl+f9刷新

 

相关文章:

SpringBoot3-web开发笔记(下)

内容协商 实现&#xff1a;一套系统适配多端数据返回 多端内容适配&#xff1a; 1. 默认规则 SpringBoot 多端内容适配。 基于请求头内容协商&#xff1a;&#xff08;默认开启&#xff09; 客户端向服务端发送请求&#xff0c;携带HTTP标准的Accept请求头。 Accept: applica…...

关于无线网络安全的基础知识,涵盖常见威胁、防护措施和实用建议

无线网络(WiFi)的普及极大地方便了我们的生活,但其开放性也带来了诸多安全隐患。以下是关于无线网络安全的基础知识,涵盖常见威胁、防护措施和实用建议: 一、无线网络常见安全威胁 窃听(Eavesdropping) 攻击者通过监听无线信号,截获未加密的数据(如登录密码、聊天记录…...

《基于 RNN 的股票预测模型代码优化:从重塑到直接可视化》

在深度学习领域&#xff0c;使用循环神经网络&#xff08;RNN&#xff09;进行股票价格预测是一个常见且具有挑战性的任务。本文将围绕一段基于 RNN 的股票预测代码的改动前后差别展开&#xff0c;深入剖析代码的优化思路和效果。 原始代码思路与问题 原始代码实现了一个完整…...

【leetcode刷题日记】lc.347-前 K 个高频元素

目录 1.题目 2.代码 1.题目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2]示例 2: 输入: nums [1], k 1 输出: [1] 提示&#xff1a; 1 <…...

进程I·介绍、查看、创建与状态

目录 介绍 PCB&#xff08;进程控制块&#xff09; task_struct 查看、创建进程 进程状态 小知识 介绍 进程&#xff1a;PCB&#xff08;process control block&#xff09;&#xff08;内核数据结构&#xff09; 代码和数据 进程创建&#xff1a;操作系统将其相关属性信…...

[k8s]随笔- spec内容整理

面对 Kubernetes 中 spec 字段的复杂性&#xff0c;关键在于建立 层次化的分类逻辑 和 功能导向的归纳方法。以下是具体的规整思路和实践步骤&#xff0c;帮助你理清脉络、高效使用&#xff1a; 一、按资源类型分层&#xff1a;先分“大类”&#xff0c;再钻“细节” K8s 资源…...

程序化广告行业(81/89):行业术语解析与日常交流词汇指南

程序化广告行业&#xff08;81/89&#xff09;&#xff1a;行业术语解析与日常交流词汇指南 在程序化广告这个不断发展的行业中&#xff0c;持续学习和知识共享是我们紧跟潮流、提升能力的关键。一直以来&#xff0c;我都希望能和大家一起探索这个领域&#xff0c;共同进步。今…...

层归一化(Layer Normalization) vs 批量归一化(Batch Normalization)

层归一化和批量归一化都是 归一化方法,目的是让训练更稳定、收敛更快,但应用场景和工作方式大不相同。 名称一句话解释BatchNorm对 同一通道、不同样本之间 做归一化,适合图像任务,依赖 Batch Size。LayerNorm对 每个样本自身所有特征维度 做归一化,适合序列任务,不依赖 …...

【杂谈】-开源 AI 的复兴:Llama 4 引领潮流

开源 AI 的复兴&#xff1a;Llama 4 引领潮流 文章目录 开源 AI 的复兴&#xff1a;Llama 4 引领潮流一、Llama 4&#xff1a;开源 AI 的挑战者二、真实利他还是战略布局&#xff1f;三、对开发者、企业和人工智能未来的启示 在过去的几年里&#xff0c;AI 领域发生了重大转变。…...

instructor 库实现缓存

目录 代码代码解释1. 基础设置2. 客户端初始化3. 数据模型定义4. 缓存设置5. 缓存装饰器6. 示例函数工作流程 示例类似例子 代码 import functools import inspect import instructor import diskcachefrom openai import OpenAI, AsyncOpenAI from pydantic import BaseModel…...

【日志链路】⭐️SpringBoot 整合 TraceId 日志链路追踪!

&#x1f4a5;&#x1f4a5;✈️✈️欢迎阅读本文章❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;本篇文章阅读大约耗时6分钟。 ⛳️motto&#xff1a;不积跬步、无以千里 &#x1f4cb;&#x1f4cb;&#x1f4cb;本文目录如下&#xff1a;&#x1f381;&#x1f381;&am…...

QT6 源(16):存储 QT 里元对象的类信息的类 QMetaClassInfo 的类,只有两个成员函数 name()、value(),比元对象属性简单多了

&#xff08;1&#xff09;所在头文件 qmetaobject.h &#xff1a; class Q_CORE_EXPORT QMetaClassInfo { private: //private 属性里包含了至关重要的数据成员的定义&#xff0c;放前面struct Data {enum { Size 2 };const uint * d; //包含了数组的起始地址uint name ()…...

deskflow使用教程:一个可以让两台电脑鼠标键盘截图剪贴板共同使用的开源项目

首先去开源网站下载&#xff1a;Release v1.21.2 deskflow/deskflow 两台电脑都要下载这个文件 下载好后直接打开找到你想要的exe desflow.exe 然后你打开他&#xff0c;将两台电脑的TLS都关掉 下面步骤两台电脑都要完成&#xff1a; 电脑点开edit-》preferences 把这个取…...

波束形成(BF)从算法仿真到工程源码实现-第六节-广义旁瓣消除算法(GSC)

一、概述 本节我们讨论广义旁瓣消除算法(GSC)&#xff0c;包括原理分析及代码实现。 更多资料和代码可以进入https://t.zsxq.com/qgmoN &#xff0c;同时欢迎大家提出宝贵的建议&#xff0c;以共同探讨学习。 二、原理分析 广义旁瓣消除(GSC)算法 GSC算法是与LCMV算法等效的&…...

企业数字化转型需要注重的深层维度:生成式AI时代的战略重构

企业数字化转型正在经历从"技术适配"到"基因重组"的质变。生成式AI技术的突破性发展,要求企业超越传统信息化框架,构建全新的数字化转型认知体系。本文将从战略认知、技术融合、组织进化、伦理治理、生态协作五个维度,系统解构企业数字化转型需注重的核…...

图论之并查集——含例题

目录 介绍 秩是什么 例子——快速入门 例题 使用路径压缩&#xff0c;不使用秩合并 使用路径压缩和秩合并 无向图和有向图 介绍 并查集是一种用于 处理不相交集合的合并与查询问题的数据结构。它主要涉及以下基本概念和操作&#xff1a; 基本概念&#xff1a; 集合&…...

解释型语言和编译型语言的区别

Python 的执行过程通常涉及字节码&#xff0c;而不是直接将代码编译为机器码。以下是详细的解释&#xff1a; ### **Python 的执行过程** 1. **源代码到字节码**&#xff1a; - Python 源代码&#xff08;.py 文件&#xff09;首先被编译为字节码&#xff08;.pyc 文件&…...

零基础上手Python数据分析 (14):DataFrame 数据分组与聚合 - 玩转数据透视,从明细到洞察

写在前面 —— 像搭积木一样分析数据,掌握Pandas GroupBy,轻松实现分组统计与聚合 回顾一下,上篇博客我们学习了如何使用 Pandas 合并与连接多个 DataFrame,将分散的数据整合到一起。 现在,我们拥有了更完整、更丰富的数据视图。 接下来,一个非常常见的分析需求就是 对…...

Honor of Kings (S39) 13-win streak

Honor of Kings (S39) 13-win streak S39赛季13连胜&#xff0c;庄周&#xff0c;廉颇硬辅助&#xff0c;对面有回血就先出红莲斗盆&#xff0c;有遇到马克没带净化的&#xff0c;出【冰霜冲击】破他大招 S39&#xff0c;庄周廉颇前排硬辅助全肉全堆血13连胜_哔哩哔哩bilibi…...

输出流-----超级详细的在程序中向文件.txt中写入内容

1.使用Fileoutputstream对象&#xff0c;如果在目录中已经存在该文件&#xff0c;那么将不会在创建&#xff0c;如果该目录中没有该文件&#xff0c;那么将会自动创建文件。 2.在目录中a.txt文件中写入一个h字符&#xff0c;这种方式是写入单个字符。 //在目录中a.txt文件中写入…...

【Mysql】死锁问题详解

【Mysql】死锁问题详解 【一】Mysql中锁分类和加锁情况【1】按锁的粒度分类&#xff08;1&#xff09;全局锁&#xff08;2&#xff09;表级锁1、表共享读锁&#xff08;Table Read Lock&#xff09;2、表独占写锁&#xff08;Table Write Lock&#xff09;3、元数据锁&#xf…...

C语言实现用户管理系统

以下是一个简单的C语言用户管理系统示例&#xff0c;它实现了用户信息的添加、删除、修改和查询功能。代码中包含了详细的注释和解释&#xff0c;帮助你理解每个部分的作用。 #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAX_USERS…...

SAP BDC:企业数据管理的新纪元

2025年4月&#xff0c;SAP在纽约发布了其全新企业数据平台——Business Data Cloud&#xff08;BDC&#xff09;&#xff0c;标志着企业数据管理和AI集成战略的重大升级。BDC不仅整合了SAP内部和外部的结构化与非结构化数据&#xff0c;还借助与Databricks的合作&#xff0c;推…...

数学建模学习资料免费分享:历年赛题与优秀论文、算法课程、数学软件等

本文介绍并分享自己当初准备数学建模比赛时&#xff0c;收集的所有资料&#xff0c;包括历年赛题与论文、排版模板、算法讲解课程与书籍、评分标准、数学建模软件等各类资料。 最近&#xff0c;准备将自己在学习过程中&#xff0c;到处收集到的各类资料都整理一下&#xff0c;并…...

计算机的运算方式

1. 计算机运算的基本概念 计算机的运算由 算术逻辑单元&#xff08;ALU&#xff09; 执行&#xff0c;其核心功能是完成 算术运算 和 逻辑运算。所有运算均基于二进制编码&#xff0c;通过硬件电路实现高速计算。 运算对象&#xff1a;二进制数&#xff08;定点数、浮点数&am…...

Tkinter事件与绑定

在Tkinter中,事件和事件绑定是实现用户交互的核心机制。通过事件机制,您可以捕捉用户的操作(例如鼠标点击、键盘输入等)并执行相应的回调函数。事件绑定是将事件与处理该事件的函数(或方法)关联起来。掌握事件和绑定技术是开发交互式应用程序的关键。 5.1 事件概述 事件…...

CAD 像素点显示图片——CAD二次开发 OpenCV实现

效果如下&#xff1a; 部分代码如下&#xff1a; public class Opencv1{[CommandMethod("xx1")]public void Opencv(){Document doc Application.DocumentManager.MdiActiveDocument;Database db doc.Database;Editor ed doc.Editor;// 设置采样精度&#xff0c;这…...

即梦+剪映:三国演义变中国好声音制作详解!

最近在刷抖音时&#xff0c;发现这种电影人物唱歌视频比较火热&#xff0c;今天手把手教大家如何制作这种让电影人物唱歌的视频&#xff01; 一、素材准备 1、准备好视频或人物图片素材 这里需要准备一张人物截图或者电影视频片段&#xff0c;大家可以去各大视频网站找原始素…...

04-线程

一、线程的概念 1、进程是系统分配资源的最少单位,操作系统会为每一个进程分配一块虚拟内存空间&#xff01; 线程是系统调度最少的单位,操作系统分配时间片的过程&#xff0c;就是系统调度&#xff01; 线程也会占用时间片&#xff01; 2、线程的内存资源 线程的内存资源是…...

7.渐入佳境 -- 优雅的断开套接字连接

前言 本章将讨论如何优雅地断开相互连接的套接字。之前用的方法不够优雅是因为&#xff0c;我们是调用close或closesocket函数单方面断开连接的。 一、基于TCP的半关闭 TCP中的断开连接过程比建立连接过程更重要&#xff0c;因为连接过程中一般不会出现大的变数&#xff0c;…...

Django3 - 开启Django Hello World

一、开启Django Hello World 要学习Django首先需要了解Django的操作指令&#xff0c;了解了每个指令的作用&#xff0c;才能在MyDjango项目里编写Hello World网页&#xff0c;然后通过该网页我们可以简单了解Django的开发过程。 1.1 Django的操作指令 无论是创建项目还是创建项…...

JavaScript 基础特性

一、变量特性 1.1 变量提升 console.log(temp); // undefined&#xff08;变量提升但未初始化&#xff09; var temp hello; 现象&#xff1a;var声明的变量会提升至作用域顶部&#xff0c;但赋值不提升 建议&#xff1a;改用 let/const 避免变量提升问题 1.2 变量泄露 fo…...

MATLAB遇到内部问题,需要关闭,Crash Decoding : Disabled - No sandbox or build area path

1.故障界面 MATLAB运行时突然中断&#xff0c;停止运行。故障界面如图&#xff1a; MATLAB Log File: C:\Users\wei\AppData\Local\Temp\matlab_crash_dump.21720-1 ------------------------------------------------ MATLAB Log File -----------------------------------…...

L1-5 吉老师的回归

题目 L1-078 吉老师的回归&#xff08;15分&#xff09; 曾经在天梯赛大杀四方的吉老师决定回归天梯赛赛场啦&#xff01; 为了简化题目&#xff0c;我们不妨假设天梯赛的每道题目可以用一个不超过 500 的、只包括可打印符号的字符串描述出来&#xff0c;如&#xff1a;Probl…...

0413-多态、Object类方法、访问权限修饰符、装箱拆箱、128陷阱

1:A and A 2:A and A 3: A and D 4: B and A 5: B and A 6:A and D 7:B and A 8: B and A 9:A and D package 第四章对象和类;public class ForthThir {//多态&#xff1a;父类的引用指向子类的对象,只能调父类的方法和子类重写的方法&#xff0c;不能调子类独有的方法&…...

Kubernetes控制平面组件:APIServer 准入控制机制详解

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计&#xff08;一&#xff09;Kubernetes架构原则和对象设计&#xff08;二&#xff09;Kubernetes架构原则和对象设计&#xff08;三&#xff09;Kubernetes控…...

苍穹外卖day02

菜品相关接口开发 图片上传-阿里云OSS 依赖注入 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>${aliyun.sdk.oss}</version> </dependency> ​ 配置密钥 sky:alioss:end…...

SpringBoot 自定义输出控制台图标

对于控制台输出的这个图标大家都不陌生吧&#xff0c;不仅在SpringBoot中有这种图标&#xff0c;在docker 、 nginx 启动时都有自身独特的图标&#xff0c;这是怎么实现的呢。 需要利用一个网站生成 banner 图标&#xff08;首页-bootschool.net&#xff09;&#xff0c; 将图标…...

联想电脑开机出现Defalut Boot Device Missing or Boot Failed怎么办

目录 一、恢复bios默认设置 二、关机重启 三、“物理”方法 在图书馆敲代码时&#xff0c;去吃了午饭回来发现刚开机就出现了下图的问题&#xff08;崩溃&#xff09;&#xff0c;想起之前也发生过一次 这样的问题&#xff0c;现在把我用到的方法写在下面&#xff0c;可能对…...

CST1020.基于Spring Boot+Vue汽车租赁管理系统

计算机/JAVA毕业设计 【CST1020.基于Spring BootVue汽车租赁管理系统】 【项目介绍】 汽车租赁管理系统&#xff0c;基于 Spring Boot Vue 实现&#xff0c;功能丰富、界面精美 【业务模块】 客户管理&#xff1a;查询客户信息、根据条件精准检索、添加客户信息、身份证号校验…...

ArkTS基础语法:从声明到类型的深度解析

# ArkTS基础语法&#xff1a;从声明到类型的深度解析 在鸿蒙应用开发的领域中&#xff0c;ArkTS作为重要的编程语言&#xff0c;其基础语法是开发者们必须掌握的关键内容。今天&#xff0c;我们就围绕ArkTS的声明和类型相关知识展开深入探讨&#xff0c;帮助大家更好地理解和运…...

Day15:关于MySQL的编程技术——基础知识

前言&#xff1a;先创建一个练习的数据库和数据 1.创建数据库并创建数据表的基本结构 -- 创建练习数据库 CREATE DATABASE db_programming; USE db_programming;-- 创建员工表&#xff08;包含各种数据类型&#xff09; CREATE TABLE employees (emp_id INT PRIMARY KEY AUTO…...

wsl下编译eXosip和osip库(Ubuntu 22.04)

1.下载eXosip和osip osip下载路径 Index of /mirror/gnu.org/savannah/osip eXosip下载路径 Index of /nongnu/exosip 我选的osip和eXosip版本为 5.2.0 2.编译osip库 tar -zxvf libosip2-5.2.0.tar.gz cd libosip2-5.2.0 ./configure make make install 在编译…...

《轨道力学导论》——第九章:轨道确定与导航

第九章 轨道确定与导航 引言 轨道确定与导航是轨道力学中最为核心的实践领域之一&#xff0c;它将理论与实际应用紧密结合&#xff0c;解决了"我们在哪里"以及"我们将去向何方"这两个航天活动中最基本的问题。无论是地球轨道上的人造卫星、飞向深空的探测…...

几何与游标

在arcgis中,数据组织方式如下 数据库(datasets): 要素类(feature class): 几何(geometry) 属性(attribute) 元数据(metadata) 游标: 查询游标:用于对数据进行查询的游标 arcpy.da.SearchCursor() 作用&#xff1a;用于对数据进行只读查询操作。它可以帮助你逐行读取数据表或…...

【使用jenkins+docker自动化部署java项目】

背景: 有A(打包机129)&#xff0c;B(游戏服130) 2个机器&#xff0c;他们都安装有docker&#xff0c;请完成部署。 一、准备好java项目&#xff0c;写好Dockerfile # 基础镜像&#xff0c;使用包含 JDK 17 的 OpenJDK 镜像 FROM openjdk:17-jdk-slim# 设置工作目录 WORKDIR /…...

Vue3+Element Plus如何实现左树右表页面案例:即根据左边的树筛选右侧表功能实现

文章目录 一、最终效果二、源代码2.1 AddDataSource.vue2.2 LeftTree.vue2.3 FieldDrawer.vue2.4 RightTable.vue2.5 Emp.vue 三、代码解读3.1 AddDataSource.vue —— 数据源新增对话框3.2 LeftTree.vue —— 数据源树视图3.3 FieldDrawer.vue —— 字段详情抽屉3.4 RightTabl…...

Redisson的红锁,分段锁,公平锁,联锁。。。。。。

红锁&#xff1a;Redisson红锁可以防止主从集群锁丢失问题。Redisson红锁要求&#xff0c;必须要构建至少三个Redis主从集群&#xff0c;若一个请求要申请锁&#xff0c;必须向所有主从集群中提交key写入请求&#xff0c;只有当大多数集群&#xff08;过半集群&#xff09;锁写…...

system V 共享内存

system V是一种标准&#xff0c;linux内核支持这种标准&#xff0c;专门设计了一个ipc模板(通信的接口设计&#xff0c;原理&#xff0c;接口&#xff0c;相似性) 使用各自的虚拟地址访问物理内存 共享内存描述共享内存的内核数据结构它所对应的物理空间 进程间通信的本质&…...

ResNet改进(27):融合EfficientViT 高效混合网络设计

在计算机视觉领域,卷积神经网络(CNN)和视觉Transformer(ViT)各有优势。 今天分享的是一种将两者巧妙结合的方案——在ResNet18基础上引入轻量化ViT模块的设计思路。 整体架构概览 这个混合网络主要由三部分组成: ResNet18骨干网络:作为特征提取器,去掉了原模型的平均池化…...