본문 바로가기
spring

spring @ExceptionHandler를 활용한 예외처리

by 토망이 2023. 6. 25.

본 글에서는 @ExceptionHandler를 활용해, mybatis를 통해 select 쿼리가 적용되어 있는 Controller 대상으로 예외처리를 구현해보겠습니다. mybatis 코드는 이전 글을 참고해주세요

spring mybatis로 RDB select 해보기

 

spring mybatis로 RDB select 해보기

본 글에서는 RDBMS를 사용할때 종종 사용하는 mybatis를 활용하여 SQL 쿼리를 사용, CRUD 중에서 기본적인 Select 쿼리를 호출하는 api를 만들어보도록 하겠습니다. 실무에서는 Oracle DB를 주로 사용하였

dnl1029.tistory.com

 

spring jwt 토큰 발급하는 restapi 만들기

 

spring jwt 토큰 발급하는 restapi 만들기

본 글에서는 spring security에서 인증/인가를 위해 활용하는 jwt 토큰의 발급하는 restapi를 만들어보도록 하겠습니다. restapi를 통해 id와 password를 보내면, DB에 저장된 id, password 를 확인하여 값이 일치

dnl1029.tistory.com

 

- MemberService

@Service
@Slf4j
@RequiredArgsConstructor
public class MemberService {

    private final MemberMapper memberMapper;

    public MemberDto getMemberByDto(MemberDto memberDto){
        LinkedHashMap<String,Object> paramMap = new LinkedHashMap<>();

        log.info("id : {}",memberDto.getUserId());
        log.info("password : {}",memberDto.getPassword());

        paramMap.put("USER_ID",memberDto.getUserId());
        paramMap.put("PASSWORD",memberDto.getPassword());

        MemberDto result = memberMapper.findMemberByMap(paramMap);
        return result;
    }

}

위와 같은 코드에서, memberMapper.findMemberByMap을 통해 불러온 값이 없을때, 즉 id, password인증으로 인해 가져온 값이 없을때, 예외를 던지는 코드를 추가해보겠습니다.

@Service
@Slf4j
@RequiredArgsConstructor
public class MemberService {

    private final MemberMapper memberMapper;

    public MemberDto getMemberByDto(MemberDto memberDto){
        LinkedHashMap<String,Object> paramMap = new LinkedHashMap<>();

        log.info("id : {}",memberDto.getUserId());
        log.info("password : {}",memberDto.getPassword());

        paramMap.put("USER_ID",memberDto.getUserId());
        paramMap.put("PASSWORD",memberDto.getPassword());

        MemberDto result = memberMapper.findMemberByMap(paramMap);
        if(result == null) {
            throw new RuntimeException();
        }
        return result;
    }

}

 

- JwtIssueService

 

 

public String createJwt(MemberDto memberDto) {
        Date now = new Date();
        MemberDto result = memberService.getMemberByDto(memberDto);

        if(result == null) {
            log.info("login failed. id:{},password:{}",memberDto.getUserId(),memberDto.getPassword());
            return null;
        }
        else {
            return Jwts.builder()
                    .setHeaderParam(Header.TYPE,Header.JWT_TYPE)
                    .setClaims(createClaims(result))
                    .setIssuedAt(now)
                    .setExpiration(new Date(System.currentTimeMillis()+1*(1000*60*60*24*365))) //발급날짜계산
                    .signWith(SignatureAlgorithm.HS256, createSignature())
                    .compact();
        }
    }

 

return null 부분을, 아래와 같이 RuntimeException을 던지도록 변경해보겠습니다.

public String createJwt(MemberDto memberDto) {
        Date now = new Date();
        MemberDto result = memberService.getMemberByDto(memberDto);

        if(result == null) {
            log.info("login failed. id:{},password:{}",memberDto.getUserId(),memberDto.getPassword());
            throw new RuntimeException();
        }
        else {
            return Jwts.builder()
                    .setHeaderParam(Header.TYPE,Header.JWT_TYPE)
                    .setClaims(createClaims(result))
                    .setIssuedAt(now)
                    .setExpiration(new Date(System.currentTimeMillis()+1*(1000*60*60*24*365))) //발급날짜계산
                    .signWith(SignatureAlgorithm.HS256, createSignature())
                    .compact();
        }
    }

 

우선 바로 swagger에서 MemberController를 실행시켜서, 임의의 id password를 입력해보겠습니다.

- 결과

 

- Controller

: Controller에 @ExceptionHandler를 추가하여, MemberController내의 모든 api에 대해 RuntimeException이 발생하면, runtimeHanldler라는 메서드를 탈 수 있게끔 추가했습니다.

@RequestMapping("api/v1")
@RestController
@RequiredArgsConstructor
@Slf4j
public class MemberController {

    private final MemberService memberService;
    private final JwtIssueService jwtIssueService;

    @GetMapping("mybatis/test")
    public MemberDto getMemberByIdPassword(@ModelAttribute MemberDto memberDto) {
        MemberDto result = memberService.getMemberByDto(memberDto);
        log.info("member : {}",result);
        return result;
    }

    @GetMapping("jwt/issue")
    public String getJwtToken(@ModelAttribute MemberDto memberDto) {
        String jwt = jwtIssueService.createJwt(memberDto);
        log.info("jwt token : {}",jwt);
        return jwt;
    }

    // MemberController 내 범위에서 RuntimeException 발생하면, runtimeHandler가 처리한다.
    @ExceptionHandler(value = RuntimeException.class)
    public Object runtimeHandler(Exception e) {
        log.info(e.getMessage());
        return "id/password 인증에 실패했습니다.";
    }

}

- 결과

위와 같이 예외처리를 했을때, String return값 설정말고, 더 다양한 처리도 가능할것같습니다.

댓글