最近博主在项目中,遇到了java对接jsonrpc的需求,稍微折腾了下,特整理一份笔记.本文主要记录的是jsonrpc4j (github地址:GitHub - briandilley/jsonrpc4j: JSON-RPC for Java)
环境:
组件 | 版本 |
SpringBoot2 | 2.5.7 |
jsonrpc4j | 1.6 |
引入依赖
<dependency>
<groupId>com.github.briandilley.jsonrpc4j</groupId>
<artifactId>jsonrpc4j</artifactId>
<version>1.6</version>
</dependency>
配置类:(注意url与字符集的设置)
一定要注意:
1. AutoJsonRpcServiceImplExporter (这里不单独配置的话,会引发rpc response返回123)
2.如果字符集不配置,可能会引发415错误,但是rpc response会返回一个105
import com.googlecode.jsonrpc4j.spring.AutoJsonRpcClientProxyCreator;
import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImplExporter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.URL;
@Configuration
@Slf4j
public class RpcConfiguration {
@Bean
@ConditionalOnProperty(value = {"ianp.external.rpc.client.url", "ianp.external.rpc.client.basePackage"})
public AutoJsonRpcClientProxyCreator rpcClientProxyCreator(@Value("${ianp.external.rpc.client.url}") String url, @Value("${ianp.external.rpc.client.basePackage}") String basePackage) {
log.info("local rpc config,url:{}, basePackage:{}", url, basePackage);
AutoJsonRpcClientProxyCreator clientProxyCreator = new AutoJsonRpcClientProxyCreator();
try {
clientProxyCreator.setBaseUrl(new URL(url));
clientProxyCreator.setContentType("application/json");
} catch (Exception e) {
log.error("create rpc url failed", e.getMessage());
}
clientProxyCreator.setScanPackage(basePackage);
return clientProxyCreator;
}
@Bean
public AutoJsonRpcServiceImplExporter rpcServiceImplExporter() {
return new AutoJsonRpcServiceImplExporter();
}
}
yml片段:
ianp:
external:
rpc:
client:
url: http://localhost:7878/
basePackage: com.xxx.backend.service.rpc
使用:
默认先声明一个对应的API,如:
@JsonRpcService是对应的接口地址,一般以rpc开头
import com.googlecode.jsonrpc4j.JsonRpcService;
@JsonRpcService("/rpc")
public interface StorageProfService {
String proofOfExistence(String address, String maindata, String password);
}
调用参考
import com.alibaba.fastjson.JSON;
import com.xxx.backend.service.rpc.service.api.StorageProfService;
import com.xxx.backend.service.rpc.service.pojo.StorageProf;
import com.googlecode.jsonrpc4j.JsonRpcClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class StorageProfConsumerService {
@Autowired
private StorageProfService storageProfService;
public String storageProf(StorageProf storageProf) {
String result = null;
try {
Object res = storageProfService.proofOfExistence(storageProf.getAddress(), storageProf.getMainData(),storageProf.getPassword());
result = JSON.toJSONString(res);
} catch (JsonRpcClientException ce) {
String message = ce.getMessage();
log.error("client error:{}", message);
throw ce;
}
return result;
}
}
参考,这个demo很详细了: GitHub - Panlf/springboot-jsonrpc: 本项目是基于SpringBoot和Json-Rpc(jsonrpc4j)的案例,其实跟dubbo的调用是类似的。
补充说明:
1. 解决与RedisConfig的冲突
在实际整合使用的过程中,发现与RedisConfig自定义配置ObjectMapper冲突
原始方案:
// @Bean
// public ObjectMapper messagePackObjectMapper() {
// return new ObjectMapper(new MessagePackFactory())
// .registerModule(new JavaTimeModule())
// .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// }
修改后的方案:
@PostConstruct public void registerModule() { objectMapper.registerModule(new JavaTimeModule()).disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); }