Springboot自定義starter解決統(tǒng)一項(xiàng)目規(guī)范

俗話說:“無規(guī)矩不成方圓”,在我們軟件開發(fā)過程中也是這樣的要求,特別是對大型項(xiàng)目必須制定諸多的開發(fā)規(guī)范,有的是通過文件制度的形式要求,有的是通過工程框架要求,我個人認(rèn)為要好的貫徹執(zhí)行只能靠工程框架約束,否則每個工程師對文件制度都有不同的認(rèn)識,長此以往這些規(guī)范制度就形同虛設(shè)了,而且通過工程框架約束還能夠通過一些檢查工具自動校驗(yàn),最大限度的降低了人為的偏差。
今天就不多說編碼的規(guī)范了,這個已經(jīng)是業(yè)界公認(rèn)的標(biāo)準(zhǔn)了,今天要介紹的是對公司大型項(xiàng)目如何通過工程框架來實(shí)現(xiàn)統(tǒng)一的規(guī)范約束。

實(shí)現(xiàn)統(tǒng)一規(guī)范的方案

  1. 統(tǒng)一結(jié)構(gòu)的工程腳手架
    這個是通過工程架構(gòu)約束的基礎(chǔ)能力,就如同蓋大樓一樣,主體結(jié)構(gòu)是大樓的基本體現(xiàn),要想快速有效的落實(shí)基礎(chǔ)架構(gòu),工程腳手架是必須的第一步。這里推薦的腳手架結(jié)構(gòu)是以項(xiàng)目為目標(biāo),功能為模塊的兩層結(jié)構(gòu),把每個模塊通用的部分放到項(xiàng)目層面,每個模塊本身只包含項(xiàng)目特有的結(jié)構(gòu)。


    腳手架項(xiàng)目結(jié)構(gòu)
  2. 以jar包封裝一些統(tǒng)一的規(guī)范能力
    項(xiàng)目中要用的統(tǒng)一能力可以通過集中封裝的方式集成到一些獨(dú)立分發(fā)的jar包中提供給項(xiàng)目的其他工程使用,這樣就把一些統(tǒng)一的規(guī)范集中管控,從而縮小了泛化的可能性,當(dāng)然同時也抑制了工程的自由度,這個要根據(jù)項(xiàng)目的實(shí)際情況做一個平衡。Springboot提供了更好的方式來實(shí)現(xiàn)這個目標(biāo),就是starter,這個也是本文重點(diǎn)介紹的方式。
  3. 以微服務(wù)方式提供黑箱服務(wù)
    將項(xiàng)目中通用的能力以微服務(wù)方式提供,對其他模塊的使用更加的隔離,微服務(wù)的優(yōu)勢和方法不在本文詳述,如果感興趣可以自行腦補(bǔ)。

自定義starter

Springboot通過starter方式提供了封裝更為精準(zhǔn)的獨(dú)立服務(wù)能力,讓使用方開箱即用。目前很多開源系統(tǒng)都提供了starter方式,這樣大大降低了我們使用這些優(yōu)秀開源系統(tǒng)的門檻,也極大提高了開發(fā)效率,那么我們項(xiàng)目自身是否也可以用這樣的方式來實(shí)現(xiàn)一些通用功能呢?答案是肯定的,而且過程也非常的簡單,讓原先以jar包分發(fā)的方式更加的優(yōu)雅和簡單。
starter工程和其他的Springboot工程結(jié)構(gòu)沒有什么區(qū)別,下面就把一些特殊的要求羅列一下。

  1. 命名規(guī)范
    1.1 官方命名空間(Springboot旗下項(xiàng)目)
    前綴:spring-boot-starter-
    模式:spring-boot-starter-{模塊名}
    舉例:spring-boot-starter-web、spring-boot-starter-jdbc
    1.2 自定義命名空間(非Springboot項(xiàng)目)
    后綴:-spring-boot-starter
    模式:{模塊}-spring-boot-starter
    舉例:mybatis-spring-boot-starter
  2. 必須引入的依賴包
    starter模式和以前的jar包模式的區(qū)別是配置裝配能力,也就是starter包可以自動從配置文件獲取項(xiàng)目本身的配置參數(shù),從而更靈活的適應(yīng)項(xiàng)目個性,那么就必須依賴這個包。
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
  1. 工程入口程序
    這個程序是取代普通Springboot工程的Application的,是配置獲取、bean裝配的入口。
@Slf4j
@Configuration
@EnableConfigurationProperties(BasicProperties.class)
@ConditionalOnClass(BasicService.class)
@ConditionalOnProperty(prefix = "myself.middle", value = "enabled", matchIfMissing = true)

public class BasicServiceAutoConfiguration {
    @Autowired
    private BasicProperties basicProperties;

    @Bean
    @ConditionalOnMissingBean(BasicService.class)
    public BasicService basicService(){
        log.info("中臺服務(wù)-基礎(chǔ)服務(wù)裝配開始...");
        log.info("運(yùn)行域:{}",basicProperties.getDomain());
        BasicService basicService=new BasicService();
        log.info("中臺服務(wù)-基礎(chǔ)服務(wù)裝配完成。");
        return basicService;
    }
}

這里指明獲取配置的類,需要實(shí)例化的bean等,這里裝配的bean在使用端就可以通過@Autowired的方式直接使用了,這些注解的詳細(xì)說明自行搜索,資料很多。
配置文件application.yml如下:

myself:
  middle:
    domain: bj.myself.middle
  1. 配置spring.factories,指明starter的主入口
    在resources目錄下建META-INF目錄,創(chuàng)建spinrg.factories文件,文件內(nèi)容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.myself.platform.middle.BasicServiceAutoConfiguration

AOP方式統(tǒng)一服務(wù)日志

原先實(shí)現(xiàn)統(tǒng)一日志都是放到每個工程中以AOP方式實(shí)現(xiàn),現(xiàn)在有了starter方式,就可以將公司的日志規(guī)范集中到這里來統(tǒng)一管理。

  1. 編寫Aspect類
    該類的實(shí)現(xiàn)和原先的方式?jīng)]有任何變化,直接放代碼如下:
@Aspect
@Component
@Slf4j
public class WebLogAspect {
    @Pointcut("execution(public * com.myself.platform.middle..web.*.*(..))")
    public void webLog(){}

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到請求,記錄請求內(nèi)容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 記錄下請求內(nèi)容
        log.info("開始服務(wù):{}", request.getRequestURL().toString());
        log.info("客戶端IP :{}" , request.getRemoteAddr());
        log.info("參數(shù)值 :{}",Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請求,返回內(nèi)容
        log.info("返回值 : {}" , ret);
    }
}
  1. starter裝載類添加AOP Bean方法
    AOP如果直接放置到Springboot工程中就可以直接生效,但是通過starter方式提供還得在裝載類中Bean化,這點(diǎn)要特別注意,否則不會生效。
@Slf4j
@Configuration
@EnableConfigurationProperties(BasicProperties.class)
@ConditionalOnClass(BasicService.class)
@ConditionalOnProperty(prefix = "myself.middle", value = "enabled", matchIfMissing = true)

public class BasicServiceAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean(WebLogAspect.class)
    public WebLogAspect webLogAspect(){
        log.info("中臺服務(wù)-統(tǒng)一web AOP裝配開始...");
        log.info("運(yùn)行域:{}",basicProperties.getDomain());
        WebLogAspect webLogAspect=new WebLogAspect();
        log.info("中臺服務(wù)-統(tǒng)一web AOP裝配完成。");
        return webLogAspect;
    }
}

發(fā)布

經(jīng)過以上步驟這個包含了AOP及統(tǒng)一功能的starter就開發(fā)完成了,執(zhí)行mvn install就可以部署到本地maven倉庫給其他項(xiàng)目使用了,如果要在全公司使用就通過mvn deploy部署到公司私有倉庫。

實(shí)際執(zhí)行效果

2019-12-12 17:29:13.736  INFO [user-base,,,] 1 --- [           main] c.s.p.m.BasicServiceAutoConfiguration    : 中臺服務(wù)-統(tǒng)一web AOP裝配開始...
2019-12-12 17:29:13.736  INFO [user-base,,,] 1 --- [           main] c.s.p.m.BasicServiceAutoConfiguration    : 運(yùn)行域:http://bj.myself.com
2019-12-12 17:29:13.736  INFO [user-base,,,] 1 --- [           main] c.s.p.m.BasicServiceAutoConfiguration    : 中臺服務(wù)-統(tǒng)一web AOP裝配完成。

看到AOP已經(jīng)Bean化了。

2019-12-13 09:58:15.007  INFO [user-base,1a66e1fde3654b29,dbaacc6e1b0dd547,true] 1 --- [nio-1010-exec-3] c.s.p.middle.service.WebLogAspect        : 開始服務(wù):http://172.16.15.229:1010/readUserinfo
2019-12-13 09:58:15.008  INFO [user-base,1a66e1fde3654b29,dbaacc6e1b0dd547,true] 1 --- [nio-1010-exec-3] c.s.p.middle.service.WebLogAspect        : 客戶端IP :172.16.15.229
2019-12-13 09:58:15.008  INFO [user-base,1a66e1fde3654b29,dbaacc6e1b0dd547,true] 1 --- [nio-1010-exec-3] c.s.p.middle.service.WebLogAspect        : 請求參數(shù) :org.apache.catalina.util.ParameterMap@22597edd
2019-12-13 09:58:15.008  INFO [user-base,1a66e1fde3654b29,dbaacc6e1b0dd547,true] 1 --- [nio-1010-exec-3] c.s.p.middle.service.WebLogAspect        : 參數(shù)值 :[61d4b219-e4e5-4c29-9688-b6759e3e6427]
2019-12-13 09:58:15.072  INFO [user-base,1a66e1fde3654b29,dbaacc6e1b0dd547,true] 1 --- [nio-1010-exec-3] c.s.p.middle.service.WebLogAspect        : 返回值 : ResponseData(code=0, message=成功, data={"avatarUrl":"fgjfgjghj","userName":"57547457","userId":"61d4b219-e4e5-4c29-9688-b6759e3e6427","email":"fghjfgjgh"})

可以看到AOP的統(tǒng)一日志已經(jīng)輸出。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容