Reputation: 37
I have one controller as:
@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";
}
}
And there are multiple controllers (e.g., assetController, liabilityController, etc):
@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";
}
}
I don't want to merge all my controllers code in one single controller. I just need to save userId whenever user signs up or login in the website, and then use it across many other controllers. Any clean solution will be appreciated.
Upvotes: 0
Views: 992
Reputation: 1821
Assuming you want share the user id across multiple controllers for a session.
In this case you can use session scoped bean to store userId
. New instance of session scoped bean will be created for each session and it will remain active for that session. Session scoped bean will be automatically destroyed once session is invalidated. Please refer below example for how to create session scoped bean and its usage:
Session scoped bean:
@Getter
@Setter
@NoArgsConstructor
@Component
@SessionScope //scope of this bean is session
public class UserDetails {
private String userId;
}
Inject session scoped bean to your controllers:
UserController
@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";
}
}
AssetController
@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";
}
}
Please refer spring docs for more information on session scoped beans.
Note: Please make sure you are not accessing session scoped bean outside the active session.
Upvotes: 1
Reputation: 16775
The default scope for beans in Spring is singleton. Since I don't see anything in your code which changes that, I would assume that your controllers are singleton.
You don't want to create instance variables, which depend on sessions, in singleton classes. It is a bad idea to have this protected int userId
instance variable. For example, if you have two users browsing your application in the same time, one user might retrieve information using the other user's userid
.
Usually the recommended way to get user information is to use the SecurityContext
(example of usage from another question. We can retrieve the SecurityContext
from the SecurityContextHolder
.
Other solution would be to inject an Authentication
or a Principal
at the endpoints, such as:
@Controller
public class MyController {
@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserName(Principal principal) {
return principal.getName();
}
}
Both of these solutions assume that we have correctly implemented authentication with Spring Security.
Upvotes: 1
Reputation: 1
You can use sessions, sessions will store value for custom values from an user for a custom period of time the duration could be the time as the application is up.
to store you can set a controler like that:
@RequestMapping(method = RequestMethod.GET)
public String testMestod(HttpServletRequest request){
User user= (User)request.getSession().setAttribute("userId",value);
return "test";
}
and to get the value you can use this method:
User user= (user)session.getAttribute("userId");
more info on this link https://www.techgeeknext.com/spring-boot/spring-boot-session-management
Upvotes: 0
Reputation: 510
Instead of saving it as a local variable of UserController, save it in another Bean for example in UserService, and all controllers will do @Autowired to it and will get the user id info.
Upvotes: 0