[Spring cloud 一步步实现广告系统] 4. 通用代码模块设计
程序员文章站
2022-05-16 11:41:32
一个大的系统,在代码的复用肯定是必不可少的,它能解决: 1. 统一的响应处理(可以对外提供统一的响应对象包装) 2. 统一的异常处理(可以将业务异常统一收集处理) 3. 通用代码定义、配置定义(通用的配置信息放在统一的代码管理中,便于维护和更新) 创建项目 POM文件 项目结构 vo (统一响应对象 ......
一个大的系统,在代码的复用肯定是必不可少的,它能解决:
- 统一的响应处理(可以对外提供统一的响应对象包装)
- 统一的异常处理(可以将业务异常统一收集处理)
- 通用代码定义、配置定义(通用的配置信息放在统一的代码管理中,便于维护和更新)
创建项目
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
具体可参考:
- before(方法执行前)
- annotation
- config
- exception
- utils
-
export
通用响应编码
- 创建通用返回对象
/** * @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; } }
- 在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
进行异常处理
- 创建统一异常拦截类
/** * 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; } }
- 创建通用异常类
/** * 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 数据流
- 新增
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()); } }
做一个好人。