Giám sát ứng dụng với Spring Boot Actuator
1. Spring Boot Actuator là gì?
Spring Boot Actuator là một dự án con (sub-project) trong dự án Spring Boot. Nó đươc xây dựng để thu thập, giám sát các thông tin về ứng dụng. Bạn có thể nhúng nó vào trong ứng dụng của mình và có thể sử dụng các tính năng của nó. Để giám sát ứng dụng bạn cần truy cập vào các endpoint (Điểm cuối) được xây dựng sẵn của Spring Boot Actuator, đồng thời bạn cũng có thể tạo ra các endpoint của riêng của bạn nếu muốn.
Trong bài viết này tôi sẽ hướng dẫn bạn sử dụng Spring Boot Actuator trong ứng dụng Spring Boot phiên bản 2.0.0.M7 hoặc mới hơn.
Chú ý rằng Spring Boot Actuator có rất nhiều thay đổi trong phiên bản 2.x so với các phiên bản 1.x, vì vậy hãy đảm bảo rằng bạn đang làm việc với Spring Boot phiên bản 2.0.0.M7 hoặc mới hơn.
2. Tạo dự án Spring Boot
Spring Boot Actuator là một dự án con (một sản phẩm hoàn thiện) trong hệ sinh thái Spring, và bạn có thể nhúng nó vào một dự án Spring Boot có sẵn của bạn. Tất cả mọi thứ bạn cần làm là khai báo các thư viện Spring Boot Actuator và một vài thông tin cấu hình trong tập tin application.properties. Trong bài viết này tôi sẽ tạo ra một dự án Spring Boot và nhúng Spring Boot Actuator vào. Mục đích của chúng ta là tìm hiểu các tính năng mà Spring Boot Actuator cung cấp.
OK!, Trên Eclipse tạo một dự án Spring Boot.
Ở đây chúng ta sẽ lựa chọn phiên bản 2.0.0.M7 hoặc mới hơn.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.o7planning</groupId>
<artifactId>SpringBootActuator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringBootActuator</name>
<description>Spring Boot +Actuator</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. Cấu hình Spring Boot Actuator
Thêm một vài đoạn cấu hình vào tâp tin application.properties:
application.properties
server.port=8080
management.server.port=8090
management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true
- server.port=8080
Ứng dụng của bạn sẽ chạy trên cổng 8080 (port 8080), đây là cổng mặc định và bạn có thể thay đổi nó nếu muốn.
- management.server.port=8090
Các endpoint liên quan tới việc giám sát của Spring Boot Actuator sẽ được truy cập theo cổng khác với cổng 8080 ở trên, mục đích của việc này là tránh nhầm lẫn và tăng cường bảo mật. Tuy nhiên điều này không bắt buộc.
- management.endpoints.web.exposure.include=*
Mặc định không phải tất cả các Endpoint của Spring Boot Actuator đều được kích hoạt. Sử dụng dấu * để kích hoạt hết tất cả các Endpoint này.
- management.endpoint.shutdown.enabled=true
shutdown là một Endpoint đặc biệt của Spring Boot Actuator, nó cho phép bạn tắt (shutdown) ứng dụng một các an toàn mà không cần phải sử dụng các lệnh như "Kill process", "end task" của hệ điều hành.
4. Các Endpoint của Spring Boot Actuator
MainController.java
package org.o7planning.sbactuator.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MainController {
@ResponseBody
@RequestMapping(path = "/")
public String home(HttpServletRequest request) {
String contextPath = request.getContextPath();
String host = request.getServerName();
// Spring Boot >= 2.0.0.M7
String endpointBasePath = "/actuator";
StringBuilder sb = new StringBuilder();
sb.append("<h2>Sprig Boot Actuator</h2>");
sb.append("<ul>");
// http://localhost:8090/actuator
String url = "http://" + host + ":8090" + contextPath + endpointBasePath;
sb.append("<li><a href='" + url + "'>" + url + "</a></li>");
sb.append("</ul>");
return sb.toString();
}
}
Chạy ứng dụng của bạn và truy cập vào đường dẫn sau:
Chú ý: Các dữ liệu mà các endpoint của Spring Boot Actuator cung cấp có định dạng JSON, vì vậy để dễ nhìn hơn bạn có thể định dạng lại (reformat) dữ liệu này. Chẳng hạn website dưới đây cung cấp công cụ trực tuyến để định dạng JSON:
/actuator
/actuator là một endpoint (Điểm cuối), nó cung cấp danh sách các endpoint khác của Spring Boot Actuator mà bạn có thể truy cập vào được.
/actuator
{
"_links": {
"self": {
"href": "http://localhost:8090/actuator",
"templated": false
},
"auditevents": {
"href": "http://localhost:8090/actuator/auditevents",
"templated": false
},
"beans": {
"href": "http://localhost:8090/actuator/beans",
"templated": false
},
"health": {
"href": "http://localhost:8090/actuator/health",
"templated": false
},
"conditions": {
"href": "http://localhost:8090/actuator/conditions",
"templated": false
},
"shutdown": {
"href": "http://localhost:8090/actuator/shutdown",
"templated": false
},
"configprops": {
"href": "http://localhost:8090/actuator/configprops",
"templated": false
},
"env": {
"href": "http://localhost:8090/actuator/env",
"templated": false
},
"env-toMatch": {
"href": "http://localhost:8090/actuator/env/{toMatch}",
"templated": true
},
"info": {
"href": "http://localhost:8090/actuator/info",
"templated": false
},
"loggers": {
"href": "http://localhost:8090/actuator/loggers",
"templated": false
},
"loggers-name": {
"href": "http://localhost:8090/actuator/loggers/{name}",
"templated": true
},
"heapdump": {
"href": "http://localhost:8090/actuator/heapdump",
"templated": false
},
"threaddump": {
"href": "http://localhost:8090/actuator/threaddump",
"templated": false
},
"metrics-requiredMetricName": {
"href": "http://localhost:8090/actuator/metrics/{requiredMetricName}",
"templated": true
},
"metrics": {
"href": "http://localhost:8090/actuator/metrics",
"templated": false
},
"scheduledtasks": {
"href": "http://localhost:8090/actuator/scheduledtasks",
"templated": false
},
"trace": {
"href": "http://localhost:8090/actuator/trace",
"templated": false
},
"mappings": {
"href": "http://localhost:8090/actuator/mappings",
"templated": false
}
}
}
/actuator/health
/actuator/health cung cấp cho bạn thông tin về sức khỏe của ứng dụng. Trạng thái còn sống (UP) hoặc đã chết (DOWN), và các thông tin khác về ổ cứng như kích thước ổ cứng, dung lượng đã sử dụng và dung lượng chưa sử dụng.
/actuator/health
{
"status": "UP",
"details": {
"diskSpace": {
"status": "UP",
"details": {
"total": 75812040704,
"free": 8067600384,
"threshold": 10485760
}
}
}
}
actuator/metrics
Endpoint này cung cấp cho bạn danh sách các metric (Chuẩn đo lường)
actuator/metrics
{
"names": [
"jvm.memory.committed",
"jvm.buffer.memory.used",
"jvm.buffer.count",
"logback.events",
"process.uptime",
"jvm.memory.max",
"jvm.memory.used",
"jvm.buffer.total.capacity",
"system.cpu.count",
"process.start.time"
]
}
Và bạn có thể xem thông tin của một metric cụ thể.
actuator/metrics/{requiredMetricName}
/actuator/metrics/jvm.memory.used
{
"name": "jvm.memory.used",
"measurements": [
{
"statistic": "Value",
"value": 109937744
}
],
"availableTags": [
{
"tag": "area",
"values": [
"heap",
"nonheap",
"nonheap",
"heap",
"nonheap",
"nonheap",
"heap"
]
},
{
"tag": "id",
"values": [
"G1 Old Gen",
"Compressed Class Space",
"CodeHeap 'non-nmethods'",
"G1 Survivor Space",
"Metaspace",
"CodeHeap 'non-profiled nmethods'",
"G1 Eden Space"
]
}
]
}
/actuator/beans
/actuator/beans cung cấp cho bạn danh sách các Spring BEAN đang được quản lý trong ứng dụng của bạn.
/actuator/beans
{
"contextId": "application:8080",
"beans": {
"endpointCachingOperationInvokerAdvisor": {
"aliases": [],
"scope": "singleton",
"type": "org.springframework.boot.actuate.endpoint.cache.CachingOperationInvokerAdvisor",
"resource": "class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.class]",
"dependencies": [
"environment"
]
},
"defaultServletHandlerMapping": {
"aliases": [],
"scope": "singleton",
"type": "org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$EmptyHandlerMapping",
"resource": "class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]",
"dependencies": []
}
....
},
"parent": null
}
/actuator/env
/actuator/env cung cấp cho bạn tất cả các thông tin về môi trường mà ứng dụng của bạn đang chạy, chẳng hạn: tên hệ điều hành, classpath, phiên bản Java,...
/actuator/env
{
"activeProfiles": [],
"propertySources": [
{
"name": "server.ports",
"properties": {
"local.management.port": {
"value": 8090
},
"local.server.port": {
"value": 8080
}
}
},
{
"name": "servletContextInitParams",
"properties": {}
},
{
"name": "systemProperties",
"properties": {
"sun.desktop": {
"value": "windows"
},
"awt.toolkit": {
"value": "sun.awt.windows.WToolkit"
},
"java.specification.version": {
"value": "9"
},
"file.encoding.pkg": {
"value": "sun.io"
},
"sun.cpu.isalist": {
"value": "amd64"
},
"sun.jnu.encoding": {
"value": "Cp1252"
},
"java.class.path": {
"value": "C:\\Users\\tran\\.m2\\repository\\org\\springframework\\spring-jcl\\5.0.2.RELEASE\\spring-jcl-5.0.2.RELEASE.jar;...."
},
"com.sun.management.jmxremote.authenticate": {
"value": "false"
},
"java.vm.vendor": {
"value": "Oracle Corporation"
},
"sun.arch.data.model": {
"value": "64"
},
"user.variant": {
"value": ""
},
"java.vendor.url": {
"value": "http://java.oracle.com/"
},
"catalina.useNaming": {
"value": "false"
},
"user.timezone": {
"value": "Asia/Bangkok"
},
"os.name": {
"value": "Windows 8.1"
},
"java.vm.specification.version": {
"value": "9"
},
"sun.java.launcher": {
"value": "SUN_STANDARD"
},
"user.country": {
"value": "US"
},
"sun.boot.library.path": {
"value": "C:\\DevPrograms\\Java\\jre-9.0.1\\bin"
},
"com.sun.management.jmxremote.ssl": {
"value": "false"
},
"spring.application.admin.enabled": {
"value": "true"
},
"sun.java.command": {
"value": "org.o7planning.sbactuator.SpringBootActuatorApplication"
},
"com.sun.management.jmxremote": {
"value": ""
},
"jdk.debug": {
"value": "release"
},
"sun.cpu.endian": {
"value": "little"
},
"user.home": {
"value": "C:\\Users\\tran"
},
"user.language": {
"value": "en"
},
"java.specification.vendor": {
"value": "Oracle Corporation"
},
"java.home": {
"value": "C:\\DevPrograms\\Java\\jre-9.0.1"
},
"file.separator": {
"value": "\\"
},
"java.vm.compressedOopsMode": {
"value": "Zero based"
},
"line.separator": {
"value": "\r\n"
},
"java.specification.name": {
"value": "Java Platform API Specification"
},
"java.vm.specification.vendor": {
"value": "Oracle Corporation"
},
"java.awt.graphicsenv": {
"value": "sun.awt.Win32GraphicsEnvironment"
},
"java.awt.headless": {
"value": "true"
},
"user.script": {
"value": ""
},
"sun.management.compiler": {
"value": "HotSpot 64-Bit Tiered Compilers"
},
"java.runtime.version": {
"value": "9.0.1+11"
},
"user.name": {
"value": "tran"
},
"path.separator": {
"value": ";"
},
"os.version": {
"value": "6.3"
},
"java.runtime.name": {
"value": "Java(TM) SE Runtime Environment"
},
"file.encoding": {
"value": "UTF-8"
},
"spring.beaninfo.ignore": {
"value": "true"
},
"java.vm.name": {
"value": "Java HotSpot(TM) 64-Bit Server VM"
},
"java.vendor.url.bug": {
"value": "http://bugreport.java.com/bugreport/"
},
"java.io.tmpdir": {
"value": "C:\\Users\\tran\\AppData\\Local\\Temp\\"
},
"catalina.home": {
"value": "C:\\Users\\tran\\AppData\\Local\\Temp\\tomcat.16949807720416048110.8080"
},
"java.version": {
"value": "9.0.1"
},
"com.sun.management.jmxremote.port": {
"value": "54408"
},
"user.dir": {
"value": "E:\\ECLIPSE_TUTORIAL\\JAVA_SPRING_BOOT\\SpringBootActuator"
},
"os.arch": {
"value": "amd64"
},
"java.vm.specification.name": {
"value": "Java Virtual Machine Specification"
},
"PID": {
"value": "5372"
},
"java.awt.printerjob": {
"value": "sun.awt.windows.WPrinterJob"
},
"sun.os.patch.level": {
"value": ""
},
"catalina.base": {
"value": "C:\\Users\\tran\\AppData\\Local\\Temp\\tomcat.8934969984130443549.8090"
},
"java.library.path": {
"value": "C:\\DevPrograms\\Java\\jre-9.0.1\\bin;...;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files\\EmEditor;."
},
"java.vm.info": {
"value": "mixed mode"
},
"java.vendor": {
"value": "Oracle Corporation"
},
"java.vm.version": {
"value": "9.0.1+11"
},
"java.rmi.server.hostname": {
"value": "localhost"
},
"java.rmi.server.randomIDs": {
"value": "true"
},
"sun.io.unicode.encoding": {
"value": "UnicodeLittle"
},
"java.class.version": {
"value": "53.0"
}
}
},
{
"name": "systemEnvironment",
"properties": {
"USERDOMAIN_ROAMINGPROFILE": {
"value": "tran-pc",
"origin": "System Environment Property \"USERDOMAIN_ROAMINGPROFILE\""
},
"LOCALAPPDATA": {
"value": "C:\\Users\\tran\\AppData\\Local",
"origin": "System Environment Property \"LOCALAPPDATA\""
},
"PROCESSOR_LEVEL": {
"value": "6",
"origin": "System Environment Property \"PROCESSOR_LEVEL\""
},
"FP_NO_HOST_CHECK": {
"value": "NO",
"origin": "System Environment Property \"FP_NO_HOST_CHECK\""
},
"USERDOMAIN": {
"value": "tran-pc",
"origin": "System Environment Property \"USERDOMAIN\""
},
"LOGONSERVER": {
"value": "\\\\TRAN-PC",
"origin": "System Environment Property \"LOGONSERVER\""
},
"SESSIONNAME": {
"value": "Console",
"origin": "System Environment Property \"SESSIONNAME\""
},
"ALLUSERSPROFILE": {
"value": "C:\\ProgramData",
"origin": "System Environment Property \"ALLUSERSPROFILE\""
},
"PROCESSOR_ARCHITECTURE": {
"value": "AMD64",
"origin": "System Environment Property \"PROCESSOR_ARCHITECTURE\""
},
"PSModulePath": {
"value": "C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\",
"origin": "System Environment Property \"PSModulePath\""
},
"SystemDrive": {
"value": "C:",
"origin": "System Environment Property \"SystemDrive\""
},
"APPDATA": {
"value": "C:\\Users\\tran\\AppData\\Roaming",
"origin": "System Environment Property \"APPDATA\""
},
"USERNAME": {
"value": "tran",
"origin": "System Environment Property \"USERNAME\""
},
"ProgramFiles(x86)": {
"value": "C:\\Program Files (x86)",
"origin": "System Environment Property \"ProgramFiles(x86)\""
},
"CommonProgramFiles": {
"value": "C:\\Program Files\\Common Files",
"origin": "System Environment Property \"CommonProgramFiles\""
},
"Path": {
"value": "D:\\DEV_PROGRAMS\\Oracle12c\\product\\12.2.0\\dbhome_1\\bin;...;C:\\Program Files\\EmEditor",
"origin": "System Environment Property \"Path\""
},
"PATHEXT": {
"value": ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC",
"origin": "System Environment Property \"PATHEXT\""
},
"OS": {
"value": "Windows_NT",
"origin": "System Environment Property \"OS\""
},
"COMPUTERNAME": {
"value": "TRAN-PC",
"origin": "System Environment Property \"COMPUTERNAME\""
},
"PROCESSOR_REVISION": {
"value": "3c03",
"origin": "System Environment Property \"PROCESSOR_REVISION\""
},
"CommonProgramW6432": {
"value": "C:\\Program Files\\Common Files",
"origin": "System Environment Property \"CommonProgramW6432\""
},
"ComSpec": {
"value": "C:\\Windows\\system32\\cmd.exe",
"origin": "System Environment Property \"ComSpec\""
},
"ProgramData": {
"value": "C:\\ProgramData",
"origin": "System Environment Property \"ProgramData\""
},
"ProgramW6432": {
"value": "C:\\Program Files",
"origin": "System Environment Property \"ProgramW6432\""
},
"HOMEPATH": {
"value": "\\Users\\tran",
"origin": "System Environment Property \"HOMEPATH\""
},
"SystemRoot": {
"value": "C:\\Windows",
"origin": "System Environment Property \"SystemRoot\""
},
"TEMP": {
"value": "C:\\Users\\tran\\AppData\\Local\\Temp",
"origin": "System Environment Property \"TEMP\""
},
"HOMEDRIVE": {
"value": "C:",
"origin": "System Environment Property \"HOMEDRIVE\""
},
"PROCESSOR_IDENTIFIER": {
"value": "Intel64 Family 6 Model 60 Stepping 3, GenuineIntel",
"origin": "System Environment Property \"PROCESSOR_IDENTIFIER\""
},
"USERPROFILE": {
"value": "C:\\Users\\tran",
"origin": "System Environment Property \"USERPROFILE\""
},
"TMP": {
"value": "C:\\Users\\tran\\AppData\\Local\\Temp",
"origin": "System Environment Property \"TMP\""
},
"CommonProgramFiles(x86)": {
"value": "C:\\Program Files (x86)\\Common Files",
"origin": "System Environment Property \"CommonProgramFiles(x86)\""
},
"ProgramFiles": {
"value": "C:\\Program Files",
"origin": "System Environment Property \"ProgramFiles\""
},
"PUBLIC": {
"value": "C:\\Users\\Public",
"origin": "System Environment Property \"PUBLIC\""
},
"NUMBER_OF_PROCESSORS": {
"value": "8",
"origin": "System Environment Property \"NUMBER_OF_PROCESSORS\""
},
"windir": {
"value": "C:\\Windows",
"origin": "System Environment Property \"windir\""
}
}
},
{
"name": "applicationConfig: [classpath:/application.properties]",
"properties": {
"server.port": {
"value": "8080",
"origin": "class path resource [application.properties]:1:13"
},
"management.server.port": {
"value": "8090",
"origin": "class path resource [application.properties]:2:24"
},
"management.endpoints.web.expose": {
"value": "*",
"origin": "class path resource [application.properties]:3:33"
},
"management.endpoint.shutdown.enabled": {
"value": "true",
"origin": "class path resource [application.properties]:4:38"
}
}
}
]
}
/actuator/info
/actuator/info cung cấp một thông tin tùy biến của bạn. Mặc định nó là một thông tin rỗng. Vì vậy bạn cần phải tạo một Spring BEAN để cung cấp thông tin này.
BuildInfoContributor.java
package org.o7planning.sbactuator.monitoring;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
@Component
public class BuildInfoContributor implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
Map<String,String> data= new HashMap<String,String>();
data.put("build.version", "2.0.0.M7");
builder.withDetail("buildInfo", data);
}
}
5. /actuator/shutdown
Đây là một endpoint giúp bạn tắt (shutdown) ứng dụng. Bạn phải gọi nó với phương thức POST, nếu thành công bạn sẽ nhận được một thông điệp "Shutting down, bye...".
ShutdownController.java
package org.o7planning.sbactuator.controller;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
@Controller
public class ShutdownController {
@ResponseBody
@RequestMapping(path = "/shutdown")
public String callActuatorShutdown() {
// Actuator Shutdown Endpoint:
String url = "http://localhost:8090/actuator/shutdown";
// Http Headers
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
// Data attached to the request.
HttpEntity<String> requestBody = new HttpEntity<>("", headers);
// Send request with POST method.
String e = restTemplate.postForObject(url, requestBody, String.class);
return "Result: " + e;
}
}
6. Tạo các Endpoint tùy biến
Spring Boot Actuator là một sản phẩm hoàn chỉnh, nó cung cấp cho bạn các endpoint để giám sát ứng dụng, tuy nhiên trong một số tình huống bạn muốn tạo ra các endpoint của riêng bạn. Để làm việc này bạn có thể xem tiếp bài học dưới đây:
- Tạo các Endpoint trong Spring Boot Actuator
Các hướng dẫn Spring Boot
- Cài đặt Spring Tool Suite cho Eclipse
- Hướng dẫn lập trình Spring cho người mới bắt đầu
- Hướng dẫn lập trình Spring Boot cho người mới bắt đầu
- Các thuộc tính thông dụng của Spring Boot
- Hướng dẫn sử dụng Spring Boot và Thymeleaf
- Hướng dẫn sử dụng Spring Boot và FreeMarker
- Hướng dẫn sử dụng Spring Boot và Groovy
- Hướng dẫn sử dụng Spring Boot và Mustache
- Hướng dẫn sử dụng Spring Boot và JSP
- Hướng dẫn sử dụng Spring Boot, Apache Tiles, JSP
- Sử dụng Logging trong Spring Boot
- Giám sát ứng dụng với Spring Boot Actuator
- Tạo ứng dụng web đa ngôn ngữ với Spring Boot
- Sử dụng nhiều ViewResolver trong Spring Boot
- Sử dụng Twitter Bootstrap trong Spring Boot
- Hướng dẫn và ví dụ Spring Boot Interceptor
- Hướng dẫn sử dụng Spring Boot, Spring JDBC và Spring Transaction
- Hướng dẫn và ví dụ Spring JDBC
- Hướng dẫn sử dụng Spring Boot, JPA và Spring Transaction
- Hướng dẫn sử dụng Spring Boot và Spring Data JPA
- Hướng dẫn sử dụng Spring Boot, Hibernate và Spring Transaction
- Tương tác Spring Boot, JPA và cơ sở dữ liệu H2
- Hướng dẫn sử dụng Spring Boot và MongoDB
- Sử dụng nhiều DataSource với Spring Boot và JPA
- Sử dụng nhiều DataSource với Spring Boot và RoutingDataSource
- Tạo ứng dụng Login với Spring Boot, Spring Security, Spring JDBC
- Tạo ứng dụng Login với Spring Boot, Spring Security, JPA
- Tạo ứng dụng đăng ký tài khoản với Spring Boot, Spring Form Validation
- Ví dụ OAuth2 Social Login trong Spring Boot
- Chạy các nhiệm vụ nền theo lịch trình trong Spring
- Ví dụ CRUD Restful Web Service với Spring Boot
- Ví dụ Spring Boot Restful Client với RestTemplate
- Ví dụ CRUD với Spring Boot, REST và AngularJS
- Bảo mật Spring Boot RESTful Service sử dụng Basic Authentication
- Bảo mật Spring Boot RESTful Service sử dụng Auth0 JWT
- Ví dụ Upload file với Spring Boot
- Ví dụ Download file với Spring Boot
- Ví dụ Upload file với Spring Boot và jQuery Ajax
- Ví dụ Upload file với Spring Boot và AngularJS
- Tạo ứng dụng Web bán hàng với Spring Boot, Hibernate
- Hướng dẫn và ví dụ Spring Email
- Tạo ứng dụng Chat đơn giản với Spring Boot và Websocket
- Triển khai ứng dụng Spring Boot trên Tomcat Server
- Triển khai ứng dụng Spring Boot trên Oracle WebLogic Server
- Cài đặt chứng chỉ SSL miễn phí Let's Encrypt cho Spring Boot
- Cấu hình Spring Boot chuyển hướng HTTP sang HTTPS
- Tìm nạp dữ liệu với Spring Data JPA DTO Projections
Show More