我在Spring Boot RestController中挣扎。
UserService
@Service
public class UserService implements IUserService {
@Autowired
public PasswordEncoder passwordEncoder;
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public UserLoginResponse register(RegisterUserRequest request) throws NoValidRegisterDataException, Exception {
UserLoginResponse response = new UserLoginResponse();
UserEntity user = request.getUser();
if(!this.checkUserDataValidity(user)) {
throw new NoValidRegisterDataException();
}
user.setPassword(this.encodePassword(user.getPassword()));
try {
user = this.userRepository.save(user);
} catch (Exception e) {
throw new Exception("Database save error");
}
response.addMessage(new ResponseMessage(ResponseMessageType.success, "Uživatel úspěšně registrován"));
response.setUser(user);
//TODO token handler
return response;
}
private boolean checkUserDataValidity(UserEntity user) {
return (user.getEmail() != null && user.getPassword() != null && user.getUsername() != null);
}
private String encodePassword(String password) {
return this.passwordEncoder.encode(password);
}
}
到目前为止,我有一个服务的注册(主要方法)。由UserController调用(下面的代码)
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping(method = POST, value = "/user/register")
@CrossOrigin
public UserLoginResponse register(RegisterUserRequest request,
HttpServletResponse servletResponse) {
UserLoginResponse response = new UserLoginResponse();
try {
response = this.userService.register(request);
} catch (NoValidRegisterDataException e) {
response.addMessage(new ResponseMessage(ResponseMessageType.danger, e.getMessage()));
servletResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
} catch (Exception e) {
response.addMessage(new ResponseMessage(ResponseMessageType.danger, e.getMessage()));
servletResponse.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
}
return response;
}
}
我返回UserLoginResponse对象。我在请求中得到了RegisterUserRequest对象(基本上是带有用户数据的对象)
public class UserLoginResponse extends Response {
private UserEntity user;
private String userToken;
public UserLoginResponse() {}
public UserLoginResponse(ArrayList<ResponseMessage> messages, UserEntity user, String userToken) {
super(messages);
this.user = user;
this.userToken = userToken;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public String getUserToken() {
return userToken;
}
public void setUserToken(String userToken) {
this.userToken = userToken;
}
}
然后扩展Response对象,该对象内部具有一个属性。我要发送到前端的邮件列表
public class Response {
private ArrayList<ResponseMessage> messages;
public Response() {}
public Response(ArrayList<ResponseMessage> messages) {
this.messages = messages;
}
public void addMessage(ResponseMessage message) {
if(this.messages == null) {
this.messages = new ArrayList<>();
}
this.messages.add(message);
}
}
第一个问题是,当发生错误(错误的用户数据,其他错误)时,我得到了空的UserLoginResponse对象。多数情况下还可以,但是我没有消息。 (错误消息是在UserController的catch块中设置的,因此它们应该在那里。)
第二个问题是,即使我在UserController的第一个catch块中(在一般Exception之上)抛出NoValidRegisterDataException,异常也是由最后一个catch块处理的。我怎样才能解决这个问题?我以为异常是由它适合的第一个catch块(从上到下)处理的。
编辑:我已经解决了第二个问题。我没有注意到在抛出异常的情况下抛出了nullpointerexception。因此,它现在变得有意义。我添加了空检查,异常现在可以正常工作。但是我仍然不知道如何返回整个响应,包括来自父响应对象的消息。
答案 0 :(得分:0)
我认为您的代码有几个问题:
1)请避免在Spring服务和控制器中使用检查的异常。它们只会增加噪音,尤其是使用各种try-catch子句时。理想情况下,如果要抛出异常,只需抛出一个运行时异常,并准备好一个异常处理程序以捕获它并创建您适当的响应。您可以在这里查看这些内容:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html
2)避免使用catch子句来捕获Exception
。在大多数情况下,如果发生一些不必要的异常,这将使您的流程混乱。只是让它冒泡到Spring的默认异常处理程序即可。
3)避免继承,而只支持组合。我认为扩展POJO并不是一件好事。
4)避免混合使用字段注入和构造函数注入。在大多数情况下,这是灾难的根源。
5)在每次手动设置servletResponse时,我看不到任何意义。只需将响应对象包装到ResponseEntity
中,该对象也可以有效地携带状态码。