Spring MVC 中的拦截器的使用“拦截器基本配置” 和 “拦截器高级配置”
1. Spring MVC 中的拦截器的使用“拦截器基本配置” 和 “拦截器高级配置”
@
2. 拦截器
拦截器(Interceptor) 类似于过滤器(Filter)
Spring MVC 的拦截器作用是在请求到达控制器之前或之后进行拦截,可以对请求和响应进行一些特定的处理。
拦截器可以用于很多场景下:
- 登录验证:对于需要登录才能访问的地址,使用拦截器可以判断用户是否已登录,如果未登录,则跳转到登录页面。
- 权限校验:根据用户权限对部分网址进行访问控制,拒绝未经授权的用户访问。
- 请求日志:记录请求信息,例如:请求地址,请求参数,请求时间等,用于排查问题和性能优化。
- 更改响应:可以对响应的内容进行修改,例如:添加头信息,调整响应内容格式等。
拦截器和过滤器的区别在于它们的作用层面不同:
- 过滤器更注重在请求和响应的流程中进行处理,可以修改请求和响应的内容,例如:设置编码和字符集,请求头,状态码等。
- 拦截器则更加侧重于对控制器进行前置或后置处理,在请求到达控制器之前或之后进行特定的操作,例如:打印日志,权限验证等。
Filter、Servlet、Interceptor、Controller的执行顺序:

3. Spring MVC 中的拦截器的创建和基本配置
3.1 定义拦截
实现org.springframework.web.servlet.HandlerInterceptor 接口,共有三个方法可以进行选择性的实现:

- preHandle( ):处理器方法调用之前执行。只有该方法有返回值,返回值是布尔类型,true 表示放行,false 表示拦截 。
- postHandle( ):处理器方法调用之后执行。
- afterCompletion( ):渲染完成后执行。
3.2 拦截器基本配置
第一步:编写拦截器,该拦截器要实现org.springframework.web.servlet.HandlerInterceptor 接口 。

package com.rainbowsea.springmvc.interceptors;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class Interceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Interceptor1's preHandle!");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor1's postHandle!");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Interceptor1's afterCompletion!");
}
}
在 Spring MVC 中拦截器的基本配置有两种方式:
- 第一种方式是:通过 xml 进行配置
- 第二种方式是:通过 @Component 注解 + xml 文件进行配置
第一种方式:通过 xml 进行配置
需要注意的是:这个基本配置,默认情况下是拦截所有请求的。
在 springmvc.xml 文件中进行如下配置:
<mvc:interceptors>
<bean class="com.powernode.springmvc.interceptors.Interceptor1"/>
</mvc:interceptors>

<?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/beans http://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/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 组件扫描-->
<context:component-scan
base-package="com.rainbowsea.springmvc.controller,com.rainbowsea.springmvc.interceptors"></context:component-scan>
<!-- 视图解析器-->
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
<!--作用于视图渲染的过程中,可以设置视图渲染后输出时采用的编码字符集-->
<property name="characterEncoding" value="UTF-8"/>
<!--如果配置多个视图解析器,它来决定优先使用哪个视图解析器,它的值越小优先级越高-->
<property name="order" value="1"/>
<!--当 ThymeleafViewResolver 渲染模板时,会使用该模板引擎来解析、编译和渲染模板-->
<property name="templateEngine">
<bean class="org.thymeleaf.spring6.SpringTemplateEngine">
<!--用于指定 Thymeleaf 模板引擎使用的模板解析器。模板解析器负责根据模板位置、模板资源名称、文件编码等信息,加载模板并对其进行解析-->
<property name="templateResolver">
<bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
<!--设置模板文件的位置(前缀)-->
<property name="prefix" value="/WEB-INF/templates/"/>
<!--设置模板文件后缀(后缀),Thymeleaf文件扩展名不一定是html,也可以是其他,例如txt,大部分都是html-->
<property name="suffix" value=".html"/>
<!--设置模板类型,例如:HTML,TEXT,JAVASCRIPT,CSS等-->
<property name="templateMode" value="HTML"/>
<!--用于模板文件在读取和解析过程中采用的编码字符集-->
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
<!-- 配置拦截器-->
<mvc:interceptors>
<!-- 基本配置,第一种方式
注意:基本配置,默认情况下是拦截所有请求的-->
<bean class="com.rainbowsea.springmvc.interceptors.Interceptor1"></bean>
</mvc:interceptors>
</beans>
编写对应的 Controller 控制器进行测试:

package com.rainbowsea.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller // 交给 Spring IOC 容器管理
public class IndexController {
@RequestMapping("/index")
public String toIndex() {
System.out.println("IndexController#toIndex() ---> 处理器方法执行了");
return "index";
}
@RequestMapping("ok")
public String toOK() {
System.out.println("IndexController#OK() ---> 处理器方法执行了");
return "ok";
}
}
运行测试:


第二种方式是:通过 @Component 注解 + xml 文件进行配置
注意:同样的,对于这种基本配置来说,拦截器是拦截所有请求的。
第二种方式的前提:
- 前提1:包扫描,在 spring mvc 中配置组件扫描
- 前提2:使用 @Component 注解进行对 编写的拦截器类进行标注即可。
- 两个前提都搞定了,就可以在 spring mvc.xml 文件中进行配置了。
<mvc:interceptors>
<ref bean="interceptor1"/>
</mvc:interceptors>
运行测试:

3.3 拦截器的高级配置
采用以上基本配置方式,拦截器是拦截所有请求路径的。如果要针对某些路径进行拦截,某些路径不拦截,某些路径拦截,可以采用高级配置:在 spring mvc.xml 文件当中进行配置

以上的配置表示,除 /ok 请求路径之外,剩下的路径全部拦截。
<?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/beans http://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/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 组件扫描-->
<context:component-scan
base-package="com.rainbowsea.springmvc.controller,com.rainbowsea.springmvc.interceptors"></context:component-scan>
<!-- 视图解析器-->
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
<!--作用于视图渲染的过程中,可以设置视图渲染后输出时采用的编码字符集-->
<property name="characterEncoding" value="UTF-8"/>
<!--如果配置多个视图解析器,它来决定优先使用哪个视图解析器,它的值越小优先级越高-->
<property name="order" value="1"/>
<!--当 ThymeleafViewResolver 渲染模板时,会使用该模板引擎来解析、编译和渲染模板-->
<property name="templateEngine">
<bean class="org.thymeleaf.spring6.SpringTemplateEngine">
<!--用于指定 Thymeleaf 模板引擎使用的模板解析器。模板解析器负责根据模板位置、模板资源名称、文件编码等信息,加载模板并对其进行解析-->
<property name="templateResolver">
<bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
<!--设置模板文件的位置(前缀)-->
<property name="prefix" value="/WEB-INF/templates/"/>
<!--设置模板文件后缀(后缀),Thymeleaf文件扩展名不一定是html,也可以是其他,例如txt,大部分都是html-->
<property name="suffix" value=".html"/>
<!--设置模板类型,例如:HTML,TEXT,JAVASCRIPT,CSS等-->
<property name="templateMode" value="HTML"/>
<!--用于模板文件在读取和解析过程中采用的编码字符集-->
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
<!-- 高级配置:指定一些路径被拦截,一些路径不拦截-->
<mvc:interceptors>
<mvc:interceptor>
<!-- /** 表示拦截所有路径-->
<mvc:mapping path="/**"/>
<!-- /ok 请求路径不拦截-->
<mvc:exclude-mapping path="/ok"/>
<!-- /index 请求路径拦截-->
<!-- <mvc:mapping path="/index"/>-->
<!-- 设置对应的那个拦截器-->
<ref bean="interceptor1"></ref>
</mvc:interceptor>
</mvc:interceptors>
</beans>
运行测试:

4. Spring MVC中多个拦截器的执行顺序
这里我们为了探究,多个拦截器存在的时候的执行顺序,我们创建 3 个 拦截器。如下:
4.1 如果所有拦截器 preHandle( ) 方法 都返回 true时,多个拦截器的的执行顺序



配置多个拦截器

<mvc:interceptors>
<!-- 配置多个拦截器,这个是基本配置,默认是所有请求都会进行拦截处理-->
<ref bean="interceptor1"></ref>
<ref bean="interceptor2"></ref>
<ref bean="interceptor3"></ref>
</mvc:interceptors>
<?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/beans http://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/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 组件扫描-->
<context:component-scan
base-package="com.rainbowsea.springmvc.controller,com.rainbowsea.springmvc.interceptors"></context:component-scan>
<!-- 视图解析器-->
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
<!--作用于视图渲染的过程中,可以设置视图渲染后输出时采用的编码字符集-->
<property name="characterEncoding" value="UTF-8"/>
<!--如果配置多个视图解析器,它来决定优先使用哪个视图解析器,它的值越小优先级越高-->
<property name="order" value="1"/>
<!--当 ThymeleafViewResolver 渲染模板时,会使用该模板引擎来解析、编译和渲染模板-->
<property name="templateEngine">
<bean class="org.thymeleaf.spring6.SpringTemplateEngine">
<!--用于指定 Thymeleaf 模板引擎使用的模板解析器。模板解析器负责根据模板位置、模板资源名称、文件编码等信息,加载模板并对其进行解析-->
<property name="templateResolver">
<bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
<!--设置模板文件的位置(前缀)-->
<property name="prefix" value="/WEB-INF/templates/"/>
<!--设置模板文件后缀(后缀),Thymeleaf文件扩展名不一定是html,也可以是其他,例如txt,大部分都是html-->
<property name="suffix" value=".html"/>
<!--设置模板类型,例如:HTML,TEXT,JAVASCRIPT,CSS等-->
<property name="templateMode" value="HTML"/>
<!--用于模板文件在读取和解析过程中采用的编码字符集-->
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
<mvc:interceptors>
<!-- 配置多个拦截器,这个是基本配置,默认是所有请求都会进行拦截处理-->
<ref bean="interceptor1"></ref>
<ref bean="interceptor2"></ref>
<ref bean="interceptor3"></ref>
</mvc:interceptors>
</beans>
如果所有拦截器 preHandle 都返回 true
按照 springmvc.xml文件中配置的顺序,自上而下调用 preHandle:
4.2 如果其中一个拦截器 preHandle ( ) 方法,返回 false,多个拦截器的的执行顺序
Interceptor3 拦截器中的 preHandle()方法返回 false。其他两个拦截器返回 true.

规则:只要有一个拦截器preHandle返回false,任何postHandle都不执行。但返回false的拦截器的前面的拦截器按照逆序执行afterCompletion。
只要有一个拦截器
preHandle()方法,返回false,则任何拦截器的postHandle()方法都不执行。但返回 false 的拦截器的前面的拦截器按照逆序执行afterCompletion。返回 false 拦截器,拦截住了,则其中的 Controllor控制器不执行了,其中的 postHandle
一个也不会执行。而对应的 afterCompletion()方法,的执行是按照配置拦截器(自上而下)的倒序执行,但其中返回 false 的拦截器中的 afterCompletion()方法不会被执行
只要有一个拦截器
preHandle返回false,任何postHandle都不执行。但返回false的拦截器的前面的拦截器按照逆序执行afterCompletion。只要有一个拦截器preHandle返回false,任何postHandle都不执行。但返回false的拦截器的前面的拦截器按照逆序执行afterCompletion。
5. 补充:源码分析
5.1 方法执行顺序的源码分析
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 调用所有拦截器的 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 调用处理器方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 调用所有拦截器的 postHandle 方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 处理视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
// 渲染页面
render(mv, request, response);
// 调用所有拦截器的 afterCompletion 方法
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
5.2 拦截与放行的源码分析
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 调用所有拦截器的 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
// 如果 mappedHandler.applyPreHandle(processedRequest, response) 返回false,以下的return语句就会执行
return;
}
}
}
public class HandlerExecutionChain {
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
// 如果 interceptor.preHandle(request, response, this.handler) 返回 false,以下的 return false;就会执行。
return false;
}
this.interceptorIndex = i;
}
return true;
}
}
5.3 DispatcherServlet 和 HandlerExecutionChain 的部分源码:
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 按照顺序执行所有拦截器的preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 执行处理器方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 按照逆序执行所有拦截器的 postHanle 方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 处理视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
// 渲染视图
render(mv, request, response);
// 按照逆序执行所有拦截器的 afterCompletion 方法
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
public class HandlerExecutionChain {
// 顺序执行 preHandle
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
// 如果其中一个拦截器preHandle返回false
// 将该拦截器前面的拦截器按照逆序执行所有的afterCompletion
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
return true;
}
// 逆序执行 postHanle
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}
}
// 逆序执行 afterCompletion
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
6. 总结:
实现
org.springframework.web.servlet.HandlerInterceptor接口,共有三个方法可以进行选择性的实现:
- preHandle( ):处理器方法调用之前执行。只有该方法有返回值,返回值是布尔类型,true 表示放行,false 表示拦截 。
- postHandle( ):处理器方法调用之后执行。
- afterCompletion( ):渲染完成后执行。
在 Spring MVC 中拦截器的基本配置有两种方式:
- 第一种方式是:通过 xml 进行配置
- 第二种方式是:通过 @Component 注解 + xml 文件进行配置
- 对于这种基本配置来说,拦截器是拦截所有请求的。
拦截器的高级配置:采用以上基本配置方式,拦截器是拦截所有请求路径的。如果要针对某些路径进行拦截,某些路径不拦截,某些路径拦截,可以采用高级配置:在 spring mvc.xml 文件当中进行配置
Spring MVC中多个拦截器的执行顺序:
如果所有拦截器 preHandle( ) 方法 都返回 true时,多个拦截器的的执行顺序:
按照 springmvc.xml文件中配置的顺序,自上而下调用 preHandle:
如果其中一个拦截器 preHandle ( ) 方法,返回 false,多个拦截器的的执行顺序
- 只要有一个拦截器
preHandle()方法,返回false,则任何拦截器的postHandle()方法都不执行。但返回 false 的拦截器的前面的拦截器按照逆序执行afterCompletion。拦截器源码分析。
7. 最后:
“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”
Spring MVC 中的拦截器的使用“拦截器基本配置” 和 “拦截器高级配置”的更多相关文章
- spring mvc中的拦截器小结 .
在spring mvc中,拦截器其实比较简单了,下面简单小结并demo下. preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Control ...
- SpringMvc(4-1)Spring MVC 中的 forward 和 redirect
Spring MVC 中,我们在返回逻辑视图时,框架会通过 viewResolver 来解析得到具体的 View,然后向浏览器渲染.通过配置,我们配置某个 ViewResolver 如下: <b ...
- spring mvc中DispatcherServlet如何得到ModelAndView的
首先看下面这种张图,这张图说明了spring mvc整体的流程. 本文讲的就是如何从DispatcherServlet中得到ModerAndView的过程. 首先看DispatherServlet这个 ...
- SpringMvc(4-1)Spring MVC 中的 forward 和 redirect(转)
Spring MVC 中,我们在返回逻辑视图时,框架会通过 viewResolver 来解析得到具体的 View,然后向浏览器渲染.通过配置,我们配置某个 ViewResolver 如下: <b ...
- Spring MVC中防止csrf攻击
Spring MVC中防止csrf攻击的拦截器示例 https://blog.csdn.net/qq_40754259/article/details/80510088 Spring MVC中的CSR ...
- spring mvc中使用freemark的一点心得
参考文档: FreeMarker标签与使用 连接http://blog.csdn.net/nengyu/article/details/6829244 freemarker学习笔记--指令参考: ht ...
- Spring MVC中处理静态资源的多种方法
处理静态资源,我想这可能是框架搭建完成之后Web开发的”头等大事“了. 因为一个网站的显示肯定会依赖各种资源:脚本.图片等,那么问题来了,如何在页面中请求这些静态资源呢? 还记得Spring MVC中 ...
- Spring MVC中各个filter的用法
转载:http://blog.csdn.net/qyp1314/article/details/42023725 Spring MVC中各个filter的用法 2014-12-19 09:08 105 ...
- Spring MVC中的HandlerMapping与HandlerAdapter
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- Spring mvc中@RequestMapping 6个基本用法
Spring mvc中@RequestMapping 6个基本用法 spring mvc中的@RequestMapping的用法. 1)最基本的,方法级别上应用,例如: Java代码 @Reques ...
随机推荐
- kubernets之横向伸缩pod与集群节点
一 pod的自动伸缩容的应用背景 在面对负载并发过高的时候,我们或许希望能够提高RS,RC以及Deployment等的replicas的参数来增加pod的cpu,mem等,或者是通过提高每个容器的r ...
- sass的几种输出格式,你都知道吗
输出格式说明 Sass编译输出的CSS格式可以自定义. 有4种输出格式: :nested – 嵌套格式 :expanded – 展开格式 :compact – 紧凑格式 :compressed – 压 ...
- linux ls命令的重要用法:按照文件大小排序和按照时间排序
1.ls命令是list的缩写,用来打印当前目录清单或者打印出指定目录下的文件及文件清单. 2.本文介绍ls的重要用法:按"文件大小"排序列出文件清单和按"时间" ...
- 29.4K star! 仅需几行代码快速构建机器学习 Web 应用项目,无需前端技能!
大家好,我是狂师! 今天给大家推荐一款开源的Python库:Gradio! Gradio是一个开源的Python库,用于创建机器学习和数据科学的交互式应用和演示. 项目地址: https://gith ...
- Vue 3指令与事件处理
title: Vue 3指令与事件处理 date: 2024/5/25 18:53:37 updated: 2024/5/25 18:53:37 categories: 前端开发 tags: Vue3 ...
- WPF ListBox 控件绑定 Binding
当我们需要用到循环的列表内容,并且模板化程度高的时候,建议使用 ListBox 来做绑定.XAML: <Window.DataContext> <local:VMTempTest/& ...
- PaddleOCR在 Linux下的webAPI部署方案
很多小伙伴在使用OCR时都希望能过采用API的方式调用,这样就可以跨端跨平台了.本文将介绍一种基于python的PaddleOCR识方案.喜欢的可以关注公众号,获取更多内容. 一. Linux环境下部 ...
- ReplayKit 启动录制按钮 RPSystemBroadcastPickerView 的使用
一.RPSystemBroadcastPickerView 介绍 ReplayKit12自从iOS11公布以来,提供了iOS系统级别的录屏能力(也就是录制自身App以外,手机屏幕内容)的能力,有一个非 ...
- github无法提交代码问题
问题描述 提交代码到个人仓库的时候发现报错,认证失败 Username for 'https://github.com': hywing Password for 'https://hywing@gi ...
- Java中的变量分类(按照位置分类)
变量按位置分 通过上面类的建立我们又得到了新的概念:成员变量和局部变量 成员变量: 可以使用基本数据类型,也可以使用引用数据类型. java中的变量在使用时必须初始化,成员变量可以不对其初始化,系统会 ...








