[SpringDataMongodb开发游戏服务器实战]

背景:

        xdb其实足够完美了,现在回想一下,觉得有点复杂,我们不应该绑定语言,最好有自己的架构思路。

        七号堡垒作为成功的商业项目,告诉我:其实数据是多读少写的,有修改的时候直接改库也是没问题的,这样子有个好处就是rpc获取到的数据足够的准确。

        跨服这块结合redis,我们可以轻松获取其它服的数据。

        华珺的Player数据管理思路,将所有的数据都存放Role上,这样子获取是十分的简单。

        因此,我决定写一个简单而又足够上线的框架,思路:

                技术栈:  SpringBoot+netty+mongo+pb 。

                是按照模块划分成多线程的,也就是: 尽量单进程多线程去完成任务。

pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.jn</groupId><artifactId>mongodemo</artifactId><version>1.0</version><name>mongodemo</name><description>Demo project for Spring Boot</description><properties><java.version>21</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

MongoConfig.java

package com.jn.framework.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;@Configuration
public class MongoConfig {@SuppressWarnings("all")@Beanpublic MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory, MongoMappingContext mongoMappingContext) {DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDatabaseFactory);MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);//去掉_class字段mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));return new MongoTemplate(mongoDatabaseFactory, mappingConverter);}
}

SpringBeanUtil.java

package com.jn.framework.utils;import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;/*** 普通的Java类中获取spring中的bean通用类*/
@Component
public class SpringBeanUtil implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if (SpringBeanUtil.applicationContext == null) {SpringBeanUtil.applicationContext = applicationContext;}}//通过class获取Bean.public static <T> T getBean(Class<T> clazz) {return applicationContext.getBean(clazz);}}

IEntity.java

package com.jn.framework;public interface IEntity {void save();
}

IProcedure.java

package com.jn.framework;public interface IProcedure {void call();
}

PlayerEntity.java

package com.jn.mongodemo.account.entity;import com.jn.framework.IEntity;
import com.jn.framework.utils.SpringBeanUtil;
import com.jn.mongodemo.bag.entity.BagEntityRepository;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;@Data
@Document("PlayerEntity")
public class PlayerEntity implements IEntity {@Id@Indexedprivate Long roleId;@Overridepublic void save() {SpringBeanUtil.getBean(PlayerEntityRepository.class).save(this);}
}

PlayerEntityRepository.java

package com.jn.mongodemo.account.entity;import org.springframework.data.mongodb.repository.MongoRepository;public interface PlayerEntityRepository extends MongoRepository<PlayerEntity, Long> {}

PLogin.java

package com.jn.mongodemo.account.procedure;import com.jn.framework.IProcedure;
import com.jn.framework.utils.SpringBeanUtil;
import com.jn.mongodemo.account.entity.PlayerEntity;
import com.jn.mongodemo.account.entity.PlayerEntityRepository;
import com.jn.mongodemo.bag.entity.BagEntity;
import com.jn.mongodemo.bag.entity.BagEntityRepository;
import com.jn.mongodemo.role.Role;public class PLogin implements IProcedure {private long roleId;public PLogin(long roleId) {this.roleId = roleId;}@Overridepublic void call() {// 加载玩家信息PlayerEntityRepository playerEntityRepository = SpringBeanUtil.getBean(PlayerEntityRepository.class);PlayerEntity playerEntity = playerEntityRepository.findById(roleId).orElse(null);if (playerEntity == null) {playerEntity = new PlayerEntity();playerEntity.setRoleId(roleId);playerEntityRepository.save(playerEntity);}Role.inst().setPlayerEntity(playerEntity);// 背包信息BagEntityRepository bagEntityRepository = SpringBeanUtil.getBean(BagEntityRepository.class);BagEntity bagEntity = bagEntityRepository.findById(roleId).orElse(null);if (bagEntity == null) {bagEntity = new BagEntity();bagEntity.setRoleId(roleId);bagEntity.setNum(100);bagEntityRepository.save(bagEntity);}Role.inst().setBagEntity(bagEntity);// 测试修改Role.inst().getBagEntity().setNum(Role.inst().getBagEntity().getNum() + 100);Integer num = Role.inst().getBagEntity().getItemMap().getOrDefault(1, 0);Role.inst().getBagEntity().getItemMap().put(1, num+1);Role.inst().getBagEntity().save();}
}

AccountMsgHandler.java

package com.jn.mongodemo.account;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jn.mongodemo.account.procedure.PLogin;@RestController
@RequestMapping("/account")
public class AccountMsgHandler {/*http://localhost:8080/account/login?roleId=3*/@RequestMapping("/login")public void login(Long roleId) {new PLogin(roleId).call();}
}

BagEntity.java

package com.jn.mongodemo.bag.entity;import com.jn.framework.IEntity;
import com.jn.framework.utils.SpringBeanUtil;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;import java.util.HashMap;
import java.util.Map;@Data
@Document("BagEntity")
public class BagEntity implements IEntity {@Id@Indexedprivate Long roleId;private Integer num;private Map<Integer, Integer> itemMap = new HashMap<>();@Overridepublic void save() {SpringBeanUtil.getBean(BagEntityRepository.class).save(this);}
}

BagEntityRepository.java

package com.jn.mongodemo.bag.entity;import org.springframework.data.mongodb.repository.MongoRepository;public interface BagEntityRepository extends MongoRepository<BagEntity, Long> {}

Role.java

package com.jn.mongodemo.role;import com.jn.mongodemo.account.entity.PlayerEntity;
import com.jn.mongodemo.bag.entity.BagEntity;
import lombok.Data;@Data
public class Role {private static Role instance = new Role();public static Role inst() {return instance;}private PlayerEntity playerEntity;private BagEntity bagEntity;
}

MongodemoApplication.java

package com.jn;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MongodemoApplication {public static void main(String[] args) {SpringApplication.run(MongodemoApplication.class, args);}}

application.yml

spring:data:mongodb:host: 127.0.0.1port: 27017database: mongodemo

效果:

总结:

可见游戏服使用mongo是十分合适的,轻松面对复杂的数据结构,并且和java集合框架完美结合。 

其实,修改数据这块,我们可以登录时是: 同步记载,保存时,可以异步。

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

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

相关文章

C语言:指针的进阶讲解

目录 1. 二级指针 1.1 二级指针是什么&#xff1f; 1.2 二级指针的作用 2. 一维数组和二维数组的本质 3. 指针数组 4. 数组指针 5. 函数指针 6. typedef的使用 7. 函数指针数组 7.1 转移表 1. 二级指针 如果了解了一级指针&#xff0c;那二级指针也是可以很好的理解…

windows安装onlyoffice8.0

安装erlang 安装Erlang25.3 下载地址 设置环境变量 ERLANG_HOME C:\Program Files\Erlang OTP Path下设置%ERLANG_HOME%\bin 打开cmd输入erl不报错即可 安装rabbitmq rabbitmq和erlang对应的关系 下载地址 执行完exe文件后&#xff0c;找到安装目录下的sbin&am…

网络原理——HTTP

1. 什么是HTTP协议 HTTP是应用层的协议。Java最主要的应用场景是做网站&#xff0c;而网站由 后端&#xff08;HTTP服务器&#xff09; 和 前端&#xff08;浏览器&#xff09;组成&#xff0c;HTTP协议就是负责这里后端和前端的数据交互。 HTTP3.0 之前在传输层是通过 TCP传…

Linux:Jenkins:GitLab+Maven+Jenkins的部署——离线包rpm版

Linux&#xff1a;Jenkins&#xff1a;GitLabMavenJenkins的部署&#xff08;1&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136157018?spm1001.2014.3001.5501这个是原版文章&#xff0c;均是使用的在线情况&#xff0c;但是不排除会有离线部署&am…

性格正直的人适合什么职业?

有信仰&#xff0c;有责任&#xff0c;有骨气&#xff0c;有尊严&#xff0c;这应该是大多数人对正直的人的理解&#xff0c;他们的心中有信仰&#xff0c;肩上有责任&#xff0c;灵魂有骨气&#xff0c;头上有尊严&#xff0c;不管在什么时候都能够坚守道德准则&#xff0c;不…

数字信号处理:傅里叶分析

本文主要参考视频如下&#xff1a; 数字信号处理9-1_线性时不变系统对复指数信号的响应_哔哩哔哩_bilibili 傅里叶分析的主要研究内容如下所示&#xff1a; 注意&#xff0c;计算机中使用的离散傅里叶变换并不是离散时间傅里叶变换&#xff1b; 前四种都是理论上的变换方式&…

nginx-------- 高性能的 Web服务端 验证模块 页面配置(三)

一、http设置 1.1 验证模块 需要输入用户名和密码 htpasswd 此命令来自于 httpd-tools 包&#xff0c;如果没有安装 安装一下即可 也可以安装httpd 直接yum install httpd -y 也一样 第一次生成文件htpasswd -c 文件路径 姓名 交互式生成密码 htpasswd -bc 文…

[java]windows和linux下jdk1.8安装包所有版本系列下载地址汇总

【windows jdk1.8系列下载地址】 java-jdk9-jdk-9.0.1-windows-x64-bin.zip下载地址&#xff1a;https://download.csdn.net/download/FL1623863129/88539300 java-jdk1.8-jdk-8u202-windows-x64.zip下载地址&#xff1a;https://download.csdn.net/download/FL1623863129/8853…

ubantu设置mysql开机启动

阅读本文之前请参阅----MySQL 数据库安装教程详解&#xff08;linux系统和windows系统&#xff09; 在Ubuntu系统中设置MySQL开机启动&#xff0c;通常有以下几种方法&#xff1a; 1. **使用systemctl命令**&#xff1a; Ubuntu 16.04及更高版本使用systemd作为…

LabVIEW的应用领域

LabVIEW&#xff08;Laboratory Virtual Instrument Engineering Workbench&#xff09;是一种基于图形表示法的程序语言&#xff0c;主要用于测量、自动化和控制系统中的数据采集和处理。它不仅是一种编程语言&#xff0c;还是一个交互式的开发和运行系统&#xff0c;专为工程…

人工智能在网络安全中的重要性

介绍&#xff1a; 人工智能&#xff08;AI&#xff09;是计算机科学的一个分支&#xff0c;基于某些独特的算法和相关数学计算&#xff0c;使机器能够拥有人类的决策能力。另一方面&#xff0c;网络安全包括保护虚拟世界免受网络攻击和威胁的安全措施。人工智能能够通过采取与…

c++用户管理信息(双向链表 -- 模板化)

c用户管理信息---双向链表 ListStu双向链表--&#xff08;把前面的单链表改一下&#xff0c;就直接可以用&#xff09;ListStu.hListStu.cpp 模板化 ListStu双向链表–&#xff08;把前面的单链表改一下&#xff0c;就直接可以用&#xff09; ListStu.h #pragma once #includ…

深入了解Spring Boot Starter Integration的用途与优势

Spring Boot Starter Integration 是 Spring Boot 提供的一个强大的集成框架&#xff0c;用于简化和加速在 Spring Boot 项目中集成不同的消息传递、数据转换和系统集成组件。本文将介绍 Spring Boot Starter Integration 的主要用途以及其在简化集成过程中的优势。 1. Spring…

前端导出下载文件后提示无法打开文件

问题 项目中的导出文件功能&#xff0c;导出下载后的文件打开提示如下&#xff1a; 原因 对返回的响应数据进行打印&#xff0c;发现响应数据为字符串格式&#xff0c;前期规划的后端返回数据应该 blob 对象的。后经排查后发现是请求头缺少了响应数据格式的配置&#xff0c;应…

#FPGA(IRDA)

1.IDE:Quartus II 2.设备&#xff1a;Cyclone II EP2C8Q208C8N 3.实验&#xff1a;IRDA&#xff08;仿真接收一个来自0x57地址的数据0x22 (十进制34)&#xff09; 4.时序图&#xff1a; 5.步骤 6.代码&#xff1a; irda_receive.v module irda_receive ( input wire…

从故宫修建看「软件物料清单」的重要性 @安全历史01

故宫&#xff0c;这座中国传统文化的重要代表和象征性建筑已屹立近600年&#xff0c;是世界上现存规模最大、保存最为完整的木质结构古建筑之一。 故宫之所以能至今保存完好&#xff0c;除持续保护和修缮外&#xff0c;其使用的木材和砖石等材料也经过了精挑细选&#xff0c;保…

C++函数对象-运算符函数对象 - 旧式绑定器与适配器 - 从成员函数指针创建包装器,可以一个对象指针调用 (std::mem_fun)

任何定义了函数调用操作符的对象都是函数对象。C 支持创建、操作新的函数对象&#xff0c;同时也提供了许多内置的函数对象。 旧式绑定器与适配器 早期提供功能支持的几个工具在 C11 中弃用&#xff0c;并于 C17 中移除&#xff08;旧否定器于 C17 中弃用并于 C20 中移除&#…

IOBR2 更新(学习自备)

IOBR查看其收录的相关基因集(自备)_肿瘤 tme特征 iobr-CSDN博客 IOBR2&#xff1a;多维度解析肿瘤微环境 - 知乎 (zhihu.com) 学习手册&#xff1a;https://iobr.github.io/book/ &#xff08;里面有详细教程&#xff09; 系统综合的分析工具&#xff08;Immuno-Oncology Bi…

渗透工具——kali中wpscan简介

一、什么是wpscan 1、常用于做用户名枚举爆破 2、WPScan是一个扫描 WordPress 漏洞的黑盒子扫描器&#xff0c;它可以为所有 Web 开发人员扫描 WordPress 漏洞并在他们开发前找到并解决问题。我们还使用了 Nikto &#xff0c;它是一款非常棒的Web 服务器评估工具&#xff0c;…

神经网络系列---独热编码(One-Hot Encoding)

文章目录 独热编码&#xff08;One-Hot Encoding&#xff09; 独热编码&#xff08;One-Hot Encoding&#xff09; 是一种常用的数据预处理技术&#xff0c;用于将分类变量转换为计算机易于处理的二进制格式。在机器学习和数据分析中&#xff0c;我们通常会遇到非数值型的特征…