version-2.3[实现连个SpringBoot间的通信(将匹配系统放在微服务模块)]

pull/1/head
dyh 3 years ago
parent 28c2c2dc04
commit 371e68cfdd

@ -1,20 +1,22 @@
<?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">
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backendcloud</artifactId>
<groupId>com.kob</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.kob</groupId>
<artifactId>backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>backend</name>
<description>backend</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
@ -128,47 +130,4 @@
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.kob.backend.BackendApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
</project>

@ -0,0 +1,13 @@
package com.kob.backend.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}

@ -41,6 +41,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.and()
.authorizeRequests()
.antMatchers("/user/account/token/", "/user/account/register/").permitAll()
.antMatchers("/pk/start/game/").hasIpAddress("127.0.0.1")
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated();

@ -9,6 +9,10 @@ import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
@ -24,8 +28,6 @@ public class WebSocketServer {
//它会锁住一小部分,其他部分的读写不受影响,其他线程访问没上锁的地方不会被阻塞。
//(userId,WebSocketServer实例连接)
public final static ConcurrentHashMap<Integer,WebSocketServer> users = new ConcurrentHashMap<>();
//匹配池
final private static CopyOnWriteArraySet<User> matchpool = new CopyOnWriteArraySet<>();
//当前用户
private User user ;
//session维护链接
@ -35,13 +37,18 @@ public class WebSocketServer {
//加入数据库
private static UserMapper userMapper;
public static RecordMapper recordMapper;
private static RestTemplate restTemplate;
@Autowired
public void setUserMapper(UserMapper userMapper){
WebSocketServer.userMapper = userMapper;
}
@Autowired
public void setRecordMapper(RecordMapper recordMapper) { WebSocketServer.recordMapper = recordMapper;}
@Autowired
public void setRestTemplate(RestTemplate restTemplate){ WebSocketServer.restTemplate = restTemplate ;}
private static final String addPlayerUrl = "http://127.0.0.1:3001/player/add/";
private static final String removePlayerUrl = "http://127.0.0.1:3001/player/remove/";
@OnOpen
public void onOpen(Session session, @PathParam("token") String token) throws IOException//token是前端url里的参数
@ -66,57 +73,67 @@ public class WebSocketServer {
System.out.println("disconnexted!");
if(this.user != null){
users.remove(this.user.getId());
matchpool.remove(this.user);
}
}
//前端点击 开始匹配 触发
private void startMatching(){
System.out.println("start matching!");
matchpool.add(this.user);
while(matchpool.size() >= 2) {
Iterator<User> it = matchpool.iterator();//迭代器
User a = it.next(), b = it.next();
matchpool.remove(a);
matchpool.remove(b);
//一局游戏的线程
Game game =new Game(13,14,20,a.getId(),b.getId());
game.createMap();
//a,b共同的地图==>将地图赋给a,b对应的连接
//封装向前端传地图,操作等信息(匹配成功后调用)
public static void startGame(Integer aId,Integer bId){
User a =userMapper.selectById(aId),b = userMapper.selectById(bId);
//一局游戏的线程
Game game =new Game(13,14,20,a.getId(),b.getId());
game.createMap();
//a,b共同的地图==>将地图赋给a,b对应的连接
if(users.get(a.getId()) != null)
users.get(a.getId()).game = game ;
if(users.get(b.getId()) != null)
users.get(b.getId()).game = game ;//b连接的地图
game.start();
JSONObject respGame = new JSONObject();
respGame.put("a_id",game.getPlayerA().getId());
respGame.put("a_sx",game.getPlayerA().getSx());
respGame.put("a_sy",game.getPlayerA().getSy());
respGame.put("b_id",game.getPlayerB().getId());
respGame.put("b_sx",game.getPlayerB().getSx());
respGame.put("b_sy",game.getPlayerB().getSy());
respGame.put("map",game.getG());
JSONObject respA = new JSONObject();//返回给a
respA.put("event", "start-matching");
respA.put("opponent_username", b.getUsername());
respA.put("opponent_photo", b.getPhoto());
respA.put("game", respGame);
game.start();
JSONObject respGame = new JSONObject();
respGame.put("a_id",game.getPlayerA().getId());
respGame.put("a_sx",game.getPlayerA().getSx());
respGame.put("a_sy",game.getPlayerA().getSy());
respGame.put("b_id",game.getPlayerB().getId());
respGame.put("b_sx",game.getPlayerB().getSx());
respGame.put("b_sy",game.getPlayerB().getSy());
respGame.put("map",game.getG());
JSONObject respA = new JSONObject();//返回给a
respA.put("event", "start-matching");
respA.put("opponent_username", b.getUsername());
respA.put("opponent_photo", b.getPhoto());
respA.put("game", respGame);
if(users.get(a.getId()) != null)
users.get(a.getId()).sendMessage(respA.toJSONString());//获取a对应的连接向前端传递信息String
JSONObject respB = new JSONObject();//返回给b
respB.put("event", "start-matching");
respB.put("opponent_username", a.getUsername());
respB.put("opponent_photo", a.getPhoto());
respB.put("game", respGame);
JSONObject respB = new JSONObject();//返回给b
respB.put("event", "start-matching");
respB.put("opponent_username", a.getUsername());
respB.put("opponent_photo", a.getPhoto());
respB.put("game", respGame);
if(users.get(b.getId()) != null)
users.get(b.getId()).sendMessage(respB.toJSONString());//获取b对应的连接向前端传递信息String
}
}
//前端点击 取消 触发
//前端点击 开始匹配 触发--》加入一个用户进行匹配--->发送请求给matchingsystem
private void startMatching(){
System.out.println("start matching!");
//向另一个Spring Boot发送的数据
MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
data.add("user_id",this.user.getId().toString());
data.add("rating",this.user.getRating().toString());
restTemplate.postForObject(addPlayerUrl, data, String.class);
}
//前端点击 取消 触发 ---》取消一个用户的匹配--->发送请求给matchingsystem
private void stopMatching(){
System.out.println("stop matching!");
matchpool.remove(this.user);
MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
data.add("user_id",this.user.getId().toString());
restTemplate.postForObject(removePlayerUrl,data,String.class);
}
public void move(int dirction){

@ -245,8 +245,10 @@ public class Game extends Thread {
public void sendAllMessage(String message){
//向全端发信息
WebSocketServer.users.get(playerA.getId()).sendMessage(message);
WebSocketServer.users.get(playerB.getId()).sendMessage(message);
if(WebSocketServer.users.get(playerA.getId())!=null)
WebSocketServer.users.get(playerA.getId()).sendMessage(message);
if(WebSocketServer.users.get(playerB.getId())!=null)
WebSocketServer.users.get(playerB.getId()).sendMessage(message);
}
private void saveToDatabase()

@ -0,0 +1,23 @@
package com.kob.backend.controller.pk;
import com.kob.backend.service.pk.StartGameService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Objects;
@RestController
public class StartGameController {
@Autowired
private StartGameService startGameService;
@PostMapping("/pk/start/game/")
public String StartGame(@RequestParam MultiValueMap<String,String> data){
Integer aId = Integer.parseInt(Objects.requireNonNull(data.getFirst("a_id")));
Integer bId = Integer.parseInt(Objects.requireNonNull(data.getFirst("b_id")));
return startGameService.startGame(aId,bId);
}
}

@ -18,7 +18,6 @@ public class Bot {
private String title;
private String description;
private String content;
private Integer rating;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "Asia/Shanghai")
private Date createtime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "Asia/Shanghai")

@ -23,4 +23,5 @@ public class User {
private String username;
private String password;
private String photo;
private Integer rating;
}

@ -62,7 +62,7 @@ public class AddServiceImpl implements AddService {
}
Date now = new Date();
Bot bot = new Bot(null,user.getId(),title,description,content,1500,now,now);
Bot bot = new Bot(null,user.getId(),title,description,content,now,now);
botMapper.insert(bot);
map.put("error_message","success");

@ -80,7 +80,6 @@ public class UpdateServiceImpl implements UpdateService {
title,
description,
content,
bot.getRating(),
bot.getCreatetime(),
now
);

@ -0,0 +1,15 @@
package com.kob.backend.service.impl.pk;
import com.kob.backend.consumer.WebSocketServer;
import com.kob.backend.service.pk.StartGameService;
import org.springframework.stereotype.Service;
@Service
public class StartGameServiceImpl implements StartGameService {
@Override
public String startGame(Integer aId, Integer bId) {
System.out.println("start game: "+ aId+" "+bId);
WebSocketServer.startGame(aId,bId);
return "start game success";
}
}

@ -79,7 +79,7 @@ public class RegisterServiceImpl implements RegisterService {
//添加一个用户
String encodedPassword = passwordEncoder.encode(password);//密码
String photo = "https://cdn.acwing.com/media/user/profile/photo/85918_lg_5ed2550a14.png";
User user = new User(null,username,encodedPassword,photo);
User user = new User(null,username,encodedPassword,photo,1500);
userMapper.insert(user);
map.put("error_message","success");

@ -0,0 +1,5 @@
package com.kob.backend.service.pk;
public interface StartGameService {
public String startGame(Integer aId,Integer bId);
}

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="web" name="Web">
<configuration>
<webroots />
<sourceRoots>
<root url="file://$MODULE_DIR$/src/main/java" />
<root url="file://$MODULE_DIR$/src/main/resources" />
</sourceRoots>
</configuration>
</facet>
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:2.7.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.13.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.13.3" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.30" level="project" />
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.26" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.2.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.2.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:5.3.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.3.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.2.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:5.3.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.2.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.11.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.41" level="project" />
<orderEntry type="library" name="Maven: org.glassfish:jakarta.el:3.0.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.41" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.2.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.2.12.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.3.7.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.3.7.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.3.7.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: jakarta.activation:jakarta.activation-api:1.2.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.16.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.6.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:3.3.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.10.18" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.10.18" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-junit-jupiter:3.3.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.2.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.2.12.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.2.12.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.7.0" level="project" />
</component>
</module>

@ -0,0 +1,64 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backendcloud</artifactId>
<groupId>com.kob</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.kob.matchingsystem</groupId>
<artifactId>matchingsystem</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.7.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

@ -0,0 +1,13 @@
package com.kob.matchingsystem;
import com.kob.matchingsystem.service.impl.MatchingServiceImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MatchingSystemApplication {
public static void main(String[] args) {
MatchingServiceImpl.matchingPool.start();//启动线程
SpringApplication.run(MatchingSystemApplication.class, args);
}
}

@ -0,0 +1,13 @@
package com.kob.matchingsystem.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}

@ -0,0 +1,23 @@
package com.kob.matchingsystem.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/player/add/","/player/remove/").hasIpAddress("localhost")//新加
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated();
}
}

@ -0,0 +1,31 @@
package com.kob.matchingsystem.controller;
import com.kob.matchingsystem.service.MatchingService;
import com.kob.matchingsystem.service.impl.MatchingServiceImpl;
import com.kob.matchingsystem.service.impl.utils.MatchingPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Objects;
@RestController
public class MatchingController {
@Autowired
private MatchingService matchingService;
@PostMapping("/player/add/")
public String addPlayer(@RequestParam MultiValueMap<String,String> data){
Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id")));
Integer rating = Integer.parseInt(Objects.requireNonNull(data.getFirst("rating")));
return matchingService.addPlayer(userId,rating);
}
@PostMapping("/player/remove/")
public String removePlayer(@RequestParam MultiValueMap<String,String> data){
Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id")));
return matchingService.removePlayer(userId);
}
}

@ -0,0 +1,6 @@
package com.kob.matchingsystem.service;
public interface MatchingService {
public String addPlayer(Integer userId,Integer rating);
public String removePlayer(Integer userId);
}

@ -0,0 +1,26 @@
package com.kob.matchingsystem.service.impl;
import com.kob.matchingsystem.service.MatchingService;
import com.kob.matchingsystem.service.impl.utils.MatchingPool;
import org.springframework.stereotype.Service;
@Service
public class MatchingServiceImpl implements MatchingService {
//就一个线程
public static final MatchingPool matchingPool = new MatchingPool();
@Override
public String addPlayer(Integer userId, Integer rating) {
System.out.println("add player: "+userId+" "+rating);
matchingPool.addPlayer(userId,rating);
return "add player success";
}
@Override
public String removePlayer(Integer userId) {
System.out.println("remove player: "+userId);
matchingPool.removePlayer(userId);
return "remove player success";
}
}

@ -0,0 +1,115 @@
package com.kob.matchingsystem.service.impl.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
//为了将Bean形容的类注入进来
@Component
public class MatchingPool extends Thread {
private static List<Player> players = new ArrayList<>();
private ReentrantLock lock = new ReentrantLock();
private final static String startGameUrl = "http://127.0.0.1:3000/pk/start/game/";
//因为是Bean
private static RestTemplate restTemplate ;
@Autowired
public void setRestTemplate(RestTemplate restTemplate) { MatchingPool.restTemplate = restTemplate ;}
//两个线程访问1.匹配线程 2.传入参数的线程,开始匹配
public void addPlayer(Integer userId,Integer rating){
lock.lock();
try {
players.add(new Player(userId,rating,0));
} finally {
lock.unlock();
}
}
public void removePlayer(Integer userId){
lock.lock();
try {
List<Player> newPlayers = new ArrayList<>();
for(Player player:players){
if(!player.getUserId().equals(userId)){
newPlayers.add(player);
}
}
players = newPlayers ;
} finally {
lock.lock();
}
}
private void increaseWaitingTime(){//所有玩家的等待加时间1
for(Player player:players){
player.setWaitingTime(player.getWaitingTime()+1);
}
}
private void matcingPlayers(){//匹配所有玩家
System.out.println("match players: "+players.toString());
boolean[] used = new boolean[players.size()];
for(int i = 0 ; i < players.size() ; i++){
if(used[i])continue;
for(int j = i+1 ;j < players.size() ;j++){
if(used[j])continue;
Player a = players.get(i),b = players.get(j);
if(checkMatched(a,b)){
used[i] = used[j] = true;
sendResult(a,b);
break;
}
}
}
//将匹配成功的删除
List<Player> newPlayers = new ArrayList<>();
for(int i= 0;i<players.size();i++){
if(!used[i]){
newPlayers.add(players.get(i));
}
}
players = newPlayers;
}
private boolean checkMatched(Player a,Player b){//判断两个玩家是否匹配
int ratingDelta = Math.abs(a.getRating() - b.getRating());
int waitingTime = Math.min(a.getWaitingTime(),b.getWaitingTime());
return ratingDelta <= 10*waitingTime ;
}
private void sendResult(Player a,Player b){
System.out.println("send result: " + a + " " + b);
MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
data.put("a_id", Collections.singletonList(a.getUserId().toString()));
data.put("b_id", Collections.singletonList(b.getUserId().toString()));
restTemplate.postForObject(startGameUrl,data,String.class);
}
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
lock.lock();
try {
increaseWaitingTime();
matcingPlayers();
} finally {
lock.unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

@ -0,0 +1,14 @@
package com.kob.matchingsystem.service.impl.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Player {
private Integer userId;
private Integer rating;
private Integer waitingTime;//等待时间
}

@ -0,0 +1,95 @@
<?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>
<groupId>com.kob</groupId>
<artifactId>backendcloud</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
<modules>
<module>matchingsystem</module>
<module>backend</module>
</modules>
<name>backendcloud</name>
<description>backendcloud</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.kob.backendcloud.BackendcloudApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Loading…
Cancel
Save