TypeScript中用for in遍历对象的属性

ts遍历对象报错误:

TS7053: Element implicitly has an ‘any’ type because expression of type ‘string’ can’t be used to index type ‘{ a: number; b: number; }’.   No index signature with a parameter of type ‘string’ was found on type ‘{ a: number; b: number; }’.

代码:

let arr = {
  a: 1,
  b: 2
};

for (const n in arr) {
  console.log(n, arr[n]);
}

解决办法为修改tsconfig.json,允许索引:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "suppressImplicitAnyIndexErrors": true,
    "outDir": "./out-tsc/app",
    "types": []
  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}

 

 

 

 

@Feign通过URI指定请求地址

@FeignClient使用起来非常方便,只需要启用配置即可使用,但是有时候需要请求不通地址的服务,这时可以指定一个URI参数。

配置:

@EnableFeignClients(basePackages = "com.test.openapi.rpc")
@Configuration
public class FeignConfig extends Compact implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {

    }
}

@FeignClient接口

@FeignClient(
        name = "testCloudService",
        url = "https://api.test.com"
)
@RequestMapping(
        value = "/api",
        headers = {
                "clientId=MY CLIENTID",
                "version=1.0"
        }
)
public interface ITestCloudService {

    @RequestMapping(value = "/call", method = RequestMethod.GET)
    ResultResp<Map<String, Object>> region(URI uri, @RequestHeader("token") String token);

    @RequestMapping(value = "/test", method = RequestMethod.POST)
    ResultResp<Map<String, Object>> login(URI uri, @RequestBody Map body, @RequestHeader("token") String token);
}

如果是GET方法,需要指定一连串参数,可以使用注解@SpringQueryMap如:

@RequestMapping(value = "/user", method = RequestMethod.GET)
ResultResp<ApiUserDevice> userDevice(URI uri, @SpringQueryMap Map queryMap, @RequestHeader("token") String token);

 

 

chroem 89+ A标签打开新窗口导致sessionStorage失效

localStorage作用范围:本地存储,关闭浏览器后,数据依然会保存。同源浏览器窗口可以共享使用localStorage存储的数据。

sessionStorage作用范围:只存在于当前会话页面,当会话结束后,数据也随之销毁,在不同的浏览器窗口中共享。也就是存在于当前浏览器页面,页面关闭,数据也会删除。(注意:通过鼠标右键打开的新标签无法共享sessionStorage)

而这块对于sessionStorage可能一直存在一个误区,在Chrome浏览器89版本前,当前会话页面指的是当浏览器窗口没有关闭时,窗口内同域网站可以共享此数据(同源浏览器多个窗口不共享),当页面全部关闭或窗口关闭后,sessionStorage数据会被摧毁,所以你用a标签跳转还是js跳转都会共享sessionStorage。

而在2021年3月初Chrome浏览器进行了批量更新,更新到89版本后,通过a标签target=”_blank”跳转到新页面时sessionStorage就会丢失。Chrome这一更新可能会导致很多网站的sessionStorage丢失,页面可能直接就崩掉了。

解决办法如下:

1、最简单的解决办法 – a标签添加属性 rel=”opener”

<a href="http://xxx" target="_blank" rel="opener">Link</a>

 

MyBatis 二级缓存

MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。 为了使它更加强大而且易于配置,我们对 MyBatis 3 中的缓存实现进行了许多改进。

默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:

<cache/>

基本上就是这样。这个简单语句的效果如下:

  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

提示 缓存只作用于 cache 标签所在的映射文件中的语句。如果你混合使用 Java API 和 XML 映射文件,在共用接口中的语句将不会被默认缓存。你需要使用 @CacheNamespaceRef 注解指定缓存作用域。

这些属性可以通过 cache 元素的属性来修改。比如:

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

可用的清除策略有:

  • LRU – 最近最少使用:移除最长时间不被使用的对象。
  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
  • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

默认的清除策略是 LRU。

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

提示 二级缓存是事务性的。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。

使用自定义缓存

除了上述自定义缓存的方式,你也可以通过实现你自己的缓存,或为其他第三方缓存方案创建适配器,来完全覆盖缓存行为。

<cache type="com.domain.something.MyCustomCache"/>

这个示例展示了如何使用一个自定义的缓存实现。type 属性指定的类必须实现 org.apache.ibatis.cache.Cache 接口,且提供一个接受 String 参数作为 id 的构造器。 这个接口是 MyBatis 框架中许多复杂的接口之一,但是行为却非常简单。

public interface Cache {
  String getId();
  int getSize();
  void putObject(Object key, Object value);
  Object getObject(Object key);
  boolean hasKey(Object key);
  Object removeObject(Object key);
  void clear();
}

为了对你的缓存进行配置,只需要简单地在你的缓存实现中添加公有的 JavaBean 属性,然后通过 cache 元素传递属性值,例如,下面的例子将在你的缓存实现上调用一个名为 setCacheFile(String file) 的方法:

<cache type="com.domain.something.MyCustomCache">
  <property name="cacheFile" value="/tmp/my-custom-cache.tmp"/>
</cache>

你可以使用所有简单类型作为 JavaBean 属性的类型,MyBatis 会进行转换。 你也可以使用占位符(如 ${cache.file}),以便替换成在配置文件属性中定义的值。

从版本 3.4.2 开始,MyBatis 已经支持在所有属性设置完毕之后,调用一个初始化方法。 如果想要使用这个特性,请在你的自定义缓存类里实现 org.apache.ibatis.builder.InitializingObject 接口。

public interface InitializingObject {
  void initialize() throws Exception;
}

提示 上一节中对缓存的配置(如清除策略、可读或可读写等),不能应用于自定义缓存。

请注意,缓存的配置和缓存实例会被绑定到 SQL 映射文件的命名空间中。 因此,同一命名空间中的所有语句和缓存将通过命名空间绑定在一起。 每条语句可以自定义与缓存交互的方式,或将它们完全排除于缓存之外,这可以通过在每条语句上使用两个简单属性来达成。 默认情况下,语句会这样来配置:

<select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>

鉴于这是默认行为,显然你永远不应该以这样的方式显式配置一条语句。但如果你想改变默认的行为,只需要设置 flushCache 和 useCache 属性。比如,某些情况下你可能希望特定 select 语句的结果排除于缓存之外,或希望一条 select 语句清空缓存。类似地,你可能希望某些 update 语句执行时不要刷新缓存。

cache-ref

回想一下上一节的内容,对某一命名空间的语句,只会使用该命名空间的缓存进行缓存或刷新。 但你可能会想要在多个命名空间中共享相同的缓存配置和实例。要实现这种需求,你可以使用 cache-ref 元素来引用另一个缓存。

<cache-ref namespace="com.someone.application.data.SomeMapper"/>

 

 

MySQL参数 · innodb_additional_mem_pool_size

参数简介

innodb_additional_mem_pool_size 是 InnoDB 用来保存数据字典信息和其他内部数据结构的内存池的大小,单位是 byte,参数默认值为8M。数据库中的表数量越多,参数值应该越大,如果 InnoDB 用完了内存池中的内存,就会从操作系统中分配内存,同时在 error log 中打入报警信息。目前8.0+的版本已经移除了这个参数。

innodb_use_sys_malloc 配置为 ON 时,innodb_additional_mem_pool_size 失效(直接从操作系统分配内存)。

innodb_additional_mem_pool_size 和 innodb_use_sys_malloc 在 MySQL 5.7.4 中移除。

参数合理值预估

./storage/innobase/handler/ha_innodb.cc:
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;

./storage/innobase/srv/srv0srv.cc:        mem_init(srv_mem_pool_size);

storage/innobase/mem/mem0dbg.cc: mem_comm_pool = mem_pool_create(size);

从源码中可以看出,innodb_additional_mem_pool_size 的参数值用于指定内存池 mem_comm_pool 的大小;

storage/innobase/mem/mem0mem.cc:
        block = static_cast<mem_block_t*>(
                mem_area_alloc(&len, mem_comm_pool));

函数 mem_area_alloc 从 mem_comm_pool 内存池中分配内存;

storage/innobase/mem/mem0pool.cc:

/* If we are using os allocator just make a simple call
to malloc */
        if (UNIV_LIKELY(srv_use_sys_malloc)) {
        return(malloc(*psize));
}

........

area = UT_LIST_GET_FIRST(pool->free_list[n]);

if (area == NULL) {
        ret = mem_pool_fill_free_list(n, pool);

        if (ret == FALSE) {
                /* Out of memory in memory pool: we try to allocate
                from the operating system with the regular malloc: */

                mem_n_threads_inside--;
                mutex_exit(&(pool->mutex));

                return(ut_malloc(size));
        }

        area = UT_LIST_GET_FIRST(pool->free_list[n]);
}

如果 innodb_use_sys_malloc (上述代码中的srv_use_sys_malloc) 设置为 ON,或者内存池中没有足够的内存可供分配,则直接从操作系统中分配内存。

mem_area_alloc 调用栈如下(use database 触发断点)

#0  mem_area_alloc
#1  0x000000000118048d in mem_heap_create_block_func
#2  0x000000000149a390 in mem_heap_create_func
#3  0x00000000014aa6d5 in dict_load_table
#4  0x0000000001481082 in dict_table_open_on_name
#5  0x000000000109d769 in ha_innobase::open
#6  0x00000000006d5245 in handler::ha_open
#7  0x0000000000b830ae in open_table_from_share
#8  0x000000000091deee in open_table
#9  0x0000000000922eea in open_and_process_table
#10 0x000000000092492f in open_tables
#11 0x0000000000926c21 in open_normal_and_derived_tables
#12 0x0000000000a83834 in mysqld_list_fields
#13 0x00000000009f28e1 in dispatch_command
#14 0x00000000009eeb51 in do_command
#15 0x0000000000982cb6 in do_handle_one_connection
#16 0x000000000098238b in handle_one_connection
#17 0x0000000001877f91 in pfs_spawn_thread
#18 0x0000003d8c007851 in start_thread ()
#19 0x0000003d8bce767d in clone ()

函数 dict_load_table 中会为每张表分配32k的空间 ( mem_heap_create(32000) 实际分配32744字节空间 ),数据字典中每张表所占空间的上限是32k,具体占用空间根据列数和索引数量分配,分配完成后回收32k中未使用的空间

storage/innobase/dict/dict0load.cc: heap = mem_heap_create(32000);

show engine innodb status BUFFER POOL AND MEMORY Dictionary cache

实际使用的数据字典缓存,不会超过每张表32k,实测过程中,每张表不包括索引占4K,每个索引占2k,列数对空间占用影响不大。

测试用表如下,未建索引时,1000张表占用空间4M,增加列占用空间增长不明显,每增加一个索引,占用空间增加2M,可以估测每张表占用空间4k(不含索引),每个索引占用空间2k。

Create Table: CREATE TABLE `1000` (
  `id` int(11) DEFAULT NULL,
  `a` varchar(255) DEFAULT NULL,
 `b` varchar(255) DEFAULT NULL,
  `c` varchar(255) DEFAULT NULL,
  `d` varchar(255) DEFAULT NULL,
  KEY `a` (`a`),
  KEY `b` (`b`),
  KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

引入和移除该参数的原因

早期操作系统的内存分配器性能和可伸缩性较差,并且当时没有适合多核心CPU的内存分配器。所以,InnoDB 实现了一套自己的内存分配系统,做为内存系统的参数之一,引入了innodb_additional_mem_pool_size

随着多核心CPU的广泛应用和操作系统的成熟,操作系统能够提供性能更高、可伸缩性更好的内存分配器,包括 Hoard、libumem、mtmalloc、ptmalloc、tbbmalloc 和 TCMalloc 等。InnoDB 实现的内存分配器相比操作系统的内存分配器并没有明显优势,所以在之后的版本,会移除 innodb_additional_mem_pool_size 和 innodb_use_sys_malloc 两个参数,统一使用操作系统的内存分配器。

文章转自:https://developer.aliyun.com/article/32384

官方文档:https://dev.mysql.com/doc/refman/8.0/en/dynamic-system-variables.html

 
Copyright © 2008-2021 lanxinbase.com Rights Reserved. | 粤ICP备14086738号-3 |