文章目录
- 1.common-tool-starter
- 1.目录结构
- 2.ResultWrapper.java
- 2.common-web-starter
- 1.目录结构
- 2.IgnoredResultWrapper.java 自定义注解,忽略对返回结果的自动包装
- 3.ReturnValueHandlersDecorator.java 对适配器进行扩展的装饰器
- 4.WebAutoConfiguration.java 将装饰器注入容器
- 3.common-web-starter-demo
- 1.WebController.java 测试三种使用方式
- 2.测试
- 1.第一种:直接使用自动包装成功结果
- 2.第二种:使用 @IgnoredResultWrapper注解忽略掉自动包装
- 3.第三种:直接使用ResultWrapper来自己封装结果
1.common-tool-starter
1.目录结构
2.ResultWrapper.java
package com.sunxiansheng.tool.response;
import lombok.Data;
import java.io.Serializable;
@Data
public class ResultWrapper<T> implements Serializable {
private static final long serialVersionUID = 1L;
private boolean success;
private int code;
private String message;
private T data;
private ResultWrapper() {
}
public static class Builder<T> {
private boolean success;
private int code;
private String message;
private T data;
public Builder<T> success(boolean success) {
this.success = success;
return this;
}
public Builder<T> code(int code) {
this.code = code;
return this;
}
public Builder<T> message(String message) {
this.message = message;
return this;
}
public Builder<T> data(T data) {
this.data = data;
return this;
}
public ResultWrapper<T> build() {
ResultWrapper<T> result = new ResultWrapper<>();
result.success = this.success;
result.code = this.code;
result.message = this.message;
result.data = this.data;
return result;
}
}
public static <T> ResultWrapper<T> ok() {
return new Builder<T>()
.success(true)
.code(RespBeanEnum.SUCCESS.getCode())
.message(RespBeanEnum.SUCCESS.getMessage())
.build();
}
public static <T> ResultWrapper<T> ok(T data) {
return new Builder<T>()
.success(true)
.code(RespBeanEnum.SUCCESS.getCode())
.message(RespBeanEnum.SUCCESS.getMessage())
.data(data)
.build();
}
public static <T> ResultWrapper<T> ok(T data, String message) {
return new Builder<T>()
.success(true)
.code(RespBeanEnum.SUCCESS.getCode())
.message(message)
.data(data)
.build();
}
public static <T> ResultWrapper<T> fail() {
return new Builder<T>()
.success(false)
.code(RespBeanEnum.ERROR.getCode())
.message(RespBeanEnum.ERROR.getMessage())
.build();
}
public static <T> ResultWrapper<T> fail(String message) {
return new Builder<T>()
.success(false)
.code(RespBeanEnum.ERROR.getCode())
.message(message)
.build();
}
public static <T> ResultWrapper<T> fail(int code, String message) {
return new Builder<T>()
.success(false)
.code(code)
.message(message)
.build();
}
public static <T> ResultWrapper<T> fail(int code, String message, T data) {
return new Builder<T>()
.success(false)
.code(code)
.message(message)
.data(data)
.build();
}
public static <T> ResultWrapper<T> fail(RespBeanEnum respBeanEnum) {
return new Builder<T>()
.success(false)
.code(respBeanEnum.getCode())
.message(respBeanEnum.getMessage())
.build();
}
}
2.common-web-starter
1.目录结构
2.IgnoredResultWrapper.java 自定义注解,忽略对返回结果的自动包装
package com.sunxiansheng.web.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoredResultWrapper {
}
3.ReturnValueHandlersDecorator.java 对适配器进行扩展的装饰器
package com.sunxiansheng.web.config;
import com.sunxiansheng.tool.response.ResultWrapper;
import com.sunxiansheng.web.annotation.IgnoredResultWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Slf4j
public class ReturnValueHandlersDecorator implements InitializingBean {
@Resource
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
@Override
public void afterPropertiesSet() {
List<HandlerMethodReturnValueHandler> returnValueHandlers = requestMappingHandlerAdapter.getReturnValueHandlers();
assert returnValueHandlers != null;
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(returnValueHandlers);
this.decorateHandlers(handlers);
requestMappingHandlerAdapter.setReturnValueHandlers(handlers);
}
private void decorateHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
if (returnValueHandler instanceof RequestResponseBodyMethodProcessor) {
ControllerReturnValueHandler controllerReturnValueHandler = new ControllerReturnValueHandler(returnValueHandler);
int index = returnValueHandlers.indexOf(returnValueHandler);
returnValueHandlers.set(index, controllerReturnValueHandler);
}
}
}
private static class ControllerReturnValueHandler implements HandlerMethodReturnValueHandler {
private final HandlerMethodReturnValueHandler handler;
public ControllerReturnValueHandler(HandlerMethodReturnValueHandler handler) {
this.handler = handler;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) || returnType.hasMethodAnnotation(ResponseBody.class);
}
@Override
public void handleReturnValue(Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest) throws Exception {
IgnoredResultWrapper methodAnnotation = methodParameter.getMethodAnnotation(IgnoredResultWrapper.class);
if (Objects.nonNull(methodAnnotation)) {
handler.handleReturnValue(o, methodParameter, modelAndViewContainer, nativeWebRequest);
return;
}
if (o instanceof ResultWrapper) {
handler.handleReturnValue(o, methodParameter, modelAndViewContainer, nativeWebRequest);
return;
}
log.info("Controller返回值已被自动包装,如果上传文件,请加@IgnoredResultWrapper注解取消自动包装!");
ResultWrapper<Object> ok = ResultWrapper.ok(o);
handler.handleReturnValue(ok, methodParameter, modelAndViewContainer, nativeWebRequest);
}
}
}
4.WebAutoConfiguration.java 将装饰器注入容器
@Bean
@ConditionalOnMissingBean
public ReturnValueHandlersDecorator returnValueHandlersDecorator() {
return new ReturnValueHandlersDecorator();
}
3.common-web-starter-demo
1.WebController.java 测试三种使用方式
package com.sunxiansheng.web.controller;
import com.sunxiansheng.tool.response.ResultWrapper;
import com.sunxiansheng.web.annotation.IgnoredResultWrapper;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WebController {
@RequestMapping("/method1")
public String method1() {
return "method1";
}
@IgnoredResultWrapper
@RequestMapping("/method2")
public String method2() {
return "method2";
}
@RequestMapping("/method3")
public ResultWrapper<String> method3() {
return ResultWrapper.fail("method3");
}
}
2.测试
1.第一种:直接使用自动包装成功结果
2.第二种:使用 @IgnoredResultWrapper注解忽略掉自动包装
3.第三种:直接使用ResultWrapper来自己封装结果