背景:微服务项目中整合dubbo框架,实现PRC与Rest的方式调用,本文是针对dubbo接口的rest方式调用实例。参考开源项目spring-cloud-alibaba。
step 1、添加依赖
<properties>
<nacos.version>2.0.2nacos.version>
<dubbo.version>2.7.12dubbo.version>
<jw.rs.version>2.0jw.rs.version>
properties>
<dependency>
<groupId>javax.ws.rsgroupId>
<artifactId>javax.ws.rs-apiartifactId>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-registry-nacosartifactId>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-rpc-restartifactId>
<exclusions>
<exclusion>
<artifactId>jboss-jaxrs-api_2.0_specartifactId>
<groupId>org.jboss.spec.javax.ws.rsgroupId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubboartifactId>
dependency>
<dependency>
<groupId>com.alibaba.nacosgroupId>
<artifactId>nacos-clientartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
step 2、dubbo配置
dubbo:
registry:
address: nacos://192.168.40.121:8848
#address: spring-cloud://localhost
application:
name: dubbo-server
config:
multiple: true
protocols:
dubbo:
name: dubbo
port: 20805
#server: netty4
rest:
name: rest
server: tomcat
port: 20866
step 3、定义接口
public interface RpcService {
String sayHello(String name);
TestObj getTestObj();
TestObj getTestObjByForm(String code, String message);
TestObj getTestObjByFormBean(TestObj test);
String param(String param);
String params(int a, String b);
String headers(String header, String header2, Integer param);
String pathVariables(String path1, String path2, String param);
String form(String form);
User requestBodyMap(Map<String, Object> data, String param);
Map<String, Object> requestBodyUser(User user);
}
step 4、实现接口
@DubboService(version = "1.8")
@Slf4j
@Path("/rpc")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
public class RpcServiceImpl implements RpcService {
@Override
@Path("/hello")
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
public String sayHello(@QueryParam("name") String name) {
return name + "";
}
@Override
@Path("/test")
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
public TestObj getTestObj() {
return null;
}
@Override
@Path("/form")
@POST
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
public TestObj getTestObjByForm(@FormParam("code") String code, @FormParam("message") String message
) {
return new TestObj();
}
@Override
@Path("/formBean")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public TestObj getTestObjByFormBean(TestObj testObj) {
TestObj test=new TestObj();
return null;
}
@Override
@Path("/formPost")
@POST
public String formPost(String name) {
return name;
}
@Override
@Path("/param")
@GET
public String param(@QueryParam("param") String param) {
log.info("/param", param);
return param;
}
@Override
@Path("/params")
@POST
public String params(@QueryParam("a") int a, @QueryParam("b") String b) {
log.info("/params", a + b);
return a + b;
}
@Override
@Path("/headers")
@GET
public String headers(@HeaderParam("h") String header,
@HeaderParam("h2") String header2, @QueryParam("v") Integer param) {
String result = header + " , " + header2 + " , " + param;
log.info("/headers", result);
return result;
}
@Override
@Path("/path-variables/{p1}/{p2}")
@GET
public String pathVariables(@PathParam("p1") String path1,
@PathParam("p2") String path2, @QueryParam("v") String param) {
String result = path1 + " , " + path2 + " , " + param;
log.info("/path-variables", result);
return result;
}
@Override
@Path("/request/body/map")
@POST
@Produces(APPLICATION_JSON_VALUE)
public User requestBodyMap(Map<String, Object> data,
@QueryParam("param") String param) {
User user = new User();
user.setId(((Integer) data.get("id")).longValue());
user.setName((String) data.get("name"));
user.setAge((Integer) data.get("age"));
log.info("/request/body/map", param);
return user;
}
@Path("request/body/user")
@POST
@Override
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Map<String, Object> requestBodyUser(User user) {
Map<String, Object> map = new HashMap<>();
map.put("id", user.getId());
map.put("name", user.getName());
map.put("age", user.getAge());
return map;
}
}
step 5、编写启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableDubbo(scanBasePackages = {"com.test.core","com.test.service.impl"})
public class DubboApplication{
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DubboApplication.class, args);
}
}
测试时遇到的问题与注意事项:
1、服务返回值为NULL,请求状态码为204。
2、注意GET、POST注解是否为ws包下的注解。
3、注意@Produces、@Consumes的使用场景。可能会出现Could not find MessageBodyWriter for response object of type: com.test.service.impl.Test of media type: application/octet-stream
4、object is not an instance of declaring class
5、No resource method found for POST, return 405 with Allow header