EndPoint详解

EndPoint详解

EndPoint主要用于暴露一些SpringMvc内部运行的信息,通常是通过SpringMvc的请求地址获取相关信息。如/health获取健康检查信息。

简单单元测试

@Test
public void testHealth() throws Exception{
  mockMvc.perform(MockMvcRequestBuilders.get("/health").contentType(MediaType.APPLICATION_JSON_UTF8)).andDo(new ResultHandler() {
    @Override
    public void handle(MvcResult result) throws Exception {
      System.out.println(result.getResponse().getContentAsString());
    }
  });
}
//结果
{"status":"UP","discoveryComposite":{"description":"Discovery Client not initialized","status":"UNKNOWN","discoveryClient":{"description":"Discovery Client not initialized","status":"UNKNOWN"}},"diskSpace":{"status":"UP","total":197553815552,"free":46789115904,"threshold":10485760},"refreshScope":{"status":"UP"},"hystrix":{"status":"UP"},"consul":{"status":"UP","services":{"consul":[]},"advertiseAddress":"172.17.0.8","datacenter":"dc1","domain":"consul.","nodeName":"node-client-v-5-1","bindAddress":"0.0.0.0","clientAddress":"0.0.0.0"}}

url映射

HandlerMapping使用EndpointHandlerMapping,重写了registerHandlerMethod,主要是注册HandlerMethod时重写请求路径。

private String[] getPatterns(Object handler, RequestMappingInfo mapping) {
  String path = getPath(handler);
  String prefix = StringUtils.hasText(this.prefix) ? this.prefix + path : path;
  Set<String> defaultPatterns = mapping.getPatternsCondition().getPatterns();
  if (defaultPatterns.isEmpty()) {
    return new String[] { prefix, prefix + ".json" };
  }
  List<String> patterns = new ArrayList<String>(defaultPatterns);
  for (int i = 0; i < patterns.size(); i++) {
    patterns.set(i, prefix + patterns.get(i));
  }
  return patterns.toArray(new String[patterns.size()]);
}
private String getPath(Object handler) {
  if (handler instanceof String) {
    handler = getApplicationContext().getBean((String) handler);
  }
  if (handler instanceof MvcEndpoint) {
    return ((MvcEndpoint) handler).getPath();
  }
  return "";
}

如果handler时MvcEndpoint类型,则请求路径调用getPath方法获取。

健康检查为例/health

实现
public HealthEndpoint(HealthAggregator healthAggregator,
    Map<String, HealthIndicator> healthIndicators) {
  super("health", false);
  Assert.notNull(healthAggregator, "HealthAggregator must not be null");
  Assert.notNull(healthIndicators, "HealthIndicators must not be null");
  CompositeHealthIndicator healthIndicator = new CompositeHealthIndicator(
      healthAggregator);
  for (Map.Entry<String, HealthIndicator> entry : healthIndicators.entrySet()) {
    healthIndicator.addHealthIndicator(getKey(entry.getKey()), entry.getValue());
  }
  this.healthIndicator = healthIndicator;
}
@Override
	public Health invoke() {
		return this.healthIndicator.health();
	}

最终回调用HealthIndicator的health()方法。而健康检查的HealthIndicator为CompositeHealthIndicator。其health方法:

@Override
public Health health() {
  Map<String, Health> healths = new LinkedHashMap<String, Health>();
  for (Map.Entry<String, HealthIndicator> entry : this.indicators.entrySet()) {
    healths.put(entry.getKey(), entry.getValue().health());
  }
  return this.healthAggregator.aggregate(healths);
}

所以,HealthIndicator才是最为关键的,CompositeHealthIndicator只是将所有的HealthIndicator合并。

自定义健康检查实现,即实现HealthIndicator。
@Component
public class TestHelthIndicator extends AbstractHealthIndicator {
    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        builder.up().withDetail("test","testHealth");
    }
}
"testHelthIndicator":{"status":"UP","test":"testHealth"},
posted @ 2017-01-01 23:06  dragonfei  阅读(10438)  评论(0编辑  收藏  举报