vue路由嵌套场景中,会有多级甚至无限极菜单路由嵌套的需求,这路由视图是层级继承的,子路由页面内容往父级放,父级在继续往更高级地放,最终所有内容显示顶级视图中,这样每级就需要一个页面去对应每个路由配置中ponent,有多少级路由就需要创建几级文件对应,这样显然比较麻烦,有一些父级路由只是起到把子路由的页面内容往上抛的作用并没有自己独立的内容,这时可以建个空页面里面放入route-view视图标签,大家共用这个页面就好了,就不用建那么多文件了。
那么问题来了,如果父级路由也要有自己的功能,支持展示、发布等功能,不但需要实现自己功能,还要把子路由的页面往上级抛且上下级页面内容互不影响,这种“变态”的需求还是有的,那怎么搞?目前方案还需在子路由数组进行新增一个路由来代替父级功能操作,并把子路由菜单隐藏起来,点击父级后跳转这个子路由页面进行操作,这目前也是常见vue后台模板中菜单路由的实现方式。
这些都是在后台动态生成前端菜单时是否能更好地遵循某个规律的考虑,
一、两级菜单就不影响,但是一些项目,比如把栏目分类当做菜单路由的子路由,便于点击栏目菜单直接维护栏目下的内容,栏目分类层级可能会很深是无限的,没有更好的规律,动态生成前端菜单就比较麻烦。
目前还是采用常见后台模板的方式,只是感觉比较麻烦,不知道大家一般怎么实现?
实在不行,那我走?不动态了,让前端去背锅?
adb shell 中的am和pm区别?
一、am命令
am全称activity manager,你能使用am去模拟各种系统的行为,例如去启动一个activity,强制停止进程,发送广播进程,修改设备屏幕属性等等。
例如:adb shell am start -a android.intent.action.VIEW
关于一些am命令的介绍:
start [options] <INTENT> :启动activity通过指定的intent参数。具体intent参数参照官方表。
startservice [options] <INTENT> : 启动service通过指定的intent参数。具体intent跟start命令参数相同。
<PACKAGE> : 强制停止指定的package包应用。
kill [options] <PACKAGE> :杀死指定package包应用进程,该命令在安全模式下杀死进程,不影响用户体验。参数选项:--user <USER_ID> | all | current: 指定user进程杀死,如果不指定默认为所有users。(关于USER_ID下面会介绍到)
kill-all :杀死所有的后台进程。
profile start <PROCESS> <FILE> :在<PROCESS>进程中运行profile,分析结果写到<FILE>里。
profile <PROCESS> :停止profile。
二、pm命令:
pm全称package manager,你能使用pm命令去模拟android行为或者查询设备上的应用等
例如:adb shell pm .example.MyApp
关于一些pm命令的介绍:
list packages [options] <FILTER> :打印所有包,选择性的查询包列表。
参数选项:-f:查看关联文件,即应用apk的位置跟对应的包名(如:package:/system/app /.sec.android.app.music);
-d:查看disabled packages;
-e:查看enable package;
-s:查看系统package;
-3:查看第三方package;
-i:查看package的对应安装者(如:
1、 .tencent.qqmusic installer=null 2、.tencent.qqpim .android.vending);
-u:查看曾被卸载过的package。(卸载后又重新安装依然会被列 入);
list permissions [options] <GROUP> :选择性的打印权限。参数选项:
list features :设备特性。硬件之类的性能。
list libraries :当前设备支持的libs。
list users :系统上所有的users。(上面提到的USER_ID查询方式,如:UserInfo{0:Primary:3}那么USER_ID为0)
path <PACKAGE> :查询package的安装位置。
install [options] <PATH> :安装命令。
uninstall [options] <PACKAGE> :卸载命令。
clear <PACKAGE> :对指定的package清除所有数据。
enable <PACKAGE_OR_COMPONENT> :使ponent可用。(如:pm enable &34;)
disable <PACKAGE_OR_COMPONENT> :使ponent不可用。
从Blocked线程堆栈着手分析,查看PrintStream相关代码片段如下图5所示,可以看到被阻塞地方有synchronized同步调用,再结合上文发现每两分钟写满一个500MB日志文件的现象,初步怀疑是日志量过大导致了线程阻塞。
AsyncAppender顾名思义是个异步Appender,采用异步方式处理日志,在其内部维护了一个BlockingQueue队列,每次处理日志时,都先尝试把Log4jLogEvent事件存入队列中,然后交由后台线程从队列中取出事件并处理(把日志交由AsyncAppender所关联的Appender处理),但队列长度总是有限的,且队列默认大小是128,如果日志量过大或日志异步线程处理不及时,就很可能导致日志队列被打满。
当日志队列满时,日志框架内部提供了两种处理方式,具体如下:
如果blocking配置为true,会选择相应的处理策略,默认是SYNCHRONOUS策略,可以在ponent.properties文件中,通过log4j2.AsyncQueueFullPolicy参数配置日志框架提供的其他策略或自定义策略。
DISCARD策略,直接忽略日志。
SYNCHRONOUS策略,当前线程直接发送日志到Appender。
ENQUEUE策略,强制阻塞入队。
如果blocking配置为false,则由ErrorHandler和ErrorAppender处理失败日志。日志框架提供了默认的ErrorHandler实现,即DefaultErrorHandler,目前暂不支持业务在XML、JSON等日志配置文件里自定义ErrorHandler。日志框架默认不提供ErrorAppender,业务如有需要可在XML、JSON等日志配置文件里自定义error-ref配置。
DefaultErrorHandler内部在处理异常日志时增加了条件限制,只有下述两个条件任一满足时才会处理,从而避免大量异常日志导致的性能问题。
两条日志处理间隔超过5min。
异常日志数量不超过3次。
但项目所用日志框架版本的默认实现看起来存在一些不太合理的地方:
lastException用于标记上次异常的时间戳,该变量可能被多线程访问,无法保证多线程情况下的线程安全。
exceptionCount用于统计异常日志次数,该变量可能被多线程访问,无法保证多线程情况下的线程安全。
所以,在多线程场景下,可能有大量异常日志同时被DefaultErrorHandler处理,带来线程安全问题。值得一提的是,该问题已有相关Issue: DefaultErrorHandler can not share values across threads反馈给社区,并在2.15.0版本中进行了修复。
从上述DefaultErrorHandler代码中可以看到,真正负责处理日志的是StatusLogger,继续跟进代码进入logMessage方法,方法执行逻辑如下:
如果StatusLogger内部注册了StatusListener,则由对应的StatusListener负责处理日志。
否则由SimpleLogger负责处理日志,直接输出日志到System.err输出流。
multisim创建仿真模型
对multisim自带的库里没有的元器件进行仿真时,需要自己创建元器件的仿真模型。
multisim的技术支持论坛提供了一篇详细的说明,通过在元器件厂家网站下载元器件的PSPICE模型,然后使用multisim自带ponent wizard功能来创建模型(详细见以下链接)。
这个说明比较旧,里面提到的几个文件都已经不能下载。通过以下方法变通实现:
对于原理图封装文件:pga.sym和preamp.sym。解决方法:不要这两个文档,自己手动画原理图封装。
对于仿真模型文件:preamp.cir和pga.cir。解决方法:到TI官网下载THS7001的pspice模型文件THS7001.LIB。这个文件包含了描述preamp和pga的子电路块,把它们分别拷贝出来另存为pga.sym和preamp.sym文件即可。
图一是最终做完后的仿真测试。
网页链接
1. 方法未被声明为@Transactional或者@Transactional(propagation=REQUIRES_NEW),或者方法调用所在的类没有被声明为@Service或@Component等Spring管理的Bean。
2. 异常被catch住,但是没有手动回滚事务,比如try-catch中没有进行transactionManager.rollback(status)操作。
3. 因为@Transactional默认对所有RuntimeException进行回滚,所以如果方法中抛出了非RuntimeException的异常,事务不会自动回滚。需要手动在catch语句块中进行回滚操作。
4.事务超时,即设置的超时时间比方法执行时间要短。在这种情况下,事务管理器会认为事务执行超时了,而进行回滚。
5. 可能是事务配置上有问题,比如@Transactional注解的属性不正确或者配置文件中的事务管理器配置不正确等等。
Spring Boot的常用注解包括:
1. @SpringBootApplication:用于启动类中,表示该类是Spring Boot应用的主入口。
2. @RestController:用于Controller层,表示该类是一个RESTful的Controller,返回JSON格式的数据。
3. @RequestMapping:用于Controller层的方法上,表示该方法处理哪种请求(GET、POST等)以及请求的路径。
4. @Autowired:用于依赖注入,自动装配Bean。
5. @Repository:用于DAO层的方法上,表示该方法是访问数据库的方法。
6. @Service:用于Service层的类上,表示该类是业务逻辑层的实现。
7. @Component:用于普通类上,表示该类是Spring容器中的一个Bean。
8. @Value:用于属性上,表示该属性的值是从配置文件中读取的。
9. @ConfigurationProperties:类似于@Value,表示读取配置文件中的属性,但可以一次读取多个属性组成的对象。
10. @EnableAutoConfiguration:用于启动类上,表示让Spring Boot自动配置应用所需的Bean。
SpringBoot核心注解:
1、@SpringBootApplication注解,这个注解是一个组合注解,4个元注解。
2、@ComponentScan:默认情况下会扫描当前包及其子包下面所有被@Component注解修饰的Java类。
3、@SpringBootConfiguration:组合了@Configuration这个注解,也就是说明被SpringBootApplication所标识的Java类就是一个Java配置类。
4、@EnableAutoConfiguration:打开自动装配的功能 -> META-INF/spring.factories文件中加载需要自动注入的Java类。
Spring允许使用自定义的实例化逻辑,因此可以通过下列方式自定义bean:
1. 使用XML配置文件定义bean:使用<bean>元素可以定义bean的各种属性,例如id、class、init-method、destroy-method等,可以自定义Bean来使用特定的参数。
2. 使用注解:可以使用ponent、@repository、@service、@controller等注解来标识自定义的Bean,然后使用<ponent-scan>元素扫描自定义的Bean。
3. 使用Spring的Java配置:使用@Configuration、@Bean注解自定义Bean,并通过@Configuration类自动创建Spring上下文。
例如:
```
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
```
上述代码定义了一个名为myService的Bean,并使用此Bean返回MyServiceImpl类型的实例。
使用以上方式自定义自己的bean后,在需要使用此bean的地方,可以使用@Autowire或者JNDI查找的方式获取该Bean的实例。
Lit是一个简单的Web组件库,用于构建快速、轻量级的Web 组件。其核心是一个消除样板文件的组件基类,它提供响应式状态、作用域样式和一个小巧、快速且富有表现力的声明性模板系统。
Lit构建在Web Components标准之上,但它又增加了开发者所期望的响应式、声明式模板等功能,提高开发者体验和开发效率,去掉了那些每次都要重复的代码,简单即是效率。
Lit的体积很小,压缩后只有5KB,这样保证了它在加载时极快;Lit的另一个特点是它在更新界面时只触碰页面的动态内容,因此也就没有必要构建虚拟DOM树和所谓的DIFF算法了,渲染速度大大提高。
Lit组件就是一个原生的Web Component,使用它就像使用Web Components,Web Components所能使用的地方,Lit皆可以使用。
Web开发的组件未来时Web Component,Lit正是为Web Component而来。
项目地址:网页链接