没有前戏,直接上代码。
注册中心:
使用 eureka
客户端:
1、配置文件
spring.application.name=my-user
server.port=8084
eureka.client.serviceUrl.defaultZone=http://admin:admin@localhost:8763/eureka/
three.server.order.name=my-order
2、Controller
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {
//封装调用第三方服务类
@Autowired
private OrderThreeService orderThreeService;
@RequestMapping("/get")
public String getOrder(String key){
// get方法调用服务端接口
String result = orderThreeService.getOrder(key,1);
log.info(result);
//post 方法调用服务端接口
OrderModel orderModel = new OrderModel();
orderModel.setId(1L);
orderModel.setName("1号订单");
result = orderThreeService.save(orderModel);
log.info(result);
return result;
}
}
3、封装类 OrderThreeService 、实现类 OrderThreeServiceImpl
public interface OrderThreeService {
String getOrder(String key,Integer valid);
String save(OrderModel orderModel);
}
@Component
public class OrderThreeServiceImpl extends AbstractThreeService implements OrderThreeService {
@Value("${three.server.order.name}")
private String serverName;
@Autowired
private RestTemplate restTemplate;
@HandlerMethodUrlParameter("order/get?key=&valid=")
@Override
public String getOrder(String key,Integer valid){
String url = buildUrlHttp(serverName, "getOrder", key,valid.toString());
String result = restTemplate.getForObject(url, String.class);
return result;
}
@HandlerMethodUrlParameter("order/save")
@Override
public String save(OrderModel orderModel){
String url = buildUrlHttp(serverName, "save", null);
ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(url, orderModel, String.class);
return stringResponseEntity.getBody();
}
}
注:
String url = buildUrlHttp(serverName, "getOrder", key,valid.toString()); 第一个参数为服务名,第二个为方法名,写在哪个方法就写那个方法的名字,后续就为参数名称了,有几个就写几个,和方法上注解@HandlerMethodUrlParameter("order/get?key=&valid=") 的=数量匹配。
4、第三方服务抽象基类 AbstractThreeService
其他服务的接口类,只要继承 AbstractThreeService 就可以按 OrderThreeServiceImpl 的方式实现
public abstract class AbstractThreeService {
private Map<String,String> methodParameter = new HashMap<>();
@PostConstruct
public void init(){
ReflectionUtils.doWithMethods(this.getClass(), method -> {
HandlerMethodUrlParameter hmup = method.getAnnotation(HandlerMethodUrlParameter.class);
if(hmup != null){
methodParameter.put(method.getName(),hmup.value());
}
});
}
protected String buildUrlHttp(String serverName,String method,String... args) {
return String.format("%s/%s",buildUrlHttp(serverName),buildGetParam(methodParameter.get(method),args));
}
protected String buildUrlHttp(String serverName) {
return String.format("http://%s", serverName);
}
protected String buildUrlHttps(String serverName,String method,String... args) {
return String.format("%s/%s",buildUrlHttps(serverName),buildGetParam(methodParameter.get(method),args));
}
protected String buildUrlHttps(String serverName) {
return String.format("https://%s", serverName);
}
/**
* TODO pattern格式为 key1=&key2=
* @param pattern
* @param agrs
* @return
*/
protected String buildGetParam(String pattern,String... agrs) {
if(StringUtils.isBlank(pattern) || agrs ==null || agrs.length == 0){
return pattern;
}
pattern = pattern.replace("=","=%s");
return String.format(pattern, agrs);
}
}
5、标识每个方法调用对应接口的地址辅助注解
注 :@HandlerMethodUrlParameter("order/get?key=&valid=") 参数的封装格式 key=&valid=
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HandlerMethodUrlParameter {
String value() default "";
}
服务端
1、提供的接口方法
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {
@GetMapping("/get")
public String getOrder(String key,Integer valid){
String result = "getOrder --> key=" + key +"&valid="+valid;
log.info(result);
return result;
}
@PostMapping("/save")
public String save(@RequestBody OrderModel orderModel){
String result = "save --> key=" + JSONObject.toJSONString(orderModel);
log.info(result);
return result;
}
}
测试:
浏览器上调用 客户端的接口,客户端接口会去调用服务端接口方法,且返回信息到客户端