我正在使用java spring创建一个电子日记应用程序,但是我遇到了一个小问题。我决定创建一个带有状态模式的角色系统。所以这个系统的逻辑应该看起来像这样:
1.在控制器中,接受请求后,创建context类的对象,context类的构造器根据用户角色得到具体的RoleClass(使用工厂)
1.在控制器中,我们调用要执行的上下文的方法
1.在上下文中,我们调用希望执行的角色的方法。
1.在角色类中,我们调用要执行的服务的方法。
但是这里我遇到了一个问题。我有一个上下文类,它创建了一个UserService类的对象,其中包含了很多**@Autowired字段。所以我决定给上下文类添加@Service
注解,并在UserContext类的构造函数上添加了@Autowired
注解。
但是Spring会在编译阶段自动连接所有字段,所以当我启动程序时,SecurityContextHolder
中不会有任何UserPrincipal**。所以这里我需要在请求阶段,在控制器中创建一个UserContext类的对象。这就是为什么我在UserContext类中添加了@Configurable
注解。但是当UserContext类创建时,UserService的自动连接字段由空值填充。
那么,什么会成为问题呢?
顺便说一句,我认为最好创建一个UserService类的构造函数,它将接受所有的参数(如UserRepository),但这里有另一个问题:
1.我在其他类中经常使用UserService类。例如,我有一个模型,在那里我调用了这个类。在这里,在创建了类的这个对象后,字段将自动连接。
@Getter @Setter
public class ClassGetModel {
private long id;
private int number;
private char letter;
private SchoolGetModel school;
private List<UserGetModel> students;
public static ClassGetModel toModel(ClassEntity schoolClass) {
ClassGetModel model = new ClassGetModel();
ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setSkipNullEnabled(true);
mapper.map(schoolClass, model);
model.setSchool(SchoolGetModel.toModel(schoolClass.getSchool()));
UserService userService = new UserService();
model.setStudents(userService.convertToUserGetModelList(schoolClass.getStudents()));
return model;
}
}
还有一个问题是构造函数的参数数量。如果我的服务有很多字段,而这些字段在我的程序中使用,我就必须把它们都给这个构造函数,即使在RoleFactory中。
下面是我的代码:用户控制器
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private UserContext userContext;
@GetMapping("/marks")
public ResponseEntity<Object> getMarks() {
try {
return ResponseEntity.ok(userContext.getMarks());
} catch (Exception e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}
用户上下文
@Service @Configurable @Scope("prototype")
public class UserContext {
@Autowired
public UserContext(UserService userService) {
this.userService = userService;
}
public List<HomeworkGetModel> getHomework() throws UserNotFoundException {
UserRole userRole = RoleFactory.getUserRole(userService.getCurrentUser().getRole().getName());
return userRole.getHomework();
}
public List<MarkGetModel> getMarks() throws UserNotFoundException {
UserRole userRole = RoleFactory.getUserRole(userService.getCurrentUser().getRole().getName());
return userRole.getMarks();
}
}
用户角色
public interface UserRole {
default UserGetModel getUser(long id) throws UserNotFoundException {
throw new NotImplementedException();
}
default List<UserGetModel> getAllUsers() {
throw new NotImplementedException();
}
default UserEntity updateUser(UserUpdateModel newUserData) throws UserNotFoundException {
throw new NotImplementedException();
}
default UserEntity deleteUser() throws UserNotFoundException {
throw new NotImplementedException();
}
default List<MarkGetModel> getMarks() throws UserNotFoundException {
throw new NotImplementedException();
}
default List<MarkGetModel> getMarksByDate(String date) throws UserNotFoundException, ParseException {
throw new NotImplementedException();
}
default List<MarkGetModel> getMarksBySubject(String subjectName) throws UserNotFoundException {
throw new NotImplementedException();
}
default List<MarkGetModel> getMarksByDateAndSubject(DateAndSubjectModel dateAndSubject) throws UserNotFoundException, ParseException {
throw new NotImplementedException();
}
default SubjectGetModel getSubject(long id) throws SubjectNotFoundException {
throw new NotImplementedException();
}
default SubjectGetModel getSubject(String name) throws SubjectNotFoundException {
throw new NotImplementedException();
}
default SchoolGetModel getSchoolById(long schoolId) throws SchoolNotFoundException {
throw new NotImplementedException();
}
default SchoolGetModel getSchoolByNumber(int schoolNumber) throws SchoolNotFoundException {
throw new NotImplementedException();
}
default List<SchoolGetModel> getSchools() {
throw new NotImplementedException();
}
default ClassGetModel getSchoolClass(ClassGetByNumberModel classData) throws com.diary.diary.exception.school_class.ClassNotFoundException, SchoolNotFoundException {
throw new NotImplementedException();
}
default List<ClassGetModel> getClasses() {
throw new NotImplementedException();
}
default List<HomeworkGetModel> getHomework() throws UserNotFoundException {
throw new NotImplementedException();
}
default List<HomeworkGetModel> getHomeworkByDate(String date) throws UserNotFoundException, ParseException {
throw new NotImplementedException();
}
default List<HomeworkGetModel> getHomeworkBySubject(String subjectName) {
throw new NotImplementedException();
}
default ClassEntity addClass(ClassAddModel classData) {
throw new NotImplementedException();
}
default ClassEntity addUserToClass(AdminAddUserToClassModel userAndClassModel) {
throw new NotImplementedException();
}
default ClassEntity deleteClass(long id) {
throw new NotImplementedException();
}
default UserEntity removeUserFromClass(AdminRemoveUserFromClassModel userClassModel) {
throw new NotImplementedException();
}
default SchoolEntity addSchool(SchoolAddModel schoolData) {
throw new NotImplementedException();
}
default SchoolEntity deleteSchool(long id) {
throw new NotImplementedException();
}
default UserEntity removeUserFromSchool(AdminRemoveUserFromSchoolModel userSchoolModel) {
throw new NotImplementedException();
}
default SubjectEntity addSubject(SubjectAddModel subjectData) {
throw new NotImplementedException();
}
default SubjectEntity updateSubject(SubjectUpdateModel newSubjectModel) {
throw new NotImplementedException();
}
default SubjectEntity deleteSubject(SubjectDeleteModel subjectDeleteData) {
throw new NotImplementedException();
}
default TimetableEntity addTimetable(TimetableAddModel timetableData) {
throw new NotImplementedException();
}
default TimetableEntity updateTimetable(TimeTableUpdateModel newTimetableData) {
throw new NotImplementedException();
}
default TimetableEntity deleteTimetable(long id) {
throw new NotImplementedException();
}
default ClassEntity addTimetableToClass(TimetableClassModel timetableClass) {
throw new NotImplementedException();
}
default ClassEntity deleteTimetableFromClass(long classId) {
throw new NotImplementedException();
}
}
用户服务
@Service @Configurable @Scope("prototype")
public class UserService implements UserDetailsService {
@Autowired
private UserRepository userRepo;
@Autowired
private RoleRepository roleRepo;
@Autowired
private MarkMethods markMethods;
private final BCryptPasswordEncoder bCryptPasswordEncoder
= new BCryptPasswordEncoder();
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserEntity user = userRepo.findByLogin(username);
if(user == null) {
throw new UsernameNotFoundException("user with such login not found");
}
SimpleGrantedAuthority userRole = new SimpleGrantedAuthority(user.getRole().toString());
return new User(Long.toString(user.getId()), user.getPassword(), List.of(userRole));
}
public UserGetModel getUser(long userID) throws UserNotFoundException {
UserEntity user = userRepo.findById(userID)
.orElseThrow(() -> new UserNotFoundException("no user with such id"));
return convertUserToGetModel(user);
}
public UserEntity getCurrentUser() throws UserNotFoundException {
Authentication authentication = SecurityContextHolder
.getContext().getAuthentication();
if(authentication == null) {
return null;
}
Long userId = Long.valueOf((String) authentication.getPrincipal());
return userRepo.findById(userId)
.orElseThrow(() -> new UserNotFoundException("current user wasn't found"));
}
public List<MarkGetModel> getMarks() throws UserNotFoundException {
checkUserRoleOrThrow(RoleNames.ADMIN, getCurrentUser());
UserEntity student = getCurrentUser();
return convertToMarkGetModelList(student.getMarks());
}
如果你知道如何解决这个问题,请告诉我,我将不胜感激!
1条答案
按热度按时间zlhcx6iw1#
您可以做的是用@Scope注解UserService类,并将作用域设置为请求作用域(请参见此处https://www.baeldung.com/spring-bean-scopes)。
现在,无论何时请求bean,都将获得一个完整的新示例(此时安全上下文已设置)。
因此TLDR:
1.通常将UserService作为bean注入控制器。
1.如上所述,使用@Scope注解UserService