Spring Boot 拦截器 HandlerInterceptor的使用以及WebMvcConfigurer简单介绍

当我们使用Spring Boot构建Web应用程序时,HandlerInterceptor 是一个重要的组件,用于拦截请求的处理过程。HandlerInterceptor 接口定义了在请求处理的不同阶段执行的方法,允许我们在请求到达处理程序之前和之后执行自定义逻辑。

HandlerInterceptor

在Spring Boot中,我们通常通过实现HandlerInterceptor 接口来创建自定义的拦截器。以下是HandlerInterceptor 接口定义的主要方法:

  1. preHandle:在请求到达处理程序之前被调用。可以用于执行一些前置处理逻辑,例如身份验证、日志记录等。如果此方法返回true,则请求继续传递到处理程序;如果返回false,则请求处理终止。
  2. postHandle:在请求处理程序执行之后,视图渲染之前被调用。可以用于执行一些后置处理逻辑,例如修改模型数据、记录执行时间等。
  3. afterCompletion:在整个请求完成之后被调用。通常用于清理资源、记录最终日志等。可以在这里获取到处理程序的执行结果和可能的异常信息。

要使用HandlerInterceptor,我们需要在配置类中注册它。例如,在Spring Boot中,我们可以创建一个继承自WebMvcConfigurerAdapter(在Spring 5中使用WebMvcConfigurer)的配置类,并重写addInterceptors 方法。

@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyHandlerInterceptor()).addPathPatterns("/**");}
}

在这个例子中,MyHandlerInterceptor 是我们自定义的拦截器类,它需要实现HandlerInterceptor 接口。

public class MyHandlerInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 在请求处理前执行的逻辑return true; // 返回 true 允许请求继续,返回 false 则终止请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 在请求处理后、视图渲染前执行的逻辑}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 在整个请求完成后执行的逻辑}
}

通过使用HandlerInterceptor,我们可以实现对请求处理过程的精细控制,例如添加全局的身份验证、记录请求日志等功能。

HandlerInterceptorAdapter

HandlerInterceptorAdapter 是 Spring 提供的一个适配器类,实现了 HandlerInterceptor 接口,并且提供了默认的空实现。它的存在使得我们在实现自定义拦截器时,只需要关注我们感兴趣的方法,而不需要实现所有方法。

具体来说,HandlerInterceptorAdapter 实现了 HandlerInterceptor 接口的三个方法:preHandlepostHandle、和 afterCompletion。默认情况下,这些方法的实现为空,允许我们只重写需要的方法,而不用关心其他方法。

以下是一个简单的例子,展示了如何使用 HandlerInterceptorAdapter

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 在请求处理前执行的逻辑return true; // 返回 true 允许请求继续,返回 false 则终止请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 在请求处理后、视图渲染前执行的逻辑}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 在整个请求完成后执行的逻辑}
}

在这个例子中,MyInterceptor 类继承了 HandlerInterceptorAdapter,并重写了 preHandlepostHandleafterCompletion 方法,实现了自定义的拦截逻辑。

然后,我们可以将这个拦截器注册到 Spring MVC 的配置中,就像之前提到的方式一样:

@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");}
}

使用 HandlerInterceptorAdapter 可以让拦截器的实现更加简洁,只需关注自己感兴趣的方法即可。

AsyncHandlerInterceptor

AsyncHandlerInterceptorHandlerInterceptor 接口的一种扩展,专门用于处理异步请求。与同步请求不同,异步请求在处理过程中可能涉及到线程的切换,因此需要专门的拦截器来支持这种场景。

与普通的 HandlerInterceptor 相比,AsyncHandlerInterceptor 接口增加了对异步请求的支持,它定义了额外的方法来处理异步场景:

  1. preHandle:与同步请求的 preHandle 方法类似,在异步请求的开始阶段被调用。可以用于执行一些前置处理逻辑。返回 true 表示请求继续进行,返回 false 则中断异步请求的处理。
  2. postHandle:与同步请求的 postHandle 方法类似,但是在异步请求的主处理线程完成处理之后调用。可以用于执行一些后置处理逻辑。
  3. afterCompletion:与同步请求的 afterCompletion 方法类似,但是在整个异步请求完成之后调用。可以用于清理资源、记录最终日志等。
  4. afterConcurrentHandlingStarted:在异步请求处理开始时被调用。此时,主处理线程已经处理完请求,而异步请求的处理可能在其他线程中进行。可以用于执行一些异步处理开始时的逻辑。

要使用 AsyncHandlerInterceptor,我们可以通过实现该接口并将其注册到配置中,就像使用普通的 HandlerInterceptor 一样。以下是一个简单的例子:

public class MyAsyncHandlerInterceptor implements AsyncHandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 在异步请求开始前执行的逻辑return true; // 返回 true 允许请求继续,返回 false 则中断异步请求的处理}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 在异步请求的主处理线程完成处理后执行的逻辑}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 在整个异步请求完成后执行的逻辑}@Overridepublic void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 在异步请求处理开始时执行的逻辑}
}

然后,将拦截器注册到配置中:

@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {@Overridepublic void configureAsyncSupport(AsyncSupportConfigurer configurer) {configurer.registerCallableInterceptors(new MyAsyncHandlerInterceptor());}
}

在这个例子中,MyAsyncHandlerInterceptor 是实现了 AsyncHandlerInterceptor 接口的自定义异步拦截器。

AsyncHandlerInterceptor使用场景

AsyncHandlerInterceptor 主要用于处理异步请求场景,其中异步请求是指在请求处理过程中,主处理线程可能会在处理的不同阶段释放出来,允许其他线程继续处理请求。以下是一些适合使用 AsyncHandlerInterceptor 的场景:

  1. 长时间任务处理:
  • 当应用需要处理长时间运行的任务时,可以使用异步请求,而 AsyncHandlerInterceptor 可以用于处理异步请求的不同阶段。
  • 例如,如果某个请求触发了一个需要很长时间才能完成的任务,你可以在异步处理的开始和结束阶段执行一些逻辑,例如记录日志、通知用户等。
  1. 非阻塞I/O操作:
  • 异步请求通常用于处理非阻塞 I/O 操作,例如读取或写入大量数据、调用外部服务等。
  • 在异步处理的开始和结束阶段,AsyncHandlerInterceptor 可以用于执行相关的逻辑,例如记录性能指标、处理异常情况等。
  1. 推送通知:
  • 当需要实现服务器端推送通知给客户端时,异步请求是一个常见的选择。
  • 使用 AsyncHandlerInterceptor 可以在推送开始和结束的时候执行逻辑,例如记录推送日志、处理异常情况等。
  1. 资源处理和清理:
  • 异步请求在整个处理过程中可能涉及到多个线程,因此可以使用 AsyncHandlerInterceptor 在异步请求的不同阶段进行资源的处理和清理。
  • 例如,可以在异步处理开始时分配某些资源,在异步请求结束时进行清理。
  1. 异步任务执行前后的逻辑:
  • 如果应用中使用了异步任务执行框架(如 Spring 的 @Async),AsyncHandlerInterceptor 可以在异步任务开始执行前和执行完成后执行一些逻辑。
  • 这可以用于记录任务执行时间、处理异常等。

总的来说,使用 AsyncHandlerInterceptor 的场景通常涉及到异步请求的处理,而这些请求在执行过程中可能涉及到线程的切换和长时间运行的任务。在这些场景中,AsyncHandlerInterceptor 提供了一种机制,允许我们在异步请求的不同阶段执行自定义逻辑,以满足特定需求。

Configurer

WebMvcConfigurer

**WebMvcConfigurer **接口是 Spring MVC 提供的用于配置 Web MVC 的接口。通过实现这个接口,可以对 Spring MVC 进行一些自定义配置,例如添加拦截器、修改视图解析器、配置消息转换器等。以下是一些常见的用法:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {// 1. 添加拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");}// 这里的 MyInterceptor 是你自定义的拦截器,可以在其中实现需要的拦截逻辑。// 2. 添加自定义静态资源处理@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");}// 这样配置后,访问路径 /static/** 将会映射到 classpath:/static/ 目录下的资源。// 3. 修改视图解析器@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {// 这里可以进行视图解析器的自定义配置,例如:// registry.jsp("/WEB-INF/views/", ".jsp");// 表示使用 JSP 视图解析器,视图文件位于 /WEB-INF/views/ 目录下,后缀为 .jsp。}// 4. 配置消息转换器@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {// 这里可以配置消息转换器,例如添加自定义的 JSON 转换器。// converters.add(new MyJsonConverter());}// 5. 配置跨域资源共享(CORS)@Overridepublic void addCorsMappings(CorsRegistry registry) {// 配置跨域资源共享,允许 http://localhost:8080 发起的跨域请求访问 /api/**registry.addMapping("/api/**").allowedOrigins("http://localhost:8080");}// 这是一个简单的例子,允许来自 http://localhost:8080 的请求跨域访问 /api/** 路径。
}

这个配置类通过实现 WebMvcConfigurer 接口,为 Spring MVC 提供了一些自定义配置。具体来说:

  • 添加拦截器: 通过 addInterceptors 方法添加拦截器,可以在请求处理的各个阶段执行自定义逻辑。
  • 添加自定义静态资源处理: 使用 addResourceHandlers 方法配置静态资源的映射,使得这些资源可以通过指定的路径访问。
  • 修改视图解析器: 使用 configureViewResolvers 方法配置视图解析器,允许自定义视图解析器的行为。
  • 配置消息转换器: 使用 configureMessageConverters 方法配置消息转换器,可以添加或修改默认的消息转换器,例如 JSON 转换器。
  • 配置跨域资源共享(CORS): 使用 addCorsMappings 方法配置跨域资源共享,定义允许跨域访问的路径和来源。

在实际应用中,你需要根据具体需求填充这些方法的具体实现,以满足项目的要求。在配置完成后,确保这个配置类被 Spring Boot 应用程序正确地扫描到,以确保这些配置生效。

WebMvcConfigurationSupport

WebMvcConfigurationSupport 是 Spring MVC 提供的用于进行更深层次自定义配置的基类。
WebMvcConfigurer 不同,WebMvcConfigurationSupport 提供的配置更为底层,允许你对 Spring MVC 的默认配置进行更彻底的改变。这里解释一下示例中的各个重要方法:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;@Configuration
@EnableWebMvc
public class MyWebMvcConfig extends WebMvcConfigurationSupport {// 1. 添加拦截器@Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");}// 这里的 MyInterceptor 是自定义的拦截器,你可以在其中实现需要的拦截逻辑。// 2. 添加自定义静态资源处理@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");}// 这样配置后,访问路径 /static/** 将会映射到 classpath:/static/ 目录下的资源。// 3. 修改视图解析器@Overrideprotected void configureViewResolvers(ViewResolverRegistry registry) {// 在这里可以进行视图解析器的自定义配置,例如:// registry.jsp("/WEB-INF/views/", ".jsp");// 表示使用 JSP 视图解析器,视图文件位于 /WEB-INF/views/ 目录下,后缀为 .jsp。}// 4. 配置消息转换器@Overrideprotected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {// 在这里可以配置消息转换器,例如添加自定义的 JSON 转换器。// converters.add(new MyJsonConverter());}// 5. 配置跨域资源共享(CORS)@Overrideprotected void addCorsMappings(CorsRegistry registry) {// 配置跨域资源共享,允许 http://localhost:8080 发起的跨域请求访问 /api/**registry.addMapping("/api/**").allowedOrigins("http://localhost:8080");}// 这是一个简单的例子,允许来自 http://localhost:8080 的请求跨域访问 /api/** 路径。//------------------------- 其它方法 -----------------------------// 配置路径匹配@Overrideprotected void configurePathMatch(PathMatchConfigurer configurer) {// 在这里可以设置路径匹配的行为,例如是否在路径末尾添加斜杠// configurer.setUseTrailingSlashMatch(false);}// 配置异步请求的支持@Overrideprotected void configureAsyncSupport(AsyncSupportConfigurer configurer) {// 在这里可以设置异步请求的超时时间、线程池等// configurer.setDefaultTimeout(30000);}// 配置内容协商策略@Overrideprotected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {// 在这里可以设置默认的内容类型、请求参数中的内容类型等// configurer.defaultContentType(MediaType.APPLICATION_JSON);}// 扩展消息转换器@Overrideprotected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {// 在这里可以在已有的转换器列表上进行扩展// converters.add(new MyAdditionalConverter());}// 配置默认的 Servlet 处理@Overrideprotected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {// 在这里可以启用或禁用对静态资源的默认 Servlet 处理// configurer.enable();}// 添加简单的视图控制器@Overrideprotected void addViewControllers(ViewControllerRegistry registry) {// 在这里可以添加简单的视图控制器,将某个 URL 直接映射到某个视图// registry.addViewController("/home").setViewName("home");}// 扩展异常处理器@Overrideprotected void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {// 在这里可以在已有的异常处理器列表上进行扩展// exceptionResolvers.add(new MyAdditionalExceptionResolver());}// 配置异常处理器@Overrideprotected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {// 在这里可以设置异常处理器的顺序和是否开启默认异常处理器// exceptionResolvers.order(1);// exceptionResolvers.setUseDefaultExceptionHandler(false);}// 配置消息代码解析器@Overrideprotected void configureMessageCodesResolver(MessageCodesResolver codesResolver) {// 在这里可以设置消息代码的解析策略// codesResolver.setMessageCodeFormatter(new MyMessageCodeFormatter());}// 配置视图解析器@Overrideprotected void configureViewResolvers(ViewResolverRegistry registry) {// 在这里可以设置视图解析器的顺序和是否开启默认视图解析器// registry.order(1);// registry.enableContentNegotiation(new MappingJackson2JsonView());}// 添加自定义的参数解析器@Overrideprotected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {// 在这里可以添加自定义的参数解析器,可以在已有的解析器列表上进行添加// argumentResolvers.add(new MyAdditionalArgumentResolver());}// 添加自定义的返回值处理器@Overrideprotected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {// 在这里可以添加自定义的返回值处理器,可以在已有的处理器列表上进行添加// returnValueHandlers.add(new MyAdditionalReturnValueHandler());}// .........
}
  • **addInterceptors**** 方法:** 通过这个方法,可以添加拦截器,允许在请求处理的不同阶段执行自定义逻辑。这与 WebMvcConfigurer 中的方法类似。
  • **addResourceHandlers**** 方法:** 这个方法用于添加自定义静态资源处理。配置后,指定路径的静态资源将会映射到指定的资源位置。
  • **configureViewResolvers**** 方法:** 通过这个方法可以修改视图解析器。在这里,你可以配置自定义的视图解析器,定义视图文件的存放位置和文件后缀等。
  • **configureMessageConverters**** 方法:** 这个方法用于配置消息转换器。可以在这里添加或修改默认的消息转换器,例如添加自定义的 JSON 转换器。
  • **addCorsMappings**** 方法:** 通过这个方法可以配置跨域资源共享(CORS)。这个例子中允许了来自 http://localhost:8080 的请求跨域访问 /api/** 路径。

需要注意的是,在使用 WebMvcConfigurationSupport 时,Spring Boot 的默认配置可能会失效,因此需要手动配置一些默认行为。此外,虽然 WebMvcConfigurationSupport 提供更灵活的配置,但也更为底层,可能会增加配置的复杂性。因此,一般情况下推荐使用 WebMvcConfigurer 进行轻量级的配置。只有在需要更深层次的自定义时,才考虑使用 WebMvcConfigurationSupport

可能会失效的配置

使用WebMvcConfigurationSupport时,Spring Boot的一些默认配置可能会失效,因为WebMvcConfigurationSupport提供了更高级别的自定义配置,可能会覆盖或替代Spring Boot的默认配置。以下是一些可能会受影响的默认配置:

  1. 自动配置的**WebMvcAutoConfiguration**可能失效:
    WebMvcAutoConfiguration是Spring Boot自动配置Web MVC的类,当你使用WebMvcConfigurationSupport时,它可能不再生效,因为你自己提供了更高级别的配置。
  2. 静态资源的默认处理可能失效:
    Spring Boot默认提供了静态资源的处理,例如/static/路径下的资源会被映射到classpath下的/static/目录。使用WebMvcConfigurationSupport时,你可能需要手动配置静态资源处理,因为默认的可能会失效。
  3. 默认的**ContentNegotiationStrategy**可能被替代:
    WebMvcConfigurationSupport中的configureContentNegotiation方法可以配置内容协商策略,这可能会替代Spring Boot默认的协商策略。
  4. 默认的**MessageConverter**可能会失效:
    使用configureMessageConvertersextendMessageConverters方法可能会替代或扩展默认的消息转换器。如果你没有显式地配置自己的转换器列表,可能会丢失Spring Boot默认配置的一些消息转换器。
  5. 默认的**HandlerExceptionResolver**可能会失效:
    configureHandlerExceptionResolversextendHandlerExceptionResolvers方法可以配置异常处理器,这可能会替代或扩展默认的异常处理器。
  6. 默认的**ViewResolver**可能会失效:
    configureViewResolvers方法可以配置视图解析器,这可能会覆盖Spring Boot默认的视图解析器配置。

总的来说,使用WebMvcConfigurationSupport时,你需要更加谨慎地配置,确保你自己提供的配置不会完全覆盖Spring Boot的默认配置,以免造成意外的问题。通常情况下,建议在必要时使用WebMvcConfigurer接口进行轻量级的配置,而不是直接使用WebMvcConfigurationSupport

如何选择

WebMvcConfigurerWebMvcConfigurationSupport 都是用于配置 Spring MVC 的接口/类,但它们有不同的使用场景和适用范围。

WebMvcConfigurer:
  1. 轻量级配置:
  • WebMvcConfigurer 接口提供了一种轻量级的方式来进行 Spring MVC 的配置。如果你只需要进行一些简单的配置,比如添加拦截器、设置视图解析器、配置资源处理等,那么使用 WebMvcConfigurer 更为合适。
  1. 保留默认配置:
  • 使用 WebMvcConfigurer 时,Spring Boot 的默认配置仍然会生效,你可以在现有的配置基础上进行定制,而不是覆盖所有默认配置。
  1. 扩展特定功能:
  • 适用于只需要扩展某个特定功能而不是替代全部配置的场景。你可以选择性地实现 WebMvcConfigurer 接口中的方法,根据需要进行配置。
WebMvcConfigurationSupport:
  1. 深度定制:
  • WebMvcConfigurationSupport 提供了更为深度的自定义配置,你可以完全替代 Spring MVC 的默认配置。如果你需要对 Spring MVC 进行更深层次的定制,比如替换默认的异常处理器、配置全局消息转换器、完全自定义路径匹配规则等,那么可以使用 WebMvcConfigurationSupport
  1. 覆盖默认配置:
  • 使用 WebMvcConfigurationSupport 时,需要注意可能会覆盖 Spring Boot 默认的配置,因此需要谨慎地配置,确保你提供的配置不会意外地影响到默认配置。
  1. 全面替代:
  • 适用于需要全面替代 Spring MVC 配置的场景,特别是当你需要做一些非常定制化的配置时,可能需要使用 WebMvcConfigurationSupport

选择建议:

  • 如果只是进行一些轻量级的配置,或者是在现有的 Spring Boot 默认配置基础上进行定制,推荐使用 WebMvcConfigurer
  • 如果需要进行更深层次的自定义,甚至是完全替代 Spring MVC 的默认配置,才考虑使用 WebMvcConfigurationSupport

通常情况下,绝大多数项目可以通过实现 WebMvcConfigurer 接口来满足配置需求,而无需使用 WebMvcConfigurationSupport。只有在需要非常深度和全面的自定义时,才考虑使用 WebMvcConfigurationSupport

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

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

相关文章

解决删除QT后Qt VS Tools中Qt Options中未删除的错误

在Qt VS Tools的Qt Options已经配置好Qt Versions后如果删除QT程序之后会出现Default Qt/Win version任然存在&#xff0c;这是如果再添加一个话就不能出现重名了&#xff0c;如果新建一个其他名字的话其实在vs中还是不能正常运行qt&#xff0c;会出现点击ui文件vs会无故重启或…

Elastic stack8.10.4搭建、启用安全认证,启用https,TLS,SSL 安全配置详解

ELK大家应该很了解了&#xff0c;废话不多说开始部署 kafka在其中作为消息队列解耦和让logstash高可用 kafka和zk 的安装可以参考这篇文章 深入理解Kafka3.6.0的核心概念&#xff0c;搭建与使用-CSDN博客 第一步、官网下载安装包 需要 elasticsearch-8.10.4 logstash-8.…

【Java 进阶篇】JQuery 案例:优雅的隔行换色

在前端的设计中&#xff0c;页面的美观性是至关重要的。而其中一个简单而实用的设计技巧就是隔行换色。通过巧妙地使用 JQuery&#xff0c;我们可以轻松地实现这一效果&#xff0c;为网页增添一份优雅。本篇博客将详细解析 JQuery 隔行换色的实现原理和应用场景&#xff0c;让我…

Android Matrix的使用详解(通过矩阵获取到图片缩放比例和角度)

网上查了好久相关的资料&#xff0c;都没有明确的答案。最终通过多次测试结果&#xff0c;结合安卓定义的矩阵含义&#xff0c;推算出来矩阵的数学含义以及相关的计算公式 1.获取Matrix矩阵&#xff1a; Matrix matrix new Matrix(); float[] matrixValues new float[9]; …

利用短视频短剧小程序系统提升品牌影响力

在当今数字化时代&#xff0c;品牌影响力的重要性日益凸显。短视频短剧小程序系统作为一种新型的内容传播和互动体验方式&#xff0c;为品牌提升影响力提供了新的机遇。本文将探讨如何利用短视频短剧小程序系统提升品牌影响力&#xff0c;以及实施过程中的挑战和策略建议。 一…

linux rsyslog日志采集格式设定二

linux rsyslog日志采集格式设定二 1.创建日志接收模板 打开/etc/rsyslog.conf文件,在GLOBAL DIRECTIVES模块下任意位置添加以下内容 命令: vim /etc/rsyslog.conf 测试:rsyslog.conf文件结尾添加以下内容 $template ztj,"%timegenerated% %hostname% %TIMESTAMP:…

C 语言实现 UDP

广播 发送广播信息&#xff0c;局域网中的客户端都可以接受该信息 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h>int main() {// 1.创建一个通信的socketint fd socket(PF_INET, …

基于单片机的线路差动保护系统设计

摘 要 随着我国微型电子技术和嵌入式系统的发展&#xff0c;目前行业内相对比较传统的线路差动保护系统无法满足客户的需求。为了改进传统线路差动保护系统在控制上得短板问题&#xff0c;在本次毕业设计中&#xff0c;将使用相对先进、快捷、智能的控制机制。该系统的控制大脑…

C-4练习题

一、单项选择题(本大题共20小题,每小题2分,共40分。在每小题给出的四个备选项中,选出一个正确的答案&#xff0c;并将所选项前的字母填写在答题纸的相应位置上。) 1. C 程序是由&#xff08;)构成的。 A.常量 B.变量 C.运算符 D. 函数 2.下列合法的标识符是() A. case …

DAY54 392.判断子序列 + 115.不同的子序列

392.判断子序列 题目要求&#xff1a;给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是…

创造者设计模式

Bike package com.jmj.pattern.builder.demo01;public class Bike {private String frame;//车架private String seat;//车座public String getFrame() {return frame;}public void setFrame(String frame) {this.frame frame;}public String getSeat() {return seat;}public…

华纳云:WordPress如何制作CMS栏目块

WordPress作为一个强大的内容管理系统(CMS)&#xff0c;允许你自定义并创建各种栏目块。你可以使用插件、主题功能或自定义开发来实现这一点。下面是一些基本方法&#xff1a; 1. 使用页面模板和自定义字段 创建自定义页面模板&#xff1a; 创建一个新的页面模板&#xff0c;例…

Windows客户端开发框架WPF简介

一、WPF简介 WPF的全称是Windows Presentation Foundation&#xff0c;WPF是 Microsoft 提供的一种用于构建桌面应用程序的 UI 框架。它包含在 .NET Framework 中&#xff0c;从 .NET 3.0 版本开始就被引入。 以下是一些关于 WPF 的关键特性&#xff1a; 1. XAML&#xff1a…

【git】解决git报错:ssh:connect to host github.com port 22: Connection timed out 亲测有效

如题&#xff0c;git使用中突然报错 ssh:connect to host github.com port 22: Connection timed out 通过查阅各种资料&#xff0c;得知原因可能是由于电脑的防火墙或者其他网络原因导致ssh连接方式 端口22被封锁。 解决方法 一&#xff1a;抛弃ssh连接方式&#xff0c;使…

深度学习实战59-NLP最核心的模型:transformer的搭建与训练过程详解,手把手搭建与跑通

大家好,我是微学AI,今天给大家介绍一下深度学习实战59-NLP最核心的模型:transformer的搭建与训练过程详解,手把手搭建与跑通。transformer是一种基于自注意力机制的深度学习模型,由Vaswani等人在2017年的论文《Attention is All You Need》中提出。它最初被设计用来处理序…

centos 6.10 编译 zstd 库

从 github 上下载最新的源码。下载链接 进入到 zstd-dev 目录下 执行下面命令 cd /build/cmake mkdir build && cd build cmake .. make我遇到了报错&#xff1a; timefn.c:(.text0x5e): undefined reference to clock_gettime原因是 centos 6.10 的 glibc 版本太老…

什么叫做一站式解决方案?

一站式解决方案&#xff08;One-stop solution&#xff09;是指为客户提供从项目起始到完成的全过程服务的经营模式。这种方案通常由某个服务提供商或公司实施&#xff0c;目的是解决客户的各种问题&#xff0c;同时省去客户寻找多个供应商合作的麻烦。一站式服务可能包括咨询、…

【luckfox】0、开发环境搭建

前言 本章简单介绍如何搭建luckfox的开发环境。 一、抓取luckfox源码 需要提前准备好ubuntu环境。 git clone https://github.com/LuckfoxTECH/luckfox-pico.git二、编译 youkaiubuntu:/home/luckfox/luckfox-pico$ ./build.sh lunchyoukaiubuntu:/home/luckfox/luckfox-p…

python数据处理作业11:建一个5*3的随机数组和一个3*2的数组,其元素为1,2,3,4,5,6,求两矩阵的积

每日小语 打碎的杯子&#xff0c;烫伤的手&#xff0c;对菩萨是堪忍&#xff0c;因为他在里面得悟甚深之法&#xff0c;心生欢喜。 可是对一般人来说&#xff0c;一生何止打破千百个杯子&#xff1f;何止烫伤过千百次手&#xff1f;他只是痛苦地忍受&#xff0c;只记得下次要…

Linux--线程概念+线程控制

1.什么是线程 相对于进程而言&#xff0c;进程是承担资源调度的实体&#xff0c;线程在进程内部运行&#xff0c;是操作系统调度的基本单位。 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列…