日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring boot 使用@Endpoint注解自定义端点, 不能通过 Restfult 访问问题 原因分析

發布時間:2024/1/1 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring boot 使用@Endpoint注解自定义端点, 不能通过 Restfult 访问问题 原因分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、使用@Endpoint注解自定義端點

參考 spring-boot-starter-actuator.jar 包健康檢查端點源碼 org.springframework.boot.actuate.health.HealthEndpoint 實現

引入依賴

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>

自定義端點代碼

注意: @EndPoint中的id不能使用駝峰法,需要以-分割。

默認的基礎路徑是/actuator,如果一個端點配置的?id?是my-endpoint,那么它的全路徑就是/actuator/my-endpoint?

@Selector?的含義是讓這個訪問路徑變成restful風格:?/actuator/my-endpoint/{name}

@Component @Endpoint(id = "my-endpoint") public class MyEndpoint {@ReadOperationpublic 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 themtry {tmp = getParameters0();} catch(IllegalArgumentException e) {// Rethrow ClassFormatErrorsthrow new MalformedParametersException("Invalid constant pool index");}// If we get back nothing, then synthesize parametersif (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: * <li>{@link JavaCompile} tasks are configured to use {@code -parameters}. ./buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java: if (!args.contains("-parameters")) { ./buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java: args.add("-parameters");

解決處理方法:

添加編譯參數 -parameters

1) 在IDEA中,

File->Settings->Java Compiler 的 Addintional command line parameters 的下面加上-parameters參數即可

2) 、在Maven中添加

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.3</version><configuration><source>1.8</source><target>1.8</target><compilerArgs><arg>-parameters</arg></compilerArgs></configuration> </plugin>

3) 、 在eclipse中

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,POST

4、 Actuator端點注解

Web 端點

@Endpoint、@WebEndpoint?或?@EndpointWebExtension?上的操作將使用 Jersey、Spring MVC 或 Spring WebFlux 通過 HTTP 自動暴露。

通過使用?@Selector?注解操作方法的一個或多個參數,可以進一步自定義路徑.

HTTP 方法由操作類型決定,如下表所示:

操作HTTP 方法
@ReadOperationGET
@WriteOperationPOST
@DeleteOperationDELETE

@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/

總結

以上是生活随笔為你收集整理的Spring boot 使用@Endpoint注解自定义端点, 不能通过 Restfult 访问问题 原因分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。