@RestControllerAdvice是組合註解,它組合了@ControllerAdvice和@ResponseBody,它的功能和@ControllerAdvice一致,主要使用於對RESTful的請求體和返回體進行定製處理。
2.4.1 先處理請求體與後處理返回體對請求體定製處理實現RequestBodyAdvice介面,它會在請求體進入控制器方法之前對請求體進行先處理;對返回體進行定製處理ResponseBodyAdvice,它會在控制器方法返回值確定之後對返回值進行後處理。他們和@RestControllerAdvice一起使用。
我們定義個註解,這個註解作為使用我們的定製功能的標記。
@Target({ElementType.PARAMETER, ElementType.METHOD}) //支援註解在方法引數和方法上@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ProcessTag {}
定製請求體的建言:
@RestControllerAdvicepublic class CustomRequestBodyAdvice implements RequestBodyAdvice { @Override public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { return methodParameter.getParameterAnnotation(ProcessTag.class) != null; //1 } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException { return inputMessage; //2 } @Override public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { if (body instanceof Person) { Person person = (Person) body; String upperCaseName = person.getName().toUpperCase(); return new Person(person.getId(), upperCaseName, person.getAge()); } return body; //3 } @Override public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { if(Person.class.isAssignableFrom((Class<?>) targetType)){ return new Person(new Random().nextLong(),"Nobody",-1); } return body; //4 }}
該請求體建言起效的條件,本例是請求體引數是否標記了@ProcessTag註解;在請求體讀取前,未做任何處理;在請求體讀取後,如果請求體型別是Person,將name轉為大寫;若不是Person保持不變;在處理請求體為空時,如果請求體型別是Person,建一個物件,否則保持不變。定製的返回體處理建言:
@RestControllerAdvicepublic class CustomResponseBodyAdvice implements ResponseBodyAdvice { @Override public boolean supports(MethodParameter returnType, Class converterType) { return returnType.hasMethodAnnotation(ProcessTag.class); //1 } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof Person){ Map<String, Object> map = new HashMap<>(); map.put("person", body); map.put("extra-response-body", "demo-body"); return map; } return body; //2 }}
該返回體建言起效的條件,本例是控制器方法上標記了@ProcessTag註解;在寫返回體前,我們將額外的資訊和body封裝到map裡返回;若不是Person型別則保持不變。我們在控制裡驗證這兩個建言:
@GetMapping("/modifyBodies")@ProcessTag //標記定製返回體public Person modifyRequestBody(@ProcessTag @RequestBody Person person){ //標記定製請求體 return person;}
我們請求體不為空時請求:
我們請求體為空時請求:
最新評論