SpringBoot 가 백 엔 드 반환 형식 을 어떻게 통일 하 는 지 자세히 알 아 보기
13816 단어 SpringBoot백 엔 드반환 형식
우선 통 일 된 표준 격식 으로 돌아 가 는 이 유 를 살 펴 보 자.
왜 SpringBoot 에 대해 통 일 된 표준 형식 으로 돌아 가 야 합 니까?
기본 적 인 상황 에서 SpringBoot 의 반환 형식 은 세 가지 가 있 습 니 다.
첫 번 째:String 복귀
@GetMapping("/hello")
public String getStr(){
return "hello,javadaily";
}
이 때 인터페이스 에서 가 져 온 반환 값 은 다음 과 같 습 니 다.hello,javadaily
두 번 째:사용자 정의 대상 되 돌리 기
@GetMapping("/aniaml")
public Aniaml getAniaml(){
Aniaml aniaml = new Aniaml(1,"pig");
return aniaml;
}
이 때 인터페이스 에서 가 져 온 반환 값 은 다음 과 같 습 니 다.
{
"id": 1,
"name": "pig"
}
세 번 째:인터페이스 이상
@GetMapping("/error")
public int error(){
int i = 9/0;
return i;
}
이 때 인터페이스 에서 가 져 온 반환 값 은 다음 과 같 습 니 다.
{
"timestamp": "2021-07-08T08:05:15.423+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/wrong"
}
상기 여러 가지 상황 을 바탕 으로 만약 당신 이 전단 개발 자 와 인 터 페 이 스 를 연결 하면 그들 은 매우 어 리 석 을 것 입 니 다.왜냐하면 우 리 는 그 에 게 통 일 된 격식 을 주지 않 았 기 때문에 전단 직원 들 은 반환 치 를 어떻게 처리 해 야 할 지 모 릅 니 다.그리고 심지어 어떤 친구 들 은 예 를 들 어 장 군 이 결 과 를 포장 하 는 것 을 좋아한다.그 는 Result 대상 을 사 용 했 고 왕 군 도 결 과 를 포장 하 는 것 을 좋아 하지만 그 는 Response 대상 을 사용 했다.이런 상황 이 발생 했 을 때 나 는 전단 인원 이 반드시 미 칠 것 이 라 고 믿는다.
그래서 우리 프로젝트 에 서 는 통 일 된 표준 반환 형식 을 정의 해 야 합 니 다.
정의 반환 표준 형식
표준 반환 형식 은 최소 3 부분 을 포함 합 니 다:
{
"status":"100",
"message":" ",
"data":"hello,javadaily"
}
물론 필요 에 따라 다른 확장 값 을 추가 할 수도 있다.예 를 들 어 우 리 는 반환 대상 에 인터페이스 호출 시간 을 추가 했다.timestamp:인터페이스 호출 시간
정의 반환 대상
@Data
public class ResultData<t> {
/** , ResultData.java*/
private int status;
private String message;
private T data;
private long timestamp ;
public ResultData (){
this.timestamp = System.currentTimeMillis();
}
public static <t> ResultData<t> success(T data) {
ResultData<t> resultData = new ResultData<>();
resultData.setStatus(ReturnCode.RC100.getCode());
resultData.setMessage(ReturnCode.RC100.getMessage());
resultData.setData(data);
return resultData;
}
public static <t> ResultData<t> fail(int code, String message) {
ResultData<t> resultData = new ResultData<>();
resultData.setStatus(code);
resultData.setMessage(message);
return resultData;
}
}
정의 상태 코드
public enum ReturnCode {
/** **/
RC100(100," "),
/** **/
RC999(999," "),
/** **/
RC200(200," , !"),
/** **/
RC201(201," , !"),
/** **/
RC202(202," , !"),
/** **/
RC203(203," , !"),
/** **/
RC204(204," , !"),
/**access_denied**/
RC403(403," , "),
/**access_denied**/
RC401(401," "),
/** **/
RC500(500," , "),
INVALID_TOKEN(2001," "),
ACCESS_DENIED(2003," "),
CLIENT_AUTHENTICATION_FAILED(1001," "),
USERNAME_OR_PASSWORD_ERROR(1002," "),
UNSUPPORTED_GRANT_TYPE(1003, " ");
/** **/
private final int code;
/** **/
private final String message;
ReturnCode(int code, String message){
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
일괄 반환 형식
@GetMapping("/hello")
public ResultData<string> getStr(){
return ResultData.success("hello,javadaily");
}
이 때 인터페이스 에서 가 져 온 반환 값 은 다음 과 같 습 니 다.
{
"status": 100,
"message": "hello,javadaily",
"data": null,
"timestamp": 1625736481648,
"httpStatus": 0
}
이렇게 해서 우리 가 원 하 는 결 과 를 실 현 했 습 니 다.제 가 많은 프로젝트 에서 본 것 은 모두 이런 기법 입 니 다.Controller 층 에서ResultData.success()
을 통 해 결 과 를 포장 한 후에 전단 으로 돌아 갑 니 다.이곳 을 보고 우 리 는 멈 춰 서서 생각해 보 자.이렇게 하 는 것 이 무슨 폐단 이 있 겠 는가?
가장 큰 단점 은 우리 뒤에 인 터 페 이 스 를 쓸 때마다 호출
ResultData.success()
이라는 코드 를 사용 하여 결 과 를 포장 하고 중복 노동 을 하 며 체력 을 낭비 하 는 것 이다.또 다른 늙 은 새들 에 게 놀림 을 받 기 쉽다.그래서 우 리 는 코드 를 최적화 시 켜 야 한다.목 표 는 모든 인터페이스 가 손 으로
ResultData
반환 값 을 제정 하지 않 는 것 이다.고급 실현 방식
이 코드 를 최적화 하 는 것 은 매우 간단 하 다.우 리 는 SpringBoot 가 제공 하 는
ResponseBodyAdvice
만 빌 리 면 된다.Response Body Advice 의 역할:Controller 방법의 반환 값 을 차단 하고 반환 값/응답 체 를 통일 적 으로 처리 하 며 보통 반환 형식,복호화,서명 등 을 통일 적 으로 처리 합 니 다.
먼저
ResponseBodyAdvice
의 소스 코드 를 살 펴 보 겠 습 니 다.
public interface ResponseBodyAdvice<t> {
/**
* advice
* true ,false
*/
boolean supports(MethodParameter var1, Class<!--? extends HttpMessageConverter<?-->> var2);
/**
*
*/
@Nullable
T beforeBodyWrite(@Nullable T var1, MethodParameter var2, MediaType var3, Class<!--? extends HttpMessageConverter<?-->> var4, ServerHttpRequest var5, ServerHttpResponse var6);
}
우 리 는 구체 적 인 실현 클래스 만 작성 하면 된다.
/**
* @author jam
* @date 2021/7/8 10:10
*/
@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<object> {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter methodParameter, Class<!--? extends HttpMessageConverter<?-->> aClass) {
return true;
}
@SneakyThrows
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<!--? extends HttpMessageConverter<?-->> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if(o instanceof String){
return objectMapper.writeValueAsString(ResultData.success(o));
}
return ResultData.success(o);
}
}
두 가지 주의 가 필요 합 니 다.@RestControllerAdvice
주해@RestControllerAdvice
은@RestController
주해 의 강화 로 세 가지 기능 을 실현 할 수 있다.
if(o instanceof String){
return objectMapper.writeValueAsString(ResultData.success(o));
}
이 코드 는 반드시 추가 해 야 합 니 다.Controller 가 String 으로 직접 돌아 가면 SpringBoot 는 직접 돌아 오기 때문에 json 으로 수 동 으로 변환 해 야 합 니 다.위의 처 리 를 통 해 우 리 는 더 이상
ResultData.success()
을 통 해 전환 할 필요 가 없다.원시 데이터 형식 으로 직접 돌아 가면 SpringBoot 는 자동 으로 포장 류 의 포장 을 실현 할 수 있다.
@GetMapping("/hello")
public String getStr(){
return "hello,javadaily";
}
이때 우리 가 인 터 페 이 스 를 호출 하여 되 돌려 준 데이터 결 과 는 다음 과 같다.
@GetMapping("/hello")
public String getStr(){
return "hello,javadaily";
}
완벽 하 다 고 생각 하 시 죠?서 두 르 지 마 세 요.또 문제 가 기다 리 고 있 습 니 다.인터페이스 이상 문제
이때 문제 가 있 습 니 다.우 리 는 Controller 의 이상 을 처리 하지 않 았 기 때문에 우리 가 호출 하 는 방법 에 이상 이 생기 면 문제 가 발생 합 니 다.예 를 들 어 아래 의 이 인터페이스 등 입 니 다.
@GetMapping("/wrong")
public int error(){
int i = 9/0;
return i;
}
돌아 온 결 과 는:이것 은 분명히 우리 가 원 하 는 결과 가 아니다.인터페이스 가 잘못 되 었 고 조작 에 성공 한 응답 코드 를 되 돌려 주 었 다.앞에서 보면 때 릴 것 이다.
서 두 르 지 마 세 요.다음은 두 번 째 의제 로 들 어가 서 전체적인 이상 을 우아 하 게 처리 하 는 방법 입 니 다.
SpringBoot 는 왜 전역 이상 프로세서 가 필요 합 니까?
손 으로 try...catch 를 쓰 지 않 고 전역 이상 프로세서 에서 일괄 적 으로 캡 처 합 니 다.
전역 이상 처리 기 를 사용 하 는 가장 큰 편리 함 은 프로그래머 가 코드 를 쓸 때 손 으로 쓸 필요 가 없다 는 것 입 니 다
try...catch
.앞에서 말씀 드 렸 듯 이 기본적으로 SpringBoot 에 이상 이 생 겼 을 때 돌아 오 는 결 과 는 다음 과 같 습 니 다.
{
"timestamp": "2021-07-08T08:05:15.423+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/wrong"
}
이러한 데이터 형식 은 전단 에 되 돌아 가 고 전단 은 알 아 볼 수 없 기 때문에 우 리 는 보통try...catch
을 통 해 이상 을 처리 합 니 다.
@GetMapping("/wrong")
public int error(){
int i;
try{
i = 9/0;
}catch (Exception e){
log.error("error:{}",e);
i = 0;
}
return i;
}
우리 가 추구 하 는 목 표 는 더 이상 수 동 으로 쓰 지 않 아 도 된다 는 것 이다try...catch
.사용자 정의 이상 에 대해 서 는 전역 이상 프로세서 로 만 처리 할 수 있 습 니 다.
@GetMapping("error1")
public void empty(){
throw new RuntimeException(" ");
}
Validator 매개 변수 검사 기 를 도입 할 때 매개 변수 검사 가 통과 되 지 않 으 면 이상 이 발생 합 니 다.이 때 는try...catch
로 캡 처 할 수 없고 전역 이상 처리 장치 만 사용 할 수 있 습 니 다.SpringBoot 통합 매개 변수 검사 이 글 을 참고 하 십시오SpringBoot 개발 비적-통합 매개 변수 검사 및 고급 기술
어떻게 전역 이상 처리 기 를 실현 합 니까?
@Slf4j
@RestControllerAdvice
public class RestExceptionHandler {
/**
* 。
* @param e the e
* @return ResultData
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResultData<string> exception(Exception e) {
log.error(" ex={}", e.getMessage(), e);
return ResultData.fail(ReturnCode.RC500.getCode(),e.getMessage());
}
}
세 가지 세부 사항 을 설명해 야 한다.@RestControllerAdvice
,RestController 의 증강 류 는 전역 이상 프로세서@ExceptionHandler
특정한 이상 을 통일 적 으로 처리 하여 코드 중복 율 과 복잡 도 를 줄인다.예 를 들 어 사용자 정의 이상 을 얻 으 려 면@ExceptionHandler(BusinessException.class)
@ResponseStatus
클 라 이언 트 가 받 은 http 상태 코드 지정이때 우 리 는 다음 과 같은 인 터 페 이 스 를 호출 합 니 다.
@GetMapping("error1")
public void empty(){
throw new RuntimeException(" ");
}
돌아 온 결 과 는 다음 과 같다.
{
"status": 500,
"message": " ",
"data": null,
"timestamp": 1625795902556
}
기본적으로 우리 의 요 구 를 만족 시 켰 다.그러나 우리 가 통 일 된 표준 형식 패 키 징 기능
ResponseAdvice
과RestExceptionHandler
전역 이상 처리 장 치 를 동시에 사용 할 때 새로운 문제 가 발생 했 습 니 다.
{
"status": 100,
"message": " ",
"data": {
"status": 500,
"message": " ",
"data": null,
"timestamp": 1625796167986
},
"timestamp": 1625796168008
}
이때 돌아 오 는 결 과 는 이 렇 습 니 다.통일 형식 강화 기능 은 돌아 오 는 이상 한 결 과 를 다시 포장 하기 때문에 다음 에 우 리 는 이 문 제 를 해결 해 야 합 니 다.전역 이상 접속 되 돌아 오 는 표준 형식
전역 이상 접속 표준 형식 은 간단 합 니 다.전역 이상 프로세서 가 표준 형식 을 봉인 해 주 었 기 때문에 클 라 이언 트 에 게 직접 되 돌려 주면 됩 니 다.
@SneakyThrows
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<!--? extends HttpMessageConverter<?-->> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if(o instanceof String){
return objectMapper.writeValueAsString(ResultData.success(o));
}
if(o instanceof ResultData){
return o;
}
return ResultData.success(o);
}
키 코드:
if(o instanceof ResultData){
return o;
}
돌아 온 결과 가 ResultData 대상 이 라면 바로 돌아 가면 된다.이때 우리 가 위의 잘못된 방법 을 다시 호출 하면 돌아 오 는 결 과 는 우리 의 요구 에 부합된다.
{
"status": 500,
"message": " ",
"data": null,
"timestamp": 1625796580778
}
자,오늘 의 글 은 여기까지 입 니 다.이 글 을 통 해 프로젝트 에서 우호 적 으로 통 일 된 표준 형식 을 되 돌려 주 고 전체 이상 을 우아 하 게 처리 할 수 있 는 방법 을 알 수 있 기 를 바 랍 니 다.github 주소:https://github.com/jianzh5/cloud-blog/
여기 서 SpringBoot 가 백 엔 드 반환 형식 을 어떻게 통일 하 는 지 에 대한 자세 한 설명 은 여기까지 입 니 다.SpringBoot 통일 백 엔 드 반환 형식 에 관 한 내용 은 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Java・SpringBoot・Thymeleaf】 에러 메세지를 구현(SpringBoot 어플리케이션 실천편 3)로그인하여 사용자 목록을 표시하는 응용 프로그램을 만들고, Spring에서의 개발에 대해 공부하겠습니다 🌟 마지막 데이터 바인딩에 계속 바인딩 실패 시 오류 메시지를 구현합니다. 마지막 기사🌟 src/main/res...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.