Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
»ùÓÚFeignµÄ΢·þÎñµ÷ÓÃÖ®ÆõÔ¼²âÊÔ Spring Cloud Contract
 
  3894  次浏览      30
 2019-7-5
 
±à¼­ÍƼö:
±¾ÎÄÀ´×ÔÓÚ²©¿ÍרÀ¸£¬±¾ÎÄÖ÷Òª½éÉÜÁËÏû·ÑÕßÇý¶¯µÄÆõÔ¼²âÊÔ£¬´ÓÏû·ÑÕßÒµÎñʵÏֵĽǶȳö·¢£¬Çý¶¯³öÆõÔ¼£¬ÔÙ»ùÓÚÆõÔ¼£¬¶ÔÌṩÕßÑéÖ¤µÄÒ»ÖÖ²âÊÔ·½Ê½¡£

ΪʲôҪ×öÆõÔ¼²âÊÔ

¼ÙÉèÎÒÃÇÓÐÒ»¸öÓɶà¸ö΢·þÎñ×é³ÉµÄϵͳ£ºÈçͼ

Èç¹ûÎÒÃÇÏë²âÊÔÓ¦ÓÃv1£¬ÎÒÃÇ¿ÉÒÔ×öÒÔÏÂÁ½¼þÊÂÖ®Ò»£º

²¿ÊðËùÓÐ΢·þÎñ²¢Ö´Ðж˵½¶Ë²âÊÔ¡£

ÔÚµ¥Ôª/¼¯³É²âÊÔÖÐÄ£ÄâÆäËû΢·þÎñ¡£

Á½Õß¶¼ÓÐÆäÓŵ㣬µ«Ò²Óкܶàȱµã¡£

²¿ÊðËùÓÐ΢·þÎñ²¢Ö´Ðж˵½¶Ë²âÊÔ

Óŵ㣺

Ä£ÄâÉú²ú¡£

²âÊÔ·þÎñÖ®¼äµÄÕæÊµÍ¨ÐÅ¡£

ȱµã£º

Òª²âÊÔÒ»¸ö΢·þÎñ£¬ÎÒÃDZØÐ벿Êð6¸ö΢·þÎñ£¬¼¸¸öÊý¾Ý¿âµÈ¡£

ÔËÐÐʱ¼äºÜ³¤£¬Îȶ¨ÐԲÈÝÒ×ʧ°Ü¡£

·Ç³£ÄÑÒÔµ÷ÊÔ£¬ÒÀÀµ·þÎñ²»ÊÜ¿ØÖÆ¡£

ÔÚµ¥Ôª/¼¯³É²âÊÔÖÐÄ£ÄâÆäËû΢·þÎñ

Óŵ㣺

·Ç³£¿ìËٵķ´À¡£¬¼òµ¥Ò×Óá£

ËûÃÇûÓлù´¡ÉèʩҪÇó,ÈçDB£¬ÍøÂçµÈ¡£

ȱµã£º

Ä£Äâ²»¹»ÕæÊµ¡£

²¿·Ö³¡¾°²âÊÔ²»µ½¡£

ʹÓÃSpring Cloud Contractºó

ÈçÏ£º²âÊÔv1¾Í²»ÓÃÆô¶¯ÆäËü·þÎñÁË

ÆõÔ¼²âÊÔ£¨Contract£©

ÆõÔ¼²âÊÔ²½Öè

Spring Cloud ContractÆõÔ¼²âÊÔ´ó¸Å·ÖÈý¸ö²½Öè

producerÌṩ·þÎñµÄ¶¨ºÃ·þÎñ½Ó¿Ú£¨¼´ÆõÔ¼£©

Éú³Éstub£¬²¢¹²Ïí¸øÏû·Ñ·½£¬¿Éͨ¹ýmvn installµ½maven¿âÖÐ

consumerÏû·Ñ·½ÒýÓÃÆõÔ¼·þÎñ£¬½øÐм¯³É²âÊÔ

Server/Producer ·þÎñÌṩ¶Ë

¹¹¼ÜÒýÈë

ÔÚpom.xmlÖмÓÈëjar°üÒÀÀµ£¬·ÅÈëdependenciesÖÐ

<!--ÆõÔ¼²âÊÔ·þÎñÌṩ¶ËÒÀÀµ-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>

ÅäÖòå¼þ£¬·ÅÈëpluginsÖÐ


<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<!-- Don't forget about this value !! -->
<extensions>true</extensions>
<configuration>
<!-- MvcMockTestΪÉú³É±¾µØ²âÊÔ°¸ÀýµÄ»ùÀà -->
<baseClassForTests>com.springboot.services.producer


.MvcMockTest</baseClassForTests>
</configuration>
</plugin>

spring-cloud-contract-maven-pluginµÄʹÓýéÉÜ

spring-cloud-contract:help£º°ïÖú

spring-cloud-contract:convert£ºÔÚtarget/stubsÏ£¬¸ù¾Ý½«ÆõÔ¼Éú³ÉmappingÎļþ£¬ÓÃÓÚ´ò°üjarÎļþ£¬Ìṩhttp·þÎñ£¬¹©consumerʹÓÃ

spring-cloud-contract:generateStubs£ºÉú³ÉstubsµÄjar°ü£¬ÓÃÓÚ·ÖÏí¸øconsumerʹÓÃ

spring-cloud-contract:generateTests£º»ùÓÚcontractÉú³É·þÎñÆõÔ¼µÄ²âÊÔ°¸Àý£¬·þÎñʵÏÖÁËÆõÔ¼ºó£¬±£Ö¤ÊµÏÖÓëÆõÔ¼Ò»ÖÂ

spring-cloud-contract:run£ºÆô¶¯ÆõÔ¼·þÎñ£¬½«ÆõÔ¼±©Â¶Îªhttp server·þÎñ

spring-cloud-contract:pushStubsToScm£º½«ÆõÔ¼·ÅÖÃÔÚscmÖйÜÀí

ÐèÇó

¼ÙÉèÓÐÐèÇó producer·þÎñÐèÒªÌṩһ¸ö¶ÔÍâµÄ½Ó¿ÚGETÇëÇóµÄ½Ó¿Ú£¬²¢ÇÒ½ÓÊÕÒ»¸önameµÄ²ÎÊý£¬Èç

GET /hello?name=zhangsan£¬ÒªÇó·µ»Ø{"code": "000000","mesg": "´¦Àí³É¹¦"}

1. дController

×¢£º¶ÔÏóResult¶ÔÏó·â×°ÁË{"code": "000000","mesg": "´¦Àí³É¹¦"} Êý¾Ý

package com.springboot.services.producer.rest;
import com.springboot.cloud.common.core.entity.
vo.Result;
import org.springframework.web.bind.annotation.*;
import static org.apache.commons.lang.
RandomStringUtils.
randomNumeric;
@RestController
public class HelloController {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Result world(@RequestParam String name) {
return Result.success(name);
}

2. ±àдÆõÔ¼

ÔÚsrc/test/resources/contracts/HelloController.groovy ÖÐÔö¼ÓÆõÔ¼Îļþ£¨¿ÉÒÔÓжàÖÖ¸ñʽÈçgroovy ¡¢yaml¡¢£¬ÕâÀï²ÉÓÃgroovy£©

ÆõÔ¼ÊéдÈçÏ£º

Contract.make {
request {
method 'GET'
url('/hello') {
queryParameters {
parameter("name", "zhangsan")
}
}
}
response {
status 200
body("""
{
"code": "000000",
"mesg": "´¦Àí³É¹¦"
}
""")
headers {
header('Content-Type': 'application/json;charset=UTF-8')
}
}
}

3.Éú³Éstub jarÎļþ

Ö´ÐУºmvn spring-cloud-contract:convertÃüÁ»áÔÚtarget/stubsÏÂÉú³ÉÏà¹ØÎļþ

Éú³ÉµÄmappingÎļþ£¬ÑùʽÈçÏÂ

{
"id" : "62db0b7f-72de-4c03-8e38-6874d4b433ab",
"request" : {
"urlPath" : "/hello",
"method" : "GET",
"queryParameters" : {
"name" : {
"equalTo" : "zhangsan"
}
}
},
"response" : {
"status" : 200,
"body" : "{\"code\":\"000000\",\"mesg\":\"´¦Àí³É¹¦\"}",
"headers" : {
"Content-Type" : "application/json;charset=UTF-8"
},
"transformers" : [ "response-template" ]
},
"uuid" : "62db0b7f-72de-4c03-8e38-6874d4b433ab"
}

Ö´ÐУºmvn spring-cloud-contract:generateStubsÃüÁ»áÔÚtargetÏÂÉú³ÉstubsµÄjar°ü

È磺producer-0.0.1-SNAPSHOT-stubs.jar

4.°²×°stubµ½maven¿âÖÐ

µ±È»Ò²¿É½«plugin °ó¶¨µ½Ïà¹ØµÄphaseÉÏ×Ô¶¯°²×°µ½maven¿âÖÐ

Àý×Ó£º

mvn install:install-file -DgroupId=com.springboot.cloud -DartifactId=producer -Dversion=0.0.1-SNAPSHOT -Dpackaging=jar -Dclassifier=stubs -Dfile=producer-0.0.1-SNAPSHOT-stubs.jar

ÒÔÉÏ£¬½«stub jar°ü·ÖÏí¸øconsumer£¬¶Ô·½¾ÍÒªÒÔÔÚ¼¯³É²âÊÔ°¸ÀýÖÐʹÓÃÁË

5.½Ó¿ÚʵÏÖ²¢¼ìÑéÊÇ·ñ·ûºÏÆõÔ¼

Ìṩһ¸ö²âÊÔ»ùÀࣨÖ÷ÒªÓÃÓÚ°´ÕÕÆõÔ¼¶Ô½Ó¿ÚÉú³É²âÊÔ°¸Àý£¬¼ìÑé½Ó¿ÚÊÇ·ñ°´ÆõԼʵÏÖÁË£©

package com.springboot.services.producer;
import com.springboot.services.producer.rest.HelloController;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
import org.junit.Test;


public class MvcMockTest {
@Before
public void setup() {
RestAssuredMockMvc.standaloneSetup(new HelloController());
}
}

Ö´ÐУºmvn spring-cloud-contract:generateTestsÃüÁ»áÔÚtarget/generated-test-sources/contractsĿ¼Ï¸ù¾ÝÆõÔ¼Éú³É²âÊÔ°¸Àý£¬ÓÃÓÚ·þÎñÌṩ·½×îºó¼ìÑéÊÇ·ñ·ûºÏÆõÔ¼¡£

Àý×Ó£º


import static com.toomuchcoding.jsonassert.JsonAssertion.assert


ThatJson;
import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;
import static org.springframework.cloud.contract.verifier.asser


tion.Spring


CloudContractAssertions.assertThat;


public class ContractVerifierTest extends MvcMockTest {


@Test
public void validate_helloController() throws Exception {
// given:
MockMvcRequestSpecification request = given();


// when:
ResponseOptions response = given().spec(request)
.queryParam("name","zhangsan")
.get("/hello");
// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).isEqualTo


("application/json;charset=UTF-8");
// and:
DocumentContext parsedJson = JsonPath.parse(response.


getBody().asString()); assertThatJson(parsedJson).field


("['code']").isEqualTo("000000");
assertThatJson(parsedJson).field("['mesg']").isEqualTo


("\u5904\u7406\u6210\u529F");
}
}

Client/Consumer ·þÎñµ÷ÓöË

¹¹¼ÜÒýÈë

jar°üÒÀÀµ£¬·ÅÈëdependenciesÖÐ

<!--ÆõÔ¼²âÊÔ·þÎñÌṩ¶ËÒÀÀµ-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
<scope>test</scope>
</dependency>

µ÷Ó÷½´úÂë

¼ÙÈçÏû·Ñ·½ÓнӿÚ/classes?name=xxx£¬¸Ã½Ó¿Úµ÷ÓÃÁËproducer·þÎñµÄ½ÖµÀ¿Ú/hello?name=xxx£¬´Ëʱ

ClassControllerÈçÏ£¬µ÷ÓÃClassService

package com.springboot.feign.rest;
import com.springboot.cloud.common.core.entity.vo.Result;
import com.springboot.feign.service.ClassService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
public class ClassController {


@Autowired
private ClassService classService;


@GetMapping("/classes")
public Result hello(@RequestParam String name) {
return classService.users(name);
}
}

ClassServiceÈçÏ£¬Í¨¹ýfeiginµ÷ÓÃproducer·þÎñ

package com.springboot.feign.service;
import com.springboot.cloud.common.core.entity.vo.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
@FeignClient(name = "producer")
public interface ClassService {


@RequestMapping(value = "/hello", method = RequestMethod.GET)
Result users(@RequestParam("name") String name);
}

²âÊÔ°¸Àý±àд

¼¯³É²âÊÔ°¸ÀýÈçÏ£º

package com.springboot.feign.rest;
import org.hamcrest.core.Is;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.


AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.stubrunner.spring.


AutoConfigureStubRunner;
import org.springframework.cloud.contract.stubrunner.spring.


StubRunnerProperties;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request


.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.


MockMvcResultMatchers;


@RunWith(SpringRunner.class)
//springbootµÄ²âÊÔÆô¶¯À࣬ÐèÒªÒÀÀµspring-boot-test¿â
@SpringBootTest
//³õʹ»¯²âÊÔ²âÊÔÅäÖ㬲âÊÔcontrollerÐèÒª
@AutoConfigureMockMvc
//Æô¶¯ÆõÔ¼·þÎñ£¬Ä£ÄâproduerÌṩ·þÎñ
@AutoConfigureStubRunner(ids = {"com.springboot.cloud:producer:+:stubs:8080"}, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
public class ClassControllerTest {


@Autowired
private MockMvc mvc;


@Test
public void testMethod() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/classes").


param("name", "zhangsan"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("code",


Is.is("000000")));
}
}

ids¸ñʽÈçÏ£º

groupId:artifactId:version:classifier:port

±íʾ´ÓÄÄÀï¼ÓÔØstubµÄjar°ü£¬ÓÐ3ÖÖ£º

CLASSPATH£º´ÓclasspathÖÐÕÒjar°ü£¬Ä¬ÈÏ

LOCAL£º´Ó±¾µØmaven¿âÖÐÕÒ

REMOTE£º´ÓÔ¶³Ì·þÎñÆ÷ÖÐÏÂÔØ£¬ÐèÒªÅäºÏgit,²¢½«repositoryRootÉ趨ֵ£¬È磺

@AutoConfigureStubRunner(
stubsMode="REMOTE",
repositoryRoot="git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git",
ids="com.example:bookstore:0.0.1.RELEASE"
)

ÍêÕûµÄÀý×Ó£¬Çë²é¿´github

   
3894 ´Îä¯ÀÀ       30
Ïà¹ØÎÄÕÂ

ÆóÒµ¼Ü¹¹¡¢TOGAFÓëArchiMate¸ÅÀÀ
¼Ü¹¹Ê¦Ö®Â·-ÈçºÎ×öºÃÒµÎñ½¨Ä££¿
´óÐÍÍøÕ¾µçÉÌÍøÕ¾¼Ü¹¹°¸ÀýºÍ¼¼Êõ¼Ü¹¹µÄʾÀý
ÍêÕûµÄArchimateÊÓµãÖ¸ÄÏ£¨°üÀ¨Ê¾Àý£©
Ïà¹ØÎĵµ

Êý¾ÝÖÐ̨¼¼Êõ¼Ü¹¹·½·¨ÂÛÓëʵ¼ù
ÊÊÓÃArchiMate¡¢EA ºÍ iSpace½øÐÐÆóÒµ¼Ü¹¹½¨Ä£
ZachmanÆóÒµ¼Ü¹¹¿ò¼Ü¼ò½é
ÆóÒµ¼Ü¹¹ÈÃSOAÂ䵨
Ïà¹Ø¿Î³Ì

ÔÆÆ½Ì¨Óë΢·þÎñ¼Ü¹¹Éè¼Æ
ÖÐ̨սÂÔ¡¢ÖÐ̨½¨ÉèÓëÊý×ÖÉÌÒµ
ÒÚ¼¶Óû§¸ß²¢·¢¡¢¸ß¿ÉÓÃϵͳ¼Ü¹¹
¸ß¿ÉÓ÷ֲ¼Ê½¼Ü¹¹Éè¼ÆÓëʵ¼ù