参考 spring-boot-starter-actuator.jar 包健康检查端点源码 org.springframework.boot.actuate.health.HealthEndpoint 实现
引入依赖自定义端点代码org.springframework.boot spring-boot-starter-actuator
注意: @EndPoint中的id不能使用驼峰法,需要以-分割。
默认的基础路径是/actuator,如果一个端点配置的 id 是my-endpoint,那么它的全路径就是/actuator/my-endpoint
@Selector 的含义是让这个访问路径变成restful风格: /actuator/my-endpoint/{name}
@Component @Endpoint(id = "my-endpoint") public class MyEndpoint { @ReadOperation public String get(@Selector String name) { return name; } }配置
// management.endpoints.web.exposure.include=my-endpoint management.endpoints.web.exposure.include=*查询端点列表:
通过端点的基础路径查询端点列表: http://localhost:9080/actuator
health 组件健康信息访问路径: http://localhost:9080/actuator/health/{component}
我们可以通过 http://localhost:9080/actuator/health/consul 查看 consul的健康信息
而对应的自定义端点访问路径: http://localhost:9080/actuator/my-endpoint/{arg0}
访问 http://localhost:9080/actuator/my-endpoint/abc 却报 404其可以正常访问路径变成: http://localhost:9080/actuator/my-endpoint/{arg0}?name=abc
为什么自定义端点restfult风格访问失效了呢?经过断点发现 WebEndpointDiscoverer.createOperation() 在绑定访问路径时, 自定义端点 通过 DiscoveredOperationMethod 获取到的方法参数名变为 arg0.
而 DiscoveredOperationMethod 是通过 jdk 的 method.getParameters() 获取参数, 其代码如下:
private native Parameter[] getParameters0(); public Parameter[] getParameters() { // TODO: This may eventually need to be guarded by security // mechanisms similar to those in Field, Method, etc. // // Need to copy the cached array to prevent users from messing // with it. Since parameters are immutable, we can // shallow-copy. return privateGetParameters().clone(); } private Parameter[] synthesizeAllParams() { final int realparams = getParameterCount(); final Parameter[] out = new Parameter[realparams]; for (int i = 0; i < realparams; i++) // TODO: is there a way to synthetically derive the // modifiers? Probably not in the general case, since // we'd have no way of knowing about them, but there // may be specific cases. out[i] = new Parameter("arg" + i, 0, this, i); return out; } private Parameter[] privateGetParameters() { // Use tmp to avoid multiple writes to a volatile. Parameter[] tmp = parameters; if (tmp == null) { // Otherwise, go to the JVM to get them try { tmp = getParameters0(); } catch(IllegalArgumentException e) { // Rethrow ClassFormatErrors throw new MalformedParametersException("Invalid constant pool index"); } // If we get back nothing, then synthesize parameters if (tmp == null) { hasRealParameterData = false; tmp = synthesizeAllParams(); } else { hasRealParameterData = true; verifyParameters(tmp); } parameters = tmp; } return tmp; }
自定义端点最终走到 native 方法 getParameters0() 获取不到方法参数信息, 交由 synthesizeAllParams() 方法得到 arg0 参数.
而actuator自带端点 走到 native 方法 getParameters0() 可以获取静态的方法的参数信息, 显然与代码编译有关.
于是搜索 method.getParameters() 得到一些解释:
在Java8之前,代码编译为class文件后,方法参数的类型是固定的,但参数名称却丢失了,这和动态语言严重依赖参数名称形成了鲜明对比。(java是静态语言,所以入参名称叫什么其实无所谓的)
java1.8以后,官方提供了反射的方法能获取到接口的参数名称。并且需要在javac编译时,加上-parameters参数才行。
后查看spring boot的源码发现, 都需要加上 -parameters 编译
./spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc:TIP: If you are using `@SpyBean` to spy on a bean with `@Cacheable` methods that refer to parameters by name, your application must be compiled with `-parameters`. ./spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/endpoints.adoc:NOTE: To let the input be mapped to the operation method's parameters, Java code that implements an endpoint should be compiled with `-parameters`, and Kotlin code that implements an endpoint should be compiled with `-java-parameters`. ./spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/reacting.adoc:10. Configures any `JavaCompile` tasks to use the `-parameters` compiler argument. ./spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/reacting.adoc:2. Configures any `KotlinCompile` tasks to use the `-java-parameters` compiler argument. ./spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging.adoc:The `application` closure uses Ant-style patch matching for include/exclude parameters. ./spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java: private static final String PARAMETERS_COMPILER_ARG = "-parameters"; ./spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/using.adoc:* Compilation with `-parameters`. ./buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java: *
添加编译参数 -parameters
1) 在IDEA中,File->Settings->Java Compiler 的 Addintional command line parameters 的下面加上-parameters参数即可
2) 、在Maven中添加3) 、 在eclipse中org.apache.maven.plugins maven-compiler-plugin3.3 1.8 -parameters
Preferences->java->Compiler下勾选Store information about method parameters选项。
2、如何在运行期获取method中的参数名见: https://www.jianshu.com/p/a7f4336f445c
3、 Actuator端点配置 PATH, 访问路径:默认的基础路径是/actuator,如果一个端点配置的 id 是sessions,那么它的全路径就是/actuator/sessions
自定义管理端点路径management.endpoints.web.base-path = /manage
此配置会将/actuator/sessions/{name}转换成/manage/sessions/{name}
自定义管理服务器地址默认端口和应用的端口是一致的
management.server.port = 8081 management.server.address = 127.0.0.1激活端点
//激活所有的端点的web方式请求 management.endpoints.web.exposure.include=* //关闭端点web方式 management.endpoints.web.exposure.exclude=env,beans //激活所有的JMX方式请求 management.endpoints.jmx.exposure.include=* //健康信息展示详细信息, 值never:永远不会显示细节,always:显示详细信息,when-authorized:详细信息仅向授权用户显示 management.endpoint.health.show-details=always //健康信息展示详细信,配置授权角色 management.endpoint.health.roles跨域方式请求
//允许跨域的网址 management.endpoints.web.cors.allowed-origins=http://example.com //允许跨域的方法 management.endpoints.web.cors.allowed-methods=GET,POST4、 Actuator端点注解 Web 端点
@Endpoint、@WebEndpoint 或 @EndpointWebExtension 上的 *** 作将使用 Jersey、Spring MVC 或 Spring WebFlux 通过 HTTP 自动暴露。
通过使用 @Selector 注解 *** 作方法的一个或多个参数,可以进一步自定义路径.
HTTP 方法由 *** 作类型决定,如下表所示:
@ReadOperation 返回一个值,响应状态为 200(OK)。如果它未返回值,则响应状态将为 404(未找到)。
如果 @WriteOperation 或 @DeleteOperation 返回值,则响应状态将为 200(OK)。如果它没有返回值,则响应状态将为 204(无内容)。
Servlet 端点通过实现一个带有 @ServletEndpoint 注解的类,Servlet 可以作为端点暴露,该类也实现了 Supplier。Servlet 端点提供了与 Servlet 容器更深层次的集成,但代价是可移植性。它们旨在用于将现有 Servlet 作为端点暴露。对于新端点,应尽可能首选 @Endpoint 和 @WebEndpoint 注解。
控制器端点@ControllerEndpoint 和 @RestControllerEndpoint 可用于实现仅由 Spring MVC 或 Spring WebFlux 暴露的端点。使用 Spring MVC 和 Spring WebFlux 的标准注解(如 @RequestMapping 和 @GetMapping)映射方法,并将端点的 ID 用作路径的前缀。控制器端点提供了与 Spring 的 Web 框架更深层次的集成,但代价是可移植性。应尽可能首选 @Endpoint 和 @WebEndpoint 注解。
5、@Endpoint 注解生效原理解析https://blog.csdn.net/kangsa998/article/details/103166953/
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)