一、orika工具使用
1)工具类
package com.xinyue.game.utils;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
/**
* @author 王广帅
* @since 2022/2/8 22:37
*/
public class XyBeanCopyUtil {
private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
/**
* 将对象S的数据,复制到对象T中
*
* @param data 要复制的数据对象
* @param clazz 新的接收数据的对象class
* @param <S>
* @param <T>
* @return
*/
public static <S, T> T copyObj(S data, Class<T> clazz) {
return mapperFactory.getMapperFacade().map(data, clazz);
}
}
2)测试
package com.xinyue.game.utils;
import com.xinyue.game.utils.model.TestUser;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* @author 王广帅
* @since 2022/2/13 19:38
*/
public class XyBeanCopyUtilTest {
@Test
public void testCopyObj() {
TestUser testUser = new TestUser();
String name = "aaa";
testUser.setName(name);
String key = "1";
String value = "北京";
testUser.getAddressMap().put(key, value);
TestUser newUser = XyBeanCopyUtil.copyObj(testUser, TestUser.class);
Assert.assertEquals(newUser.getName(), name);
Assert.assertEquals(newUser.getAddressMap().get(key), testUser.getAddressMap().get(key));
}
}
可以看出是深拷贝!!!
我们在开发中,经常需要异步线程进行数据库的落地,这里就用到了深拷贝技术,我们无需考虑List,因为游戏中都是单个实体进行落地的。
二、游戏中定时落地实现
1.时机1:缓存中移除时
@PostConstruct
public void init() {
roleCache = CacheBuilder.newBuilder().expireAfterAccess(Duration.ofMinutes(gameServerConfig.getExpireOfAccess()))
.initialCapacity(1000).maximumSize(gameServerConfig.getMaxCacheSize()).removalListener(new RemovalListener<String, PlayerEntity>() {
@Override
public void onRemoval(RemovalNotification<String, PlayerEntity> notification) {
logger.info("角色被从内存中移除,更新一次到数据库,playerId:{}", notification.getKey());
PlayerEntity playerEntity = notification.getValue();
flushPlayer(playerEntity);
}
}).build();
}
2.时机2:下线时
@EventListener
public void logoutEvent(LoginOutEvent event) {
// 用户下线时,刷新一下缓存
this.flushPlayer(event.getPlayerId());
logger.info("用户下线,刷新缓存,playerId:{},threadId:{}", event.getPlayerId(), Thread.currentThread().getId());
}
3.落地实现
public void flushPlayer(String roleId) {
PlayerEntity playerEntity = this.getPlayerIfPresent(roleId);
this.flushPlayer(playerEntity);
}
private void flushPlayer(PlayerEntity playerEntity) {
if (playerEntity != null) {
// 深拷贝出来当前对象
PlayerEntity newPlayerEntity = XyBeanCopyUtil.copyObj(playerEntity, PlayerEntity.class);
// 异步线程进行落地
gameAsyncTaskService.execute(String.valueOf(playerEntity.getPlayerId()), "更新role信息", () -> {
this.daoPlayerService.updatePlayer(newPlayerEntity);
});
}
}