沒有前戲,直接上代碼。
註冊中心:
使用 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;
}
}
測試:
瀏覽器上調用 客戶端的接口,客戶端接口會去調用服務端接口方法,且返回信息到客戶端