개발자 끄적끄적
RestAPI와 예외상황 처리 본문
<@RestController = @Controller + @RespnoseBody>
- Spring에서 컨트롤러를 지정해주기 위한 어노테이션은 @Controller와 @RestController가 있다
- @Controller : 전통적은 Spring MVC 컨트롤러
- 'View'를 반환하기 위해 사용
- @RestController d: HTTP ResponseBody가 생성
- Spring MVC의 컨트롤러를 사용하면서 'Data를 반환해야 하는 경우'가 생기는데 컨트롤러에서는 데이터를 반환하기위해 @ResponseBody 어노테이션을 활용한다
이를 통해서 Controller로 JSON 형태로 데이터를 변환 할 수 있다
즉, JSON의 형태로 객체 데이터를 반환하는 것이다
<@RequestMapping>
- 클라이언트의 요청(url)에 맞는 클래스나 메서드를 연결시켜주는 어노테이션이다. 이 어노테이션은 그 위치에 따라 의미가 다르다
- 클래스 레벨 : 공통 주소
- 메서드 레벨 : 공통 주소 외 나머지 하위 주소
- 단, 클래스 레벨에 @RequestMapping이 없다면,메서드 레벨은 단독 요청 처리 주소이다
- @RequestMapping 작성 방법
- @RequestMapping("url") : 요청방식(GET/POST)에 관계없이 url이 일치하는 요청을 처리한다
- @RequestMapping(value="url", method=RequestMethod.Get | POST) : 지정된 요청 방식에 따라 처리한다
- 요청 방식에 관계없이 요청을 처리할 경우 메서드 레벨에서 GET/POST 방식을 분후여 Mapping해야 한다 -> @GetMapping('url') / @PostMapping('url')
OfferRestController.java 코드-------------------------------------------------------------------------------------------------------------------------
package kr.ac.hansung.cse.controller;
import kr.ac.hansung.cse.exceptioin.OfferNotFoundException;
import kr.ac.hansung.cse.model.Offer;
import kr.ac.hansung.cse.service.OfferService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.util.List;
@RestController //@Controller + @ResponseBody
@RequestMapping("/api/offers")
public class OfferRestController {
@Autowired
private OfferService offerService;
//CRUD
@GetMapping("/{id}") //return 값은 Offer, 하나의 Offer를 줘야한다
public ResponseEntity<Offer> getOffer(@PathVariable int id){
//조회
Offer offer = offerService.getOfferById(id);
if(offer==null) { //만약 offer에 id가 없다면
throw new OfferNotFoundException(id); //예외상황 -> Custom Exception
}
return new ResponseEntity<>(offer, HttpStatus.OK); //offer는 body에들어가고 HttpStatus.OK는 status에 들어간다
}
@GetMapping //모든 Offer를 return, 함수 이름은 'getOffers'
public ResponseEntity<List<Offer>> getOffers(){
List<Offer> offers = offerService.getAllOffers();
if(offers.isEmpty()) { //만약 offer에 id가 없다면
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(offers, HttpStatus.OK); //offer는 body에들어가고 HttpStatus.OK는 status에 들어간다
}
//insert를 생성하기 위해서는 @POSTMapping
@PostMapping //id는 필요없다(생성하는 것이므로)
public ResponseEntity<Void> createOffer(@RequestBody Offer offer){
offerService.insertOffer(offer);
HttpHeaders headers = new HttpHeaders();
//url 생성
UriComponents uriComponents = UriComponentsBuilder
.fromPath("api/offers/{id}")
.buildAndExpand(offer.getId())
.encode();
URI loactionUri = uriComponents.toUri();
headers.setLocation(loactionUri);
return new ResponseEntity<>(headers, HttpStatus.CREATED);
}
//update는 @PutMapping, update할 때도 id가 필요
@PutMapping("/{id}")
public ResponseEntity<Offer> updateOffer(@PathVariable int id, @RequestBody Offer offer) {
//조회를 한 다음에 수정을 한 다음 update
Offer currentOffer = offerService.getOfferById(id);
if (currentOffer == null)
throw new OfferNotFoundException(id);
currentOffer.setName(offer.getName());
currentOffer.setEmail(offer.getEmail());
currentOffer.setText(offer.getText());
//데이터를 업데이트
offerService.updateOffer(currentOffer);
//ResonpseEntity에 넣어준다
return new ResponseEntity<>(currentOffer, HttpStatus.OK);
}
//delete는 @DeleteMapping, delete 할 때는 id가 필요, id값을 받기 위해서 @PathVariable
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteOffer(@PathVariable int id){
Offer currentOffer = offerService.getOfferById(id);
if (currentOffer == null)
throw new OfferNotFoundException(id);
offerService.deleteOfferById(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
-----------------------------------------------------------------------------------------------------------------------------------------
<예외처리(Excpetion) 종류>
1. Throwable class
- Java 언어의 모든 오류 및 예외의 슈퍼 클래스이다
- 이 클래스의 인스턴스(또는 그 서브 클래스 중 하나)인 객체만 Java Virtual Machine에 의해 발생되거나 Java throw문에 의해서 발생
- 예외의 comple-time checking을 위해, RunTimeException 또는 Error의 서브 클래스가 아닌 Throwable 및 Throwalbe의 서브 클래스는 Checked 예외로 간주
2. Error class
- Error는 Throwable의 하위 클래스로서, 응용 프로그램의 심각한 문제를 나타내는 클래스이다
- 시스템에 비정상적인 상황이 생겼을 때 발생한다(시스템 레벨에서 발생)
- Error의 서브 클래스를 throws 선언할 필요는 없다
- Error 및 해당 서브 클래스는 예외 컴파일 시간 검사를 위해 unchcked Exception으로 간주된다
3. Exception class
- Exception 클래스와 그 subclass는 응용프로그램이 catch할 수 있는 조건을 나타내는 Throwable 형식이다
- Exception 클래스와 RuntimeException의 subclass가 아닌 서브 클래스는 checked exception이다
4. RunTimeException
- Java Virtual Machine의 정상적인 작동 중에 발생할 수 있는 예외의 슈퍼 클래스이다
- RuntimeException 및 해당 서브 클래스는 unchecked exception이다
unchecked exception은 메서드 또는 생성자의 실행에 의해 발생한다
<Checked Exception vs. Unchecked Exception>
1. checked exception
- 반드시 예외 처리를 해야한다(try~catch문)
- 컴파일 단계에서 확인 가능
- 예외 발생 시 트랜잭션 roll back 하지 않는다
- RuntimeException을 제외한 Exception의 하위 클래스
2. unchecked exception
- 명시적 에외 처리를 강제하지 않는다
- 실행 단계에서 확인 가능하다
- 예외 발생 시 트랜잭션 roll back한다
- RuntimeException의 하위 클래스
*Getter vs. Setter
- pirvate에서 관리하는 메스드
- private할 때 다른 클래스에서 접근하려면 해당 클래스 안의 메서드를 통해서만 가능하다. 그 관리하는 메서드를 Getter, Setter라고 한다
1. Getter
- Private를 외부로 꺼내는 메서드
- 내부의 멤버변수에 저장된 값을 외부로 리ㄷ턴
- 메서드 명은 주로 getXXX() 메서드 형식으로 지정
- XXX는 해당 멤버변수의 변수명을 사용
2. Setter
- Private에 값을 넣는 메서드
- 외부러부터 데이터를 전달받아 멤버변수에 저장
- 매개변수만 있고, 리턴값은 없는 메서드로 정의
GlobalExceptionController코드-----------------------------------------------------------------------------------------------------------------------
@RestControllerAdvice //전역(모든) Controller에서 예외 처리 가능
public class GlobalExceptionController {
@ExceptionHandler(OfferNotFoundException.class)
public ResponseEntity<ErrorResponse> handleOfferNotFoundException(HttpServletRequest req, OfferNotFoundException ex) {
String requestUri = req.getRequestURI();
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setRequestUri(requestUri);
errorResponse.setErrorCode("offer.notfound.exception");
errorResponse.setErrorMsg("offer with id" + ex.getOfferId() + "not found");
return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.NOT_FOUND); //body(ResponseEntity)에 넘겨지게된다
}
ErrorResponse.java 코드 ----------------------------------------------------------------------------------------------------------------------
package kr.ac.hansung.cse.model;
import lombok.Data;
@Data //getter, setter, 인자가 없는(있는) 생성자 등
public class ErrorResponse {
private String errorCode;
private String errorMsg;
private String requestUri;
}
-----------------------------------------------------------------------------------------------------------------------------------------
'웹프레임워크' 카테고리의 다른 글
Spring Boot (1) | 2024.05.16 |
---|---|
RestAPI (0) | 2024.05.01 |
JPA (0) | 2024.04.23 |