• Spring Boot 7 微服务执行Bot代码(传递路线是难点)


    在这里插入图片描述

    本节课也是新开一个微服务:BotRunningSystem
    红色为本次实现:
    在这里插入图片描述
    代码执行,此项目只支持java代码的执行,用的是joor java 8实现。

    可扩展为docker实现,设置内存上限,时间,用命令可执行所有语言代码,并具备一定安全性,因为docker与运行环境隔绝。

    1.让BotRunning System获得到前端选择的Bot

    1.1.新建Bot执行微服务项目

    右键backendcloud->新建->maven

    1.2.修改pom依赖

    1.复制粘贴matchingsystem的pom中的所有依赖
    2.添加新依赖 joor-java-8 :可以在Java中动态编译Java代码

    1.3.BotRunningSystem接收前端选择的botId

    文件结构

    botrunningsystem
        config
            RestTemplateConfig.java
            SecurityConfig.java
        controller
            BotRunningController.java
        service
            impl
                BotRunningServiceImpl.java
            BotRunningService.java
        BotRunningSystemApplication.java
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    将BotRunningSystem/Main.java 更名为 BotRunningSystemApplication.java

    package com.kob.botrunningsystem;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class BotRunningSystemApplication {
        public static void main(String[] args) {
            SpringApplication.run(BotRunningSystemApplication.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    接口

    package com.kob.botrunningsystem.service;
    
    public interface BotRunningService {
        public String addBot(Integer userId,String botCode,String input);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    接口实现

    package com.kob.botrunningsystem.service.impl;
    
    import com.kob.botrunningsystem.service.BotRunningService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class BotRunningServiceImpl implements BotRunningService {
        @Override
        public String addBot(Integer userId, String botCode, String input) {
            System.out.println("add bot: " + userId + " " + botCode + " " + input);
            return "add bot success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    控制器

    package com.kob.botrunningsystem.controller;
    
    import com.kob.botrunningsystem.service.BotRunningService;
    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 BotRunningController {
        @Autowired
        private BotRunningService botRunningService;
    
        @PostMapping("/bot/add/")
        public String addBot(@RequestParam MultiValueMap<String,String> data){
            Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id")));
            String botCode = data.getFirst("bot_code");
            String input = data.getFirst("input");
            return botRunningService.addBot(userId,botCode,input);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    权限控制(网关)

    package com.kob.botrunningsystem.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("/bot/add/").hasIpAddress("127.0.0.1")//新加
                    .antMatchers(HttpMethod.OPTIONS).permitAll()
                    .anyRequest().authenticated();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    服务间发送消息的RestTemplate

    package com.kob.botrunningsystem.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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    端口配置
    在resources新建文件

    1.4.前端选择Bot+发送bot_id给后端

    匹配界面
    添加选择操作方式
    在这里插入图片描述

    <template>
      <div class="matchground">
        <div class="row">
            
            <!-- 自己 -->
            <div class="col-4">
                <div class="user-photo">
                    <img :src="$store.state.user.photo" alt="">
                </div>
                <div class="user-username">
                    {{$store.state.user.username}}
                </div>
            </div>
            <!-- 选择Bot -->
            <div class="col-4">
                <div class="user-select-bot">
                    <select class="form-select" aria-label="Default select example" v-model="select_bot">
                        <option value="-1" selected>亲自出马</option>
                        <option v-for="bot in bots" :key="bot.id" :value="bot.id">{{ bot.title }}</option>
                    </select>
                </div>
            </div>
            <!-- 对手 -->
            <div class="col-4">
                <div class="user-photo">
                    <img :src="$store.state.pk.opponent_photo" alt="">
                </div>
                <div class="user-username">
                    {{$store.state.pk.opponent_username}}
                </div>
            </div>
    
            <div class="col-12" style="text-align : center;  padding-top : 12vh;">
                <button type="button" class="btn btn-warning btn-lg" @click="click_match_btn">{{match_btn_info}}</button>
            </div>
            
        </div>
      </div>
    </template>
    
    <script>
    import { ref } from "vue"
    import { useStore } from "vuex"
    import $ from "jquery"
    
    export default {
        setup(){
            const store = useStore();
            let match_btn_info = ref("开始匹配")
            let bots = ref([])
            let select_bot = ref(-1)
    
            const click_match_btn = ( )=>{
                if(match_btn_info.value === "开始匹配"){
                    match_btn_info.value = "取消";
                    
                    //向后端发送信息
                    store.state.pk.socket.send(JSON.stringify({
                        event:"start-matching",
                        bot_id: select_bot.value,
                    }));
                } else if(match_btn_info.value === "取消"){
                    match_btn_info.value = "开始匹配";
                    
                    store.state.pk.socket.send(JSON.stringify({
                        event:"stop-matching",
                    }));
                }
            }
    
            const refresh_bots = () => {
                $.ajax({
                    url: "http://127.0.0.1:3000/user/bot/getlist/",
                    type: "get",
                    headers: {
                        'Authorization': "Bearer " + store.state.user.token,
                    },
                    success(resp) {
                        bots.value = resp;
                    }
                })
            };
            refresh_bots();
    
            return {
                match_btn_info,
                click_match_btn,
                bots,
                select_bot,
            }
        }
    }
    </script>
    
    <style scoped>
    
    div.matchground {
        width: 60vw;
        height: 70vh;
        background-color:rgba(50 ,50 ,50 ,0.5);
        margin: 40px auto;
    }
    div.user-photo {
        text-align: center;
        padding-top: 10vh;
    }
    div.user-photo > img{
        border-radius: 50%;
        width: 20vh;
    }
    div.user-username {
        text-align: center;
        font-size: 20px;
        font-weight: 600;
        color: white;
        margin-top: 2vh;
    }
    div.user-select-bot {
        padding-top: 20vh;
    }
    div.user-select-bot > select {
        width: 60%;
        margin: 0 auto;
    }
    
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126

    1.5.后端接收bot

    backend接收Bot

    在这里插入图片描述

    WebSocketServer接收到匹配请求,将bot传给匹配服务
    在这里插入图片描述
    在这里插入图片描述

    Matching System接收Bot

    在这里插入图片描述

    Matching System接收到backend传的botId,将bot传给BotRunningSystem服务
    控制器
    在这里插入图片描述
    接口
    在这里插入图片描述
    实现接口
    在这里插入图片描述

    匹配池

    在这里插入图片描述
    在这里插入图片描述

    匹配池的Player

    在这里插入图片描述

    匹配池返回结果加上botId

    在这里插入图片描述
    在这里插入图片描述

    StartGameController.java

    在这里插入图片描述

    在这里插入图片描述

    StartGameService.java

    在这里插入图片描述

    StartGameServiceImpl.java

    在这里插入图片描述

    WebSocketServer.java

    在这里插入图片描述
    在这里插入图片描述

    Player.java

    在这里插入图片描述

    WebSocketServer.java

    将RestTemplate变成public,若是代码输入则屏蔽人的输入
    在这里插入图片描述

    Game.java

    在这里插入图片描述

    private final Player playerA,playerB;
    private final static String addBotUrl = "http://127.0.0.1:3002/bot/add/";
    
    public Game(
            Integer rows,
            Integer cols,
            Integer inner_walls_count,
            Integer idA,
            Bot botA,
            Integer idB,
            Bot botB
    ) {
        this.rows = rows;
        this.cols = cols;
        this.inner_walls_count = inner_walls_count;
        this.g = new int[rows][cols];
        Integer botIdA = -1,botIdB = -1;
        String botCodeA = "",botCodeB = "";
        if(botA != null){
            botIdA = botA.getId();
            botCodeA = botA.getContent();
        }
        if(botB != null){
            botIdB = botB.getId();
            botCodeB = botB.getContent();
        }
        playerA = new Player(idA,botIdA,botCodeA,this.rows - 2, 1, new ArrayList<>());
        playerB = new Player(idB,botIdB,botCodeB,1, this.cols - 2, new ArrayList<>());
    }
    
    
    
    //获得input
    private String getInput(Player player){
        Player me,you ;
        if(playerA.getId().equals(player.getId())){
            me = playerA ;
            you = playerB ;
        } else {
            me = playerB ;
            you = playerA ;
        }
        return getMapString() + "#" +
                me.getSx() + "#" +
                me.getSy() + "#(" +
                me.getStepsString() + ")#" +
                you.getSx() + "#" +
                you.getSy() + "#(" +
                you.getStepsString() + "#)" ;
    }
    
    private void sendBotCode(Player player){
        if(player.getBotId().equals(-1)) return ;//亲自出马
        MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
        data.add("user_id",player.getId().toString());
        data.add("bot_code",player.getBotCode());
        data.add("input",getInput(player));
        WebSocketServer.restTemplate.postForObject(addBotUrl,data,String.class);
    }
    
    private boolean nextStep(){//两名玩家的下一步
        try {
            Thread.sleep(200);//因为前端走一格200ms
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
        sendBotCode(playerA);
        sendBotCode(playerB);
    ......
    }
    
    private String getMapString(){
        StringBuilder res = new StringBuilder();
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                res.append(g[i][j]);
            }
        }
        return res.toString();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    成功
    在这里插入图片描述

    1.6.总结:实现了BotId传送到BotRunningSystem系统

    在这里插入图片描述

    2.BotRunning System的实现

    2.1思路:生产者消费者模型

    在这里插入图片描述

    2.2文件结构

    BotRunningSystem
        service
            impl
                utils
                    Bot.java
                    BotPool.java
                    Consumer.java
        utils
            Bot.java
            BotInterface.java
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.3Bot的实现

    package com.kob.botrunningsystem.service.impl.utils;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Bot {
        private Integer userId;
        private String botCode;
        private String input;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.4BotPoll的实现

    虽然队列没用消息队列,但是因为我们写了条件变量与锁的操作,所以等价于消息队列

    package com.kob.botrunningsystem.service.impl.utils;
    
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class BotPool extends Thread{
    
        private final ReentrantLock lock = new ReentrantLock();
        private final Condition condition = lock.newCondition();//条件变量
        private final Queue<Bot> bots = new LinkedList<>();//消息队列-->add,remove-->锁
    
        //添加一个任务-Bot
        public void addBot(Integer userId,String botCode,String input){
            lock.lock();//涉及到bots
            try {
                bots.add(new Bot(userId,botCode,input));
                condition.signalAll();
            } finally {
                lock.unlock();
            }
    
        }
        //消费一个任务
        private void consume(Bot bot){
            Comsumer comsumer = new Comsumer();
            comsumer.startTimeut(2000,bot);
        }
    
        @Override
        public void run() {
            while (true){
                lock.lock();
                if(bots.isEmpty()){//空
                    try {
                        condition.await();//【消息队列空】阻塞当前线程,直到被唤醒(默认包含解锁)
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        lock.unlock();
                        break;
                    }
                } else {
                    Bot bot = bots.remove();//取出当前任务+移除
                    lock.unlock();
                    consume(bot);//消耗任务,用时长,执行代码
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    2.5BotRunningServiceImpl.java

    加任务

    package com.kob.botrunningsystem.service.impl;
    
    import com.kob.botrunningsystem.service.BotRunningService;
    import com.kob.botrunningsystem.service.impl.utils.BotPool;
    import org.springframework.stereotype.Service;
    
    @Service
    public class BotRunningServiceImpl implements BotRunningService {
    6    public final static BotPool botPool = new BotPool();
    
        @Override
        public String addBot(Integer userId, String botCode, String input) {
            System.out.println("add bot: " + userId + " " + botCode + " " + input);
            botPool.addBot(userId,botCode,input);
            return "add bot success";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.6BotPool线程的启动

    package com.kob.botrunningsystem;
    
    import com.kob.botrunningsystem.service.impl.BotRunningServiceImpl;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class BotRunningSystemApplication {
        public static void main(String[] args) {
            BotRunningServiceImpl.botPool.start();//启动线程
            SpringApplication.run(BotRunningSystemApplication.class,args);
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.7BotInterface.java

    用户写Bot实现的接口

    package com.kob.botrunningsystem.utils;
    
    public interface BotInterface {
        public Integer nextMove(String input);//下一步方向
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.8Bot.java

    package com.kob.botrunningsystem.utils;
    
    public class Bot implements com.kob.botrunningsystem.utils.BotInterface {
        @Override
        public Integer nextMove(String input) {
            return 0;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.9Consumer的实现

    package com.kob.botrunningsystem.service.impl.utils;
    
    import com.kob.botrunningsystem.utils.BotInterface;
    import org.joor.Reflect;
    
    import java.util.UUID;
    
    public class Comsumer extends Thread{
        private Bot bot;
        public void startTimeut(long timeout,Bot bot){
            this.bot = bot;
            this.start();
            try {
                this.join(timeout);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                this.interrupt();
            }
        }
    
        private String addUid(String code,String uid){
            int k = code.indexOf(" implements com.kob.botrunningsystem.utils.BotInterface");
            return code.substring(0,k) + uid +code.substring(k);
        }
    
        @Override
        public void run() {
            UUID uuid = UUID.randomUUID();
            String uid = uuid.toString().substring(0,8);
    
            BotInterface botInterface = Reflect.compile(
                    "com.kob.botrunningsystem.utils.Bot" + uid,
                    addUid(bot.getBotCode(),uid)
            ).create().get();
            Integer direction = botInterface.nextMove(bot.getInput());
    
            System.out.println("move-direction: " + bot.getUserId() + " " + direction);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    2.10BotPool.java

    在这里插入图片描述

    2.11测试

    package com.kob.botrunningsystem.utils;
    
    public class Bot implements com.kob.botrunningsystem.utils.BotInterface {
        @Override
        public Integer nextMove(String input) {
            return 0;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    package com.kob.botrunningsystem.utils;
    
    public class Bot implements com.kob.botrunningsystem.utils.BotInterface {
        @Override
        public Integer nextMove(String input) {
            return 2;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    2.12小Bug

    在游戏结束后,点到其他页面再点回pk页面,结果没有消失
    在这里插入图片描述

    3.将Bot执行结果传给前端

    3.1.BackEnd接收Bot代码的结果

    在这里插入图片描述
    文件结构

    backend
        controller
            pk
                ReceiveBotMoveController.java
        service
            impl
                pk
                    ReceiveBotMoveServiceImpl.java
            pk
                ReceiveBotMoveService.java
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    接口

    package com.kob.backend.service.pk;
    
    public interface ReceiveBotMoveService {
        public String receiveBotMove(Integer userId,Integer direction);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    WebSocketServer操作类
    在这里插入图片描述

    接口实现

    package com.kob.backend.service.impl.pk;
    
    import com.kob.backend.consumer.WebSocketServer;
    import com.kob.backend.consumer.utils.Game;
    import com.kob.backend.service.pk.ReceiveBotMoveService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class ReceiveBotMoveServiceImpl implements ReceiveBotMoveService {
        @Override
        public String receiveBotMove(Integer userId, Integer direction) {
    
            System.out.println("receive bot move: " + userId + " " +direction);
            if(WebSocketServer.users.get(userId)!=null){
                Game game = WebSocketServer.users.get(userId).game;
                if(game != null){
                    if(game.getPlayerA().getId().equals(userId)){//当前链接是A用户
                        game.setNextStepA(direction);
                    } else if(game.getPlayerB().getId().equals(userId)){//当前链接是B用户
                        game.setNextStepB(direction);
                    }
                }
            }
            return "receive bot move success";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    控制器

    package com.kob.backend.controller.pk;
    
    import com.kob.backend.service.pk.ReceiveBotMoveService;
    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 ReceiveBotMoveController {
        @Autowired
        private ReceiveBotMoveService receiveBotMoveService;
    
        @PostMapping("/pk/receive/bot/move/")
        public String receiveBotMove(@RequestParam MultiValueMap<String,String> data){
            System.out.println("+++++++++++++++++++++++++++++++");
            Integer userId = Integer.parseInt(Objects.requireNonNull(data.getFirst("user_id")));
            Integer direction = Integer.parseInt(Objects.requireNonNull(data.getFirst("direction")));
            return receiveBotMoveService.receiveBotMove(userId,direction);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    权限控制(网关)

    //实现用户密码的加密存储。==>加上此文件,必须是密文存储
    //实现公开页面
    package com.kob.backend.config;
    
    import com.kob.backend.config.filter.JwtAuthenticationTokenFilter;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpMethod;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    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;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/user/account/token/", "/user/account/register/").permitAll()
                    .antMatchers("/pk/start/game/","/pk/receive/bot/move/").hasIpAddress("127.0.0.1")
                    .antMatchers(HttpMethod.OPTIONS).permitAll()
                    .anyRequest().authenticated();
    
            http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        }
    
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/websocket/**");//放行这一类链接
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    3.2.BotRunningSystem返回Bot执行结果

    Consumer.java

    
    
    package com.kob.botrunningsystem.service.impl.utils;
    
    import com.kob.botrunningsystem.utils.BotInterface;
    import org.joor.Reflect;
    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.UUID;
    
    @Component
    public class Consumer extends Thread{
    
        private static RestTemplate restTemplate ;
        @Autowired
        public void setRestTemplate(RestTemplate restTemplate){
            Consumer.restTemplate = restTemplate;
        }
        private Bot bot;
        private final static String receiveBotMoveUrl = "http://127.0.0.1:3000/pk/receive/bot/move/";
    
    
        public void startTimeout(long timeout,Bot bot){
            this.bot = bot;
            this.start();
            try {
                this.join(timeout);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                this.interrupt();
            }
        }
    
        private String addUid(String code,String uid){
            int k = code.indexOf(" implements com.kob.botrunningsystem.utils.BotInterface");
            System.out.println(k);
            return code.substring(0,k) + uid +code.substring(k);
        }
    
        @Override
        public void run() {
            UUID uuid = UUID.randomUUID();
            String uid = uuid.toString().substring(0,8);
    
            BotInterface botInterface = Reflect.compile(
                    "com.kob.botrunningsystem.utils.Bot" + uid,
                    addUid(bot.getBotCode(),uid)
            ).create().get();
    
            Integer direction = botInterface.nextMove(bot.getInput());
    
            System.out.println("move-direction: " + bot.getUserId() + " " + direction);
    
            MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
            data.add("user_id",bot.getUserId().toString());
            data.add("direction",direction.toString());
    
            restTemplate.postForObject(receiveBotMoveUrl,data,String.class);
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    测试

    y总bot代码:

    package com.kob.botrunningsystem.utils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Bot implements com.kob.botrunningsystem.utils.BotInterface {
        static class Cell {
            public int x, y;
            public Cell(int x, int y) {
                this.x = x;
                this.y = y;
            }
        }
    
        private boolean check_tail_increasing(int step) {  // 检验当前回合,蛇的长度是否增加
            if (step <= 10) return true;
            return step % 3 == 1;
        }
    
        public List<Cell> getCells(int sx, int sy, String steps) {
            steps = steps.substring(1, steps.length() - 1);
            List<Cell> res = new ArrayList<>();
    
            int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
            int x = sx, y = sy;
            int step = 0;
            res.add(new Cell(x, y));
            for (int i = 0; i < steps.length(); i ++ ) {
                int d = steps.charAt(i) - '0';
                x += dx[d];
                y += dy[d];
                res.add(new Cell(x, y));
                if (!check_tail_increasing( ++ step)) {
                    res.remove(0);
                }
            }
            return res;
        }
    
        @Override
        public Integer nextMove(String input) {
            String[] strs = input.split("#");
            int[][] g = new int[13][14];
            for (int i = 0, k = 0; i < 13; i ++ ) {
                for (int j = 0; j < 14; j ++, k ++ ) {
                    if (strs[0].charAt(k) == '1') {
                        g[i][j] = 1;
                    }
                }
            }
    
            int aSx = Integer.parseInt(strs[1]), aSy = Integer.parseInt(strs[2]);
            int bSx = Integer.parseInt(strs[4]), bSy = Integer.parseInt(strs[5]);
    
            List<Cell> aCells = getCells(aSx, aSy, strs[3]);
            List<Cell> bCells = getCells(bSx, bSy, strs[6]);
    
            for (Cell c: aCells) g[c.x][c.y] = 1;
            for (Cell c: bCells) g[c.x][c.y] = 1;
    
            int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
            for (int i = 0; i < 4; i ++ ) {
                int x = aCells.get(aCells.size() - 1).x + dx[i];
                int y = aCells.get(aCells.size() - 1).y + dy[i];
                if (x >= 0 && x < 13 && y >= 0 && y < 14 && g[x][y] == 0) {
                    return i;
                }
            }
    
            return 0;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
  • 相关阅读:
    【C语言】指针的进阶(二)—— 回调函数的讲解以及qsort函数的使用方式
    排序 “叁” 之交换排序
    Kaggle使用上传的d2l包
    Baumer工业相机堡盟工业相机如何通过BGAPI SDK设置相机的图像剪切(ROI)功能(C#)
    如何看待越来越多人报名参加软考?
    glide set gif start stop
    当今微服务盛行之架构师必经之路-领域驱动设计-上
    pico+unity3d运行测试方法
    微信怎么自动添加好友?
    Centos7宝塔部署python
  • 原文地址:https://blog.csdn.net/qq_52384627/article/details/126531278