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

news2025/2/11 9:24:40

参考资料:

参考视频

拦截器自定义注解

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 {

    @Test
    public 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);
    }

    @Test
    public 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);
    }

    @Test
    public 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);
    }

    @Test
    public 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);
    }

    @Test
    public 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 地址 解析工具类
     */
    @Autowired
    private 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)) {
                // 根据网卡取本机配置的IP
                InetAddress 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 {

    @Autowired
    private 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 {
    @Override
    public 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 {
    @Override
    public 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;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public 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://www.coloradmin.cn/o/1335744.html

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

相关文章

智能优化算法应用:基于减法平均算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于减法平均算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于减法平均算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.减法平均算法4.实验参数设定5.算法结果6.…

[C/C++]数据结构 希尔排序

&#x1f966;前言: 希尔排序也称 “缩小增量排序”&#xff0c;它也是一种插入类排序的方法,在学习希尔排序之前我们首先了解一下直接插入排序. 一: &#x1f6a9;直接插入排序 1.1 &#x1f31f;排序思路 直接插入排序的基本原理是将一条记录插入到已排好的有序表中&#x…

微信小程序开发系列-01创建一个最小的小程序项目

本文讲述了通过微信开发者工具&#xff0c;创建一个新的小程序项目&#xff0c;完全从零开始&#xff0c;不依赖开发者工具的模板。目的是为了更好的理解小程序工程项目的构成。 文章目录 创建一个空项目app.json全局配置pagessitemapLocation app.js 创建一个空项目 打开微信…

Android 11.0 系统默认打开OEM解锁开关功能实现

1.前言 在11.0的系统rom定制化开发中,在9.0系统以后为了设备的安装,系统开始启用oem机制,所以在adb push文件就需要先oem解锁,然后才可以 进行相关操作,所以就需要默认打开oem解锁的开关,来方便oem解锁功能的实现 如图: 2.系统默认打开OEM解锁开关功能实现的核心类 pac…

大数据Doris(四十一):物化视图简单介绍

文章目录 物化视图简单介绍 一、适用场景

Apache Commons Math: 面向Java的数学和统计库

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们今天要聊的是Apache Commons Math这个宝藏级的Java库。为啥说它是宝藏呢&#xff1f;因为它简直就是处理数学问题的瑞士军刀&#xff0c;无论你是要搞统计分析、数值计算&#xff0c;还是解决优化问题&#…

微信小程序备案流程整理

一、备案流程 [找备案入口]–[填主体信息]–[填小程序信息]–[初审]–[短信核验]–[通管局审核] 1&#xff0c;在小程序后台找到备案入口 &#xff08;1&#xff09;新的未上架小程序&#xff0c;可以在小程序首页点击【去备案】进入。 &#xff08;2&#xff09;已上架小程…

智能优化算法应用:基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.袋獾算法4.实验参数设定5.算法结果6.参考文献7.MA…

【Midjourney】Midjourney提示词格式详解

目录 &#x1f347;&#x1f347;Midjourney是什么&#xff1f; &#x1f349;&#x1f349;Midjourney怎么用&#xff1f; &#x1f514;&#x1f514;Midjourney提示词格式 &#x1f341; 1.模型版本提示词&#x1f341; 参数 参数详解 应用示例 &#x1f343; 2.风格…

小狐狸GPT付费2.4.9 去除授权弹窗版

后台安装步骤&#xff1a; 1、在宝塔新建个站点&#xff0c;php版本使用7.2 、 7.3 或 7.4&#xff0c;把压缩包上传到站点根目录&#xff0c;运行目录设置为/public 2、导入数据库文件&#xff0c;数据库文件是 /db.sql 3、修改数据库连接配置&#xff0c;配置文件是/.env 4、…

三列布局 css

实现如下图的三列布局&#xff1a; .box {width:1400px;margin:0 auto;padding-bottom:40px;> .left {float:left;width:180px;margin-top:100px;text-align:center;}> .center {float:left;margin-top:100px;margin-left:130px;item-box {float:left;text-align:left;…

RPC(6):RMI实现RPC

1RMI简介 RMI(Remote Method Invocation) 远程方法调用。 RMI是从JDK1.2推出的功能&#xff0c;它可以实现在一个Java应用中可以像调用本地方法一样调用另一个服务器中Java应用&#xff08;JVM&#xff09;中的内容。 RMI 是Java语言的远程调用&#xff0c;无法实现跨语言。…

蓝牙物联网通信网络设计方案

随着当前经济的快速发展&#xff0c;社会运行节奏加快&#xff0c;人们更倾向于选择高效的出行方式&#xff0c;而飞机就是其中之一。近年来&#xff0c;全国各地机场的吞吐量不断增长&#xff0c;导致航站楼面积过大&#xff0c;而 GPS全球定位系统在室内感测不到卫星信号无法…

Java开发框架和中间件面试题(5)

44.Tomcat一个请求的处理流程&#xff1f; 假设来自客户的请求为&#xff1a; http&#xff1a;//localhost&#xff1a;8080/test/index.jsp请求被发送到本机端口8080&#xff0c;被在那里侦听Copote HTTP/1.1 Connector,然后 1.Connector把该请求交给它所在的Service的Engi…

(GCC) 库的操作

文章目录 预备静态库生成链接环境区别 动态库生成链接环境区别 END参考ar指令 预备 准备两个文件&#xff0c;以最简单的形式进行展示。 add.c int add(int x, int y) {return x y; }main.c 为了方便直接在头文件中声明函数 #include <stdio.h>extern int add(int,…

Python电能质量扰动信号分类(三)基于Transformer的一维信号分类模型

目录 引言 1 数据集制作与加载 1.1 导入数据 1.2 制作数据集 2 Transformer分类模型和超参数选取 2.1 定义Transformer分类模型 2.2 定义模型参数 3 Transformer模型训练与评估 3.1 模型训练 3.2 模型评估 代码、数据如下&#xff1a; 往期精彩内容&#xff1a; 电…

Leetcode—86.分隔链表【中等】

2023每日刷题&#xff08;六十九&#xff09; Leetcode—86.分隔链表 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* partition(struct ListNode* head, int x) {struct ListNode…

实验室安全教育考试管理系统v3.0功能介绍

瑞熙贝通实验室安全练习和在线考试系统&#xff0c;采取线上培训学习与安全考试相结合的教学形式&#xff0c;在学生进入开放实验室之前通过系统对实验的安全与规范有一个系统的认识与学习。通过线上考试系统&#xff0c;为评价学生的实验室安全学习效果提供了快速有效的实验平…

【bug】uniapp一键登录,自定义协议条款是否支持内部路由?

uniapp一键登录的自定义协议条款&#xff0c;不支持内部路由跳转 在uniapp文档上搜一键登录 加二维码之后可以提问

动态内存管理(补)

1.内核空间的代码为操作系统 2.栈区&#xff1a;函数内局部变量在栈区上创建&#xff0c;执行结束后其所占空间被自动释放&#xff0c;栈区的内存运算内置于处理器的指令集中&#xff0c;效率高&#xff0c;但容量有限。栈区主要存放函数的局部变量&#xff0c;函数参数&#…