如何在 Web 服务请求之间保留数据?

How to keep a data between requests at web service?

假设我开发了一个订票网络服务。订票有一些步骤,需要在步骤之间保留一些用户数据。

假设我使用Spring(Boot)技术栈和MVC

怎样实施比较好?

  1. 使用无状态 REST 并使用 cookie 来回移动日期?
  2. 将其存储在会话上下文中?
  3. 使用有状态 bean(它们在 Spring 中是什么样子?原型?)
  4. 使用一些有状态的协议,比如 SOAP(它是有状态的吗?)

视情况而定。

1 如果您想使用 Web 服务的多个实例(用于平衡负载等),那么您的选择是无状态 REST 和基于令牌的身份验证

2 如果您不需要此功能,您可以将会话信息存储在 MVC 模型中(无论如何它都会将其放入会话中)

@RestController
@SessionAttributes("armUserSession")
public class SessionController {

    @Autowired
    private LoginService loginService;

    @ModelAttribute("armUserSession")
    public ArmUserSession getArmUserSession() {
        return new ArmUserSession();
    }

    @CrossOrigin
    @RequestMapping({"/login"})
    public ArmUserSession login(@ModelAttribute("armUserSession") ArmUserSession userSession,
                                Model model,
                                @RequestParam(required = false) String login,
                                @RequestParam(required = false) String password) {
        if (!userSession.isLoggedIn()) {
            userSession = loginService.login(login, password);
            model.addAttribute("armUserSession", userSession);
        }

        return userSession;
}

    @CrossOrigin
    @RequestMapping({"/logout"})
    public ArmUserSession logout(SessionStatus status) {
        status.setComplete();
        return new ArmUserSession();
    }


}

3 您也可以使用会话作用域的 bean,但它有点复杂。 默认情况下 Spring bean 是单例的。当您想在单例中使用会话范围的 bean(它们不是单例)时,您需要一个代理。

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private ArmUserSessionProxy armUserSessionProxy;

    @Override
    public ArmUserSession login(String login, String password) {
        ArmUserSession armUserSession = armUserSessionProxy.getArmUserSession();

...................................
}

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ArmUserSessionProxy {

    private ArmUserSession armUserSession = new ArmUserSession();

    public ArmUserSession getArmUserSession() {
        return armUserSession;
    }

}