基于spring boot,如何自己动手封装一个接口响应的Result,以及一个starter

基于spring boot,如何自己动手封装一个接口响应的ResultBean的starter

相信大家在开发中都有这样的操作,将查询到数据放在ResultBean.setData里面,还包括状态码,message,及一些业务异常等。然后给上一个@ResponseBody以json数据的格式返回给前端。几乎每个接口都都setData,setCode,setMessage的操作,这些操作也是相当的繁琐。为何不能给一个注解就将这些操作自动帮我们做了呢?

废话不多说,直接上代码

这是一个类似于ResultBean的接口,实现这个接口

package annotation;


import utils.JsonUtils;

import java.io.Serializable;

/**
 * @ClassName Result
 * @Description TODO
 * @Author DL
 * @Date 2019/6/21 15:40
 * @Version 1.0
 */
public interface Result<T> extends Serializable {
    String getCode();

    void setCode(String var1);

    String getMsg();

    void setMsg(String var1);

    T getData();

    void setData(T var1);

    default String toJson() {//default是java8的新特性,不知道的可以去百度一下

        return JsonUtils.objectToJson(this);//这个方法是将这个对象转换成json字符串
    }
}

Result接口实现类

package annotation;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.util.StringUtils;


/**
 *@ClassName MyResult
 *@Description TODO
 *@Author DL
 *@Date 2019/7/16 15:50    
 *@Version 1.0
 */
public class MyResult<T> implements Result<T> {
    private static final long serialVersionUID = 874200365941306385L;
    private String code;
    private String msg;
    private T data;

    public MyResult() {
    }

    public MyResult(String code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public MyResult(MyResultCode myResultCode) {
        this.code = myResultCode.code();
        this.msg = myResultCode.message();
    }

    public MyResult(MyResultCode myResultCode, T data) {
        this.code = myResultCode.code();
        this.msg = myResultCode.message();
        this.data = data;
    }

    public MyResult(T data) {
        this.code = MyResultCode.SUCCESS.code();
        this.msg = MyResultCode.SUCCESS.message();
        this.data = data;
    }

    public MyResult(MyException myException, String additionalMessage) {
        this.code = myException.getCode();
        this.msg = StringUtils.isEmpty(additionalMessage) ? myException.getMsg() : myException.getMsg().concat(",").concat(additionalMessage);
    }

    @JsonIgnore
    public boolean isSuccess() {
        return MyResultCode.SUCCESS.code().equals(this.code);
    }

    @Override
    public String getCode() {
        return this.code;
    }

    @Override
    public void setCode(String code) {
        this.code = code;
    }

    @Override
    public String getMsg() {
        return this.msg;
    }

    @Override
    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public T getData() {
        return this.data;
    }

    @Override
    public void setData(T data) {
        this.data = data;
    }
}

自定义的异常

package annotation;

/**
 *@ClassName MyException
 *@Description TODO
 *@Author DL
 *@Date 2019/7/16 15:58    
 *@Version 1.0
 */

public class MyException extends RuntimeException implements Result<String> {
    private static final long serialVersionUID = 194906846739586856L;
    private final String code;
    private final String msg;

    public MyException(MyResultCode myResultCode) {
        this.code = myResultCode.code();
        this.msg = myResultCode.message();
    }

    public MyException(Result<?> result) {
        this.code = result.getCode();
        this.msg = result.getMsg();
    }

    public MyException(String code, String message) {
        this.code = code;
        this.msg = message;
    }

    public MyException(MyResultCode myResultCode, Throwable cause) {
        super(cause);
        this.code = myResultCode.code();
        this.msg = myResultCode.message();
    }

    public MyException(String code, String message, Throwable cause) {
        super(cause);
        this.code = code;
        this.msg = message;
    }

    @Override
    public String getMsg() {
        return this.msg;
    }

    @Override
    public String getCode() {
        return this.code;
    }

    @Override
    public String getData() {
        return null;
    }

    @Override
    public void setCode(String code) {
    }

    @Override
    public void setMsg(String msg) {
    }

    @Override
    public void setData(String data) {
    }
}

自己定义的注解,这个注解用在controller里面返回数据的时候

package annotation;

import java.lang.annotation.*;

/**
 * @ClassName MyResponse
 * @Description TODO
 * @Author DL
 * @Date 2019/6/21 15:36
 * @Version 1.0
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyResponse {
    Class<? extends Result> value() default MyResult.class;
}

这个是一些常用的状态码,和一些状态码所对应的描述的一个枚举类

package annotation;

/**
 *@ClassName MyResultCode
 *@Description TODO
 *@Author DL
 *@Date 2019/7/16 15:57    
 *@Version 1.0
 */
public enum  MyResultCode {
    /**
     *
     */
    SUCCESS("0", "success"),
    /**
     *
     */
    BAD_REQUEST("505-00-00-40000", "bad request"),
    /**
     *
     */
    REQUEST_ID_IS_NULL("505-00-00-40001", "request id is null"),
    PARAM_IS_INVALID("505-00-00-40002", "param is invalid"),
    PARAM_IS_BLANK("505-00-00-40003", "param is blank"),
    PARAM_TYPE_BIND_ERROR("505-00-00-40004", "param type bind error"),
    UNSUPPORTED_RESPONSE_TYPE("505-00-00-40005", "unsupported response type"),
    GATEWAY_UNKNOWN_EXCEPTION("505-00-00-40006", "gateway unknown exception"),
    USER_ID_NOT_FOUND("505-00-00-40011", "user id not found"),
    USER_NAME_NOT_FOUND("505-00-00-40012", "user name not found"),
    USER_NAME_IS_REGISTERED("505-00-00-40013", "user name is registered"),
    USER_NAME_CANNOT_CHANGE("505-00-00-40014", "user name cannot change"),
    PHONE_NUMBER_IS_REGISTERED("505-01-00-40015", "phone number is registered"),
    INVALID_GRANT("505-00-00-40022", "invalid grant"),
    UNSUPPORTED_GRANT_TYPE("505-00-00-40023", "unsupported grant type"),
    UNAUTHORIZED("505-00-00-40100", "unauthorized"),
    ACCESS_TOKEN_IS_NULL("505-00-00-40102", "access token is null"),
    ACCESS_TOKEN_EXPIRED("505-00-00-40103", "access token expired"),
    ACCESS_TOKEN_INVALID("505-00-00-40104", "access token invalid"),
    UNAUTHORIZED_USER("505-00-00-40110", "unauthorized user"),
    INVALID_USER("505-00-00-40111", "invalid user"),
    USER_LOGIN_FAILURE("505-00-00-40112", "user login failuer"),
    USER_NAME_ERROR("505-00-00-40113", "user name error"),
    USER_PASSWORD_ERROR("505-00-00-40114", "user password error"),
    USER_IS_NOT_LOGIN("505-00-00-40115", "user is not login"),
    UNAUTHORIZED_CLIENT("505-00-00-40120", "unauthorized client"),
    INVALID_CLIENT("505-00-00-40121", "invalid client"),
    CLIENT_ID_ERROR("505-00-00-40122", "client id error"),
    CLIENT_SECRET_ERROR("505-00-00-40123", "client secret error"),
    CLIENT_IS_NOT_LOGIN("505-00-00-40124", "client is not login"),
    CLIENT_LOGIN_FAILURE("505-00-00-40125", "client login failuer"),
    ACCESS_TOKEN_NO_AUTHORITY("505-00-00-40301", "access token no authority"),
    ACCESS_IP_NO_AUTHORITY("505-00-00-40302", "access ip no authority"),
    ACCESS_TIMES_EXCESSIVE("505-00-00-40303", "access times excessive"),
    INSUFFICIENT_SCOPE("505-00-00-40304", "insufficient scope"),
    ACCESS_DENIED("505-00-00-40305", "access denied"),
    INSUFFICIENT_AUTHENTICATION("505-00-00-40306", "insufficient authentication"),
    INTERFACE_ADDRESS_NOT_FOUND("505-00-00-40400", "interface address not found"),
    SERVICE_ADDRESS_NOT_FOUND("505-00-00-40401", "service address not found"),
    INTERFACE_REQUEST_TIMEOUT("505-00-00-40402", "interface request timeout"),
    METHOD_NOT_ALLOWED("505-00-00-40501", "method not allowed"),
    UNSUPPORTED_MEDIA_TYPE("505-00-00-41500", "unsupported media type"),
    SYSTEM_INNER_ERROR("505-00-00-50000", "system inner error"),
    SYSTEM_BUSY_NOW("505-00-00-50001", "system is busy now");

    private String code;
    private String message;

    private MyResultCode(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public String code() {
        return this.code;
    }

    public String message() {
        return this.message;
    }

    @Override
    public String toString() {
        return this.name();
    }
}

ok,下面我们先来一个拦截器,计算一下这个接口的响应时间(不知道拦截器是啥的,干嘛用的,自行百度哈)

package handler;

import annotation.MyResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 *@ClassName ResponseResultInterceptor
 *@Description TODO
 *@Author DL
 *@Date 2019/7/16 15:40    
 *@Version 1.0
 */
@Component
public class ResponseResultInterceptor implements HandlerInterceptor {
    public static final String RESPONSE_RESULT = "RESPONSE-RESULT";
    private static final String REQUEST_TIME = "REQUEST-TIME";
    private static final Logger LOGGER = LoggerFactory.getLogger(ResponseResultInterceptor.class);

    public ResponseResultInterceptor() {

    }
    //方法执行前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod)handler;
            Class<?> clazz = handlerMethod.getBeanType();//拿到将要执行该方法的类
            Method method = handlerMethod.getMethod();//拿到将要执行的方法
            if (method.isAnnotationPresent(MyResponse.class)) {
            //判断这个方法是否有@MyResponse
                request.setAttribute("RESPONSE-RESULT", method.getAnnotation(MyResponse.class));
                request.setAttribute("REQUEST-TIME", System.currentTimeMillis());//执行方法前的当前时间的毫秒数,与执行完方法后的当前时间毫秒数相减就可以得到执行该方法接口的耗时了
            } else if (clazz.isAnnotationPresent(MyResponse.class)) {
            //判断这个类是否有@MyResponse
                request.setAttribute("RESPONSE-RESULT", clazz.getAnnotation(MyResponse.class));
                request.setAttribute("REQUEST-TIME", System.currentTimeMillis());
            }
        }

        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    }
     //方法执行后
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod)handler;
            Class<?> clazz = handlerMethod.getBeanType();
            Method method = handlerMethod.getMethod();
            if (method.isAnnotationPresent(MyResponse.class) || clazz.isAnnotationPresent(MyResponse.class)) {
                String requestID = request.getHeader("requestId");
                int statusCode = response.getStatus();
                long requestTime = ((Long)request.getAttribute("REQUEST-TIME")).longValue();
                if (statusCode != HttpStatus.OK.value()) {
                    LoggerFactory.getLogger(clazz).error("RequestID: {}, Method: {}, Response Time: {}ms, HttpStatus: {}", new Object[]{requestID, method.getName(), System.currentTimeMillis() - requestTime, statusCode, ex});
                } else {
                    LoggerFactory.getLogger(clazz).info("RequestID: {}, Method: {}, Response Time: {}ms", new Object[]{requestID, method.getName(), System.currentTimeMillis() - requestTime});
                }
            }
        }

    }
}

ok,下面我着重介绍一下这个类ResponseBodyAdvice,这个类是spring boot提供的一个类,这个类拦截了 接口 的返回数据,可以对返回数据进行封装,这样可以保持一个统一的模板格式给前端,易于前端处理,同时,简化后端每个接口都需要手动构建返回格式的维护等。这正是我们想要的

package handler;


import annotation.MyResponse;
import annotation.MyResult;
import annotation.MyResultCode;
import annotation.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 *@ClassName ResponseResultHandler
 *@Description TODO
 *@Author DL
 *@Date 2019/6/25 9:14    
 *@Version 1.0
 */
@ControllerAdvice
@ConditionalOnBean({ResponseResultInterceptor.class})//这个注解表示只有ResponseResultInterceptor注入在spring容器中,该类才会被注入
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
    private static final Logger LOGGER = LoggerFactory.getLogger(ResponseResultHandler.class);
    //注意,先执行这个方法,且必须返回true下面的方法才会执行
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        MyResponse response= (MyResponse)((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getAttribute("RESPONSE-RESULT");
        return response!=null;
      
    }


    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        HttpServletRequest httpRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        MyResponse myResponse = (MyResponse)httpRequest.getAttribute("RESPONSE-RESULT");
        Object objBuffer = null;

        try {
            ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse().setHeader("requestId", httpRequest.getHeader("requestId"));
            Result result = (Result)myResponse.value().newInstance();
            result.setCode(MyResultCode.SUCCESS.code());
            result.setMsg(MyResultCode.SUCCESS.message());
            result.setData(o);//这个o就是我们返回的数据放在data里面统一封装
            if (!(o instanceof String) && !aClass.isAssignableFrom(StringHttpMessageConverter.class)) {
                if (o instanceof Result) {
                    objBuffer = o;
                } else {
                    objBuffer = result;
                }
            } else {

                objBuffer = result.toJson();
            }
        } catch (IllegalAccessException | InstantiationException  var11) {
            objBuffer = new MyResult(MyResultCode.SYSTEM_INNER_ERROR);
            LOGGER.error("BeforeBodyWrite got failed!", var11);
        }

        return objBuffer;
    }

}

好的,到这里为止我们就已经把返回的数据封装在Result里面了,没有异常的情况下,code为0,message为success,data里面为我们任何想要返回给前端的数据。但是如果我们要抛出业务异常呢?这里我们就将用到springmvc的全局异常处理。

package handler;


import annotation.MyException;
import annotation.MyResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 *@ClassName GlobalExceptionHandlerImpl
 *@Description TODO
 *@Author DL
 *@Date 2019/6/26 15:51    
 *@Version 1.0
 */
@RestControllerAdvice//这个注解就是@ResponseBody和@ControllerAdvice的合体
@ConditionalOnBean({ResponseResultInterceptor.class})
public class GlobalExceptionHandlerImpl {
    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandlerImpl.class);

    @ExceptionHandler(value = {MyException.class})//当代码中抛出MyException异常时就会执行这个方法
    public MyResult<Object> handleSaeException(MyException myException, HttpServletRequest request) {

        LOGGER.error(myException.getCode(),myException.getMsg());
        return new MyResult(myException.getCode(), myException.getMsg(), (Object)null);
    }
}

到这里我们还差最后一步,添加拦截器在springboot中。

package configure;

import handler.ResponseResultInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 *@ClassName InterceptorConfig
 *@Description TODO
 *@Author DL
 *@Date 2019/7/16 15:39    
 *@Version 1.0
 */
@Configuration
@ConditionalOnBean({ResponseResultInterceptor.class})
public class InterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private ResponseResultInterceptor responseResultInterceptor;

    public InterceptorConfig() {
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        String apiUri = "/**";//这里我们拦截所有的请求
        registry.addInterceptor(this.getResponseResultInterceptor()).addPathPatterns(new String[]{apiUri});
    }

    public ResponseResultInterceptor getResponseResultInterceptor() {
        return this.responseResultInterceptor;
    }

    public void setResponseResultInterceptor(ResponseResultInterceptor responseResultInterceptor) {
        this.responseResultInterceptor = responseResultInterceptor;
    }

}

这个是json转换的工具类

package utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.IOException;

/**
 *@ClassName JsonUtils
 *@Description TODO
 *@Author DL
 *@Date 2019/7/16 16:05    
 *@Version 1.0
 */
public class JsonUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtils.class);
    private static ObjectMapper objectMapper = new ObjectMapper();

    protected JsonUtils() {
    }

    public static String objectToJson(Object object) {
        String ret = null;
        if (object != null) {
            try {
                ret = getObjectMapper().writeValueAsString(object);
            } catch (JsonProcessingException var3) {
                LOGGER.error("Object to json failed!", var3);
            }
        }

        return ret;
    }

    public static <T> T jsonToObject(String json, Class<T> clazz) {
        T ret = null;
        if (!StringUtils.isEmpty(json)) {
            try {
                ret = getObjectMapper().readValue(json, clazz);
            } catch (IOException var4) {
                LOGGER.error("Json {} to object failed!", json, var4);
            }
        }

        return ret;
    }

    public static <T> T jsonToObject(String json, TypeReference<?> typeReference) {
        T ret = null;
        if (!StringUtils.isEmpty(json)) {
            try {
                ret = getObjectMapper().readValue(json, typeReference);
            } catch (IOException var4) {
                LOGGER.error("Json {} to object failed!", json, var4);
            }
        }

        return ret;
    }

    public static <T> T toObject(String content, Class<?> collectionClass, Class... elementClasses) throws Exception {
        if (StringUtils.isEmpty(content)) {
            return null;
        } else {
            try {
                JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
                return objectMapper.readValue(content, javaType);
            } catch (Exception var4) {
                var4.printStackTrace();
                return null;
            }
        }
    }

    public static <T> boolean canDeserialize(String json, Class<T> clazz) {
        boolean flag = true;

        try {
            (new ObjectMapper()).readValue(json, clazz);
        } catch (IOException var4) {
            flag = false;
        }

        return flag;
    }

    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    public static void setObjectMapper(ObjectMapper objectMapper) {
        objectMapper = objectMapper;
    }

    static {
        getObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }
}

到这里为止,基本上我们就大功告成了。
但是我有想把他像starter一样,弄一个开关。在properties里面给一个配置项,就可以让这个注解生效,或者不生效。怎么做呢?
ok,第一步,将上述的所有类在项目里 通过mvn install package打包到仓库
maven配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.dl.myresponse</groupId>
    <artifactId>my-response</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <!-- spring boot version -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath />
    </parent>
    <properties>
        <!-- sourceEncoding -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- outputEncoding -->
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- java version -->
        <java.version>1.8</java.version>
        <log4j.version>2.11.1</log4j.version>
        <slf4j.version>1.7.25</slf4j.version>
        <disruptor.version>3.3.6</disruptor.version>
        <jackson.version>2.9.6</jackson.version>
    </properties>

<dependencies>

    <!-- spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-json</artifactId>
        <version>2.1.0.RELEASE</version>
    </dependency>

    <!-- validation-api -->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>
    <!-- javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-web</artifactId>
        <version>${log4j.version}</version>
    </dependency>
</dependencies>
    <build>
        <plugins>
            <!-- maven plugin for deploy -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <configuration>
                    <attach>true</attach>
                </configuration>
                <executions>
                    <!-- delete attach-sources -->
                    <execution>
                        <id>attach-sources</id>
                        <phase>package</phase>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

就像这样,就表示打包成功了
这样就表示打包成功了。

第二步,新起一个springboot项目maven配置如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.dl.spring.boot</groupId>
    <artifactId>my-response-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.1.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
        <version>2.1.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>2.1.3.RELEASE</version>
    </dependency>

  <!--  <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
        <version>2.0.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>2.0.4.RELEASE</version>
    </dependency>-->
    <-- 引用刚才打好的包到新的项目-->
    <dependency>
        <groupId>com.dl.myresponse</groupId>
        <artifactId>my-response</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

</dependencies>

</project>

新建一个配置类

package config;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 *@ClassName MyResponseProperties
 *@Description TODO
 *@Author DL
 *@Date 2019/7/18 16:36    
 *@Version 1.0
 */
@ConfigurationProperties(prefix = "dl.response")//这个注解表示获取properties配置文件的属性,前缀为dl.response
public class MyResponseProperties {
    private String enabled;

    public String getEnabled() {
        return enabled;
    }

    public void setEnabled(String enabled) {
        this.enabled = enabled;
    }
}

再建一个注入bean的配置类

package config;

import configure.InterceptorConfig;
import handler.ResponseResultHandler;
import handler.ResponseResultInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *@ClassName MyResponseAutoConfiguration
 *@Description TODO
 *@Author DL
 *@Date 2019/7/19 14:44    
 *@Version 1.0
 */
@Configuration
@EnableConfigurationProperties(MyResponseProperties.class)
public class MyResponseAutoConfiguration {

    @Bean
    @ConditionalOnProperty(prefix = "dl.response",name="enabled",havingValue = "true")//这个注解就表示配置文件中有dl.response.enabled=true 才能注入注入这个bean,没有或者不等于true则不注入
    public ResponseResultInterceptor responseResultInterceptor(){

    return new ResponseResultInterceptor();

    }
    @ConditionalOnBean(ResponseResultInterceptor.class)
    @Bean
    public InterceptorConfig interceptorConfig(){
    return  new InterceptorConfig();
    }
    @ConditionalOnBean(ResponseResultInterceptor.class)
    @Bean
    public ResponseResultHandler responseResultHandler(){
        return new ResponseResultHandler();
    }



}

第三步,在resources目录下新建一个META-INF目录,再在这个目录下建一个spring.factories文件,
文件内容为

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
config.MyResponseAutoConfiguration

多个配置类的话以逗号分隔,换行加\

最后同样用mvn install package命令打包。
到这里为止就大功告成了。

在其它项目里引用
自己打好的starter包就可以了

<dependency>
			<groupId>com.dl.spring.boot</groupId>
			<artifactId>my-response-spring-boot-starter</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

引用后,在配置文件里输入dl. idea会有提示的哦!
在这里插入图片描述我这里用的是yml同样的会有提示

写个方法测试一下
在这里插入图片描述
这样就会返回我们封装好的数据结构了
在这里插入图片描述
到这里就全部结束了,本人第一次写博客,有不对的地方欢迎大家指出来。不喜勿喷哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值