spring事务方法调用不生效的场景

news2024/9/20 22:39:00

 同一个类中,事务方法调用非事务方法时,事务是可以生效的。反例事务不生效见以下 4. 同一个类中,方法内部调用

@Autowired
private XXXMapper xxxMapper;

@Autowired

private YYYMapper yyyMapper;

@Transactional
public ResultVO<AssetChangeVO> changeAssetDetail{
      xxxMapper.execute();
}
private void copyYYY()
{
  yyyMapper.copy("xxx","yyy");
}

  • 前言

  • 1. 你的service类没有被Spring管理

  • 2.没有在Spring配置文件中启用事务管理器

  • 3. 事务方法被final、static关键字修饰

  • 4. 同一个类中,方法内部调用

  • 5.方法的访问权限不是public

  • 6. 数据库的存储引擎不支持事务

  • 7 .配置错误的 @Transactional 注解

  • 8.事务超时时间设置过短

  • 9. 使用了错误的事务传播机制

  • 10. rollbackFor属性配置错误

  • 11.事务注解被覆盖导致事务失效

  • 12.嵌套事务的坑

  • 13. 事务多线程调用

  • 14.异常被捕获并处理了,没有重新抛出

  • 15. 手动抛了别的异常

图片


前言

日常开发中,我们经常使用到spring事务。最近一位朋友去美团面试,被问了这么一道面试题: Spring 事务在哪几种情况下会不生效? 今天田螺哥跟大家聊聊,spring事务不生效 的15种场景。

图片

1. 你的service类没有被Spring管理

//@Service (注释了@Service)
public class TianLuoServiceImpl implements TianLuoService {

    @Autowired
    private TianLuoMapper tianLuoMapper;
    
     @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional
    public void addTianLuo(TianLuo tianluo) {
        //保存tianluo实体数据库记录
        tianLuoMapper.save(tianluo);
        //保存tianluo流水数据库记录
        tianLuoFlowMapper.saveFlow(buildFlowByTianLuo(tianluo));
    }
}
  • 事务不生效的原因 :上面例子中, @Service注解注释之后,spring事务(@Transactional)没有生效,因为Spring事务是由AOP机制实现的,也就是说从Spring IOC容器获取bean时,Spring会为目标类创建代理,来支持事务的。但是@Service被注释后,你的service类都不是spring管理的,那怎么创建代理类来支持事务呢 。

  • 解决方案 :加上@Service注解。

2.没有在Spring配置文件中启用事务管理器

@Configuration
public class AppConfig {
    // 没有配置事务管理器
}

@Service
public class MyService {
    @Transactional
    public void doSomething() {
        // ...
    }
}
  • 事务不生效的原因 :没有在AppConfig中配置事务管理器,因此Spring无法创建事务代理对象,导致事务不生效。即使在MyService中添加了@Transactional注解,该方法也不会被Spring管理的事务代理拦截。

  • 解决方案 :为了解决这个问题,应该在AppConfig中配置一个事务管器。例如:

@Configuration
public class AppConfig {
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

@Service
public class MyService {
    @Transactional
    public void doSomething() {
        // ...
    }
}

如果是Spring Boot项目,它默认会自动配置事务管理器并开启事务支持。

3. 事务方法被final、static关键字修饰

@Service
public class TianLuoServiceImpl  {

    @Autowired
    private TianLuoMapper tianLuoMapper;
    
    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional
    public final void addTianLuo(TianLuo tianluo) {
         //保存tianluo实体数据库记录
        tianLuoMapper.save(tianluo);
        //保存tianluo流水数据库记录
        tianLuoFlowMapper.saveFlow(buildFlowByTianLuo(tianluo));
    }
}
  • 事务不生效的原因 :如果一个方法被声明为final或者static,则该方法不能被子类重写,也就是说无法在该方法上进行动态代理,这会导致Spring无法生成事务代理对象来管理事务。

  • 解决方案 :addTianLuo事务方法 不要用final修饰或者static修饰。

4. 同一个类中,方法内部调用

@Service
public class TianLuoServiceImpl implements TianLuoService {

    @Autowired
    private TianLuoMapper tianLuoMapper;
    
    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;
    
    public void addTianLuo(TianLuo tianluo){
     // 调用内部的事务方法
     this.executeAddTianLuo(tianluo);
   }

    @Transactional
    public void executeAddTianLuo(TianLuo tianluo) {
        tianLuoMapper.save(tianluo);
        tianLuoFlowMapper.saveFlow(buildFlowByTianLuo(tianluo));
    }
}
  • 事务不生效的原因 : 事务是通过Spring AOP代理来实现的,而在同一个类中,一个方法调用另一个方法时,调用方法直接调用目标方法的代码,而不是通过代理类进行调用 。即以上代码,调用目标executeAddTianLuo方法不是通过代理类进行的,因此事务不生效。

  • 解决方案 :可以新建多一个类,让这两个方法分开,分别在不同的类中。如下:

@Service
public class TianLuoExecuteServiceImpl implements TianLuoExecuteService {

    @Autowired
    private TianLuoMapper tianLuoMapper;
    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;
    
    @Transactional
    public void executeAddTianLuo(TianLuo tianluo) {
        tianLuoMapper.save(tianluo);
        tianLuoFlowMapper.saveFlow(buildFlowByTianLuo(tianluo));
    }
}

@Service
public class TianLuoAddServiceImpl implements TianLuoAddService {

    @Autowired
    private TianLuoExecuteService tianLuoExecuteService;
    
    public void addTianLuo(User user){
     tianLuoExecuteService.executeAddTianLuo(user);
   }
}

当然,有时候你也可以在该 Service 类中注入自己,或者通过AopContext.currentProxy()获取代理对象。

5.方法的访问权限不是public

@Service
public class TianLuoServiceImpl implements TianLuoService {

    @Autowired
    private TianLuoMapper tianLuoMapper;
    
    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional
    private void addTianLuo(TianLuo tianluo) {
        tianLuoMapper.save(tianluo);
        tianLuoFlowMapper.saveFlow(buildFlowByTianLuo(tianluo));
    }
}
  • 事务不生效的原因 :spring事务方法addTianLuo的访问权限不是public,所以事务就不生效啦,因为Spring事务是由AOP机制实现的,AOP机制的本质就是动态代理,而代理的事务方法不是public的话,computeTransactionAttribute()就会返回null,也就是这时事务属性不存在了。大家可以看下AbstractFallbackTransactionAttributeSource的源码:

图片

  • 解决方案 :addTianLuo事务方法的访问权限修改为public

6. 数据库的存储引擎不支持事务

Spring事务的底层,还是依赖于数据库本身的事务支持。在MySQL中,MyISAM存储引擎是不支持事务的,InnoDB引擎才支持事务。因此开发阶段设计表的时候,确认你的选择的存储引擎是支持事务的 。

图片

7 .配置错误的 @Transactional 注解

@Transactional(readOnly = true)
public void updateUser(User user) {
    userDao.updateUser(user);
}
  • 事务不生效的原因 :虽然使用了@Transactional注解,但是注解中的readOnly=true属性指示这是一个只读事务,因此在更新User实体时会抛出异常。

  • 解决方案 :将readOnly属性设置为false,或者移除了@Transactional注解中的readOnly属性。

8.事务超时时间设置过短

@Transactional(timeout = 1)
public void doSomething() {
    //...
}
  • 事务不生效的原因 :在上面的例子中,timeout属性被设置为1秒,这意味着如果事务在秒内无法完成,则报事务超时了。

9. 使用了错误的事务传播机制

@Service
public class TianLuoServiceImpl {
 
    @Autowired
    private TianLuoMapper tianLuoMapper;
    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;
 
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public  void doInsertTianluo(TianLuo tianluo) throws Exception {
        tianLuoMapper.save(tianluo);
        tianLuoFlowMapper.saveFlow(buildFlowByTianLuo(tianluo));
    }
}
  • 事务不生效的原因 :Propagation.NOT_SUPPORTED传播特性不支持事务。

  • 解决方案 :选择正确的事务传播机制。

帮大家复习一下,Spring提供了七种事务传播机制。它们分别是:

  • REQUIRED(默认):如果当前存在一个事务,则加入该事务;否则,创建一个新事务。该传播级别表示方法必须在事务中执行。

  • SUPPORTS:如果当前存在一个事务,则加入该事务;否则,以非事务的方式继续执行。

  • MANDATORY:如果当前存在一个事务,则加入该事务;否则,抛出异常。

  • REQUIRES_NEW:创建一个新的事务,并且如果存在一个事务,则将该事务挂起。

  • NOT_SUPPORTED:以非事务方式执行操作,如果当前存在一个事务,则将该事务挂起。

  • NEVER:以非事务方式执行操作,如果当前存在一个事务,则抛出异常。

  • NESTED:如果当前存在一个事务,则在嵌套事务内执行。如果没有事务,则按REQUIRED传播级别执行。嵌套事务是外部事务的一部分,可以在外部事务提交或回滚时部分提交或回滚。

10. rollbackFor属性配置错误

@Service
public class TianLuoServiceImpl implements TianLuoService {

    @Autowired
    private TianLuoMapper tianLuoMapper;
    
    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional(rollbackFor = Error.class)
    public void addTianLuo(TianLuo tianluo) {
        //保存tianluo数据库记录
        tianLuoMapper.save(tianluo);
        //保存tianluo流水数据库记录
        tianLuoFlowMapper.saveFlow(tianluo);
        //模拟异常抛出
        throw new Exception();
    }
}
  • 事务不生效的原因 : 其实rollbackFor属性指定的异常必须是Throwable或者其子类。默认情况下,RuntimeExceptionError两种异常都是会自动回滚的。但是因为以上的代码例子,指定了rollbackFor = Error.class,但是抛出的异常又是Exception,而Exception和Error没有任何什么继承关系,因此事务就不生效。

图片

大家可以看一下Transactional注解源码哈:

图片

  • 解决方案 :rollbackFor属性指定的异常与抛出的异常匹配。

11.事务注解被覆盖导致事务失效

public interface MyRepository {
    @Transactional
    void save(String data);
}

public class MyRepositoryImpl implements MyRepository {
    @Override
    public void save(String data) {
        // 数据库操作
    }
}

public class MyService {

    @Autowired
    private MyRepository myRepository;

    @Transactional
    public void doSomething(String data) {
        myRepository.save(data);
    }
}

public class MyTianluoService extends MyService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void doSomething(String data) {
        super.doSomething(data);
    }
}
  • 事务失效的原因 :MyTianluoServiceMyService的子类,并且覆盖了doSomething()方法。在该方法中,使用了不同的传播行为(REQUIRES_NEW)来覆盖父类的@Transactional注解。在这种情况下,当调用MyTianluoServicedoSomething()方法时,由于子类方法中的注解覆盖了父类的注解,Spring框架将不会在父类的方法中启动事务 。因此,当MyRepositorysave()方法被调用时,事务将不会被启动,也不会回滚。这将导致数据不一致的问题,因为在MyRepositorysave()方法中进行的数据库操作将不会回滚。

12.嵌套事务的坑

@Service
public class TianLuoServiceInOutService {

    @Autowired
    private TianLuoFlowService tianLuoFlowService;
    @Autowired
    private TianLuoMapper tianLuoMapper;

    @Transactional
    public void addTianLuo(TianLuo tianluo) throws Exception {
        tianLuoMapper.save(tianluo);
        tianLuoFlowService.saveFlow(tianluo);
    }
}

@Service
public class TianLuoFlowService {

    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional(propagation = Propagation.NESTED)
    public void saveFlow(TianLuo tianLuo) {
        tianLuoFlowMapper.save(tianLuo);
        throw new RuntimeException();
    }
}

以上代码使用了嵌套事务,如果saveFlow出现运行时异常,会继续往上抛,到外层addTianLuo的方法,导致tianLuoMapper.save也会回滚啦。如果不想因为被内部嵌套的事务影响 ,可以用try-catch包住,如下:

    @Transactional
    public void addTianLuo(TianLuo tianluo) throws Exception {
        tianLuoMapper.save(tianluo);
        try {
            tianLuoFlowService.saveFlow(tianluo);
        } catch (Exception e) {
          log.error("save tian luo flow fail,message:{}",e.getMessage());
        }
    }

13. 事务多线程调用

@Service
public class TianLuoService {

    @Autowired
    private TianLuoMapper tianLuoMapper;

    @Autowired
    private TianLuoFlowService tianLuoFlowService;

    @Transactional
    public void addTianLuo(TianLuo tianluo) {
        //保存tianluo数据库记录
        tianLuoMapper.save(tianluo);
        //多线程调用
        new Thread(() -> {
            tianLuoFlowService.saveFlow(tianluo);
        }).start();
    }
}

@Service
public class TianLuoFlowService {

    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional
    public void save(TianLuo tianLuo) {
        tianLuoFlowMapper.saveFlow(tianLuo);
    }
}
  • 事务不生效原因 :这是因为Spring事务是基于线程绑定的,每个线程都有自己的事务上下文 ,而多线程环境下可能会存在多个线程共享同一个事务上下文的情况,导致事务不生效。Spring事务管理器通过使用线程本地变量(ThreadLocal)来实现线程安全。大家有兴趣的话,可以去看下源码哈.

在Spring事务管理器中,通过TransactionSynchronizationManager类来管理事务上下文。TransactionSynchronizationManager内部维护了一个ThreadLocal对象,用来存储当前线程的事务上下文。在事务开始时,TransactionSynchronizationManager会将事务上下文绑定到当前线程的ThreadLocal对象中,当事务结束时,TransactionSynchronizationManager会将事务上下文从ThreadLocal对象中移除。

图片

14.异常被捕获并处理了,没有重新抛出

@Service
public class TianLuoServiceImpl implements TianLuoService {

    @Autowired
    private TianLuoMapper tianLuoMapper;

    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional
    public void addTianLuo(TianLuo tianluo) {
        try {
            //保存tianluo数据库记录
            tianLuoMapper.save(tianluo);
            //保存tianluo flow数据库记录
            tianLuoFlowMapper.saveFlow(tianluo);
        } catch (Exception e) {
            log.error("add TianLuo error,id:{},message:{}", tianluo.getId(),e.getMessage());
        }
    }

}
  • 事务不生效的原因 : 事务中的异常已经被业务代码捕获并处理,而没有被正确地传播回事务管理器,事务将无法回滚。我们可以从spring源码(TransactionAspectSupport这个类)中找到答案:

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

 //这方法会省略部分代码,只留关键代码哈
  @Nullable
 protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable {

  if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
  
   TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
   Object retVal;
   try {
        //Spring AOP中MethodInterceptor接口的一个方法,它允许拦截器在执行被代理方法之前和之后执行额外的逻辑。
    retVal = invocation.proceedWithInvocation();
   }
   catch (Throwable ex) {
        //用于在发生异常时完成事务(如果Spring catch不到对应的异常的话,就不会进入回滚事务的逻辑)
    completeTransactionAfterThrowing(txInfo, ex);
    throw ex;
   }
   finally {
    cleanupTransactionInfo(txInfo);
   }

      //用于在方法正常返回后提交事务。
   commitTransactionAfterReturning(txInfo);
   return retVal;
  }
}

invokeWithinTransaction方法中,当Spring catch到Throwable异常的时候,就会调用completeTransactionAfterThrowing()方法进行事务回滚的逻辑。但是,在TianLuoServiceImpl类的spring事务方法addTianLuo中,直接把异常catch住了,并没有重新throw出来,因此 Spring自然就catch不到异常啦,因此事务回滚的逻辑就不会执行,事务就失效了。

  • 解决方案 :在spring事务方法中,当我们使用了try-catch,如果catch住异常,记录完异常日志什么的,一定要重新把异常抛出来,正例如下:

@Service
public class TianLuoServiceImpl implements TianLuoService {

    @Autowired
    private TianLuoMapper tianLuoMapper;

    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional(rollbackFor = Exception.class)
    public void addTianLuo(TianLuo tianluo) {
        try {
            //保存tianluo数据库记录
            tianLuoMapper.save(tianluo);
            //保存tianluo flow数据库记录
            tianLuoFlowMapper.saveFlow(tianluo);
        } catch (Exception e) {
            log.error("add TianLuo error,id:{},message:{}", tianluo.getId(),e.getMessage());
            throw e;
        }
    }
}

15. 手动抛了别的异常

@Service
public class TianLuoServiceImpl implements TianLuoService {

    @Autowired
    private TianLuoMapper tianLuoMapper;
    
    @Autowired
    private TianLuoFlowMapper tianLuoFlowMapper;

    @Transactional
    public void addTianLuo(TianLuo tianluo) throws Exception {
        //保存tianluo数据库记录
        tianLuoMapper.save(tianluo);
        //保存tianluo流水数据库记录
        tianLuoFlowMapper.saveFlow(tianluo);
        throw new Exception();
    }
}
  • 失效的原因 :上面的代码例子中,手动抛了Exception异常,但是是不会回滚的,因为Spring默认只处理RuntimeException和Error,对于普通的Exception不会回滚,除非,用rollbackFor属性指定配置。

  • 解决方案:添加属性配置@Transactional(rollbackFor = Exception.class)

注解为事务范围的方法中,事务的回滚仅仅对于unchecked的异常有效。对于checked异常无效。也就是说事务回滚仅仅发生在,出现RuntimeException或Error的时候。通俗一点就是:代码中出现的空指针等异常,会被回滚。而文件读写、网络超时问题等,spring就没法回滚了。

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

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

相关文章

pag动效预览

潮玩apk里面分析静态资源发现动效有lottie 和pag文件 PAG官网 | PAG动效PAG动效组件可以降低或消除动效相关的研发成本&#xff0c;接入SDK后&#xff0c;设计师可通过PAGExpoter、PAGViewer等工具&#xff0c;一键将设计师在 AE 中制作的动效内容导出成素材文件&#xff0c;并…

【QT 5 +Linux下软件qt软件打包+qt生成软件创建可以安装压缩包+学习他人文章+第三篇:学习打包】

【QT 5 Linux下软件qt软件打包qt生成软件创建可以安装压缩包学习他人文章第三篇&#xff1a;学习打包】 1、前言2、实验环境3、自我学习总结-本篇总结&#xff08;1&#xff09;了解安装包的目录结构&#xff08;2&#xff09;了解要编写文件与编写脚本1. control文件2. postin…

vue3+vite 项目的创建

这里要提醒一下&#xff0c;如果我们要使用 vue3 的组合式api 的写法的话&#xff0c; 那么我们使用的 vue 版本不能低于 vue3.2 版本&#xff0c;不能低于 vue3.2 版本&#xff0c;不能低于 vue3.2 版本 vue2 已停止维护了&#xff0c; 现在全面拥抱vue3 之前用 vue-cli 创建…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:图片边框设置)

设置容器组件的图片边框样式。 说明&#xff1a; 从API Version 9开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 borderImage borderImage(value: BorderImageOption) 设置组件的图片边框。 卡片能力&#xff1a; 从API version 9开始…

2.2_4 调度算法的评价指标

文章目录 2.2_4 调度算法的评价指标&#xff08;一&#xff09;CPU利用率&#xff08;二&#xff09;系统吞吐量&#xff08;三&#xff09;周转时间&#xff08;四&#xff09;等待时间&#xff08;五&#xff09;响应时间 总结 2.2_4 调度算法的评价指标 注&#xff1a;要理解…

CentOs的yum报错: except KeyboardInterrupt, e:

1.报错 File “/bin/yum”, line 30 except KeyboardInterrupt, e: ^^^^^^^^^^^^^^^^^^^^ 2.原因&#xff1a;yum需要用python2编译&#xff0c;如果服务器安装的是python3.6并作为默认编译器的话&#xff0c;就会出现这个错误。 3.解决方法&#xff1a;whereis python 4.修改y…

【EI会议征稿通知】第三届新能源、储能与电力工程国际学术会议(NESP 2024)

第三届新能源、储能与电力工程国际学术会议&#xff08;NESP 2024&#xff09; 2024 3rd International Conference on New Energy, Energy Storage and Power Engineering (NESP 2024) 近几十年来&#xff0c;全球能源消耗迅速增加&#xff0c;因此寻找和开发性能优良的环保…

如何根据我的世界/Minecraft玩家数量选择合适的服务器配置,包括内存和CPU核心数的实际案例分析?

根据Minecraft玩家数量选择合适的服务器配置&#xff0c;首先需要考虑的是服务器的处理能力&#xff0c;这主要由CPU和内存决定。对于Minecraft服务器来说&#xff0c;CPU核心数直接影响到服务器能够同时处理的任务数量&#xff0c;而内存容量则决定了服务器能承载的人数。 对…

P1160 队列安排题解

题目 一个学校里老师要将班上N个同学排成一列&#xff0c;同学被编号为1∼N&#xff0c;他采取如下的方法&#xff1a; 先将1号同学安排进队列&#xff0c;这时队列中只有他一个人&#xff1b; 2∼N号同学依次入列&#xff0c;编号为i的同学入列方式为&#xff1a;老师指定编…

我写了个ImageWindow应用

文章目录 0 引言1 应用简介2 主要功能和特点2.1 多图像同/异步像素级对比2.2 支持多达30种图像格式2.3 高效率的图像处理性能 3 简明使用教程3.1 软件下载安装与更新3.1.1 软件下载与安装3.1.2 软件更新 3.2 多视窗添加并自动最优排列3.3 多样化图像导入方式3.4 自动切换显示模…

如何实现WordPress后台显示文章、分类目录、标签等的ID?

我们平时在使用WordPress的过程中&#xff0c;偶尔需要用到文章的ID&#xff0c;或分类目录ID&#xff0c;或标签ID&#xff0c;或媒体库ID&#xff0c;或评论ID&#xff0c;或用户ID等&#xff0c;但是WordPress后台默认是不显示它们的ID的。 今天boke112百科就跟大家分享如何…

Linux 下安装Jupyter

pip3 install jupyter pip3 install ipython -------------------------------------------- pip3 install jupyterlab jupyter lab pip3 list | grep jupyterlab 启动&#xff1a; python3 -m jupyter lab 2.安装朱皮特 pip3 install -i https://pypi.douban.com/simpl…

力扣1107 每日新用户统计

力扣SQL查询案例——在过去90天内&#xff0c;每个日期首次登录的用户数 目录 题目描述 解题思路 完整代码 题目描述 Traffic 表&#xff1a; ------------------------ | Column Name | Type | ------------------------ | user_id | int | | activity …

计算机二级MySQL-错题、知识点合集04

计算机二级MySQL 第四章 索引 主键约束&#xff0c;不允许为空也不允许重复。 NOT NULL非空约束属于自定义完整约束 PRIMARY KEY 属于实体完整性约束 FOREIGN KEY外键约束 外键与其引用的主键应分别属于不同的表&#xff0c;可以属于同一个关系&#xff1b;一个关系中可以定…

如何在Window系统部署BUG管理软件并结合内网穿透实现远程管理本地BUG

文章目录 前言1. 本地安装配置BUG管理系统2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射本地服务3. 测试公网远程访问4. 配置固定二级子域名4.1 保留一个二级子域名5.1 配置二级子域名6. 使用固定二级子域名远程 前言 BUG管理软件,作为软件测试工程师的必备工具之一。在…

css5定位

css 一.定位1.概念&#xff08;定位定位模式边位移&#xff09;2.静态位移static&#xff08;不常用&#xff09;3.相对定位relative&#xff08;不脱标&#xff09;&#xff08;占位置&#xff09;4.绝对定位absolute&#xff08;脱标&#xff09;&#xff08;不占位置&#x…

Unity(第十七部)Unity自带的角色控制器

组件Character Controller 中文角色控制器 using System.Collections; using System.Collections.Generic; using UnityEngine;public class player : MonoBehaviour {private CharacterController player;void Start(){player GetComponent<CharacterController>();}v…

leetcode刷题(javaScript)——栈相关场景题总结

在LeetCode刷题中&#xff0c;栈是一个非常有用的数据结构&#xff0c;可以解决许多问题&#xff0c;包括但不限于以下几类问题&#xff1a; 括号匹配问题&#xff1a;例如检查括号序列是否有效、计算表达式的值等。逆波兰表达式求值&#xff1a;使用栈来实现逆波兰表达式的计算…

Linux线程【1概念】

目录 前言&#xff1a; 正文&#xff1a; 1.什么是线程&#xff1f; 1.1基本概念 1.2线程理解 1.3进程与线程的关系 1.4线程使用 2.重谈地址空间 2.1页表的大小 2.2、内存与磁盘的交互 2.3深入页表 2.4小结 3.线程概念总结 3.1、再谈线程 3.2线程的优点 3.3…

MYSQL 解释器小记

解释器的结果通常通过上述表格展示&#xff1a; 1. select_type 表示查询的类型 simple: 表示简单的选择查询&#xff0c;没有子查询或连接操作 primary:表示主查询&#xff0c;通常是最外层的查询 subquery :表示子查询&#xff0c;在主查询中嵌套的查询 derived: 表示派…