前后端分离

按照现在的趋势,前后端分离几乎已经是业界对开发和部署方式所达成的一种共识。所谓的前后端分离,并不是传统行业中的按部门划分,一部分人只做前端(HTML/CSS/JavaScript等等),另一部分人只做后端(或者叫服务端),因为这种方式是不工作的:比如很多团队采取了后端的模板技术(JSP, FreeMarker, ERB等等),前端的开发和调试需要一个后台Web容器的支持,从而无法将前后端开发和部署做到真正的分离。

通常,前后端分别有着自己的开发流程,构建工具,测试等。做前端的谁也不会想要用Maven或者Gradle作为构建工具,同样的道理,做后端的谁也不会想要用Grunt或者Gulp作为构建工具。前后端仅仅通过接口来协作,这个接口可能是JSON格式的RESTFul的接口,也可能是XML的,重点是后台只负责数据的提供和计算,而完全不处理展现。而前端则负责拿到数据,组织数据并展现的工作。这样结构清晰,关注点分离,前后端会变得相对独立并松耦合。但是这种想法依然还是很理想化,前后端集成往往还是一个很头痛的问题。比如在最后需要集成的时候,我们才发现最开始商量好的数据结构发生了变化,而且这种变化往往是在所难免的,这样就会增加大量的集成时间。

归根结底,还是前端或者后端感知到变化的时间周期太长,不能“及时协商,尽早解决”,最终导致集中爆发。怎么解决这个问题呢?我们需要提前协商好一些契约,并将这些契约作为可以被测试的中间产品,然后前后端都通过自动化测试来检验这些契约,一旦契约发生变化,测试就会失败。这样,每个失败的测试都会驱动双方再次协商,有效的缩短了反馈周期,并且降低集成风险。具体的实践方式,请参加我同事的一篇博文,“前后端分离了,然后呢?”http://icodeit.org/2015/06/whats-next-after-separate-frontend-and-backend/。

不过,仅仅靠纪律是不够的,还需要通过工具的辅助来提高效率。下面,我们就来看一下,一个API设计工具——Swagger,将如何帮助我们更好的实现“前后端分离”。

两款更符合前后分离的

swagger-bootstrap-ui:https://gitee.com/xiaoym/swagger-bootstrap-ui
swagger-mg-ui:https://gitee.com/zyplayer/swagger-mg-ui

封装swagger依赖,方便使用
pom核心依赖

<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>
  <parent>
    <groupId>com.open.capacity</groupId>
    <artifactId>inner-intergration</artifactId>
    <version>2.0.1</version>
  </parent>
  <artifactId>swagger-spring-boot-starter</artifactId>
  <description>API文档支撑</description>
  <properties>
      <swagger.version>2.9.2</swagger.version>
      <swagger.m.version>1.0.6</swagger.m.version>
  </properties>

  <dependencies>

        <!-- swagger -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-bean-validators</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.1</version>
        </dependency>
        <dependency>
            <groupId>com.zyplayer</groupId>
            <artifactId>swagger-mg-ui</artifactId>
            <version>${swagger.m.version}</version>
        </dependency>
  </dependencies>

</project>

使用方法

<!-- swagger -->
          <dependency>
              <groupId>com.open.capacity</groupId>
              <artifactId>swagger-spring-boot-starter</artifactId>
          </dependency>

SwaggerConfig 自动形成swagger文档核心代码

以认证中心代码为例



java工程开放接口给别的工程使用_Source

认证中心代码

@Component
@Configuration
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {

    @Bean
    public Docket createRestApi() {

        ParameterBuilder tokenPar = new ParameterBuilder();
        List<Parameter> pars = new ArrayList<>();
        tokenPar.name("Authorization").description("令牌").
        modelRef(new ModelRef("string")).
        parameterType("header").required(false).build();

        ParameterBuilder clientPar = new ParameterBuilder();
        clientPar.name("client_id").description("应用ID").
        modelRef(new ModelRef("string")).
        parameterType("header").required(false).build();

        ParameterBuilder secretPar = new ParameterBuilder();
        secretPar.name("client_secret").description("应用密钥").
        modelRef(new ModelRef("string")).
        parameterType("header").required(false).build();

        pars.add(tokenPar.build());
        pars.add(clientPar.build()); 
        pars.add(secretPar.build()); 

        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
                // .apis(RequestHandlerSelectors.basePackage("com.open.capacity"))
                .apis(RequestHandlerSelectors.any())
                .paths( input ->
                        PathSelectors.regex("/oauth/client.*").apply(input) ||
                        PathSelectors.regex("/oauth/user.*").apply(input)   ||
                        PathSelectors.regex("/oauth/get.*").apply(input)    ||
                        PathSelectors.regex("/oauth/userinfo.*").apply(input)     || 
                        PathSelectors.regex("/oauth/remove.*").apply(input) || 
                        PathSelectors.regex("/oauth/refresh/token.*").apply(input)||
                        PathSelectors.regex("/oauth/token/list.*").apply(input)||
                        PathSelectors.regex("/clients.*").apply(input)||
                        PathSelectors.regex("/services.*").apply(input)||
                        PathSelectors.regex("/redis.*").apply(input)

                      )
                // .paths(PathSelectors.any())
                .build().globalOperationParameters(pars);
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("认证中心swagger接口文档").description("认证中心swagger接口文档").version("1.0").build();
    }

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/");
        resolver.setSuffix(".html");
        return resolver;

    }

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        return messageSource;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
//        super.addResourceHandlers(registry);
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

}

访问网关swagger-ui

http://127.0.0.1:9200/swagger-ui.html



java工程开放接口给别的工程使用_spring_02

image

访问认证中心swagger-ui

http://127.0.0.1:8000/doc.html(http://127.0.0.1:8000/api-auth/doc.html)

注意查看认证中心代码



java工程开放接口给别的工程使用_java工程开放接口给别的工程使用_03

image

如果有上下文路径
## 接口地址 http://127.0.0.1:8000/api-auth/doc.html



java工程开放接口给别的工程使用_java工程开放接口给别的工程使用_04

image

java工程开放接口给别的工程使用_java工程开放接口给别的工程使用_05

image

访问用户中心swagger-ui



java工程开放接口给别的工程使用_spring_06

image

企业微服务开放平台 ,历经多家公司生产考验

  • 基于layui前后端分离的企业级微服务架构
  • 兼容spring cloud netflix & spring cloud alibaba
  • 优化Spring Security内部实现,实现API调用的统一出口和权限认证授权中心
  • 提供完善的企业微服务流量监控,日志监控能力
  • 提供完善的压力测试方案
  • 提供完善的微服务部署方案

项目演示地址

http://59.110.164.254:8066/login.html 用户名/密码:admin/admin

项目监控地址

http://47.98.236.203:3000 用户名/密码:admin/1q2w3e4r