我如何使用一个控制器中定义的变量跨多个不同的控制器使用?

How do i use variable defined in one controller be used across multiple different controller?

我有一个控制器:

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    protected int userId; // I need to use it across many other controllers. HOW?

    @GetMapping("/")
    private String viewHomePage(Model model) {
        
        return "eAccounts";
    }

    @GetMapping("/dashboard")
    private String getDashboardPage() {
        return "dashboard";
    }

    @GetMapping("/signup")
    private String getSignupPage(Model model) {
        User user = new User();
        model.addAttribute("user", user);
        return "signup";
    }

    @PostMapping("/verifySignup")
    private String verifySignup(@ModelAttribute("user") User user, Model model, HttpServletRequest request) {
    if (userService.verifySignup(user) == 1) {
        userId = user.getId();// save user id for later use
        return "redirect:/dashboard";
    }

    return "signup";
    }
}

并且有多个控制器(例如,assetController、liabilityController 等):

@Controller
public class AssetController {
    @Autowired
    private AssetService assetService;

    @GetMapping("/assets")
    public String getAssetsPage(Model model) {
        model.addAttribute("listAssets", assetService.getAllAssets(userId)); // here i need to use userId, and at many more places
        return "assets";
    }
}

我不想将所有控制器代码合并到一个控制器中。 我只需要在用户注册或登录网站时保存 userId,然后在许多其他控制器上使用它。任何干净的解决方案将不胜感激。

与其将其保存为 UserController 的局部变量,不如将其保存在另一个 Bean 中,例如在 UserService 中,所有控制器将对其执行@Autowired 并获取用户 ID 信息。

您可以使用会话, session 将在自定义时间段内存储来自用户的自定义值的值,持续时间可以是应用程序启动的时间。

要存储,您可以像这样设置控制器:

@RequestMapping(method = RequestMethod.GET)
public String testMestod(HttpServletRequest request){
   User user= (User)request.getSession().setAttribute("userId",value);
   return "test";
}

要获取值,您可以使用此方法:

User user= (user)session.getAttribute("userId");

更多信息link https://www.techgeeknext.com/spring-boot/spring-boot-session-management

Spring 中 bean 的默认作用域是 singleton。因为我在你的代码中没有看到任何改变它的东西,所以我假设你的控制器是单例的。

您不想在单例中创建依赖于会话的实例变量 类。使用这个 protected int userId 实例变量是个坏主意。例如,如果您有两个用户同时浏览您的应用程序,一个用户可能会使用另一个用户的 userid.

检索信息

通常推荐的获取用户信息的方法是使用SecurityContext(来自另一个的用法示例。我们可以从SecurityContextHolder检索SecurityContext .

其他解决方案是在端点注入 AuthenticationPrincipal,例如:

@Controller
public class MyController {

    @RequestMapping(value = "/username", method = RequestMethod.GET)
    @ResponseBody
    public String currentUserName(Principal principal) {
        return principal.getName();
    }
}

这两种解决方案都假定我们已经使用 Spring 安全性正确实施了身份验证。

假设您希望在会话的多个控制器之间共享用户 ID。

在这种情况下,您可以使用会话范围的 bean 来存储 userId。将为每个会话创建会话作用域 bean 的新实例,并且它将在该会话中保持活动状态。一旦会话失效,会话范围的 bean 将自动销毁。请参考下面的示例,了解如何创建会话范围的 bean 及其用法:

会话作用域 bean:

@Getter
@Setter
@NoArgsConstructor
@Component
@SessionScope //scope of this bean is session
public class UserDetails {
    private String userId;
}

将会话作用域的 bean 注入您的控制器:

用户控制器

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private UserDetails userDetails; //adding session scoped bean

    @GetMapping("/")
    private String viewHomePage(Model model) {

        return "eAccounts";
    }

    @GetMapping("/dashboard")
    private String getDashboardPage() {
        return "dashboard";
    }

    @GetMapping("/signup")
    private String getSignupPage(Model model) {
        User user = new User();
        model.addAttribute("user", user);
        return "signup";
    }

    @PostMapping("/verifySignup")
    private String verifySignup(@ModelAttribute("user") User user, Model model, HttpServletRequest request) {
        if (userService.verifySignup(user) == 1) {
            userDetails.setUserId(user.getId());// save user id in session scoped bean
            return "redirect:/dashboard";
        }

        return "signup";
    }
}

资产控制器

@Controller
public class AssetController {
    @Autowired
    private AssetService assetService;

    @Autowired
    private UserDetails userDetails;

    @GetMapping("/assets")
    public String getAssetsPage(Model model) {
        model.addAttribute("listAssets", assetService.getAllAssets(userDetails.getUserId())); //get user id from session scoped bean

        return "assets";
    }
}

有关 session scoped beans 的更多信息,请参阅 spring 文档。

注意:请确保您没有在活动会话之外访问会话范围的 bean。