Spring Boot将我自己的端点添加为端点管理

时间:2014-07-30 15:51:34

标签: java spring spring-boot

我对Spring框架非常陌生并且所有的春天 - 我开始潜入spring boot并将其评估为围绕REST服务构建新产品的候选者。

目前我对通过" 执行器"曝光的内容感兴趣模块,开箱即用我知道我可以收集信息(/ info)监控挂钩(/ health)甚至关闭端点,所有这些都通过提供配置选项将端点置于特定端口和&下而与主服务器分离#39;命名空间'

management.port=9000
management.contextPath=/admin

我正在寻找一个提示,将我自己的端点添加到已定义的端点(注意,我不想像HealthIndicator提议的那样丰富现有端点,但我真的想添加一个新端点比如说' / admin / get_me_out_of_load_balancers')

我可以看到所有现有的端点都扩展了AbstractEndpoint,但没有设法在管理contextPath下获取我的端点......

3 个答案:

答案 0 :(得分:10)

Endpoint类的实例公开为bean; Spring Boot的执行器自动配置will discover it。例如:

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public static Endpoint exampleEndpoint() {
        return new Endpoint<String>() {
            @Override
            public String getId() {
                return "example";
            }

            @Override
            public boolean isEnabled() {
                return true;
            }

            @Override
            public boolean isSensitive() {
                return false;
            }

            @Override
            public String invoke() {
                return "example";
            }
        };
    }
}

答案 1 :(得分:0)

您可以使用AbstractMvcEndpoint在单独的类中轻松实现它,并使用@RequestMapping来简化或添加params到端点,以便您可以查找其他服务信息:

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.endpoint.mvc.AbstractMvcEndpoint;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.LoadBalancerStats;
import com.netflix.loadbalancer.Server;
import lombok.Builder;

@Configuration
public class BalancingEndpoint extends AbstractMvcEndpoint {

    @Value("${spring.application.name}")
    private String localServiceName;

    @Autowired
    private SpringClientFactory springClientFactory;

    @Autowired
    private DiscoveryClient discoveryClient;

    public BalancingEndpoint() {
        super("/balancing", false);
    }

    @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public BalancingResponse get() {
        return getEndpointContent(localServiceName);
    }

    @RequestMapping(value = "/{serviceName}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public BalancingResponse get(@PathVariable("serviceName") String serviceName) {
        return getEndpointContent(serviceName);
    }

    private BalancingResponse getEndpointContent(String serviceName) {

        DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) springClientFactory.getLoadBalancer(serviceName);

        return BalancingResponse.builder()
            .discovery(discoveryClient.getLocalServiceInstance())
            .loadBalancerStats(loadBalancer.getLoadBalancerStats())
            .loadBalancerAllServers(loadBalancer.getAllServers())
            .build();
    }

    @Builder
    @JsonPropertyOrder({"discovery", "loadBalancerStats", "loadBalancerAllServers"})
    public static class BalancingResponse {

        @JsonProperty
        ServiceInstance discovery;

        @JsonProperty
        private LoadBalancerStats loadBalancerStats;

        @JsonProperty
        private List<Server> loadBalancerAllServers;
    }
}

此外,考虑这个问题很有意思(+info):

  

如果您将此作为库功能考虑添加一个   使用@ManagementContextConfiguration注释的配置类   密钥下的/META-INF/spring.factories   org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration。   如果这样做,那么端点将移动到具有all的子上下文   如果您的用户要求单独管理,则使用其他MVC端点   港口或地址。以这种方式声明的配置可以是a   WebConfigurerAdapter是否要添加静态资源(for   实例)到管理端点。

答案 2 :(得分:0)

对于Spring Boot 2,请查看示例: Spring Boot Actuator: 5.2. Custom Endpoint

@Component
@Endpoint(id = "custom-endpoint")
public class CustomEndpoint{

  @ReadOperation
  public String custom() {
    return "custom-end-point";
  }

  @ReadOperation
  public String customEndPointByName(@Selector String name) {
    return "custom-end-point";
  }

  @WriteOperation
  public void writeOperation(@Selector String name) {
    //perform write operation
  }

  @DeleteOperation
  public void deleteOperation(@Selector String name){
    //delete operation
  }
}

另请参见Introducing Actuator Endpoints in Spring Boot 2.0

相关问题