day61_SSM+自定义注解实现日志记录

news2024/11/15 15:54:19

SSM+自定义注解+AOP实现日志记录

1 需求

工作中,经常会遇到记录日志的动作,以前是使用日志框架来实现,现在可以使用注解来实现,使用起来更方便,随用随加~


今天我们演示在SSM的基础上,对普通的方法加上自定义注解,注解中写上该方法的日志信息,然后将日志信息记录到数据库中.

编号用户ip时间描述
1admin192.168.37.452023-01-01 17:56:00修改了user信息
2zs192.168.37.352023-02-01 17:56:00登录

2 技术

Spring+AOP+SpringMVC+Mybatis+注解+反射

3 注解(annotation)

注解,又称为注释.它是给程序看的注释.JDK1.5以后出现的新技术

常见注解: @Override

3.1 创建注解文件

public @interface MyLog {
}

3.2 设置元注解

  • 元注解是给注解加的注解
  • @Target 作用位置
  • @Retention 保留策略
  • @Documented 不用
  • @Inherited 不用

3.2.1 @Target

定义注解使用的位置

使用位置EmentType
packaget包上PACKAGE
/接口/数组/枚举/注解TYPE
类型成员(方法/构造方法/成员变量/枚举值)CONSTRUCTOR
FIELD
METHOD
方法中的参数/局部变量LOCAL_VARIABLE
PARAMETER

3.2.2 @Retention

指定注解的保留策略,即注解在什么时期生效.

RetentionPolicy的值作用
SOURCE在源文件中有效
CLASS在class文件中有效
RUNTIME在运行时有效(即运行时保留),为Runtime可以在反射机制中读取

3.3 设置参数

@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {

    String log(); // 设置了参数,使用注解时必须给该参数赋值

    int type() default 0; // 如果给了default,如果不设置参数,那就是默认值

    // 当参数命名为是其他值时,使用时必须写上参数=值,
    String value();// 当参数名设置成value时,单独使用时可以直接写值,不需要写value属性

}

4 反射

在程序==运行过程==中,获得字节码class文件,从而获得其中的属性和方法包括构造方法.以便于使用这些属性和方法.

4.1 获得字节码文件

    public static void main(String[] args) throws ClassNotFoundException {
        // 获得字节码文件
        // 1.类的静态方法
        Class clazz1 = User.class;

        // 2. Object类的getClass()
        User user = new User( );
        Class clazz2 = user.getClass( );

        // 3.通过类路径获得
        Class clazz3 = Class.forName("com.qf.model.User");
    }

4.2 获得并使用属性

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Class clazz = User.class;

        // 获得属性
        /**
         * getFiled()
         * getFields()
         * 获得公共的属性,即只能获得public修饰的属性
         */
        Field username =  clazz.getField("age");// 根据字段名,获得字段对象
        System.out.println(username );
        Field[] fields = clazz.getFields( ); // 所有字段对象
        for (Field field: fields) {
            System.out.println(field );
        }
        System.out.println("---------" );
        /**
         * getDeclaredField()
         * getDeclaredFields()
         * 获得所声明的所有字段
         */
        Field username1 = clazz.getDeclaredField("username");
        System.out.println(username1 );
        Field[] declaredFields = clazz.getDeclaredFields( );
        for (Field f : declaredFields) {
            System.out.println(f );
        }

        // ==============================
        // 给属性赋值
        User user = new User( );
        user.setPassword("66666");
        Field password = clazz.getDeclaredField("password");

        // 设置访问权限
        password.setAccessible(true);

        // 无法获得私有属性值
        String o = (String)password.get(user);
        System.out.println("利用反射获得字段值: "+o );


        // 需要先设置访问权限
        username1.setAccessible(true);

        // 不能只能直接给私有属性赋值
        username1.set(user,"随意");

        System.out.println(user.getUsername() );
    }

4.3 获得并使用方法

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class clazz = User.class;

        // 获得方法
        /**
         * getMethod(); 只会获得public修饰的方法
         * getDeclaredMethod() 获得所有方法,包括非私有
         */
        Method add1 = clazz.getMethod("add");// 获得的是方法名叫做add的方法,且空参
        Method add2 = clazz.getMethod("add", int.class, int.class);// 获得add方法,且有两个参数,类型是int,int
        Method add3 = clazz.getMethod("add", String.class, String.class);// 获得add方法,且有两个参数,类型是String,String

        // 使用方法
        User user = new User( );
        // add1.setAccessible(true);
        Object r1 = add1.invoke(user);
        System.out.println(r1 );

        Object r2 = add2.invoke(user, 2, 2);
        System.out.println(r2 );

        Object r3 = add3.invoke(user, "4", "4");
        System.out.println(r3 );
    }

4.4 获得并使用构造方法

    public static void main(String[] args) throws Exception {
        Class clazz = User.class;
        /**
         * getConstructor() 获得public修饰构造方法
         * getDeclaredConstructor() 获得所有构造方法,包括私有
         */
        Constructor constructor = clazz.getConstructor( );// 获得空参构造

        // 使用构造方法
        Object o = constructor.newInstance( );// 创建对象
        System.out.println(o );
    }

5 AOP

AOP面向切面(Aspect)编程

面向切面编程的作用:就是将项目中与核心逻辑无关的代码横向抽取成切面类,通过织入作用到目标方法,以使目标方法执行前后达到增强的效果.

原理: AOP底层使用的就是动态代理,给AOP指定哪些类型需要增强,就会产生对应的代理对象,代理对象执行方法前后会先执行增强的方法.

好处:

  • 抽取代码,复用,提高效率
  • 减少耦合
  • 利于代码扩展

image-20221031195155129

AOP的术语:

目标类(Target): 被代理的类

连接点(JoinPoint): 目标类中准备被切入的方法

切入点(Pointcut): 真正执行的目标方法

切面(Aspect) : 切面中定义中增强的方法

增强(Advice): 也叫通知,就是在目标方法执行前/后的方法

织入(Weaving): 将增强作用到切入点的过程

6 SSM环境

对User表进行操作

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `gender` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `tel` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=DYNAMIC;
INSERT INTO `user` VALUES (1, '张三', 29, '女', '19593741393');
INSERT INTO `user` VALUES (2, '李四', 12, '男', '19593741393');
INSERT INTO `user` VALUES (3, '王五', 32, '女', '19593741393');
INSERT INTO `user` VALUES (5, '赵六', 55, '男', '19593741393');
INSERT INTO `user` VALUES (6, '李青', 62, '男', '19593741393');
INSERT INTO `user` VALUES (7, '福雷格斯', 58, '男', '19693741393');
INSERT INTO `user` VALUES (8, '赵信', 53, '男', '19593741393');
INSERT INTO `user` VALUES (10, '易大师', 70, '男', '19393741393');
INSERT INTO `user` VALUES (11, '蛮族之王', 28, '女', '19293741393');

6.1 pom依赖

<?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>com.qf</groupId>
    <artifactId>ssm_crud_annotation_log</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- SpringMVC依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.16.RELEASE</version>
        </dependency>
        <!-- Spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.16.RELEASE</version>
        </dependency>
        <!-- spring面向切面 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.16.RELEASE</version>
        </dependency>
        <!-- spring单元测试 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.16.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <!-- Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        
        <!--Mybatis-spring适配包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <!-- 数据库连接池,驱动-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
        <!--数据库连接必须-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!-- json处理-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.1</version>
        </dependency>
    </dependencies>
	<!-- 当mapper在java下时需要设置 -->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>*.xml</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>

6.2 配置文件

6.2.1 applicationContext.xml

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 注解扫描 -->
    <context:component-scan base-package="com.qf">
        <!--排除controller控制器的包-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 1加载db.properties
        classpath类路径,即项目的根路径
    -->
    <context:property-placeholder location="classpath:db.properties"/>

    <!-- 2创建数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!-- 注意属性名,要换成driverClassName -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="${jdbc.initialSize}"/>
        <property name="minIdle" value="${jdbc.minIdle}"/>
        <property name="maxActive" value="${jdbc.maxActive}"/>
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="${jdbc.maxWait}"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}"/>
    </bean>


    <!-- 3创建SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 加载mybatis配置文件 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!-- 加载数据源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 4创建Mapper扫描器 -->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- spring扫描mapper所在包,就可以创建接口的代理对象 -->
        <property name="basePackage" value="com.qf.mapper"/>
        <!-- 指定SqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
</beans>

6.2.2 springmvc.xml

<?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/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--  配置扫描包-->
    <context:component-scan base-package="com.qf">
        <!-- 只扫描控制器-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 注解驱动 -->
    <mvc:annotation-driven/>
</beans>

6.2.3 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 开启下划线转驼峰 -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <typeAliases>
        <package name="com.qf.model"/>
    </typeAliases>
</configuration>

6.2.4 db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_log?useSSL=false
jdbc.username=root
jdbc.password=123456
jdbc.initialSize=5
jdbc.minIdle=3
jdbc.maxActive=20
jdbc.maxWait=0
jdbc.timeBetweenEvictionRunsMillis=600000
jdbc.minEvictableIdleTimeMillis=300000

6.2.5 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--服务器启动的时候,加载这个全局配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <!-- 监听服务器启动 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--注册前端控制器DispatcherServlet-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--给当前的Servlet配置初始化参数-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--配置DispatcherServlet的映射路径-->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <!--编码格式过滤器-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

6.3 实体类

package com.qf.model;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class User {

    private Integer id;
    private String name;
    private Integer age;
    private String gender;
    private String tel;
    // setter & getter
}

6.4 查询全部

6.4.1 UserMapper

package com.qf.mapper;

import com.qf.model.User;

import java.util.List;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public interface UserMapper {

    List<User> selectAll();

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qf.mapper.UserMapper">

    <select id="selectAll" resultType="User">
        select * from user;
    </select>

</mapper>

6.4.2 UserService

package com.qf.service;

import com.qf.model.User;

import java.util.List;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public interface UserService {

    List<User> selectAll();

}

package com.qf.service.impl;

import com.qf.mapper.UserMapper;
import com.qf.model.User;
import com.qf.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> selectAll() {
        return userMapper.selectAll();
    }
}

6.4.3 UserController

package com.qf.controller;

import com.qf.model.User;
import com.qf.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
@RestController // 该类中所有方法返回的都是JSON数据
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/list")
    public List<User> selectAll() {
        return userService.selectAll();
    }

}

6.5 测试

启动服务器,测试

7 自定义注解实现日志记录[重点]

首先设计日志表,将来存储日志信息

CREATE TABLE `log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `log_time` datetime DEFAULT NULL,
  `log` varchar(255) DEFAULT NULL,
  `ip` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ps: 数据库字段是下划线,mybatis配置文件中要开驼峰转换才可以自动完成orm.

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
// 日志类
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Log {

    private int id;
    private String name;
    private Date logTime;
    private String log;
    private String ip;

}

7.1 日志注解文件

package com.qf.annotation;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
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 value();
}

7.2 切面类

package com.qf.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import com.qf.annotation.MyLog;
import com.qf.model.Log;
import com.qf.model.User;
import com.qf.service.MyLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
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 org.springframework.web.util.WebUtils;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
@Component
@Aspect
public class MyLogAspect {

    @Autowired
    private MyLogService logService;

    /**
     * 后置增强
     */
    @After("@annotation(com.taotie.aop_log_aspect.Log)")
    public void saveLog(JoinPoint joinPoint) {
        // 1 获得时间
        Date date = new Date( );

        // 2 获得ip
        // 3 获得当前操作的用户名
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes( )).getRequest( );
        // 当时登录成功后,存入session数据,session中的key为user
        User user = (User) WebUtils.getSessionAttribute(request, "user");
        String username = null;
        if (user != null) {
            username = user.getUsername();
        }
        String ip = request.getRemoteAddr( );

        // 4 获得日志描述
        // 获得目标类
        Object target = joinPoint.getTarget( );
        Method[] declaredMethods = target.getClass( ).getDeclaredMethods( );
        String logDesc = null;
        String targetMethodName = joinPoint.getSignature( ).getName( );
        for (Method method : declaredMethods) {
            if (method.getName().equals(targetMethodName)) {
                Log log = method.getAnnotation(Log.class);
                if (log != null) {
                    logDesc = log.value( );
                }
            }
        }

        com.taotie.model.Log log = new com.taotie.model.Log( );
        log.setIp(ip);
        log.setName(username);
        log.setLogTime(date);
        log.setLog(logDesc);

        /**
         * 插入数据库
         */
        logService.saveLog(log);

    }
}

7.3 使用注解

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/login")
    public User login(String name, HttpSession session) {
        User user = userService.selectUserByUsername(name);

        if (user != null) {
            session.setAttribute("user",user);
        }
        return user;
    }


    @GetMapping("/list")
    @MyLog("查询全部") // 使用日志注解
    public List<User> selectAll() {
        return userService.selectAll();
    }
}

7.4 aop扫描

    <!-- 开启aop注解
日志注解加在业务层,aop注解驱动设置在applicationContext.xml 
日志注解加在控制层,aop注解驱动设置在springmvc.xml
-->
    <aop:aspectj-autoproxy/>

7.5 测试

浏览器访问测试

image-20221030224401686

ip是因为使用localhost访问,换成127.0.0.1来访问就会正常

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

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

相关文章

时间序列预测 | Matlab移动平均模型MA时间序列预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列预测 | Matlab移动平均模型MA时间序列预测 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源码 %% 清空环境变量 warning off % 关闭报警信息…

Go 并发模型—Goroutines

前言 Goroutines 是 Go 语言主要的并发原语。它看起来非常像线程&#xff0c;但是相比于线程它的创建和管理成本很低。Go 在运行时将 goroutine 有效地调度到真实的线程上&#xff0c;以避免浪费资源&#xff0c;因此您可以轻松地创建大量的 goroutine&#xff08;例如每个请求…

win11病毒和防护功能显示‘页面不可用’的解决方法

问题如上图所示&#xff0c;试了很多种方法&#xff0c;有一种是可以用的&#xff0c;记录一下。 步骤&#xff1a; 1、搜索框输入cmd&#xff0c;以管理员身份运行命令提示符 2、输入 第一条代码 reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows D…

吉他谱如何自动播放?个人乐谱播放网站YUERGS搭建

吉他谱如何自动播放&#xff1f;个人乐谱播放网站YUERGS搭建 背景介绍网站布局技术栈代码结构吉他谱文件结构滚动播放 背景 我是一个吉他弹唱爱好者&#xff0c;我的吉他谱都是自己在网络上收集到的图片&#xff0c;一般一首曲子都是好几张图片组成的。当我在弹吉他时&#xf…

#systemverilog# 进程控制问题#(五)关于 disable fork的陷阱

一 概念回顾 SV中的进程包括:静态进程、动态进程。 静态进程:initial、always、fork...join 发起; 动态进程:fork...join_any 、fork...join_none 发起; 注意,以下情形,进程(process)会产生相应的线程(thread)。 (1)initial 、always 执行,会产生相应的线程 (…

[VUE学习]权限管理系统前端vue实现8-右上角用户头像显示实现

1.登录成功之后存储 用户信息 在store里面添加代码 SET_USERINFO: (state, userInfo) > {sessionStorage.setItem("userInfo", JSON.stringify(userInfo))},GET_USERINFO: state > {return JSON.parse(sessionStorage.getItem("userInfo"))} 2.Logi…

顺利通过高项

这里有我自己手敲的2022年12月改版后&#xff08;最新&#xff09;的十个项目管理的过程&#xff0c;包括他们的输入、输出、工具与技术&#xff0c;还有各个过程的作用&#xff1a; 然后还有十篇自己写的论文&#xff1a; 更有第四版的教程&#xff08;PDF版&#xff09;&a…

❤️创意网页:动态彩色泡泡页面(HTML+CSS+JS)简单好用

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

二叉搜索树的第K大节点

还是做简单题有成就感&#xff0c;看到题就有了想法&#xff0c;先来一个中序遍历放到一个容器里面&#xff0c;然后按下标找到第k大的数就行&#xff0c;这是我的代码。 class Solution {Deque<Integer> deque new LinkedList<Integer>();public int kthLargest…

Android NTP时间同步源码分析

Android NTP时间同步源码分析 Android系统设置自动时间后&#xff0c;如果连接了可用的网络。会同步网络时间。这个处理是 NetworkTimeUpdateService完成的。某些定制化的系统&#xff0c;需要禁止网络时间同步。比如仅仅使用GPS时间。基于Android9&#xff0c;分析一下 Andro…

高效协作助力企业发展:企业网盘在提升工作效率方面的重要作用!

企业网盘是一种专门为了企业协作工作而设计的在线文档管理平台&#xff0c;受到了众多企业用户的青睐与喜爱。企业网盘如何大幅提高企业协作工作效率&#xff1f; 1、提高文件访问效率 传统的文件共享方式往往使用邮件附件或U盘进行传递&#xff0c;可能会遇到文档版本不一致、…

我用Python破解了邻居家的WiFi,从此实现了流量自由

前言 先声明一下&#xff0c;并不是一直白嫖邻居家的WiFi&#xff0c;emmmmmm事情是这样的 周六在家休息&#xff0c;突然领导来了个急活让我搞一下&#xff0c;虽然只花费一点时间&#xff0c;但是我内心是表示不愿意的&#xff0c;毕竟周六是我的私人休息时间&#xff0c;但…

Matlab画二维、三维等T0构造图(或称为等高线图)

clc;clear;close all; data xlsread(J-UNCONFORMITY等T0构造.xlsx); x data(:,1) xmax max(x); xmin min(x); y data(:,2) ymax max(y); ymin min(y); z data(:,3); N …

HBuilder:开发者之梦的实现

目录 引言关于HBuilderHBuilder的优点&#xff1a;HBuilder的缺点&#xff1a;HBuilder使用的简单示例总结 Hbuilder 官网 引言 在当今数字化时代&#xff0c;移动应用程序开发已经成为了一个全球热门的领域。伴随着智能手机和移动设备的普及&#xff0c;人们对于移动应用的需求…

Canal adapter同步MySQL到ES,部分时间字段始终同步不过来

解决思路&#xff1a;把查出来的字符串格式化一下 MySQL查出来的20180116120000这个如何转换成2018-01-16 这是一个常见的需求&#xff0c;我们通常在MySQL中使用DATE或DATETIME函数将字符串格式转换为日期或日期时间格式。但是&#xff0c;你的数字并不符合MySQL直接转换的标…

论文解读:PeSTo:用于精确预测蛋白质结合界面的无参数几何深度学习

Title:PeSTo: parameter-free geometric deep learning for accurate prediction of protein binding interfaces 期刊&#xff1a;nature communication 分区&#xff1a;一区 影响因子&#xff1a;16.6 webserver:t Pesto Github:GitHub - LBM-EPFL/PeSTo 摘要 蛋白质是…

Self-supervised Graph Learning for Recommendation(SGL)

Code&#xff1a;GitHub - wujcan/SGL-Torch: SGL PyTorch version&#xff08;作者给出了Pytorch和Tensorflow两个版本&#xff09; 本文提出了一种应用于用户-物品二分图推荐系统的图自监督学习框架。核心的思想是&#xff0c;对用户-物品二部图做数据增强&#xff08;本文提…

ActiveMQ一文解读

消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用耦合、异步消息、流量削锋等问题&#xff0c;实现高性能、高可用、可伸缩和最终一致性架构&#xff0c;是大型分布式系统不可缺少的中间件。 目前在生产环境中使用较多的消息队列有 ActiveMQ、RabbitMQ、ZeroM…

42. 会话划分问题

文章目录 题目需求思路一实现一题目来源 题目需求 现有页面浏览记录表&#xff08;page_view_events&#xff09;如下&#xff0c;每行数据代表&#xff1a;每个用户的每次页面访问记录。 规定若同一用户的相邻两次访问记录时间间隔小于60s&#xff0c;则认为两次浏览记录属于…

紧急提醒,你的计算机或许已中招,赶快进行排查

大家早上好&#xff0c;我是YUAN。 这几天&#xff0c;安全圈又曝出了一个重大漏洞。如果你的电脑使用的是技嘉-GIGABYTE主板&#xff0c;那么你可能已经中招了&#xff0c;但还不知情。 在介绍这个漏洞之前&#xff0c;让我们思考一个问题&#xff1a;如果产品经理让你实现一…