Spring: @ControllerAdvice & @ResponseBodyAdvice
Config:
package io.jot.memento; import org.springframework.context.annotation.Configuration; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; @Configuration public class Config{ @ControllerAdvice static class MyControllerAdvice implements ResponseBodyAdvice{ @Override public boolean supports(MethodParameter returnType, Class converterType){ if(returnType.getMethodAnnotation(ResponseBody.class) != null || AnnotationUtils.findAnnotation(returnType.getContainingClass(), ResponseBody.class) != null /*returnType.getContainingClass().isAnnotationPresent(ResponseBody.class)*/){ return true; } return false; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response){ if(body instanceof Result) return body; return Result.ok(body); } } // @Controller // @ResponseBody @RestController public static class MyController{ public User user(){ return new User("bbbbbbbbbb", 55); } } public static class User{ private String name; private int age; public User(String name, int age){ this.name = name; this.age = age; } public String getName(){ return name; } public void setName(String name){ this.name = name; } public int getAge(){ return age; } public void setAge(int age){ this.age = age; } } }
Result:
package io.jot.memento; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @JsonInclude(JsonInclude.Include.NON_NULL) public class Result{ private int code; private String msg; private Object data; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } @JsonCreator private Result(@JsonProperty("code") int code, @JsonProperty("data") Object data) { this.code = code; this.data = data; } private Result(int code, String msg) { this.code = code; this.msg = msg; } public static Result ok() { return new Result(200, null); } public static Result ok(Object data) { return new Result(200, data); } public static Result error(String msg) { return new Result(500, "服务器内部错误:" + msg); } }
package io.jot.memento; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.ControllerAdviceBean; import org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver; import org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver; import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite; import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.mvc.method.annotation.*; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; public class Venal{ public static void main(String[] args) throws Exception{ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); ServletInvocableHandlerMethod handlerMethod = new ServletInvocableHandlerMethod(context.getBean(Config.MyController.class), Config.MyController.class.getMethod("user")); handlerMethod.setDataBinderFactory(new ServletRequestDataBinderFactory(Collections.emptyList(), null)); handlerMethod.setHandlerMethodArgumentResolvers(getArgumentResolvers(context)); handlerMethod.setHandlerMethodReturnValueHandlers(getReturnValueHandlers(context)); handlerMethod.setParameterNameDiscoverer(new DefaultParameterNameDiscoverer()); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); handlerMethod.invokeAndHandle(new ServletWebRequest(request, response), new ModelAndViewContainer()); System.out.println("\033[37;7m>>>>>> " + new String(response.getContentAsByteArray(), StandardCharsets.UTF_8) + " <<<<<<\033[0m"); context.close(); } public static HandlerMethodArgumentResolverComposite getArgumentResolvers(AnnotationConfigApplicationContext context){ HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite(); composite.addResolvers( new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(), false), new PathVariableMethodArgumentResolver(), new RequestHeaderMethodArgumentResolver(context.getDefaultListableBeanFactory()), new ServletCookieValueMethodArgumentResolver(context.getDefaultListableBeanFactory()), new ExpressionValueMethodArgumentResolver(context.getDefaultListableBeanFactory()), new ServletRequestMethodArgumentResolver(), new ServletModelAttributeMethodProcessor(false), new RequestResponseBodyMethodProcessor(List.of(new MappingJackson2HttpMessageConverter())), new ServletModelAttributeMethodProcessor(true), new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(), true) ); return composite; } public static HandlerMethodReturnValueHandlerComposite getReturnValueHandlers(AnnotationConfigApplicationContext context){ // 添加 advice ListannotatedBeans = ControllerAdviceBean.findAnnotatedBeans(context); List