自定义注解 - java文档生成、结合SpringBoot使用

参考资料:

参考视频

拦截器自定义注解

AOP自定义注解

通过AOP获取属性

 拦截器、过滤器、AOP的区别和联系

个人学习笔记及源码

注:这里仅讲怎么使用,具体原理请参考个人学习笔记 


自定义注解源码介绍:

  •  其中视频例子2为上述参考视频的例子
  • 视频例子1为原先反射视频的例子

生成JAVA文档:

可以通过javadoc命令生成API文档

  • 首先将要转为文档的类,去掉包名,放在磁盘中

  • 用记事本,notepad++,或者其他工具将编码转化为ANSI编码

  • 在磁盘目录 打开CMD,输入以下命令,回车即可生成API文旦

javadoc XXX.java

  • 打开生成的inde.html即可看到API文档


注解的基本结构

  • 注解的基本结构为:

#{元注解}

public  @interface  #{注解名称} {

        #{属性列表}

}

 注解名称:自定义的注解名称

元注解:用于定义注解的注解,常用的元注解有如下四个:

@Target :  描述该注解作用范围,即应该标注在java文件的什么上面,常用的值为:

  • ElementType.Type : 作用于类
  • ElementType.METHOD: 作用于方法
  • ElementType.FIELD:作用于字段

        当然还有其他值可以进行查阅

@Retention:描述注解被保留的阶段,常用的值为:

  • RetentionPolicy.RUNTIME:当前描述的注解,会保留到class字节码文件中,并被jvm读取到

        当然还有其他值可以进行查阅

@Documented:描述注解是否被抽取到api文档中,选填,填上就表示参与到API文档中

@Inherited:描述注解是否可以被继承,选填,填上就表示可以被继承

属性列表:注解的属性,需要抽象方法来定义,且必须要有返回值,关于原理下面会讲,这里仅仅讲使用规则

  • 抽象方法必须有返回结果,且返回结果必须是如下类型:

        ① 基本数据类型
        ② String类型
        ③ 枚举类型
        ④ 注解
        ⑤ 以上类型的数组

  • 属性赋值注意点:

        下面将结合例子进行说明

  • 如果定义的属性时,使用default关键字给属性默认初始值,可以在使用注解时不赋值;

  • 注解只有一个抽象方法,且抽象方法名为value,那么在使用时可以直接赋值而不去声明value = XXX;

  • 数组赋值的时,使用大括号{}进行包裹,但是如果只有一个值,那么大括号{}可以省略

 


注解的基本使用方式

下面演示在不结合SpringBoot的情况下,使用自定义注解进行简单的测试

  • 首先自定义一个注解
package com.example.demo.localAnnotation.selfDemo.annoUse;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnno {String shuXing1() default "zhangsan";int shuXing2();}
  • 然后加在测试的方法上
package com.example.demo.localAnnotation.selfDemo.annoUse;/*** @program: AnnotationDemo* @description:* @author: wjl* @create: 2023-12-04 23:48**/
@TestAnno(shuXing2 = 12315)
public class AnnoMethods {@TestAnno(shuXing1 = "XXX",shuXing2 = 66)private String str = "testShuXing";@TestAnno(shuXing2 = 10086)public int method01(int a,int b){return a+b;}@TestAnno(shuXing1 = "lisi",shuXing2 = 10010)public String method02(String str1,String str2,String str3){return str1+"======"+str2+"======"+str3;}@TestAnno(shuXing1 = "wanglong",shuXing2 = 123456)public void method03(){}}
  • 然后使用反射进行解析

 

package com.example.demo.localAnnotation.selfDemo.annoUse;import org.junit.Test;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*** @program: AnnotationDemo* @description:* @author: wjl* @create: 2023-12-05 00:14**/
@SuppressWarnings("all")
public class TestAnnoMethods {@Testpublic void test01() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {String mathodName = "method01";//   一定要创建一个实例AnnoMethods methods = new AnnoMethods();// 确定执行方法Class<?> methodsClass = methods.getClass();Class<?>[] classArr = new Class[]{int.class,int.class};Method method = methodsClass.getDeclaredMethod(mathodName, classArr);// 设置私有方法可达method.setAccessible(true);// 确定方法的参数Object[] valueArr = new Object[]{1,100};// 执行方法 和返回值Object result = method.invoke(methods, valueArr);// 获取 该方法上面的注解 以及相关值TestAnno anno = method.getAnnotation(TestAnno.class);String shuXing1 = anno.shuXing1();int shuXing2 = anno.shuXing2();// 遍历进行输出System.out.println("下面是获取到的相关值,以及通过反射获取到的结果");System.out.println("执行方法为:"+mathodName);System.out.println("方法参数为:"+valueArr[0]+"******"+valueArr[1]);System.out.println("执行结果为:"+result);System.out.println("注解属性1的值为:"+shuXing1);System.out.println("注解属性2的值为:"+shuXing2);}@Testpublic void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {String mathodName = "method02";//   一定要创建一个实例AnnoMethods methods = new AnnoMethods();// 确定执行方法Class<?> methodsClass = methods.getClass();Class<?>[] classArr = new Class[]{String.class,String.class,String.class};Method method = methodsClass.getDeclaredMethod(mathodName, classArr);// 设置私有方法可达method.setAccessible(true);// 确定方法的参数Object[] valueArr = new Object[]{"peter","wanglili","xuanfeng"};// 执行方法 和返回值Object result = method.invoke(methods, valueArr);// 获取 该方法上面的注解 以及相关值TestAnno anno = method.getAnnotation(TestAnno.class);String shuXing1 = anno.shuXing1();int shuXing2 = anno.shuXing2();// 遍历进行输出System.out.println("下面是获取到的相关值,以及通过反射获取到的结果");System.out.println("执行方法为:"+mathodName);System.out.println("方法参数为:"+valueArr[0]+"******"+valueArr[1]+"******"+valueArr[2]);System.out.println("执行结果为:"+result);System.out.println("注解属性1的值为:"+shuXing1);System.out.println("注解属性2的值为:"+shuXing2);}@Testpublic void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {String mathodName = "method03";//   一定要创建一个实例AnnoMethods methods = new AnnoMethods();// 确定执行方法Class<?> methodsClass = methods.getClass();Class<?>[] classArr = new Class[]{};Method method = methodsClass.getDeclaredMethod(mathodName, classArr);// 设置私有方法可达method.setAccessible(true);// 确定方法的参数Object[] valueArr = new Object[]{};// 执行方法 和返回值Object result = method.invoke(methods, valueArr);// 获取 该方法上面的注解 以及相关值TestAnno anno = method.getAnnotation(TestAnno.class);String shuXing1 = anno.shuXing1();int shuXing2 = anno.shuXing2();// 遍历进行输出System.out.println("下面是获取到的相关值,以及通过反射获取到的结果");System.out.println("执行方法为:"+mathodName);System.out.println("方法参数为:");System.out.println("执行结果为:"+result);System.out.println("注解属性1的值为:"+shuXing1);System.out.println("注解属性2的值为:"+shuXing2);}@Testpublic void test04(){Class<AnnoMethods> methodsClass = AnnoMethods.class;TestAnno annotation = methodsClass.getAnnotation(TestAnno.class);String shuXing1 = annotation.shuXing1();int shuXing2 = annotation.shuXing2();System.out.println("类上注解属性1的值为:"+shuXing1);System.out.println("类上注解属性2的值为:"+shuXing2);}@Testpublic void test05() throws NoSuchFieldException, IllegalAccessException {AnnoMethods methods = new AnnoMethods();// 确定执行方法Class<?> methodsClass = methods.getClass();Field field = methodsClass.getDeclaredField("str");field.setAccessible(Boolean.TRUE);String fieldName = field.getName();Object o = field.get(methods);TestAnno annotation = field.getAnnotation(TestAnno.class);String shuXing1 = annotation.shuXing1();int shuXing2 = annotation.shuXing2();System.out.println(fieldName);System.out.println(o);System.out.println(shuXing1);System.out.println(shuXing2);}}

AOP+自定义注解:

AOP+自定义注解,是以自定义注解作为切面,进入动态代理,获取到被加注解的类、方法、变量的信息,结合注解的值,进行相关操作,比如:记录日志等;

参考文章 

配置流程如下(具体见本人demo):

  • 搭建SpringBoot项目,参考
  • 添加依赖
        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
  •  添加自定义注解
package com.example.demo.springAnnotation.AOP;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/***/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {String upDbName();
}
  •  添加自定义注解的解析类
package com.example.demo.springAnnotation.AOP;import com.example.demo.utils.IPAddressUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;/***/
@Component
@Aspect
@Slf4j
public class MyLogAspect {/***  IP 地址 解析工具类*/@Autowiredprivate IPAddressUtils ipAddressUtils;/*** 只要用到了com.javaxl.p2.annotation.springAop.MyLog这个注解的,就是目标类*/@Pointcut("@annotation(MyLog)")private void MyValid() {}/*    @Before("MyValid()")public void before(JoinPoint joinPoint) {log.info("----------Before开始-----------");MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();String classType = joinPoint.getTarget().getClass().getName();MyLog myLog = method.getAnnotation(MyLog.class);String desc = myLog.upDbName();//获取当前请求request对象ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();log.info("方法名:"+ signature.getName());log.info("参数值集合:"+ Arrays.asList(joinPoint.getArgs()));log.info("参数值类型:"+ joinPoint.getArgs()[0].getClass().getTypeName());log.info("获取目标方法所在类:"+ classType);log.info("指定注解MyLog的属性值为:"+desc);log.info("获取URI地址:"+request.getRequestURI());log.info("获取URL地址:"+request.getRequestURL());log.info("获取请求方式:"+request.getMethod());log.info("获取请求的ip地址:"+IPAddressUtils.getIpAdrress(request));log.info("----------Before结束-----------");}*//*    @After("MyValid()")public void after(JoinPoint joinPoint){log.info("后置通知");}*/@Around("MyValid()")public void around(ProceedingJoinPoint joinPoint)throws Throwable {log.info("----------Around开始-----------");log.info("=========================================================");log.info("==========================================================");log.info("===你可以根据获取到的信息进行任何操作,比如:进行日志的记录等!!!===");log.info("==========================================================");log.info("==========================================================");MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();String classType = joinPoint.getTarget().getClass().getName();MyLog myLog = method.getAnnotation(MyLog.class);String desc = myLog.upDbName();//获取当前请求request对象ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();log.info("方法名:"+ signature.getName());log.info("参数值集合:"+ Arrays.asList(joinPoint.getArgs()));log.info("参数值类型:"+ joinPoint.getArgs()[0].getClass().getTypeName());log.info("获取目标方法所在类:"+ classType);log.info("指定注解MyLog的属性值为:"+desc);log.info("获取URI地址:"+request.getRequestURI());log.info("获取URL地址:"+request.getRequestURL());log.info("获取请求方式:"+request.getMethod());log.info("获取请求的ip地址:"+IPAddressUtils.getIpAdrress(request));Object result = joinPoint.proceed();log.info("方法的执行结果:"+result);log.info("----------Around结束-----------");}}
  •  工具类:IP解析类
package com.example.demo.utils;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;@Slf4j
@Component
public class IPAddressUtils {/*** 获取IP地址*/public static String getIpAdrress(HttpServletRequest request) {String ipAddress = request.getHeader("X-Forwarded-For");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();if ("127.0.0.1".equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) {// 根据网卡取本机配置的IPInetAddress inet = null;try {inet = InetAddress.getLocalHost();} catch (Exception e) {log.error("根据网卡获取本机配置的IP异常=>", e.getMessage());}if (inet.getHostAddress() != null) {ipAddress = inet.getHostAddress();}}}// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) {if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}return ipAddress;}}
  • 添加Service及其实现
package com.example.demo.service;public interface LogService {String test01(String str1,String str2);Integer test02(Integer num1,Integer num2);
}
package com.example.demo.service.impl;import com.example.demo.service.LogService;
import com.example.demo.springAnnotation.AOP.MyLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;/*** @program: AnnotationDemo* @description:* @author: wjl* @create: 2023-12-13 00:49**/
@Service
@Slf4j
public class LogServiceImpl implements LogService {@Override@MyLog(upDbName = "redis")public String test01(String str1, String str2) {log.info("进入方法,参数方法分别为: {} ,{}",str1,str2);String str = str1+"==="+str2;return str;}@Override@MyLog(upDbName = "mysql")public Integer test02(Integer num1,Integer num2) {log.info("进入方法,参数方法分别为: {} ,{}",num1,num2);Integer num = num1+num2;return num;}
}
  •  添加Controller
package com.example.demo.controller;import com.example.demo.service.LogService;
import com.example.demo.springAnnotation.AOP.MyLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** @program: AnnotationDemo* @description:* @author: wjl* @create: 2023-12-01 00:02**/
@RestController
public class AopController {@Autowiredprivate LogService logService;@RequestMapping("test_01")public String testLogAspect01(@RequestParam("str1")String str1,@RequestParam("str2")String str2){String str = logService.test01(str1, str2);return str;}@RequestMapping("test_02")public Integer testLogAspect02(@RequestParam("num1")Integer num1,@RequestParam("num2")Integer num2){Integer num = logService.test02(num1, num2);return num;}}

 


拦截器+自定义注解:

拦截器+自定义注解:拦截器通常是获取链接的入口方法(一半以controller方法为主),然后通过反射获取到方法信息以及相关注解的信息进行相关操作,比如登录验证等

参考文章

配置流程如下(具体见本人demo):

  •  搭建SpringBoot项目,参考

  • 自定义注解
package com.example.demo.springAnnotation.INTERCEPT;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {String userName();}
  • 配置允许通过的请求和需要拦截的请求
package com.example.demo.springAnnotation.INTERCEPT;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** @program: AnnotationDemo* @description:* @author: wjl* @create: 2023-12-01 10:24**/
@Configuration
public class InterceptorTrainConfigurer implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new SourceAccessInterceptor()).addPathPatterns("/**")                        //需要拦截 验证的的.excludePathPatterns("/test_01","/test_02");   //需要放过的}
}
  • 配置拦截的请求,需要进行的操作
package com.example.demo.springAnnotation.INTERCEPT;import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;/*** @program: AnnotationDemo* @description:* @author: wjl* @create: 2023-12-01 10:21**/
public class SourceAccessInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("进入拦截器了");// 反射获取方法上的LoginRequred注解HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();LoginRequired loginRequired = method.getAnnotation(LoginRequired.class);if (loginRequired == null) {return true;}// 有LoginRequired注解说明需要登录,提示用户登录String userName = loginRequired.userName();response.setContentType("application/json; charset=utf-8");response.getWriter().println("你访问的资源需要登录");response.getWriter().println("注解的属性名为:"+userName);response.getWriter().println("访问的方法名为:"+method.getName());response.getWriter().println("返回的类型为:"+method.getReturnType().getName());response.getWriter().println("=========================================================");response.getWriter().println("=========================================================");response.getWriter().println("=====拦截器同样可以获取到各种属性,根据自身需要进行调用=============");response.getWriter().println("=========================================================");response.getWriter().println("=========================================================");return 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 {}
}
  • 配置Controller请求
package com.example.demo.controller;import com.example.demo.springAnnotation.INTERCEPT.LoginRequired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @program: AnnotationDemo* @description:* @author: wjl* @create: 2023-12-01 10:15**/
@RestController
public class InterceptController {@GetMapping("/sourceA")public String sourceA(){return "你正在访问sourceA资源";}@GetMapping("/sourceB")@LoginRequired(userName = "peter")public String sourceB(){return "你正在访问sourceB资源";}}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp:全局消息是推送,实现app在线更新,WebSocket,apk上传

全局消息是推送&#xff0c;实现app在线更新&#xff0c;WebSocket 1.在main.js中定义全局的WebSocket2.java后端建立和发送WebSocket3.通知所有用户更新 背景&#xff1a; 开发人员开发后app后打包成.apk文件&#xff0c;上传后通知厂区在线用户更新app。 那么没在线的怎么办&…

如何文件从电脑传到iPhone,这里提供几个方法

本文介绍了如何使用Finder应用程序、iTunes for Windows、iCloud和谷歌照片将照片从Mac或PC传输到iPhone。 如何将照片从Mac传输到iPhone 如果你有一台Mac电脑&#xff0c;里面装满了你想转移到iPhone的照片&#xff0c;这是一件非常简单的事情。只需遵循以下步骤&#xff1a…

参数归一化-实现时间格式化

文章目录 需求分析具体实现完整源码 不知道大家有没有尝试封装过一个时间格式化的函数啊&#xff0c;在之前我封装的时候&#xff0c;开始是觉得手到擒来&#xff0c;但是实践之后发现写非常的shi啊&#xff0c;大量的分支判断&#xff0c;哪怕是映射起到的作用也只是稍微好一点…

第二十一章Java网络通信

网络通信这一章 基本分为三个部分 网络基础概念和TCP,UDP这三个部分主要如下&#xff1a; 计算机网络实现了堕胎计算机间的互联&#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是再已连接的不同计算机上运行的程序&#xff0c;这些程序借助于网络协议&#x…

Java线上问题排查思路

1、Java 服务常见问题 Java 服务的线上问题从系统表象来看大致可分成两大类: 系统环境异常、业务服务异常。 系统环境异常&#xff1a;主要从CPU、内存、磁盘、网络四个方面考虑。比如&#xff1a;CPU 占用率过高、CPU 上下文切换频率次数较高、系统可用内存长期处于较低值、…

第二证券:普通人怎么选个股?

普通人怎么选个股 1、成果 成果是推动个股上涨的内在动力&#xff0c;即成果好的个股能推动个股持续上涨&#xff0c;成果差的个股会导致个股持续跌落&#xff0c;因而&#xff0c;投资者应该选择成果较好的个股。 2、资金 资金是影响股价涨跌的一重要因素&#xff0c;当资…

使用electron属性实现保存图片并获取图片的磁盘路径

在普通的网页开发中&#xff0c;JavaScript由于安全性的考虑&#xff0c;通常是无法直接获取到客户端的磁盘路径的。浏览器出于隐私和安全原因对此类信息进行了限制。 在浏览器环境下&#xff0c;JavaScript主要通过Web APIs来与浏览器进行交互&#xff0c;而这些API通常受到浏…

代码随想录-刷题第四十一天

343. 整数拆分 题目链接&#xff1a;343. 整数拆分 思路&#xff1a;动态规划五步曲 dp[i]&#xff1a;拆分数字i&#xff0c;可以得到的最大乘积为dp[i]。 递推公式&#xff1a;dp[i] max(dp[i], max((i - j) * j, dp[i - j] * j)) 从1遍历j&#xff0c;有两种渠道得到dp[…

媲美保时捷:小米汽车正式亮相| 一周 IT资讯

1、对标保时捷、特斯拉&#xff01;小米汽车首款产品发布 12月28日&#xff0c;万众瞩目之下&#xff0c;小米汽车首场技术发布会终于揭开神秘面纱&#xff0c;来自全国各地的米粉齐聚北京&#xff0c;共同见证了小米汽车的技术特色及优势。 在本次发布会上&#xff0c;小米汽…

数据库进阶教学——读写分离(Mycat1.6+Ubuntu22.04主+Win10从)

目录 1、概述 2、环境准备 3、读写分离实验 3.1、安装jdk 3.2、安装Mycat 3.3、配置Mycat 3.3.1、配置schema.xml ​​​​3.3.2、配置server.xml 3.4、修改主从机远程登陆权限 3.4.1、主机 3.4.2、从机 3.5、启动Mycat 3.6、登录Mycat 3.7、验证 1、概述 读写分…

【HarmonyOS开发】案例-记账本开发

OpenHarmony最近一段时间&#xff0c;简直火的一塌糊度&#xff0c;学习OpenHarmony相关的技术栈也有一段时间了&#xff0c;做个记账本小应用&#xff0c;将所学知识点融合记录一下。 1、记账本涉及知识点 基础组件&#xff08;Button、Select、Text、Span、Divider、Image&am…

TikTok真题第8天 | 418.屏幕可显示句子的数量、395.至少有K个重复字符的最长子串、1010.总持续时间可以被60整除的歌曲对

418.屏幕可显示句子的数量 题目链接&#xff1a;418.sentence-screen-fitting 解法&#xff1a; 这道题&#xff0c;看题解都很难看懂&#xff0c;哪怕看出点门道了&#xff0c;也很难用自己的话解释出来。 有几点必须清楚&#xff1a; &#xff08;1&#xff09;将字符串…

10. Opencv检测并截取图中二维码

1. 说明 在二维码扫描功能开发中,使用相机扫描图片时,往往图片中的信息比较多样,可能会造成二维码检测失败的问题。一种提高检测精度的方式就是把二维码在图片中单独抠出来,去除其它冗余信息,然后再去识别这张提取出来的二维码。本篇博客记录采用的一种实现二维码位置检测…

计算机网络——应用层与网络安全(六)

前言&#xff1a; 前几章我们已经对TCP/IP协议的下四层已经有了一个简单的认识与了解&#xff0c;下面让我们对它的最顶层&#xff0c;应用层进行一个简单的学习与认识&#xff0c;由于计算机网络多样的连接形式、不均匀的终端分布&#xff0c;以及网络的开放性和互联性等特征&…

L1-069:胎压监测

题目描述 小轿车中有一个系统随时监测四个车轮的胎压&#xff0c;如果四轮胎压不是很平衡&#xff0c;则可能对行车造成严重的影响。 让我们把四个车轮 —— 左前轮、右前轮、右后轮、左后轮 —— 顺次编号为 1、2、3、4。本题就请你编写一个监测程序&#xff0c;随时监测四轮的…

GaussDB数据库中的同义词SYNONYM

目录 一、前言 二、GasussDB数据库中的Synonym 1、Synonym的概念 2、语法介绍 3、Synonym的用途 三、Synonym在GaussDB数据库中是如何使用的 1、表的同义词使用&#xff08;示例&#xff09; 2、视图的同义词使用&#xff08;示例&#xff09; 3、函数的同义词使用&am…

分布式IO在工业自动化中的应用

传统的自动化产线及物流系统主要是利用PLC来处理数据&#xff0c;并将这些数据保存在PC当中。但是随着互联网技术的迅速发展&#xff0c;越来越多的系统集成商利用分布式IO模块&#xff0c;实现从控制器到自动化最底层之间的IO通信。 分布式IO在工业自动化中的应用 分布式IO是用…

Vue3+ElementPlus: 给点击按钮添加触发提示

一、需求 在Vue3项目中&#xff0c;有一个下载按钮&#xff0c;当鼠标悬浮在按钮上面时&#xff0c;会出现文字提示用户可以点击按钮进行数据的下载技术栈 Vue3 ElementPlusTooltip组件 ElementPlus中的Tooltip组件 &#xff0c;可用于展示鼠标 hover 时的提示信息 二、实现…

【SD】IP-Adapter 进阶 - 垫图 【1】

目录 关于SD1.5的画风迁移 修改动作-方法一&#xff1a;提示词 修改动作-方法二&#xff1a;openpose 关于SD1.5的画风迁移 1.5测试模型&#xff1a;flat2DAnimerge_v30_2.safetensors [b2c93e7a89] 测试图&#xff1a; 文生图&#xff1a;best quality,masterpiece, co…

GPT-5、开源、更强的ChatGPT!

年终岁尾&#xff0c;正值圣诞节热闹气氛的OpenAI写下了2024年的发展清单。 OpenAI联合创始人兼首席执行官Sam Altman在社交平台公布&#xff0c;AGI&#xff08;稍晚一些&#xff09;、GPT-5、更好的语音模型、更高的费率限制&#xff1b; 更好的GPTs&#xff1b;更好的推理…