使用Apache CXF的JAX-RS Client發(fā)送HTTP請(qǐng)求

技術(shù)公眾號(hào):Java In Mind(Java_In_Mind),歡迎關(guān)注!

Apache CXF JAX-RS Client介紹

JAX-RS Client是Apache CXF的基于JAX-RS規(guī)范的客戶端實(shí)現(xiàn),Apache CXF是一個(gè)開放源代碼服務(wù)框架, CXF使用Front-End API(例如JAX-WS和JAX-RS)來構(gòu)建和開發(fā)服務(wù)。 這些服務(wù)可以說各種協(xié)議,例如SOAP,XML / HTTP,RESTful HTTP或CORBA,并且可以通過各種傳輸方式(例如HTTP,JMS或JBI)工作。

使用Apache CXF可以和Spring很方便的集成,也可以單獨(dú)使用,這里我們只使用JAX-RS Client模塊來實(shí)現(xiàn)RESTFul API的調(diào)用,他可以很好地提供面向?qū)ο缶幊痰膶?shí)現(xiàn),并且支持各種數(shù)據(jù)封裝,很方便我們做代碼層面上的抽象與封裝。

依賴

a<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-client</artifactId>
    <version>3.0.15</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.8.10</version>
</dependency>

模擬服務(wù)

@RestController
@RequestMapping("/demo")
@SpringBootApplication
@Slf4j
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    private List<Foo> foos = new CopyOnWriteArrayList<>();

    @GetMapping("/list")
    public ResponseEntity list(@RequestParam(value = "name", required = false) String name) {
        log.info("accept a list request...");
        boolean emptyQuery = StringUtils.isEmpty(name);
        return ResponseEntity
            .ok(foos.stream().filter(i -> emptyQuery || i.getName().equals(name)).collect(Collectors.toList()));
    }

    @PostMapping
    public ResponseEntity create(@RequestBody Foo foo) {
        log.info("accept create request,foo:{}", foo);
        // uuid
        foo.setId(UUID.randomUUID().toString());
        // add
        foos.add(foo);
        return ResponseEntity.ok(foo);
    }

    @GetMapping("/error")
    public ResponseEntity error() {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("error");
    }

    @Data
    @AllArgsConstructor
    public static class Foo {
        private String id;
        private String name;
        private int age;
    }
}


序列化Provider

public JacksonJaxbJsonProvider jsonProvider() {
        JacksonJaxbJsonProvider jacksonJaxbJsonProvider = new JacksonJaxbJsonProvider();
        Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean();
        jackson2ObjectMapperFactoryBean.afterPropertiesSet();
        ObjectMapper objectMapper = jackson2ObjectMapperFactoryBean.getObject();
        objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        jacksonJaxbJsonProvider.setMapper(objectMapper);
        return jacksonJaxbJsonProvider;
}

發(fā)起POST請(qǐng)求

@Data
public class FooCreateDTO {
    private String name;
    private int age;
}

@Data
public class FooDTO {
    private String id;
    private String name;
    private int age;
}

String endPoint = "http://localhost:8080";

FooClient fooClient = JAXRSClientFactory.create(endPoint, FooClient.class, Collections.singletonList(jsonProvider()), true);

FooCreateDTO fooCreateDTO = new FooCreateDTO();
fooCreateDTO.setName("seven");
fooCreateDTO.setAge(18);

FooDTO fooDTO = fooClient.create(fooCreateDTO);

log.info("result:{}",fooDTO);

發(fā)起GET請(qǐng)求

String endPoint = "http://localhost:8080";

FooClient fooClient = JAXRSClientFactory.create(endPoint, FooClient.class, Collections.singletonList(jsonProvider()), true);

List<FooDTO> list = fooClient.list("seven");
log.info("result:{}",list);

異常處理

String endPoint = "http://localhost:8080";

FooClient fooClient = JAXRSClientFactory.create(endPoint, FooClient.class, Collections.singletonList(jsonProvider()), true);

try{
    String message = fooClient.error();
    System.out.println(message);
}catch (WebApplicationException e){
    Response response = e.getResponse();
    int status = response.getStatus();
    String body = response.readEntity(String.class);

    log.error("error,status code={},body={}",status,body);
}

集成Spring

集成Spring可以帶了許多好處,首先是解耦,然后可以配置分離,并且對(duì)開發(fā)友好,就好像是調(diào)用本地服務(wù)一樣區(qū)實(shí)現(xiàn)調(diào)用一個(gè)外部請(qǐng)求這樣使用起來方便,對(duì)于測(cè)試也方便。

@Bean
public FooClient fooClient(){
        //一般在配置文件中配置
        String endPoint = "http://localhost:8080";
        return JAXRSClientFactory.create(endPoint, FooClient.class,         Collections.singletonList(jsonProvider()), true);
}

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class RunWithSpringTest {

    @Autowired
    private FooClient fooClient;

    @Test
    public void list(){
        List<FooDTO> list = fooClient.list(null);
        System.out.println(list);
    }
}

其他配置

  • 超時(shí)配置

    FooClient fooClient = ...//get Client
    //set Timeout
    HTTPConduit conduit = WebClient.getConfig(client).getHttpConduit();
    HTTPClientPolicy policy = new HTTPClientPolicy();
    policy.setReceiveTimeout(millisecond);
    conduit.setClient(policy);
    
  • 統(tǒng)一Header

    FooClient fooClient = ...//get Client
    //set token
    WebClient.client(client).header("access-token", "Bearer " + token);
    

總結(jié)

使用JAX-RS Client來調(diào)用RESTFul API更加方便了,代碼也更符合面向?qū)ο缶幊蹋⑶铱梢苑奖愕丶傻絊pring框架中,它幫我們處理了很多事情,請(qǐng)求體的構(gòu)造、結(jié)果的封裝等等,使我們更加專注于業(yè)務(wù)邏輯的編寫就夠了,避免繁瑣的重復(fù)類似的代碼處理。

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

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

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