寻求一些建议,尝试制作一款纸牌游戏。我是 Spring MVC 的完全初学者(如果以下问题还没有透露这一点..)
使用代理 session 范围 Bean 来管理游戏状态,我的路线似乎可以使用 Postman 正常工作,并且能够创建新玩家。
游戏类
@Component
public class Game {
private Deck deck;
private ArrayList<Player> players;
private HashMap<Player, Integer> wins;
@Autowired
public Game(Deck deck){
this.deck = deck;
this.players = new ArrayList<>();
this.wins = new HashMap<>();
}
public ArrayList<Player> getPlayers() {
return players;
}
public void addPlayer(String name){
this.players.add(new Player(name));
<小时/>
ApplicationConfig 类
@EnableWebMvc
@Configuration
@ComponentScan("com.kane.cardgame")
public class ApplicationConfig {
private Deck deck = new Deck();
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode =
ScopedProxyMode.TARGET_CLASS)
public Game game(){
return new Game(deck);
}
}
<小时/>
Controller
@CrossOrigin
@RestController(value="PlayerController")
@RequestMapping("/game/players")
public class PlayerController {
@Autowired
private Game game;
@RequestMapping(method=RequestMethod.GET, value="/")
public ArrayList<Player> allPlayers(){
return game.getPlayers();
}
@RequestMapping(method= RequestMethod.POST, value="/")
public ArrayList<Player> addPlayer(@RequestParam(value="name") String
name){
game.addPlayer(name);
return game.getPlayers();
}
<小时/>
发出请求的 React 组件
const handleLinkClick = e => {
const url = `http://localhost:8080/game/players/?
name=${this.state.name}`
fetch(url, {
method: 'POST',
mode: 'cors'
})
.then(res => res.json())
.then(res => {
const newState = this.state.newPlayers;
newState.push(res);
this.setState({newPlayers: newState})
})
}
return(
<div>
<h1>Enter your name</h1>
<input id="name-input" type="text" name="name" onChange= .
{handleNameChange}/>
<Link to="/newPlayer" onClick={handleLinkClick}>Start Game</Link>
</div>
)
<小时/>
当我在 Postman 中提出这些请求时,一切都很好。它按其应有的方式工作 - 触发后路由并添加一名新玩家,当我触发 Get 路由时,它会返回所有添加了新玩家的玩家。
当我使用 React 发出此请求时,它似乎创建了我的 Player 类的实例(因为 id 递增),但它似乎没有将玩家添加到 Game 中包含的 ArrayList 中。我可以让它以 JSON 形式返回刚刚创建的 Player 并将其存储在状态中。但是,当我获取与 Get 路由关联的 URL 以返回游戏玩家时,没有存储任何内容。我的预感是我没有正确存储此游戏状态。
我的猜测是,这可能可以归结为对这个 Bean 工作原理的根本误解。任何建议将不胜感激。
最佳答案
好的,就到这里,
这里有几处不对劲的地方。首先让我们从 Game
开始类(class)。其注释为 @Component
。这意味着 Spring 的自动类路径扫描会自动选择并配置。话虽如此,您可以在需要时随时进行注入(inject)。同时,这意味着您在 ApplicationConfig
中执行的手动安装类是不必要的。在那里您手动实例化 Game
并尝试使用@Bean
将其带入Spring上下文中注解。这是错误的,可能会导致意想不到的结果。要么保留 @Component
类或其他。
其次,Game
实际上是一个管理整个游戏的服务组件。考虑到这一点,我建议删除 @Component
并添加 @Service
注释以更好地表示它的实际用法(毕竟它是一项服务)。 @Autowired
它的构造函数上的注释也是不需要的,因为您没有在其中有效地注入(inject)任何 Spring 托管 bean。相反,如果您想执行 post bean 创建操作(即初始化 Deck
对象以及各种列表和映射),只需创建一个新的 void 方法并用 @PostConstruct
对其进行注释。 。同时,请确保将这些声明更改为 private ArrayList<Player> players;
至private List<Player> players;
因为对接口(interface)进行编码总是比实际实现更好。 getPlayers
的返回参数也是如此。 .
最后,所有这些都就位后,只需注入(inject) Game
类进入你的PlayerController
(还要确保使用基于首选构造函数的 DI 方法来执行此操作),您应该可以开始了。
最后,我建议您在继续之前仔细阅读 Spring 和一般 DI 的工作原理,否则您将不断遇到问题。
编辑:正如上面的答案中提到的,客户端也应该进行更改。
关于java - 在 Spring 的 Controller 中存储状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52105168/