Response 포맷
Login 성공 및 실패 시 두 경우 모두 httpStatusCode 는 200 으로, Body 형식 또한 같은 형식을 씀
{
"resultCode": 200,
"resultMsg": "인증 성공",
"data": { ... }
}
{
"resultCode": 400,
"resultMsg": "패스워드가 일치하지 않습니다.",
"data": {
"pwdFailCnt": 3
}
}
Field | Type |
---|---|
resultCode | Integer |
resultMsg | String |
data | Object |
BusinessException 발생 시
ControllerAdvice(ExceptionHandler) 에서 httpStatusCode 400, Body 형식은 아래와 같이 응답됨
BusinessException 은 ErrorCode Enum 을 필드로 가지고 있어서 code 와 message 필드값을 가져와 해당 값으로 ErrorResponse 클래스를 생성해 응답해줌
{
"errorCode": "E9999",
"errorMsg": "",
"status": ""
}
Field | Type |
---|---|
errorCode | String |
resultMsg | String |
status | String |
HTTP 요청 모듈
Response 포맷
→ API 성공, 실패 여부에 따라 Http Status Code 를 다르게 하고, Body 포맷은 공통화
👉 Response Class
public class Response {
private String resultCode;
private String resultMsg;
private Map<String, Object> data;
...
public static Response create(String responseCode) {
return Response.builder()
.resultCode(responseCode)
.resultMsg(getMessage(responseCode))
.build();
}
public static Response create(String responseCode, Map<String, Object> data) {
return Response.builder()
.resultCode(responseCode)
.resultMsg(getMessage(responseCode))
.data(data)
.build();
}
}
Name | Type |
---|---|
resultCode | String |
resultMsg | String |
data | Object |
// 성공 Http Status Code :: 200
{
"resultCode": "E0000",
"resultMsg": "정상",
"data": {
"count": 5
}
}
// 실패 Http Status Code :: 500
{
"resultCode": "E9999",
"resultMsg": "서비스중 오류가 발생했습니다",
"data": null
}
👉 ErrorCode Enum
기존 ErrorCode Enum
public enum ErrorCode {
API_STATUS_OK("E0000", "정상"),
API_SERVER_ERROR("E9999", "서비스중 오류가 발생했습니다."),
;
private String code;
private String message;
}
수정 ErrorCode Enum
public enum ResponseCode {
API_STATUS_OK("E0000", 200),
API_SERVER_ERROR("E9999", 500)
;
private String code;
private Integer status;
public ResponseEntity<Response> [toResponseEntity()](<https://elegant-field-eb6.notion.site/0f67a4674a62473aaf79f40cb83d7a1e>) {
return ResponseEntity
.status(this.getStatus())
.body(Response.create(this.getCode()));
}
public ResponseEntity<Response> [toResponseEntity(Map<String, Object> data)](<https://elegant-field-eb6.notion.site/0f67a4674a62473aaf79f40cb83d7a1e>) {
return ResponseEntity
.status(this.getStatus())
.body(Response.create(this.getCode(), data));
}
}
👉 BusinessException
기존 BusinessException
public class BusinessException extends Exception {
private static final long serialVersionUID = 1L;
private final ErrorCode errorCode;
public BusinessException(ErrorCode code) {
this.errorCode = code;
}
public ErrorCode getError() {
return errorCode;
}
}
수정 BusinessException
public class BusinessException extends Exception {
private static final long serialVersionUID = 1L;
private final ResponseCode responseCode;
private final Map<String, Object> data;
public BusinessException(ResponseCode code) {
this.responseCode = code;
this.data = null;
}
public BusinessException(ResponseCode responseCode, Map<String, Object> data) {
this.responseCode = responseCode;
this.data = data;
}
public ResponseCode getResponseCode() {
return this.responseCode;
}
public Map<String, Object> getData() {
return this.data;
}
}
👉 사용예시
@Service
public class TestService {
...
public String getUserName(String userNo) {
UserDTO userDto = userDao.getUser(userNo);
if (userDto == null) {
throw new BusinessException(ResponseCode.USER_NOT_FOUND);
}
return userDto.getName();
}
}
throw new BusinessException(ResponseCode.USER_NOT_FOUND);
가 발생 시 ExceptionController 가 에러 캐치
@Slf4j
@RestControllerAdvice
public class ExceptionController {
@ExceptionHandler(BusinessException.class)
protected ResponseEntity<Response> handleBusinessException(BusinessException e) {
ResponseCode responseCode = e.getResponseCode();
if (responseCode == null) {
responseCode = ResponseCode.API_SERVER_ERROR;
}
return responseCode.[toResponseEntity()](<https://elegant-field-eb6.notion.site/0f67a4674a62473aaf79f40cb83d7a1e>);
}
}
→ 응답값
// Http Status Code :: 500
{
"resultCode": "E9999",
"resultMsg": "서비스중 오류가 발생했습니다",
"data": null
}
Exception 발생 없이 Controller 로 리턴 될 경우
@RestController
public class TestController {
...
@GetMapping("/user/name/{userNo}")
public ResponseEntity<Response> getUserName(@PathVariable String userNo) throws BusinessException {
String userName = testService.getUserName(userNo);
Map<String, Object> responseData = new HashMap<>();
responseData.put("userName", userName");
return ResponseCode.API_STATUS_OK.[toResponseEntity(responseData)](<https://elegant-field-eb6.notion.site/0f67a4674a62473aaf79f40cb83d7a1e>);
}
}
→ 응답값
// Http Status Code :: 200
{
{
"resultCode": "E0000",
"resultMsg": "정상",
"data": {
"userName": "minsu"
}
}
HTTP 요청 모듈
기존에 구현된 HttpConnector 클래스 코드 정리
GET - Query Param
// URIBuilder 사용
HttpGet httpGet = new HttpGet("<https://example.com>");
URI uri = new URIBuilder(httpGet.getURI())
.addParameter("param1", "value1")
.addParameter("param2", "value2")
.build();
httpGet.setURI(uri);
CloseableHttpResponse response = client.execute(httpGet);
client.close();
// NameValuePair List 사용
HttpGet httpGet = new HttpGet("<https://example.com>");
List<NameValuePair> nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair("param1", "value1"));
nameValuePairs.add(new BasicNameValuePair("param2", "value2"));
// List<NameValuePair> nameValuePairs = convertParam(params);
URI uri = new URIBuilder(httpGet.getURI())
.addParameters(nameValuePairs)
.build();
httpGet.setURI(uri);
CloseableHttpResponse response = client.execute(httpGet);
client.close();
// Map to NameValuePair
private List<NameValuePair> convertParam(Map<String, String> params) {
List<NameValuePair> nameValuePairs = new ArrayList<>();
for (Map.Entry<String, String> entry : params.entrySet()) {
nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
return nameValuePairs;
}
POST - JSON
HttpPost httpPost = new HttpPost("<https://example.com>");
String requestJson = "{"id":1,"name":"John"}";
// String requestJson = new Gson().toJson(requestMap);
StringEntity entity = new StringEntity(requestJson);
httpPost.setEntity(entity);
httpPost.setHeader("Content-type", "application/json");
CloseableHttpResponse response = client.execute(httpPost);
client.close();
POST - Form Data
HttpPost httpPost = new HttpPost("<https://example.com>");
List<NameValuePair> nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair("param1", "value1"));
nameValuePairs.add(new BasicNameValuePair("param2", "value2"));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8));
CloseableHttpResponse response = client.execute(httpPost);
client.close();
POST - Multipart
// addBinaryBody(), addTextBody() 메서드 사용
HttpPost httpPost = new HttpPost("<https://example.com>");
File file = new File(fileName); // file
String message = "message"; // text
InputStream inputStream = new FileInputStream(zipFileName); // zip file
File imageFile = new File(imageFileName); // image file
byte[] bytes = "binary code".getBytes(); // byte array
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("upload-file", file, ContentType.DEFAULT_BINARY, fileName);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
builder.addBinaryBody("zip-file", inputStream, ContentType.create("application/zip"), zipFileName);
builder.addBinaryBody("image-file", imageFile, ContentType.DEFAULT_BINARY, imageFileName);
builder.addBinaryBody("byte-array", bytes, ContenteType.DEFAULT_BINARY, "byte-array");
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
CloseableHttpResponse response = client.execute(httpPost);
client.close();
// addPart() 메서드 사용
HttpPost httpPost = new HttpPost("<https://example.com>");
File file = new File(fileName);
FileBody = fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
StringBody stringBody = new StringBody("Message", ContentType.MULTIPART_FORM_DATA);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("upload-file", fileBody);
builder.addPart("text", stringBody);
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
CloseableHttpResponse response = client.execute(httpPost);
client.close();