使用Apache Camel构建Restful Web服务

664 阅读2分钟

目录

阅读时间: 4 分钟

使用Apache Camel的Restful webservices介绍

在这篇博客中,我们将使用Apache Camel暴露Restful Webservices。如你所知,Camel框架是基于Spring的。如果你利用Spring数据从Postgres数据库中获取数据,那么你的团队负责编写测试线束的唯一业务逻辑就是你对Spring框架的实现。你的开发团队并没有编写单元测试来验证Spring Data从JDBC数据源或该框架的任何底层技术中返回的行和列是否正确。JNDI、JVM、Linux内核。

Camel是一个在不同系统之间进行合并的框架。它通常不会自己做一些事情,而是创建和配置一些东西(例如一个组件),这些东西将真正做这些工作。

Camel最大的好处之一是,Camel框架的测试被外包给了社区。

Apache Camel在创建REST服务时也遵循同样的概念。你只需要为Camel写一些指令,它就会使用一堆其他的组件来为你暴露你的REST服务。你只需要准确地选择你想要的服务的实现方式,Camel会负责所有的配置。

让我们从使用Apache Camel的Restful webservices的项目结构开始吧

pom.xml将如下所示。

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.7</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.jss</groupId>
	<artifactId>camel</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>camel</name>
	<description>Apache Camel with rest services</description>

	<properties>
		<java.version>1.8</java.version>
		<junit.platform.version>1.6.0</junit.platform.version>
		<camel.version>3.7.3</camel.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.apache.camel.springboot</groupId>
			<artifactId>camel-spring-boot-starter</artifactId>
			<version>${camel.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-test</artifactId>
			<scope>test</scope>
			<version>${camel.version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-rabbitmq</artifactId>
			<version>${camel.version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-jackson</artifactId>
			<version>${camel.version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-jaxb</artifactId>
			<version>${camel.version}</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
			<version>1.18.12</version>
		</dependency>

		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-servlet</artifactId>
			<version>${camel.version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.camel.springboot</groupId>
			<artifactId>camel-servlet-starter</artifactId>
			<version>${camel.version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.camel.springboot</groupId>
			<artifactId>camel-rest-starter</artifactId>
			<version>${camel.version}</version>
		</dependency>

		<dependency>
			<groupId>org.junit.platform</groupId>
			<artifactId>junit-platform-runner</artifactId>
			<version>${junit.platform.version}</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.junit.vintage</groupId>
			<artifactId>junit-vintage-engine</artifactId>
			<version>5.7.0</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-test-junit5</artifactId>
			<version>${camel.version}</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-test-spring-junit5</artifactId>
			<version>${camel.version}</version>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

创建RestJavaDsl.java,该类将暴露GET服务以获取针脚代码的细节。

package com.spring.components.rest;

import com.spring.components.dto.PinCodeDto;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.apache.camel.support.DefaultMessage;
import org.springframework.stereotype.Component;

import java.util.Objects;

import static org.apache.camel.Exchange.HTTP_RESPONSE_CODE;
import static org.springframework.http.HttpStatus.NOT_FOUND;

@Component
public class RestJavaDsl extends RouteBuilder {
    private final PinDataProvider pinDataProvider;

    public RestJavaDsl(PinDataProvider pinDataProvider) {
        this.pinDataProvider = pinDataProvider;
    }

    @Override
    public void configure() throws Exception {
        restConfiguration().component("servlet").bindingMode(RestBindingMode.auto);


        from("rest:get:javadsl/pin/{pinCode}?produces=application/json").outputType(PinCodeDto.class).process(this::getPinCodeData);
    }

    private void getPinCodeData(Exchange exchange) {
        String city = exchange.getMessage().getHeader("pinCode", String.class);
        PinCodeDto currentPinCode = pinDataProvider.getUserPin(city);

        if (Objects.nonNull(currentPinCode)) {
            Message message = new DefaultMessage(exchange.getContext());
            message.setBody(currentPinCode);
            exchange.setMessage(message);
        } else {
            exchange.getMessage().setHeader(HTTP_RESPONSE_CODE, NOT_FOUND.value());
        }
    }
}

实现PinDataProvider.java,这个类将帮助你设置和获取Pin Code细节。

package com.spring.components.rest;

import com.spring.components.dto.PinCodeDto;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class PinDataProvider {
    private static Map<String, PinCodeDto> pinCodeData = new HashMap<>();

    public PinDataProvider() {
        PinCodeDto dto = PinCodeDto.builder().pinCode("244717").state("Uttarakhand").city("Ramnagar").receivedTime(new Date().toString()).id(1).build();
        pinCodeData.put("244717", dto);
    }

    public PinCodeDto getUserPin(String city) {
        return pinCodeData.get(city);
    }

    public void setUserPin(PinCodeDto dto) {
        dto.setReceivedTime(new Date().toString());
        pinCodeData.put(dto.getCity(), dto);
    }
}

创建PinCodeDto.java,这个类包含了所有的参数,这些参数将以JSON格式显示在响应中。

package com.spring.components.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class PinCodeDto implements Serializable {
    static int counter = 1;
    private int id =counter++;
    private String city;
    private String state;
    private String pinCode;
    private String receivedTime;
}

现在,你可以创建RestDsl.java,以便将数据传送到服务器上。

package com.spring.components.rest;

import com.spring.components.dto.PinCodeDto;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.apache.camel.support.DefaultMessage;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import java.util.Objects;

import static org.apache.camel.Exchange.HTTP_RESPONSE_CODE;
import static org.springframework.http.HttpStatus.NOT_FOUND;

@Component
public class RestDsl extends RouteBuilder {
    private final PinDataProvider pinDataProvider;

    public RestDsl(PinDataProvider pinDataProvider) {
        this.pinDataProvider = pinDataProvider;
    }

    @Override
    public void configure() throws Exception {
        restConfiguration().component("servlet").bindingMode(RestBindingMode.auto);
        rest().consumes(MediaType.APPLICATION_JSON_VALUE).produces(MediaType.APPLICATION_JSON_VALUE).get("pin/{pinCode}").outType(PinCodeDto.class).to("direct:get-pin-data").post("/pin").type(PinCodeDto.class).to("direct:save-pin-data");

        from("direct:get-pin-data").process(this::getPinCodeData);
        from("direct:save-pin-data").process(this::savePinDataAndSetToExchange);

    }

    private void savePinDataAndSetToExchange(Exchange exchange) {
        PinCodeDto pinCodeDto = exchange.getMessage().getBody(PinCodeDto.class);
        pinDataProvider.setUserPin(pinCodeDto);

    }

    private void getPinCodeData(Exchange exchange) {
        String userPin = exchange.getMessage().getHeader("pinCode", String.class);
        PinCodeDto pinCode = pinDataProvider.getUserPin(userPin);

        if (Objects.nonNull(pinCode)) {
            Message message = new DefaultMessage(exchange.getContext());
            message.setBody(pinCode);
            exchange.setMessage(message);
        } else {
            exchange.getMessage().setHeader(HTTP_RESPONSE_CODE, NOT_FOUND.value());
        }
    }
}

在application.yml中进行配置。

camel:
     component:
              servlet:
                      mapping:
                              context-path: /services/*

使用Postman测试rest服务

你可以用下面的网址来测试你的休息服务。

对于GET休息服务:http://localhost:8080/services/pin/244717

对于POST休息服务:http://localhost:8080/services/pin

总结

在这篇博客中,我们已经学会了如何使用Apache Camel编写REST服务(GET和POST)。Camel REST允许使用Restlet、Servlet和许多这样的HTTP感知组件来实现REST服务的创建。你可以利用Camel REST组件来公开REST API,并使用已知的Camel DSL来消费/生产消息,这可以帮助你实现技术上的标准化。点击这里继续学习Apache Camel。

Apache Camel ActiveMQ与生产者和消费者服务

分享Knol。

相关信息