You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SOAP连接Java类实例问题:多客户端猜字游戏需实例隔离

How to Create Independent Game Instances for Each Hangman Client

Got it, let's break down how to solve this problem. The root cause here is that your current SOAP server is likely using a single shared instance of your game class (GalgeI) for all connected clients. That's why everyone ends up guessing the same word—they're all interacting with the same object. Here's how to fix this by giving each client their own isolated game session:

1. Make Your Game Class Stateful

First, refactor GalgeI to hold per-client game state. Each instance should have its own target word, guessed letters, wrong guess count, etc. This way, every client gets a fresh, independent game when they connect.

public class GalgeI implements GalgeService {
    // Instance-specific game state
    private String targetWord;
    private List<Character> guessedLetters;
    private int wrongGuessCount;

    // Constructor initializes a new game for each instance
    public GalgeI() {
        this.targetWord = pickRandomWord();
        this.guessedLetters = new ArrayList<>();
        this.wrongGuessCount = 0;
    }

    // SOAP-exposed method for guessing a letter
    public GuessResult guessLetter(char letter) {
        boolean isCorrect = targetWord.indexOf(letter) != -1;
        if (!guessedLetters.contains(letter)) {
            guessedLetters.add(letter);
            if (!isCorrect) wrongGuessCount++;
        }
        return new GuessResult(isCorrect, wrongGuessCount, getCurrentWordState());
    }

    // Helper to return the masked word (e.g., "a__le" for "apple")
    private String getCurrentWordState() {
        StringBuilder sb = new StringBuilder();
        for (char c : targetWord.toCharArray()) {
            sb.append(guessedLetters.contains(c) ? c : '_');
        }
        return sb.toString();
    }

    // Helper to pick a random target word
    private String pickRandomWord() {
        String[] wordList = {"hangman", "distributed", "soap", "java", "university"};
        return wordList[new Random().nextInt(wordList.length)];
    }

    // Add other SOAP methods (e.g., getGameStatus, restartGame) here
}

2. Configure Your SOAP Server to Use Per-Session Instances

Most default SOAP server setups (like JAX-WS Endpoint) use a singleton instance. We need to override this behavior to create a new GalgeI instance for each client session.

Option 1: Custom Instance Provider (Standalone JAX-WS)

If you're using the basic JAX-WS Endpoint to publish your service, create an InstanceProvider to track instances by client session ID:

public class PerSessionGameProvider implements InstanceProvider {
    // Thread-safe map to link session IDs to game instances
    private final Map<String, GalgeI> sessionGames = new ConcurrentHashMap<>();

    @Override
    public Object getInstance(MessageContext messageContext) {
        // Get the HTTP session tied to the client's request
        HttpSession session = (HttpSession) messageContext.get(MessageContext.SESSION);
        String sessionId = session.getId();

        // Create a new game instance if the session doesn't have one yet
        return sessionGames.computeIfAbsent(sessionId, id -> new GalgeI());
    }

    @Override
    public void releaseInstance(MessageContext messageContext, Object instance) {
        // Clean up old instances when sessions expire (prevents memory leaks)
        HttpSession session = (HttpSession) messageContext.get(MessageContext.SESSION);
        sessionGames.remove(session.getId());
    }
}

Update your server main method to use this provider:

public class Galgeserver {
    public static void main(String[] arg) throws Exception {
        Endpoint endpoint = Endpoint.create(new GalgeI());
        endpoint.setInstanceProvider(new PerSessionGameProvider());
        endpoint.publish("http://localhost:8080/HangmanService");
        System.out.println("Hangman server running on http://localhost:8080/HangmanService");
    }
}

Option 2: Java EE Stateful Beans (Container Deployment)

If you're deploying to a Java EE server (like WildFly or GlassFish), use @Stateful to mark your game class as session-scoped. The container will automatically create a new instance per client session:

import javax.ejb.Stateful;
import javax.jws.WebService;

@WebService(serviceName = "HangmanService")
@Stateful
public class GalgeI implements GalgeService {
    // Same stateful game logic as above...
}

3. Ensure Clients Maintain Session

For this setup to work, your SOAP clients need to persist their session with the server. Most SOAP client libraries (like JAX-WS Service) support session tracking—enable cookie handling in your client code so the server can map requests to the correct game instance.

Key Takeaways

  • Stateful Design: Your game class must store unique state per instance (target word, guesses, etc.).
  • Session Mapping: The server needs to tie each client to their own instance using session IDs.
  • Cleanup: Remove expired session instances to avoid unnecessary memory usage.

内容的提问来源于stack exchange,提问作者Krede

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:14:19