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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring boot actuator工作原理之http服务暴露源码分析

發(fā)布時間:2025/4/5 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring boot actuator工作原理之http服务暴露源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

spring boot actuator的官方文檔地址:https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready.html

1.增加actuator支持

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

2.修改配置

示例:

endpoints.actuator.enabled=true endpoints.actuator.sensitive=false endpoints.beans.sensitive=false endpoints.beans.enabled=true endpoints.health.sensitive=false endpoints.health.enabled=true management.security.enabled=false

紅色部分重要,默認是需要身份認證的,一些頁面不能訪問,加上后所有頁面不需要認證,都可以訪問。

3.啟動效果如下:

2017-04-07 14:42:46.569 INFO 10912 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2017-04-07 14:42:46.569 INFO 10912 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2017-04-07 14:42:46.621 INFO 10912 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3224bdee: startup date [Fri Apr 07 14:42:43 CST 2017]; root of context hierarchy 2017-04-07 14:42:47.127 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String) 2017-04-07 14:42:47.127 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.128 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.128 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String) 2017-04-07 14:42:47.128 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.129 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.129 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.129 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest) 2017-04-07 14:42:47.129 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.130 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.130 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.131 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String) 2017-04-07 14:42:47.131 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException 2017-04-07 14:42:47.132 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String) 2017-04-07 14:42:47.132 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>) 2017-04-07 14:42:47.132 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.133 INFO 10912 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2017-04-07 14:42:47.247 INFO 10912 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2017-04-07 14:42:47.248 INFO 10912 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'dataSource' has been autodetected for JMX exposure 2017-04-07 14:42:47.251 INFO 10912 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource] 2017-04-07 14:42:47.256 INFO 10912 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0 2017-04-07 14:42:47.326 INFO 10912 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2017-04-07 14:42:47.330 INFO 10912 --- [ main] xxx.xxx.xxx.Application : Started Application in 3.642 seconds (JVM running for 6.678) 2017-04-07 14:43:05.269 INFO 10912 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet' 2017-04-07 14:43:05.269 INFO 10912 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started 2017-04-07 14:43:05.282 INFO 10912 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 13 ms

4.工作原理分析

4.1 EndpointHandlerMapping

從上述日志中,我們可以看到映射是由EndpointHandlerMapping完成的。我們看一下EndpointHandlerMapping的定義:

/*** {@link HandlerMapping} to map {@link Endpoint}s to URLs via {@link Endpoint#getId()}.* The semantics of {@code @RequestMapping} should be identical to a normal* {@code @Controller}, but the endpoints should not be annotated as {@code @Controller}* (otherwise they will be mapped by the normal MVC mechanisms).* <p>* One of the aims of the mapping is to support endpoints that work as HTTP endpoints but* can still provide useful service interfaces when there is no HTTP server (and no Spring* MVC on the classpath). Note that any endpoints having method signatures will break in a* non-servlet environment.** @author Phillip Webb* @author Christian Dupuis* @author Dave Syer*/ public class EndpointHandlerMapping extends AbstractEndpointHandlerMapping<MvcEndpoint> {/*** Create a new {@link EndpointHandlerMapping} instance. All {@link Endpoint}s will be* detected from the {@link ApplicationContext}. The endpoints will not accept CORS* requests.* @param endpoints the endpoints*/public EndpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints) {super(endpoints);}/*** Create a new {@link EndpointHandlerMapping} instance. All {@link Endpoint}s will be* detected from the {@link ApplicationContext}. The endpoints will accepts CORS* requests based on the given {@code corsConfiguration}.* @param endpoints the endpoints* @param corsConfiguration the CORS configuration for the endpoints* @since 1.3.0*/public EndpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints,CorsConfiguration corsConfiguration) { super(endpoints, corsConfiguration);}}

?

4.2?EndpointWebMvcManagementContextConfiguration

EndpointHandlerMapping從哪里來的呢?EndpointWebMvcManagementContextConfiguration定義了EndpointHandlerMapping:

/*** Configuration to expose {@link Endpoint} instances over Spring MVC.** @author Dave Syer* @author Ben Hale* @author Vedran Pavic* @since 1.3.0*/ @ManagementContextConfiguration @EnableConfigurationProperties({ HealthMvcEndpointProperties.class,EndpointCorsProperties.class }) public class EndpointWebMvcManagementContextConfiguration {private final HealthMvcEndpointProperties healthMvcEndpointProperties;private final ManagementServerProperties managementServerProperties;private final EndpointCorsProperties corsProperties;private final List<EndpointHandlerMappingCustomizer> mappingCustomizers;public EndpointWebMvcManagementContextConfiguration(HealthMvcEndpointProperties healthMvcEndpointProperties,ManagementServerProperties managementServerProperties,EndpointCorsProperties corsProperties,ObjectProvider<List<EndpointHandlerMappingCustomizer>> mappingCustomizers) {this.healthMvcEndpointProperties = healthMvcEndpointProperties;this.managementServerProperties = managementServerProperties;this.corsProperties = corsProperties;List<EndpointHandlerMappingCustomizer> providedCustomizers = mappingCustomizers.getIfAvailable();this.mappingCustomizers = providedCustomizers == null? Collections.<EndpointHandlerMappingCustomizer>emptyList(): providedCustomizers;} @Bean@ConditionalOnMissingBeanpublic EndpointHandlerMapping endpointHandlerMapping() {Set<MvcEndpoint> endpoints = mvcEndpoints().getEndpoints();CorsConfiguration corsConfiguration = getCorsConfiguration(this.corsProperties);EndpointHandlerMapping mapping = new EndpointHandlerMapping(endpoints,corsConfiguration);mapping.setPrefix(this.managementServerProperties.getContextPath());MvcEndpointSecurityInterceptor securityInterceptor = new MvcEndpointSecurityInterceptor(this.managementServerProperties.getSecurity().isEnabled(),this.managementServerProperties.getSecurity().getRoles());mapping.setSecurityInterceptor(securityInterceptor);for (EndpointHandlerMappingCustomizer customizer : this.mappingCustomizers) {customizer.customize(mapping);}return mapping;}private CorsConfiguration getCorsConfiguration(EndpointCorsProperties properties) {if (CollectionUtils.isEmpty(properties.getAllowedOrigins())) {return null;}CorsConfiguration configuration = new CorsConfiguration();configuration.setAllowedOrigins(properties.getAllowedOrigins());if (!CollectionUtils.isEmpty(properties.getAllowedHeaders())) {configuration.setAllowedHeaders(properties.getAllowedHeaders());}if (!CollectionUtils.isEmpty(properties.getAllowedMethods())) {configuration.setAllowedMethods(properties.getAllowedMethods());}if (!CollectionUtils.isEmpty(properties.getExposedHeaders())) {configuration.setExposedHeaders(properties.getExposedHeaders());}if (properties.getMaxAge() != null) {configuration.setMaxAge(properties.getMaxAge());}if (properties.getAllowCredentials() != null) {configuration.setAllowCredentials(properties.getAllowCredentials());}return configuration;}@Bean@ConditionalOnMissingBeanpublic MvcEndpoints mvcEndpoints() {return new MvcEndpoints();}@Bean@ConditionalOnBean(EnvironmentEndpoint.class)@ConditionalOnEnabledEndpoint("env")public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {return new EnvironmentMvcEndpoint(delegate);}@Bean@ConditionalOnMissingBean@ConditionalOnEnabledEndpoint("heapdump")public HeapdumpMvcEndpoint heapdumpMvcEndpoint() {return new HeapdumpMvcEndpoint();}@Bean@ConditionalOnBean(HealthEndpoint.class)@ConditionalOnEnabledEndpoint("health")public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate,ManagementServerProperties managementServerProperties) {HealthMvcEndpoint healthMvcEndpoint = new HealthMvcEndpoint(delegate,this.managementServerProperties.getSecurity().isEnabled(),managementServerProperties.getSecurity().getRoles());if (this.healthMvcEndpointProperties.getMapping() != null) {healthMvcEndpoint.addStatusMapping(this.healthMvcEndpointProperties.getMapping());}return healthMvcEndpoint;}@Bean@ConditionalOnBean(LoggersEndpoint.class)@ConditionalOnEnabledEndpoint("loggers")public LoggersMvcEndpoint loggersMvcEndpoint(LoggersEndpoint delegate) {return new LoggersMvcEndpoint(delegate);}@Bean@ConditionalOnBean(MetricsEndpoint.class)@ConditionalOnEnabledEndpoint("metrics")public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {return new MetricsMvcEndpoint(delegate);}@Bean@ConditionalOnEnabledEndpoint("logfile")@Conditional(LogFileCondition.class)public LogFileMvcEndpoint logfileMvcEndpoint() {return new LogFileMvcEndpoint();}@Bean@ConditionalOnBean(ShutdownEndpoint.class)@ConditionalOnEnabledEndpoint(value = "shutdown", enabledByDefault = false)public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {return new ShutdownMvcEndpoint(delegate);}@Bean@ConditionalOnBean(AuditEventRepository.class)@ConditionalOnEnabledEndpoint("auditevents")public AuditEventsMvcEndpoint auditEventMvcEndpoint(AuditEventRepository auditEventRepository) {return new AuditEventsMvcEndpoint(auditEventRepository);}private static class LogFileCondition extends SpringBootCondition {@Overridepublic ConditionOutcome getMatchOutcome(ConditionContext context,AnnotatedTypeMetadata metadata) {Environment environment = context.getEnvironment();String config = environment.resolvePlaceholders("${logging.file:}");ConditionMessage.Builder message = ConditionMessage.forCondition("Log File");if (StringUtils.hasText(config)) {return ConditionOutcome.match(message.found("logging.file").items(config));}config = environment.resolvePlaceholders("${logging.path:}");if (StringUtils.hasText(config)) {return ConditionOutcome.match(message.found("logging.path").items(config));}config = new RelaxedPropertyResolver(environment, "endpoints.logfile.").getProperty("external-file");if (StringUtils.hasText(config)) {return ConditionOutcome.match(message.found("endpoints.logfile.external-file").items(config));}return ConditionOutcome.noMatch(message.didNotFind("logging file").atAll());}}}

紅色部分:

4.2.1.獲取endpoint,Set<MvcEndpoint> endpoints = mvcEndpoints().getEndpoints();?

方法如下:

@Overridepublic void afterPropertiesSet() throws Exception {Collection<MvcEndpoint> existing = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, MvcEndpoint.class).values();this.endpoints.addAll(existing);this.customTypes = findEndpointClasses(existing);@SuppressWarnings("rawtypes")Collection<Endpoint> delegates = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, Endpoint.class).values();for (Endpoint<?> endpoint : delegates) {if (isGenericEndpoint(endpoint.getClass()) && endpoint.isEnabled()) {EndpointMvcAdapter adapter = new EndpointMvcAdapter(endpoint);String path = determinePath(endpoint,this.applicationContext.getEnvironment());if (path != null) {adapter.setPath(path);}this.endpoints.add(adapter);}}}

獲取容器中的MvcEndpoint接口實現(xiàn)類。

4.2.2.實例化EndpointHandlerMapping?

EndpointHandlerMapping mapping = new EndpointHandlerMapping(endpoints,
corsConfiguration);

創(chuàng)建實例

/*** Create a new {@link EndpointHandlerMapping} instance. All {@link Endpoint}s will be* detected from the {@link ApplicationContext}. The endpoints will accepts CORS* requests based on the given {@code corsConfiguration}.* @param endpoints the endpoints* @param corsConfiguration the CORS configuration for the endpoints* @since 1.3.0*/public EndpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints,CorsConfiguration corsConfiguration) {super(endpoints, corsConfiguration);}

4.2.3.設(shè)置安全過濾器

MvcEndpointSecurityInterceptor securityInterceptor = new MvcEndpointSecurityInterceptor(
this.managementServerProperties.getSecurity().isEnabled(),
this.managementServerProperties.getSecurity().getRoles());
mapping.setSecurityInterceptor(securityInterceptor);

定義:

/*** Security interceptor for MvcEndpoints.** @author Madhura Bhave* @since 1.5.0*/ public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {private static final Log logger = LogFactory.getLog(MvcEndpointSecurityInterceptor.class);private final boolean secure;private final List<String> roles;private AtomicBoolean loggedUnauthorizedAttempt = new AtomicBoolean();public MvcEndpointSecurityInterceptor(boolean secure, List<String> roles) {this.secure = secure;this.roles = roles;}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {if (CorsUtils.isPreFlightRequest(request) || !this.secure) {return true;}HandlerMethod handlerMethod = (HandlerMethod) handler;if (HttpMethod.OPTIONS.matches(request.getMethod())&& !(handlerMethod.getBean() instanceof MvcEndpoint)) {return true;}MvcEndpoint mvcEndpoint = (MvcEndpoint) handlerMethod.getBean();if (!mvcEndpoint.isSensitive()) {return true;}if (isUserAllowedAccess(request)) {return true;}sendFailureResponse(request, response);return false;}private boolean isUserAllowedAccess(HttpServletRequest request) {AuthoritiesValidator authoritiesValidator = null;if (isSpringSecurityAvailable()) {authoritiesValidator = new AuthoritiesValidator();}for (String role : this.roles) {if (request.isUserInRole(role)) {return true;}if (authoritiesValidator != null && authoritiesValidator.hasAuthority(role)) {return true;}}return false;}private boolean isSpringSecurityAvailable() {return ClassUtils.isPresent("org.springframework.security.config.annotation.web.WebSecurityConfigurer",getClass().getClassLoader());}private void sendFailureResponse(HttpServletRequest request,HttpServletResponse response) throws Exception {if (request.getUserPrincipal() != null) {String roles = StringUtils.collectionToDelimitedString(this.roles, " ");response.sendError(HttpStatus.FORBIDDEN.value(),"Access is denied. User must have one of the these roles: " + roles);}else {logUnauthorizedAttempt();response.sendError(HttpStatus.UNAUTHORIZED.value(),"Full authentication is required to access this resource.");}}private void logUnauthorizedAttempt() {if (this.loggedUnauthorizedAttempt.compareAndSet(false, true)&& logger.isInfoEnabled()) {logger.info("Full authentication is required to access "+ "actuator endpoints. Consider adding Spring Security "+ "or set 'management.security.enabled' to false.");}}/*** Inner class to check authorities using Spring Security (when available).*/private static class AuthoritiesValidator {private boolean hasAuthority(String role) {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();if (authentication != null) {for (GrantedAuthority authority : authentication.getAuthorities()) {if (authority.getAuthority().equals(role)) {return true;}}}return false;}}}

4.2.4. 自定義EndpointHandlerMapping?

@FunctionalInterface public interface EndpointHandlerMappingCustomizer {/*** Customize the specified {@link EndpointHandlerMapping}.* @param mapping the {@link EndpointHandlerMapping} to customize*/void customize(EndpointHandlerMapping mapping);}

5.映射的實現(xiàn)EndpointWebMvcManagementContextConfiguration

@Bean@ConditionalOnBean(EnvironmentEndpoint.class)@ConditionalOnEnabledEndpoint("env")public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {return new EnvironmentMvcEndpoint(delegate);}@Bean@ConditionalOnMissingBean@ConditionalOnEnabledEndpoint("heapdump")public HeapdumpMvcEndpoint heapdumpMvcEndpoint() {return new HeapdumpMvcEndpoint();}@Bean@ConditionalOnBean(HealthEndpoint.class)@ConditionalOnEnabledEndpoint("health")public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate,ManagementServerProperties managementServerProperties) {HealthMvcEndpoint healthMvcEndpoint = new HealthMvcEndpoint(delegate,this.managementServerProperties.getSecurity().isEnabled(),managementServerProperties.getSecurity().getRoles());if (this.healthMvcEndpointProperties.getMapping() != null) {healthMvcEndpoint.addStatusMapping(this.healthMvcEndpointProperties.getMapping());}return healthMvcEndpoint;}@Bean@ConditionalOnBean(LoggersEndpoint.class)@ConditionalOnEnabledEndpoint("loggers")public LoggersMvcEndpoint loggersMvcEndpoint(LoggersEndpoint delegate) {return new LoggersMvcEndpoint(delegate);}@Bean@ConditionalOnBean(MetricsEndpoint.class)@ConditionalOnEnabledEndpoint("metrics")public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {return new MetricsMvcEndpoint(delegate);}@Bean@ConditionalOnEnabledEndpoint("logfile")@Conditional(LogFileCondition.class)public LogFileMvcEndpoint logfileMvcEndpoint() {return new LogFileMvcEndpoint();}@Bean@ConditionalOnBean(ShutdownEndpoint.class)@ConditionalOnEnabledEndpoint(value = "shutdown", enabledByDefault = false)public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {return new ShutdownMvcEndpoint(delegate);}@Bean@ConditionalOnBean(AuditEventRepository.class)@ConditionalOnEnabledEndpoint("auditevents")public AuditEventsMvcEndpoint auditEventMvcEndpoint(AuditEventRepository auditEventRepository) {return new AuditEventsMvcEndpoint(auditEventRepository);}

最終的映射來自MvcEndpoint的各種實現(xiàn)

以health為例:

@ActuatorGetMapping@ResponseBodypublic Object invoke(HttpServletRequest request, Principal principal) {if (!getDelegate().isEnabled()) {// Shouldn't happen because the request mapping should not be registeredreturn getDisabledResponse();}Health health = getHealth(request, principal);HttpStatus status = getStatus(health);if (status != null) {return new ResponseEntity<>(health, status);}return health;}

其中,@ActuatorGetMapping注解等同于@RequestMapping

/*** Specialized {@link RequestMapping} for {@link RequestMethod#GET GET} requests that* produce {@code application/json} or* {@code application/vnd.spring-boot.actuator.v1+json} responses.** @author Andy Wilkinson*/ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @RequestMapping(method = RequestMethod.GET, produces = {ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON_VALUE,MediaType.APPLICATION_JSON_VALUE }) @interface ActuatorGetMapping {/*** Alias for {@link RequestMapping#value}.* @return the value*/@AliasFor(annotation = RequestMapping.class)String[] value() default {};}

注意,其中涉及到非常重要的一個類:EndpointMvcAdapter,它代理了MvcEndpoint,實現(xiàn)其invoke方法

/*** Adapter class to expose {@link Endpoint}s as {@link MvcEndpoint}s.** @author Dave Syer* @author Andy Wilkinson*/ public class EndpointMvcAdapter extends AbstractEndpointMvcAdapter<Endpoint<?>> {/*** Create a new {@link EndpointMvcAdapter}.* @param delegate the underlying {@link Endpoint} to adapt.*/public EndpointMvcAdapter(Endpoint<?> delegate) {super(delegate);}@Override@ActuatorGetMapping@ResponseBodypublic Object invoke() {return super.invoke();}}

總結(jié):

1.代理層

?2.實現(xiàn)層

3.代理邏輯

以HealthMvcEndpoint為例講述:

HealthMvcEndpoint主方法

@ActuatorGetMapping@ResponseBodypublic Object invoke(HttpServletRequest request, Principal principal) {if (!getDelegate().isEnabled()) {// Shouldn't happen because the request mapping should not be registeredreturn getDisabledResponse();} Health health = getHealth(request, principal);HttpStatus status = getStatus(health);if (status != null) {return new ResponseEntity<>(health, status);}return health;}

調(diào)用邏輯

private Health getHealth(HttpServletRequest request, Principal principal) {long accessTime = System.currentTimeMillis();if (isCacheStale(accessTime)) {this.lastAccess = accessTime;this.cached = getDelegate().invoke();}if (exposeHealthDetails(request, principal)) {return this.cached;}return Health.status(this.cached.getStatus()).build();}

delegate獲取由HealthMvcEndpoint構(gòu)造方法注入

public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure,List<String> roles) {super(delegate);this.secure = secure;setupDefaultStatusMapping();this.roles = roles;}

觸發(fā)HealthEndpoint#invoke()方法:

/*** Invoke all {@link HealthIndicator} delegates and collect their health information.*/@Overridepublic Health invoke() {return this.healthIndicator.health();}

HealthIndicator接口代理了其子類:

?

轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/6678982.html

總結(jié)

以上是生活随笔為你收集整理的spring boot actuator工作原理之http服务暴露源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品扒开腿做爽爽爽视频 | 成人毛片网站 | 国产不卡av在线 | 91中文字幕视频 | 伊人性视频 | 久久精品99久久久久久 | 日本免费a级片 | 欧美一级做性受免费大片免费 | 欧美高潮视频 | 国产特黄级aaaaa片免 | 玖草视频在线 | 一对一色视频聊天a | 四虎在线免费观看 | 免费观看理伦片在线播放视频软件 | 亚洲色图首页 | 国产欧美日韩专区发布 | 一本久 | wwwwww色| av在线.com | 一级欧美一级日韩片 | 久草影视在线 | 怡春院国产 | 黄色一级录像片 | 亚洲少妇xxx | 国产免费麻豆 | 少妇特黄一区二区三区 | 欧美日韩制服 | 亚洲图片视频小说 | 住在隔壁的她动漫免费观看全集下载 | 国产偷亚洲偷欧美偷精品 | 国产成人a亚洲精v品无码 | 国产精品一区二区三区久久久 | 视频一区国产精品 | 欧美aaa在线观看 | 天天操夜夜干 | 99国产精品久久久久久久 | 肥熟女一区二区三肥熟女 | 国产综合欧美 | 欧美性视频播放 | www.伊人.com| 日本极品喷水 | 黄网站免费大全入口 | 一区二区欧美在线 | 亚洲福利午夜 | 国产亚洲性欧美日韩在线观看软件 | aa黄色大片| 啪啪短视频 | 宅男午夜影院 | 精品人妻午夜一区二区三区四区 | 性爱免费在线视频 | 大胸喷奶水www视频妖精网站 | 久久爱一区 | 伊人毛片 | a毛片在线 | 潘金莲三级野外 | 日韩每日更新 | 高潮喷水一区二区三区 | 国产污视频在线播放 | 欧美精品一区在线 | 精品免费看 | 欧美日韩国产免费一区二区三区 | 国产亚洲欧美视频 | 色婷婷综合久久久久中文一区二区 | 亚洲第一色区 | 夜夜骚视频 | 97在线免费公开视频 | 一区二区亚洲视频 | 亚洲人成色777777精品音频 | 亚洲精品成人在线 | 欧美日韩久久婷婷 | 国产精品久久777777毛茸茸 | 美国色综合 | 黄色片久久久久 | 国产91精品ai换脸 | 久久久精品动漫 | 亚洲中文字幕97久久精品少妇 | 又大又粗欧美黑人aaaaa片 | 国产八区| 久久精品国产亚洲av蜜臀色欲 | 国产一区免费观看 | 国产九色av | 91欧美日韩麻豆精品 | 开心激情亚洲 | 新版红楼梦在线高清免费观看 | 99视频导航 | 男人天堂视频在线观看 | 中国男人操女人 | 精品久久久久久亚洲综合网站 | 免费性网站 | 久久久无码18禁高潮喷水 | 亚洲hh | 岛国精品在线播放 | 观看免费av| 337p亚洲欧洲色噜噜噜 | 日本aa在线观看 | 国产精品主播一区二区 | 五十路中出 | 日韩免费高清一区二区 | 老司机午夜视频 |