Как заменить структуру обработки исключений - PullRequest
3 голосов
/ 22 июня 2019

Я пытаюсь реализовать Spring Security + JWT. Я сделал методы входа и выхода, настроен JWT фильтр, провайдер и веб-конфигурации. Таким образом, основная проблема заключается в том, что мой контроллер и как вернуть пользователю сообщения об ошибках, например, если пользователь ввел неправильный пароль / имя пользователя или учетная запись пользователя заблокирована и т. Д. Я получил структуру, построенную на обработке исключений, выглядит ужасно.

Контроллер

@PostMapping("/log-in")
    public ResponseEntity logIn(@RequestBody UserDto userDto) {
        log.info("[LOG-IN] user with username " + userDto.getUsername());
        try {
            HashMap<String, String> response = userService.logIn(userDto);
            return ResponseEntity.ok(response);

        } catch (UserStatusException ex) {
            return ResponseEntity.badRequest().body("Account is Pending");
        } catch (UsernameNotFoundException ex) {
            return ResponseEntity.badRequest().body("Could not find account!");
        } catch (AuthenticationException ex) {
            log.error("Wrong username or password!");
            return ResponseEntity.badRequest().body("Wrong username or password!");
        }
    }

сервис

@Override
    public HashMap<String, String> logIn(UserDto userDto)throws AuthenticationException, UserStatusException{
        User user = findByUsername(userDto.getUsername());

        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userDto.getUsername(), userDto.getPassword())); //login

        checkUserStatus(user);              //check if user pending or banned
        user.setUserStatus(UserStatus.ACTIVE);

        String token = jwtTokenProvider.createToken(user.getUsername(), user.getUserRoles());
        HashMap<String, String> response = new HashMap<>();
        response.put("token", token);
        response.put("username", user.getUsername());
        userRepository.save(user);
        return response;
    }
@Override
    public User findByUsername(String username)throws UsernameNotFoundException {
        log.info("[UserService, findByUsername]");
        User user = userRepository.findByUsername(username);
        if(user == null){
            log.error("User not found with {} username: ", username);
            throw new UsernameNotFoundException("User not found!");
        }
        log.info("User {} successfully loaded ",username);
        return user;
    }
@Override
    public void checkUserStatus(User user)throws UserStatusException {
        if (user.getUserStatus().equals(UserStatus.BANNED)
           || user.getUserStatus().equals(UserStatus.PENDING)) {
            throw new UserStatusException("Not confirmed");
        }
    }

Есть ли другой способ заменить эту структуру?

Ответы [ 2 ]

4 голосов
/ 22 июня 2019

Вы должны использовать ControllerAdvice (см. Учебник здесь ).

Это особый класс, который выглядит так

@ControllerAdvice
public class ControllerAdvice {

   @ExceptionHandler(PersonNotFoundException.class) 
   public ResponseEntity <VndErrors > notFoundException(final PersonNotFoundException e) {

    return error(e, HttpStatus.NOT_FOUND, e.getId().toString());

   }

}

Это позволит вам привязать определенный код возврата и ответ к каждому исключению, которое вам нужно обработать, и автоматически перехватит все исключения, возвращаемые вашим контроллером. Это также хороший способ обработки всех исключений в одном месте, а не над каждым исключением ...

Я не уверен в этом, но я думаю, что вы даже можете привязать его к определенному отображению вашего API для большей детализации.

Надеюсь, это поможет! Веселитесь!

2 голосов
/ 22 июня 2019

Вы можете добавить статус repose непосредственно в свой класс исключений:

@ResponseStatus(HttpStatus.BAD_REQUEST)
public class UsernameNotFoundException extends RuntimeException {
    public UsernameNotFoundException(String message) {
        super(message);
    }

    public UsernameNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}

Таким образом, вам больше не нужно перехватывать их в контроллере и добавлять сообщение и статус в ResponseEntity.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...