欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

[Spring cloud 一步步实现广告系统] 4. 通用代码模块设计

程序员文章站 2022-05-16 11:41:32
一个大的系统,在代码的复用肯定是必不可少的,它能解决: 1. 统一的响应处理(可以对外提供统一的响应对象包装) 2. 统一的异常处理(可以将业务异常统一收集处理) 3. 通用代码定义、配置定义(通用的配置信息放在统一的代码管理中,便于维护和更新) 创建项目 POM文件 项目结构 vo (统一响应对象 ......

一个大的系统,在代码的复用肯定是必不可少的,它能解决:

  1. 统一的响应处理(可以对外提供统一的响应对象包装)

[Spring cloud 一步步实现广告系统] 4. 通用代码模块设计

  1. 统一的异常处理(可以将业务异常统一收集处理)

[Spring cloud 一步步实现广告系统] 4. 通用代码模块设计

  1. 通用代码定义、配置定义(通用的配置信息放在统一的代码管理中,便于维护和更新)

创建项目mscx-ad-common

pom文件

<?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">
    <parent>
        <artifactid>mscx-ad</artifactid>
        <groupid>com.sxzhongf</groupid>
        <version>1.0-snapshot</version>
        <relativepath>../pom.xml</relativepath>
    </parent>
    <modelversion>4.0.0</modelversion>
    <packaging>jar</packaging>

    <groupid>com.sxzhongf</groupid>
    <artifactid>mscx-ad-common</artifactid>
    <version>1.0-snapshot</version>
    <name>common-service</name>
    <description>公共逻辑 and 帮助类</description>

    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>
        <!-- fastjson是阿里巴巴的开源json解析库,它可以解析json格式的字符串,支持将java bean序列化为json字符串,也可以从json字符串反序列化到javabean -->
        <dependency>
            <groupid>com.alibaba</groupid>
            <artifactid>fastjson</artifactid>
            <version>1.2.58</version>
        </dependency>
        <!--  -->
        <dependency>
            <groupid>commons-codec</groupid>
            <artifactid>commons-codec</artifactid>
        </dependency>
        <dependency>
            <groupid>org.apache.commons</groupid>
            <artifactid>commons-lang3</artifactid>
        </dependency>
    </dependencies>
        <!--maven编译插件-->
    <build>
        <plugins>
            <plugin>
                <groupid>org.springframework.boot</groupid>
                <artifactid>spring-boot-maven-plugin</artifactid>
            </plugin>
        </plugins>
    </build>
</project>

项目结构

  • vo (统一响应对象package)

  • advice (bean 增强package )

    spring支持五种类型的增强或通知(advice)
    • before(方法执行前) org.apringframework.aop.methodbeforeadvice
    • afterreturning(方法返回后) org.springframework.aop.afterreturningadvice
    • after-throwing(异常抛出后) org.springframework.aop.throwsadvicearround环绕,即方法前后 org.aopaliance.intercept.methodinterceptor
      引介,不常用 org.springframework.aop.introductioninterceptor
      具体可参考:
  • annotation
  • config
  • exception
  • utils
  • export

    通用响应编码
  1. 创建通用返回对象
/**
* @data是下属注解的组合注解
* 
* @see getter
* @see setter
* @see requiredargsconstructor
* @see tostring
* @see equalsandhashcode
* @see lombok.value 
*/
@data
@noargsconstructor //无参构造函数
@allargsconstructor //全参构造函数
public class commonresponse<t> implements serializable {
   private integer code = 0;
   private string message = "success";
   /**
    * 具体的数据对象信息
    */
   private t data;

   public commonresponse(integer code, string message) {
       this.code = code;
       this.message = message;
   }

   public commonresponse(t data) {
       this.data = data;
   }
}
  1. 在advice包中实现对响应的统一拦截com.sxzhongf.ad.common.advice.commonresponsedataadvice,参考 responsebodyadvice, restcontrolleradvice 可查看源码org.springframework.web.servlet.mvc.method.annotation.responsebodyadvice
   @restcontrolleradvice
   public class commonresponsedataadvice implements responsebodyadvice<object> {
   
       /**
        * 判断是否需要对响应进行处理
        *
        * @return false -> 不处理,true -> 处理
        */
       @override
       public boolean supports(methodparameter methodparameter, class<? extends httpmessageconverter<?>> convertertype) {
   //
   //        //获取当前处理请求的controller的方法
   //        string methodname = methodparameter.getmethod().getname().tolowercase();
   //        // 不拦截/不需要处理返回值 的方法
   //        string method = "login"; //如登录
   //        //不拦截
   //        return !method.equals(methodname);
   
           // 如果类上标记了@ignoreresponseadvice,则不拦截
           if (methodparameter.getdeclaringclass().isannotationpresent(ignoreresponseadvice.class)) {
               return false;
           }
   
           // 如果方法上标记了@ignoreresponseadvice,则不拦截
           if (methodparameter.getmethod().isannotationpresent(ignoreresponseadvice.class)) {
               return false;
           }
   
           //对响应进行处理,执行beforebodywrite方法
           return true;
       }
   
       /**
        * 目的 拦截commonresponse
        *
        * @param body 原始的controller需要返回的数据
        */
       @override
       public object beforebodywrite(object body, methodparameter returntype,
                                     mediatype selectedcontenttype,
                                     class<? extends httpmessageconverter<?>> selectedconvertertype,
                                     serverhttprequest request,
                                     serverhttpresponse response) {
   
           commonresponse<object> commonresponse = new commonresponse<>();
   
           if (null == body) {
               return commonresponse;
           } else if (body instanceof commonresponse) {
               commonresponse = (commonresponse<object>) body;
           } else {
               commonresponse.setdata(body);
           }
           return commonresponse;
       }
   }

我们在annotation包下面添加一个注解com.sxzhongf.ad.common.annotation.ignoreresponseadvice,用它来标柱是否需要支持上面的统一返回拦截。

   /**
    * ignoreresponseadvice for 标示需要忽略拦截动作
    *
    * @author <a href="mailto:magicianisaac@gmail.com">isaac.zhang</a>
    */
   //elementtype.type 表示该注解可用于class
   //elementtype.method 表示可用于方法
   @target({elementtype.type, elementtype.method})
   @retention(retentionpolicy.runtime)
   public @interface ignoreresponseadvice {
   }
通用异常处理

异常处理也是统一的,那么同样就要使用到restcontrolleradvice,同时,需要使用的spring 的exceptionhandler进行异常处理

  1. 创建统一异常拦截类
/**
 * globalexceptionadvice for 全局统一异常拦截
 *
 * @author <a href="mailto:magicianisaac@gmail.com">isaac.zhang</a>
 * @see restcontrolleradvice
 * @see exceptionhandler
 */
@restcontrolleradvice
public class globalexceptionadvice {

    /**
     * 对 {@link adexception} 进行统一处理
     * {@link exceptionhandler}  对指定的异常进行拦截
     * 可优化:
     * 定义多种类异常,实现对应的异常处理,
     * 例如:
     * <ul>
     * <li>
     * 推广单元操作异常,抛出 adunitexception
     * </li>
     * <li>
     * binlog 解析异常,抛出 binlogexception
     * </li>
     * </ul>
     * 拦截spring exception 使用 {@link exceptionhandler}注解
     */
    @exceptionhandler(value = adexception.class)
    public commonresponse<string> handleradexception(httpservletrequest request, adexception ex) {
        commonresponse<string> response = new commonresponse<>(-1, "business error");
        response.setdata(ex.getmessage());
        return response;
    }
}
  1. 创建通用异常类
/**
 * adexception for 统一异常处理类
 *
 * @author <a href="mailto:magicianisaac@gmail.com">isaac.zhang</a>
 */
public class adexception extends exception {
    public adexception(string message) {
        super(message);
    }
}
通用配置信息

通过http消息转换器httpmessageconverter,实现对象转换,java object -> http 数据流

  1. 新增webconfiguration,我们通过实现org.springframework.web.servlet.config.annotation.webmvcconfigurer来定制和修改spring mvc的配置信息。
/**
 * webconfiguration for 对spring的配置和行为进行定制修改
 *
 * @author <a href="mailto:magicianisaac@gmail.com">isaac.zhang</a>
 * @see webmvcconfigurer
 */
@configuration
public class webconfiguration implements webmvcconfigurer {
    /**
     * 匹配路由请求规则
     */
    @override
    public void configurepathmatch(pathmatchconfigurer configurer) {

    }
    /**
     * 注册自定义的formatter 和 convert
     */
    @override
    public void addformatters(formatterregistry registry) {

    }
    /**
     * 添加静态资源处理器
     */
    @override
    public void addresourcehandlers(resourcehandlerregistry registry) {

    }
    /**
     * 添加自定义视图控制器
     */
    @override
    public void addviewcontrollers(viewcontrollerregistry registry) {

    }
    /**
     * 添加自定义方法参数处理器
     */
    @override
    public void addargumentresolvers(list<handlermethodargumentresolver> resolvers) {

    }
    /**
     * 配置消息转换器
     */
    @override
    public void configuremessageconverters(list<httpmessageconverter<?>> converters) {
        //清空所有转换器
        converters.clear();
        // java obj -> json obj (http header: application/json)
        converters.add(new mappingjackson2httpmessageconverter());
    }
}

做一个好人。