SpringMVC:拦截器(12)
拦截器
- 1. 拦截器概念
- 2. 拦截器入门案例
- 2.1 环境准备
- 2.2 拦截器开发
- 步骤1: 创建拦截器类
- 步骤2: 配置拦截器类
- 步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描
- 步骤4: 简化SpringMvcSupport的编写
- 5 测试
- 3. 拦截器参数解析(了解)
- 3.1 前置处理方法
- 3.2 后置处理方法
- 3.3 完成处理方法
- 4. 拦截器链配置
1. 拦截器概念
(1) 浏览器发送一个请求会先到Tomcat的web服务器
(2) Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源
(3) 如果是静态资源,会直接到Tomcat的项目部署目录下去直接访问
(4) 如果是动态资源,就需要交给项目的后台代码进行处理
(5) 在找到具体的方法之前,我们可以去配置过滤器(可以配置多个Filter),按照顺序进行执行
(6) 然后进入到到中央处理器(SpringMVC中的内容),SpringMVC会根据配置的规则进行拦截
(7) 如果满足规则,则进行处理,找到其对应的controller类中的方法进行执行,完成后返回结果
(8) 如果不满足规则,则不进行处理
拦截器要做的事情:
- 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
- 作用:
- 在指定的方法调用前后执行预先设定的代码
- 阻止原始方法的执行
- 拦截器就是用来做增强
注意区分过滤器和拦截器:
- 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
- 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
2. 拦截器入门案例
2.1 环境准备
步骤1:创建一个Web的Maven项目
步骤2:在pom.xml中添加所需的jar包
<?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>org.example</groupId><artifactId>springMVC_12_interceptor</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>8080</port><path>/</path></configuration></plugin></plugins></build>
</project>
步骤3:编写Controller
package com.itheima.controller;import com.itheima.domain.Book;
import org.springframework.web.bind.annotation.*;/*** @Author Mr.Lu* @Date 2023/2/11 15:16* @ClassName BookController* @Version 1.0*/
@RestController
@RequestMapping("/books")
public class BookController {@PostMappingpublic String save(@RequestBody Book book){System.out.println("book save ..." + book);return "{'module':'book save'}";}@DeleteMapping("/{id}")public String delete(@PathVariable Integer id){System.out.println("book delete..." + id);return "{'module':'book delete'}";}@PutMappingpublic String update(@RequestBody Book book){System.out.println("book update ... " + book);return "{'module':'book update'}";}@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println("book getById ... " + id);return "{'module':'book getById'}";}@GetMappingpublic String getAll(){System.out.println("book getAll...");return "{'module':'book getAll'}";}
}
步骤4:创建模型类Book
package com.itheima.domain;/*** @Author Mr.Lu* @Date 2023/2/11 15:12* @ClassName Book* @Version 1.0*/
public class Book {private String name;private double price;public Book() {}public Book(String name, double proce) {this.name = name;this.price = proce;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getProce() {return price;}public void setProce(double proce) {this.price = proce;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", proce=" + price +'}';}
}
步骤5:创建对应的配置类
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
public class SpringMvcConfig {
}
package com.itheima.config;import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;import javax.servlet.Filter;public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {/*** 加载springmvc配置类** @return*/@Overrideprotected WebApplicationContext createServletApplicationContext() {AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();ctx.register(SpringMvcConfig.class);return ctx;}/*** 设置由springmvc控制器处理的请求映射路径** @return*/@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}/*** 加载spring配置类** @return*/@Overrideprotected WebApplicationContext createRootApplicationContext() {
// AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
// ctx.register(SpringConfig.class);
// return ctx;return null;}// 乱码处理@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");return new Filter[]{filter};}
}
2.2 拦截器开发
步骤1: 创建拦截器类
在com.itheima目录下面建一个interceptor包,在interceptor包下面建一个实现HandlerIntercepror接口的类,并重写里面的额三个方法。
注意: 拦截器中的preHandler
方法,如果返回true,则代表放行,会执行原始Controller类中要请求的方法,如果返回false,则代表拦截,后面的就不会再执行了。
当有拦截器后,请求会先进入preHandle方法,
-
如果方法返回true,则放行继续执行后面的handle[controller的方法]和后面的方法
-
如果返回false,则直接跳过后面方法的执行。
package com.itheima.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;// 定义拦截器类,实现HandlerInterceptor接口
// 注意当前类必须受Spring容器控制
@Component
public class ProjectInterceptor implements HandlerInterceptor {@Override// 原始方法调用前执行的内容public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle...");return true;}@Override// 原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...");}@Override// 原始方法调用完成后执行的内容public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...");}
}
步骤2: 配置拦截器类
在config目录下创建一个类来配置拦截器类
package com.itheima.config;import com.itheima.interceptor.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;/*** @Author Mr.Lu* @Date 2023/2/12 15:13* @ClassName SpringMvcSupport* @Version 1.0*/
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowired(required = false)private ProjectInterceptor projectInterceptor;// @Override
// protected void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
// }@Overrideprotected void addInterceptors(InterceptorRegistry registry) {// 配置拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*"); // 为可变参数,可以写几种路径}
}
步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描
@Configuration
@ComponentScan({"com.itheima.controller", "com.itheima.interceptor", "com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig {
}
步骤4: 简化SpringMvcSupport的编写
让SpringMvcConfig类实现WebMvcConfigurer接口。
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
// 实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {@Autowiredprivate ProjectInterceptor projectInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//配置多拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");}
}
5 测试
访问http://localhost:8080/books
访问http://localhost:8080/books/666
3. 拦截器参数解析(了解)
3.1 前置处理方法
原始方法之前运行preHandle
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {System.out.println("preHandle");return true;
}
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象,本质上是一个方法对象,对反射中的Method对象进行了再包装
3.2 后置处理方法
原始方法运行后运行,如果原始方法被拦截(前置方法返回false),则不执行
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception {System.out.println("postHandle");
}
modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整
3.3 完成处理方法
拦截器最后执行的方法,无论原始方法是否执行(只要前置方法返回true,那么完成处理方法就一定执行)
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) throws Exception {System.out.println("afterCompletion");
}
4. 拦截器链配置
步骤1:创建拦截器类:实现接口,并重写接口中的方法
拦截器2: ProjectInterceptor2
package com.itheima.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @Author Mr.Lu* @Date 2023/2/12 15:09* @ClassName ProjectInterceptor* @Version 1.0*/// 定义拦截器类,实现HandlerInterceptor接口
// 注意当前类必须受Spring容器控制
@Component
public class ProjectInterceptor2 implements HandlerInterceptor {@Override// 原始方法调用前执行的内容public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle...222");return true;}@Override// 原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...222");}@Override// 原始方法调用完成后执行的内容public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...222");}
}
拦截器3:ProjectInterceptor3
package com.itheima.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @Author Mr.Lu* @Date 2023/2/12 15:09* @ClassName ProjectInterceptor* @Version 1.0*/// 定义拦截器类,实现HandlerInterceptor接口
// 注意当前类必须受Spring容器控制
@Component
public class ProjectInterceptor3 implements HandlerInterceptor {@Override// 原始方法调用前执行的内容public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle...333");return true;}@Override// 原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...333");}@Override// 原始方法调用完成后执行的内容public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...333");}
}
步骤2:配置拦截器类
package com.itheima.config;import com.itheima.interceptor.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;/*** @Author Mr.Lu* @Date 2023/2/12 15:13* @ClassName SpringMvcSupport* @Version 1.0*/
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowired(required = false)private ProjectInterceptor projectInterceptor;@Autowired(required = false)private ProjectInterceptor2 projectInterceptor2;@Autowired(required = false)private ProjectInterceptor3 projectInterceptor3;// @Override
// protected void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
// }@Overrideprotected void addInterceptors(InterceptorRegistry registry) {// 配置拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");registry.addInterceptor(projectInterceptor2).addPathPatterns("/books", "/books/*");registry.addInterceptor(projectInterceptor3).addPathPatterns("/books", "/books/*");}
}
步骤3:运行程序,观察顺序
拦截器执行的顺序是和配置顺序有关,先进后出。
- 当配置多个拦截器时,形成拦截器链
- 拦截器链的运行顺序参照拦截器添加顺序为准
- 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
- 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作
注:
-
当ProjectInterceptor,ProjectInterceptor2,ProjectInterceptor3中的preHandle方法都返回true时,拦截器链执行顺序为:pre1, pre2, pre3, Controller, post3, post2, post1, after3, after2, after1.
-
当ProjectInterceptor,ProjectInterceptor2中的preHandle方法返回true,ProjectInterceptor3中的preHandle方法返回false时,拦截器链执行顺序为:pre1, pre2, pre3, after2, after1.
-
当ProjectInterceptor中的preHandle方法返回true,ProjectInterceptor2中的preHandle方法返回false时,拦截器链执行顺序为:pre1, pre2, after1.
-
当ProjectInterceptor中的preHandle方法返回false时,拦截器链执行顺序为:pre1
相关文章:

SpringMVC:拦截器(12)
拦截器1. 拦截器概念2. 拦截器入门案例2.1 环境准备2.2 拦截器开发步骤1: 创建拦截器类步骤2: 配置拦截器类步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描步骤4: 简化SpringMvcSupport的编写5 测试3. 拦截器参数解析(了解)3.1 前置处理…...

计算机网络3:HTTP1.0和HTTP1.1的区别
目录1. HTTP是什么2.HTTP1.0和HTTP1.1的区别3.名词解释(1)If-Modified-Since(IMS)、Expires(2)If-None-Match,Etag(3)If-Unmodified-Since1. HTTP是什么 超文本传输协议…...
Urho3D 编辑器说明
Urho3D编辑器是一个脚本应用程序,可以与Urho3D播放器应用程序一起运行。要开始,请执行以下任意命令:(在bin目录中)Editor.bat、Editor.sh或Urho3DPlayer Scripts/Editor.as Urho3D播放器应用程序支持的所有命令行选项…...

C++类基础(十一)
运算符重载(二) ● 对称运算符通常定义为非成员函数以支持首个操作数的类型转换 struct Str {int val 0;Str(int input): val(input){}auto operator(Str x){std::cout << "auto operator(Str x)\n";return Str(val x.val);} }; int …...

Windows安装系列:SVN Server服务
一、下载与安装 1、下载VisualSVN-Server-5.1.1-x64.msi 地址:Download | VisualSVN Server 2、找到最新版本SVN 5.1.1,直接双击它,弹出如下安装界面 3、点击Next 4、勾选我接受, 点击"Next" 5、默认选项,…...
快速傅里叶算法(FFT)快在哪里?
目录 前言 1、DFT算法 2、FFT算法 2.1 分类 2.2 以基2 DIT(时间抽取) FFT 算法为例 2.2.1 一次分解 2.2.2 多次分解 参考 前言 对信号分析的过程中,为了能换一个角度观察问题,很多时候需要把时域信号波形变换到频域进行分…...
利用Markdown写学术论文资料汇总贴
1是最详细的,重点看! Markdown 写作,Pandoc 转换:我的纯文本学术写作流程 2补充一些细节,也可以看看。 用Markdown写作学术论文 3写得和上面差不多,如果上面两篇有什么问题还没解决,可以看看…...

MySQL 高级查询
目录1.左关联2.右关联3.子查询4.联合查询5.分组查询1.左关联 MySQL中的左关联(Left Join)是一种基于共同列的连接操作, 它将左侧表中的所有行与右侧表中匹配的行结合在一起, 如果右侧表中没有匹配的行,则结果集中右侧…...

JavaSE学习day4_01 循环for,while,do...while
1. 循环高级 1.1 无限循环 for、while、do...while都有无限循环的写法。 最为常用的是while格式的。 因为无限循环是不知道循环次数的,所以用while格式的 代码示例: while(true){} 1.2 跳转控制语句(掌握) 跳转控制语句&…...
C/C++中的static关键字
概述在C/C中都有static关键字的使用,可以分别修饰变量和函数,分为静态变量【静态成员】、静态成员函数。2. static用法概况静态变量的作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0ÿ…...

67 自注意力【动手学深度学习v2】
67 自注意力【动手学深度学习v2】 深度学习学习笔记 学习视频:https://www.bilibili.com/video/BV19o4y1m7mo/?spm_id_fromautoNext&vd_source75dce036dc8244310435eaf03de4e330 给定长为n 的序列,每个xi为长为d的向量,自注意力将xi 既当…...

电子学会2022年12月青少年软件编程(图形化)等级考试试卷(二级)答案解析
青少年软件编程(图形化)等级考试试卷(二级) 一、单选题(共25题,共50分) 1. 一个骰子,从3个不同角度看过去的点数如图所示,请问5的对面是什么点数?( ) …...

关于链表中插入结点的操作……
服了,好久没敲链表了,这都忘了 newnode->next cur->next; cur->next newnode; newnode->next cur->next; cur->next newnode; newnode->next cur->next; cur->next newnode; newnode->next cur->next; cur-…...

【项目精选】百货中心供应链管理系统
点击下载源码 近年来,随着计算机技术的发展,以及信息化时代下企业对效率的需求,计算机技术与通信技术已经被越来越多地应用到各行各业中去。百货中心作为物流产业链中重要的一环,为了应对新兴消费方式的冲击,从供货到销…...

Qt优秀开源项目之十六:SQLite数据库管理系统—SQLiteStudio
首先,感谢CSDN官方认可 SQLiteStudio是一款开源、跨平台(Windows、Linux和MacOS)的SQLite数据库管理系统。 github地址:https://github.com/pawelsalawa/sqlitestudio 官网:https://sqlitestudio.pl/ 特性很多…...

Python __doc__属性:查看文档
在使用 dir() 函数和 __all__ 变量的基础上,虽然我们能知晓指定模块(或包)中所有可用的成员(变量、函数和类),比如:import string print(string.__all__)程序执行结果为:[ascii_lett…...

电子科技大学操作系统期末复习笔记(一):操作系统概述
目录 前言 操作系统概述 操作系统的目标与功能 操作系统的定义 目标 功能 操作系统的历史 单用户系统 简单批处理系统 多道批处理系统 分时系统 个人电脑 → 分布式系统 → 互联网时代 → 移动计算时代 → ...... 实时系统 操作系统的基本特征 并发 共享 虚拟…...
[实践篇]13.20 Qnx进程管理slm学习笔记(三)
【QNX Hypervisor 2.2用户手册】目录(完结) 4.2 模块 我们可以将组件组合成一个模块。模块中的进程可以组成一个子系统,也可以用于建立一组系统状态,例如基本操作和各种更高级别操作。注意,必须命名模块,以便可以在内部引用它们。而且每个模块必须描述成一个元素,形势如…...

冰冰学习笔记:多线程
欢迎各位大佬光临本文章!!! 还请各位大佬提出宝贵的意见,如发现文章错误请联系冰冰,冰冰一定会虚心接受,及时改正。 本系列文章为冰冰学习编程的学习笔记,如果对您也有帮助,还请各位…...

补充一些前端面试题
javascript有哪些库指路>js中的库uniapp和vue有什么区别什么是uniappuni-app(uni,读you ni,是统一的意思)是一个使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web&#…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

C++11 constexpr和字面类型:从入门到精通
文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...