Spring Boot Actuator 使用
转载于:https://www.jianshu.com/p/af9738634a21
Spring Boot 的 Actuator 提供了很多生产级的特性,比如监控和度量Spring Boot 应用程序。Actuator 的这些特性可以通过众多 REST 接口、远程 shell 和 JMX 获得。
一、Actuator 的 REST 接口
Spring Boot Actuator 的关键特性是在应用程序里提供众多 Web 接口,通过它们了解应用程序运行时的内部状况。Actuator 提供了 13 个接口,可以分为三大类:配置接口、度量接口和其它接口,具体如下表所示。
| HTTP 方法 | 路径 | 描述 |
|---|---|---|
| GET | /autoconfig | 提供了一份自动配置报告,记录哪些自动配置条件通过了,哪些没通过 |
| GET | /configprops | 描述配置属性(包含默认值)如何注入Bean |
| GET | /beans | 描述应用程序上下文里全部的Bean,以及它们的关系 |
| GET | /dump | 获取线程活动的快照 |
| GET | /env | 获取全部环境属性 |
| GET | /env/{name} | 根据名称获取特定的环境属性值 |
| GET | /health | 报告应用程序的健康指标,这些值由HealthIndicator的实现类提供 |
| GET | /info | 获取应用程序的定制信息,这些信息由info打头的属性提供 |
| GET | /mappings | 描述全部的URI路径,以及它们和控制器(包含Actuator端点)的映射关系 |
| GET | /metrics | 报告各种应用程序度量信息,比如内存用量和HTTP请求计数 |
| GET | /metrics/{name} | 报告指定名称的应用程序度量值 |
| POST | /shutdown | 关闭应用程序,要求endpoints.shutdown.enabled设置为true |
| GET | /trace | 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等) |
要启用 Actuator 的端点,只要在项目中引入 Actuator 的依赖即可。对于 Maven 依赖,引入的依赖是这样的:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
1. 查看配置明细
Actuator 有一些接口不仅可以显示组件映射关系,还可以告诉你自动配置在配置 Spring 应用程序上下文时做了哪些决策。
1.1 获得 Bean 装配报告
要了解应用程序中 Spring 上下文的情况,最重要的接口就是 /beans。它会返回一个 JSON 文档,描述上下文里每个 bean 的情况,包括其 Java 类型以及注入的其它 bean。返回的信息如下所示:
[
{
"context": "application",
"parent": null,
"beans": [
{
"bean": "demoApplication",
"aliases": [],
"scope": "singleton",
"type": "com.example.DemoApplication$$EnhancerBySpringCGLIB$$88686e04",
"resource": "null",
"dependencies": []
},
{
"bean": "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory",
"aliases": [],
"scope": "singleton",
"type": "org.springframework.core.type.classreading.CachingMetadataReaderFactory",
"resource": "null",
"dependencies": []
}
]
}
]
所有的 Bean 条目都有五类信息:
- bean:Spring 应用程序上下文中的 Bean 名称或 ID。
- resource:.class 文件的物理位置,通常是一个 URL,指向构建出的 JAR 文件。这会随着应用程序的构建和运行方式发生变化。
- dependencies:当前 Bean 注入的 Bean ID 列表。
- scope:Bean 的作用域(通常是单例,这也是默认作用域)。
- type:Bean 的 Java 类型。
1.2 详解自动配置
/autoconfig接口能告诉你为什么会有这个 bean ,或者为什么没有这个 bean。
{
"positiveMatches": {
"AuditAutoConfiguration#auditListener": [
{
"condition": "OnBeanCondition",
"message": "@ConditionalOnMissingBean (types: org.springframework.boot.actuate.audit.listener.AbstractAuditListener; SearchStrategy: all) did not find any beans"
}
],
"MultipartAutoConfiguration#multipartConfigElement": [
{
"condition": "OnBeanCondition",
"message": "@ConditionalOnMissingBean (types: javax.servlet.MultipartConfigElement; SearchStrategy: all) did not find any beans"
}
]
},
"negativeMatches": {
"AuditAutoConfiguration#authenticationAuditListener": {
"notMatched": [
{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass did not find required class 'org.springframework.security.authentication.event.AbstractAuthenticationEvent'"
}
],
"matched": []
},
"AuditAutoConfiguration#authorizationAuditListener": {
"notMatched": [
{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass did not find required class 'org.springframework.security.access.event.AbstractAuthorizationEvent'"
}
],
"matched": []
}
}
}
1.3 查看配置属性
/env接口会生成应用程序可用的所有环境属性的列表,无论这些属性是否用到。这其中包括环境变量、JVM 属性、命令行参数,以及 application.properties 或 application.yml 文件提供的属性。
{
"profiles": [],
"server.ports": {
"local.server.port": 8080
},
"servletContextInitParams": {},
"systemProperties": {
"java.runtime.name": "Java(TM) SE Runtime Environment",
"spring.output.ansi.enabled": "always",
"sun.boot.library.path": "/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib",
"java.vm.version": "25.121-b13",
"gopherProxySet": "false",
"java.vm.vendor": "Oracle Corporation",
"java.vendor.url": "http://java.oracle.com/",
"path.separator": ":",
"idea.launcher.port": "7532",
"java.vm.name": "Java HotSpot(TM) 64-Bit Server VM",
"file.encoding.pkg": "sun.io",
"user.country": "CN",
"sun.java.launcher": "SUN_STANDARD",
"sun.os.patch.level": "unknown",
"PID": "2716",
"java.vm.specification.name": "Java Virtual Machine Specification",
"user.dir": "/Users/FlySheep/FlySheep/Code/ServerCode/SpringBoot_Demo/demo",
"java.runtime.version": "1.8.0_121-b13",
"java.awt.graphicsenv": "sun.awt.CGraphicsEnvironment",
"org.jboss.logging.provider": "slf4j",
"java.endorsed.dirs": "/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/endorsed",
"os.arch": "x86_64",
"visualvm.id": "11136812717769",
"java.io.tmpdir": "/var/folders/d6/zn9yrwns46j4pwbl1_mv_6hw0000gn/T/",
"line.separator": "\n",
"java.vm.specification.vendor": "Oracle Corporation",
"os.name": "Mac OS X",
"sun.jnu.encoding": "UTF-8",
"spring.beaninfo.ignore": "true",
"java.library.path": "/Users/FlySheep/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.",
"java.specification.name": "Java Platform API Specification",
"java.class.version": "52.0",
"sun.management.compiler": "HotSpot 64-Bit Tiered Compilers",
"os.version": "10.11",
"user.home": "/Users/FlySheep",
"catalina.useNaming": "false",
"user.timezone": "Asia/Shanghai",
"java.awt.printerjob": "sun.lwawt.macosx.CPrinterJob",
"file.encoding": "UTF-8",
"idea.launcher.bin.path": "/Applications/IntelliJ IDEA.app/Contents/bin",
"java.specification.version": "1.8",
"catalina.home": "/private/var/folders/d6/zn9yrwns46j4pwbl1_mv_6hw0000gn/T/tomcat.6698906163877756728.8080",
"java.class.path": "/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/lib/tools.jar:/Users/FlySheep/FlySheep/Code/ServerCode/SpringBoot_Demo/demo/target/classes:/Users/FlySheep/.m2/repository/org/springframework/boot/spring-boot-starter-web/1.5.2.RELEASE/spring-boot-starter-web-1.5.2.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/boot/spring-boot-starter/1.5.2.RELEASE/spring-boot-starter-1.5.2.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/boot/spring-boot/1.5.2.RELEASE/spring-boot-1.5.2.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/1.5.2.RELEASE/spring-boot-autoconfigure-1.5.2.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/boot/spring-boot-starter-logging/1.5.2.RELEASE/spring-boot-starter-logging-1.5.2.RELEASE.jar:/Users/FlySheep/.m2/repository/ch/qos/logback/logback-classic/1.1.11/logback-classic-1.1.11.jar:/Users/FlySheep/.m2/repository/ch/qos/logback/logback-core/1.1.11/logback-core-1.1.11.jar:/Users/FlySheep/.m2/repository/org/slf4j/jcl-over-slf4j/1.7.24/jcl-over-slf4j-1.7.24.jar:/Users/FlySheep/.m2/repository/org/slf4j/jul-to-slf4j/1.7.24/jul-to-slf4j-1.7.24.jar:/Users/FlySheep/.m2/repository/org/slf4j/log4j-over-slf4j/1.7.24/log4j-over-slf4j-1.7.24.jar:/Users/FlySheep/.m2/repository/org/yaml/snakeyaml/1.17/snakeyaml-1.17.jar:/Users/FlySheep/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/1.5.2.RELEASE/spring-boot-starter-tomcat-1.5.2.RELEASE.jar:/Users/FlySheep/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.11/tomcat-embed-core-8.5.11.jar:/Users/FlySheep/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/8.5.11/tomcat-embed-el-8.5.11.jar:/Users/FlySheep/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/8.5.11/tomcat-embed-websocket-8.5.11.jar:/Users/FlySheep/.m2/repository/org/hibernate/hibernate-validator/5.3.4.Final/hibernate-validator-5.3.4.Final.jar:/Users/FlySheep/.m2/repository/javax/validation/validation-api/1.1.0.Final/validation-api-1.1.0.Final.jar:/Users/FlySheep/.m2/repository/org/jboss/logging/jboss-logging/3.3.0.Final/jboss-logging-3.3.0.Final.jar:/Users/FlySheep/.m2/repository/com/fasterxml/classmate/1.3.3/classmate-1.3.3.jar:/Users/FlySheep/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.8.7/jackson-databind-2.8.7.jar:/Users/FlySheep/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.8.0/jackson-annotations-2.8.0.jar:/Users/FlySheep/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.8.7/jackson-core-2.8.7.jar:/Users/FlySheep/.m2/repository/org/springframework/spring-web/4.3.7.RELEASE/spring-web-4.3.7.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/spring-aop/4.3.7.RELEASE/spring-aop-4.3.7.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/spring-beans/4.3.7.RELEASE/spring-beans-4.3.7.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/spring-context/4.3.7.RELEASE/spring-context-4.3.7.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/spring-webmvc/4.3.7.RELEASE/spring-webmvc-4.3.7.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/spring-expression/4.3.7.RELEASE/spring-expression-4.3.7.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/boot/spring-boot-starter-actuator/1.5.2.RELEASE/spring-boot-starter-actuator-1.5.2.RELEASE.jar:/Users/FlySheep/.m2/repository/org/springframework/boot/spring-boot-actuator/1.5.2.RELEASE/spring-boot-actuator-1.5.2.RELEASE.jar:/Users/FlySheep/.m2/repository/org/slf4j/slf4j-api/1.7.24/slf4j-api-1.7.24.jar:/Users/FlySheep/.m2/repository/org/springframework/spring-core/4.3.7.RELEASE/spring-core-4.3.7.RELEASE.jar:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar",
"user.name": "FlySheep",
"java.vm.specification.version": "1.8",
"sun.java.command": "com.intellij.rt.execution.application.AppMain com.example.DemoApplication",
"java.home": "/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre",
"sun.arch.data.model": "64",
"user.language": "zh",
"java.specification.vendor": "Oracle Corporation",
"awt.toolkit": "sun.lwawt.macosx.LWCToolkit",
"java.vm.info": "mixed mode",
"java.version": "1.8.0_121",
"java.ext.dirs": "/Users/FlySheep/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java",
"sun.boot.class.path": "/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/classes",
"java.awt.headless": "true",
"java.vendor": "Oracle Corporation",
"catalina.base": "/private/var/folders/d6/zn9yrwns46j4pwbl1_mv_6hw0000gn/T/tomcat.6698906163877756728.8080",
"file.separator": "/",
"java.vendor.url.bug": "http://bugreport.sun.com/bugreport/",
"sun.io.unicode.encoding": "UnicodeBig",
"sun.cpu.endian": "little",
"sun.cpu.isalist": ""
},
"systemEnvironment": {
"PATH": "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin:/usr/local/mysql/bin:/Users/FlySheep/FlySheep/JavaTools/apache-maven-3.3.9/bin/bin",
"SHELL": "/bin/zsh",
"PAGER": "less",
"LSCOLORS": "Gxfxcxdxbxegedabagacad",
"OLDPWD": "/Applications/IntelliJ IDEA.app/Contents/bin",
"USER": "FlySheep",
"VERSIONER_PYTHON_PREFER_32_BIT": "no",
"ZSH": "/Users/FlySheep/.oh-my-zsh",
"TMPDIR": "/var/folders/d6/zn9yrwns46j4pwbl1_mv_6hw0000gn/T/",
"SSH_AUTH_SOCK": "/private/tmp/com.apple.launchd.vZEKsGdZ1T/Listeners",
"JAVA_MAIN_CLASS_2716": "com.intellij.rt.execution.application.AppMain",
"XPC_FLAGS": "0x0",
"VERSIONER_PYTHON_VERSION": "2.7",
"__CF_USER_TEXT_ENCODING": "0x1F5:0x19:0x34",
"Apple_PubSub_Socket_Render": "/private/tmp/com.apple.launchd.5VgRuDCQ5D/Render",
"LOGNAME": "FlySheep",
"LESS": "-R",
"LC_CTYPE": "",
"PWD": "/Users/FlySheep/FlySheep/Code/ServerCode/SpringBoot_Demo/demo",
"XPC_SERVICE_NAME": "com.jetbrains.intellij.136992",
"HOME": "/Users/FlySheep"
},
"applicationConfig: [classpath:/application.properties]": {
"management.security.enabled": "false"
}
}
基本上,任何能给Spring Boot 应用程序提供属性的属性源都会列在 /env 的结果里,同时会显示具体的属性。
为了避免敏感信息暴露到 /env 里,所有名为password、secret、key(或者名字中最后一段是这些)的属性在 /env 里都会加上“*”。举个例子,如果有一个属性名字是database.password,那么它在/env中的显示效果是这样的:
"database.password":"******"
/env 接口还能用来获取单个属性的值,只需要在请求时在 /env 后加上属性名即可。
1.4 查看属性的使用方法
/configprops 接口会生成一个报告,说明属性如何进行设置(注入或其他方式)。
{
"endpoints-org.springframework.boot.actuate.endpoint.EndpointProperties": {
"prefix": "endpoints",
"properties": {
"enabled": true,
"sensitive": null
}
},
"management.info-org.springframework.boot.actuate.autoconfigure.InfoContributorProperties": {
"prefix": "management.info",
"properties": {
"git": {
"mode": "SIMPLE"
}
}
},
"metricsEndpoint": {
"prefix": "endpoints.metrics",
"properties": {
"id": "metrics",
"sensitive": true,
"enabled": true
}
},
"spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties": {
"prefix": "spring.jackson",
"properties": {
"propertyNamingStrategy": null,
"defaultPropertyInclusion": null,
"dateFormat": null,
"timeZone": null,
"locale": null,
"jodaDateTimeFormat": null
}
},
"heapdumpMvcEndpoint": {
"prefix": "endpoints.heapdump",
"properties": {
"path": "/heapdump",
"sensitive": true,
"enabled": true
}
},
"endpoints.cors-org.springframework.boot.actuate.autoconfigure.EndpointCorsProperties": {
"prefix": "endpoints.cors",
"properties": {
"allowedOrigins": [],
"maxAge": 1800,
"exposedHeaders": [],
"allowedHeaders": [],
"allowedMethods": [],
"allowCredentials": null
}
},
"environmentMvcEndpoint": {
"prefix": "endpoints.env",
"properties": {
"path": "/env"
}
},
"environmentEndpoint": {
"prefix": "endpoints.env",
"properties": {
"id": "env",
"sensitive": true,
"enabled": true
}
},
"spring.http.multipart-org.springframework.boot.autoconfigure.web.MultipartProperties": {
"prefix": "spring.http.multipart",
"properties": {
"maxRequestSize": "10MB",
"fileSizeThreshold": "0",
"location": null,
"maxFileSize": "1MB",
"enabled": true,
"resolveLazily": false
}
},
"spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties": {
"prefix": "spring.info",
"properties": {
"build": {
"location": {}
},
"git": {
"location": {}
}
}
},
"auditEventsEndpoint": {
"prefix": "endpoints.auditevents",
"properties": {
"enabled": true
}
},
"traceEndpoint": {
"prefix": "endpoints.trace",
"properties": {
"id": "trace",
"sensitive": true,
"enabled": true
}
},
"metricsMvcEndpoint": {
"prefix": "endpoints.metrics",
"properties": {
"path": "/metrics"
}
},
"infoEndpoint": {
"prefix": "endpoints.info",
"properties": {
"id": "info",
"sensitive": false,
"enabled": true
}
},
"auditEventMvcEndpoint": {
"prefix": "endpoints.auditevents",
"properties": {
"path": "/auditevents",
"sensitive": true,
"enabled": true
}
},
"management.trace-org.springframework.boot.actuate.trace.TraceProperties": {
"prefix": "management.trace",
"properties": {
"include": [
"COOKIES",
"REQUEST_HEADERS",
"RESPONSE_HEADERS",
"ERRORS"
]
}
},
"spring.resources-org.springframework.boot.autoconfigure.web.ResourceProperties": {
"prefix": "spring.resources",
"properties": {
"cachePeriod": null,
"addMappings": true,
"chain": {
"cache": true,
"htmlApplicationCache": false,
"gzipped": false,
"strategy": {
"fixed": {
"enabled": false,
"paths": [
"/**"
],
"version": null
},
"content": {
"enabled": false,
"paths": [
"/**"
]
}
}
},
"staticLocations": [
"/",
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
]
}
},
"management.health.status-org.springframework.boot.actuate.autoconfigure.HealthIndicatorProperties": {
"prefix": "management.health.status",
"properties": {
"order": null
}
},
"healthMvcEndpoint": {
"prefix": "endpoints.health",
"properties": {
"path": "/health"
}
},
"serverProperties": {
"prefix": "server",
"properties": {
"address": null,
"maxHttpPostSize": 0,
"undertow": {
"maxHttpPostSize": 0,
"bufferSize": null,
"buffersPerRegion": null,
"ioThreads": null,
"workerThreads": null,
"directBuffers": null,
"accesslog": {
"enabled": null,
"pattern": "common",
"prefix": "access_log.",
"suffix": "log",
"dir": "/Users/FlySheep/FlySheep/Code/ServerCode/SpringBoot_Demo/demo/logs",
"rotate": true
}
},
"tomcat": {
"accesslog": {
"enabled": false,
"pattern": "common",
"directory": "logs",
"prefix": "access_log",
"suffix": ".log",
"rotate": true,
"renameOnRotate": false,
"requestAttributesEnabled": false,
"buffered": true
},
"internalProxies": "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|169\\.254\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}",
"protocolHeader": null,
"protocolHeaderHttpsValue": "https",
"portHeader": "X-Forwarded-Port",
"remoteIpHeader": null,
"basedir": null,
"backgroundProcessorDelay": 30,
"maxThreads": 0,
"minSpareThreads": 0,
"maxHttpPostSize": 0,
"redirectContextRoot": null,
"uriEncoding": null,
"maxConnections": 0,
"acceptCount": 0,
"additionalTldSkipPatterns": []
},
"displayName": "application",
"session": {
"timeout": null,
"trackingModes": null,
"persistent": false,
"storeDir": null,
"cookie": {
"name": null,
"domain": null,
"path": null,
"comment": null,
"httpOnly": null,
"secure": null,
"maxAge": null
}
},
"contextPath": null,
"error": {
"path": "/error",
"includeStacktrace": "NEVER"
},
"ssl": null,
"serverHeader": null,
"useForwardHeaders": null,
"port": null,
"maxHttpHeaderSize": 0,
"servletPath": "/",
"jspServlet": null,
"jetty": {
"maxHttpPostSize": 0,
"acceptors": null,
"selectors": null
},
"connectionTimeout": null
}
},
"spring.metrics.export-org.springframework.boot.actuate.metrics.export.MetricExportProperties": {
"prefix": "spring.metrics.export",
"properties": {
"excludes": null,
"statsd": {
"host": null,
"port": 8125,
"prefix": null
},
"includes": null,
"enabled": true,
"redis": {
"prefix": "spring.metrics.application.7a5b013db041f4a1b6c45b6456487d05",
"key": "******"
},
"aggregate": {
"prefix": "application.7a5b013db041f4a1b6c45b6456487d05",
"keyPattern": "k.d"
}
}
},
"configurationPropertiesReportEndpoint": {
"prefix": "endpoints.configprops",
"properties": {
"id": "configprops",
"sensitive": true,
"enabled": true
}
},
"healthEndpoint": {
"prefix": "endpoints.health",
"properties": {
"timeToLive": 1000,
"id": "health",
"sensitive": false,
"enabled": true
}
},
"loggersMvcEndpoint": {
"prefix": "endpoints.loggers",
"properties": {
"path": "/loggers"
}
},
"loggersEndpoint": {
"prefix": "endpoints.loggers",
"properties": {
"id": "loggers",
"sensitive": true,
"enabled": true
}
},
"endpoints.metrics.filter-org.springframework.boot.actuate.autoconfigure.MetricFilterProperties": {
"prefix": "endpoints.metrics.filter",
"properties": {
"counterSubmissions": [
"MERGED"
],
"gaugeSubmissions": [
"MERGED"
]
}
},
"dumpEndpoint": {
"prefix": "endpoints.dump",
"properties": {
"id": "dump",
"sensitive": true,
"enabled": true
}
},
"autoConfigurationReportEndpoint": {
"prefix": "endpoints.autoconfig",
"properties": {
"id": "autoconfig",
"sensitive": true,
"enabled": true
}
},
"endpoints.jmx-org.springframework.boot.actuate.autoconfigure.EndpointMBeanExportProperties": {
"prefix": "endpoints.jmx",
"properties": {
"uniqueNames": false,
"enabled": true,
"domain": ""
}
},
"spring.http.encoding-org.springframework.boot.autoconfigure.web.HttpEncodingProperties": {
"prefix": "spring.http.encoding",
"properties": {
"charset": "UTF-8",
"force": false,
"mapping": null,
"forceRequest": false,
"forceResponse": false
}
},
"shutdownEndpoint": {
"prefix": "endpoints.shutdown",
"properties": {
"id": "shutdown",
"sensitive": true,
"enabled": false
}
},
"beansEndpoint": {
"prefix": "endpoints.beans",
"properties": {
"id": "beans",
"sensitive": true,
"enabled": true
}
},
"managementServerProperties": {
"prefix": "management",
"properties": {
"security": {
"enabled": false,
"roles": [
"ACTUATOR"
],
"sessions": "STATELESS"
},
"address": null,
"port": null,
"addApplicationContextHeader": true,
"contextPath": "",
"ssl": null
}
},
"requestMappingEndpoint": {
"prefix": "endpoints.mappings",
"properties": {
"id": "mappings",
"sensitive": true,
"enabled": true
}
},
"endpoints.health-org.springframework.boot.actuate.autoconfigure.HealthMvcEndpointProperties": {
"prefix": "endpoints.health",
"properties": {
"mapping": {}
}
},
"spring.mvc-org.springframework.boot.autoconfigure.web.WebMvcProperties": {
"prefix": "spring.mvc",
"properties": {
"dateFormat": null,
"servlet": {
"loadOnStartup": -1
},
"staticPathPattern": "/**",
"dispatchOptionsRequest": true,
"dispatchTraceRequest": false,
"locale": null,
"ignoreDefaultModelOnRedirect": true,
"logResolvedException": false,
"async": {
"requestTimeout": null
},
"messageCodesResolverFormat": null,
"mediaTypes": {},
"view": {
"prefix": null,
"suffix": null
},
"localeResolver": "ACCEPT_HEADER",
"throwExceptionIfNoHandlerFound": false
}
},
"diskSpaceHealthIndicatorProperties": {
"prefix": "management.health.diskspace",
"properties": {
"path": "/Users/FlySheep/FlySheep/Code/ServerCode/SpringBoot_Demo/demo/.",
"threshold": 10485760
}
}
}
1.5 生成接口道控制器的映射
在应用程序相对较小的时候,很容易搞清楚控制器都映射到了哪些接口上。如果Web界面的控制器和请求处理方法数量多,那最好能有一个列表,罗列出应用程序发布的全部接口。/mappings 接口就提供了这么一个列表。
{
"/webjars/**": {
"bean": "resourceHandlerMapping"
},
"/**": {
"bean": "resourceHandlerMapping"
},
"/**/favicon.ico": {
"bean": "faviconHandlerMapping"
},
"{[/error]}": {
"bean": "requestMappingHandlerMapping",
"method": "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)"
},
"{[/error],produces=[text/html]}": {
"bean": "requestMappingHandlerMapping",
"method": "public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)"
},
"{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)"
},
"{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String)"
},
"{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String)"
},
"{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>)"
},
"{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}": {
"bean": "endpointHandlerMapping",
"method": "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"
},
"{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)"
},
"{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
"{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)"
},
"{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
}
}
这里我们可以看到不少接口的映射。每个映射的键都是一个字符串,其内容就是 Spring MVC 的 @RequestMapping 注解上设置的属性。实际上,这个字符串能让你清晰地了解控制器是如何映射的,哪怕不看源代码。每个映射的值都有两个属性:bean 和 method。bean 属性标识了 Spring Bean 的名字,映射源自这个Bean。method属性是映射对应方法的全限定方法签名。
2. 运行时指标
对运行时指标情况做一个快照,这对评估应用程序的健康情况很有帮助。Actuator 提供了一系列接口,让你能在运行时快速检查应用程序。
2.1 查看应用程序的指标值
关于运行中的应用程序,有很多有趣而且有用的信息。举个例子,了解应用程序的内存情况 (可用或空闲)有助于决定给JVM分配多少内存。对Web应用程序而言,不用查看Web服务器日志,如果请求失败或者是耗时太长,就可以大概知道内存的情况了。运行中的应用程序有诸多计数器和度量器,/metrics 接口提供了这些东西的快照。
{
"mem": 365004,
"mem.free": 153938,
"processors": 8,
"instance.uptime": 852279,
"uptime": 855002,
"systemload.average": 3.509765625,
"heap.committed": 316928,
"heap.init": 262144,
"heap.used": 162989,
"heap": 3728384,
"nonheap.committed": 50816,
"nonheap.init": 2496,
"nonheap.used": 48077,
"nonheap": 0,
"threads.peak": 18,
"threads.daemon": 16,
"threads.totalStarted": 23,
"threads": 18,
"classes": 5974,
"classes.loaded": 5974,
"classes.unloaded": 0,
"gc.ps_scavenge.count": 4,
"gc.ps_scavenge.time": 35,
"gc.ps_marksweep.count": 1,
"gc.ps_marksweep.time": 27,
"httpsessions.max": -1,
"httpsessions.active": 0,
"gauge.response.mappings": 4,
"gauge.response.configprops": 155,
"counter.status.200.mappings": 1,
"counter.status.200.configprops": 1
}
对 /metrics 接口提供的信息进行简单分类如下表:
| 分类 | 前缀 | 报告内容 |
|---|---|---|
| 垃圾收集器 | gc.* | 已经发生过的垃圾收集次数,以及垃圾收集所耗费的时间,适用于标记-清理垃圾收集器和并行垃圾收集器(数据源自java.lang.management. GarbageCollectorMXBean) |
| 内存 | mem.* | 分配给应用程序的内存数量和空闲的内存数量(数据源自java.lang. Runtime) |
| 堆 | heap.* | 当前内存用量(数据源自java.lang.management.MemoryUsage) |
| 类加载器 | classes.* | JVM类加载器加载与卸载的类的数量(数据源自java.lang. management.ClassLoadingMXBean) |
| 系统 | processors、instance.uptime、uptime、systemload.average | 系统信息,例如处理器数量(数据源自java.lang.Runtime)、运行时间(数据源自java.lang.management.RuntimeMXBean)、平均负载(数据源自java.lang.management.OperatingSystemMXBean) |
| 线程池 | thread.* | 线程、守护线程的数量,以及JVM启动后的线程数量峰值(数据源自 java.lang .management.ThreadMXBean) |
| 数据源 | datasource.* | 数据源连接的数量(源自数据源的元数据,仅当Spring应用程序上下文里存在 DataSource Bean 的时候才会有这个信息) |
| Tomcat 会话 | httpsessions.* | Tomcat的活跃会话数和最大会话数(数据源自嵌入式Tomcat的Bean,仅在使用嵌入式Tomcat服务器运行应用程序时才有这个信息) |
| HTTP | counter.status.、gauge.response. | 多种应用程序服务HTTP请求的度量值与计数器 |
请注意,这里的一些度量值,比如数据源和Tomcat会话,仅在应用程序中运行特定组件时才有数据。你还可以注册自己的度量信息。
HTTP的计数器和度量值需要做一点说明。counter.status 后的值是HTTP状态码,随后是所请求的路径。举个例子,counter.status.200.metrics 表明/metrics端点返回 200(OK) 状态码的次数。
HTTP的度量信息在结构上也差不多,却在报告另一类信息。它们全部以gauge.response 开头,,表明这是HTTP响应的度量信息。前缀后是对应的路径。度量值是以毫秒为单位的时间,反映了最近处理该路径请求的耗时。
这里还有几个特殊的值需要注意。root路径指向的是根路径或/。star-star代表了那些Spring 认为是静态资源的路径,包括图片、JavaScript和样式表,其中还包含了那些找不到的资源。这就是为什么你经常会看到 counter.status.404.star-star,这是返回了HTTP 404 (NOT FOUND) 状态的请求数。
/metrics 接口会返回所有的可用度量值,但你也可能只对某个值感兴趣。要获取单个值,请求时可以在URL后加上对应的键名。例如,要查看空闲内存大小,可以向/metrics/mem.free发一 个GET请求。
2.2 追踪 Web 请求
/trace 接口能报告所有Web请求的详细信息,包括请求方法、路径、时间戳以及请求和响应的头信息。
[
{
"timestamp": 1491279254447,
"info": {
"method": "GET",
"path": "/metrics",
"headers": {
"request": {
"host": "localhost:8080",
"connection": "keep-alive",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"accept-encoding": "gzip, deflate, sdch, br",
"accept-language": "zh-CN,zh;q=0.8,en;q=0.6",
"cookie": "JSESSIONID=24CCB83195B2A35F5193C97D2CD51D69"
},
"response": {
"X-Application-Context": "application",
"Content-Type": "application/vnd.spring-boot.actuator.v1+json;charset=UTF-8",
"Transfer-Encoding": "chunked",
"Date": "Tue, 04 Apr 2017 04:14:14 GMT",
"status": "200"
}
}
}
}
]
2.3 导出线程活动
在确认应用程序运行情况时,除了跟踪请求,了解线程活动也会很有帮助。/dump 接口会生成当前线程活动的快照。
2.4 监控应用程序健康状况
如果你想知道自己的应用程序是否在运行,可以直接访问/health 接口。在最简单的情况下,该端点会显示一个简单的JSON,内容如下:
{
"status": "UP",
"diskSpace": {
"status": "UP",
"total": 48978722816,
"free": 8812167168,
"threshold": 10485760
}
}
二、定制 Actuator
虽然Actuator提供了很多运行中Spring Boot应用程序的内部工作细节,但难免和你的需求有所偏差。也许你并不需要它提供的所有功能,想要关闭一些也说不定。或者,你需要对Actuator 稍作扩展,增加一些自定义的度量信息,以满足你对应用程序的需求。
1. 修改接口 ID
每个Actuator 接口都有一个ID用来决定接口的路径,比方说,/beans接口的默认ID就是beans。比如要修改 /beans 为 /instances,则设置如下:
endpoints.beans.id = instances
2. 启用和禁用接口
虽然Actuator的接口都很有用,但你不一定需要全部这些接口。默认情况下,所有接口(除 了/shutdown)都启用。比如要禁用 /metrics 接口,则可以设置如下:
endpoints.metrics.enabled = false
如果你只想打开一两个接口,那就先禁用全部接口,然后启用那几个你要的,这样更方便。
endpoints.enabled = false
endpoints.metrics.enabled = true
3. 添加自定义度量信息
Actuator 自动配置有两个实例 CounterService 和 GaugeService 可以用来计数使用,我们所要做的就是把它们的实例注入所需的 bean 然后调用相应的方法。除此之外,我们还可以实现 PublicMetrics 接口,提供自己需要的度量信息。
4. 创建自定义跟踪仓库
默认情况下,/trace 接口报告的跟踪信息都存储在内存仓库里,100个条目封顶。一旦仓库满了,就开始移除老的条目,给新的条目腾出空间。在开发阶段这没什么问题,但在生产环境中,大流量会造成跟踪信息还没来得及看就被丢弃。我们可以将那些跟踪条目存储在其他地方——既不消耗内存,又能长久保存的地方。只需实现Spring Boot的TraceRepository接口即可。
5. 插入自定义的健康指示器
实现 HealthIndicator 接口则可以实现自定义的健康指示器。
6. 保护 Actuator 接口
很多Actuator端点发布的信息都可能涉及敏感数据,还有一些端点,(比如/shutdown)非常危险,可以用来关闭应用程序。因此,保护这些端点尤为重要,能访问它们的只能是那些经过授权的客户端。
Spring Boot Actuator 使用的更多相关文章
- Complete Guide for Spring Boot Actuator
You are here to learn about Spring Boot Actuator for collecting metrics about your production grade ...
- springboot(十九):使用Spring Boot Actuator监控应用
微服务的特点决定了功能模块的部署是分布式的,大部分功能模块都是运行在不同的机器上,彼此通过服务调用进行交互,前后台的业务流会经过很多个微服务的处理和传递,出现了异常如何快速定位是哪个环节出现了问题? ...
- spring boot admin + spring boot actuator + erueka 微服务监控
关于spring boot actuator简单使用,请看 简单的spring boot actuator 使用,点击这里 spring boot admin 最新的正式版本是1.5.3 与 spri ...
- spring boot actuator 简单使用
spring boot admin + spring boot actuator + erueka 微服务监控 简单的spring boot actuator 使用 POM <dependenc ...
- 使用Spring Boot Actuator、Jolokia和Grafana实现准实时监控
由于最近在做监控方面的工作,因此也读了不少相关的经验分享.其中有这样一篇文章总结了一些基于Spring Boot的监控方案,因此翻译了一下,希望可以对大家有所帮助. 原文:Near real-time ...
- spring boot actuator专题
spring-boot-starter-actuator模块的实现对于实施微服务的中小团队来说,可以有效地减少监控系统在采集应用指标时的开发量.当然,它也并不是万能的,有时候我们也需要对其做一些简单的 ...
- 使用Spring Boot Actuator将指标导出到InfluxDB和Prometheus
使用Spring Boot Actuator将指标导出到InfluxDB和Prometheus Spring Boot Actuator是Spring Boot 2发布后修改最多的项目之一.它经过 ...
- (转)Spring Boot (十九):使用 Spring Boot Actuator 监控应用
http://www.ityouknow.com/springboot/2018/02/06/spring-boot-actuator.html 微服务的特点决定了功能模块的部署是分布式的,大部分功能 ...
- 朱晔和你聊Spring系列S1E7:简单好用的Spring Boot Actuator
阅读PDF版本 本文会来看一下Spring Boot Actuator提供给我们的监控端点Endpoint.健康检查Health和打点指标Metrics等所谓的Production-ready(生产环 ...
随机推荐
- django之用户表的继承
有这样一个场景,之前已经设计好了用户的信息表,但是再设计另外一个业务表的时候,信息有点重复,如何重新设计呢? 可以采用表的继承,让一个表作为基类,业务表就可以继承它 要注意以下几点 1 作为基类的表使 ...
- how find out what is causing Visual Studio to think each project is out of date
You can find out what is causing Visual Studio to think each project is out of date, and then addres ...
- JAVA Aes加解密详解
上篇随笔留了一个问题,两种加密结果不一样? 其实是内部实现方式不一样,具体见注释 /** * 提供密钥和向量进行加密 * * @param sSrc * @param key * @param iv ...
- leetcode438
public class Solution {;public IList<int> FindAnagrams(string s, string p) { List<int> l ...
- Delphi RTTI的应用(一)
1.获取DbgrdiEH 某一个选项的属性.加载到ComBox procedure TForm1.FormCreate(Sender: TObject); var PropInfo: PPropInf ...
- 微商城项目 请求接口封装中出现 callback && callback() 原理
http://www.imooc.com/wenda/detail/522579 因为逻辑运算符&& ||通常具有短路求值的特性即,如果只求部分值就可以得到整个表达式的值,那么剩下的部 ...
- Shiro HashedCredentialsMatcher 认证匹配
Shiro 提供了用于加密密码和验证密码服务的 CredentialsMatcher 接口,而 HashedCredentialsMatcher 正是 CredentialsMatcher 的一个实现 ...
- springboot整合mybatis遇到的那些坑
1.接口类(指*Mapper.java)在spring中注册的问题 当控制台打印如下信息: A component required a bean named '*Mapper' that could ...
- 转载:轻量级Config文件AppSettings节点编辑帮助类
using System.Configuration; using System.Windows.Forms; namespace Allyn.Common { public class XmlHep ...
- Curl 基本命令
下载单个文件,默认将输出打印到标准输出中(STDOUT)中 curl http://www.centos.org 通过-o/-O选项保存下载的文件到指定的文件中:-o:将文件保存为命令行中指定的文件名 ...